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

问题描述 投票:2回答:2

此代码选择数据ID之间的最高数值,并为其添加石灰背景。 代码在页面首次加载时起作用,但是当加载页面时,data-id正在改变,因此不会搜索新的data-id。我添加了一个再次启动代码的功能,但它无法正常工作。

如何找到不断变化的数据ID并添加石灰背景?

我在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>
javascript jquery greasemonkey tampermonkey
2个回答
2
投票

你试图破解的页面/网站显然是通过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>

0
投票

首先,您需要再次调用该函数,但是很多时候您希望发生此行为。

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.