Creare un widget scalabile usando YUI3 parte 4

Benvenuto nell'ultima parte del tutorial del widget YUI3; anche se abbiamo finito di costruire il widget, vedremo quanto è facile aggiungere funzionalità extra a un widget senza doverlo riscrivere.

Iniziamo subito!

Se la funzionalità è richiesta per un particolare modulo è un'estensione. Altrimenti, è un plugin.

Esistono due modi per aggiungere funzionalità: estensioni e plug-in. La differenza tra loro è sottile ma essenzialmente si riduce a se la funzionalità è richiesta o facoltativa. Se la funzionalità è richiesta per un particolare modulo è un'estensione, se la funzionalità è opzionale, è un plug-in.

Il plugin che aggiungeremo gestirà le funzionalità di paging per il nostro widget; forse non tutti gli sviluppatori vorranno aggiungere il paging, o alcuni potrebbero volerlo aggiungere ad alcune istanze del widget ma non ad altre. Aggiungere la funzionalità ha senso se visto in questo modo - se lo sviluppatore vuole usare il paging, può usare il plugin, ma non imponiamo agli sviluppatori di eseguire tutto il codice aggiuntivo richiesto se non lo fanno usalo.


Creare un plugin

Il processo per creare un plugin è simile a quello per la creazione di un widget, quindi molti dei costrutti che useremo qui dovrebbero essere familiari dalle parti precedenti di questo tutorial. Proprio come quando si crea un widget, usiamo YUI Inserisci() metodo come wrapper per il nostro codice:

YUI.add ("tweet-search-paging", funzione (Y) ,
  • Il nome del plugin (il nome che gli sviluppatori useranno per inizializzare il plugin) è il primo argomento del metodo
  • una funzione di callback anonimo è il secondo parametro. La funzione riceve un riferimento all'istanza YUI corrente.
  • il terzo argomento è il numero di versione del plugin e
  • il quarto è un oggetto che elenca tutte le dipendenze richieste dal plugin.

The Constructor and Namespace

Proprio come con il nostro widget, abbiamo bisogno di aggiungere un costruttore per il nostro plugin in modo che possa inizializzare e impostare lo spazio dei nomi per esso. A differenza del nostro plugin, è necessario impostare lo spazio dei nomi. Aggiungi il seguente codice all'interno della funzione anonima che abbiamo appena aggiunto:

var Node = Y.Node; function TweetSearchPaging (config) TweetSearchPaging.superclass.constructor.apply (this, arguments);  Y.namespace ("Plugin.DW"). TweetSearchPaging = TweetSearchPaging;

Iniziamo memorizzando nella cache i riferimenti a qualsiasi risorsa YUI utilizzata di frequente, che in questo caso è solo l'utilità Node. Aggiungiamo il costruttore per il plugin nello stesso modo di prima; il TweetSearchPaging il metodo plugin è definito come una funzione che accetta un oggetto di configurazione. La classe è inizializzata usando il applicare() metodo del costruttore della superclasse.

Impostiamo uno spazio dei nomi per il nostro plugin, ma questa volta lo spazio dei nomi è collegato al Collegare spazio dei nomi in contrapposizione all'oggetto YUI.


Proprietà statiche

Come prima ci sono alcune proprietà statiche che dovremmo impostare per il nostro plugin, queste sono le seguenti:

TweetSearchPaging.NAME = "tweetsearch-paging"; TweetSearchPaging.NS = "paging"; TweetSearchPaging.ATTRS = origShowUIValue: null, stringhe: valore: nextlink: "Pagina successiva", prevLink: "Pagina precedente"; TweetSearchPaging.PAGING_CLASS = Y.ClassNameManager.getClassName (TweetSearchPaging.NAME, "link"); TweetSearchPaging.LINK_TEMPLATE = "linktext";

Il nome del plugin è impostato con NOME proprietà, e anche il NS proprietà, che può essere utilizzata per fare riferimento al plug-in dall'host (l'host è il modulo o il widget a cui è connesso il plug-in).

