Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Нужна проверка поддержки события "DOMMouseScroll" (https://javascript.ru/forum/events/6056-nuzhna-proverka-podderzhki-sobytiya-dommousescroll.html)

Denisko-Redisko 09.11.2009 00:33

Нужна проверка поддержки события "DOMMouseScroll"
 
Никак не могу найти способ выяснить поддерживает ли браузер событие "DOMMouseScroll". Проверять ЮА на предметт соответствия FF кажется плохой идеей.

can3p 09.11.2009 21:50

Можно попробовать использовать сторонний плагин - http://github.com/brandonaaron/jquer...el/tree/master

B~Vladi 09.11.2009 21:51

Цитата:

Сообщение от Denisko-Redisko
Никак не могу найти способ выяснить поддерживает ли браузер событие "DOMMouseScroll"

Что мешает повесить и DOMMouseScroll и onmousewheel?!

Denisko-Redisko 10.11.2009 09:16

can3p, постановка задачи (кроссбраузерные функции установки обрабочиков) исключает использование jquery.

B~Vladi,
Цитата:

Что мешает повесить и DOMMouseScroll и onmousewheel?!
Как раз не хочется извращаться. Нужно минимальным вмешательством в существующий код добавить поддержку onmousewheel.
Временно я опеделяю FF через Event.LOAD, но это очень криво, надо поменять на что-то. Или решить проблему иным способом.
/*
    Установка обработчиков событий.

    windows.addEH(node, type, handler) -- повесить обработчик
    windows.delEH(node, type, handler) -- снять обработчик

    В MSIE обработчик получает аргумент event дополненный следующими методами и свойствами:

        event.preventDefault
        event.stopPropagation

        event.pageX
        event.pageY
        event.relatedTarget
        event.which

    Во всех браузерах:

        метод stop объекта Event выполняет методы preventDefault и stopPropagation
        свойство isWheelDown возвращает направление колеса мыши (true -- колесо на себя, false -- от себя)

*/

(function(){

    //
    // Установка обработчиков для MSIE основана на коде Dean Edwards.
    //

    var win = window,
        doc = document,
        huid = 0,                   // счетчик, используемый для создания уникальных ID
        uniPropName = "$RNV601MCTCU",
        W3C = !! win.addEventListener, // document.implementation.hasFeature("Events", "2.0")
// -------------------------------------------------------------------------------------
// ВОТ ЗДЕСЬ
// надо заменить Event.LOAD на внятную проверку поддержки события "DOMMouseScroll"
        mousewheel = { mousewheel : win.Event && Event.LOAD ? "DOMMouseScroll" : null },

    handle = function () {
        var returnValue = true,
            event = getFixedIEEvent(window.event || (this.ownerDocument || this).parentWindow.event),
            handlers = this[uniPropName][event.type];

        for (var i in handlers)
           if (handlers[i].call(this, event) === false)
               returnValue = false;

        return returnValue;
    },

    getFixedIEEvent = function (event) {

        // Добавление стандартных методов событий W3C

        var d = doc.documentElement,
            b = doc.body,
            button = event.button,
            target = event.target = event.srcElement || doc;

        // pageX и pageY корректные для quirks и строгих режимов
        event.pageX = event.clientX + (d.scrollLeft || b.scrollLeft || 0) - (d.clientLeft || 0);
        event.pageY = event.clientY + (d.scrollTop  || b.scrollTop  || 0) - (d.clientTop  || 0);

        event.relatedTarget = event.fromElement == target ? event.toElement : event.fromElement;

        // which -- Returns the numeric keyCode of the key pressed, or the character code (charCode) for an alphanumeric key pressed
        // -------------------------------------------------------------------------
        //                          | MSIE      | Konqueror | Opera, FF, Safari Win
        // -------------------------------------------------------------------------
        //  левая   | event.which   | undefined |    1      |    1
        //  кнопка  | event.button  | 1         |    1      |    0
        //  средняя | event.which   | undefined |    2      |    2
        //  кнопка  | event.button  | 4         |    4      |    1
        //  правая  | event.which   | undefined |    3      |    3
        //  кнопка  | event.button  | 2         |    2      |    2
        //
        // Поскольку в W3C-совместимых движках мы обходимся без оберток, (и соответственно фиксим событие только в ие),
        // то для определения нажатой кнопки мыши приходится использовать устаревший which (почему -- см. таблицу)
        //
        event.which = event.charCode || event.keyCode || (button < 2 ? 1 : button == 4 ? 2 : 3);
        event.preventDefault = preventDefault;
        event.stopPropagation = stopPropagation;
        //event.detail = event.wheelDelta / -40;
        event.stop = stop;
        event.isWheelDown = event.wheelDelta < 0;

        return event;
    },

    preventDefault = function() {
        this.returnValue = false;
    },

    stopPropagation = function() {
        this.cancelBubble = true;
    },

    stop = function () {
        this.preventDefault();
        this.stopPropagation();
    };

    if(win.Event) {
        Event.prototype.stop = stop;
        // В FF MouseScrollEvent не наследует у Event, поэтому добавляем "isWheelDown" соответствующему объекту
        (win.MouseScrollEvent || Event).prototype.__defineGetter__("isWheelDown", function (){
            // Особенности события mousewheel в браузерах: [url]http://generalized.ru/?p=133[/url]
            return this.detail > 0 || this.wheelDelta < 0
        })
    };

    win.addEH = W3C ?

        function(node, type, handler) {
            node.addEventListener(mousewheel[type] || type, handler, false);
        } :

        function(node, type, handler) {
            type = mousewheel[type] || type;
            var ontype = "on" + type,
                events = node[uniPropName] || (node[uniPropName] = {}),
                handlers = events[type];

            handlers || (
                handlers = events[type] = {},
                node[ontype] &&
                    (handlers[0] = node[ontype])
            );

            handler[uniPropName] || (
                handler[uniPropName] = huid++
            );

            handlers[huid] = handler;
            node[ontype] = handle;
        };

    win.delEH = W3C ?

        function(node, type, handler) {
            node.removeEventListener(mousewheel[type] || type, handler, false);
        } :

        function(node, type, handler) {
            type = mousewheel[type] || type;
            if (node[uniPropName] && node[uniPropName][type])
               delete node[uniPropName][type][handler[uniPropName]];
        };
})()

can3p 10.11.2009 21:23

Denisko-Redisko,
прошу прощения, больше не буду. Но кроссбраузерный jquery плагин может быть источником кроссбраузерных самопальных функций.

Denisko-Redisko 10.11.2009 22:16

Они там вешают сразу оба обработчика, как и все везде.

Kolyaj 11.11.2009 09:37

Цитата:

Сообщение от Denisko-Redisko
Как раз не хочется извращаться.

А где в навешивании функции на два события извращение?

B~Vladi 11.11.2009 10:17

Цитата:

Сообщение от Kolyaj
А где в навешивании функции на два события извращение?

Да, кажется некрасиво - один обработчик связывать с двумя событиями... Но найти другое решение я не смог...

Kolyaj 11.11.2009 10:23

B~Vladi,
что в этом плохого?

B~Vladi 11.11.2009 11:00

Цитата:

Сообщение от Kolyaj
что в этом плохого?

Нет плохого, я же сказал - некрасиво. Сам так делаю ибо другого пути нет, поэтому и предложил поступить именно так.

Kolyaj 11.11.2009 11:03

А некрасивого чего? Если одни и те же действия должны выполнятся при возникновении нескольких событий. Делать несколько одинаковых функций?

B~Vladi 11.11.2009 13:49

Некрасиво то, что мы пытаемся прикрутить обработчик на событие, которого не существует.

Denisko-Redisko 14.11.2009 15:29

И кроме того будет очень весело если FF начнет поддерживать onmousewheel.

B~Vladi 14.11.2009 21:38

Можно поступить так... Создаём элемент, вешаем на него обработчик для onmousewheel, программно генерим событие и регистрируем это. После генерации проверяем - произошло или нет, а потом уже делаем соответствующие выводы;)

