代码之家  ›  专栏  ›  技术社区  ›  Nur Bar

如何再次启动代码?(在动态更新的页面上)

  •  2
  • Nur Bar  · 技术社区  · 8 年前

    此代码在数据ID之间选择最高的数值,并向其添加石灰背景。
    代码仅在第一次加载页面时有效,但在加载页面时,数据id发生了变化,因此无法搜索新的数据id。我添加了一个函数,用于再次启动代码,但它不起作用。

    如何找到不断变化的数据id并添加lime背景?

    我在Tampermonkey和Greasemonkey上用它。

    var i = 0, howManyTimes = 20;
    function f() {
        maxData = $(".answers li[data-id]").get().reduce((maxObj, crrntNode) => {
            var node = $(crrntNode).data("id");
            var idVal = parseInt(node.substr(node.length - 4), 16);
    
            if (idVal > maxObj.value) {
                maxObj.value = idVal;
                maxObj.node = crrntNode;
    
            }
            return maxObj;
        },
            { value: 0, node: null }
        );
        // $("body").append (`<p>The highest data-id value was ${maxData.value}.</p>`)
        $(maxData.node).css("background", "lime").attr("id", "findvalue");
    
        $(document).ready(function () { //When document has loaded
    
            setTimeout(function () {
                // document.getElementById("findvalue").setAttribute("id", "oldvalue");
                $('li').css("background", "");
            }, 100); //Two seconds will elapse and Code will execute.
        });
    
        var x = Math.floor((Math.random() * 500) + 1);
        i++;
        if (i < howManyTimes) {
            setTimeout(f, x);
        }
    }
    f();
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div id="question-text" class="question sp-element border-radius active">What is favorite colour?</div>
    <ul class="answers" id="answers">
        <li data-id="58b9890062279282090ddc61" class="answer active">Purple</li>
        <li data-id="58b9890062279282090ddc85" class="answer active">Blue</li>
        <li data-id="58b9890062279282090ddc64" class="answer active">Yellow</li>
        <li data-id="58b9890062279282090ddc66" class="answer active">Red</li>
    </ul>
    2 回复  |  直到 8 年前
        1
  •  2
  •   Brock Adams    8 年前

    您试图入侵的页面/站点显然是通过AJAX更新的,并且 这是一份最适合 waitForKeyElements() MutationObserver .
    这对 setTimeout() . setInterval() 无论如何,这更合适。

    而且,你不需要 $(document).ready @run-at document-start .

    无论如何,下面是如何使用MutationObserver检测新的/更改的答案:

    function highliteMaxAnswer () {
        var maxData     = $(".answers li[data-id]").get ().reduce ( (maxObj, crrntNode) => {
            //-- Don't trust page to update data. But we know attributes are changing.
            var nodeId  = $(crrntNode).attr ("data-id");
            var idVal   = parseInt (nodeId.slice (-4), 16);
            if (idVal > maxObj.value) {
                maxObj.value = idVal;
                maxObj.node = crrntNode;
            }
            return maxObj;
          },
            {value: 0, node: null}
        );
        $(".answers li[data-id]").css ("background", "");
        $(maxData.node).css ("background", "lime");
    }
    highliteMaxAnswer ();
    
    var answerObsrvr    = new MutationObserver (answerChangeHandler);
    var obsConfig       = {
        childList: true, attributes: true, subtree: true, attributeFilter: ['data-id']
    };
    answerObsrvr.observe (document.body, obsConfig);  //  Use container versus body, if possible.
    
    function answerChangeHandler (mutationRecords) {
        var answersChanged  = false;
    
        mutationRecords.forEach (muttn => {
            if (muttn.type === "attributes")
                answersChanged = true;
            else if (muttn.type === "childList"  &&  muttn.addedNodes  &&  muttn.addedNodes.length) {
                for (let nwNode of muttn.addedNodes) {
                    if (nwNode.attributes  &&  nwNode.attributes["data-id"]) {
                        answersChanged = true;
                        break;
                    }
                }
            }
        } );
        if (answersChanged)  highliteMaxAnswer ();
    }
    
    /*---------------------------------------------------------------------
    All code, below, is just to simulate the changing page.
    Do not include it in your script.
    */
    $("button").click ( function () {
        this.qCnt = this.qCnt || 1;
        this.qCnt++;
        $("#question-text").text (`What is your favorite color ${this.qCnt}?`);
    
        $(".answer").each ( function () {
            var newDataId = "58b9890062279282090d" + getRandomHexWord ();
            //-- Use attr() versus data() to simulate what website does.
            $(this).attr ("data-id", newDataId);
        } );
    } );
    function getRandomHexWord () {
        return ('0000' + parseInt (65536 * Math.random() ).toString (16) ).slice (-4);
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div id="question-text" class="question">What is your favorite color?</div>
    <ul class="answers" id="answers">
        <li data-id="58b9890062279282090ddc61" class="answer">Purple</li>
        <li data-id="58b9890062279282090ddc85" class="answer">Blue</li>
        <li data-id="58b9890062279282090ddc64" class="answer">Yellow</li>
        <li data-id="58b9890062279282090ddc66" class="answer">Red</li>
    </ul>
    <button>Simulate New Question</button>
        2
  •  0
  •   Jake    8 年前

    首先,您需要一些东西来再次调用该函数,无论您希望这种行为发生多少次。

    然后,确保在代码中的某个地方将计数器重置回零。

    i++;
    if (i < howManyTimes) {
        setTimeout(f, x);
    }
    

    只有当计数器小于限制变量时,才会调用setTimeout。重置计数器,调用f()时可以再次调用setTimeout。

    推荐文章