Перебор и изменение элементов DOM, добавленных через Ajax, без jQuery

Я работаю над небольшим дополнением Firefox, которое использует PageMod для обработки элементов изображения, загруженных на веб-страницу. Я видел в Интернете примеры использования jQuery, но, поскольку я добавляю скрипт содержимого на каждую веб-страницу, добавление jQuery может нанести непоправимый ущерб.

Поскольку Firefox поддерживает MutationObserver, я попытался сделать следующее благодаря AndrewVermie:

content.js

var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {

    if(mutation.tagName == "IMG")
    {
        //I'm not sure this object can be treated as a DOM Element (?)
        mutation.src = "http://s6.tinypic.com/15npphk_th.jpg";
    }

    for (var i = 0; i < mutation.addedNodes.length; ++i) {
          var node = mutation.addedNodes[i],
              matches = [].slice.call(node.querySelectorAll('img'));

          for (var j = 0; j < matches.length; ++j) {
              var img = matches[j];
              img.src = "http://s6.tinypic.com/15npphk_th.jpg";
          }
      }
   });
});

var config = { attributes: true, childList: true, subtree: true, characterData: true};
observer.observe(window.document, config);


var elements = document.getElementsByTagName("img");
var elementsLength = elements.length;
for (var i = 0; i < elementsLength; i++) 
{
    elements[i].src = "http://s6.tinypic.com/15npphk_th.jpg";
}

main.js

pageMod.PageMod({
    include: "*",
    contentScriptWhen: 'ready',
    contentScriptFile: [self.data.url("content.js")],
    onAttach: //...
    }
});

Что происходит :

  1. Перейдите на страницу http://imgur.com/.
  2. Начните прокручивать, пока изображения не будут загружаться динамически
  3. Обратите внимание, что они не меняются

Я console.log() каждые .tagName и вижу только p и #text при наведении курсора на изображения.

Что мне нужно

Итерация по каждому элементу, динамически загружаемому на веб-странице, на которую внедрен скрипт, и возможность изменять атрибуты элемента.

Если это можно сделать с помощью чистого JavaScript и с MutationObserver или без него, это будет действительно здорово.

В противном случае, если я смогу узнать, что некоторые элементы были загружены для повторного повторения ВСЕХ элементов страницы, это будет нормально, но не набухнет.

Надеюсь, я немного прояснил ситуацию.

Любая помощь будет принята с благодарностью.


person Sebastian-Laurenţiu Plesciuc    schedule 20.05.2014    source источник
comment
Этот вопрос кажется не по теме, поскольку в нем недостаточно информации для диагностики проблемы. Опишите свою проблему более подробно или включите минимальный пример в сам вопрос. На данный момент ваши требования слишком неконкретны, и я даже не могу не понять, чего точно вы пытаетесь достичь.   -  person nmaier    schedule 20.05.2014
comment
Эта скрипка может делать то, что вы хотите; у тебя с скрипки работает, а с аддона нет?   -  person Andrew Vermie    schedule 20.05.2014
comment
@AndrewVermie Я сейчас же это проверю.   -  person Sebastian-Laurenţiu Plesciuc    schedule 20.05.2014
comment
@AndrewVermie Это не работает из аддона. Я предоставлю код из вашего примера в качестве тестового примера для запроса nmaier.   -  person Sebastian-Laurenţiu Plesciuc    schedule 20.05.2014
comment
@nmaier Надеюсь, я немного прояснил ситуацию. Английский не мой родной язык.   -  person Sebastian-Laurenţiu Plesciuc    schedule 20.05.2014


Ответы (1)


Ваша ошибка здесь состоит в том, что вы думаете, что все узлы на самом деле имеют метод querySelectorAll. Например. текстовые узлы нет! Итак, вы вызвали несуществующий метод, который выдал исключение и преждевременно завершил вашу обработку (поскольку первый узел мутации на imgur.com на самом деле является текстовым узлом).

Вот что я придумал, что, кажется, делает то, что вам нужно, немного ecma-6-ified: p. Мой контент-скрипт:

var observer = new MutationObserver(function(mutations) {
  for (var m of mutations) {
    for (var node of m.addedNodes) {
      if (!node || !node.querySelectorAll) {
        // Not all nodes support querySelectorAll, e.g. text nodes.
        continue;
      }
      for (var img of node.querySelectorAll("img")) {
        img.src = "http://s6.tinypic.com/15npphk_th.jpg";
      }
    }
  }
});

var config = { attributes: true, childList: true, subtree: true, characterData: true};
observer.observe(window.document, config);

var elements = document.getElementsByTagName("img");
var elementsLength = elements.length;
for (var i = 0; i < elementsLength; i++) {
    elements[i].src = "http://s6.tinypic.com/15npphk_th.jpg";
}
person nmaier    schedule 20.05.2014
comment
Это сработало очень хорошо. Большое спасибо. Два раза в один день :) - person Sebastian-Laurenţiu Plesciuc; 20.05.2014
comment
Просто примечание: поскольку вы уже используете функции ECMA 6, я бы использовал let вместо var для циклов или написал бы var в одном месте, чтобы с первого взгляда было ясно, какие переменные привязаны к область действия ( подъем var) - person t.niese; 20.05.2014
comment
@t.niese Спасибо. У меня есть опыт системного программирования на C/C++, и я не очень хорошо разбираюсь в этих вопросах. nmaier и вы предоставили мне несколько очень важных разъяснений. Может ли кто-нибудь из вас предложить рекомендуемое чтение (кроме документов MDN), чтобы я мог избежать подобных ошибок в будущем? - person Sebastian-Laurenţiu Plesciuc; 20.05.2014
comment
Когда я ищу этот тип информации, я обычно сталкиваюсь с jQuery или с тем, как заставить текст веб-страницы мигать, что менее чем полезно. - person Sebastian-Laurenţiu Plesciuc; 20.05.2014
comment
@Sebastian-LaurenţiuPlesciuc: в настоящее время у меня нет. Дуглас Крокфорд, как правило, дает хорошие объяснения и, вероятно, смотрит это видео: YouTube: Дуглас Крокфорд - JavaScript, Всемирная Самый непонятый язык — хорошая отправная точка, чтобы получить общее представление о проблемах. Но в целом такие вещи, как: scope, closures, var hoisting, Promise, requirejs/adm и async поведение многих библиотек, вам следует знать. - person t.niese; 20.05.2014
comment
@t.niese Большое спасибо. - person Sebastian-Laurenţiu Plesciuc; 20.05.2014