通过Javascript检测文档标题的更改

14

有没有办法通过Javascript检测document.title/head > title的更改?我希望通过Google Chrome扩展内容脚本来检测这一点,因此我无法在目标页面的JS中连接代码,其中实际的标题更改是执行的。

我发现WebKitMutationObserver理论上应该能够检测head > title的更改,但它并不适用于所有情况:

// 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';

有什么想法吗?

你提到了JavaScript,但我看到你正在使用jQuery。你是否愿意使用jQuery或纯JavaScript? - anAgent
我只看到过变异观察器在body内的更改时触发。 - Mitya
2个回答

36

我已经找到了一个完全可用的解决方案,只需要对我在原始帖子中发布的示例进行小修改即可。

// 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
< p >增加subtree: true就足以使其正常工作。

在结尾处用setTimeout包装三个更改标题的方法只是为了演示目的;没有这些,标题值更改得如此之快,以至于WebKitMutationObserver不会单独报告每个更改,因为MutationObserver设计为在短时间内累积更改,然后执行观察器回调。

如果不需要检测最后一个仅使用jQuery的方法进行的标题更改,则可以从observer.observe行中省略childList: true属性;只需要characterData: true即可检测前两个更改标题的方法。


1
只是一个快速的提醒,这个问题已经有对应的链接:http://code.google.com/p/chromium/issues/detail?id=134322 - psema4
+1 只是为了 $('head > title').text('cheezburger'); :') - Marco Bonelli
只是提醒大家一下,head > title选择器会忽略一些半破碎的HTML网页上出现的两个边缘情况:https://github.com/erichgoldman/add-url-to-window-title/pull/33#issue-535090796 - phiresky

2
你的代码示例中同时用了jQuery和Javascript。不确定你是否只限于使用JavaScript,但以下是使用jQuery的方法:
如果你想触发改变,请查看: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");
});

不幸的是,这只有在手动触发更改时才起作用,就像您的示例一样;如果使用document.title = 'foobar';,则事件侦听器不会触发。 - joelpt
不确定您的意图是什么,但请查看以下链接:https://dev59.com/L3RC5IYBdhLWcg3wFdFx#413455,看看它是否会在将来引起任何问题。关于这一点,只是提醒一下,也许您可以更新您的问题并说明细节;为什么要更改文档的标题? - anAgent
我不会自己改变文档标题,相反我希望我的Chrome扩展程序能够检测到任何给定页面更新其自己的标题。 - joelpt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接