Possiamo anche usare il ATTRIBUTI proprietà per impostare qualsiasi attributo di configurazione per il plugin. Questi attributi usano anche il modulo Attributi YUI3, proprio come gli attributi del widget, e possono essere usati allo stesso modo. Gli attributi che definiamo sono i origShowUIValue attributo, che il plugin imposterà per memorizzare se l'interfaccia utente di ricerca è stata inizialmente visualizzata nel widget quando il plugin è inizializzato. Memorizziamo anche le stringhe di testo utilizzate dal plugin, sempre per una facile internazionalizzazione.

Generiamo manualmente un nome di classe per gli elementi che creeremo usando il classNameManager, e definire il modello con cui verranno creati i nostri collegamenti di paging. Poiché esiste solo un nome e un modello di classe singola, non dobbiamo preoccuparci di usare a per ciclo.


Estendere la classe base di plugin

Proprio come abbiamo fatto durante la creazione della classe per il nostro widget, usiamo YUI estendere() metodo per estendere un modulo sottostante. Nel caso di un plugin, è il Plugin.Base classe che stiamo estendendo. Il estendere() il metodo dovrebbe apparire come segue:

Y.extend (TweetSearchPaging, Y.Plugin.Base, );

Passiamo nel nostro plugin come primo argomento al estendere() metodo, la classe che stiamo estendendo come secondo metodo e un oggetto letterale contenente la funzionalità che stiamo aggiungendo.


Metodi del ciclo di vita

I plugin ottengono inoltre l'accesso a diversi metodi del ciclo di vita che possono essere sostituiti per aggiungere codice personalizzato che il plug-in verrà eseguito per noi nei momenti appropriati. Possiamo usare usare il initializer e distruttore metodi del ciclo di vita:

initializer: function () Y.StyleSheet ("tweetSearchPagingBase"). set (". yui3-tweetsearch-paging-link", float: "right"); if (Y.one (". yui3-skin-sam")) Y.StyleSheet ("tweetSearchPagingSkin"). set (". yui3-skin-sam .yui3-tweetsearch-paging-link", marginLeft: "2 % ");  var widget = this.get ("host"); if (! widget.get ("showUI")) this.set ("_ origShowUIValue", false); widget.set ("showUI", true);  else this.set ("_ origShowUIValue", true);  this.afterHostEvent ("tweetsChange", this._afterHostTweetsChange); , destructor: function () Y.StyleSheet ("tweetSearchPagingBase"). unset (". yui3-tweetsearch-paging-link", "float"); if (Y.one (". yui3-skin-sam")) Y.StyleSheet ("tweetSearchPagingSkin"). unset (". yui3-skin-sam .yui3-tweetsearch-paging-link", "marginLeft");  if (! this.get ("_ origShowUIValue")) this.get ("host"). set ("showUI", false); . Y.one ( "yui3-tweetsearch-ui") rimuovere (); ,

Il initializer il metodo verrà eseguito quando il plugin viene inizializzato; in questo metodo creiamo per la prima volta il foglio di stile base di cui il nostro plugin ha bisogno. Potremmo semplicemente includere un file CSS separato, ma poiché abbiamo bisogno solo di una singola regola di stile, è opportuno ridurre il numero di file che qualsiasi sviluppatore di implementazione deve gestire.

Usiamo YUI Foglio di stile() metodo per creare il nostro nuovo foglio di stile. Questo metodo accetta un singolo argomento che è il nome del nuovo foglio di stile. Quindi usiamo il impostato() metodo per impostare gli stili che richiediamo. Il impostato() il metodo accetta due argomenti; il primo è il selettore che vogliamo scegliere come target e il secondo è un oggetto letterale contenente gli stili che devono essere applicati al selettore, che in questo caso è semplicemente float: giusto.

Controlliamo quindi se il .yui3-sam-pelle selettore esiste nel documento; se lo fa, andiamo avanti e creiamo un foglio di stile skin per il plugin. Se la skin sam non è in uso, non vale la pena creare alcun skin style in quanto lo sviluppatore implementatore avrà senza dubbio stili personalizzati che potrebbero voler applicare.

Successivamente, dobbiamo verificare se il ShowUI l'attributo del widget è abilitato. Possiamo ottenere l'accesso alla classe host a cui è collegato il plugin utilizzando l'attributo host incorporato, che utilizzeremo ottenere() metodo proprio come qualsiasi altro attributo. Il ShowUI l'attributo del widget deve essere abilitato se viene utilizzato il plugin, quindi se l'attributo non è impostato originariamente lo impostiamo qui.

