So the other day I was sending a JavaScript string into jQuery's .html() method, and I got this funky, funky little exception in Firefox:
Error: uncaught exception: [Exception... "Could not convert JavaScript argument arg 0 [nsIDOMDocumentFragment.appendChild]" nsresult: "0x80570009 (NS_ERROR_XPC_BAD_CONVERT_JS)"And in Internet Explorer, the message was this:
SCRIPT5022: DOM Exception: HIERARCHY_REQUEST_ERR (3)
Now, according to the officially official jQuery API specs for the html method, when you call .html() as a setter, you can pass in one of two types of arguments -- either a string of HTML, or a function that returns the HTML to set.
But in fact, there's one other type of input accepted that isn't (as of today, anyway) mentioned in the documentation -- a jQuery object:
Perfectly legit, that chunk o' code there. In the case above, #target's contents will be replaced with every span element on the page. In other words, those spans will all move from wherever they are in the DOM, into the #target element.
Now what happens when there's more than one target? For example, on a page with two divs and two spans, what will the following code do?
Don't worry -- I won't leave you hangin'. Never did much like those "exercise for the reader" things anyway. The two spans will vanish from their present location, and a copy is placed into each div.
So, back to my original problem -- why was my string input causing the exceptions above? Because I had sent in a String object, rather than a String primitive.
jQuery evaluates the argument you send to .html() using typeof. If it evaluates to "string", it'll get handled like a string. So, is a JavaScript string a typeof "string" or "object"?
Interestingly, that evaluates to "object".
This, however, evaluates to "string":
This is the nuance that causes jQuery to branch in the wrong direction -- if you pass .html() something that's not a typeof string, and it isn't a function, then jQuery makes the assumption that it's a jQuery object. And when it tries to append the object as a node onto the DOM (using node.appendChild), an exception is thrown, because it's not the right kind of object.
Incidentally, if you're stuck with a JavaScript string object rather than a string primitive, you can morph it into a primitive with the .valueOf() method.
No comments:
Post a Comment