Стилизация элементов форм и попытка обойти подводные камни

Приветствую читатели, стилизованные элементы формы на сайтах сейчас прочно вошли в реалии современного дизайна и кто бы что не говорил, во многих случаях смотрятся они действительно приятно.
Многие из вас уже обзавелись плагинчиками типа chosen и прочим добром, некоторые из них весьма качественно написаны. В этой статье я не буду рассказывать про очередной плагин, а лишь хочу обратить ваше внимание на один из способов расширения возможностей плагина, возможно кому-то он поможет.
Я являюсь сторонником того, чтобы подключая плагины для стилизации форм, мы должны продолжать работать с элементами форм в нативном стиле и никак не зависеть от плагина стилизации. Я практически ни у одного (можно сказать ни у одного) плагина не видел корректную обработку изменения поведения элементов при изменении атрибутов DOM элементов, а именно — обработку изменения атрибута disabled (min, max, maxlength), всегда надо было учитывать апи плагины, верстку элемента и тд, а это неудобно если вы в будущем захотите поменять плагин или верстку. Как вариант — подумать заранее и для всего сделать обертки и работать с ними как с внутренним апи. Но есть и альтернативный путь.

Изучив проблему с атрибутами невольно приходит на ум — «а не начать ли нам отлавливать изменения атрибутов элемента?» Обратив внимание на MutationObserver и проконсультировавшись с caniuse, понимаю, что пора: crome, firefox давно поддерживают, новый IE11 тоже, android потихоньку переползает, а ios полностью поддерживает уже. В итоге получился следующий код (jsFiddle)

var MO = (window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver);
var observer = new MO(function(){ console.log("disabled changed") });
observer.observe(document.querySelector("id"), { attributes: true, attributeFilter: ["disabled"] });

Уже хорошо осталось только побороть IE, а тут все плохо… Первая идя — ну есть же DOMAttrModified, а также для совсем старых propertychange.
Конечно есть, даже работают, но не в нашем случае: события на задизейбленном элементе не кидаются. Отсюда получаем интересную картину: при добавлении атрибута disabled события молчат как партизаны, при удалении спокойно прокидываются. Я бы назвал это багой нежели стандартным поведением, так как ивент ивенту рознь и обрубать все на корню плохо, но что поделать. Однако это не мешает нам написать мини workaround для данной проблемы (jsFiddle)

var AttributeObserver = function(element, callback, attribute){
    var MO = (window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver);
    if (MO) {
        var observer = new MO(callback);
        observer.observe(element, { attributes: true, attributeFilter: [attribute] });
    } else {
        if (!AttributeObserver.__timer) {
            AttributeObserver.__observed = []
            AttributeObserver.__timer = setInterval(function(){
                for (var i = 0; i < AttributeObserver.__observed.length; i++) {
                    var o = AttributeObserver.__observed[i];
                    if (o.element.hasAttribute(o.attribute) !== o.flag) {
                        callback()
                    }
                    o.flag = o.element.hasAttribute(o.attribute)
                }
            }, 500)
            AttributeObserver.__observed.push({
                element: element,
                attribute: attribute,
                flag: element.hasAttribute(attribute)
            })
        }

    }
}

Предвидя возмущения некоторых лиц по поводу setInterval поясню: нет, это не хак, setInterval — вполне себе рабочая конструкция языка, которая при разумном подходе не привносит хаоса и тормозов, если посмотреть на реальную ситуацию то разумным интервалом был бы 500-1000мс, а если допускать что на странице обычно 10-20 контролов, а даже если и 100 проверить их атрибут — не есть проблема.
Также данный способ применим для случаев если вам надо отреагировать на изменение maxlength, min, max и прочих атрибутов которые могу влиять на поведение кастомных контролов. Те же min, max атрибуты для range input, если вы работаете с нативным range input и делаете fallback для браузеров без поддержки, будут хорошо смотреться при подобном подходе к наблюдению за атрибутами и это может решить многие проблемы — вы работаете с input в нативном виде, а плагин подхватывает изменения. Вот этот вариант я бы и хотел сейчас рассмотреть ибо тут у нас выпадает важная проблема — мы работаем не с disabled элементами, а значит может проапгрейдить наше решение (jsFiddle)

var AttributeObserver = function(element, callback, attribute){
    var MO = (window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver);
    if (MO) {
        var observer = new MO(callback);
        observer.observe(element, { attributes: true, attributeFilter: [attribute] });
    } else if (element.addEventListener) {
        element.addEventListener('DOMAttrModified', function(e){
            if (e.attrName == attribute) {
                callback()
            }
        }, false);
    } else if ("onpropertychange" in document) {
        element.attachEvent ('onpropertychange', function(e){
            if (e.attrName == attribute) {
                callback()
            }
        });

    }
}

P.S. Хочется добавить, что код не претендует на звание готового плагина, а скорее просто демонстрирует один из возможных подходов.