Greasemonkey - Wait for element to appear

Scorpion Ghost

Elite Member
Executive VIP
Jr. VIP
Joined
Mar 22, 2013
Messages
9,143
Reaction score
10,489
I created this Greasemonkey script to clear out an annoying field that gets autofilled on some site.

Code:
// ==UserScript==
// @name     Whatevs
// @include  https://site.com/
// @require  http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// @require  https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant    GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
    introduced in GM 1.0.   It restores the sandbox.
*/


setTimeout(function() {

var elems = document.querySelectorAll('[name^="url"]');

for (var i = 0, len = elems.length; i < len; i++)

{     elems[i].value = ""; }

}, 20000);

The problem is that the element appears 10-20 seconds after the page has loaded. In order to make the script work, I had to use the "setTimeout" function. But it's not efficient.

The element could appear after 10 seconds, and then I have 10 seconds of the field not being cleared. Or it could appear after 30 seconds and never get cleared, because when the script runs it won't find the selector.

I tried googling and reading stackoverflow, using some "waitforkeyelements" and other solutions, but I didn't manage to make it work.

Can anyone wrap my code in a "wait until element appears" type of code black magic? :D

Thanks
 
The answer is simple. You need setInterval, not setTimeout. setTimeout would only fire that function once. setInterval will keep firing that function as many times as you like. Modify the code like below:

Code:
// ==UserScript==
// @name     Whatevs
// @include  https://site.com/
// @require  http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// @require  https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant    GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
    introduced in GM 1.0.   It restores the sandbox.
*/


var intv = setInterval(function() {
    var elems = document.querySelectorAll('[name^="url"]');
    if(elems.length < 1){
        return false;
    }
    //when element is found, clear the interval.
    clearInterval(intv);
    for (var i = 0, len = elems.length; i < len; i++){  
        elems[i].value = "";
    }
}, 100);
This will be fired every 100 milliseconds, and once the element is found; the interval will be cleared.

Try this and let me know if it works. :)
 
The answer is simple. You need setInterval, not setTimeout. setTimeout would only fire that function once. setInterval will keep firing that function as many times as you like. Modify the code like below:

Code:
// ==UserScript==
// @name     Whatevs
// @include  https://site.com/
// @require  http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js
// @require  https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant    GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
    introduced in GM 1.0.   It restores the sandbox.
*/


var intv = setInterval(function() {
    var elems = document.querySelectorAll('[name^="url"]');
    if(elems.length < 1){
        return false;
    }
    //when element is found, clear the interval.
    clearInterval(intv);
    for (var i = 0, len = elems.length; i < len; i++){ 
        elems[i].value = "";
    }
}, 100);
This will be fired every 100 milliseconds, and once the element is found; the interval will be cleared.

Try this and let me know if it works. :)

That is awesome, works perfectly! :)

Another member of the forum gave me a solution via PM, but he used Timeout... anyway he did it in a way that improved on what I had, but still wasn't perfect. Your solution is 100% perfect.

Thanks man :)
 
That is awesome, works perfectly! :)

Another member of the forum gave me a solution via PM, but he used Timeout... anyway he did it in a way that improved on what I had, but still wasn't perfect. Your solution is 100% perfect.

Thanks man :)
You're welcome :)
 
Back
Top