8

MutationObserver を使用して、Web ページに追加された画像を探しています。CSSプロパティを介して多くの画像が表示されるbackground-imageため、タグを探すことに加えて、現在/計算されたCSSスタイルをチェックしていimgます。たとえば...

var hasBackgroundImage = function(node) {
    var nodeStyle = node.currentStyle || getComputedStyle(node, null);
    return (
        nodeStyle &&
        nodeStyle.backgroundImage &&
        nodeStyle.backgroundImage != "none"
        );
};

ただし、ノードがミューテーション イベントをトリガーしてから CSS ルールが適用されるまでには遅延があるようbackgroundImageです。これは、コードがデバッグ中 (ブレークポイントでのステップ実行) に機能したが、実行時に機能しなかったときに気付きました。ミューテーションイベントの処理をsetTimeout遅らせることもできますが、遅延がかなり大きく、ページごとに変化する必要があることを確認する必要があります (CSS ルールがいつ適用されることが保証されるかは正確にはわかりません)。考えられる原因は、単に CSS コンテンツのロードまたはインジェクションの遅延である可能性があります。

この機能を実現する最善の方法は何ですか? 私はオンスタイル変更の突然変異の後だと思いますが、これが存在するとは思えません。

4

1 に答える 1

16

これは私のために働く...

  1. 突然変異オブザーバーを使用して、スタイル属性の変更をキャッチします...

    var observer = new MutationObserver(parseMutations);
    observer.observe(document, {
        ...
        attributes:    true,
        attributeFilter: ["style"]
    });
    
    ...
    
        if (mutation.attributeName) //we'll assume it's "style"
            parseNode(mutation.target); //check for style.backgroundImage and call filterNode()
    

    これは と の両方 setAttribute("style", ...)で機能しelement.style.whatever = somethingます。

  2. 突然変異オブザーバーで新しい要素styleと要素をキャッチし、イベントを追加して、該当するノードを解析します...linkonload

    var stylenodes = ["STYLE", "LINK"];
    
    ...
    
    for (var i = 0; i < mutation.addedNodes.length; i++)
    {
        var node = mutation.addedNodes[i];
        var nodeName = node.nodeName.toUpperCase();
        if (stylenodes.indexOf(nodeName) !== -1)
            node.addEventListener("load", styleLoaded);
    
    ...
    
    //catch loading of stylenodes and parse all new rules
    var currentLoadedStyles = [];
    var styleLoaded = function() {
        //check all styles and look for one that has just added some rules
        for (var i = 0; i < document.styleSheets.length; ++i)
        {
            if (document.styleSheets[i].rules && document.styleSheets[i].rules.length > 0 && currentLoadedStyles.indexOf(document.styleSheets[i]) == -1)
            {
                currentLoadedStyles.push(document.styleSheets[i]);
                parseNewStyle(document.styleSheets[i].rules);
            }
        }
    };
    
    //look for rules with background images and re-filter all nodes it applies to
    var parseNewStyle = function(rules) {
        for (var i = 0; i < rules.length; ++i)
        {
            //if any rule contains a background-image (could look for anything here really)
            if (rules[i].style && rules[i].style.backgroundImage && rules[i].style.backgroundImage != "none")
            {
                //get all affected nodes and re-parse them
                var nodes = document.querySelectorAll(rules[i].selectorText);
                for (var j = 0; j < nodes.length; ++j)
                    filterNode(nodes[j]);
            }
        }
    };
    
于 2013-12-13T05:34:29.473 に答える