Crear un widget escalable utilizando YUI3 Parte 4

Bienvenido a la última parte del tutorial del widget YUI3; Aunque en realidad hemos terminado de construir el widget, veremos lo fácil que es agregar funcionalidad adicional a un widget sin tener que volver a escribirlo..

Empecemos de inmediato!

Si la funcionalidad es necesaria para un módulo en particular, es una extensión. De lo contrario, es un plugin..

Hay dos formas de agregar funcionalidad: extensiones y complementos. La diferencia entre ellos es sutil, pero esencialmente se reduce a si la funcionalidad es obligatoria o no. Si la funcionalidad es necesaria para un módulo en particular, es una extensión, si la funcionalidad es opcional, es un complemento.

El complemento que agregaremos manejará la funcionalidad de paginación de nuestro widget; tal vez no todos los desarrolladores quieran agregar paginación, o algunos querrán agregarlo a algunas instancias del widget pero no a otras. Agregar la funcionalidad tiene sentido cuando se ve de esta manera: si el desarrollador desea usar la paginación, puede usar el complemento, pero no obligamos a los desarrolladores a ejecutar todo el código adicional que se requiere si no van a usalo.


Creando un complemento

El proceso para crear un complemento es similar al de crear un widget, por lo que muchas de las construcciones que usaremos aquí deberían ser familiares de las partes anteriores de este tutorial. Al igual que al crear un widget, utilizamos YUI añadir() Método como envoltorio para nuestro código:

YUI.add ("tweet-search-paging", función (Y) ,
  • El nombre del complemento (el nombre que los desarrolladores usarán para inicializar el complemento) es el primer argumento del método.
  • Una función de devolución de llamada anónima es el segundo parámetro. La función recibe una referencia a la instancia YUI actual.
  • El tercer argumento es el número de versión del complemento y
  • el cuarto es un objeto que enumera las dependencias requeridas por el complemento.

El constructor y espacio de nombres

Al igual que con nuestro widget, necesitamos agregar un constructor para nuestro complemento para que pueda inicializarse y establecer el espacio de nombres para él. A diferencia de nuestro complemento, es necesario configurar el espacio de nombres. Agregue el siguiente código dentro de la función anónima que acabamos de agregar:

Nodo var = Y.Nodo; función TweetSearchPaging (config) TweetSearchPaging.superclass.constructor.apply (esto, argumentos);  Y.namespace ("Plugin.DW"). TweetSearchPaging = TweetSearchPaging;

Comenzamos por almacenar en caché las referencias a cualquier recurso YUI de uso frecuente, que en este caso es solo la utilidad Node. Añadimos el constructor para el complemento de la misma manera que antes; la TweetSearchPaging El método de complemento se define como una función que acepta un objeto de configuración. La clase se inicializa usando el aplicar() Método del constructor de la superclase..

Establecemos un espacio de nombres para nuestro complemento, pero esta vez el espacio de nombres se adjunta a la Enchufar espacio de nombres en oposición al objeto YUI.


Propiedades estáticas

Como antes, hay algunas propiedades estáticas que deberíamos configurar para nuestro complemento, estas son las siguientes:

TweetSearchPaging.NAME = "tweetsearch-paging"; TweetSearchPaging.NS = "paginación"; TweetSearchPaging.ATTRS = origShowUIValue: null, strings: value: nextLink: "Next Page", prevLink: "Previous Page"; TweetSearchPaging.PAGING_CLASS = Y.ClassNameManager.getClassName (TweetSearchPaging.NAME, "link"); TweetSearchPaging.LINK_TEMPLATE = "linktext";

El nombre del complemento se establece con el NOMBRE propiedad, y también la NS propiedad, que se puede utilizar para referirse al complemento desde el host (el host es el widget o módulo al que está conectado el complemento) clase.

También podemos utilizar el ATTRS Propiedad para establecer cualquier atributo de configuración para el complemento. Estos atributos también utilizan el módulo de atributos YUI3, al igual que los atributos del widget, y se pueden usar de la misma manera. Los atributos que definimos son los origShowUIValue atributo, que el complemento establecerá para almacenar si la IU de búsqueda se mostró inicialmente en el widget cuando se inicializa el complemento. También almacenamos las cadenas de texto utilizadas por el complemento, una vez más para facilitar la internacionalización..

Generamos manualmente un nombre de clase para los elementos que crearemos usando el classNameManager, y define la plantilla con la que se crearán nuestros enlaces de paginación. Como solo hay un único nombre de clase y plantilla, no tenemos que preocuparnos por usar un en bucle.


Extendiendo la Clase Base del Plugin

Al igual que hicimos al crear la clase para nuestro widget, usamos YUI's ampliar() Método para extender un módulo subyacente. En el caso de un plugin, es el Plugin.Base clase que estamos extendiendo. los ampliar() El método debe aparecer como sigue:

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

Pasamos en nuestro plugin como el primer argumento al ampliar() método, la clase que estamos extendiendo como segundo método y un objeto literal que contiene la funcionalidad que estamos agregando.


Métodos del ciclo de vida

Los complementos también tienen acceso a varios métodos de ciclo de vida que se pueden anular para agregar el código personalizado que el complemento ejecutará para nosotros en el momento adecuado. Podemos hacer uso del uso del inicializador y incinerador de basuras Métodos del ciclo de vida:

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"). Remove (); ,

los inicializador el método se ejecutará cuando se inicialice el complemento; En este método, primero creamos la hoja de estilo base que nuestro complemento necesita. Simplemente podríamos incluir un archivo CSS separado, pero como solo necesitamos una regla de estilo única, tiene sentido reducir la cantidad de archivos que cualquier desarrollador de implementación necesita administrar.

Utilizamos YUI's Hoja de estilo () Método para crear nuestra nueva hoja de estilo. Este método acepta un solo argumento que es el nombre de la nueva hoja de estilo. Entonces usamos el conjunto() Método para configurar los estilos que requerimos. los conjunto() método toma dos argumentos; el primero es el selector al que queremos apuntar y el segundo es un objeto literal que contiene los estilos que deben aplicarse al selector, que en este caso es simplemente flotar derecho.

Luego verificamos si el .yui3-sam-skin selector existe en el documento; Si lo hace, seguimos adelante y creamos una hoja de estilo de máscara para el complemento. Si la máscara sam no está en uso, no vale la pena crear estilos de máscara, ya que el desarrollador de la implementación sin duda tendrá estilos personalizados que tal vez deseen aplicar..

A continuación, tenemos que comprobar si el showUI El atributo del widget está habilitado. Podemos obtener acceso a la clase de host a la que se adjunta el complemento mediante el uso del atributo de host incorporado, que obtenemos al usar el obtener() Método al igual que cualquier otro atributo. los showUI el atributo del widget debe estar habilitado si se usa el complemento, por lo tanto, si el atributo no se estableció originalmente, lo establecemos aquí.

Cuando usamos complementos, tenemos la capacidad de detectar y reaccionar a cualquier cambio de atributos del host. Agregamos un atributo controlador de cambio para el cuando el tweets atributo de nuestros cambios de widgets utilizando el afterHostEvent () método. Este método acepta dos argumentos; el primero es el atributo a monitorear, el segundo es el método para ejecutar cuando el atributo cambia.

La función destructor se llama cuando se destruye el complemento; Este método se utiliza para ordenar después del complemento. Cualquier cambio en la página debe revertirse, así como cualquier cambio que realicemos en el widget. Los cambios que hacemos en la página que tenemos que deshacer son la adición de las hojas de estilo, así que esto es lo que hacemos primero. Los estilos de hoja de estilo se pueden eliminar utilizando el desarmar () método; Este método hace que el selector se desactive como primer argumento y los estilos que se desarmen como segundo argumento..

Luego verificamos si el _origShowUiValue variable se establece en cierto o falso; si la variable se establece en falso sabemos que tenemos que revertir su valor, por lo que establecemos el atributo del host de nuevo a falso. Si se cambió el valor y el complemento mostró la interfaz de usuario, lo ocultamos para que el widget vuelva a su estado original.


Atributos de los controladores de cambio

Solo usamos un método de manejo de cambios de un solo atributo en este complemento; el que se llama cuando el Pío atributo del host cambia. Este método debe aparecer como sigue:

_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 ("strings"). 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 ("strings"). prevLink) ); if (this._prevLinkNode) this._prevLinkNode.remove ();  this._prevLinkNode = widget._uiNode.appendChild (prevLink); Y.on ("click", Y.bind (this._getPage, this), this._prevLinkNode); ,

