14

Is there any way to detect a change to document.title / head > title via Javascript? I want to detect this via a Google Chrome extension content script, so I can't really wire up code in the target page's JS where the actual title change is performed.

I've found WebKitMutationObserver which theoretically should be able to detect a change to head > title, but it doesn't work for all cases:

// set up an observer for the title element
var target = document.querySelector('title');
var observer = new WebKitMutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        console.log(mutation);
    });
});
var config = { attributes: true, childList: true, characterData: true };
observer.observe(target, config);

// this jQuery statement fires the observer as expected ...
$('head > title').text('foo');

// ... but this doesn't:
document.querySelector('title').innerText = 'cheezburger';

// ... and neither does this:
document.title = 'lorem ipsum';

Any ideas?

11684
  • 7,120
  • 10
  • 45
  • 69
joelpt
  • 3,379
  • 1
  • 26
  • 26

2 Answers2

34

I have found a fully working solution which is only a small modification to the example I posted in the original post.

// set up an observer for the title element
var target = document.querySelector('head > title');
var observer = new window.WebKitMutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        console.log('new title:', mutation.target.textContent);
    });
});
observer.observe(target, { subtree: true, characterData: true, childList: true });

// all three of these methods correctly fire the mutation observer
setTimeout(function() { document.title = 'foo'; }, 1000); // the usual method
setTimeout(function() { document.querySelector('head > title').innerText = 'bar'; }, 2000); // DOM method
setTimeout(function() { $('head > title').text('cheezburger'); }, 3000); // jQuery-only method

The addition of subtree: true was all that was needed to get this working right.

The wrapping of the three title-changing methods in setTimeout calls at the end is just for demonstration purposes; without this the title value changes so quickly that the WebKitMutationObserver doesn't report each change individually, since MutationObserver is designed to accumulate changes over a short period before executing the observer callback.

If one does not need to detect title changes made via the last jQuery-only method, the childList: true property can be omitted from the observer.observe line; only characterData: true is needed to detect the first two title-changing methods.

joelpt
  • 3,379
  • 1
  • 26
  • 26
  • 1
    Just a quick note that there's an issue for this: http://code.google.com/p/chromium/issues/detail?id=134322 – psema4 Dec 11 '12 at 23:28
  • ​+1 just for `$('head > title').text('cheezburger');` :') – Marco Bonelli Jan 11 '15 at 16:34
  • Just as a note for everyone, the head > title selector misses two edge cases that appear on some webpages with semi-broken HTML: https://github.com/erichgoldman/add-url-to-window-title/pull/33#issue-535090796 – phiresky Dec 09 '20 at 10:57
2

You have both JQuery and Javascript in your code example. Not sure if your only restricted to JavaScript, but here's how you can do it with jQuery

If you want to trigger the change, take a look at: http://api.jquery.com/trigger/

jQuery

$(document).ready(function () {
    $("title", "head").change(function () {
        console.log("Title has changed");
    });
    //Trigger Change
    $("title","head").text("New Title").trigger("change");
});
anAgent
  • 1,980
  • 17
  • 28
  • Unfortunately this only works if the change is manually triggered as per your example; if `document.title = 'foobar';` is used the event listener does not fire. – joelpt Jul 27 '12 at 18:53
  • Not sure what your intent is, but take a look at: http://stackoverflow.com/a/413455/1220302 and see if it causes you any future issues. Just a note on this, maybe you can update your question with the detials; why are you changing the title of the document? – anAgent Jul 27 '12 at 18:58
  • I'm not changing the document title myself, but rather want my Chrome extension to be able to detect when any given page updates its own title. – joelpt Jul 27 '12 at 19:11