Staršie verzie Internet Exploreru netušia, že myšou sa dá ukázať aj na iné elementy než odkazy. Takže namiesto toho, aby sa jednoducho používal CSS selektor s pseudo-triedou :hover, musia sa vymýšľať kdejaké komplikované javascriptové kraviny.
Takéto elementárne záležitosti v rukách neskúsených kóderov žiaľ často páchajú na kóde hrozné krivdy. Ukážem ti, ako by si pravdepodobne postupoval pri písaní takéhoto kódu. Vysvetlím ti, prečo by to bol nesprávny postup. A nakoniec ti vyzradím sladké tajomstvo – ako to napísať poriadne.
Primitívne začiatky
Zjavným prvým riešením je zavesiť onmouseover a onmouseout eventy na element. Áno, bude to fungovať:
var mojElement = $( 'mojElement' );
mojElement.observe( 'mouseover', function ( event ) {
event.element().addClassName( 'hover' );
} );
mojElement.observe( 'mouseover', function ( event ) {
event.element().removeClassName( 'hover' );
} );
Lenže písať tento bordel kvôli každému elementu je blbosť. Niečo jednoriadkové by bolo rozhodne oveľa lepšie.
Poďme si to zuniverzálniť
Pomôže trieda Hover. V podstate iba obaľuje predchádzajúci kód kvôli znovupoužiteľnosti. Zavolá sa, ako parameter sa jej pošle element a ona sa už o všetku tú piplačku postará sama:
// definícia triedy Hover
var Hover = Class.create({
initialize : function ( element ) {
element = $( element );
element.observe( 'mouseover', function ( event ) {
event.element().addClassName( 'hover' );
} );
element.observe( 'mouseover', function ( event ) {
event.element().removeClassName( 'hover' );
} );
}
});
// aplikácia na element #mojElement
new Hover( 'mojElement' );
Lenže čo ak chcem sám definovať názov atribútu class, ktorý sa má elementu pri mouseoveri pridať?
Komplikuje sa to
Pridaním druhého parametru (hoverClassName) sa to celé trochu komplikuje. Zrazu si treba niektoré veci pamätať. Tým pádom si treba dávať na scope a event listenery sa nafukujú:
// definícia triedy Hover
var Hover = Class.create({
initialize : function ( element, hoverClassName ) {
this.element = $( element );
this.hoverClassName = hoverClassName || 'hover';
this.element.observe( 'mouseover', this.mouseover.bindAsEventListener( this ) );
this.element.observe( 'mouseout', this.mouseout.bindAsEventListener( this ) );
},
mouseover : function () { this.element.addClassName( this.hoverClassName ); },
mouseout : function () { this.element.removeClassName( this.hoverClassName ); }
});
// aplikácia na element #mojElement
new Hover( 'mojElement', 'mojaHoverTrieda' );
Hromadné nasadenie
Toto všetko je síce fajn, ale iba za predpokladu, že sa to celé nasadzuje iba na jeden element. Lenže v praxi sa hovery obvykle robia na zbierky elementov. Napríklad na všetky položky v odrážkovom zozname, alebo na všetky riadky v tabuľke.
Síce nie je problém to nasadiť, ale kód sa už zase zbytočne komplikuje:
$$( '#mojaTabulka tbody tr' ).each( function ( element ) {
new Hover( element, 'mojaHoverTrieda' );
} );
Správne riešenie
Dúfam, že ti už došlo, že cesta k efektívnemu hoveru nevedie cez triedy. Prototype je totiž schopný hravo urobiť väčšinu práce sám, stačí len vedieť ako na to.
Namiesto samostatnej triedy je lepšie rozšíriť si objekt Element o novú metódu. Vďaka tomu sa táto nová metóda môže volať aj na zbierku elementov pomocou metódy Element.invoke().
Element.addMethods({
addHoverClass : function ( element, className ) {
element = $( element );
className = className || 'hover'; // ak trieda nie je uvedena, pouzije sa defaltne "hover"
element.observe( 'mouseover', function ( event ) {
event.element().addClassName( className );
} );
element.observe( 'mouseout', function ( event ) {
event.element().removeClassName( className );
} );
return element;
}
});
Inicializovať sa to (napríklad pri dom:loaded) bude takto:
// pridanie defaultnej hover triedy k #mojElement $( 'mojElement' ).addHoverClass(); // pridanie vlastnej hover triedy k #mojElement $( 'mojElement' ).addHoverClass( 'mojaHoverTrieda' ); // pridanie defaultnej hover triedy vsetkym polozkam zoznamu $$( 'li' ).invoke( 'addHoverClass' ); // pridanie hover triedy "zvyraznenyRiadok" vsetkym riadkom v tele tabulky #mojaTabulka $$( '#mojaTabulka tbody tr' ).invoke( 'addHoverClass', 'zvyraznenyRiadok' );