Denisko-Redisko 27.11.2009 16:06

Да, пожалуй это самый правильный способ :) Спасибо.

Denisko-Redisko 02.01.2012 04:52

Вроде нашел короткое решение. В Gecko DOMMouseScroll является частью интерфейса nsIDOMMouseScrollEvent. Наличие этого интерфейса проверяется так:
Components.interfaces.nsIDOMMouseScrollEvent

Теперь тот участок скрипта выглядит так:
...
    //
    // Gecko использует событие "DOMMouseScroll" вместо "mousewheel"
    // Наличие этого интерфейса в Gecko можно проверить так: Components.interfaces.nsIDOMMouseScrollEvent
    //

    ff, mousewheel = {
        mousewheel : (ff = window.Components) && 
            (ff = ff.interfaces) && 
            (ff = ff.nsIDOMMouseScrollEvent ) ? "DOMMouseScroll" : null
    },

devote 02.01.2012 16:32

Цитата:

Сообщение от B~Vladi
Тебе спасибо! Раньше я вешал обработчик на оба события, но твой топ заставил меня найти нормальное решение! Буду сам его юзать

Это не нормальное решение, так как можно вызвать таким макаром и самопальное событие.

B~Vladi 02.01.2012 16:46

Цитата:

Сообщение от devote
так как можно вызвать таким макаром и самопальное событие.

