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
Better Way to Prevent Browser Caching of JavaScript Files
Change CSS of Class in JavaScript
How to Detect CSS3 Resize Events
How to Make Jquery UI Tabs Scroll Horizontally If There Are Too Many Tabs
Jquery Event That Triggers After CSS Is Loaded
Get the Scale Value of an Element
Count Down Timer with Circular Progress Bar
How to Concatenate and Minify Multiple CSS and JavaScript Files with Grunt.Js (0.3.X)
How to Make Changeable Themes Using CSS and JavaScript
How to Dynamically Modify <Select> in Materialize CSS Framework
Check If an Array Contains Any Element of Another Array in JavaScript
How to Invoke a Jsf Managed Bean on a HTML Dom Event Using Native JavaScript
Converting a Js Object to an Array Using Jquery
How to Check If a Variable Is an Array in JavaScript
I'Ve Heard Global Variables Are Bad, What Alternative Solution Should I Use