代码之家  ›  专栏  ›  技术社区  ›  Alex C

在Javascript中将事件侦听器添加到“内存对象”中?

  •  1
  • Alex C  · 技术社区  · 14 年前

    问题的一些背景: Reverse Engineering the DOM, Javascript events & "what's going on"?

    我正在写一些东西,将“发挥”谷歌的网页预览功能的实时搜索。实际上,我想在keyup事件中添加一个事件侦听器

    1. 查询页面预览结果(向google发送ajax请求)
    2. 在内存中读取结果
    3. 将其实时添加到搜索页面

    这将基本上创建一个实时页面预览搜索结果将谷歌。

    公平地说,我实际上已经有95%的工作在不同的组件中,我正在调整功能,使其更加用户友好。如果你对我所做的事情的原因和方式感兴趣,请随时查看我以前在 http://chesser.ca 或者看看“最新版本的代码” http://chesser.ca/gvs.marklet.0.3.js (目前我有点“功能之间”的问题,所以很麻烦。

    浏览器的bookmarklet代码如下:

     javascript:(function{var head= document.getElementsByTagName('head')[0];var script= document.createElement('script');script.type= 'text/javascript';script.src= 'http://chesser.ca/gvs.marklet.0.3.js';head.appendChild(script);};)();
    

    (keyup event listener当前设置为off,基本上是为了使其在当前状态下工作,您可以在带有实时预览的页面上运行搜索,然后单击bookmarklet一次(以启动查询),等待一两秒钟,然后再次单击它(以显示页面预览)

    所以我要做一些改变:

    在第1部分(性能)中,我只想查询前两个元素。我想这很容易,唯一能阻止我的是我还没有试过(而不是所有的div.length,只需设置为2)

    function query_current_pages(){
         var all_divs = document.getElementsByTagName('div');
         for (i=0;i < all_divs.length; i++) {
             if (all_divs[i].className == 'vsc') {
                 google.vs.ea(all_divs[i]);
             }
         }
     }
    

    下一个问题(也是我不确定的一个问题)是如何设置事件侦听器并修改add_previews函数,以便在请求返回时添加预览,而不是通过在 google.vs.ha 内存空间,而不是我想创造一些东西,将监听数据在那里,然后采取行动。

    这个 原因 我试着这么做是因为我觉得它会非常整洁。我在做这件事的时候学到了很多关于编码的东西。

    对于那些对页面预览如何被“扔在页面上”感兴趣的人来说,这里有一个函数,它循环遍历内存中的所有图像并将它们放置起来。

     function add_previews(){
        c=document.getElementById('ires');
        nli=document.createElement('div');
        cell = 0;
        for(var Obj in google.vs.ha){
            na=document.createElement('a');
            na.href=Obj;
    
            nd=document.createElement('div');
            cldiv=document.createElement('div');
            cldiv.style.clear = 'both';
    
            nd.style.width=google.vs.ha[Obj].data.dim[0]+'px';
            nd.style.height=google.vs.ha[Obj].data.dim[1]+'px';
            nd.style.margin = '5px';
            nd.style.padding = '5px';
            nd.style.cssFloat = 'left';
            nd.style.border = '1px solid #999999';
    
            if (google.vs.ha[Obj].data.tbts.length) {
                nilDiv = document.createElement('div'); 
                for(i = 0; i < google.vs.ha[Obj].data.tbts.length; i++){
                    box = google.vs.ha[Obj].data.tbts[i].box;
                    newbox = document.createElement('div');
                    newbox.className = 'vsb vsbb';
                    newbox.style.position = 'relative';
                    newbox.style.top = (box.t)+'px';
                    newbox.style.left = box.l+'px';
                    newbox.style.height = box.h+'px';
                    newbox.style.width = box.w+'px';
                    nilDiv.appendChild(newbox);
                    newtext = document.createElement('div');
                    newtext.className = 'vsb vstb';
                    newtext.innerHTML = google.vs.ha[Obj].data.tbts[i].txt;
                    newtext.style.top = (box.t)+'px';
                    newtext.style.position = 'relative';
                    nilDiv.appendChild(newtext);
                }
                nilDiv.style.height = '0px';
                nd.appendChild(nilDiv);
            }
    
            for(i = 0; i < google.vs.ha[Obj].data.ssegs.length; i++){
                ni=document.createElement('img');
                ni.src += google.vs.ha[Obj].data.ssegs[i];
                ni.className+=' vsi';
                na.appendChild(ni);
            }
            nd.appendChild(na);
            nli.appendChild(nd);
        };
        c.insertBefore(nli,c.firstChild);           
     } 
    

    在这里(使用事件侦听器)明显要改变的一点是 for(var Obj in google.vs.ha){ 单身 google.vs.rs 传入的对象。

    如果你一直在问这个问题:谢谢你的阅读:) -亚历克斯

    编辑

    根据下面的讨论,google.vs.Ga似乎负责查询数据(答案是对函数的过度编写)

    为了提供信息和乐趣,这里是.Ga代码。

      google.vs.Ga = function (a, b, c) {
            var d = google.vs.b.kfe.kfeHost,
                g = google.vs.Ya(a),
                i = a.getAttribute("sig");
            if (i) {
                var f = google.vs.qa(a);
                if (f) {
                    d = [d ? "http://" + d : "", google.vs.b.kfe.kfeUrlPrefix, "&d=", encodeURIComponent(f), "&b=1", "&jsonp=google.vs.r"];
                    d.push("&a=");
                    d.push(encodeURIComponent(i));
                    if (i = a.getAttribute("blobref")) {
                        d.push("&bl=");
                        d.push(i)
                    }
                    d.push("&rs=");
                    i = 0;
                    for (var j; j = g[i++];) {
                        d.push(encodeURIComponent(j));
                        i < g.length && d.push("&rs=")
                    }
                    g = google.vs.m(a) || {
                        ub: a
                    };
                    g.G = c;
                    google.vs.ha[f] = g;
                    c = d.join("");
                    c = new google.vs.Ia(f, c, function () {
                        google.vs.P(a, h);
                        o(google.vs.k, f)
                    });
                    b ? p(google.vs.k, c) : q(google.vs.k, c)
                }
            }
        };
    
    2 回复  |  直到 7 年前
        1
  •  3
  •   Matt    14 年前

    google.vs.ha对象是一个基本的JavaScript对象,具有键/值对属性,没有任何功能可言。也就是说,这些简单的对象无法在更改时通知您。

    在我看来,你基本上有两个选择:

    • 定期检查google.vs.ha以获取您正在查找的数据,并跟踪您已经获取的图像。这可以通过setInterval()实现;

    • 确定页面或谷歌中的哪个功能。namespace负责执行加载数据的工作。一旦确定了数据加载的位置,以及google.vs.ha对象的更新位置,就可以用包含事件通知的自己的手工艺替换原始函数。

    例如,如果我有一个基本函数如下所示:

    var Example = function(value){
      var closured = ' world';
      this.value = value;
      this.doSomething = function(){ alert(this.value + closured); };
    };
    
    var test = new Example('hello');
    test.doSomething(); // will only alert 'hello world';
    
    var oldFunc = test.doSomething;
    var notifyMe = function(){ alert('notified'); }; // callback function
    
    // Update previous method to do it's normal thing, but then notify after
    test.doSomething = function(){
      oldFunc.apply(this, arguments);
      notifyMe();
    };
    
    test.doSomething(); // will alert 'hello world', and then 'notified'
    

    在上面的代码中,我们已经用自己的函数有效地替换了旧的doSomething函数。这个新版本仍然执行它以前的职责(通过oldFunc.apply),但是之后会通知您。

    请注意,您的新函数只能访问对象的“public”属性,而不能访问闭包捕获的私有元素(例如“closured”var)。我似乎记得谷歌倾向于避免私有变量作为闭包方法,这是因为这会增加内存管理的复杂性,所以这可能不是问题。

    更新:我在谷歌搜索结果页面上玩了一会儿。我运行了一个新的搜索,但在单击预览之前,我在Chrome控制台中执行了以下操作:

    var old = google.vs.Ga;
    var newFunc = function(){
      old.apply(this, arguments);
      console.log(arguments);
    };
    
    google.vs.Ga = newFunc; 
    

    它似乎是在点击预览后触发的。

        2
  •  1
  •   naugtur    14 年前

    图像是下载后存储的,对吧?很明显。 所以他们唯一能改变的就是AJAX请求。

    因此,每次AJAX请求成功时,都必须运行一些检查。jQuery具有成功的AJAX调用的全局绑定,因此即使没有它也应该是可能的。

    现在,当我们知道这一点时,检查可能会从查看响应对象或XMLHTTPRequest对象本身中可用的某些变量调用的类型开始。这可以减少您需要调用更新程序的次数。