2013-07-13 23 views
6

文書の読み込み中にクラス 'nav'を持つ要素が作成されたときに通知する必要があります。グーグルで私は突然変異監視を見つけ、完璧だと思ったが、動かすことができない。greasemonkeyスクリプトの要素作成を監視しますか?

// ==UserScript== 
// @name  ii-shortcuts 
// @namespace https://github.com/RedHatter 
// @include  * 
// @version  1 
// @run-at document-start 
// ==/UserScript== 

var observer = new MutationObserver(function(mutations) 
{ 
    mutations.forEach(function(mutation) 
    { 
     if (mutation.target.getAttribute('class') == 'nav') 
      GM_log('nav creation'); 
    });  
}); 
observer.observe(document, {subtree: true, attributes: true, attributeFilter: ['class']});  

私も試しました。

しかし、netherのケースでは、 'nav creation'がページのログに記録されていました。私は何が欠けていますか?

+0

http://www.w3.org/html/wg/drafts([仕様]にaccoudingない@CrazyTrain /html/master/syntax.html#syntax) "DOMの突然変異イベントは、UAがドキュメントを解析することによって引き起こされた変更に対して発生してはいけません...しかし、突然変異の観察者は、DOM仕様の必要に応じて起動します。 – RedHatter

+0

あなたは[arrive.js](https://github.com/uzairfarooq/arrive)を使うことができます。要素の作成を聞く素敵な単純なAPIを提供しています(内部的にMutationObserverを使用しています)。 –

+0

うーん。ありがとうございました@UzairFarooq – RedHatter

答えて

6

いくつかの問題:

  1. 文書が最初で、静的にロードされました。イベントはchildListイベントで、attributesイベントではありません。例えば

    後続

    $("#foo").attr ("class", "bar2"); 
    

    attributesイベントを生成しながら、

    $("body").append ('<p id="foo" class="bar">Hiya!</p><p>blah</p>'); 
    

    は、 childListイベントを生成します。

  2. mutation.addedNodes[0]クラスnav持つ要素を含むこと確率は実質的にゼロです。これはほとんどの場合、テキストノードです。
    配列全体を確認する必要があります。プラスはtargetです。

  3. クラスを確認するのにgetAttribute('class') == 'nav'を使用しないでください。これにより、getAttribute機能のないノードの例外がスローされ、複数のクラスを持つ要素が欠落します。 EG:<p class="foo nav bar">...

    classList.contains()を適切なノードタイプで使用してください。

  4. GM_log()のようなGM_の機能を使用する場合は、@grantディレクティブを使用してください。とにかくグラントを使用して、サンドボックスがオンになっていることを確認します。

  5. // @include *の使用は避けてください。特にタイマーやオブザーバーでは、これはブラウザーとマシンを駄目にする可能性があります。

  6. この情報はFirefox用です。クロムは、それが突然変異の観察者をどのように実装するかに大きな違いがあります。この種のコードは、ページが読み込まれる前にChromeで動作しません。一緒にすべてを置く


、スクリプトは次のようになります。

// ==UserScript== 
// @name  _ii-shortcuts 
// @namespace https://github.com/RedHatter 
// @include  http://YOUR_SERVER.COM/YOUR_PATH/* 
// @run-at  document-start 
// @version  1 
// @grant  GM_log 
// ==/UserScript== 
/*- The @grant directive is needed to work around a design change 
    introduced in GM 1.0. It restores the sandbox. 
*/ 
var MutationObserver = window.MutationObserver; 
var myObserver  = new MutationObserver (mutationHandler); 
var obsConfig  = { 
    childList: true, attributes: true, 
    subtree: true, attributeFilter: ['class'] 
}; 

myObserver.observe (document, obsConfig); 

function mutationHandler (mutationRecords) { 

    mutationRecords.forEach (function (mutation) { 

     if ( mutation.type    == "childList" 
      && typeof mutation.addedNodes == "object" 
      && mutation.addedNodes.length 
     ) { 
      for (var J = 0, L = mutation.addedNodes.length; J < L; ++J) { 
       checkForCSS_Class (mutation.addedNodes[J], "nav"); 
      } 
     } 
     else if (mutation.type == "attributes") { 
      checkForCSS_Class (mutation.target, "nav"); 
     } 
    }); 
} 

function checkForCSS_Class (node, className) { 
    //-- Only process element nodes 
    if (node.nodeType === 1) { 
     if (node.classList.contains (className)) { 
      console.log (
       'New node with class "' + className + '" = ', node 
      ); 
      // YOUR CODE HERE 
      //GM_log ('nav creation'); 
     } 
    } 
} 
+0

ヒントをありがとう!スクリプトを実行したときに '@ grant'を追加しようとしましたが(そうでなければその厄介なポップが出ます)、私はスクリプトを使っていたサイトを表示したくないので' @include * 'だけを入れますに。 – RedHatter

0

MutationObserversは、ノードの追加だけでなく、属性の変更やノードの削除など、より多くのことが求められます。

mutation.addedNodes nullを返すことに注意してください。この場合、このコードは失敗します。試してみてください:

if (mutation.addedNodes && mutation.addedNodes[0].getAttribute('class') === 'nav') { 
    ... 

mutationオブジェクトには、詳細情報を取得するために使用できる 'type'属性もあります。 MDNのAPIドキュメントをお読みになりましたか?そこには良い例がいくつかあります。 (小への大きな)

+0

私はコードを試して、何も変更されません。この問題は、スクリプトが失敗するのではなく、クラスnavを持つ要素が決してMutationObserverに渡されないということです。はい、私はドキュメントを読んでいます。 – RedHatter

+0

このコードで見ているHTMLのテストページがありますか? – Wheeyls

関連する問題