Utilizarea utilitarului jQuery UI's Widget Factory

Pentru o lungă perioadă de timp, singura modalitate de a scrie comenzi personalizate în jQuery a fost extinderea $ .fn Spațiu de nume. Acest lucru funcționează bine pentru widget-uri simple, cu toate acestea, pe măsură ce începeți să construiți mai multe widget-uri state, devine rapid greoaie. Pentru a ajuta la procesul de construire a widget-urilor, echipa jQuery UI a introdus Fabrica de Widget, care elimină cea mai mare parte a plăcii de boot care este de obicei asociată cu gestionarea unui widget.

Fabrica de widgeturi, o parte din jQuery UI Core, oferă o modalitate orientată pe obiecte pentru a gestiona ciclul de viață al unui widget. Aceste activități pe durata ciclului de viață includ:

  • Crearea și distrugerea unui widget
  • Modificarea opțiunilor widgetului
  • Efectuarea "super"apeluri în widget-uri subclasate
  • Evenimente de notificare

Să explorăm acest API, pe măsură ce construim un simplu widget grafic pentru gloanțe.


Bullet Chart Widget

Înainte de a construi acest widget, să înțelegem câteva dintre elementele de bază ale widget-ului. Diagrama Bullet este un concept introdus de Stephen Few ca variație a diagramei barei.

Diagrama constă dintr-un set de bare și markere suprapuse unul pe altul pentru a indica performanța relativă. Există o scală cantitativă pentru a arăta intervalul real de valori. Prin stivuirea barelor și a marcatorilor în acest fel, pot fi transmise mai multe informații fără a compromite lizibilitatea. Legenda spune tipul de informații pe care le complotăm.

HTML-ul pentru această diagramă arată astfel:

 
Linia verde
0
25
50
75
100

Widgetul nostru, pe care îl vom apela jquery.bulletchart, va genera dinamic acest HTML din datele furnizate. Widgetul final poate fi vizualizat în fișierele sursă, pe care le puteți descărca de la GitHub. Apelul de a crea widget-ul ar trebui să arate așa:

 $ ('' '' '' '' '' '', ' albastru ', marcatori: [title:' Green Line ', valoare: 80, css:' verde ', title:' Minimum Threshold ', value: 50, css: 0, 25, 50, 75, 100]);

Toate valorile sunt în procente. mărimea opțiunea poate fi utilizată atunci când doriți să aveți mai multe diagrame de gloanțe așezate una lângă cealaltă, cu o dimensiune relativă. căpușe opțiunea este utilizată pentru a pune etichetele pe scară. Marcatorii și barele sunt specificate ca o serie de literali de obiecte cu titlu, valoare și css proprietăţi.


Construirea Widget-ului

Acum, când știm structura widgetului, să mergem să-l construim. Un widget este creat prin apelare $ .Widget () cu numele widget-ului și a unui obiect care conține metodele instanței. API-ul exact arată astfel:

jQuery.widget (nume [, bază], prototip)

Pentru moment, vom lucra doar cu numele și argumentele prototipului. Pentru broșură, elementul nostru de bază de widgeturi arată după cum urmează:

 $ .widget ('nt.bulletchart', optiuni: , _create: function () , _destroy: function () , _setOption: functie (cheie, valoare) );

Se recomandă să aveți întotdeauna namespace numele widget-urilor. În acest caz, folosim "nt.bulletchart“. Toate widget-urile jQuery UI se află sub "ui"spațiul de nume. Cu toate că suntem cu numelepagina widgetului, apelul pentru crearea unui widget pe un element nu include spațiul de nume. Astfel, pentru a crea o diagramă a bulletului, am sunat $ ( '# Elem'). Bulletchart ().

