javascript - 如何检测已加载新内容以响应滚动触发器?

标签 javascript facebook greasemonkey tampermonkey

我在 Facebook 上运行一个脚本,要求我在我的“ friend ”窗口中获取人们的 ID(这可能不是完成此特定任务的最有效方法,但因为我想知道如何一般来说,这是一个很好的例子)。

这意味着如果我的好友数量较多,我必须向下滚动 Facebook 才能将他们添加到页面。

我添加了将页面向下滚动到页脚的逻辑,但我不知道如何强制获取 ID 的函数在内容加载后运行。

现在,我已经使用了 setTimeout 几秒钟 - 显然,这不能保证在适当的时间,所以我想知道如何正确地做到这一点:

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);
  });

最佳答案

Crayon Violent 在 his answer to JavaScript detect an AJAX event 中详细介绍了如何完成此操作.诀窍是 Hook 底层 XMLHttpRequest 对象,以便检测何时发送请求。

我已经重新编写了一些逻辑以使其更适合您的需求:

//
// 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;
})();

在您的用户脚本中加载这段代码后,您就可以按如下方式实现您的逻辑:

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();
});

关于javascript - 如何检测已加载新内容以响应滚动触发器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24021826/

相关文章:

javascript - 在 Jquery 中调用带参数的函数(单击时)

javascript - 将 iframe 调整为嵌入的 facebook 视频的原始高度/纵横比

python - 在 Django 中使用 python-social-auth 重定向回网站时不可散列的类型

ios - Facebook 登录后 Segue 不起作用

javascript - 覆盖Javascript SetTimeout时间但保留内部函数

javascript - 在 JavaScript 中转换为字符串

javascript - koa:promise vs async await 中间件

javascript - Firebase 9(模块化 sdk web)替换 fieldPath

javascript - 尝试修改 HTMLTableRowElement.prototype

javascript - GreaseMonkey - 在同一选项卡中运行的两个脚本之间共享数据