1

What kind of handler/hook do I need to set from Greasemonkey script to capture small changes like adding new page elements (thinking of FB messages..)? Can I change the style and innerhtml before the element is drawn?

Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778
kagali-san
  • 2,964
  • 7
  • 48
  • 87

1 Answers1

0

You can override many native functions. If it was the element creation, you'd override document.createElement:

//Remember the old function refference
var old_createElement = document.createElement; 
//Override the native function
document.createElement = function(tagName) {
    //Our own script for the function
    if(!confirm("Element "+tagName+" is being created. Allow?")) 
         throw new Error("User denied creation of a element.");
    else 
        //And eventual call for the original function
        return old_createElement(tagName);
}

Regarding the DOM elements, there seems to be no means of capturing the DOM parser element creation. (creation from HTML string)

Similarly, you can override AJAX methods and in fact I have done this on facebook to see how messages are sent - and I noticed they're sent with tons of other data.

Here's a part of my greasemonkey script for this purpose:

function addXMLRequestCallback(event, callback){
    var oldSend, i;
    if( XMLHttpRequest.callbacks!=null ) {
        // we've already overridden send() so just add the callback
          //XMLHttpRequest.callbacks.push( callback );
        if(XMLHttpRequest.callbacks[event]!=null)
          XMLHttpRequest.callbacks[event].push(callback);
    } else {
        // create a callback queue
        XMLHttpRequest.callbacks = {send:[], readystatechange:[]};
        if(XMLHttpRequest.callbacks[event]!=null)
          XMLHttpRequest.callbacks[event].push(callback);
        // store the native send()
        oldSend = XMLHttpRequest.prototype.send;
        // override the native send()
        XMLHttpRequest.prototype.send = function() {
            // process the callback queue
            // the xhr instance is passed into each callback but seems pretty useless
            // you can't tell what its destination is or call abort() without an error
            // so only really good for logging that a request has happened
            // I could be wrong, I hope so...
            // EDIT: I suppose you could override the onreadystatechange handler though
            for( i = 0; i < XMLHttpRequest.callbacks.send.length; i++ ) {
                XMLHttpRequest.callbacks.send[i].apply( this, arguments );
            }
            /*if(typeof this.onreadystatechange == "function")
              callbacks.readystatechange.push(this.onreadystatechange);*/
            var old_onreadystatechange = this.onreadystatechange;
            this.onreadystatechange = function(event) {
              for( i = 0; i < XMLHttpRequest.callbacks.readystatechange.length; i++ ) {
                  try {
                    XMLHttpRequest.callbacks.readystatechange[i].apply( this, arguments );
                  }
                  catch(error) {
                    console.error(error);
                  }
              }
              if(typeof old_onreadystatechange == "function") {
                  old_onreadystatechange.apply(this, arguments)
              }
            }
            // call the native send()
            oldSend.apply(this, arguments);
        }
    }
}
//Usage
addXMLRequestCallback( "send", function(data) {
   console.log(data);
});
addXMLRequestCallback( "onreadystatechange", ...);

I also often use the MutationObserver in userscripts. At allows to to watch over either properties or children and calls a callback for every added/removed node. I'm not sure how good the performance is and how easy will it be to hook up the correct node.

If you had eventually succeded in capturing creation of facebook chat message containers and/or posts on wall, I'd really love to see how you did it. For a long time, I'm thinking of adding Markdown on facebook. Many friends share sourcecode here but it's barely readable.

Community
  • 1
  • 1
Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778