улучшенный hover

интерфейс, элементы которого разумно реагируют на наведение мыши, воспринимается гораздо лучше. Видимо, поэтому в CSS есть псевдокласс :hover. Однако, как мы все знаем, его реализация в IE6- оставляет желать лучшего — абсолютное большинство элементов не получают этот псевдокласс. Исправляя такое поведение при помощи javascript, мы можем заодно расширить возможности обычного hover

итак, задача стоит следующим образом: при наведении мыши на элемент нужно добавить ему класс hover или другой, заказанный верстальщиком; при уведении мыши с элемента этот класс нужно убрать; опционально при этом нужно вызывать какие-то функции для дополнительной обработки интерфейса. Значит, наш метод, помимо самого элемента, будет получать опциональными параметрами имя класса и функции-обработчики. Впрочем, разумнее будет сделать один обработчик, в который мы передадим тип происходящего события: mouseover или mouseout. И скорее всего он сам справится с добавлением/удалением класса.

объявление нашего метода выглядит так:

Element.Methods.hover = function(element, className)

вторым параметром может быть undefined, имя класса или функция, поэтому имя навешиваемого класса вычислим вот так:

className = (className instanceof Function) 
    ? 'hover' 
    : (className || 'hover');

обработчик по умолчанию будет добавлять или удалять класс в зависимости от своего параметра, который удобно сделать булевым значением, кодирующим mouseover в true, mouseout в false:

function(hover){ 
    element[hover 
        ? 'addClassName' 
        : 'removeClassName'
    ](className); 
}

но, поскольку обработчик можно подменить параметром, конечная функция вычисляется так:

var func  = (className instanceof Function) 
    ? className 
    : function(hover){ element[hover ? 'addClassName' : 'removeClassName'](className); };

теперь нужно упомянуть, что в IE, помимо стандартной пары событий mouseover/mouseout есть еще одна, больше подходящая для нашей задачи: невсплывающие mouseenter/mouseleave. Дело в том, что первые два события срабатывают на рассматриваемом элементе даже тогда, когда мышь пересекает границу дочернего элемента (см. event bubbling), что порождает огромное количество ненужных в нашем случае вызовов. Борьба с ними — отдельная тема, а в рассмативаемом примере мы просто будем использовать возможности IE:

var names = Prototype.Browser.IE 
    ? ['mouseenter', 'mouseleave'] 
    : ['mouseover', 'mouseout'];

теперь осталось только подключить обработчик к элементу, используя описанный в предыдущем посте карринг:

return element.
    observe(names[0], func.curry(true)).
    observe(names[1], func.curry(false));

в итоге полный текст метода с несколькими примерами вызова выглядит так:

Element.Methods.hover = function(element, className){
    element = $(element);
    var func  = (className instanceof Function) 
        ? className 
        : function(hover){ element[hover ? 'addClassName' : 'removeClassName'](className); };
    className = (className instanceof Function) ? 'hover' : (className || 'hover');

    var names = Prototype.Browser.IE ? ['mouseenter', 'mouseleave'] : ['mouseover', 'mouseout'];

    return element.
        observe(names[0], func.curry(true)).
        observe(names[1], func.curry(false));
};

element.hover();
element.hover('specific_hover_class');
element.hover(function(hover){ treasure[hover ? 'show' : 'hide']() });

Артемий Трегубенко,
, ,

comments powered by Disqus