views:

55

answers:

3

I have written a Userscript for Facebook and it groups similar notifications together. Now, using just a static HTML page with old notifications I had, the script works 100%.

Here's the problem: the DIV that holds notifications by default, has no notifications in it until the user clicks on the Notification button. Facebook has an inline onclick event that displays the DIV (Notifications menu) and uses AJAX to grab the notifications. Since my userscript only runs on startup, it finds nothing there - it has no effect on the page. I tried using a .click() event but right when you click the Notifications button it runs my code. The thing is, Facebook is still running it's AJAX request for the notifications, meaning that there are still no notifications for my script to work with, making it have no effect.

I don't want to use a generic setTimeout because I don't want the user to have to see the notifications before and then suddenly see them after. Is there a way to monitor the DIV so once the notifications are added, it runs? Or that once Facebook finishes it's AJAX request, it will run my code?

A: 

Maybe you can add a setTimeout loop. Something like

setTimeout(function(){
/* check for divs */

if(/* divs are found */){
//apply code
}
else {
setTimeout(/* loop again */);
}

},1000);
digitalFresh
I see your point but if for some reason Facebook stalls, then I might miss the point. If Facebook loads quite fast, I don't want my script to have to way down the user and make them wait on it. Thanks though!
NessDan
A: 

You can setInterval() to monitor the div's innerHTML, once populated you can run.

Babiker
For the sake of performance, I'm about to put a setInterval that starts on-click of the Notifications button and does a check every .5sec . How and when can I end it?
NessDan
You can use `clearInterval()`.
Babiker
Thanks man, I ended up using a setInterval() and called all the JS to change the notifications (I also used CSS to hide the default-looking notifications.)Everything turned out better than expected :)
NessDan
using setInterval() is going to further hurt the performance of an already hurting website. It's much better to listen to the DOMNodeInserted event.
Erik Vold
Right now I have on click of the notifications button, run the setInterval which calls function X every .1 seconds. I replaced that with adding an event listener to the Facebook notifications on click. This did nothing for me :/ The function wasn't called and all it said was that addEventListener was not defined. Can you give me a code snippet? Code as of now for me looks like this:http://www.jsfiddle.net/aeYpx/
NessDan
A: 

Here's the problem: the DIV that holds notifications by default, has no notifications in it until the user clicks on the Notification button. Facebook has an inline onclick event that displays the DIV (Notifications menu) and uses AJAX to grab the notifications.

...

I don't want to use a generic setTimeout because I don't want the user to have to see the notifications before and then suddenly see them after. Is there a way to monitor the DIV so once the notifications are added, it runs?

Yes there is:

var notificationDiv = document.getElementById(...);
var lastTimeoutID = null;
var main = function(evt){
  // evt.target is the inserted element
  // if you expect more elements, then do the following:
  lastTimeoutID = setTimeout(function(){
    lastTimeoutID = null;
    // uncomment below block if you only need to do the work once.
    /*
    notificationDiv.removeEventListener("DOMNodeInserted", main, false);
    */

    // do your work here.
  }, 500); // waiting 500ms for next element to be added, otherwise doing work.
  if (lastTimeoutID) {
    clearTimeout(lastTimeoutID);
    lastTimeoutID = null;
  }
};
notificationDiv.addEventListener("DOMNodeInserted", main, false);

All of the timeout code above might be removable depending on what it is you're userscript is doing.

Erik Vold