Reputation: 75
This code chooses the highest numerical value between the data ids and adds a lime background to it.
The code works just when page is first load, but when page is loaded, data-id was changing so not searching new data-id. I added a function for starting the code again but it isn't working.
How can I find the changing data-id and add a lime background?
I'm using it on Tampermonkey and 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>
Upvotes: 2
Views: 96
Reputation: 93473
The page/site you are trying to hack is apparently updated via AJAX, and this is a job best suited for waitForKeyElements()
or MutationObserver
.
This is not a good use for setTimeout()
. setInterval()
would be a better fit, anyway.
Also, you don't need $(document).ready
unless your script is set to @run-at document-start
.
Anyway, here is how to detect new/changed answers using 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>
Upvotes: 2
Reputation: 9
First, you'll need something to call the function again, however many times you want this behavior to occur.
Then, make sure that you're resetting your counter back to zero somewhere within your code.
i++;
if (i < howManyTimes) {
setTimeout(f, x);
}
setTimeout will only be called when your counter is less than your limit variable. Reset the counter, and setTimeout can be called again when f() is called.
Upvotes: 0