jQuery vtičniki (plugini), prvi del

November 10th, 2009 by Krof Drakula Leave a reply »

jQuery je ena izmed najbolj popularnih Javascript knjižnic na spletu, poganja pa zelo širok spekter različnih spletnih strani; od medijsko bogatih, interaktivnih in efektov polnih strani, do poslovno kritičnih aplikacij z naprednimi vmesniki.

Tema te serije člankov bo pisanje vtičnikov oz. pluginov, kakor že hočete imenovati te zadeve. Začeli bomo z osnovami in se počasi premikali proti naprednejšim funkcijam knjižnice in prijemom, ki so na voljo pri razširjanju funkcionalnosti knjižnice.

Začnimo torej z osnovno strukturo, ki nam omogoča izolacijo kode:

(function($) {
  // ...
})(jQuery);

Kaj torej ta struktura počne in čemu je namenjena?

Ko pišemo plugine za katerokoli knjižnico, se moramo zavedati, da bo koda tekla v več različnih okoljih, nad katerimi pa nimamo nadzora, hkrati pa je lahko to okolje polno ostalih motečih faktorjev, ki bi ob nepravilno oblikovani kodi lahko vplivali na izvajanje naše kode. V tem primeru moramo poskrbeti, da se naša koda drži naslednjih dveh pravil:

  1. pri pisanju kode moramo zmanjšati (ali izničiti) število deklariranih in/ali uporabljenih globalnih spremenljivk,
  2. pri izvajanju naše kode uporabimo le parametre, ki jih uporabnik knjižnice eksplicitno poda in se ne zanašamo na podatke, ki jih pridobimo iz drugih globalnih spremenljivk.

Velja seveda pravilo, da lahko pravilo prekršimo, če imamo dober razlog za to, ampak tega zaenkrat ne bi posebej izpostavljal, ker gre v večini primerov samo za narobe zastavljeno rešitev na slabo definiran problem, kar se da rešiti s tehtnim premislekom.

Skratka, vrnimo se torej na primer, ki sem ga prej zapisal: kaj pravzaprav je in kako nam pomaga pri izpolnjevanju zahtev teh dveh pravil?

Odgovor na prvo vprašanje je ustvarjanje navideznega imenskega prostora znotraj okolja, kjer se nahaja naš plugin. Znotraj prvega oklepaja ustvarimo novo anonimno funkcijo (funkcije v Javascriptu so prvorazredni objekti, s katerimi lahko upravljamo isto kot z drugimi objekti), ki ima en deklariran parameter – $. Takoj za tem oklepajem se nahaja še en par oklepajev, ki vsebuje jQuery objekt – ker smo v prvem oklepaju deklarirali funkcijo, jo drugi par izvede in ji poda jQuery kot parameter.

Mogoče se na prvi pogled zdi to neintuitivno in kriptično, ampak poglejmo si primer, ki smo ga bolj vajeni pri pisanju klasične Javascript kode:

var f = function($) {
  // ...
};
f(jQuery);

S stališča kode, ki se izvaja znotraj funkcije f, je primer identičen prejšnjemu, z eno pomembno razliko – deklarirali smo spremenljivko f, da smo lahko potem izvedli funkcijo in ji podali referenco na jQuery objekt. Če sedaj namesto deklaracije spremenljivke kot funkcije damo deklaracijo funkcije v oklepaje, dobimo primer, identičen prvemu, ampak smo se znebili deklarirane spremenljivke.

Na drugi del vprašanja pa bomo odgovorili z naslednjim primerom:

var a = "zunanji";
var f = function() {
  var a = "notranji";
  document.write(a);
};
document.write(a);
f();

Tukaj imamo primer, kako Javascript išče vrednost spremenljivke, ko le-te deklariramo znotraj funkcije. Zanimivo pri Javascript je dejstvo, da funkcija nosi svoje spremenljivke s seboj, podobno kot objekt nosi svoje lastnosti, kamorkoli ga že prenesemo. Če deklariramo spremenljivko znotraj funkcije, je ta vidna samo kodi, ki se nahaja znotraj konteksta te funkcije, koda zunaj tega konteksta pa teh spremenljivk ne vidi.

V zgornjem primeru se torej v brskalniku izpiše naslednje zaporedje:

zunanji notranji

S tem smo pravzaprav spoznali način, kako v kodi uporabljati deklarirane spremenljivke, ki ne vplivajo na zunanje okolje, hkrati pa smo s tem izolirali našo kodo pred spremembami, ki bi jo lahko zunanja koda izvajala nad našimi spremenljivkami.

Torej, če to znanje sedaj apliciramo na prvi primer in ga rahlo razširimo:

(function($) {
  var debug = function(msg) {
    if(console && console.debug) {
      console.debug(msg);
    } else {
      alert(msg);
    }
  };
 
  debug("Hello world!");
})(jQuery);

V tem primeru smo sedaj deklarirali funkcijo debug, ki izpiše neko sporočilo, bodisi v konzoli, če je le-ta na voljo, ali pa kot opozorilno okno s sporočilom; pomembno pri tem je dejstvo, da če skušamo iz zunanjega okolja klicati funkcijo debug, le-to ni možno.

Ostaja pa še ena nepojasnjena lastnost tega primera – zakaj podajamo jQuery kot parameter in zakaj je parameter deklariran kot $?

Razlog je prenosljivost kode (portability, ako vam izraz ni všeč). Velikokrat se zgodi, da uporabnik meša več knjižnic na isti strani, pri čemer lahko več različnih knjižnic uporablja $ kot lastno spremenljivko (Prototype je eden izmed množice primerov). jQuery podpira možnost izvajanja v t.i. compatibility mode načinu, kjer referenco na $ povrne na prvotno vrednost, če naložimo jQuery za katerokoli drugo knjižnico.

Ker v tem primeru ne želimo pisati kodo našega plugina kot jQuery. namesto $., si s tem ustvarimo okolje znotraj funkcije, kjer $ kaže na jQuery objekt, ampak s tem ne spremenimo asociacijo spremenljivke $ v ostalih delih kode, ker ta asociacija velja lokalno in samo znotraj konteksta naše funkcije.

Tako. Za danes naj bo to dovolj. Naslednjič pa več o osnovi pisanja pluginov za jQuery – pripenjanje novih statičnih in dinamičnih funkcij na sam jQuery objekt.

Advertisement