Код в студию!

devote 02.01.2012 16:54

B~Vladi,
оно у тебя якобы работает лишь по простой причине, то что ты допустил ошибку в коде. Строка 12 вместо onmousewheel нужно писать mousewheel
а так ты не пытаешься вызвать событие на которое повесил обработчик в браузерах поддерживающих addEvenetListener

devote 02.01.2012 16:55

попробуй написать брехню вместо onmousewheel и оно у тебя также сработает. Тоесть ты просто вызовешь собственное событие, которое не обязательно должно существовать в браузере

B~Vladi 02.01.2012 17:07

Цитата:

Сообщение от devote
Строка 12 вместо onmousewheel нужно писать mousewheel

Нет, у меня всё правильно.
Цитата:

Сообщение от devote
попробуй написать брехню вместо onmousewheel и оно у тебя также сработает. Тоесть ты просто вызовешь собственное событие, которое не обязательно должно существовать в браузере

Ты в этом точно уверен? Прочитай ещё раз мою подпись.

devote 02.01.2012 17:15

B~Vladi,
Ну вот смотри, Опера поддерживает как mousewheel так и DOMMouseScroll.

привожу пример:

function getWheelEvent(){
    var eventType='DOMMouseScroll';
    var listener=function(){
        eventType='myevent';
    }
    var ele=document.createElement('div');
    document.body.appendChild(ele);
    if(ele.addEventListener)ele.addEventListener('myevent',listener,false);
    else if(ele.attachEvent)ele.attachEvent('onmyevent',listener);
    if(document.createEvent&&ele.dispatchEvent){
        var evt=document.createEvent('HTMLEvents');
        evt.initEvent('myevent',true,true);
        ele.dispatchEvent(evt);
    }else ele.fireEvent('onmyevent',event);
    if(ele.removeEventListener)ele.removeEventListener('myevent',listener,false);
    else if(ele.detachEvent)ele.detachEvent('onmyevent',listener);
    document.body.removeChild(ele);
    return eventType;
}
alert(getWheelEvent());
тут ты получишь myevent потому что функция addEvenetListener по стандартам w3c позволяет создавать собственные события и инициировать их. просто пример по аналогии jQuery

$('div').bind('myevent', function(){
    alert("triggered myevent");
});
$('div').trigger('myevent');


тоесть в твоем коде по стандарту initEvent не должен начинаться с префикса on у тебя же оно есть, а событие висит на обычном событие без префикса.

B~Vladi 02.01.2012 18:05

Цитата:

Сообщение от devote
Опера поддерживает как mousewheel так и DOMMouseScroll.

Потому что опера - единственный браузер, подражающий IE. В любом случае к ошибке это не приводит.
Цитата:

Сообщение от devote
пример по аналогии jQuery

В jQuery это обертка, кури исходники. Так же как пространства имен в именах событий.

devote 02.01.2012 18:18

Цитата:

Сообщение от B~Vladi
В jQuery это обертка, кури исходники. Там же как пространства имен в именах событий.

Не ужто так сложно прочесть стандарты. Я не сказал что это как сделано в jQuery я сказал что по аналогии, тоесть я хочу проверить есть ли в браузере событие допустим "TratataEvent". идем твоим способом:

function test( event ) {
    var status = false,
        elem = document.createElement('div');

    document.body.appendChild( elem );

    elem.addEventListener( event, function() {
        status = true;
    }, false);

    var evt=document.createEvent('HTMLEvents');
    evt.initEvent( event ,true, true );

    elem.dispatchEvent( evt );

    document.body.removeChild( elem );

    return status;
}

