Máš webovú aplikáciu. V nej formulár, v ktorom okrem iného chceš definovať zoznam niečoho (napr. keywordov). Máš tam políčko, vedľa neho tlačítko. Napíšeš keyword do políčka, klikneš na tlačítko a JavaScript ti do zoznamu pridá novú položku bez toho, aby sa submitoval celý formulár.
Až potiaľ hrozne jednoduché. Ale čo ak chcem, aby sa nová položka do zoznamu pridala keď stlačím Enter v mojom políčku? To už je iná vec.
Prototype s tým ochotne pomôže.
Formulár
Najprv ukážka zjednodušeného formuláru:
<form action="" method="get"> <ul id="zoznamPoloziek"> <li>nejaká položka</li> </ul> <p> <label> Pridaj položku: <input type="text" name="polozka" id="novaPolozka" /> </label> <input type="button" value="Pridaj" id="pridajPolozku" /> </p> <p> <input type="submit" value="Odošli formulár" /> </p> </form>
Funkcia
Funkcia pre pridanie položky do zoznamu:
function pridajPolozkuDoZoznamu() {
// nájdenie a zapamätanie elementov
var zoznam = $( 'zoznamPoloziek' );
var policko = $( 'novaPolozka' );
// vytvorenie novej položky zoznamu, jej obsahom je hodnota políčka
var polozka = new Element( 'li' ).update( policko.value );
zoznam.insert( polozka, { position : 'bottom' } );
// políčko sa vyprázdni a získa focus, aby užívateľ rovno mohol pridať ďalšiu položku
policko.value = '';
policko.focus();
}
Ošetrenie stlačenia Enteru
Teraz potrebuješ skript, ktorý:
- bude sledovať či vybrané formulárové políčko má alebo nemá focus,
- ak políčko má focus, zabrániť submitu formuláru,
- namiesto submitu zavolať nejakú funkciu.
Použijeme na to triedu. Hovorme jej EnterMonitor. Bude volaná s dvoma parametrami:
var EnterMonitor = Class.create({
/**
* @param {Object} element ID formulárového políčka
* @param {Object} action Funkcia, ktorá sa má vykonať pri stlačení Enteru v políčku
*/
initialize : function ( element, action ) {
}
});
V rámci tejto triedy sa dosť intenzívne pracuje s eventmi. Kvôli zachovaniu scopu a referencie na this nezaškodí naštudovať si na čo je metóda bindAsEventListener.
var EnterMonitor = Class.create({
/**
* @param {Object} element ID formulárového políčka
* @param {Object} action Funkcia, ktorá sa má vykonať pri stlačení Enteru v políčku
*/
initialize : function ( element, action ) {
// zapamätanie elementov pre neskoršie použitie
this.element = $( element );
this.form = $( this.element.form );
this.action = action;
// zmena správania formuláru, ale iba ak je focus na vybranom políčku
this.element.observe( 'focus', this.activate.bindAsEventListener( this ) );
this.element.observe( 'blur', this.deactivate.bindAsEventListener( this ) );
// zapamätanie si volanie akcie kvôli event listenerom
this.fixedEventAction = this.doAction.bindAsEventListener( this );
},
activate : function () {
this.form.observe( 'submit', this.fixedEventAction );
},
deactivate : function () {
this.form.stopObserving( 'submit', this.fixedEventAction );
},
doAction : function ( event ) {
this.action(); // zavolanie vybranej akcie
event.stop(); // zrušenie defaultnej akcie formuláru
}
});
Inicializácia
Pri načítaní dokumentu treba urobiť dve veci:
- Naviazať funkciu na pridanie položky po kliknutí na tlačítko
- a zinicializovať triedu EnterMonitor na vybrané políčko
Event.observe( document, 'dom:loaded', function () {
$( 'pridajPolozku' ).observe( 'click', pridajPolozkuDoZoznamu );
new EnterMonitor( 'novaPolozka', pridajPolozkuDoZoznamu );
} );
Google Chrome
Všetky bežné prehliadače s týmto skriptom nemajú problém. Google Chrome je však natoľko zoptimalizovaný, že mu treba trošku pomôcť.
Problém je dobre popísaný vývojármi Prototypu a jeho fix je fakt jednoduchý. Bude zverejnený v najbližšej verzii Prototypu (1.6.0.4).