Thursday, February 5, 2015

Adding and keeping a paste event for Sencha's Extjs 4.x's HtmlEditor.

In Sencha's Extjs 4.x, they redid the entire HtmlEditor class vs. version 3.x. We needed to grab information off the clipboard before Ext and make custom changes. For Extjs 3.x, that was as simple as adding a listener to the iframe body. This is what several people on varying websites on the Internet suggested as the fix, and this worked for the older version. But on the newer version, the paste event was either ignored or would simply just quite working after a short amount of time. More searching the Internet found that no one had suggestions for fixing the issue in Extjs 4.x (and probably newer).

When the paste event did work, the pasted text would be edited by our custom code and inserted into the editor. Then, mysteriously, unedited text was also entered, which appeared as a double paste. Along with our custom paste methods not working after a short period time, this double edit issue confused many a developer.

Allowing anyone access to the user's clipboard is a security issue. Browsers have allowed sandboxing the clipboard content, but Mozilla's Firefox developers did not, at least not until recently. The only surefire cross-browser solution was to use the aging and outgoing Flash. We can not use Flash for our customer's code. Several developers for HTML editors have solved this by 'tricking' the browser. The solution was to have a hidden field and a visual field. The hidden field would grab the pasted html, manipulate it, then sync that edited text with the visual field. This works great. But we needed access to the unedited text straight from the clipboard to do our own custom editing.

The two parts of an HTML editor are a textArea and an iframe. We added our event to the iframe's body, as the several places on the web suggested. And this was the mistake when working with Extjs 4.x. The newer version loosly couples the textArea and the iframe to an parent object, whereas the older version more tightly coupled the two. Remember this.

Example of the textArea and the iframe:
<textarea id="ext-comp-1284-inputCmp-textareaEl" 
 class="x-hidden" autocomplete="off" tabindex="-1" 
 name="comments" style="height: 46px;">
</textarea>
<iframe id="ext-comp-1284-inputCmp-iframeEl" 
 class="x-htmleditor-iframe" frameborder="0" 
 src="about:blank" name="ext-gen1439" 
 style="width: 100%; 
 height: 46px;">
<!DOCTYPE html>
 <html>
  <head>
   <body style="font-size: 12px; 
   font-family: tahoma,arial,verdana,sans-serif; 
   background-image: none; background-repeat: 
   repeat; background-color: rgb(255, 255, 255); 
   color: rgb(0, 0, 0); background-attachment: fixed; 
   cursor: text;">
  </html>
</iframe>

The other issue we had was the double insert. After some searching, I came across a site that said we needed to stop the paste event when we did our custom editing. This was easy. I added Ext.EventManager.preventDefault(e), Ext's built in version of preventDefault(). 'e' is the event being passed into our method, which is our specific 'paste' event. PreventDefault stops the propagation of the event. Adding it solved the double insert. So we were having only one insert, instead of two. Yay!

