HTML

Gyakorlat: új plugin (menü), opciók, animate

Most pedig elkészítjük az első jQuery-pluginunkat, ami már azért érni is fog valamit. Így első körben még valami rövidre gondoltam, ami ettől még hasznos és látványos is. Ez a plugin egy natúr HTML-lista (felsorolás) segítségével alkotott menüt fog kissé feljavítani. Akkor ne is szarozzunk... vágjunk bele!

<ul id="mymenu">
    <li><a href="#">Home</a></li>
    <li><a href="#">Services</a></li>
    <li><a href="#">Gallery</a></li>
    <li><a href="#">Blog</a></li>
    <li><a href="#">Contact</a></li>
</ul>

Ez egy teljesen alap, formázatlan "ul" lista, benne "li" elemekkel, amelyekben a linkek csücsülnek. A példa kedvéért még CSS-stílust sem adunk meg neki, azt is a jQuery fogja elvégezni... A program most már külön fájlban lesz eltárolva, hogy akkor már igazán stílusosan nyomjuk a témát. Akkor a HTML leírásunk - azon kívül,   hogy kialakítjuk a környezet felépítését és persze behívjuk a jQuery-t is - még fűszerezve lesz ehhez hasonlókkal:

<script src="js/myplugin.js"></script>
<script>
    $(document).ready(function(){
        $('#mymenu').myPlugin();
    });
</script>

Tehát ha kész a plugin leírása a "myplugin.js" fájlunkban, akkor ez a kis definíció egy frankó kis menüt fog készíteni a gagyi link-felsorolásunkból. Mit fog csinálni...? Először is eltüntetjük a felsorolásjeleket, aztán a "li" tagokat nem egymás alá, hanem egymás mellé helyezzük, állítunk térközöket, stb... a menüpontok háttérszínét belőjjük fehérre, a betűszínt pedig feketére. Aztán... ha a menüpont fölé visszük az egeret, egy gyors klassz kis átmenettel a színek felcserélődnek. Nem egy nagy durranás, de határozottan feldobja a feelinget. Aztán, hogy teljes legyen a dolog: lehetőséget adunk a felhasználónak, hogy megadhasson két bármilyen színt a háttérnek és a szövegnek is. Lássuk akkor, mi kerül a "JS" fájlba...

A plugin megírása...

Most azért találkozunk egy kissé spécibb esettel a többihez képest: az "animate" effekt alapjáraton nincs felkészítve a színekkel történő buherálásra, így ahhoz be kell hívnunk a programba egy kiegészítést is, amit a jQueryUI fog jelenteni nekünk (később még jobban bele is megyünk, hogy milyen egyéb dolgokkal is gazdagít minket ez). Innen le is szedhetitek akár: http://code.jquery.com/ui/1.10.0/jquery-ui.js. Aztán ezt az állományt vagy meghívjátok a HTML-ben még pluszban, vagy a pluginunk forrásában hivatkozunk rá. Én az utóbbit választottam. Egy külső szkript behívása jQuery-ben:

$.getScript("http://code.jquery.com/ui/1.10.0/jquery-ui.js");

Akkor jöhet a már ismert - új függvény létrehozásához szükséges - "keret", ami létrehozza a "myPlugin" nevű jQuery-függvényt. Tegyük bele már az opciókat is: "color1" legyen a szöveg, "color2" pedig a háttér színe, alapértelmezésként pedig a háttér legyen fehér, a szöveg fekete.

(function($){
    $.fn.myPlugin = function(ops) {
        var defOps = {color1:'black',color2:'white'};
        ops = $.extend({},defOps,ops);
    };
})(jQuery);

És elméletileg ebben a kódban mindenkinek tök nyilvánvaló, hogy mi mit jelent :) ha nem... akkor nem lesz hátrány még egyszer átrágni az előző bejegyzést.

Összekapcsolás és find() függvény

Akkor most beállítjuk az elemek stílusát a "css" függvény segítségével, ami már szintén régóta nem újdonság a számunkra. Viszont van valami, amiről még nem esett szó, és valószínűleg eddig nem is lehetett egyértelmű feltételezni, hogy működik... a jQuery függvényei egy adott szelektált elemre vonatkozóan a kívánt végrehajtás sorrendjében összefűzhetők... Nyugi, kifejtem érthetőbben is :D Szóval...

$('#elem').css('background','black');
$('#elem').css('color','white');

