Saturday, September 27, 2008

Ext JS Custom TreeNodeUI

I wrote this some time ago and then noticed that Blogger blasted the indentation in the code snippets so I'm only posting it now.

Hey, this should be a good dump - I needed an Ext JS tree with a custom TreeNodeUI. In addition to the usual text, I wanted each TreeNode to feature a select box that would allow a selection (and Ajax saving of the selection) to be made for each node. While the Ext JS API Documentation is pretty good, it doesn't always provide the information needed when trying to "step outside the box." (This framework is just dying for someone to write a book about it...) After just a little head scratching I found writing such a custom TreeNodeUI to be fairly straight forward.

The first thing I needed to do was to define my SelectNodeUI having it call its parent constructor on instantiation:



After that, I needed to extend my SelectNodeUI, inheriting from the standard TreeNodeUI, while overriding the renderElements and onSelectChange methods. The renderElements method is overridden to add the select box (look for the sel variable). The onSelectChange method is overriden to prevent the normal focus change which would unfortunately cause the select box to close immediately when first selected. This looks like a lot of code but is primarily a copy of the TreeNodeUI renderElements method with the rendering of the select box added. I've marked the parts I've added / changed with // DJB: comments:



Take special note of the building of the selectHtml string from the COMMAND_HIERARCHY_TYPE_ARRAY which has been written into the page in the format of [["label text", id], ...] and how the correct option is selected after the selectHTML has been rendered into a select box DOM node.

Now that the custom tree node is defined and ready to use the loader for the TreePanel needs to be informed about which UI providers are available. This is done by setting the uiProviders property of the loader property of the TreePanel:



With this code in place, a mapping has been defined between the string "select" and the SelectNodeUI. If the JSON for a tree node comes back with the value uiProvider: "select", the SelectNodeUI will be used to render that tree node, otherwise, it will fall back to using a regular TreeNodeUI. Keep in mind that such a tree node will also need a typeId property so that the proper option can be selected in the select box. With Rails the JSON for these tree nodes might be rendered with a method like this:



Unfortunately, as the comment says in the code, Internet Exploder does not bubble change events. Thus each select node has its own change listener that calls selectChange (otherwise I could have wired up a single change listener at a level above these tree nodes in the DOM tree). selectChange is a fairly straight forward function which uses an Ajax call to save the new state for the tree node's underlying model:



Finally, the select boxes are slightly taller than the normal content held at a tree node and thus mess up the lines that are drawn connecting the + / - expanders along the left side of the tree. Instead of fixing this up to look write I would recommend just turning the tree lines off. This can be done with by setting up the TreePanel with either the lines: false or useArrows: true properties. With lines: false the tree will render with the same old + / - expanders but won't render the lines. With useArrows: true the tree will render with a look that is supposed to emulate "Vista," using small triangles and drawing no lines. I'm not sure what this "Vista" thing is and I couldn't seem sudo apt-get install it ;-).

Wednesday, September 24, 2008

Attach and Detach SQL Server Databases from the Command Line with osql

I'm usually working with MySQL but I also work on a project that uses SQL Server for a back end. Lately I've been writing a script that massages some data from a CSV dump from another system into our system. This led to a rather, rinse, repeat cycle of switching to SQL Server in VMWare, detaching the existing database, copying a fresh copy of the database into place, and re-attaching the data when doing sample runs of the script against the data. This got to be a real hassle! Finally I took the time to learn how to detach and attach a SQL Server database using command line osql commands. Here is an example of a script that detaches the database, copies clean files into position, and then re-attaches the database:



Enjoy!

Sunday, September 21, 2008

Generating Combinations in Ruby and Javascript

Hey, time to dust off your discrete math text! (The one I used is Discrete Mathematics and Its Applications by Kenneth H. Rosen). The number of combinations of r items that can be selected from n items is given by the formula = n!/r!(n - r)! (note to self, render this with MathML). The following three code blocks show how to return those combinations in Ruby, Javascript, and Javascript with Prototype. Note that these functions yield (in Ruby) or do a callback with (Javascript) each combination. These could easily be modified to return an array of the combinations. After the three code snippets is a live example of the Javascript code. First the Ruby: Now the Javascript: And finally Javascript with Prototype (wow, now like Ruby): Wow, if that doesn't make you want to learn Prototype using Prototype and script.aculo.us: You Never Knew JavaScript Could Do This! then nothing will.

