Sorry to keep the trend of meta-blogging but my life really is that boring otherwise so here goes…
In my last post I decided to let everyone know how I went about implementing that nice little search form trick of having the form input itself be its own label. Just check out the post for the details. Looking at this it was a working solution but it seemed ugly and as though there was too much of my code there. So lets see what I’ve done now.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
var DefaultField = Behavior.create({ initialize: function(options) { this.options = Object.extend({ className: 'default' }, options || {}); if (!this.options.defaultText) throw new Error('FieldDefault: Must provide defaultText value'); this.onblur(); }, onblur: function() { if (this.element.value.blank()) this.element.addClassName(this.options.className).value = this.options.defaultText; }, onfocus: function() { if (this.element.value == this.options.defaultText) this.element.removeClassName(this.options.className).clear(); } }); Event.addBehavior({ '#q': DefaultField({ defaultText: 'live search...' }) }); |
It’s not particularly shorter or cleaner, in fact I really hate the fact that almost every line has this.element in it multiple times but there’s one important difference between this code and its predecessor, it’s re-usable! The previous implementation was directly attached to the element and did not allow for any re-usability without being duplicated. Now I can re-use this behavior in a test suite and quickly verify it’s function in many browsers very quickly. I can also use this behavior elsewhere that similar functionality is desired and I don’t have to copy and paste the code.
There’s also a hidden value to this technique. Had I re-used the previous implementation over several portions of a larger system and then decided to change how the default value was displayed, say I wanted to make it an overlay so it doesn’t impact other behaviors like live search where you may want to observe the field value for changes to fire off a search, I’d have to go modify at least a few of these implementations. This modification would have left me with different implementations of the same idiom without any way of telling them apart without digging through the code. By bottling this up in a behavior I can have multiple implementations with each having a descriptive name and appropriate documentation. More importantly, I can change all of them in a single place which makes it more maintainable.
Again, if it wasn’t obvious this post relies upon prototype.js and now also upon LowPro. Check these libraries out if you haven’t already and make sure to look at them from the perspective of not necessarily just letting you keep your JavaScript out of your HTML, but also letting you bottle that JavaScript into more re-usable chunks because after all the last thing we want to do as programmers is write more code.