Quando utilizzi i plug-in, abbiamo la possibilità di rilevare e reagire a qualsiasi modifica degli attributi dell'host. Aggiungiamo un gestore di modifiche agli attributi per quando il tweets l'attributo del nostro widget cambia usando il afterHostEvent () metodo. Questo metodo accetta due argomenti; il primo è l'attributo da monitorare, il secondo è il metodo da eseguire quando l'attributo cambia.

La funzione distruttore viene chiamata quando il plugin viene distrutto; questo metodo è usato per riordinare dopo il plugin. Eventuali modifiche alla pagina devono essere invertite, così come eventuali modifiche apportate al widget. Le modifiche che apportiamo alla pagina che dobbiamo annullare sono l'aggiunta dei fogli di stile, quindi questo è ciò che facciamo per primo. Gli stili del foglio di stile possono essere rimossi usando il unset () metodo; questo metodo porta il selettore a disinserire come primo argomento e gli stili da disinserire come secondo argomento.

Controlliamo quindi se il _origShowUiValue la variabile è impostata su vero o falso; se la variabile è impostata su falso sappiamo che dobbiamo ripristinare il suo valore, quindi impostiamo l'attributo dell'host su falso. Se il valore è stato modificato e l'interfaccia utente è stata mostrata dal plug-in, la nascondiamo in modo che il widget venga riportato allo stato originale.


Attribute Change-Handlers

In questo plug-in utilizziamo solo un singolo metodo di gestione delle modifiche degli attributi; quello che viene chiamato quando il Tweet attributo dell'host cambia. Questo metodo dovrebbe apparire come segue:

_afterHostTweetsChange: function () var widget = this.get ("host"); if (widget.get ("tweets"). next_page) var nextPageUrl = widget.get ("tweets"). next_page, nextLink = Node.create (Y.substitute (TweetSearchPaging.LINK_TEMPLATE, linkclass: TweetSearchPaging.PAGING_CLASS, url : ["http://search.twitter.com/search.json", nextPageUrl, "& callback = callback"]. join (""), linktext: this.get ("stringhe"). nextLink)) ; if (this._nextLinkNode) this._nextLinkNode.remove ();  this._nextLinkNode = widget._uiNode.appendChild (nextLink); Y.on ("clic", Y.bind (this._getPage, this), this._nextLinkNode);  if (widget.get ("tweets"). previous_page) var prevPageUrl = widget.get ("tweets"). previous_page, prevLink = Node.create (Y.substitute (TweetSearchPaging.LINK_TEMPLATE, linkclass: TweetSearchPaging.PAGING_CLASS, url: ["http://search.twitter.com/search.json", prevPageUrl, "& callback = callback"]. join (""), linktext: this.get ("stringhe"). prevLink) ); if (this._prevLinkNode) this._prevLinkNode.remove ();  this._prevLinkNode = widget._uiNode.appendChild (prevLink); Y.on ("clic", Y.bind (this._getPage, this), this._prevLinkNode); ,

Per prima cosa memorizziamo nuovamente un riferimento alla classe ospitante poiché dovremo farvi riferimento più volte. Ora dobbiamo determinare se ci sono o meno risultati paginati nella risposta di Twitter e se ci sono pagine precedenti o successive di risultati. La cosa interessante della risposta di Twitter è che manterrà automaticamente la pagina dei risultati che stiamo visualizzando se ci sono più risultati del numero configurato di risultati per pagina.

Se c'è un'altra pagina di risultati dopo la pagina corrente, ci sarà una proprietà nell'oggetto di risposta JSON chiamato pagina successiva. Allo stesso modo, se c'è una pagina precedente di risultati, ci sarà a pagina precedente proprietà. Tutto ciò che dobbiamo fare è verificare la presenza di queste proprietà e creare collegamenti alla pagina successiva e alla pagina precedente.

I collegamenti vengono creati utilizzando il modello che abbiamo archiviato in precedenza nella classe del plugin e vengono forniti i generati NOME DELLA CLASSE. Il pagina successiva e pagina precedente oggetti di risposta sono ottenuti da Twitter utilizzando un URL con uno speciale ID nella stringa di query. Quando creiamo questi nuovi nodi, l'URL fornito in queste proprietà viene aggiunto a ciascun link rispettivamente. I collegamenti sono aggiunti al searchUI nodo dell'host e per essi vengono aggiunti i gestori di clic. Questi gestori di clic indicano un metodo di utilità chiamato _getPage (). Aggiungeremo questo metodo successivamente.