Proprietățile instanței sunt specificate după numele widget-ului. Prin convenție, toate metodele private ale widget-ului trebuie prefixate cu '_'. Există câteva proprietăți speciale care sunt așteptate de fabrică widget. Acestea includ Opțiuni, _crea, _distruge și _setOption.

  • Opțiuni: Acestea sunt opțiunile implicite pentru widget
  • _crea: Fabrica de widget-uri apelează această metodă prima dată când widgetul este instanțiat. Aceasta este folosită pentru a crea DOM inițial și a atașa orice manipulator de evenimente.
  • _init: În urma apelului către _crea, apelurile din fabrică _init. Acest lucru este utilizat în general pentru a reseta widget-ul la starea inițială. Odată ce un widget este creat, apelați constructorul simplu widget, de exemplu: $ .Bulletchart (), va reseta și widget-ul. Acest apel intern _init.
  • _setOption: Numit atunci când setați o opțiune pe widget, cu un apel, cum ar fi: $ ('elem') bulletchart ('opțiune', 'dimensiune', 100). Mai târziu vom vedea și alte modalități de a seta opțiuni pe widget.

Crearea DOM inițial cu _crea

Widget-ul nostru de bullet-list vine la viață în _crea metodă. Iată locul în care construim structura de bază a graficului. _crea funcția poate fi văzută mai jos. Veți observa că nu se întâmplă prea multe aici, pe lângă crearea containerului de nivel superior. Lucrarea reală de a crea DOM pentru bare, markeri și căpușe se întâmplă în _setOption metodă. Acest lucru poate părea oarecum contra-intuitiv pentru a începe, dar există un motiv valid pentru asta.

 _create: funcția () this.element.addClass ('bullet-chart'); // grafice container this._container = $ ('
') .appendTo (acest element); this._setOptions ('size': this.options.size, 'ticks': this.options.ticks, 'bars': this.options.bars, 'markers': this.options.markers);

Rețineți că barele, marcatorii și căpușele pot fi de asemenea modificate prin setarea opțiunilor pe widget. Dacă am păstrat codul pentru construcția sa în interior _crea, ne-am fi repetat înăuntru _setOption. Prin mutarea codului la _setOption și invocând-o _crea elimină duplicarea și centralizează, de asemenea, construcția.

În plus, codul de mai sus vă arată o altă modalitate de a seta opțiuni pe widget. Cu _setOptions (notați pluralul), puteți seta opțiunile mutiple dintr-o dată. Pe plan intern, fabricantul va efectua apeluri individuale _setOption pentru fiecare dintre opțiuni.

_setOption metodă

Pentru diagrama bullet, _setOption metoda este călăul. Ea se ocupă de crearea de markere, bare și căpușe, precum și orice modificări aduse acestor proprietăți. Funcționează prin eliminarea oricăror elemente existente și recrearea acestora pe baza noii valori.

_setOption metoda primește atât cheia de opțiune, cât și o valoare ca argumente. Cheia este numele opțiunii, care ar trebui să corespundă uneia dintre tastele din opțiunile implicite. De exemplu, pentru a modifica barele de pe widget, ați efectua următorul apel:

