jQuery Selector Tests

Testing jQuery selectors

A colleague told me that the jQuery 1.3.2 selector is very buggy. Let's see.

Tested to run on IE 7.0, FireFox 3.0, FireFox 3.5, Opera 9.64, Opera 10b, Chrome 2.0 and Safari 4.0.

HTML



$("div.test h1").length 1
$("div.test").find("h1").length 1
$("div.test p").length 3
$("div.test").find("p").length 3

XML



$("elm h1", xml_dom).length 1
$("elm", xml_dom).find("h1").length 1
$("elm p", xml_dom).length 3
$("elm", xml_dom).find("p").length 3

Namespaced XML



$(_NS("ns\\:elm ns\\:h1"), xml_dom2).length 1
$(_NS("ns\\:elm"), xml_dom2).find(_NS("ns\\:h1")).length 1
$(_NS("ns\\:elm ns\\:p"), xml_dom2).length 3
$(_NS("ns\\:elm"), xml_dom2).find(_NS("ns\\:p")).length 3

It looks like jQuery 1.3.2 is buggy for XML with namespace. But how many people use such XML?

Namespaced XML and jQuery

jQuery manipulates namespaced XML poorly. First, jQuery uses ':' to denote a selector. That means the XML namespace must be escaped as '\:'. However, '\' is a special character in Javascript strings, so we need to write it as '\\:'.

Then, some browsers require you to omit the namespace when querying. jQuery does not abstract this, so the caller has to do it. The only way currently is to use a wrapper function, hence the wrapper _NS() call.

The known browsers are, FireFox 2, Opera 9.x, Opera 10b, Chrome 2, Safari 3.x and Safari 4. Note that FireFox 3 requires the namespace, so there is precedence that browsers may change over time.

Thus, rather than hardcoding which browser requires special handling, we test it during startup:

$("ns\\:elm", xml_dom2).length Access an element directly
$("elm", xml_dom2).length Access it without the namespace

Your browser is .

It can be very long, but that's how some browsers identify themselves.

(For speed, we will probably hardcode the known browser/versions and test only the unknown ones.)

Testing jQuery clone()

Can your browser handle clone()? HTML is not a problem, but you cannot take it for granted for XML. It works in IE and FireFox, but not Opera, Safari and Chrome. In particular, it gives an error in Opera.

HTML



$("div.test").clone().length 1
$("div.test").clone().children().length 4
$("*", "div.test").clone().length 4

XML



$(xml_dom).length 1
$(xml_dom).children().length 1
$(xml_dom).children().children().length 2
$(xml_dom).clone().length 1
$(xml_dom).clone().children().length 1
$(xml_dom).clone().children().children().length 2
$("*", xml_dom).clone().length 9
$(xml_dom).children().clone().length 1
$(xml_dom).children().clone().children().length 2

This table gives us a clue what's wrong. $(xml_dom).length is 1, but $(xml_dom).children().length is also 1! Thus, the XML object that we have is actually the XML document. The next level is the XML DOM that we are interested in.

For some reason, some browsers do not allow us to clone the XML document. Now that we know this is the case, we clone the XML DOM instead. It works!

Namespaced XML



$(xml_dom2).length 1
$(xml_dom2).children().length 1
$(xml_dom2).children().children().length 2
$(xml_dom2).clone().length 1
$(xml_dom2).clone().children().length 1
$(xml_dom2).clone().children().children().length 2
$("*", xml_dom2).clone().length 9
$(xml_dom2).children().clone().length 1
$(xml_dom2).children().clone().children().length 2

It is really unfortunate that Opera has such a small market share that people don't see the need to make it work.