alert( test( 'TratataEvent' ) );
alert( test( 'click' ) );
alert( test( 'DOMMouseScroll' ) );
alert( test( 'onmousewheel' ) );
alert( test( 'mousewheel' ) );


Все эти тесты всегда выведут значение true

Цитата:

Сообщение от B~Vladi
В jQuery это обертка, кури исходники.

Прокурены давно, и я не ставлю в пример jQuery, говорю что стандартные работают по тому же принципу.

А для ИЕ достаточно сделать такую проверку:
function test( event ) {
    var status = false,
        elem = document.createElement('div');

    document.body.appendChild( elem );

    try {
        elem.fireEvent( event, document.createEventObject() );
        status = true;
    } catch ( _ ) {
    }

    document.body.removeChild( elem );

    return status;
}

alert( test( 'onmousewheel' ) );

alert( test( 'onblahtest' ) );

Nekromancer 02.01.2012 19:15

B~Vladi,
У вас таки ошибка.
if(ele.addEventListener)ele.addEventListener('mousewheel',listener,false);
        var evt=document.createEvent('HTMLEvents');
        evt.initEvent('onmousewheel',true,true);
        ele.dispatchEvent(evt);

Найдите разницу в 2 символа в создаваемом и запускаемом объекте. Это лишь ИЕ падает на fireEvent, когда пытаешься ему вызвать не существующее событие в браузере.
И так, как правильно проверить, в браузере поддерживается mousewheel или DOMMouseScroll
if(document.body.addEventListener){
if('onmousewheel' in document.body || document.body.onmousewheel === null){
// mousewheel event
}else if(window.MouseScrollEvent){
//DOMMouseScroll by Gecko
}else if(window.WheelEvent){
//DOMMouseScroll DOM 3 Events - Webkit support
}else {
//default behavior
//passing 2 events - DOMMouseScroll && mousewheel
}
}else if(window.attachEvent){
//old IE - mousewheel

}else {
//default behavior ...
}

Nekromancer 02.01.2012 19:20

Как заметили мне в приват, лучше конечно проверять с начала на существование DOMMouseScroll события :)

devote 02.01.2012 19:34

if ( window.MouseScrollEvent || window.WheelEvent ) {
    // Gecko | Webkit
    event = "DOMMouseScroll";
} else if ( window.addEventListener ) {
    // Opera | IE 9
    event = "mousewheel";
} else {
    // IE before v9
    event = "onmousewheel";
}

Nekromancer 02.01.2012 19:42

Цитата:

Сообщение от devote (Сообщение 147714)
if ( window.MouseScrollEvent || window.WheelEvent ) {
    // Gecko | Webkit
    event = "DOMMouseScroll";
} else if ( window.addEventListener ) {
    // Opera | IE 9
    event = "mousewheel";
} else {
    // IE before v9
    event = "onmousewheel";
}

Не, криво, серьёзно.

B~Vladi 02.01.2012 22:04

Да ок ок, вы посмотрите какого года этот пост. Кстати, я удалил 2 последние.

Nekromancer 02.01.2012 22:14

B~Vladi,
гг, действительно, кто блин такое апает :)

devote 02.01.2012 22:37

хех... дык сам автор темы и апнул ее сегодня =)

Denisko-Redisko 03.01.2012 00:35

Цитата:

Цитата:

Опера поддерживает как mousewheel так и DOMMouseScroll.
Потому что опера - единственный браузер, подражающий IE. В любом случае к ошибке это не приводит.
DOMMouseScroll, это проприетарная фича геко, Gecko-Specific DOM Events, в других стандартах ее нет, и вебкит ее не поддерживает.

Цитата:

дык сам автор темы и апнул ее сегодня
Ковырялся в ксулах, выяснил, что DOMMouseScroll относится к интерфейсу nsIDOMMouseScrollEvent, решил, что это наиболее корректный способ проверить поддержку события DOMMouseScroll, стал править код своей либы, там ссылка на эту тему :)
Отписался. Так как с 2009 года в этом отношении ничего не улучшилось, как вешали под два обработчика, так и вешают, и в популярных фреймворках, и в велосипедах.

Nekromancer 03.01.2012 00:55

Denisko-Redisko,
Вообще вы правы, да. WebKit поддерживает событие mousewheel, причём которое тоже не является стандартизированным, в отличии от события wheel. Но хоть интерфейс для него правильный использует.


Часовой пояс GMT +3, время: 00:20.