2011-09-11 7 views
5

私はfacebookでuser.js// messagesページをやろうとしていましたが、greasemonkeyのように見えます。他の内部ページでも発生します。 まず、AJAXナビゲーションが原因だと思っていましたが、URLが変更されています(ハッシュ部分ではありません)。なぜgreasemonkeyはFacebookの一部のページ変更を検出しないのですか?

// ==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のバージョン:Firefoxの4+を含む、それをサポートするブラウザについては、0.9.11

+0

この他の質問は関連する場合があります。 http://stackoverflow.com/questions/3522090/event-when-window-location-href-changes – bronsoja

答えて

8

、FacebookがHTML5履歴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についてお読みください。

+0

私はあなたがプロキシを使用する必要はないと思う - あなただけの 'window.onpopstate'イベントを処理することはできませんでした? – Coderer

+0

'onpopstate'は、forwardまたはbackボタン(またはforwardおよびback API呼び出し)を使用するときだけ、新しいページに対してpushStateが呼び出されたときに検出されません。 – rampion

+0

このアプローチの問題は、 'old.apply(window.history、arguments)'が返った後に新しいページ要素が必ずしも読み込まれないため、スクリプトが処理する準備ができていない可能性があるということです。 – rampion

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」イベントを取得することスクリプトで既に変更したページに再度挿入されているコンテンツの場合は、重複したコントロールなどを挿入しないように、ページに対して通常行った変更が既に行われているかどうかを確認する必要があります。

0

+1と@の候補です。私は単純なリダイレクトを実行したいと思っていました。ページ上の要素を探すことは、ユーザを無人でリダイレクトしたくないのであまり役に立ちませんでした。

はとにかく、私は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); 
} 

はかなりきちんと動作します。私はリスナが他のものの前に実行されるように、正しい第3のaddEventListener paramを計算しなければなりませんでした。完全なスクリプトについては

は、私は確実にかかわらず、そのURLを変更するには、Webサイトで使用されるメソッドのURLの変更を検出する方法を見つけることができませんでしhttps://greasyfork.org/en/scripts/8176-switch-to-mobile-version-on-facebook-video-page

を見てください。 @ andy-eのアプローチは素晴らしいようですが何らかの理由で私のために働かなかったのです。おそらく私はスクリプト@grantを正しく作れませんでした。

関連する問題