Category Archives: Script

Client side scripting.

Selectors API Naming Debate

The Selectors API naming debate is finally over! (I hope)

The number of possibilities and arguments was absurd! There were over 38 pairs of names to choose from, with arguments for and against every single one of them. Today, after carefully reviewing the arguments and considering the possibilities, I eventually decided upon selectElement() and selectAllElements().

In an attempt to settle the debate once and for all, I wrote a detailed rationale explaining how I came to this decision. You can see the latest version of the spec in CVS.

Scripts in XHTML

I frequently come across people who aren’t aware of the problems with using scripts inside XHTML documents. One of these problems is particularly fatal because it can cause a well-formedness error, but it’s not seen as an issue when documents are served as text/html.

The problem is with the use of special characters like ampersands (&), less-than (<) and greater-than signs (>). Only the first 2 of those are actually fatal, but it’s good practice to escape the latter as well.

Note: This is not an issue if you use external scripts in a separate file, which is usally a better alternative anyway, but there are times when including scripts in the page itself is useful.

To illustrate the problem, here are some examples. The following is fine in HTML 4, but not in XHTML.

<script type="text/javascript">
  if (a && b) {
     // Oops! Ampersands cause well-formedness error in XHTML!
  }
</script>

For XHTML, that would need to be written like this.

<script type="text/javascript"><![CDATA[
  if (a && b) {
  }
]]></script>

Or this:

<script type="text/javascript">
  if (a &amp;&amp; b) {
    // Oops! JavaScript syntax error in text/html
  }
</script>

But now, when served as text/html (not XML), both the CDATA section and the escaped ampersands are going to cause JavaScript syntax errors. You can comment them out like this:

<script type="text/javascript">//<![CDATA[
  if (a && b) {
  }
//]]></script>

But it’s easier to just admit you’re not using XHTML and use HTML instead.

XBL Part 2: Event Handlers

This is part 2 in my 5 part series on XML Binding Language. If you haven’t already read part 1, I suggest you do so now before you continue reading. XBL provides a mechanism for attaching event listeners to elements, and declaring the conditions under which the handlers should be invoked. In this article, I’m going to compare traditional event handling techniques with those that will be provided using by XBL.

Traditional Event Handling

The following example illustrates some typical unobtrusive scripting techniques to attach event listeners, including both the window.onload property and the addEventListener() function.

window.onload = function() {
    var nav = document.getElementById("nav");
    var li = nav.getElementsByTagName("li");
    for (var i = 0; i < li.length; i++) {
        li[i].addEventListener("mouseover", doSomething, false);
    }
}

Another common method, though generally considered bad practice these days, is to use the HTML onevent attributes, like the following.

<li onmouseover="doSomething();">...</li>

There are advantages and disadvantages to both methods, but the former is generally considered better because it separates the behaviour layer from the markup. However, the latter is a simple declarative syntax that can be quite convenient in some cases.

Handling Events with XBL

In XBL, instead of requiring authors to use a script to search for the elements, the event listeners are attached to those that the binding is attached to. XBL provides a simple declerative syntax which also continues to separate the behaviour layer from the semantic markup layer. Event listeners are declared using both the handlers element and its child handler elements.

In the previous article, we looked at how bindings are associated with elements using a selector, just like in CSS. For example, this binding will be attached to all li elements within an element with id="nav".

<xbl xmlns="http://www.w3.org/ns/xbl">
  <binding element="#nav li">
    <handlers>
      <handler event="mouseover">
        doSomething();
      </handler>
    </handlers>
  </binding>
</xbl>

If present, only one handlers element is allowed within a binding, but it can contain as many child handler elements as required, to capture as many different events as you like. This binding declares a single event handler that listens for the mouseover event. When the mouseover event is fired on a bound element (i.e. an element to which this binding is attached), the handler is invoked in effectively the same way it would have been using the other methods shown above.

Event Filters

There are often times when you only want to handle an event under certain conditions. For example, when you want to capture a click event and do something only when the user clicks the left mouse button; or capture a keyboard event and perform different functions depending on which key was pressed. In traditional scripting techniques, you have to check the values of certain properties using if or switch statements in your function, like the following.

function doSomething(e) {
    var code;
    e = e || window.event;
    code = e.keyCode || e.which;
    switch(code) {
        ...
    }
}

Much of that involves handling of browser incompatibilities, but even if all browsers supported the DOM Events standard, it’s still quite complicated. XBL addresses this by providing a simple declarative syntax for describing these conditions using attributes on the handler element.

In the following example, separate handlers are provided for for handling the keypress events depending on which character was entered. The first handles the character a, the second handles b. If any other character was entered, neither of these two handlers will be invoked.

<handlers>
  <handler event="keypress" text="a">
    doSomethingA();
  </handler>
  <handler event="keypress" text="b">
    doSomethingB();
  </handler>
</handlers>

Similarly, in the following example, the handler will only be invoked when the user left clicks while holding the Shift key down.

<handlers>
  <handler event="click" button="0" modifiers="shift">
    doSomething();
  </handler>
</handlers>

Other Common Event Filters

There are several other filters that can be used. The following list is a subset of the available attributes for this purpose. I suspect these will be the most commonly used filters because they cover the majority of mouse and keyboard event usage on the web today.

button
A space separated list of mouse buttons pressed by the user. e.g. button="0 2" matches either the left or right mouse buttons.
click-count
The number of times the user clicked. e.g. click-count="2" matches double clicks.
text
The text entered by the user. This is different from the key code because it matches the letter that was entered, regardless of the keys that were pressed. This is particularly important for languages that require several key presses to enter certain letters.
modifiers
Modifer keys, including alt, control, shift, meta, etc.
key
Matches against the keyIdentifier value defined in DOM 3 Events
key-location
For matching the location of the key that was pressed on the keyboard, including standard, left, right and numpad.

In the next article in this series, I’ll be taking a look at XBL Templates, which will provide significant presentaional enhancements, particularly in regards to layout.