Way Wrong

The TITLE element and jQuery’s text() function

You’re doing it wrong. In a day of zero fun, a coworker and I ended up tasked with debugging a jQuery-based script that seemed to be perfectly fine, except of course, the part where it wasn’t working as expected in IE. After some tracing, it turns out the issue had everything to do with one line of code not returning a value: $("title").text();. To translate, the author of the code had been trying to retrieve the text of the title element using jQuery’s text function. But, turns out that doesn’t work in IE.

The solution

If you want to retrieve the value of the page title, use document.title. If you want to set the value of the page title—the title displayed at the top of the browser—use document.title.

It doesn’t matter if you’re working with straight JavaScript or a library like jQuery, the correct way to interact with the page title is through document.title.

Here’s a full code example:

var foo = document.title;
alert("The title was "+foo);
// on this site, the above alert would read
// "The title was The TITLE element and jQuery’s text() function"
document.title = "Now it’s been changed.";
alert(document.title);
// this alert = "Now it’s been changed"
// the display at the top of the browser changes too

The explanation

Don’t worry, I’m not going to leave you high and dry without explaining why the original approach didn’t work.

The problem exists in IE because IE doesn’t consider the title element to have child nodes. By W3C specs, the title element contains one, and only one child node: a text node. It can not have any child elements. Just the one text node.  But according to IE, that text exists in some strange nebulous state outside of a normal text node. Here’s a code example.

var titles = document.getElementsByTagName("title");
var kids = titles[0].childNodes;
alert(kids.length);

If you run that code in IE, the alert will be 0. In FireFox, Chrome, Safari, Opera, etc, it will return 1, the expected amount.

Breaking down jQuery.text()

So, the reason $("title").text() doesn’t work in IE is because of jQuery.text()’s reliance on children nodes. Let’s take a look at the function (jQuery version 1.4.2, line 3418):

function getText( elems ) {
	var ret = "", elem;
	for ( var i = 0; elems[i]; i++ ) {
		elem = elems[i];
		// Get the text from text nodes and CDATA nodes
		if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
			ret += elem.nodeValue;
		// Traverse everything else, except comment nodes
		} else if ( elem.nodeType !== 8 ) {
			ret += getText( elem.childNodes );
		}
	}
	return ret;
}

A quick translation of the code is as follows. The first line of the function sets up a variable ret as an empty string. This variable is the return variable for the function. Then we jump into a loop that goes through each object in the array that was passed in (remember, $("title") will return an array with a single element). For each of these elements it checks whether it is a text node. If it is, it appends the node’s value to the return value (ret). If it is an element, it recursively calls itself on that element, appending the result of the recursive call to the return value. At the end, ret is returned.

But, remember, in IE, the title element has no text node, because there are no child nodes. So what does ret equal? An empty string. The entire for loop is skipped, because elems is empty. It essentially goes straight from declaring ret="" to returning that initial value.

The code continues to work in other browsers because they rightly treat the element as having a single child node—a text node— and that node’s value—the text—is added to ret.

innerText doesn’t work either

Even if you’re using plain JavaScript without a a library, document.title is the way to do this. Typically, to set the text of an element in IE you would use the innerText property, but you shouldn’t do that in this situation. There are a couple reasons for this:

  1. It doesn’t work in IE. In fact, it’s a documented issue dating back to IE 5, maybe earlier. At this point, we have to assume Microsoft has it working as they intend it to.
  2. The innerText property doesn’t work cross browser. In FireFox, you have to use the textContent property. Why bother writing extra code to be cross-browser compatible when document.title will work without issue?

Wrapping it up

Here’s that first script again, showing the correct way to do it:

var foo = document.title;
alert("The title was "+foo);
document.title = "Now it’s been changed.";
alert(document.title);

So now you know why you can’t use jQuery.text() to retrieve the page title. But that’s ok, because doing so would be inefficient anyway when you can just call document.title. Good luck with your dev.

8 thoughts on “The TITLE element and jQuery’s text() function”

  1. I just spent an hour or so single-stepping through a bunch of code and libraries tracking down the very same problem. Sure would be nice if you could actually see a stacktrace when debugging javascript in IE/Visual Studio…

  2. Thank you for this thorough explanation.

    I was just having the problem of $(“title”).text();
    not returning anything in ie.
    Now I know why. :)

  3. If any of your guys can help out with this, would be great…

    I’ll try and keep this as short as possible (honest), scenario is this… I have a “price comparison” website which looks for deals via a php? query string url and returns the results as an Iframe inserted into a static “show” template page. Unfortunately that gives me 1000+ pages with duplicate title and meta descriptions…

    What I’m trying to do is grab (server-side, from returned iframe content) a certain element of text (e.g. first text) to change/insert and use the same text to insert in front of my description (i.e. . Hope that makes sense…

    I know basic html and css etc and started reading up on Jquery, but thats it… I’m not a programmer, so having asked question on a couple of forums and “googled” relevant topics, I’ve only got confusing info… most pointing towards Jquery, ajax etc. Thing is everyone goes “tech-speak” on me, might as well be martian… If anyone can help out with this please imagine you are talking to an idiot (yeah, yeah, very funny!)

    Thanks in advance.

    1. Dean,

      That’s a difficult question that is hard to answer without really being able to look at the code, but the most important part of this is that with JQuery/JavaScript you won’t be able to change those titles and descriptions in a way that will benefit you in terms of search engine optimization at all.

      That sounds like a very unfortunate implementation of the site, coding-wise. If I were approached to fix something like that, I’d likely recommend a full restructuring of the site.

      That said, you should be able to use jQuery to navigate the DOM of both the outer frame and the iFrame elements (meaning you can find the first heading of the iFrame, or something) and set the title element using the examples provided above. Hope that helps. If not, feel free to email me. My address is in the footer.

  4. It is indeed a very rare bug to change upon. In my case, I was trying to change the title of the page using jQuery().text(string) function and IE was throwing up a Javascript error!
    After reading this article of course, fixing it was child’s play. Thank you!

Comments are closed.