[ combinations ]

Saturday, September 13, 2008

method_missing in Javascript

method_missing in Javascript? Well not yet -- but you might be surprised to learn that some Javascript implementations already feature this functionality. For example, it appears that Mozilla based browsers have had __noSuchMethod__ since at least Javascript version 1.5. Also, it looks like this feature is quite possible to become a standard feature of Javascript in the future although not likely for 3.1. Look here for a couple of threads discussing this feature.

What might you do with a feature like this? If you found this page I imagine you already have a few ideas in mind but if not the Ruby on Rails framework contains many examples of this technique. Ruby on Rails uses Ruby's method_missing for all sorts of "meta-programming" magic like dynamic finders such as ActiveRecord::Base#find_by_login_and_password('bob', 'cheese').

So I can't leave you without an example...If your browser is so inclined, the following text box will allow you to enter any call you like against the "example" object and will use __noSuchMethod__ to spit back information about the call.






The code that sets up the "example" instance looks like this:




I, for one, would really like to see a feature like this become a Javascript standard.

Hey, if you are interested in learning more about Javascript I would recommend the following books: Javascript: The Definitive Guide, Pro Javascript Techniques, and Prototype and script.aculo.us: You Never Knew JavaScript Could Do This!

Oh yeah, one last thing - since Javascript objects are pretty much just hashes this type of method missing technique really only needs hashes to be extended to allow a default value to be specified like you can do with a Ruby Hash. This would result in the possibility of writing code like this:



I'm not sure what type of syntax could be offered if the object didn't begin its life as a Hash.

Thursday, September 11, 2008

Javascript - Change your Stylesheet not your Style

Most Javascript code that interacts with the CSS of a document does it by interacting with the individual elements on the page. For example, a Prototype script to change the background color of a specific element on the page might look like this:



