An interesting question came up at work today. We had some existing code that was using the innerText dom method. It worked fine on IE, but not on Firefox (to be clear, I’m used to that working the other way around). If you look at QuirksMode you will see Firefox is the only browser that does not support this method as well.
Turns out if you use innerText on any dom element in IE you will get the text inside the element (in this case a span tag), but in Firefox you just get nothing. I mentioned that JQuery has a text method that does the same thing…but how did that work? I had to look that one up.
Step 1: Find the code
This is actually relatively easy if you know a bit about how methods can be added to objects. Turns out there are three ways to do declare a function in JavaScript – and 5 ways to call one. Anyway, search for “text:”. This is what you should find around line 201 (as of JQuery 1.3.2)
1: text: function(text) {
2: if (typeof text !== "object" && text != null)
3: return this.empty().append((this[0] && this[0].ownerDocument || document).createTextNode(text));
4:
5: var ret = "";
6:
7: jQuery.each(text || this, function() {
8: jQuery.each(this.childNodes, function() {
9: if (this.nodeType != 8 )
10: ret += this.nodeType != 1 ?
11: this.nodeValue :
12: jQuery.fn.text([this]);
13: });
14: });
15:
16: return ret;
17: }
Step 2: Interpreting the code
Line 1 is the method declaration. We are attaching the method to jQuery.fn (line 35 in the document), which is using JavaScript prototype inheritance. The full line is “jQuery.fn = jQuery.prototype = {“. So jQuery.fn is extending all instances of the jQuery class type with the function defined with in the curly brackets {}.
If you look at the JQuery documentation you will notice there are two methods called text, one that takes a parameter, one that does not. You might assume this is the method that takes the parameter – actually, this single function handles both.
In JavaScript, according to JavaScript the Good Parts, what we call parameters, are arguments. You can retrieve arguments passed into a JavaScript function either by the named arguments passed in (the text argument) or via the arguments array (arguments[0]). Using the arguments array you can accept as many, or as few, arguments as you want.
Reading the setter (lines 2 and 3)
Crazy little think about JavaScript, declaring parameters is optional and so is passing them in. Using the line numbers in the code above as a guide: lines 2 and 3 are used if you pass in text to the method. If you did not pass anything into the text parameter, then you move on to line 7 (effectively).
Also note on line 2, the !== operator. In JavaScript there is a difference between != and !==, and their opposites == and ===. The triple === checks the type as well as the value, whereas the == does not check type. So ‘0’ == 0 returns true, where ‘0’ === 0 returns false. Try to use === and !== instead of != and ==.
On line 3 you see ‘this’ a lot. In this particular case, ‘this’ is a reference to the control you are setting the text of. First the element is being cleared, then an element with the text is being created and appended to the control.
A reference to the controls is being returned when everything is said and done.
Reading the getter (lines 4 – 16)
I’m starting on line 9 with the nodeType code. nodeType 9 is a comment, so that isn’t something we want to change. Also nodeType 1 is an element. You would think we would want the text directly from an element type, but we don’t, we want the ‘text’ nodeType (nodeType 3), which should be a child of an element node. So on line 12 you see a recursive call to the text method. Then, once the appropriate nodeType is found, nodeValue is called.
Line 7 and 8 are just there to loop through the multiple elements that a JQuery selector can return (Note: JQuery Selectors always return an array, even if only one item is returned).
Conclusion
OK, I hope you learned something from this, even if it is that JQuery can be opened up, and you can understand what is going on. Please leave a comment if anything I’ve written is in error.
On a side note, the innerText call that was causing trouble could have been replaced with a call to the JQuery text() method, but they went with innerHtml instead. Also, I did a quick search through JQuery to see if innerText was being used anywhere; it is, once, in a filter function that is part of the selector engine.
JavaScript: The Good Parts: Douglas Crockford: Books
ISBN: 0596517742
ISBN-13: 9780596517748
Great article.
I also love how you have enabled smileys in your code block 🙂
OK, that is going to be fun to remove. The smiley is “9 )”
That is a Nice explanation and I also loved the SMILEY 🙂
You are voted!
Track back from WebDevVote.com
I’m having a problem with it however when integrating it into a CMS I have put together. Creating new thumbnails (and other assorted meta and publish infos) are straightforward enough, however I’m coming unstuck when I try to allow administrators the ability to update the thumbnail selection. I have managed to get the selection box to display correctly on my larger image, but I need this selection to be shown in the RHS thumb.
Just noticed a small typo “I’m starting on line 9 with the nodeType code. nodeType 9 is a comment…” nodeType should be 8, not 9
Great article, did learn a few things