Ako na vlastné jQuery plug-in
jQuery je jedným z najobľúbenejších javascriptových frameworkov vôbec. Sprvu to bola len knižnica, ktorá mala poskytovať CSS selektory do jazyka JavaScript, ale potom čo Dean Edwards vydal svoju výbornú knižnicu cssQuery, sa vývoj jQuery posunul trošku iným smerom. Autorom knižnice jQuery je John Resig.
Dosť bolo teórie o jQuery, teraz pôjdeme programovať. Ako už napovedá
titulok článku, napíšeme si vlastné plug-in do jQuery. Určite ste sa už s
nejakým takýmto pluginom stretli. Volajú sa rovnako ako akákoľvek funkcia v
tejto knižnici a to napríklad takto $(element).funkce()
.
Pluginov je na internete veľa, možno aj preto je framework tak úspešný. Môže sa ale stať, že vám žiadny tento plug-in nebude vyhovovať a to treba licencií. Tá totiž ani zďaleka nemusí byť iba open-source, a tak sa môžete stretnúť aj s platenými plug-iny. Avšak rovnako tak môžete platené pluginy vydávať sami. Tento článok je úvodom do tvorby vlastných doplnkov do jQuery. Článok je založený na vývoji reálneho plug-inu a to na jednoduchom slideru obsahu.
Štruktúra HTML & CSS
Keď píšeme vlastné doplnok, musíme si uvedomiť, aká bude štruktúra
HTML a podľa nej sa zariadiť a nastylovať ju. Chceme slider obsahu, a preto
pre nás bude najlepšie použiť zoznam, teda element <ul>
.
Nastylujeme ho podľa tried, ktoré priradí sám plug-in. Tu je malá ukážka
HTML štruktúry so základnými CSS štýly:
Html štruktúra
<ul> <li>Obsah prvního slidu</li> <li>Obsah druhého slidu</li> </ul>
CSS štýly
/** * Vsechny slidy */ ul.easySlider-content { padding: 20px; margin-bottom: 25px; position: relative; height: 250px; z-index: 100; -webkit-box-shadow: 0 0 10px #aaa; -moz-box-shadow: 0 0 10px #aaa; box-shadow: 0 0 10px #aaa; border: 1px solid #dcdcdc; background: #ffffff; background: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIxJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNlZWVlZWUiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+); background: -moz-linear-gradient(top, #ffffff 1%, #eeeeee 100%); background: -webkit-gradient(linear, left top, left bottom, color-stop(1%,#ffffff), color-stop(100%,#eeeeee)); background: -webkit-linear-gradient(top, #ffffff 1%,#eeeeee 100%); background: -o-linear-gradient(top, #ffffff 1%,#eeeeee 100%); background: -ms-linear-gradient(top, #ffffff 1%,#eeeeee 100%); background: linear-gradient(top, #ffffff 1%,#eeeeee 100%); filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eeeeee',GradientType=0 ); } ul.easySlider-content li { margin-right: 20px; } /** * Aktivní slide */ ul li.active { display: block !important; } /** * Posuvne sipky */ a.arrowLeft { display: block; width: 70px; height: 70px; background: #fff url('images/arrow_left.png') 3px center no-repeat; position: absolute; margin: 140px -48px; border-radius: 50px; border: 5px solid #dcdcdc; } a.arrowRight { display: block; width: 70px; height: 70px; background: #fff url('images/arrow_right.png') 18px center no-repeat; position: absolute; margin: 140px 770px; border: 5px solid #dcdcdc; border-radius: 50px; } a.arrowLeft:hover, a.arrowRight:hover { background-color: #dcdcdc; }
JQuery.fn
jQuery.fn
je, dalo by sa povedať, menný priestor pre vaše
doplnky. Všetky funkcie umiestnené práve do tohto objektu môžeme zavolať
priamo z jQuery. Kontextom týchto funkcií je práve vybraný element. Čo je
to ale ten kontext funkcií? Každá funkcia v JavaScripte je spracovávaná v
nejakom kontexte. Laicky povedané je to to kľúčové slovo this
.
Ak teda vložíme funkciu do jQuery.fn
a zavoláme náš plug-in
napr .: $('#obsah').nazevMeFunkce()
, bude v danej funkcii
kľúčové slovo this
obsahovať element s
id="obsah"
. Bude však prístupný ako objekt
HTMLElement
, nie ako jQuery objekt. Ak by sme ho chceli použiť
ako objekt jQuery, jednoducho uvedieme this
ako parameter jQuery
objektu: jQuery(this)
alebo $(this)
(toto sú
totožné zápisy).
Keď už vieme, kam vložiť náš plug-in, môžeme začať písať.
Všeobecne je najlepšie náš doplnok zabaliť do anonymný funkcie, aby sa
nepřepisovaly premenné a tak ďalej. Je to lepšie aj preto, že znak
$
používajú aj iné knižnice (okrem jQuery) ako zástupný znak
a to v anonymných funkciách riešiť nemusíme. Mali by sme si tiež
navrhnúť, ako budeme volať ďalšie funkcie v plug-inu a ako vyriešime
užívateľské nastavenie. Uvediem teraz jednoduchý príklad základného
plug-inu s logikou volanie funkcií, ktorý potom rozoberiem.
// Naše anonymní funkce - jediným parametrem je $, který zastupuje objekt jQuery (function( $ ) { // Zde budou metody, které může z plug-inu zavolat i sám uživatel var methods = { // Inicializační metoda - je volána z hlavní funkce init: function( o ) {} }; // Vstupní funkce plug-inu $.fn.easySlider = function( method ) { // Pokud máme jméno funkce, kterou chceme zavolat if ( methods[method] ) { // Zavoláme danou funkci se všemi ostatními předanými argumenty plug-inu return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); } else if ( typeof method == 'object' || !method ) { // Pokud ne, zavoláme inicializační metodu return methods.init.apply(this, arguments); } else { // Pokud metoda neexistuje, vypíšeme chybu $.error('Metoda ' + method + ' neexistuje v plug-inu jQuery.easySlider'); } }; // Základní nastavení $.fn.easySlider.defaults = { }; })( jQuery ); // zavoláme funkce s parametrem jQuery
Vytvorili sme si funkciu easySlider()
v objekte
jQuery.fn
. Môžeme ju teda zavolať napr .:
$('ul#slider').easySlider()
.
Ale čo keď bude potrebné niečo nastaviť alebo zavolať nejakú
vnútornú funkciu pluginu? Je veľmi nepraktické meniť samotný kód pluginu.
Tieto kódy sú tiež často minimalizované a tak to ani nejde. Vyššie
uvedený príklad však počíta aj s týmto. Ako argument môžeme uviesť buď
objekt, v ktorom bude všetko nastavenie plug-inu, alebo meno funkcie v objekte
methods
a alebo tiež nič a plugin si potom sám zavolá
methods.init()
. Toto je len jeden spôsob, ako urobiť logiku
volanie funkcií. Dalo by sa to urobiť aj inak. Pre nás je však toto veľmi
praktické, a tak nemusíme nič riešiť.
Naposledy tu máme objekt defaults
. V ňom je uložené
základné nastavenie. Je to preto, aby užívateľ nemusel nastavovať všetko,
ale len to, čo práve chce inak.
Ešte než sa vrhneme na samotný plug-in, chcel by som ujasniť, čo vlastne
robí funkcie apply()
. Každá funkcia v JavaScripte má nejaký
svoj kontext, v ktorom sa spracováva, ako už som spomenul vyššie. Funkcia
apply()
zavolá danú funkciu s kontextom, aký si zvolíme. Má
celkom dva argumenty, prvým je práve ten kontext. Ten sme si nastavili na
this
, teda na práve vybraný element. Druhým argumentom je
pole, v ktorom uvedieme všetky argumenty funkcie. Tu uvádzame
premennú arguments
, čo je pole všetkých argumentov funkcie.
Inicializačnú metóda
Máme základ a tak si každý prvok inicializujeme. Jediný argument bude
objekt s užívateľským nastavením. Aby sme však mali istotu, že sú v
tomto objekte všetky nastavenia, rozšírime defaults
práve o
tento objekt. Opäť uvediem celý kód funkcie, ktorý vzápätí
rozoberiem:
// Inicializační metoda - je volána z hlavní funkce init: function( o ) { // Získáme nastavené volby plug-inu o = $.extend({}, $.fn.easySlider.defaults, o); // Uložíme si aktuální kontext funkce (element plug-inu) var $that = $(this); // Funkce po kliknutí na šipky var left_click = function( e ) { e = $.event.fix(e); e.preventDefault(); $that.easySlider("prev"); }, right_click = function( e ) { e = $.event.fix(e); e.preventDefault(); $that.easySlider("next"); }; // Projdeme všechny předané elementy a inicializujeme pro ně plug-in return this.each(function() { // Najdeme všechny obrázky ve slideru var $items = $(this).find('li'), count = $items.length, $self = $(this); // Všechny je skryjeme a pozicujeme absolutně $items.css({ display: 'none', position: 'absolute' }); // Vložíme seznamu třídu pro přístupnější manipulování v CSS $self.addClass('easySlider-content').data('speed', o.speed); // Aktivujeme první element $($items.get(o.active)).addClass("active"); // Vytvoříme si postranní šipky pro posun slideru var $arrowLeft = $('<a />').attr('href', '#left').addClass('arrowLeft'); var $arrowRight = $('<a />').attr('href', '#right').addClass('arrowRight'); // Nastavíme callback na kliknutí $arrowLeft.bind('click', left_click); $arrowRight.bind('click', right_click); // Vložíme šipky před seznam slidů $self.before( $arrowRight ); $self.before( $arrowLeft ); }); }
Hneď na prvom riadku je použitá funkcia jQuery.extend()
.
Táto funkcia rozširuje ľubovoľný počet objektov, kde objekty uvedené
poslednýkrát majú väčšiu prioritu. Prvý argument je cielený objekt, kam
chceme výsledok uložiť (viac info v oficiálnej dokumentácii
jQuery.extend). A teraz česky. Vezmeme premenné a funkcie z objektu
defaults
a ak existuje rovnomenná funkcie či premenná v objekte
o
, prepíšeme jej hodnotu na hodnotu, ktorá je v objekte
o
. To zaistí, že nemusíme zložito zisťovať, či ak nám
užívateľ zadal všetky voľby. Ďalšie je pomocná premenná
$that
. Okrem jednoduchšieho zápisu, ktorý nám možno ušetrí
desatinu sekundy, sú vo funkcii methods.init()
definované ešte
iné funkcie s iným kontextom a v týchto funkciách by výraz
$(this)
znamenal úplne niečo iné. Preto si ho musíme uložiť
do premennej, ktorá bude prístupná aj z týchto funkcií.
Celá funkcia vracia this
, teda opäť vybrané elementy, a pre
každý tento element vykoná nastavenia plug-inu. Poďme si teda kód podrobne
rozobrať. Keďže predpokladáme, že štruktúra slideru bude zoznam (v HTML
<ul>
a <li>
), nájdeme si všetky elementy
<li>
a uložíme si ich do premennej $items
.
Ďalej tu máme pomocnú premennú, v ktorej je počet elementov
<li>
(teda počet slidov) a opäť pomocnú premennú
$self
, v ktorej je kontext funkcie, v ktorej pracujeme. Ten sa
totiž zmenil s použitím jQuery.each
, ako ste si mohli
všimnúť.
Všetko sme si už načítali do premenných, a tak si ich nastavíme. Zo
všetkého najskôr skryjeme všetok obsah a nastavíme mu absolútnu pozíciu.
To z toho dôvodu, aby sa nám obsah nerozhádzal pri prechode. Ďalej potom
elementu <ul>
pridáme triedu
.easySlider-content
a nastavíme ju data-speed
na
hodnotu, ktorú zadá používateľ. To urobíme preto, aby sme si ju mohli v
inej funkcii prečítať, ale nebudem predbiehať.
Teraz už vytvoríme tlačidlá pre prechod na ďalšiu alebo
predchádzajúcu slide. Nastavíme im danú triedu a vložíme ich pred slider.
Preskočil som zámerne bind('click')
. Musíme totiž povedať
skriptu, čo sa má stať po kliknutí na tieto šípky. Použijeme vopred
nadefinované funkcie left_click()
a right_click()
.
Tieto funkcie máme nadefinované ešte pred return, aby sme ich nemuseli
definovať napríklad aj sto krát, čo by mohlo spomaliť celý skript. V tejto
funkcii by ste totiž mali definovať len to najnutnejšie, čo sa musí takto
vykonať naozaj pre každý element. Čo by som chcel zdôrazniť v týchto
funkciách je použitie $.event.fix(e)
. Ako už možno viete, v
niektorých prehliadačoch musíte pristupovať k premennej udalosti
(event
) inak alebo sú tam inak nazvané parametre, takže si
musíme dávať pozor. Čo už však málokto vie je, že táto jQuery funkcia
to zariadi za nás a my už sa s tým nemusíme znepokojovať. Potom len
použijeme e.preventDefault()
, ktorá zamedzí prevedenie
východiskovej udalosti (u odkazov je to presmerovanie na danú adresu
href
). Na konci funkcia je zavolaná metóda
methods.next()
cez našu volací logiku. Synonymom pre toto volanie
je methods.next.apply(that);
, Kde that
je kontext
funkcie init()
.
Verejné a privátne funkcie
Ako som už hovoril, všetky funkcie v objekte methods sú volatelné z
nášho pluginu a to týmto spôsobom:
$(element).easySlider("nazev_funkce", ["první parametr", "druhý parametr", ...]);
(Hranaté zátvorky naznačujú len to, že sú tieto argumenty nepovinné - v
normálnom skriptu tam nie sú!). Funkcie sú teda verejné. Môžeme tiež
vytvoriť privátne funkcie a to tak, že ich uložíme mimo objekt
methods
, do tej istej anonymný funkcie. Takéto funkcie by boli
prístupné len v našej anonymný funkciu a zvonku by prístupné neboli. V
tomto prípade privátne metódy nepoužívame, ale niekedy sú veľmi
užitočné.
Teraz už zostávajú len tri funkcie. Jedna nastaví aktívnu vrstvu a
zároveň vykoná animáciu (tzv. Slide) na základe odovzdaného indexu.
Nazveme jej napríklad active()
. Ďalšie dve budú funkcie
prev()
a next()
, ktoré vypočítajú index
predchádzajúceho, resp. ďalšieho slidu a odovzdajú ho funkciu
active()
.
// Funkce nastaví aktivní slide (Index od 0 do počtu obrázků v galerii) active: function( index, direction ) { // Nastavíme rychlost speed = $(this).data('speed') || 800; // Nastavíme směry efektů directionHide = direction || 'left'; directionShow = directionHide == 'left' ? 'right' : 'left'; // Skryjeme aktivní položku $(this).find('li.active').hide('slide', { direction: directionHide }, speed); // Všem položkám odstraníme třídu .active $(this).find('li').removeClass('active'); // Načteme aktivní slide var slide = $(this).find('li').get(index) || false; // Zobrazíme ho $(slide).addClass('active').show('slide', { direction: directionShow }, speed); // Vrátíme aktivní element return $(this).find('li').get(index) || false; }, // Přesune se na další slide next: function() { // Najdeme další element a zjistíme jeho index, ke kterému přičteme +1 var index = ($(this).find('li.active').index()+1); // Aktivujeme tento slide, pokud existuje. Pokud ne, automaticky se přesuneme na první (nultý) return $(this).easySlider("active", ($(this).find('li').get(index) ? index : 0)); }, // Přesune se na předchozí slide prev: function() { var index = $(this).find('li.active').index()-1 < 0 ?$(this).find('li').length-1 : $(this).find('li.active').index()-1; // Aktivujeme slide s títo indexem return $(this).easySlider("active", index, 'right'); }, /** Metoda init ... */
$ (element) .easySlider ( "active", index, direction)
Stačí rozobrať tieto tri metódy a náš plugin bude hotový. Prvá
funkcia active()
aktivuje element, ktorý zistíme z odovzdaného
indexu (viď. Prvý parameter funkcie). Druhý parameter direction
je nepovinný (buď 'left'
alebo 'right'
) a ten
určuje smer, kam sa slider posunie. Funkcia na zobrazenie a skrytie elementu
používa jquery.effects.core.js
z knižnice jQuery UI. Preto je
tento plug-in na nej závislý. Ak budete chcieť použiť len čisto jQuery,
môžete ich nahradiť funkciami fadeIn()
a fadeOut()
alebo slideDown()
a slideUp()
alebo jednoducho
animate()
, to už je na vás.
$ (element) .easySlider ( "next")
Posunie slider na ďalší element. Ak ďalšie nie je, presunie sa na
začiatok. Volá funkciu active()
. Funkcia prev()
je
rovnaká s tým rozdielom, že sa presunie na predchádzajúcu alebo posledný
element.
Pár tipov nakoniec
- Minimalizujte svoj kód, ale poskytujte verzia aj normálny (pokiaľ teda nechcete robiť komerčné pluginy). Tak budú môcť vaše pluginy ďalej vyvíjať a upravovať aj iní, pokiaľ to nebude v rozpore s vami danou licenciou. Pre minimalizovanie kódu odporúčam skript Deana Edwardsa - Packer
- Do používateľského nastavenia vložte čo najviac vecí. Spíšte potom podrobnú dokumentáciu tohto nastavenia.
- Snažte sa moc nenastavovať CSS štýly. To nechajte na externých súboroch. V skripte nechajte len nevyhnutné štýly.
- Píšte nevtieravý kód. Nechcite po užívateľoch, aby museli pridávať HTML, to predsa dokáže JavaScript taky
- Pred vydaním otestujte svoj výtvor v čo možno najviac prehliadačoch. Ak ho nejaký prehliadač nepodporuje, napíšte to do dokumentácie.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 1366x (90.17 kB)
Aplikácia je vrátane zdrojových kódov v jazyku JavaScript