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.)

Saturday, July 26, 2008

Applets are Dead? Here's my Crapplet!

Applets are dead.

I decided to put together a little demo that shows the basic building blocks of using applet technology to build a RIA. I call my applet Crapplet. It builds a little GUI, does javascript to applet communications and vice versa, and fetches remote data from the server. The applet can be found here. A directory holding the source complete with a little build script can be found here.

Now if Sun would do something to reduce load times, browsers would make java plugins easy to install, and people would lose the bad memory of dancing icons - maybe this stuff could become useful again.

My applet has a problem though - when I hit refresh on my browser the applet bails. I must not be using init() correctly. I'm done trouble shooting it though ... time to learn Flex.

Saturday, July 19, 2008

Compile Flex 3 SDK from the Command Line

Here is a guide to setting up a Flex 3 project so that you can compile it from the command line:

  • download and set up the Flex 3 SDK, make sure the bin/ directory is on your path
  • make a directory for your project
  • in your projects directory make src/ and bin/ directories
  • copy the flex-config.xml from the flex SDK's frameworks directory into the root of your project
  • edit the flex-config.xml in your project, prepending ${flexlib}/ to all the libs/ paths and before the path references to manifest.xml and locale/
  • edit the flex-config.xml in your project, uncommenting the source-path element and setting its path-element element to src
  • create a compile file in the root of your project with the following content:

    Make this file executable.
  • Run the compile script to compile the project. The compiled swf will go to the bin/ directory and can be opened with your browser.

Here is a link to a zipped up version of a project where all the previously described steps have already been done for you (other than setting up the Flex 3 SDK of course).

This information primarily came from Simple Blog.

UPDATE: To use the trial data visualization components you need to copy several files over from a user that has installed flex builder. The instructions on which files and where they need to be placed in your sdk directory can be found here.

UPDATE UPDATE: The good people at Adobe have now made the data visualization components available as a separate download. You can find it here. You can download this archive and unzip it into your sdk and you will be good to go with the data visualization components - you won't need to download flex builder.

Firefox Greasemonkey Outlook Web Access Extension Part III

Other posts on OWAX: [ Part I | Part II ]

I have reverse engineered the way Microsoft Outlook Web Access uses Ajax to mark records read / unread under Internet Exploder and have added similar functionality to my Firefox Greasemonkey Outlook Web Access Extensions.

The code, also shown below, can be downloaded here.