Run Greasemonkey Script on the Same Page, Multiple Times

Run Greasemonkey script on the same page, multiple times?

The simplest, most robust way is to use the waitForKeyElements() utility.

Here is a complete script that uses jQuery and waitForKeyElements to alter Amazon search results:

// ==UserScript==
// @name _Amazon Search, alter results
// @include http://www.amazon.com/s/*
// @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.
*/

function addCustomSearchResult (jNode) {
//***** YOUR CODE HERE *****
jNode.prepend (
'<div id="result_000" class="fstRow">Buy my stuff, instead!</div>'
);
}

waitForKeyElements ("#atfResults", addCustomSearchResult);

Run a Greasemonkey script only once per page load?

First, you probably don't want the script to run in iFrames.

You can block that using the @noframes directive which now works in both Greasemonkey and Tampermonkey as of October, 2014.

For older versions, or for script engines that don't support @noframes, you can use this code, just after the metadata block:

if (window.top != window.self)  //don't run on frames or iframes
{
//Optional: GM_log ('In frame');
return;
}


Second, you can wait and fire your GM code, once, on page load. Wrap everything in a main() and call it on the load event, like so:

window.addEventListener ("load", LocalMain, false);

function LocalMain () {
// Your code goes here.
}


Third, you can exclude sites or pages by adding // @exclude directives to the metadata block.

Overall, it's best to avoid universally included GM scripts, if possible.

Other methods might set flags or reload the page with URL parameters. These get tricky so save them as a last resort.

Userscript should run once, not multiple times

your script could be loading for each frame in the page.

add // @noframes to prevent this.

// ==UserScript==
// @name Test
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author You
// @match https://myanimelist.net/*
// @require http://code.jquery.com/jquery-3.4.1.slim.min.js
// @grant none
// @noframes
// ==/UserScript==

Why is my GreaseMonkey function unexpectedly being called multiple times?

addIcon collapses all ticketpostcontainer elements, but waitForKeyElements will fire and run it for all three ticketpostcontainer elements. Try something like this to run it once for each:

function addIcon($el) {
var curElement = $el.get(0); // get DOM element
// proceed as above but without the for loop
}

Run notification script only once, even though script runs on multiple tabs

On modern spec-compliant browsers, you can use BroadcastChannel inside the userscript to communicate with other tabs on the same domain. Make the timeout slightly random - add or subtract a few seconds to allow for all the open tabs to coordinate. When sending a notification, also send a message in the BroadcastChannel telling other instances of the userscript to reset their timers as well.

const channel = new BroadcastChannel('logout-notify');

let timeoutId;
function makeTimeout() {
clearTimeout(timeoutId);
timeoutId = setTimeout(function () {
GM_notification({
title: 'Refresh Business Manager', text: 'Your about to be logged out of staging, click here to refresh your login.', image: 'https://i.stack.imgur.com/geLPT.png',
onclick: () => {
console.log("My notice was clicked.");
location.reload();
}
});
channel.postMessage('notified');
}, 1000 * 60 * 20 + (Math.random() * 10000)); // 20 minutes plus up to 10 seconds
}

// When below runs, another tab created a notification
// reset the timeout for this tab, schedule another one for 20ish minutes from now
channel.onmessage = makeTimeout;

// initialize timeout on pageload?
makeTimeout();

This code will result in alerts being shown only once every 20 minutes at most. If you close one tab you were working on, other tabs will take up the slack without interruption.



Related Topics



Leave a reply



Submit