为什么greasemonkey在facebook中没有检测到某些页面更改?

时间:2011-09-11 21:27:23

标签: javascript facebook greasemonkey

我试图在facebook中对user.js进行/ message页面,但看起来像在导航从/到/消息更改时不会注意到。它也出现在其他内部页面中。 首先我认为它是由AJAX导航引起的,但URL改变了(不是散列部分),所以这是正常的导航,对吧?

这是我使用的测试页面:

// ==UserScript==
// @name           Test
// @namespace      none
// @description    just an alert when page changes
// @include        http*://www.facebook.com/*
// ==/UserScript==

alert(location.href);

如何正确检测页面更改?


Firefox版本:6.0.2

Greasemonkey版本:0.9.11

3 个答案:

答案 0 :(得分:9)

对于支持它的浏览器,包括Firefox 4+,Facebook利用HTML5 History API。此API允许使用history.pushState()方法更改位置,但实际上不会发生导航。虽然页面似乎已经发生了变化,但所有发生的事情都是幕后的ajax调用,它会改变大部分内容。

如果您想捕获此更改,则必须使用自己的函数代理pushState()方法:

(function (old) {
    window.history.pushState = function () {
        old.apply(window.history, arguments);
        alert(window.location.href);
    }
})(window.history.pushState); 

https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history了解有关历史记录API的更多信息。

答案 1 :(得分:3)

另一种方法是为页面挂钩DOMNodeInserted,并在插入后路径与/messages匹配时运行:

// ==UserScript==
// ...
// @include https://www.facebook.com/*
// ...
// ==/UserScript==

var url = document.location.toString();
function scriptBody(){
   if (!url.match(/facebook.com\/messages/)) return;
   // ...
   // do stuff
   // ...
});

scriptBody(); // run on initial page load

document.querySelector('html').addEventListener('DOMNodeInserted', function(ev){
  var new_url = document.location.toString();
  if (url == new_url) return; // already checked or processed
  url = new_url;

  scriptBody(); // run when URL changes
});

请注意,如果您的用户使用前进/后退按钮,您可能会为正在重新插入已使用脚本修改的页面的内容获取“DOMNodeInserted”事件,因此您需要确保检查是否通常对页面进行了任何更改,以防止插入重复控件或其他任何内容。

答案 2 :(得分:0)

+1 @rampion建议。我想执行一个简单的重定向,在页面上查找元素并不是很有用,因为我不想无意中重定向用户。

无论如何,我使用此代码安装了一个侦听器,当用户点击特定href的链接时,该侦听器会根据需要重定向:

if (document.addEventListener ){
  document.addEventListener("click", function(event) {
    var targetElement = event.target || event.srcElement;
    // TODO: support deeper search for parent element with a href attribute
    var href = targetElement.getAttribute('href') || targetElement.parentElement.getAttribute('href') ;
    if (href && videoURLRe.test(href)) {
      var target = "";
      if (href.indexOf("/") == 0) {
        target = "https://m.facebook.com" + href
      } else {
        target = href.replace("www.facebook", "m.facebook");
      }
      window.location.assign(target);
    }   
  }, true);
}

工作非常整洁。我必须想出正确的第三个addEventListener参数,以便我的侦听器在任何其他参数之前执行。

有关完整的脚本,请查看https://greasyfork.org/en/scripts/8176-switch-to-mobile-version-on-facebook-video-page

无论网站使用何种方法更改该网址,我都无法找到可靠地检测网址更改的方法。 @ andy-e方法看起来很棒但是由于某种原因对我不起作用。也许我无法正确制作脚本@grant标签。