While this works well, in some cases you may be wanting to apply the same style to 100s of elements. Recently I ran into this problem when coding a Prototype version of the Flickr Photo Demo. (Hey, sorry this might be foobar on IE, I just haven't had time to take a look at cross browser issues for IE on this demo.) The demo has a slider in the upper right corner that changes the size of the displayed images. My first cut at the demo can be found here. On a fast modern computer, this works pretty well, however, given the loops that are needed to apply new pixel sizes to the images and the divs that contain them, the slider can be jumpy on an average system. This demo only displays 20 images at a time, so it is easy to see how this problem could get very noticeable when more elements are involved. The key code applying the styling changes looks like this:



This had me thinking of ways to get the slider to work more smoothly. The first solution I thought of was to use different classes for the containing "#content div" which would result in the needed style changes to the contained div and img tags. The new code looked like this:



Look mom! No loops. The new code is fast and the slider operates very smoothly. As the astute reader may have figured out, however, this required me to have a very large stylesheet for this page. The reason is that the class for the "#content div" is being changed to sizeXXXpx where XXX can be any number from 50 to 250. How big is the stylesheet? Well picture 402 lines of this kind of stuff:



This version of the Flickr Photo Demo can be found here.

Without my emacs fu this file would have been a pain to create - but no matter what its still ugly. This got me thinking about another solution - surely Javascript will let you modify the rules in the stylesheet dynamically, right? After a little googling I found out it is possible but it doesn't seem like it is a very popular technique. I quickly hacked together the following general function for modifying the rules of a stylesheet:



On thing to keep in mind about this code is that it stops searching for the rule to change once it finds the first matching selector that it runs into. This is of course going to be a problem if you have the same selector defining css rules at multiple places in your stylesheets. You may need to adjust the above function if you don't have control over how your stylesheets have been defined.

This allowed me to change my slider code to the following:



Wow, it works, no loops, fast, and my stylesheet is back to being slim and sexy. This version of the Flickr Photo Demo can be found here.

This got me to wondering how cross browser this technique would be. To test this out I made this page which implements the most bare bones demonstration of this technique and tried it out on a few different browsers. It worked fine on all the browsers I tried it on. I wanted to do one last test that targets more browsers so I made this page and submitted it to Browsershots. (Browsershots is cool, you submit it a page and tell which browsers to take screenshots for - then sit back and wait for the results to roll in). This final test put the stylesheet modifying code in the window.onload event and changed the background from red to green. This would make the browser shot screenshots show in green on a browser that handles the technique and show in red on a browser that trips up on it. It worked in every browser I asked Browsershots to test it on.

So there you have it, you apparently can dynamically change the rules in stylesheets rather than changing the styles on individual DOM elements. So now I'm wondering, why is the usage of this technique not more prevalent?

Tuesday, September 09, 2008

Flickr Photo Demo the new Hello World of Web Client Frameworks

Hello World

It looks like the "Flickr Photo Demo" might become the "hello world" of web client frameworks. First the 280 North team released the Cappuccino framework and published their Flickr Photo Demo. Then the broken digits blog released a version written with the help of jQuery.

I've been wanting to improve my Prototype and Scriptaculous skills so I took the broken digits example and replaced the jQuery code with Prototype and Scripty code (yes, I borrowed all heavy lifting on the HTML and CSS work from broken digits). My version can be found here.

If you are interested in learning Prototype and Scripty I strongly recommend the book Prototype and script.aculo.us: You Never Knew JavaScript Could Do This!. It is very well written and will help you understand not only the frameworks but will also give you a deeper understanding of the Javascript language as well.

If you are interested in arguing the future of these frameworks...bah, I'm going to sleep.

Sunday, August 10, 2008

Converting from REXML to LibXML-Ruby

With the recent resurrection of LibXML-Ruby I decided to investigate converting one of our more XML processing heavy applications from REXML to LibXML-Ruby. LibXML-Ruby is touted to be much faster than REXML, and, I found this to be the case. In the process I kept track of some of the differences between the two that should help you if you decide to do the same. Here are some of the command equivalents between the two:

REXMLLibXML-Ruby
create doc from filenameREXML::Document.new(filename)XML::Document.file(filename)
create doc from fileREXML::Document.new(file)XML::Parser.io(file).parse
grab to root of a docdoc.rootdoc.root
create doc from stringREXML::Document.new(string)
parser = XML::Parser.new
parser.string = string
doc = parser.parse
(no, you can pass a StringIO to XML::Parser.io)
return all elements (not text nodes)node.elementsnode.find('*')
xpath from elementelem[xpath](annoyingly can return a single item or an array)elem.find(xpath)
xpath to the first matchREXML::XPath.first(elem, xpath)elem.find_first(xpath)
grab text content of nodeelem.textelem.content
working with attributes
elem.attributes[attr]
(elem[...] reserved for xpath)
elem[attr]
creating nodes
REXML::Element.new(name)
REXML::Element.new(name, attr_hash)
XML::Node.new(name)
XML::Node.new(name, content)
(can't set attrs on create)
deep clone a nodeelem.deep_copyelem.copy(true)
add a child element
node.elements.add(child)
(child can be node or string)
node.elements.add_element(name, attr_hash)
node << child_node
node.child = child.node
node.child_add(child)
removing elements
parent.remove(child)
parent.delete_element(child)
(child may be Element, String, or Integer)
child.remove!
jump to the next siblingelem.next_elementelem.next
can XPath node not in a document?yesno
can add node directly from one document to anotheryesno


Ok, for those of you that actually read all the way through the table the bonus is right down here, because the biggest difference between REXML and LibXML-Ruby is in the handling of default namespaces. A default namespace is a namespace placed on an XML document that acts as the default, that is it doesn't use a prefix. A good example of this is KML documents which are often defined like this:



With REXML, you can use XPath expressions with the assumption that you are referencing the default namespace and they will just work - no prefix necessary. With LibXML-Ruby, this is not the case. Say you have a reference to a node with LibXML-Ruby, and you want to run some XPath on it, with LibXML-Ruby you will be forced to do something like this:



I found an approach of registering a prefix for the default namespace on Bogle's Blog. While this is nice, you still can't register this once for the whole document, but must do it on each node you will be running an XPath expression on.

(On another note, did I just remove all carriage returns from my table to make blogger happy? Why yes, yes I did.)