Primero almacenamos una referencia a la clase de host una vez más, ya que necesitaremos referirnos varias veces. Ahora debemos determinar si hay resultados paginados en la respuesta de Twitter y si hay páginas de resultados anteriores o siguientes. Lo bueno de la respuesta de Twitter es que mantendrá automáticamente la página de resultados que estamos viendo si hay más resultados que el número configurado de resultados por página..

Si hay otra página de resultados después de la página actual, habrá una propiedad en el objeto de respuesta JSON llamado siguiente página. Del mismo modo, si hay una página anterior de resultados, habrá una pagina anterior propiedad. Todo lo que necesitamos hacer es verificar la presencia de estas propiedades y crear los enlaces de la página siguiente y la página anterior.

Los enlaces se crean utilizando la plantilla que almacenamos anteriormente en la clase de plugin, y reciben la información generada. NOMBRE DE LA CLASE. los siguiente página y pagina anterior los objetos de respuesta se obtienen de Twitter mediante una URL con un especial CARNÉ DE IDENTIDAD en la cadena de consulta. Cuando creamos estos nuevos nodos, la URL proporcionada en estas propiedades se agrega a cada enlace respectivamente. Los enlaces se adjuntan a la búsquedaUI nodo del host, y los controladores de clic se agregan para ellos. Estos controladores de clic apuntan a un método de utilidad llamado _getPage (). Agregaremos este método a continuación.


Métodos de prototipo personalizados

Al igual que al crear el widget, podemos agregar cualquier número de métodos prototipo personalizados que se utilizan para ejecutar cualquier código personalizado requerido por nuestro complemento en respuesta a la interacción del usuario o cambios de estado. En este complemento, solo necesitamos agregar un método único, que debe aparecer como sigue:

_getPage: function (e) var widget = this.get ("host"); 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 (); 

Primero, almacenamos una referencia a la clase de host y luego evitamos que se siga el enlace de paginación en el que se hizo clic. Luego eliminamos todos los tweets existentes en el visor del widget y mostramos el nodo de carga. Recuerde, cada enlace de paginación (o el que exista si estamos en la primera o la última página) tendrá la URL que recupera la página de resultados siguiente (o anterior), por lo que recuperamos esta URL de los enlaces. href y establecer el baseURL Atributo del widget. Una vez hecho esto, llamamos al _retrieveTweets () Método de nuestro widget para solicitar la siguiente página. Finalmente, eliminamos los enlaces de paginación actuales, ya que se volverán a crear si hay páginas siguientes o anteriores incluidas en el nuevo objeto de respuesta.


Usando el Plugin

Ahora que hemos creado nuestro complemento, podemos ver lo fácil que es utilizarlo con nuestro widget. Necesitamos actualizar nuestro utilizar() Método para usar nuestro plugin, y llamar al enchufe() Método antes de que se muestre el widget:

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

los enchufe() método conecta nuestro plugin, que es accesible a través de la Enchufar espacio de nombres y cualquier espacio de nombres que especificamos al definir la clase del complemento. Ahora cuando ejecutamos la página, deberíamos tener enlaces de paginación en la parte inferior del widget:

Una de las características de nuestro complemento (al igual que nuestro widget) es la fácil internacionalización; Con el fin de proporcionar cadenas para el complemento en otro idioma (o anular cualquier atributo si se trata de un complemento), simplemente podemos proporcionar el objeto de configuración como el segundo argumento para el complemento. enchufe() método, por ejemplo:

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

El enlace de paginación ahora debería aparecer así:


Terminando

En esta parte del tutorial, observamos lo fácil que es crear un complemento que se pueda usar para mejorar los widgets existentes u otros módulos. Esta es una excelente manera de proporcionar una funcionalidad adicional que no es esencial, que los desarrolladores pueden elegir si lo desean. Vimos que la estructura de un complemento es similar a la de un widget en una escala más pequeña.

En este ejemplo, el complemento estaba muy unido a nuestro widget; no sería posible utilizar el complemento con un widget diferente, por ejemplo. Esto no tiene por qué ser el caso y los complementos, así como las extensiones se pueden acoplar de forma mucho más sencilla para agregar o mejorar la funcionalidad de una variedad de módulos diferentes.

Esto nos lleva ahora al final de la serie sobre los widgets YUI3; Espero haber dado una idea de los poderosos mecanismos implementados por la biblioteca que nos permiten crear fácilmente widgets escalables y robustos que aprovechan las fortalezas de la biblioteca..

Háganos saber lo que piensa en la sección de comentarios a continuación y muchas gracias por leer!