Itt a példában az "elem" azonosítójú objektumot választjuk ki, majd a "css" függvény alkalmazásával a háttérszínét feketévé változtatjuk. Ezután egy újabb kijelöléssel szintén az "elem" elemet kényszerítjük változásra, ahol a betűszínét cseréljük fehérre. Ugyanezen hatás eléréséhez írhatjuk egyszerűen ezt is:

$('#elem').css('background','black').css('color','white');

Itt kiválasztjuk az "elem"-et, végrehajtjuk rajta az első stílus-változtatást, majd egy ponttal hozzácsatoljuk a következő függvényt és ez mehet akármeddig, amíg még mindig az "elem" a kijelölt objektum. Na mielőtt tovább lépek, itt az ideje, hogy feldobjam a "find" függvényt is, mert szerintem elég sokszor alkalmazni fogjátok. Ennek pusztán annyi a lényege, hogy a már szelektált elemünkön belül további elemekre keresünk rá és jelüljük ki azokat. Például:

$('#elem').find('a').fadeIn();

Ez a fenti kis példa annyit jelent, hogy a kijelölt "elem" id-jű objektumban keressük fel az "a" linkeket és azokat egy "fadeIn" hatással varázsoljuk elő. Igazából ennyi a "find" lényege :) most már ezt is tudjátok...

És visszakanyarodva a fenti összefűzési példa gondolatmenetéhez... ugyanígy akár hozzácsatolhatunk egy .find('a') kifejezést is, ami ugye az aktuálisan kijelölt elemünkön (ami ugye az "elem" volt, ha elfelejtettük volna) belüli "a" tagokat keresi meg, hogy azokon hajtson végre további változtatásokat, de fontos emlékezni arra, hogy ez már egy újabb kiválasztást jelent, tehát a további hozzácsatolt függvények már ezekre az "a" tag-ekre vonatkoznak! Na, akkor most a példák után lássuk, miként formázza meg a plugin az elemeket:

$(this).css('list-style','none').find('li').css('float','left')
.find('a').css('background',ops.color2).css('padding','20px')
.css('text-decoration','none').css('color',ops.color1);

Szép kis összefűzés, mi? :D És bizony működképes. A biztonság kedvéért rágjuk át magunkat rajta... Ugye az a terv, hogy egy "ul" listából alkotott menürendszert alakít át a program és erre az "ul"-re fogjuk majd "ráhúzni a plugin-t. Akkor tehát a $(this) ezt az "ul" elemet fogja jelenteni a függvényünkben. Annyit változtatunk ennek a stílusán, hogy kivesszük a felsorolásjeleket a "list-style" tulajdonság buherálásával. Ezt követően felkutatjuk a benne található "li" elemeket... és innentől kezdve a további függvény már ezekre fog hatni. A "float" értékét "left"-re állítva a "li" tagok szépen egymás mellé kerülnek. Most pedig ezeken a "li" elemeken belüli "a" tagokra irányítjuk a reflektorfényt. Minden "a" link háttere az opciókban megadott "color2" változóban eltárolt színt kapja. Majd a linkek "padding" értékét 20 pixelesre állítjuk, hogy legyen kis távolság a szövegük és a széleik között, a "text-decoration" módosításával eltüntetjük a linkek alapértelmezett aláhúzását is, és végül a "color" tulajdonsággal a szöveg színét az opciók közötti "color1" színnel tesszük egyenlővé. Ilyen egyszerű :)

Akkor már csak a lényeg...

És... akkor már a csak a lényeg van hátra, maga a használat közbeni működés... tehát: ha egy menüpont fölé visszük az egeret szépen átváltanak a színek, majd ha elvisszük onnan, akkor vissza. Ez ugye két esemény megírását jelenti. Több lehetőségünk is van, a leggyakoribbak talán a "hover" és a "mouseout" függvények (gondolom, egyértelmű, hogy melyik melyik :) ). 

$(this).find('li').hover(function(){
    $(this).find('a').animate({
        backgroundColor:ops.color1,color:ops.color2
    },250);

});
$(this).find('li').mouseout(function(){
    $(this).find('a').animate({
        backgroundColor:ops.color2,color:ops.color1
    },50);

});

