улучшенный 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']() });