setTimeout not waiting inside my Tampermonkey script with jQuery?

4.8k Views Asked by At

I'm trying to execute a script in Tampermonkey that will click a checkbox label on a webpage that contains items from various designers. I have the men/women designer in two separate arrays and then merge the arrays.

I check the array against the checkbox inputs on the page and click each corresponding designer's checkbox. Since this executes an AJAX call, it sometimes kills the page when all items are clicked at once. I'd like to wait 500 milliseconds before each iteration of the loop. However, setTimeout does not seem to work - it clicks all of the buttons after page load and completely ignores the timeout.

I've read that there is a jQuery wait function:
$(allDesigners).each().wait(500, {function(){}});
but this just causes an undefined function error and does not work either.

Any advice, tips, or hints relating to adding a timeout or simplifying my code would be great!

// ==UserScript==
// @name     Click Specified Designers
// @require  http://code.jquery.com/jquery-1.9.1.js
// @grant    GM_addStyle
// @run-at document-end
// ==/UserScript==
/*- The @grant directive is needed to work around a major design
change introduced in GM 1.0.
It restores the sandbox.
*/
$(document).ready(function(){
var womenDesigners = ["127","132","223","2709","267","286","296","260","531","815","842","860","938","1081","1361","1415"];
var mensDesigners  = ["84","128","131","224","2218","268","380","297","530","544","579","814","843","861","1080","1104","1362","1401","1416"];
var allDesigners   = $.merge( $.merge( [], womenDesigners ), mensDesigners );

$.each(allDesigners, function(i, val) {
$("input[type=checkbox]").each(function(){
  var inputValue = $(this).attr("value");     
    if(inputValue == val) {   
        setTimeout(function() {
            $(this).parent().click();
        }, 500);
        }                
    });

});
1

There are 1 best solutions below

0
On

this lost its scope, so when calling $(this) inside setTimeout this represents the anonymous function passed as the setTimeout callback.

Save the scope before.

$("input[type=checkbox]").each(function(){
  var self = $(this);
  var inputValue = self.attr("value");

    if(inputValue == val) {   
        setTimeout(function() {
            self.parent().click();
        }, 500);
    }                
});

Also, the .each loop is a synchronus loop, all the setTimeouts will be set at the same time and all will trigger after 500ms. You need a recursive loop to chain setTimeouts.

Another thing is that you do not need the .each() for the checkboxes, you can use directly a CSS selector for that:

$.each(allDesigners, function(i, val) {
    var el = $("input[type=checkbox][val=" + val + "]");

    setTimeout(function() {
        el.parent().click();
    }, 500 * i);
});