Snippet of the onPaste method called by the 'paste' listener:
onPaste : function(e, elem) {
    var text = "";
    Ext.EventManager.preventDefault(e);

    if(Ext.isIE) {

But, we still had the issue of after some time, our paste event was being ignored. While searching the web for a solution, I came across another person that had a similar issue. They were hiding a form so that when the user needed it, it would appear, then when done it would hide. This makes showing forms or other objects easy as the html doesn't need to be rebuilt every time. In some code, that's a speed increase. As a user, that is nice to have a page load immediately instead of waiting those few precious seconds.

The answer to this issue was that losely coupled hidden objects are garbage collected by the browser. Bingo! Remember that losely coupled hidden field for HTML editors? It was being garbage collected, hence why our event was being ignored after some time. After some more searching and being fairly familiar with Ext's HtmlEditor.js file (after all, I searched over it time and time again looking for reasons why something was removing our 'paste' listener). I found the solution. Instead of adding the listener to the iframe, as was done in the older Extjs version, we add it to the parent via Ext.EventManager.on(doc, { paste : fn}) where 'doc' is a reference back to the parent document of the editor, and 'fn' is the function we pass in to do our custom editing. Previously we used el.addListener('paste', this.onPaste, this), where el is this.getEditorBody(), which is the iframe's .

As part of the 'constructor' function, add this to the config:
listeners: {
    initialize: function () {
        var doc = me.getDoc();
        var fn = Ext.Function.bind(me.onPaste, me);
        Ext.EventManager.on(doc, {
            paste : fn
        });
    }
}

Now we have the ability to manipulate text before adding it to the editor. We used preventDefault() to stop the paste event from bubbling, and added a listener to the document, rather than to it's iframe's body.

Wednesday, April 2, 2014

Adding Icon Labels to Openlayers with KML styles

I've been working on a project that uses OpenLayers, KML, Extjs4, GeoExt, and a few other libraries.  On this project, customers would like to use a map to track assets.  They want to see a specific icon for a type of asset with a label below the icon.  What we found was that OpenLayers doesn't support KML styles along with OpenLayers styleMap on a Vector layer.

Searching online turned up a handful of individuals with the same issue, but no solution. Here is how I solved it:

Problematic Code example:
Setup a styleMap:
var styleMap = new OpenLayers.StyleMap({'default':{
    label : "${name}",
    fontColor: "#000000",
    fontSize: "11px",
    labelAlign: "center",
    pointRadius: 2,
    labelXOffset : -16,
    labelYOffset : 0,
    labelSelect: true
}});

Setup to get and parse KML:
var myKmlFormat = new OpenLayers.Format.KML({
    internalProjection: sphericalMercatorProj,
    externalProjection: mapProj,
    extractStyles: true,
    extractAttributes: true,
    maxDepth: 2
});

Finally, setup the vector layer:
var layer = new OpenLayers.Layer.Vector("KML", {
    projection: latLonProj,
    strategies: [new OpenLayers.Strategy.Fixed()],
    protocol: new OpenLayers.Protocol.HTTP({
    url: myKmlUrl,
    format: myKmlForma 
    }),
    styleMap: kmlStyleMap,
    eventListeners: { 'loadend': kmlLoaded },
    renderers: renderer
});

The KML:
 <document>
 <name>Geolocation Case: 17564</name>
  <style id="style1">
   <iconstyle>
    <icon>
     <href>http://127.0.0.1:8000/static/images/pointicon.png</href>
    </Icon>
   </IconStyle>
  </style>
  <placemark>
   <name>My Point</name>
    <point>
     <coordinates>-81.522832781,-3.33918759741,0.0</coordinates>
    </point>
    <lookat>
     <longitude>-81.522832781</longitude>
     <latitude>-3.33918759741</latitude>
    </lookat>
   <styleurl>#style1</styleurl>
  </placemark>
</document>

Google Earth will use the Placemark Name as the label, OpenLayers does not.  The line "extractStyles: true," in the OpenLayers KML section tells OpenLayers to parse the styles in the KML.  Setting it to false tells OpenLayers to ignore the style sections of the KML.

When this boolean is set to true, OpenLayers.Format.KML ignores manually added styleMap, such as the line "styleMap: kmlStyleMap".  So if your wanting a label on your placemark, it won't happen.  It is an 'or', not an 'and'.  This is a bug in OpenLayers in my opinion.

So, how do you get around this issue and add a label?  Well, read on.

Here is the Solution Code:

First off, don't create a styleMap and add it to the Vector constructor.  Add a listener to the layer:

layer.events.on({
  loadend : this.addLabel
});

Now, go through each icon (feature) and give the style a label, an offset, and anything else your label may need.
addLabel : function(event) {
    var features = event.object.features;

    for (var i = 0, len = features.length; i < len; i++) {
        var style = features[i]['style'];
        var attributes = features[i]['attributes'];
        if (!Ext.isEmpty(style) && !Ext.isEmpty(attributes)){
            style.label = attributes.name;
            style.labelYOffset = -16;
            style.fontSize = '11px';
            style.fontColor = '#000000';
            style.labelSelect = true;
        }
    }
    event.object.redraw();
}


The icons on the map should now have labels.

Sunday, December 8, 2013

Projected Bill Organizer/planner

I have always had a hard time remembering just about everything, including, when to pay my bills.  First, my wife and I tried using a calendar.  As bills came in, their due date was posted on the calendar.  But, then we'd forget to send the bill off days ahead so the bill arrived on time.  So, we decided to put it on the calendar 7 days ahead (or, whatever the average time bills took to go through our postal system).  This failed also. We'd forget to write something down.

Next, we bought a little desktop organizer.  The bills would be set in their due dates, and as we were paid, we'd pay all the bills due before the next pay period.  This actually worked quite well.  This system became the foundation upon the eventual spreadsheet software I wrote.  But, this system had some flaws.  Our house is small and cluttered.  We had nowhere to put this bulky organizer. 

Then, I setup a spreadsheet system in Excel, but being the Linux user I am, this required a virtual machine to run Windows.  I then imported my spreadsheet to Google Docs Spreadsheet.  Which worked fine, but I needed a little bit more control than the complicated spreadsheet formulas could give.  My formulas where getting so long and out of control, I had to decipher them a month later.

I looked into different languages that worked with Google Docs. Well, that sounds easy, until you realize, Google changed the API about every 3-4 months for different languages, such as Python and Java.  So, I settled on Javascript.  I've been writing Javascript professionally for some time, but I knew Javascript had one big flaw that would haunt me, especially Googles restricted version.

Javascript does a very poor job with time.  Time seems like an easy concept, until you start digging into it.  I didn't need to become a physicist, I just wanted to manipulate time in my algorithms for forecasting due dates.  Sounds easy, until midnight on a day that time changes, and Google's servers are in some unknown location (the "cloud").

After a week of pounding my head against the wall because of this very important shortcoming of Javascript (still, to this day, professionally I face the Javascript time issue.  Many libraries exist to help with this failure, but they cannot be used on Google Docs), I decided to find alternative avenues.

I started searching for Open Source Software that would meet my needs.  While the choices are abundant, none of them really did what I want.  Most financial software track paid expenses to help decided future forecasts, but were more complex than I needed.  I don't need to track every dollar I spend, I just want a reminder so that I can pay my bills on time.  If such a software exists, I couldn't find it.

I had been writing some software in Python for some time.  I love the powerful, yet simple Pythonic way of developing.  Though, I do miss my curly brackets.  So, I set out to find a Python friendly spreadsheet.  I found pySpread, but that software had errors everywhere.  It failed miserably.  It's a fine piece of code to show the power of Python, but just didn't work for me too well.

Next, I looked at Open Office's spreadsheet.  To write external methods for it was even more complicated than inline methods.  I also find Open Office to be poor software.  I have used it since Star Office and over the years grew less and less interested in it.  While I'm not a fan of Microsoft, I do have to say they have taken a lot of time to understand their customer needs and applied that to their Office product.  I prefer to use MS Office over any Open Source option.

Finally, I found Gnumeric.  A simple spread sheet that interfaced with full Python.  I could write my methods, build a small interface for Gnumeric and was good to go.  I translated my Javascript methods over (which were translated from my Excel spreadsheet formulas).  Within a few hours, I had my planner going.  Over the next couple of months, I refined my methods and interfaces.  I have used this for over a year with great success.

The spreadsheet knows when bills are due and shows the amount due under the best payday.  I just go into my banks bill pay area and setup the bills on that columns payday.  As I setup the bills, I marked them with some highlight color, such as orange.  When I noticed the bank paid the bill, I would then mark the bill green.  When all bills in that payday column were paid, I marked that entire column green. 

As stated above, this has successfully worked for over a year.  Not one late payment.  But now, I have the bug.  How can I make this better?  Well, now, that's the next article.

Sunday, September 22, 2013

Whisker Menu for XFCE exemplifies poor usability of today's desktop menu systems.

The other day I was looking at new Linux distributions on DistroWatch.com.  I came across this offshoot of Arch called Manjaro.  Use of XFCE as the desktop really caught my eye.  I have been using Xubuntu since Canonical decided to release Unity.  I do not like unity.  Then the Gnome developers made some decisions with which I don't agree (read Ignorant Guru's blog...use Google).

I have been quite happy with XFCE.  I liked it in the early days, but something always seemed amiss and eventually, I would slide back to my usage of KDE.  Then, KDE4 happened.  I was not happy.  I still can't stand to use it for long.  My opinion is that the desktop is a place to hold stuff like my real desk.  I don't need it to do fancy things, just hold my stuff.

I don't spend hours looking at backgrounds, although I do like XFCE's ability to put a different background on each monitor, and I do change them often.  I don't like icons on my desktop.  I have to close a window or many to get back to the desktop.  I prefer to have my icons either in the menu, or as I have my own setup, Cairo Dock, which sits on my main monitor on the left.

Now all of that is out of the way, I'll get back to the reason for this blog.  Actually, I have two reasons.  First, today's developers have no idea how to make intuitive software.  Don't get mad at me, I'm a developer and see the direction of many softwares forcing users to click many times to do small tasks.  User's should not have to refer to a help document to use the desktop.  The second part of this first reason is workflow, which brings me to Whisker Menu for XFCE.

A desktop should not force the user to work hard.  The Whisker Menu does just that, makes the user work harder.  Main menu's for desktops are usually on the left side of the desk.  Mac OS was once on the right, but is now on the left.  Windows is on the left. Default Gnome is on the left.  Default KDE is on the left.  Left is where we usually find the default main menu for desktops.

The Whisker Menu, when opened, puts all the main sections on the right side of the menu popup, instead of above or below as most other menu sections are.  This causes the user to move the courser to the up and right to find the section they wish to open, instead of the natural up or down from the "open" main menu button.

Then the user must choose their software on the left of the menu sections.  So now the user has had to make a '7' mouse motion to get their software, which opens centered to the right of the menu.  The user must now move the mouse in the opposite direction, again.  These may seem like small 'extra' steps, but subconsciously, the user gets fatigued.

The Whisker Menu's current (default) setup would be perfect for a right sided menu, but fails for a left sided menu system.  The developer seemed to go out of their way to make this menu 'different'.  A good 'fix' would be to move the menu sections to above the menu button, and the software choices to the right, when the menu is on the left, and as it is now when the menu is on the right side of the desktop.

Having the Whisker menu flow correctly, the user would have a more natural flow from menu button to menu section to software choice to the opened software's GUI.  The first thing I did in Manjaro was remove the Whisker menu and install the default XFCE menu.  Flow was much better.

Another gripe I have of several of the menu's today, from Microsoft, the Whisker Menu, etc. Is forcing the user to view the menu in a reserved amount of space, causing the user to scroll.  A better choice is to show all options and let the user use their eyes to look down all the choices.  But instead this reserved menu space is small, so the user must look down the menu, scroll, look back at the menu top, then look down the menu again, then repeat this process over and over until the end of the menu choices.  A long list will get tiresome.

A user should not be forced by software to work so hard to complete simple tasks.  The purpose of the desktop is as a place to view things, such as email, web pages, code in an IDE, etc.  Getting to that point should not exhaust the user.

Tuesday, August 13, 2013

Aftermath: check your chock blocks.

Rambling thoughts about the aftermath of the accident.  Don't try this at home.

Three weeks after the accident.  I've seen a pain specialist that injected steroids and numbing agent into the trap muscle at the base of my skull, that was nearly two weeks after the accident.  Up to that time, I was having severe headaches, afterwards, my headaches have been less severe and less often.  The force of rolling my head into my chest, while not breaking bones, did strain my muscles and sprain my ligaments, basically, the same injury as whiplash.

During week three, I started physical therapy and have to go twice a week for the next four weeks, including this week.  The first visit wasn't bad, I managed to get a wider angle of movement from the session, although, looking to my right is still painful enough I can't drive much.  I can drive short distances alright, but can't drive in too much traffic that requires a lot of looking around.

The pain is a cross like shape across my shoulders and from the mid-back of my head down to the bottom of my shoulder blades.  In the first two weeks, the doctor prescribed hydrocodone and Flexeril, which didn't seem to take away much pain, but did put me to sleep.  At least while asleep on these meds, I didn't feel the pain.

A while back I went to the doctor for bursitis in my shoulder and was prescribed Tramadol, an opiate (synthetic, I believe).  It requires a pill every 4-6 hours as needed.  I was looking for some Tylenol in the medicine cabinet when I ran across this prescription (not outdated, just not used).  I did some Google searching and found it was for medium to severe pain, so I decided to take some for my neck.  After 3 pills in about 14 hours, I felt very motion sick, but the pain was 80% gone.  Less pain was nice, the motion sickness was not.  So, I didn't take any more for a few days.  I decided to take some before bed, maybe it would help me sleep, and I wouldn't be sick from motion while I'm sleeping.

The Tramadol helped mostly with sleeping, I did sleep a bit longer and woke up with less pain.  But after a while of being up, the pain is returning...but at least I slept a bit better.

I don't sleep many hours in a row.  I can't sleep laying down, I have to be in a reclined position, which means creating some form of support on the couch end so I can sleep there.  I sleep about 2-3 hours before I need to re-position myself.

Each day doesn't seem to be better than the last, but looking back, I have gotten better each week.

If someone sprains an ankle, they can use crutches to get around. If someone sprains a wrist, they can use a sling.  Both of these keep that person off those muscles as they heal.  Neck muscles don't get that luxury, so after brief periods of time, I have to go rest my head and neck.  Like writing in this blog, I write some, I rest some, rinse and repeat.

I've injured myself before, twice I've nearly taken off fingers, the same two fingers.  That took time to heal, but I could do a lot of work without those two fingers.  I can't say the same about an injured neck muscle.

Well, more pain means I've lost my train of thought, so until next time, check your chock blocks.

Thursday, July 25, 2013

Conversing with Death, a.k.a. The Reaper.

Sometimes we get so laid back in life we forget how easy life can leave us.  One stupid mistake.  One time not thinking actions all the way through.  One time, that is all.  Here is the tale of my stupid mistake. (On a side note: I was a mechanic in the U.S. Army for 9 years.  I know safety under vehicles.  But 'stupid' chose this day to come out and play).

On the week of July 15, I received a package in the mail.  It was the electronic parts for the transmission in my 1996 Dodge Ram 2500 with a Cummins Turbo Diesel.  The transmission had been shifting incorrectly.  Once in gear, it was fine, but sometimes, it would forget which gear it needed.  A Google search identified the issue as a bad Governor Solenoid (yeah, he's an important political figure).  Forum posts suggested also replacing the pressure sensor too.  It's right next to the solenoid.  I checked online and for the price of buying these two parts locally, I purchased a kit online with pan gaskets, filters, as well as the 4th gear shift solenoid, torque converter lockup solenoid pack.  The kit also contained a couple of other parts that I wasn't planning on using, but still, the price was right.

I had planned all week to put these parts into the tranny.  I looked at many forum posts and YouTube videos and the task looked simple enough.  On Saturday morning, the day my family was all to come up and celebrate my eldest son's birthday (he had turned 13 during the week), I set out in the morning to tear down the lower end of the transmission.

I moved my truck so that it crossed my driveway.  On the inside of the drive, the lawn has somewhat of a sharp hill.  I put the front tires on this hillside.  The 'valley' of the hillside and the driveway created enough space under the truck to work without lifting the truck.  I placed a concrete block under one of the rear tires.  At this point, I would usually get in the truck and place it in neutral to check the block works.  But not this day.  I wasn't planning on removing anything that would allow the truck to move.

Once I was inside, I removed the section holding the governor solenoid and pressure sensor.  That was easy.  I looked at the wiring harness for the 4th/torque converter lockup pack, and the wire went toward the top of the transmission...sigh, more research to replace that part.  Granted, I could have replaced the two bad parts now and been finished...but, no, I moved forward.

So, now I went into the house, cleaned up a little, then set out on another Google search to find out how to remove that wire harness.  Luckly, the same shop that sold me the parts, also had a video on YouTube.  The guy in the video showed removing the valvebody to get to the screw holding the wire harness in place.  He did his work on his transmission on a workbench, so I missed a key point in his video.  the valvebody contained a rod that holds the transmission's parking sprag.  I went outside, and removed the bolts and some other parts so that the valve body would come loose.

If ever in your life, you notice you've just made a big mistake, like leaning just a bit too far in a chair, and the feeling as it tips over; or the feeling when that heavy object leaves your hands and falls toward your feet; or the feeling when you pull out at a green light and notice the large semi bearing down on you from right, while failing to yield to the red light.  That feeling.  That is the feeling I had when I heard the parking sprag let loose.

I did have the concrete block under the rear wheel, but it did not stop the truck.  The truck began to roll.  I did not have enough time to roll out from under the truck.  The only direction I could be was to stay under the truck.  My body was almost parallel with the frame of the truck.

A full sized Dodge truck with a Cummins engine weighs around the 7000lbs area.  My whole 240lbs body was not about to stop the momentum of this truck, even as it slowly rolled.  I tried to no avail.  I felt the lower control arm push my head.  It forced my head into my chest.  I tried to call out, but my wind pipe had already been closed.  The though then ran through my head, "So, this is how I die..."

All went black.

Seconds, minutes, hours went by, I don't know.  Time did not exist.

Then, as if waking from a deep sleep from some dream world, I turn my head, my body to try to figure out what is happening to me.  Nothing was familiar.  "Where am I?"  "What is holding me down?"  Slowly the dark figure of the truck's frame came into focus.  I slowly realize I am under something.  I reach out to grab something to get me away from this place.  My hand slaps against the side of the truck.  Then I hear a voice.  I did not recognize the voice.  I could not identify the source of the voice.  My mind still hazy from the dream.  I hear it say, "Are you alright?".
I call out, "No, help me."
"Where are you?"
My consciousness finally caught up to reality, "I'm over here, under the driver's side."
I hear footsteps, "How can I help?"
"Grab my arms and pull me out"
The person grabs ahold of my oily black arms and pulls...I am free.  I am still in some dreamstate in which I was never under the truck.  I stood as blood rushed down my face into my eye.

I don't remember saying any more to the soul that pulled me from danger.  I barely remember his face.

I rushed into the house and called for my wife.  The look of shock and horror of her face will never be forgotten.  I got me a towel for my head.  My body was covered in the crimson red of transmission fluid...or was it blood.

Moments later, a team of first responders came in as I sat in this very chair from which I write this.   They braced my neck, placed me on a stretcher and wisped me off to the hospital.  I was safe.  I was alive.

I do not remember my time under the truck.  But the truck rolled about ten feet with me under it.  But during this time, I had a conversation with Death.  Apparently, we had a good chat and saw that this was not my time.

At the end of the day, my son had a good birthday party.  I came home from the hospital without a broken bone, no internal injuries, only scars of my battle.

Why did I write this?  I dunno.  Maybe someone will someday read it and take that extra step to make sure their tires are chocked (metaphorically speaking).

Saturday, March 9, 2013

I should post more often.

Yep, I should.  I should run down the list here.  I've had the Prius for a year now.  I love it, still.  When I trade the Prius in, I've thought about getting the Lexus hybrid or going full on to a Tesla electric vehicle.  I hope that Tesla keeps going strong.  For more information about Tesla, Google.

The distro: well, with a real full time job, I just haven't had time to do anything with the idea.  Every once in a while, I do some research.  But, I believe the pot is full, so I really don't put forth the effort.

The tornado: we're approaching the anniversary.  Much work has been done in Joplin.  The area is less naked now, but still a lot is missing.  My coworker, whose house was destroyed by the tornado, moved to Pennsylvania.  We still work together, just online now.

Python: still really into Python.  I really love this language.  I've moved a lot of my code over to GitHub.  Some code I use for scripting stuff I do at work.  Other things are a bit more useful for others.  My recent project is making a GUI frontend for inxi, inxi-gui.  Yep, a lot of thought went into the name.  So far, I have a Tkinter(tk) version and a PySide (QT) version.  The PySide version is not as advanced as the Tkinter version.  Both are a learning experience. 

For a real job, I develop web applications in Javascript and Java.  We use ReST, SOAP, and a variety of other acronyms.  We use Extjs for our Javascript framework.  It's a nice framework.  I can't say I enjoy Java a lot, but at least it's fairly straight forward.  Groovy is so much nicer.  It's what happens when a Python drinks some Java, while wearing Perls, and other fun stuff. 

Oh, the chickens.  They are laying like mad.  Nearly 20 eggs per day from the flock.  They make great pets.  They don't require much of you.  They don't lick your face, after licking their junk.  They don't cough up furballs around the house.  But, they don't potty train well.  The roosters like to announce when they believe everyone should wakeup.  

Well, I think I'll keep this post short.  I'm going to try to post once a week and discuss something I learned for the week.  Last week, it was KML and OpenLayers. Go Chickens!