Подтвердить что ты не робот

Наблюдая за изменениями DOM, элегантный способ

Мне нужно следить за изменением атрибута для любого из дочерних элементов определенного элемента DOM. До сих пор я использовал события мутации.

Проблема заключалась в том, что они были ошибочными: например, под хромом DOMAttrModified не был уволен, но DOMSubtreeModified был. Проблема была легко решена: потому что согласно спецификации DOMSubtreeModified запускается, если какое-либо из других событий запущено, поэтому я просто прослушал DOMSubtreeModified.

В любом случае, Chromium в последних версиях прекратил стрельбу, если атрибут был изменен.

Новый API-интерфейс Mutation Observer работает безупречно.

До сих пор мне нужно только запустить обратный вызов при ЛЮБОЙ смене поддерева определенного элемента - просто потому, что ничего другого не должно меняться - поэтому я решил свою проблему, просто используя события мутации и наблюдатель мутаций (когда это доступно) в том же фрагменте кода.

Однако теперь мне нужно сделать более мощную фильтрацию событий (например, в новом node, на удаленной node)), так что есть библиотека, возможно, плагин jQuery, что позволило бы мне элегантно использовать оба этих API-интерфейсов - MutationObserver, если они доступны, и события мутации в качестве резервной копии, с возможностью фильтрации для определенных типов событий (например, добавленный элемент, измененный атрибут).

например.

$("#test").watch({onNewElement: 1}, function(newElement){})
$("#test").watch({onNewAttribute: 1}, function(modifiedElement) {})

Или без jQuery

watchChanges("#test", {onNewElement: 1}, function(newElement){})
watchChanges("#test", {onNewAttribute: 1}, function(modifiedElement){})
4b9b3361

Ответ 1

Будет ли это работать?

http://darcyclarke.me/development/detect-attribute-changes-with-jquery/

$.fn.watch = function(props, callback, timeout){
    if(!timeout)
        timeout = 10;
    return this.each(function(){
        var el      = $(this),
            func    = function(){ __check.call(this, el) },
            data    = { props:  props.split(","),
                        func:   callback,
                        vals:   [] };
        $.each(data.props, function(i) { data.vals[i] = el.css(data.props[i]); });
        el.data(data);
        if (typeof (this.onpropertychange) == "object"){
            el.bind("propertychange", callback);
        } else if ($.browser.mozilla){
            el.bind("DOMAttrModified", callback);
        } else {
            setInterval(func, timeout);
        }
    });
    function __check(el) {
        var data    = el.data(),
            changed = false,
            temp    = "";
        for(var i=0;i < data.props.length; i++) {
            temp = el.css(data.props[i]);
            if(data.vals[i] != temp){
                data.vals[i] = temp;
                changed = true;
                break;
            }
        }
        if(changed && data.func) {
            data.func.call(el, data);
        }
    }
}

Ответ 2

Для эффективного мониторинга DOM с помощью jQuery вы можете взглянуть на jQuery Behavior Plugin (Отказ от ответственности: я автор), который использует оптимизированная версия Live Query. Я использую его в нескольких продуктах уже 3 года без каких-либо проблем.

Изменить: прослушивание изменений атрибутов будет работать следующим образом:

$.behavior({
    'div:first': {
        'changeAttr': function (event, data) {
            console.log('Attribute "' +  data.attribute + '" changed from "' + data.from + '" to "' + data.to + '"');
        }
    }
});

$('div:first').attr('foo', 'bar');