$ 'elem') bulletchart ('opțiune', 'bare', [title: 'New Marker', valoare: 50

_setOption metoda pentru bullet arata asa:

 _setOption: funcție (cheie, valoare) var self = această, prev = această opțiuni [cheie], fnMap = bars ': function () createBars; , "markeri": function () createMarkers (valoare, auto); , "căpușe": funcție () createTickBar (valoare, auto); , 'dimensiune': functie () self.element.find ('. chart-container') .css ('lățime', valoare + '%'); ; // base this._super (cheie, valoare); dacă (tastați în fnMap) fnMap [tasta] (); // eveniment de incendiu this._triggerOptionChanged (cheie, prev, valoare); 

Aici, creăm un simplu hash al opțiunii-nume la funcția corespunzătoare. Folosind acest hash, lucrăm doar la opțiuni valide și ignorăm în tăcere acelea nevalide. Mai sunt două lucruri care se întâmplă aici: un apel către _super() și declanșarea evenimentului modificat. Ne vom uita mai târziu în acest articol.

Pentru fiecare dintre opțiunile care modifică DOM, numim o metodă specifică de ajutor. Metodele de ajutor, createBars, createMarkers și createTickBar sunt specificate în afara proprietăților instanței widget. Acest lucru se datorează faptului că acestea sunt aceleași pentru toate widgeturile și nu trebuie create individual pentru fiecare instanță widget.

// Funcția de creare a funcțiilor createTickBar (ticks, widget) // Șterge widget._container.find existent ('. Tick-bar') remove (); var tickBar = $ ('
„); $ .each (căpușe, funcție (idx, bifați) var t = $ ('
') .css (' stânga ', bifați +'% '); var tl = $ ('
') .css (' stânga ', bifați +'% ') .text (bifați); tickBar.append (t); tickBar.append (tl); ); widget._container.append (tickBar); functie createMarkers (marcatori, widget) // Clear widget._container.find existent ('. marker') remove (); $ (orice marker, funcția (idx, m) var marker = $ ('
') .css (stânga: m.value +'% ') .addClass (m.css) .attr (' index-marker ', idx); widget._container.append (marcator); ); functie createBars (bare, widget) // Clear widget._container.find ('.bar') existent remove (); $. fiecare (bare, funcție (idx, bar) var bar = $ ('
') .css (left: 0, width:' 0% ') .addClass (bar.css) .attr (' bar-index ', idx) .animate (width: bar.value +'% ' ); widget._container.append (bar); );

Toate funcțiile de creație funcționează pe procente. Acest lucru asigură faptul că graficul se reface frumos atunci când redimensionați elementul care conține.

Opțiunile prestabilite

Fără opțiunile specificate la crearea widgetului, valorile implicite vor intra în joc. Acesta este rolul lui Opțiuni proprietate. Pentru broșură, opțiunile implicite arata astfel:

 $ .widget ('nt.bulletchart', opțiuni: // procentaj: 0 - 100 dimensiune: 100, // [title: 'Bară de probă', valoare: 75, css: , // [titlu: 'Marker de probă', valoare: 50, css: "], marcatori: [], // ticks - valori procentuale bifați: [0, 10, 20, 30, 40, 50, 60 , 70, 80, 90, 100], ...

Începem cu o mărime de 100%, nu există bare și marcatori și cu căpușe plasate fiecare 10%. Cu aceste valori implicite, graficul bullet ar trebui să arate astfel:

Până acum, am văzut cum să creăm widget-ul _crea și actualizarea acestuia folosind _setOption. Există o altă metodă a ciclului de viață, care va fi apelată atunci când distrugeți un widget. Acesta este _distruge metodă. Când sunați $ ( '# Elem'). Bulletchart ( 'distruge'), Fabrica de widget-uri solicită intern _distruge pe instanța dvs. widget. Widgetul este responsabil pentru eliminarea tot ceea ce a introdus în DOM. Aceasta poate include clase și alte elemente DOM adăugate în _crea metodă. Acesta este, de asemenea, un loc bun pentru a dezabona orice manipulator de eveniment. _distruge ar trebui să fie exact opusul _crea metodă.

Pentru widget-ul grafic al gloanțelor, _distruge este destul de simplu:

 _destroy: funcția () this.element.removeClass ("bullet-chart"); this.element.empty (); ,

Subclasarea, evenimentele și altele

Widgetul nostru de bullet-diagramă este aproape complet, cu excepția unei ultime caracteristici: legendă. Legenda este foarte esențială, deoarece va da mai multă semnificație markerilor și barurilor. În această secțiune vom adăuga o legendă lângă diagramă.

În loc să adăugați această caracteristică direct în widgetul bullet-chart, vom crea o subclasă, bulletchart2, care va avea suportul legendei. În acest proces, vom analiza, de asemenea, unele dintre caracteristicile interesante ale moștenirii Fabrica de Widget.

Adăugarea unei legende

Fabrica Widget acceptă subclasarea unui widget pentru a crea versiuni mai specializate. Mai devreme în articol, am văzut API pentru $ .Widget (), care avea trei argumente:

jQuery.widget (nume [, bază], prototip)

Al doilea parametru ne permite să alegem o bază pentru widget-ul nostru. Al nostru bulletchart2 widget, care subclase bulletchart, va avea următoarea semnătură:

 $ .widget ('nt.bulletchart2', $ .nt.bulletchart, opțiuni: // Afișare / ascundere legendă legendă: true, // aceasta asigură păstrarea aceluiași spațiu de nume ca widgetul de bază widgetEventPrefix: $ .nt.bulletchart .prototype.widgetEventPrefix, _create: function () ..., _destroy: function () ..., _setOption: functie (cheie, valoare) ...)

Există puține lucruri interesante pe care trebuie să le menționăm aici:

  • Continuăm să denumim numele widget-ului nostru: nt.bulletchart2.
  • Fabrica de widgeturi pune automat widget-ul sub $ .nt Spațiu de nume. Astfel, pentru a face referire la widgetul nostru anterior, am folosit $ .nt.bulletchart. În mod similar, dacă am fi la subclasa unul dintre widget-urile jQuery standard, vom face referire la acestea $ .Ui.widget nume-
  • widgetEventPrefix este o proprietate nouă pe care nu am mai văzut până acum. Vom ajunge la asta când vorbim despre evenimente. Restul proprietăților instanței ar trebui să fie familiare.

Deoarece adăugăm mai multe elemente DOM cu legenda, va trebui să ignorăm _crea metodă. Acest lucru înseamnă, de asemenea, că trebuie să ne override _distruge, pentru a fi simetric.

 _create: funcția () var self = aceasta; this._legend = $ ('
') .appendTo (acest element); ... // Apelați baza this._super (); this._setOption ("legenda", this.options.legend); , _destroy: function () this.element.find ('legenda'), empty (); ... this._super (); ,

Aici, din nou, vedem același model ca și cel de mai devreme _crea metodă. Creăm containerul pentru legenda și apoi sunăm _setOption pentru a construi restul legendei. Deoarece noi ne supunem _crea, trebuie să ne asigurăm că numim baza _crea. Facem asta cu apelul la _super. În mod similar, în _distruge, vedem de asemenea apelul către _super.

Acum s-ar putea să vă întrebați: cum face widgetul să știe ce supermetodă să apeleze cu o simplă necalificată _super invocare? Smarts-urile pentru care se află în intestinul fabricii widget. Atunci când un widget este subclasat, din fabrică se instalează _super referință diferită pentru fiecare dintre funcțiile instanței. Astfel, când sunați _super din metoda instanței dvs., indică întotdeauna corect _super metodă.

Evenimente Notificări

Deoarece tabloul bullet acceptă modificarea marcatorilor și a barelor, legenda trebuie să fie sincronizată cu aceste modificări. În plus, vom sprijini și oprirea vizibilității marcatorilor și barelor făcând clic pe elementele legendei. Acest lucru devine util când aveți mai multe marcatori și bare. Prin ascunderea câtorva elemente, puteți vedea pe ceilalți mai clar.

Pentru a susține sincronizarea legendei cu modificările aduse marcatorilor și barelor, bulletchart2 widgetul trebuie să asculte orice schimbare care se întâmplă cu acele proprietăți. Ghilimele de bază deja declanșează un eveniment de schimbare de fiecare dată când se schimbă opțiunile sale. Iată fragmentul corespunzător din widget-ul de bază:

 _setOption: funcție (cheie, valoare) var self = this, prev = this.options [cheie]; // base this._super (cheie, valoare); dacă (tastați în fnMap) fnMap [tasta] (); // eveniment de incendiu this._triggerOptionChanged (cheie, prev, valoare); , _triggerOptionChanged: funcție (optionKey, previousValue, currentValue) this._trigger ('setOption', type: 'setOption', option: optionKey, previous: previousValue, current: currentValue); 

Ori de câte ori este setată o opțiune, setOption evenimentul este declanșat. Datele evenimentului conțin valoarea precedentă și cea nouă pentru opțiunea care a fost modificată.

Ascultând acest eveniment în widgetul subclasat, puteți ști când se schimbă marcajele sau barele. bulletchart2 widget se abonează la acest eveniment în cadrul acestuia _crea metodă. Abonarea la evenimente widgeturi se realizează prin apelul către this.element.on (). this.element indică elementul jQuery pe care a fost instanțiat widgetul. Deoarece evenimentul va fi lansat pe element, abonamentul la eveniment trebuie să se întâmple în acest sens.

 _create: funcția () var self = aceasta; this._legend = $ ('
') .appendTo (acest element); // Aplică legenda privind modificările markerelor și barelor this.element.on (' bulletchart: setoption ', funcție (eveniment, date) if (data.option ===' markers ') createLegend (date.current, self.options.bars, self); altceva dacă (data.option ===' bare ') createLegend (self.options.markers, data.current, self); ); // Apelați baza this._super (); this._setOption ("legenda", this.options.legend);

Observați numele evenimentului utilizat pentru înscriere: 'Bulletchart: setoption'. Ca politică, fabrică widget atașează un prefix de eveniment pentru evenimentele declanșate de widget. În mod prestabilit, acest prefix este numele widgetului, dar acest lucru se poate schimba ușor cu widgetEventPrefix proprietate. Widget-ul de bază a bulletului se schimbă 'Bulletchart:'.

$ .widget ('nt.bulletchart', opțiuni: ..., widgetEventPrefix: 'bulletchart:' ...);

De asemenea, trebuie să ne abonați 'clic' evenimente de pe elementele legendei de ascundere / afișare a marcatorului / barei corespunzătoare. Facem asta cu _pe metodă. Această metodă preia funcția handler a hash-ului semnăturii evenimentului. Contextul handlerului (acest) este setat corect la instanța widget. Un alt confort cu _pe este că fabrica de widget-uri dezactivează în mod automat evenimentele pe care le distruge.

 _create: function () ... // Ascultați clicurile pe legendele-item this._on ('click .legend-item': funcția (event) var elt = $ (event.currentTarget), item = elt.data ('item-chart'), selector = '[' + item.type +'-index = '+ item.index +'] '; el.target.info (selector) decolorare');  );… 

Mai multe sfaturi

Fabrica de la Widget încorporează câteva alte minunate pe care ar trebui să le cunoașteți.

Referindu-se la instanța widget

Până acum, am văzut doar o modalitate de a apela metode pe widget. Am făcut asta $ ( '# Elem) .bulletchart (' metoda nume "). Totuși, acest lucru permite doar apelarea unor metode publice cum ar fi "opțiunea", "distrugerea", "on", "off". Dacă doriți să invocați aceste metode direct pe instanța widget, există o modalitate de a face acest lucru. Fabrica de widget-uri atașează instanța widget la date() obiect al elementului. Puteți obține această instanță astfel:

var widget = $ ('# elem'). date ("bulletchart"); widget.destroy ();

În plus, dacă doriți să țineți apăsat toate widgeturile de tip bulletchart din pagină, există și un selector pentru aceasta:

var allCharts = $ (': nt-bulletchart');

Unele metode speciale

Există câteva metode speciale pe care ar trebui să le cunoașteți, care sunt folosite mai rar: _getCreateEventData () și _getCreateOptions (). Primul este folosit pentru a atașa datele evenimentului pentru evenimentul "crea" care este declanșat după finalizarea apelului _crea.

_getCreateOptions este pentru atașarea de opțiuni implicite suplimentare pentru widget sau suprascrierea celor existente. Opțiunile de suprascriere a opțiunilor furnizate de utilizator returnate de această metodă, care la rândul lor suprascrie opțiunile widget implicite.


rezumat

E o înfășurare! Dacă doriți să explorați mai departe, referințele de mai jos ar trebui să vă servească destul de bine. Desigur, cea mai bună sursă de informații va fi întotdeauna codul sursă, în sine. Aș încuraja citirea sursei jquery.ui.widget de pe GitHub.

  • JQueryUI Widget Factory API
  • Prezentări pe Fabrica de Widget
Cod