Добавление слушателей событий к «объектам памяти» в Javascript? - PullRequest
1 голос
/ 24 ноября 2010

Некоторые предыстории проблемы: Обратный инжиниринг DOM, события Javascript и «что происходит»?

Я пишу что-то, что будет «играть» с функциональностью GoogleПредварительный просмотр страницы в режиме реального времени.По сути, я хотел бы добавить прослушиватель событий к событию keyup, который будет

  1. запрашивать результаты предварительного просмотра страницы (отправлять запрос ajax в Google)
  2. читать этот результат в памяти
  3. добавьте его на свою страницу поиска в режиме реального времени

По сути, это создаст живой результат предварительного просмотра страницы в Google.

Если честно, яна самом деле получилось около 95% этой работы в различных компонентах, и я нахожусь на стадии настройки функциональности, чтобы сделать ее немного более удобной для пользователя.Если вам интересны причины и причины того, что я делаю, пожалуйста, ознакомьтесь с моими предыдущими постами в блоге на http://chesser.ca или даже посмотрите «последнюю версию кода» на http://chesser.ca/gvs.marklet.0.3.js (в настоящее время очень глючит, потому что я немного "между функциями" на данный момент.

Код букмарклета для вашего браузера здесь:

 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слушатель в настоящее время отключен, по сути, чтобы он работал в своем текущем состоянии, вы запускаете поиск на странице с предварительным просмотром в реальном времени и один раз нажимаете на букмарклет (для инициирования запросов), ждете секунду или две, затем нажимаете на него второй раз(для предварительного просмотра страницы)

Итак, я должен внести некоторые изменения:

В части 1 (для производительности) меня интересуют только запросы к первым двум элементам.Я полагаю, что это будет легко, и единственное, что меня останавливает, это то, что я еще не пробовал (вместо всех divs.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 ]

3 голосов
/ 24 ноября 2010

Объект google.vs.ha - это базовый объект JavaScript с атрибутами пары ключ / значение и без функций, о которых можно было бы говорить. При этом эти простые объекты не способны уведомлять вас, когда они изменяются.

На мой взгляд, у вас есть 2 варианта:

  • Периодически проверяйте google.vs.ha на наличие данных, которые вы ищете, отслеживая, какие из них вы уже захватили изображения. Это может быть выполнено с помощью setInterval ();

  • Определите, какая функция на странице или в Google. 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, а не к закрытым элементам, захваченным замыканием (таким как var 'closured'). Кажется, я где-то помню, что Google стремится избегать закрытых переменных при подходе к замыканиям из-за сложностей, которые это может добавить к управлению памятью, поэтому это может не быть проблемой.

ОБНОВЛЕНИЕ: я немного поиграл с этим на странице результатов поиска Google. Я запустил новый поиск, но перед нажатием на предварительный просмотр я выполнил в консоли Chrome следующее:

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

google.vs.Ga = newFunc; 

И, похоже, оно сработало после нажатия кнопки предварительного просмотра.

1 голос
/ 24 ноября 2010

Изображения хранятся, ПОКА они загружены, верно? Очевидный. Таким образом, единственный момент, который они могут изменить, - это запрос AJAX.

Поэтому вы должны запускать некоторые проверки каждый раз, когда AJAX-запрос выполняется успешно. jQuery имеет глобальные привязки для успешных вызовов AJAX, поэтому это должно быть возможно даже без него.

Теперь, когда мы знаем это - проверка может начаться с просмотра типа вызова по некоторым переменным, доступным в объекте ответа, или сам объект XMLHTTPRequest. Это может еще больше сократить количество вызовов вашего средства обновления.

...