Twitter Bootstrap. Почему модальные события работают в JQuery, но НЕ в чистом JS?

Модальный диалог Twitter Bootstrap имеет набор событий, которые можно использовать с обратными вызовами.

Вот пример в jQuery:

    $(modalID).on('hidden.bs.modal', function (e) {

        console.log("hidden.bs.modal");
    });

Однако, когда я переписываю этот метод JS, событие "hidden.bs.modal" не работает. Использование "click" работает:

    document.querySelector(modalID).addEventListener('hidden.bs.modal', function(e) {

        console.log("hidden.bs.modal");
    }, false);

Являются ли эти события Bootstrap доступными только для jQuery? Зачем?

Благодаря,
Doug

Ответ 1

Это объясняется тем, что Twitter Bootstrap использует that.$element.trigger('hidden.bs.modal') (строка 997), чтобы вызвать события. Другими словами, он использует .trigger.

Теперь jQuery отслеживает каждый обработчик событий элемента (все .on или .bind или .click т.д.), Используя ._data. Это связано с тем, что нет другого способа получить обработчики событий, которые связаны (используя .addEventListener) с элементом. Таким образом, метод триггера фактически получает только набор исполнителей/обработчиков событий из ._data(element, 'events') & ._data(element, 'handle') в качестве массива и запускает каждый из них.

handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
if ( handle ) {
    handle.apply( cur, data );
}

(строка 4548)

Это означает, что независимо от контекста, если событие связано с .addEventListener оно не будет работать с использованием .trigger. Вот пример. При загрузке будет загружен только jquery (запускается .trigger). При нажатии a элемент, хотя, как будет работать.

$('a')[0].addEventListener('click', function(){console.log('addlistener');}, false);

$('a').on('click', function(){
    console.log('jquery');
});

$('a').trigger('click');

DEMO

Кроме того, вы можете инициировать событие на элементе в javascript, используя fireEvent (ie) & dispatchEvent (non-ie). Я не обязательно понимаю или знаю аргументы jQuery. .trigger не делая этого, но они могут иметь или не иметь его. После небольшого исследования я обнаружил, что они этого не делают, потому что некоторые старые браузеры поддерживали только 1 обработчик событий на событие.

В общем, мы не пытались внедрить функциональность, которая работает только на некоторых браузерах (и на некоторых событиях), но не на всех, так как кто-то сразу же сообщит об ошибке, что она не работает правильно.

Хотя я не рекомендую это, вы можете обойти это с минимальным количеством изменений в код начальной загрузки. Вам просто нужно убедиться, что функция, приведенная ниже, прикреплена первой (или у вас будут два раза подряд слушатели).

$(modalID).on('hidden.bs.modal', function (e, triggered) {
    var event; // The custom event that will be created

    if(!triggered){
        return false;
    }

    e.preventDefault();
    e.stopImmediatePropagation();

    if (document.createEvent) {
        event = document.createEvent("HTMLEvents");
        event.initEvent("hidden.bs.modal", true, true);
    } else {
        event = document.createEventObject();
        event.eventType = "hidden.bs.modal";
    }

    event.eventName = "hidden.bs.modal";

    if (document.createEvent) {
        this.dispatchEvent(event);
    } else {
        this.fireEvent("on" + event.eventType, event);
    }
});

Наконец, измените строку Twitter Bootstrap сверху:

that.$element.trigger('hidden.bs.modal', true)

Это значит, что вы знаете, что это срабатывает, а не событие, которое вы стреляете в себя после. Пожалуйста, имейте в виду, что я не пробовал этот код с модальным. Хотя он отлично работает на click демо ниже, может или не может работать, как ожидалось с модальным.

DEMO