A fő objektumon belül felkeressük a "li" elemeket és kifejtjük a "hover" eseményüket (azaz, mi történik, ha föléjük kerül az egér). Ne felejtsük el most se, hogy ezen a függvényen belül a "this" kijelölés már ezekre a "li" elemekre vonatkozik. Szóval akkor megkeressük ezekben az "a" linkeket és rájuk erőszakolunk egy "animate" effektet (tehát: a "li"-re húzzuk az egeret és ezáltal az abban lévő "a" kerül változtatásra). Azt mondjuk: a "backgroundColor" tulajdonság változzon a "color1" értékre, a "color" pedig a "color2" értékre, mindez pedig egy negyed másodperc leforgása alatt (250 ms). 
Ezután pedig szinte ugyanez a folyamat: a "mouseout" eseménykor (amikor elvisszük az egeret a "li"-ről) a benne levő "a" tagok színeit ugyanígy animáljuk, csak pont fordítva és ez gyorsabban fut le, 50 ms alatt.

Ezzel el is készült a plugin. Ki is lehet próbálni a működését... én három listát hoztam létre és különböző módon paramétereztem őket: opciók nélkül, egy opció megadásával, és mindkét opció értékének változtatásával:

$(document).ready(function(){
    $('#mymenu').myPlugin();
    $('#mymenu2').myPlugin({color1:'purple'});
    $('#mymenu3').myPlugin({color1:'yellow',color2:'gray'});
});

Próbálj meg Te is nekiugrani és készítsd el magadnak ezt a kis progit. Amennyiben szükségesnek érzed, segítségül letöltheted az általam kreált verziót. A csomagot itt éred el: KLIKK

Szólj hozzá:

Saját jQuery-plugin készítése

Most végre elérkezett az idő: megalkothatjuk első saját könnyen beágyazható jQuery-pluginunkat. Gondolom, mind használtunk már többfélét is az oldalainkban. Általánosítva valahogy így néz ki a folyamat: belinkeljük az odalunkba a "jquery" szkriptet, a "js" fájlt, ami a plugin kódját tartalmazza, majd definiáljuk azt egy - az oldalunkon megtalálható - elemre. Tehát valami ilyesmit kell beírnunk:

<script src="http://code.jquery.com/jquery-latest.js"></script>
<script src="js/myplugin.js"></script>
<script> 
    $(document).ready(function(){
        $('#box').myPlugin();
    });
</script>

Ez azért jó, mert csak egy rövidke szkript beillesztését igényli, és bárhova beilleszthető, majd azonnal használható is. És ha már itt tartunk, jöjjön egy újabb fontos javaslat... A szkriptek futása kudarcba fulladhat olyan esetben, ha például a szóban forgó elemek még nem kerültek betöltésre az oldalon, ezért érdemes a "document" objektum "ready" eseményében elhelyezni azokat (ez akkor következik be, ha az oldal betöltődött és készen áll a használatra). A fenti kódrészlet tehát a "jquery" után betölti a "myPlugin" nevezetű programocska fájlját, majd ha a dokumentum készen áll, közli a jQuery-vel, hogy a "box" azonosítóval ellátott elemre gyakoroljon hatást a "myPlugin" néven elkeresztelt függvény.

Akkor lássuk, milyen kódnak kell szerepelnie abban a "myplugin.js" fájlban, hogy ez működjön. A plugin gyakorlatilag egy új jQuery-függvény definiálásaként testesül meg... ohh, ezt a csodaszép megfogalmazást :D

(function($){
    $.fn.myPlugin = function() {
        //ide jön a plugin kódja
    };
})(jQuery);

Ezt a kifejezést kell leírnunk így, ahogy van, csak ugye a "myPlugin" szó helyett a sajátunk elnevezését :D értelemszerűen. A biztonság kedvéért jobb, ha erre is felhívom a figyelmet: ha egy külön "js" fájlban el kezded írni a szkriptet, és figyelemmel kíséred a változásokat a weblapon, ne felejtsd el, hogy egyes böngészőbeállítások esetében nem frissül mindig újra a külső JavaScript fájl tartalma (tehát megeshet, hogy nem észlelsz változást)!

Amiről eddig még szintén nem esett szó: egy adott objektumra gyakorolt bármilyen jQuery-függvényen belüli metódus írásakor az aktuális elemre a $(this) kifejezéssel hivatkozhatunk. Ez érvényes például a "box" id-jű elemre végrehajtott "fadeIn" függvény "complete" metódusán belül (ahol ez a "this" a "box" elemet fogja jelenteni), és érvényes a plugin függvényén belül is.

$.fn.myPlugin = function() {
    $(this).css('background','black');
};

Ebben a példában tehát azt mondjuk, hogy a kiválasztott elem háttere legyen fekete. Így, ha a $('#box').myPlugin(); definíciót írjuk, akkor ez azt eredményezi, hogy a "box" objektumunk lesz fekete. Ilyen egyszerű a dolog :)

