Bienvenue dans la dernière partie du tutoriel sur les widgets YUI3; bien que nous ayons fini de construire le widget, nous allons voir à quel point il est facile d'ajouter des fonctionnalités supplémentaires à un widget sans avoir à le réécrire..
Commençons tout de suite!
Si la fonctionnalité est requise pour un module particulier, il s'agit d'une extension. Sinon, c'est un plugin.
Il y a deux façons d'ajouter des fonctionnalités - des extensions et des plugins. La différence entre eux est subtile mais se résume essentiellement au fait que la fonctionnalité soit requise ou non. Si la fonctionnalité est requise pour un module particulier, c'est une extension, si la fonctionnalité est optionnelle, c'est un plugin.
Le plugin que nous ajouterons gérera la fonctionnalité de pagination de notre widget; peut-être que tous les développeurs ne voudront pas ajouter de pagination ou que certains voudront l’ajouter à certaines instances du widget mais pas à d’autres. L'ajout de la fonctionnalité est logique vu de cette façon: si le développeur souhaite utiliser la pagination, il peut utiliser le plug-in, mais nous ne forçons pas les développeurs à exécuter tout le code supplémentaire nécessaire s'ils ne le font pas. utilise le.
Le processus de création d'un plugin est similaire à celui de la création d'un widget. Par conséquent, bon nombre des constructions que nous allons utiliser ici devraient être familières des parties précédentes de ce didacticiel. Tout comme lors de la création d'un widget, nous utilisons YUI ajouter()
méthode comme un wrapper pour notre code:
YUI.add ("recherche sur Twitter", fonction (Y) ,
Comme avec notre widget, nous devons ajouter un constructeur pour notre plugin afin qu'il puisse initialiser et définir l'espace de noms correspondant. Contrairement à notre plugin, la définition de l'espace de nom est obligatoire. Ajoutez le code suivant dans la fonction anonyme que nous venons d'ajouter:
var Node = Y.Node; fonction TweetSearchPaging (config) TweetSearchPaging.superclass.constructor.apply (this, arguments); Y.namespace ("Plugin.DW"). TweetSearchPaging = TweetSearchPaging;
Nous commençons par mettre en cache les références aux ressources YUI fréquemment utilisées, qui dans ce cas ne sont que l’utilitaire Node. Nous ajoutons le constructeur du plugin de la même manière que précédemment; la TweetSearchPaging
La méthode plugin est définie comme une fonction qui accepte un objet de configuration. La classe est initialisée en utilisant le appliquer()
méthode du constructeur de la superclasse.
Nous avons défini un espace de noms pour notre plugin, mais cette fois-ci, l’espace de noms est attaché au Brancher
espace de noms par opposition à l'objet YUI.
Comme auparavant, il y a quelques propriétés statiques que nous devrions définir pour notre plugin, celles-ci sont les suivantes:
TweetSearchPaging.NAME = "tweetsearch-paging"; TweetSearchPaging.NS = "paging"; TweetSearchPaging.ATTRS = origShowUIValue: null, chaînes: valeur: nextLink: "page suivante", prevLink: "page précédente"; TweetSearchPaging.PAGING_CLASS = Y.ClassNameManager.getClassName (TweetSearchPaging.NAME, "lien"); TweetSearchPaging.LINK_TEMPLATE = "linktext";
Le nom du plugin est défini avec le PRÉNOM
la propriété, et aussi la NS
propriété, qui peut être utilisée pour faire référence au plugin à partir de l'hôte (l'hôte est le widget ou le module auquel le plugin est connecté).
Nous pouvons aussi utiliser le ATTRS
propriété pour définir les attributs de configuration du plug-in. Ces attributs utilisent également le module Attributs YUI3, tout comme les attributs de widget, et peuvent être utilisés de la même manière. Les attributs que nous définissons sont les origShowUIValue
attribut, que le plug-in va définir pour stocker si l'interface utilisateur de recherche a été initialement affichée dans le widget lors de l'initialisation du plug-in. Nous stockons également les chaînes de texte utilisées par le plugin, encore une fois pour faciliter l'internationalisation.
Nous générons manuellement un nom de classe pour les éléments que nous allons créer en utilisant le classNameManager
, et définir le modèle avec lequel nos liens de pagination seront créés. Comme il n’existe qu’un seul nom de classe et un seul modèle, nous n’avons pas à nous soucier de l’utilisation d’un pour la boucle
.
Tout comme nous l'avons fait lors de la création de la classe pour notre widget, nous utilisons YUI étendre()
méthode pour étendre un module sous-jacent. Dans le cas d'un plugin, c'est le Plugin.Base
classe que nous étendons. le étendre()
méthode devrait apparaître comme suit:
Y.extend (TweetSearchPaging, Y.Plugin.Base, );
Nous passons dans notre plugin comme premier argument de la étendre()
méthode, la classe que nous étendons en tant que deuxième méthode et un littéral d'objet contenant la fonctionnalité que nous ajoutons.
Les plugins ont également accès à plusieurs méthodes de cycle de vie qui peuvent être remplacées pour ajouter un code personnalisé que le plugin exécutera pour nous aux moments appropriés. Nous pouvons utiliser les initialiseur
et destructeur
méthodes du cycle de vie:
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 ("hôte"); if (! widget.get ("showUI")) this.set ("_ origShowUIValue", false); widget.set ("showUI", true); else this.set ("_ origShowUIValue", true); this.afterHostEvent ("tweetsChange", this._afterHostTweetsChange); , destructeur: 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 ("hôte"). set ("showUI", false); Y.one (". Yui3-tweetsearch-ui"). Remove (); ,
le initialiseur
La méthode sera exécutée à l’initialisation du plugin; Dans cette méthode, nous créons d’abord la feuille de style de base dont notre plugin a besoin. Nous pourrions simplement inclure un fichier CSS séparé, mais comme nous n’avons besoin que d’une règle de style unique, il est logique de réduire le nombre de fichiers que tout développeur qui met en œuvre doit gérer..
Nous utilisons les YUI Feuille de style ()
méthode pour créer notre nouvelle feuille de style. Cette méthode accepte un seul argument qui est le nom de la nouvelle feuille de style. Nous utilisons ensuite le ensemble()
méthode pour définir les styles dont nous avons besoin. le ensemble()
méthode prend deux arguments; le premier est le sélecteur que nous souhaitons cibler et le second est un littéral d'objet contenant les styles à appliquer au sélecteur, qui dans ce cas est simplement Flotter à droite
.
Nous vérifions ensuite si le .yui3-sam-skin
le sélecteur existe dans le document; si c'est le cas, nous allons ensuite créer une feuille de style de peau pour le plugin. Si le skin sam n'est pas utilisé, il est inutile de créer des styles de skin, car le développeur chargé de la mise en œuvre disposera certainement de styles personnalisés qu'il pourra souhaiter appliquer..
Ensuite, nous devons vérifier si le showUI
L'attribut du widget est activé. Nous pouvons avoir accès à la classe d’hôte à laquelle le plugin est attaché en utilisant l’attribut hôte intégré, que nous obtenons en utilisant obtenir()
méthode comme tout autre attribut. le showUI
l'attribut du widget doit être activé si le plugin est utilisé, donc si l'attribut n'est pas défini à l'origine, nous le définissons ici.
Lors de l'utilisation de plugins, nous avons la possibilité de détecter et de réagir à tout changement d'attribut de l'hôte. Nous ajoutons un attribut change-handler pour le moment où tweets
attribut de nos changements de widget en utilisant le afterHostEvent ()
méthode. Cette méthode accepte deux arguments. le premier est l'attribut à surveiller, le second est la méthode à exécuter lorsque l'attribut change.
La fonction de destructeur est appelée lorsque le plugin est détruit. cette méthode est utilisée pour ranger après le plugin. Toute modification apportée à la page doit être annulée, ainsi que toute modification apportée au widget. Les modifications que nous apportons à la page que nous devons annuler sont l'ajout de feuilles de style. C'est ce que nous faisons en premier. Les styles de feuille de style peuvent être supprimés à l’aide des touches non défini ()
méthode; cette méthode prend le sélecteur à désactiver en tant que premier argument et les styles à désactiver en tant que second argument.
Nous vérifions ensuite si le _origShowUiValue
variable est définie sur vrai
ou faux
; si la variable est définie sur faux
nous savons que nous devons rétablir sa valeur, nous avons donc redéfini l'attribut de l'hôte sur faux
. Si la valeur a été modifiée et que l'interface utilisateur a été affichée par le plug-in, nous la masquons pour que le widget revienne à son état d'origine..
Nous n'utilisons qu'une méthode d'attribution de changement d'attribut unique dans ce plugin; celui qui est appelé quand le tweet
attribut de l'hôte change. Cette méthode devrait apparaître comme suit:
_afterHostTweetsChange: function () var widget = this.get ("hôte"); 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 ("chaînes"). nextLink)) ; if (this._nextLinkNode) this._nextLinkNode.remove (); this._nextLinkNode = widget._uiNode.appendChild (nextLink); Y.on ("cliquez sur", 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 ("chaînes"). prevLink) ) if (this._prevLinkNode) this._prevLinkNode.remove (); this._prevLinkNode = widget._uiNode.appendChild (prevLink); Y.on ("cliquez sur", Y.bind (this._getPage, this), this._prevLinkNode); ,
Nous stockons d'abord une référence à la classe hôte une fois de plus, car nous devrons y faire référence plusieurs fois. Nous devons maintenant déterminer s'il y a des résultats paginés dans la réponse de Twitter et s'il y a des pages de résultats précédentes ou suivantes. La bonne chose à propos de la réponse de Twitter est qu’elle conservera automatiquement la page de résultats que nous consultons s’il ya plus de résultats que le nombre configuré de résultats par page..
S'il existe une autre page de résultats après la page en cours, il y aura une propriété dans l'objet de réponse JSON appelée page suivante
. De même, s’il existe une page précédente de résultats, il y aura une page précédente
propriété. Il suffit de vérifier la présence de ces propriétés et de créer des liens de page suivante et de page précédente..
Les liens sont créés en utilisant le modèle que nous avons stocké précédemment dans la classe de plugin, et sont générés NOM DU COURS
. le page suivante
et page précédente
les objets de réponse sont obtenus à partir de Twitter en utilisant une URL avec un ID
dans la chaîne de requête. Lorsque nous créons ces nouveaux nœuds, l'URL fournie dans ces propriétés est ajoutée à chaque lien, respectivement. Les liens sont ajoutés à la searchUI
noeud de l'hôte, et les gestionnaires de clics sont ajoutés pour eux. Ces gestionnaires de clics pointent vers une méthode utilitaire appelée _getPage ()
. Nous allons ajouter cette méthode à côté.
Tout comme lors de la création du widget, nous pouvons ajouter un nombre quelconque de méthodes de prototype personnalisées utilisées pour exécuter tout code personnalisé requis par notre plug-in en réponse à une interaction utilisateur ou à des changements d'état. Dans ce plugin, il suffit d'ajouter une seule méthode, qui devrait apparaître comme suit:
_getPage: function (e) var widget = this.get ("hôte"); e.preventDefault (); widget._viewerNode.empty (). hide (); widget._loadingNode.show (); widget.set ("baseURL", e.target.get ("href")), widget._retrieveTweets (); Y.all (". Yui3-tweetsearch-paging-link"). Remove ();
Premièrement, nous stockons une référence à la classe d’hôte, puis nous ne suivons pas le lien de pagination sur lequel on a cliqué. Nous supprimons ensuite les tweets existants dans la visionneuse du widget et affichons le nœud de chargement. Rappelez-vous que chaque lien de pagination (ou le lien existant si nous sommes sur la première ou la dernière page) aura l'URL qui récupère la page de résultats suivante (ou précédente), nous récupérons donc cette URL à partir du lien. href
et mettre le baseURL
attribut du widget. Une fois que cela est fait, nous appelons le _retrieveTweets ()
méthode de notre widget pour demander la page suivante. Enfin, nous supprimons les liens de pagination actuels, car ils seront recréés si des pages suivantes ou précédentes sont incluses dans le nouvel objet de réponse..
Maintenant que nous avons créé notre plugin, nous pouvons voir à quel point il est facile à utiliser avec notre widget. Nous devons mettre à jour notre utilisation()
méthode pour utiliser notre plugin, et appelez le prise de courant()
méthode avant le rendu du widget:
YUI (). Use ("tweet-search", "tweet-search-paging", fonction (Y) var myTweetSearch = new Y.DW.TweetSearch (srcNode: "#ts"); myTweetSearch.plug (Y .Plugin.DW.TweetSearchPaging); myTweetSearch.render (););
le prise de courant()
méthode connecte notre plugin, qui est accessible via le Brancher
namespace et quel que soit l'espace de nommage que nous avons spécifié lors de la définition de la classe du plugin. Maintenant, quand nous courons la page, nous devrions avoir des liens de pagination au bas du widget:
Une des caractéristiques de notre plugin (tout comme notre widget) est une internationalisation facile. afin de fournir des chaînes pour le plugin dans une autre langue (ou de remplacer tout attribut s'il s'agit d'un plugin), nous pouvons simplement fournir l'objet de configuration comme second argument du prise de courant()
méthode, par exemple:
myTweetSearch.plug (Y.Plugin.DW.TweetSearchPaging, chaînes: nextLink: "Página Siguiente", prevLink: "Página Anterior");
Le lien de pagination devrait maintenant ressembler à ceci:
Dans cette partie du didacticiel, nous avons expliqué à quel point il est facile de créer un plug-in pouvant être utilisé pour améliorer des widgets existants ou d'autres modules. C'est un excellent moyen de fournir des fonctionnalités supplémentaires qui ne sont pas essentielles, que les développeurs peuvent choisir d'inclure s'ils le souhaitent. Nous avons vu que la structure d'un plugin est similaire à celle d'un widget à plus petite échelle.
Dans cet exemple, le plugin était très étroitement lié à notre widget; il ne serait pas possible d'utiliser le plugin avec un widget différent, par exemple. Cela ne doit pas forcément être le cas et les plugins, de même que les extensions peuvent être couplées de manière beaucoup plus souple pour ajouter ou améliorer des fonctionnalités pour une gamme de modules différents.
Cela nous amène maintenant à la fin de la série sur les widgets YUI3; J'espère avoir donné un aperçu des puissants mécanismes mis en place par la bibliothèque qui nous permettent de créer facilement des widgets robustes et évolutifs qui exploitent les atouts de la bibliothèque..
Dites-nous ce que vous pensez dans la section commentaires ci-dessous et merci beaucoup de votre lecture!