1

I'm running a script on Facebook that requires me to get the IDs of people in my "friends" window (this might not be the most efficient way to accomplish this specific task, but since I'd like to know how to do this in general it's a good example).

This means that if I have more than a small number of friends I have to scroll down for Facebook to add them to the page.

I've added logic that scrolls the page down to the footer, but I don't know how to force my function that grabs the IDs to run after the content loads.

For now, I've resorted to using setTimeout for a few seconds - obviously, this isn't guaranteed to at the appropriate time, so I'd like to know how to do this properly:

var k;
function doit(){

    k = document.getElementsByClassName("_698");

    var g= Array.prototype.slice.call(k);
    confirm(g.length);
    // the confirm is just to make sure it's working 
    // (if i don't use setTimeout it'll return a smaller number 
    //  since not all the friends were included)

} 

window.addEventListener("load", function(){ 
  document.getElementById( "pageFooter" )
    .scrollIntoView();setTimeout(doit,3000);
  });
Brock Adams
  • 90,639
  • 22
  • 233
  • 295

1 Answers1

2

Crayon Violent details how to accomplish this in his answer to JavaScript detect an AJAX event. The trick is to hook the underlying XMLHttpRequest object in order to detect when a request is sent.

I've re-written the logic there a bit to make it more suitable for your needs:

//
// Hooks XMLHttpRequest to log all AJAX requests. 
// Override ajaxHook.requestCompleted() to do something specific 
// in response to a given request.
//
var ajaxHook = (function()
{
   // we're using a self-executing function here to avoid polluting the global
   // namespace. The hook object is returned to expose just the properties 
   // needed by client code.
   var hook = { 
     // by default, just logs all requests to the console. 
     // Can be overridden to do something more interesting.
     requestCompleted: function(xmlHttp, url, method) { console.log(url); } 
   };

   // hook open() to store URL and method
   var oldOpen = XMLHttpRequest.prototype.open;
   XMLHttpRequest.prototype.open = function(method, url)
   {
      this.hook_method = method;
      this.hook_url = url;
      oldOpen.apply(this, arguments);
   }

   // hook send() to allow hooking onreadystatechange
   var oldSend = XMLHttpRequest.prototype.send;
   XMLHttpRequest.prototype.send = function()
   {
      var xmlhttp = this;

      //hook onreadystatechange event to allow processing results
      var oldReadyStateChange = xmlhttp.onreadystatechange;
      xmlhttp.onreadystatechange = function()
      {
         oldReadyStateChange.apply(xmlhttp, arguments);

         if ( this.readyState === 4 ) // completed
         {
            hook.requestCompleted(xmlhttp, 
              xmlhttp.hook_url, xmlhttp.hook_method);
         }
      };

      oldSend.apply(this, arguments);
   };

   return hook;
})();

With this bit of code loaded in your userscript, you can then implement your logic as follows:

var k;
function doit()
{
    k = document.getElementsByClassName("_698");

    var g= Array.prototype.slice.call(k);
    confirm(g.length);
} 

window.addEventListener("load", function()
{     
   ajaxHook.requestCompleted = function(xmlhttp, url, method)
   {
      // is this the request we're interested in? 
      // (Facebook appears to load friends from a URL that contains this string)
      if ( /AllFriendsAppCollectionPagelet/.test(url) ) 
      {
         // Facebook defers rendering the results here, 
         // so we just queue up scraping them until afterwards
         setTimeout(doit, 0); 
      }
   };

  // trigger loading of more friends by scrolling the bottom into view
  document.getElementById( "pageFooter" )
    .scrollIntoView();
});
Community
  • 1
  • 1
  • Not familiar with ajax but seems like a good place to start, are you defining ajaxHook as a function which uses itself? –  Jun 03 '14 at 21:34
  • I'm a pretty hard time understanding some of those, would you mind if we chat? –  Jun 04 '14 at 09:51
  • 1
    This question should help you understand that construct, @user336: http://stackoverflow.com/questions/592396/what-is-the-purpose-of-a-self-executing-function-in-javascript - if you have more extensive questions about the code here, you might wish to just ask a new question. – Shog9 Jun 04 '14 at 19:59