Felmerül a kérdés: mi van akkor ha olyan plugin-t akarunk írni, mely különböző beállítási opciókkal vezérelhető. Akkor ugye a definíció a HTML oldalunkban valami ilyesmi lenne:

$('#box').myPlugin({w:200,h:100});

Mondjuk olvastuk a plugin dokumentációját, ahol azt láttuk, hogy bemenő opciókkal változtatható a magassága és szélessége, mégpedig "w" és "h" nevű tulajdonságok megadásával. Ekkor ennyiben változik a történet:

$.fn.myPlugin = function(ops) {
    $(this).css('width',ops.w+'px');
    $(this).css('height',ops.h+'px');
};

Annyiban változott a "myPlugin" függvényem meghatározása, hogy a "function" kulcsszó utáni zárójelben megadtam egy "ops" nevű bemenő paramétert. Ez egy objektum lesz, tulajdonságokkal és azok értékeivel. Tehát a fenti esetben ez az "ops" két tulajdonságot fog kapni: a "w"-t (aminak értéke 2009, és a "h"-t (értéke 100). Ilyen objektum elemeire pedig úgy hivatkozunk, hogy leírjuk az objektum nevét, majd egy pont után a tulajdonság nevét. Ezek akkor már könnyen alkalmazhatóak a következő sorokban, a "this" elem CSS-tulajdonságaiból a szélességet "ops.w" pixelre, a magasságot pedig "ops.h" pixelre állítjuk.

Akkor ezekhez még egy kis apróság... mi van, ha a "myPlugin" beillesztésekor nem adok meg bemenő opciókat, vagy esetleg csak az egyiket adom meg? Mondjuk van három "div" elemem "box1", "box2", és "box3" azonosítóval és ezeket írom:

$('#box1').myPlugin();
$('#box2').myPlugin({h:300});
$('#box3').myPlugin({w:200,h:100});

Az első kettő elbukik a teszten. A harmadik működne, de ő sem fog, mert a szkript lefullad. Az ilyen esetek miatt javasolt minden ilyen jQuery függvényhez alapértelmezett értékeket megadni, amiket akkor használunk, ha a felhasználó nem adott meg semmit. Legyen mondjuk a "w" és "h" alapértelmezett értéke 50...

var defOps = {w:50,h:50};
ops = $.extend({},defOps,ops);

Egy lehetséges megoldás: létrehoztam egy "defOps" nevezetű változót, ami egy "w" és "h" tulajdonságokkal rendelkező objektum, ezeknek pedig az értékük egyaránt 50. Ezután pedig az "ops" bemenő változót felülírom egy új objektummal, amit az "extend" nevű jQuery-függvény fog legyártani nekem a "defOps" és a még eredeti "ops" objektumokból. Elég annyit tudni erről az "extend"-ről, hogy a megadott két objektumot egyesíteni fogja, tehát az általa létrehozott objektumban már a "defOps" és az "ops" elemei is szerepelni fognak, de úgy, hogy ugyanazon tulajdonságok esetében az utóbbiban (ami jelen esetben az "ops") szereplő értékek felülírják az elsőben levőket. Akkor tehát mi is zajlik? Az "extend" fogja a "defOps" minden elemét.. azaz a "w:50" és a "h:50" értékeket... ha az "ops" üres, akkor maradnak ezek és kész... ha az "ops"-ban szerepel mondjuk egy "h:300", akkor a "h" értéke változik, a "w" 50 marad továbbra is... ha pedig "w" is szerepel az "ops"-ban, akkor az is megváltozik. Így akkor lesznek alapértelmezett értékeink arra az esetre, ha nem adunk meg bemenő opciókat. Remélem, eléggé érthető volt :D Jelen esetben tehát a méretezést végrehajtó kis plugin-unk így néz ki teljes egészében:

(function($){
    $.fn.myPlugin = function(ops) {
        var defOps = {w:50,h:50};
        ops = $.extend({},defOps,ops);

        $(this).css('width',ops.w+'px');
        $(this).css('height',ops.h+'px');
    };
})(jQuery);

Ezze kész is az első jQuery-pluginunk, ami kissé gagyi, mivel csak méreteket változtat, de a lényeg, hogy már tisztában vagyunk magával a módszerrel :) Mellékelek egy kis kódot, amiben három "div"-et méretezünk ezzel a függvénnyel, opciókkal is, meg azok nélkül is (mivel ez a "plugin" még elég rövid, nem írtam külön fájlba). Ha szeretnéd kicsit átnyálazni, töltsd le itt: KLIKK

Szólj hozzá:
süti beállítások módosítása