Metodi prototipo personalizzati

Proprio come quando si crea il widget, possiamo aggiungere qualsiasi numero di metodi prototipo personalizzati che vengono utilizzati per eseguire qualsiasi codice personalizzato richiesto dal nostro plug-in in risposta all'interazione dell'utente o alle modifiche dello stato. In questo plugin, abbiamo solo bisogno di aggiungere un singolo metodo, che dovrebbe apparire come segue:

_getPage: function (e) var widget = this.get ("host"); e.preventDefault (); widget._viewerNode.empty () nascondere ().; widget._loadingNode.show (); widget.set ("baseURL", e.target.get ("href")), widget._retrieveTweets (); . Y.all ( "yui3-tweetsearch-paging-link") rimuovere (); 

Innanzitutto, memorizziamo un riferimento alla classe host e quindi impediamo il collegamento di paging su cui è stato fatto clic. Quindi rimuoviamo eventuali tweet esistenti nel visualizzatore del widget e mostriamo il nodo di caricamento. Ricorda, ogni link di paging (o qualsiasi link esiste se siamo nella prima o nell'ultima pagina) avrà l'URL che recupera la pagina successiva (o precedente) dei risultati, quindi recuperiamo questo URL dal link href e impostare il baseURL attributo del widget. Fatto questo, chiamiamo il _retrieveTweets () metodo del nostro widget per richiedere la pagina successiva. Infine, rimuoviamo i collegamenti di paging correnti poiché verranno ricreati se ci sono pagine successive o precedenti incluse nel nuovo oggetto risposta.


Usando il plugin

Ora che abbiamo creato il nostro plugin possiamo vedere quanto sia facile da usare con il nostro widget. Dobbiamo aggiornare il nostro uso() metodo per usare il nostro plugin e chiamare il spina() metodo prima del rendering del widget:

Utilizzare YUI () ("tweet-search", "tweet-search-paging", function (Y) var myTweetSearch = new Y.DW.TweetSearch (srcNode: "#ts"); myTweetSearch.plug (Y .Plugin.DW.TweetSearchPaging); myTweetSearch.render (););

Il spina() metodo collega il nostro plugin, che è accessibile tramite il Collegare namespace e qualsiasi spazio dei nomi che abbiamo specificato durante la definizione della classe del plugin. Ora quando eseguiamo la pagina, dovremmo avere collegamenti di paging nella parte inferiore del widget:

Una delle caratteristiche del nostro plugin (proprio come il nostro widget) è l'internazionalizzazione facile; per fornire stringhe per il plugin in un'altra lingua (o sovrascrivere qualsiasi attributo se un plugin), possiamo semplicemente fornire l'oggetto di configurazione come secondo argomento al spina() metodo, per esempio

myTweetSearch.plug (Y.Plugin.DW.TweetSearchPaging, stringhe: nextLink: "Página Siguiente", prevLink: "Página Anterior");

Il link di paging dovrebbe ora apparire così:


Avvolgendo

In questa parte del tutorial, abbiamo osservato quanto sia facile creare un plug-in che può essere utilizzato per migliorare i widget esistenti o altri moduli. Questo è un ottimo modo per fornire funzionalità aggiuntive che non sono essenziali, che gli sviluppatori possono scegliere di includere se lo desiderano. Abbiamo visto che la struttura di un plugin è simile a quella di un widget su una scala più piccola.

In questo esempio, il plugin era strettamente collegato al nostro widget; ad esempio, non sarebbe possibile utilizzare il plugin con un widget diverso. Questo non deve essere il caso e i plugin, così come le estensioni possono essere molto più liberamente accoppiati per aggiungere o migliorare la funzionalità per una gamma di diversi moduli.

Questo ora ci porta alla fine della serie sui widget YUI3; Spero di aver dato qualche idea dei potenti meccanismi messi in atto dalla libreria che ci consentono di creare facilmente widget scalabili e robusti che sfruttano i punti di forza della biblioteca.

Facci sapere cosa ne pensi nella sezione commenti qui sotto e ti ringrazio tanto per la lettura!