Сегодня поговорим про божественный API Mutation Observer.
Предисловие
Мне достаточно часто нужно добавить свои куски кода в чужой код, к которому я не имею ни малейшего доступа. Или это готовый плагин/тема в WordPress с компилированным JS кодом в один файл, где нормально прочитать код просто не получается. От этого требование — дописывать отдельно на чистом JS. И часто нужно выполнить свою функцию, как только что-то определенное изменится на странице.
Например, кто-то уже сделал функционал который срабатывает при клике\скролле\ховере\etc. Логика там достаточно сложная, написана в чужом коде, который вы не можете редактировать. И вам нужно по этой же логике просто добавить свой мини-функционал. Чтобы не повторять чужую логику, вы можете следить за изменением DOM-объекта, и привязаться уже к этим изменениям! Самый простой пример: следить за изменением CSS (HTML) класса DOM-объекта.
Функция
Если класс у объекта .search-trigger
изменился — добавить к <body>
класс .noscroll
. Если класс у объекта .search-trigger
изменился назад на .search-trigger
— удаляем класс .noscroll
у <body>
.
var mutationObserver = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation);
console.log(mutation.oldValue);
if (mutation.oldValue === 'search-trigger') {
document.getElementsByTagName('body')[0].classList.add('noscroll');
} else {
document.getElementsByTagName('body')[0].classList.remove('noscroll');
}
});
});
// Starts listening for changes in the '.search-trigger' HTML element
mutationObserver.observe(document.querySelector('.search-trigger'), {
attributes: true,
characterData: true,
childList: true,
subtree: true,
attributeOldValue: true,
characterDataOldValue: true
});
Тут я почему-то слежу за старым значением (mutation.oldValue), но можно следить напрямую за классом:
mutation.target.classList.contains('active');
Очень простая APIшка, очень полезная, всем рекомендую.