По сути, я хочу, чтобы скрипт выполнялся при изменении содержимого DIV. Поскольку сценарии являются отдельными (контентный скрипт в расширении Chrome и скрипте веб-страницы), мне нужен способ просто наблюдать изменения в состоянии DOM. Я мог бы настроить опрос, но это кажется неаккуратным.
В течение долгого времени события мутации DOM3 были наилучшим доступным решением, но они были признаны устаревшими по соображениям производительности. Наблюдатели мутации DOM4 являются заменой устаревших событий мутации DOM3. В настоящее время они реализованы в современных браузерах как MutationObserver(или как префикс поставщика WebKitMutationObserverв старых версиях Chrome):
MutationObserver= window.MutationObserver|| window.WebKitMutationObserver;var observer =newMutationObserver(function(mutations, observer){// fired when a mutation occurs
console.log(mutations, observer);// ...});// define what element should be observed by the observer// and what types of mutations trigger the callback
observer.observe(document,{
subtree:true,
attributes:true//...});
В этом примере прослушиваются изменения DOM documentи всего его поддерева, и он запускает изменения атрибутов элемента, а также структурные изменения. Черновик спецификации имеет полный список допустимых свойств слушателя мутаций :
childList
Установите, trueесли должны наблюдаться мутации для детей-мишеней.
атрибуты
Установите, trueесли должны наблюдаться мутации атрибутов цели.
CharacterData
Установите, trueесли должны наблюдаться мутации данных цели.
поддерево
Установите, чтобы trueмутации были направлены не только на цель, но и на потомков цели.
attributeOldValue
Установите в значение trueif attributes, равное true, и в качестве значения атрибута цели перед записью мутации.
characterDataOldValue
Установите в значение trueif, если characterDataустановлено значение true, и данные цели перед записью мутации.
attributeFilter
Установите список локальных имен атрибутов (без пространства имен), если не все мутации атрибутов необходимо соблюдать.
(Этот список действителен по состоянию на апрель 2014 года; вы можете проверить спецификации на наличие изменений.)
@AshrafBashir Я вижу, что пример отлично работает в Firefox 19.0.2: я вижу ([{}])журнал в консоли, который показывает ожидаемое, MutationRecordкогда я нажимаю на него. Пожалуйста, проверьте еще раз, поскольку это может быть временная техническая ошибка в JSFiddle. Я еще не тестировал его в IE, поскольку у меня нет IE 10, который в настоящее время является единственной версией, поддерживающей события мутации.
Апсиллеры
1
Я только что опубликовал ответ, который работает в IE10 + и в основном во всем остальном.
naugtur
1
В спецификации, похоже, больше нет зеленого поля, в котором перечислены параметры наблюдателя мутации. Он перечисляет опции в разделе 5.3.1 и описывает их чуть ниже.
LS
2
@LS Спасибо, я обновил ссылку, удалил немного о зеленом поле и отредактировал весь список в своем ответе (на случай гниения будущей ссылки).
Этот ответ сейчас устарел. Смотрите ответ от апсиллеров .
Поскольку это расширение Chrome, вы можете также использовать стандартное событие DOM - DOMSubtreeModified. Смотрите поддержку этого события в разных браузерах. Поддерживается в Chrome с 1.0.
По-прежнему работает, если вы создаете расширения Chrome. бесценным.
concept47
49
Многие сайты используют AJAX для динамического добавления / показа / изменения контента. Иногда он используется вместо навигации внутри сайта, поэтому текущий URL-адрес изменяется программно, и в этом случае браузер не выполняет автоматически скрипты содержимого, так как страница полностью не выбирается с удаленного сервера.
Обычные JS-методы обнаружения изменений страницы доступны в скрипте содержимого .
MutationObserver ( документы ) для буквального обнаружения изменений DOM:
Периодическая проверка DOM через setInterval :
Очевидно, это будет работать только в тех случаях, когда вы ожидаете появления определенного элемента, идентифицируемого его идентификатором / селектором, и не позволит вам универсально обнаруживать новое динамически добавляемое содержимое, если вы не придумали какой-либо отпечаток пальца. существующее содержание.
document.head.appendChild(document.createElement('script')).text ='('+function(){// injected DOM script is not a content script anymore, // it can modify objects and functions of the pagevar _pushState = history.pushState;
history.pushState =function(state, title, url){
_pushState.call(this, state, title, url);
window.dispatchEvent(newCustomEvent('state-changed',{detail: state}));};// repeat the above for replaceState too}+')(); this.remove();';// remove the DOM script element// And here content script listens to our DOM script custom events
window.addEventListener('state-changed',function(e){
console.log('History state changed', e.detail, location.hash);
doSomething();});
Другой подход в зависимости от того, как вы меняете div. Если вы используете JQuery для изменения содержимого div с помощью его метода html (), вы можете расширить этот метод и вызывать функцию регистрации каждый раз, когда помещаете html в div.
(function( $, oldHtmlMethod ){// Override the core html method in the jQuery object.
$.fn.html =function(){// Execute the original HTML method using the// augmented arguments collection.var results = oldHtmlMethod.apply(this, arguments );
com.invisibility.elements.findAndRegisterElements(this);return results;};})( jQuery, jQuery.fn.html );
Мы просто перехватываем вызовы html (), вызываем функцию регистрации с этим, которая в контексте относится к целевому элементу, получающему новое содержимое, затем мы передаем вызов исходной функции jquery.html (). Не забудьте вернуть результаты оригинального метода html (), потому что JQuery ожидает его для цепочки методов.
В дополнение к «необработанным» инструментам, предоставляемым MutationObserverAPI , существуют «удобные» библиотеки для работы с мутациями DOM.
Обратите внимание: MutationObserver представляет каждое изменение DOM с точки зрения поддеревьев. Так что, если вы, например, ожидаете вставки определенного элемента, он может быть глубоко внутри дочерних элементов mutations.mutation[i].addedNodes[j].
Другая проблема - когда ваш собственный код, реагируя на мутации, меняет DOM - вы часто хотите отфильтровать его.
Хорошей удобной библиотекой, которая решает такие проблемы, является mutation-summary(отказ от ответственности: я не автор, я просто довольный пользователь), которая позволяет вам задавать вопросы, которые вас интересуют, и получать именно это.
([{}])
журнал в консоли, который показывает ожидаемое,MutationRecord
когда я нажимаю на него. Пожалуйста, проверьте еще раз, поскольку это может быть временная техническая ошибка в JSFiddle. Я еще не тестировал его в IE, поскольку у меня нет IE 10, который в настоящее время является единственной версией, поддерживающей события мутации.редактировать
Этот ответ сейчас устарел. Смотрите ответ от апсиллеров .
Поскольку это расширение Chrome, вы можете также использовать стандартное событие DOM -
DOMSubtreeModified
. Смотрите поддержку этого события в разных браузерах. Поддерживается в Chrome с 1.0.Смотрите рабочий пример здесь .
источник
Многие сайты используют AJAX для динамического добавления / показа / изменения контента. Иногда он используется вместо навигации внутри сайта, поэтому текущий URL-адрес изменяется программно, и в этом случае браузер не выполняет автоматически скрипты содержимого, так как страница полностью не выбирается с удаленного сервера.
Обычные JS-методы обнаружения изменений страницы доступны в скрипте содержимого .
MutationObserver ( документы ) для буквального обнаружения изменений DOM:
Прослушиватель событий для сайтов, которые сигнализируют об изменении содержимого, отправляя событие DOM:
pjax:end
обdocument
использовании многих сайтов на основе pjax, например, GitHub,см. Как запустить jQuery до и после загрузки pjax?
message
наwindow
используемый , например , поиск Google в браузере Chrome,см расширение Chrome обнаружить обновление поиска Google
spfdone
о том, какdocument
использовать Youtube,см. Как обнаружить навигацию по страницам на Youtube и изменить HTML перед отображением страницы?
Периодическая проверка DOM через setInterval :
Очевидно, это будет работать только в тех случаях, когда вы ожидаете появления определенного элемента, идентифицируемого его идентификатором / селектором, и не позволит вам универсально обнаруживать новое динамически добавляемое содержимое, если вы не придумали какой-либо отпечаток пальца. существующее содержание.
API Cloaking History внутри внедренного сценария DOM :
Прослушивание hashchange , событий popstate :
Специфично для расширений: обнаружение изменений URL на странице фона / события .
Существует расширенный API для работы с навигацией: webNavigation , webRequest , но мы будем использовать простой приемник событий chrome.tabs.onUpdated , который отправляет сообщение в скрипт содержимого:
manifest.json:
объявить фон / страницу события
объявить разрешение на добавление сценария содержимого .
"tabs"
background.js
content.js
источник
Другой подход в зависимости от того, как вы меняете div. Если вы используете JQuery для изменения содержимого div с помощью его метода html (), вы можете расширить этот метод и вызывать функцию регистрации каждый раз, когда помещаете html в div.
Мы просто перехватываем вызовы html (), вызываем функцию регистрации с этим, которая в контексте относится к целевому элементу, получающему новое содержимое, затем мы передаем вызов исходной функции jquery.html (). Не забудьте вернуть результаты оригинального метода html (), потому что JQuery ожидает его для цепочки методов.
Для получения дополнительной информации о переопределении и расширении метода, проверьте http://www.bennadel.com/blog/2009-Using-Self-Executing-Function-Arguments-To-Override-Core-jQuery-Methods.htm , где Я заколдовал функцию закрытия. Также ознакомьтесь с руководством по плагинам на сайте JQuery.
источник
В дополнение к «необработанным» инструментам, предоставляемым
MutationObserver
API , существуют «удобные» библиотеки для работы с мутациями DOM.Обратите внимание: MutationObserver представляет каждое изменение DOM с точки зрения поддеревьев. Так что, если вы, например, ожидаете вставки определенного элемента, он может быть глубоко внутри дочерних элементов
mutations.mutation[i].addedNodes[j]
.Другая проблема - когда ваш собственный код, реагируя на мутации, меняет DOM - вы часто хотите отфильтровать его.
Хорошей удобной библиотекой, которая решает такие проблемы, является
mutation-summary
(отказ от ответственности: я не автор, я просто довольный пользователь), которая позволяет вам задавать вопросы, которые вас интересуют, и получать именно это.Базовый пример использования из документов:
источник