40

I'm totally new to Greasemonkey, javascript, in fact all the UI stuff.

Requirement: Userscript is run by GS once after the page loads. However, I need the same script to be run multiple times without refresh

Use case: For ex, Amazon.com search happens using Ajax. I need to embed a custom element in the search results.

I need to inject my content to the search-results-div along with the results every time a search happens in the same page (there's no page refresh)

My current script runs only with the page refresh.

I hope above explanation is clear. Please help.

Brock Adams
  • 90,639
  • 22
  • 233
  • 295
Firefox
  • 941
  • 2
  • 14
  • 22

2 Answers2

57

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);
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • 2
    Thanks A LOT!!!!! Though I have some programming experience, this UI scripting is kind of troubling (annoying) me. Your code performs exactly the way I wanted. I would customize it to meet further requirements. Thanks a lot again. – Firefox Jun 25 '12 at 22:59
  • I'm trying to use this, but it's not giving me anything useful. It fires when I need it to, but the value in "jNode" is just of type "object". It doesn't appear to be a node or element or anything. Asking for jNode.innerHTML yields "undefined". jNode.parent yields the text of a function that looks like it's internal to the waitForKeyElements script. – Sean Worle Dec 04 '18 at 21:28
  • 1
    @SeanWorle, `jNode` is a [jQuery object](https://learn.jquery.com/using-jquery-core/jquery-object/). You would use `jNode.html()`, for example. – Brock Adams Dec 04 '18 at 21:33
  • @BrockAdams Ah, that's helps. It's frustrating that the "typeof" operator wouldn't tell me that - it only reports the type as "object". – Sean Worle Dec 05 '18 at 22:19
  • I used it to but, I cannot understand why, the function is null. Of course the @require tag in on top of my page – Salvatore Di Fazio Mar 22 '19 at 17:32
  • @SalvatoreDiFazio, we cannot tell what you are doing. Ask a new question if you have to, but be very sure it includes a [mcve]. – Brock Adams Mar 22 '19 at 17:37
14

You can use the DOMNodeInserted event to call your callback, e.g.:

document.addEventListener('DOMNodeInserted', function() { alert('hi') }, false);

Note that the event will be triggered by any change in the page structure, so you'll have to check that you're targeting the right change.

ncreep
  • 473
  • 3
  • 11
  • Thanks a lot, I will check it out. Is is possible to track 'click' event related to search button? – Firefox Jun 25 '12 at 19:56
  • 1
    Mutation events are deprecated, buggy, and not straightforward to use in practice. ... You could track the click event, but the actual page changes will happen some random interval (up to many seconds) after that. – Brock Adams Jun 25 '12 at 22:01
  • `https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Mutation_events` are deprecated and should not be used. Use `https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver` instead. – user136036 Apr 23 '16 at 00:00
  • If the function that you want to attach to `DOMNodeInserted` itself modifies the DOM then a workaround to avoid a `RangeError: Maximum call stack size exceeded` is to temporarily remove the event listener in the function before applying the modification. – Stefan Schmidt Apr 06 '23 at 15:46