Advancing JavaScript with Libraries

Written by on April 13th, 2007 in Ajax News.

The Yahoo! UI team kindly invited me to listen to John Resig, of Mozilla and jQuery, talk to the team on “Advancing JavaScript with Libraries”.

John wanted to talk about his experiences developing a number of JavaScript libraries,

At Mozilla John is working on FUEL, a JavaScript library that should be shipping in Firefox 3, that will reduce the complexity for developers to create add-ons.

What is a library?

  • An abstraction away from an existing API
  • Give us new APIs to interface with

APIs breed patterns based on how the API is constructed. Libraries will develop new patterns on top of the existing APIs.

For example, compare the DOM API versus a library that makes the DOM easier to work with. This enables library authors to enhance The Way.

Why create a library?

There are many, many libraries out there. Why write a library?

  • Avoid repetition
  • In JavaScript: Distance from browser differences
  • In C: stdlib distances itself from the platform differences

What about the DOM API?

DOM is implemented in every modern browser, and is very stable and web documented. Even here libraries are useful.

This breaks in IE 7, and always returns an empty set:

HTML:

  1.  
  2. document.getElementById("obj").getElementsByTagName("param")
  3.  
  4. <object id=”obj”>
  5.   <param name=”src” value=”test.mov” />
  6.   <param name=”title” value=”My Video” />
  7. </object>
  8.  

This fails in Safari 2

HTML:

  1.  
  2. document.getElementById("opt").selected
  3.  
  4. <div style=”display: none;”>
  5.  <select><option id=”opt” alue=”test”/></select>
  6. </div>
  7.  

These are genuine bugs in a specific strange way.

These fail in Opera and IE (return the input where the name is q)

HTML:

  1.  
  2. document.getElementById("q")
  3.  
  4. <form action=”" method=”POST”>
  5.   <input type=”text” name=”q” />
  6.   <span id=”q”>Search</span>
  7. </form>
  8.  

And expandos mess you up if you use an id of length (in Opera and IE)

HTML:

  1.  
  2. var f = document.getElementsByTagName("input")
  3. for (var x = 0; x <f.length; f++) {
  4.  
  5. }
  6.  
  7. <form action=”" method=”POST”>
  8.   <input type=”text” id=”length” value=”22″ />
  9.  
  10.  

And these fail in all browsers (for valid reasons, but Joe User doesn’t get it):

HTML:

  1.  
  2. document.getElementById("name").setAttribute("disabled", false)
  3.  
  4. <input type=”text” id=”name” disabled=”disabled” />
  5.  

Reason: DOM doesn’t grok booleans.

HTML:

  1.  
  2. document.body.setAttribute("className", "home");
  3.  
  4. <body> … </body>
  5.  

Reason: class is reserved in JavaScript. Use className.

All of these differences cause libraries to be created.

  • IE has lots of well documented bugs.
  • Safari has less, but more obscure, bugs

Libraries break down issues into meta-problems

E.g.

  • Waiting for the document to load
  • Traversing the DOM
  • Injecting HTML into a page

Waiting for the document to load

A DOM document must be fully loaded before you can work with it, and most wait for the window to load which causes flashes of un-effected content.

What people often do:

HTML:

  1.  
  2. <input type=”text” id=”test” />
  3. <script>document.getElementById"test".docus();</script>
  4.  

jQuery example:

HTML:

  1.  
  2. <head><script src=”script.js”></script></head>
  3.  
  4. $(document).ready(Function() {
  5.   $("#test").focus();
  6. }
  7.  

Traversing the DOM

We all know it is ugly, tricky, and long-winded.

We are moving to DOM Selectors to improve the DOM Traversal API. We have looked to standards such as XPath selectors (//div/span[2]), and CSS 3 selectors (div > span:nth-of-type(2)).

Most web developers grok CSS more than XPath, however they are stuck in CSS 1-ish land due to IE.

Here are some one line solutions that would take a lot more in DOM:

JAVASCRIPT:

  1.  
  2. $(”#menu> li:not(:first-child)”).hide(); // CSS 3
  3.  
  4. $(”ul[ul]“).show(); // XPath
  5.  
  6. $(”tr:even”).addClass(”even”); // Users want it
  7.  

Injecting HTML

Many issues here, such as injecting table rows, select options, etc.

jQuery and others allow you to create HTML and insert into the DOM directly.

JAVASCRIPT:

  1.  
  2. $(”table tr”).append(”<td>test</td>”);
  3. $(”select”).prepend(”<option>test</option>”);
  4.  

Put them together and you get unobtrusive DOM scripting:

JAVASCRIPT:

  1.  
  2. $(document).ready(function() {
  3.   $(”select”).append(”<option>test</option>”);
  4. })
  5.  

and it sets up new expectations:

jQuery users have thought that this should work:

HTML:

  1.  
  2. $("ul> li").click(function(){
  3.   $(this).load("menu.html");
  4. });
  5.  
  6.   <li>item a</li>
  7.   <li>item b</li>
  8. </ul>
  9.  

The users expect these behaviours to not be running once on page load. It should be like CSS. You don’t re-run CSS rules.

function handleClick() {
$(”li”, this).click(loadMenu);
}

function loadMenu() {
$(this).load(”menu.html”, handleClick);
}

$(document).ready(function() {
$(document).each(handleClick);
});

and becomes the behaviour pattern:

$(document).ready(function() {
$(”li”).behaviour(”click”, function(){
$(this).load(”menu.html”, handleClick);
})

FUEL

JavaScript library for Firefox Extension development, designed to be used by Web Developers (not C++ centric folk).

XPCOM is very daunting, and John shows the code for setting a preference. Lots of lines, lots of ugly XPCOM.

With FUEL:

JAVASCRIPT:

  1.  
  2. Application.prefs.setValue(”some.pref”, “some non-ascii text”);
  3.  

This isn’t new to JavaScript

John compares our library development to other worlds.

E.g. SQL

SELECT * FROM users WHERE id = 5;

to Ruby on Rails ActiveRecord::Base

Conclusion

  • Libraries build new patterns on top of existing APIs
  • New library patterns advance development in meaningful considerable ways

And there is more… Meta-Libraries

John is excited about the DSL movement and what it can mean to the web.

He has been playing with jquery2 which isn’t version 2 of jquery, but rather a DSL for JavaScript.

Browsers ignore a script tag where the type isn’t know, which means that you can have your code go back and grok and run it.

This is how the LISP in Firefox works.

Here is how jquery2 is plugged in:

HTML:

  1.  
  2. <script type=”text/jquery”>
  3. pre.run:
  4.   append ‘<input type=”submit” value=”Run”/>‘
  5.   input: click
  6.     each this.parentNode.firstChild.nodeValue
  7.     remove ‘foo’
  8.  
  9. #download> div: oneclick
  10.   #form + li: slideDown
  11.   remove
  12. </script>
  13.  

Come on, time for:

HTML:

  1.  
  2. <script type=”text/ruby”>
  3.   document.ready do |dom|
  4.     dom["table tr"] <<”<td>test"
  5.   end
  6. </script>
  7.  

Could get to this via JRuby and the JVM?

Source: Ajaxian
Original Article: http://ajaxian.com/archives/advancing-javascript-with-libraries

Leave a Reply

You must be logged in to post a comment.



Site Navigation