1. Code
  2. JavaScript
  3. jQuery

Codificando tu primer jQuery UI Plugin

jQuery contiene el método fn.extend (), lo que hace que la creación de complementos jQuery sea bastante sencilla, lo que nos permite escribir código que se usa exactamente de la misma manera que otros métodos de jQuery. jQuery UI también contiene estructuras que facilitan la creación de plugins jQuery UI personalizados. Así que eso es lo que vamos a ver en el transcurso de este tutorial. Los métodos utilizados difieren de los plugins de jQuery estándar, y hay convenciones más estrictas que deben seguirse, por lo que creo que el tema es merecedor de un artículo.
Scroll to top

Spanish (Español) translation by Juan Pablo Diaz Cuartas (you can also view the original English article)

jQuery contiene el método fn.extend (), lo que hace que la creación de complementos jQuery sea bastante sencilla, lo que nos permite escribir código que se usa exactamente de la misma manera que otros métodos de jQuery. jQuery UI también contiene estructuras que facilitan la creación de plugins jQuery UI personalizados.  Así que eso es lo que vamos a ver en el transcurso de este tutorial. Los métodos utilizados difieren de los plugins de jQuery estándar, y hay convenciones más estrictas que deben seguirse, por lo que creo que el tema es merecedor de un artículo.


En el transcurso de este tutorial, le mostraré las convenciones de codificación y las pautas generales que deben cumplirse al crear complementos para jQuery UI. Crearemos un complemento simple que solo agrega títulos a las imágenes en la página. Es deliberadamente simple para que podamos centrarnos en lo que se necesita para hacer un plugin de jQuery UI sin perderse en el código. Cualquiera que haya escrito un plugin jQuery no debería tener problemas. El conocimiento de jQuery UI puede ayudar pero no debe ser esencial para completar este tutorial. Empecemos.

Empezando

Necesitaremos una copia de jQuery, así como un par de archivos de jQuery UI, pero debe ser jQuery UI 1.8 (esto se puede encontrar en el blog). Cree un directorio de trabajo en su máquina llamado jqueryui-plugin, luego dentro de este cree una carpeta css, una carpeta js y una carpeta img (las imágenes utilizadas en este tutorial se pueden encontrar en la descarga del código).

Descargue la biblioteca y descomprímala en algún lugar accesible. Solo necesitamos unos pocos archivos del archivo, es decir, el archivo fuente jQuery que está en la raíz del archivo como jquery-1.4.1.js, y los archivos jquery.ui.core.js y jquery.ui.widget.js , que están ambos en la carpeta ui. Coge estos y colócalos en la carpeta js en tu directorio de trabajo. También haremos un uso ligero del marco CSS, por lo que necesitaremos una de las hojas de estilo de tema disponibles con la versión estable actual de jQuery UI (utilicé ui-lightness en este ejemplo).

Haremos un widget de captionator, por lo que también necesitaremos una página, con un montón de imágenes, para desarrollar / probar el plugin con. Este ejemplo usa la siguiente página:

1
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
2
<html>
3
  <head>
4
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5
		<title>jQuery UI Captionator</title>
6
		<link rel="stylesheet" type="text/css" href="css/ui-lightness/jquery-ui-1.7.2.custom.css">
7
		<link rel="stylesheet" type="text/css" href="css/ui.captionator.css">
8
	</head>
9
	<body>
10
		<img src="img/1.jpg" alt="Royal Air Force Eurofighter Typhoon">
11
		<img src="img/2.jpg" alt="A British military GR-9 Harrier">
12
		<img src="img/3.jpg" alt="Two RAF Tornado GR-4s pull away from a KC-135 Stratotanker after refueling">        
13
		<script type="text/javascript" src="js/jquery.js"></script>
14
		<script type="text/javascript" src="js/jquery.ui.core.js"></script>
15
		<script type="text/javascript" src="js/jquery.ui.widget.js"></script>
16
		<script type="text/javascript" src="js/jquery.ui.captionator.js"></script>
17
	</body>
18
</html>

Vamos a mantener las cosas bastante simples por ahora; solo tenemos tres imágenes en la página, seguidas de cuatro archivos de script; tres enlaces a los archivos fuente jQuery y jQuery UI, el cuarto al archivo fuente de nuestro plugin que crearemos en breve. Todos los widgets / complementos de jQuery UI requieren el archivo jquery.ui.core.js. El archivo jquery.ui.widget.js es la fábrica de widgets y permite la creación de widgets consistentes que comparten una funcionalidad de API común. La mayoría de los componentes de la biblioteca lo requieren, y lo usaremos para crear nuestro complemento.

Creando el archivo de complemento

Cree un nuevo archivo JavaScript y guárdelo como jquery.ui.captionator.js en la carpeta js; debemos seguir con la convención de nomenclatura de jQuery UI, que acaba de actualizarse en la versión 1.8 de la biblioteca, y usar jquery.ui.plugin_name.js. Agregue el siguiente código al nuevo archivo:

1
(function($) {
2
3
})(jQuery);

Todo el código que compone nuestro complemento debe estar encapsulado dentro de una función anónima autoejecutable. El objeto jQuery se pasa a esta función y se usa dentro de la función a través de $ alias; esto es para asegurar que el complemento sea compatible con el método noConflict () de jQuery. Este es un requisito específico y siempre debe cumplirse.

A continuación, tenemos que definir el complemento; agregue el siguiente código a nuestra función anónima:

1
$.widget("ui.captionator", {
2
3
});

El patrón para usar la fábrica de widgets es simple de usar, simplemente llamamos al método widget () especificando el nombre del complemento como primer argumento, y un literal de objeto que contiene las propiedades y métodos que hacen que el complemento funcione. Esto permite que nuestro complemento sea llamado (y creado) usando la sintaxis jQuery commen $ ("element_caption_applied_to"). Captionator (); como cualquier otro método jQuery o jQuery UI.

La fábrica de widgets nos proporciona una cantidad de estas propiedades y métodos; por ejemplo, podemos establecer las opciones predeterminadas para el complemento usando la propiedad de opciones y agregar una función de inicialización que la fábrica de widgets ejecuta automáticamente tan pronto como se invoca una instancia del complemento. Dentro del objeto que aparece como el segundo argumento en el código anterior, agregue el siguiente código: 

1
options: {
2
  location: "bottom",
3
  color: "#fff",
4
  backgroundColor: "#000"
5
},

Estas son las únicas opciones que usaremos en nuestro plugin de ejemplo; los usuarios (y los usuarios me refiero a implementadores, no a los usuarios finales) del complemento pueden especificar la posición del título en la parte superior de la imagen a la que se llama, o en la parte inferior, pueden especificar el color del texto en el título, o cambie el color de fondo de la leyenda. Para cambiar una opción configurable de cualquier widget de jQuery UI antes de la inicialización, el desarrollador de implementación solo usaría algo como esto:

$("element_caption_applied_to").captionator({ localizacion: "top" });

A continuación, podemos crear nuestra función de inicialización, después de que el objeto de opciones agregue el siguiente método:

1
_create: function() {
2
			
3
	var self = this,
4
		o = self.options,
5
		el = self.element,
6
		cap = $("<span></span>").text(el.attr("alt")).addClass("ui-widget ui-caption").css({
7
			backgroundColor: o.backgroundColor,
8
			color: o.color,
9
			width: el.width()
10
		}).insertAfter(el),
11
		capWidth = el.width() - parseInt(cap.css("paddingLeft")) - parseInt(cap.css("paddingRight")),
12
		capHeight = cap.outerHeight() - parseInt(cap.css("paddingTop")) + parseInt(cap.css("paddingBottom"));
13
				
14
	cap.css({
15
		width: capWidth,
16
		top: (o.location === "top") ? el.offset().top : el.offset().top + el.height() - capHeight,
17
		left: el.offset().left,
18
		display: "block"
19
	});
20
			
21
	$(window).resize(function(){
22
		cap.css({
23
			top: (o.location === "top") ? el.offset().top : el.offset().top + el.height() - capHeight,
24
			left: el.offset().left
25
		});
26
	});			
27
},

El nombre del método debe comenzar con un guión bajo, ya que jQuery UI impide que cualquier método de complemento que comience con un guión bajo se invoque desde fuera del complemento, por lo que no se llamará accidentalmente desde la página HTML. Cualquier método que comencemos con un guión bajo estará protegido de esta manera.

La mayoría de nuestro método de inicialización es una serie de variables; dentro de nuestra función la palabra clave esto se refiere a un objeto pasado al método que representa la instancia del complemento. La primera variable almacena en caché una referencia a la instancia actual del complemento; se llama al método _create para cada elemento al que se invoca el método de complemento, que podría ser un elemento único o varios.

Podemos acceder a las opciones predeterminadas del complemento (que se reemplazan automáticamente si el implementador configura cualquiera de ellas) utilizando la propiedad de opciones del objeto; almacenamos esto en la segunda variable. El elemento al que se llamó el método de complemento (captionator ()), que en este ejemplo sería una imagen, se puede acceder utilizando la propiedad de elemento del objeto. Almacenamos esto en la tercera variable. 

Utilizamos la cuarta variable para almacenar una referencia al nuevo elemento de título, que está construido a partir de un simple <span> ; el <span>  tiene su innerText configurado en el atributo alt de la imagen actual, y se le agregan varios nombres de clase; le damos el nombre de la clase ui-widget para que pueda seleccionar un estilo predeterminado del tema actual de jQuery UI. También le damos un nombre de clase personalizado para que podamos agregar algo de nuestro propio estilo.

A continuación, debemos establecer algunas propiedades de CSS; usaremos una hoja de estilos separada para algunos estilos, pero ciertas cosas, como el color y los estilos de fondo de color, se pueden controlar a través de opciones configurables, por lo que debemos configurarlos mediante el complemento. El ancho del título debe coincidir con el ancho de la imagen que se superpone, por lo que también debemos determinarlo y configurarlo mediante programación. Finalmente, el nuevo <span>  se inyecta en la página directamente después de la imagen de destino.

Una vez que el subtitulo ha sido insertado, necesita ser dimensionada y posicionada; la única forma en que se puede clasificar con precisión es si ya existe en el DOM y tiene reglas de CSS aplicadas, como el tamaño de la fuente. Es por eso que agregamos el título a la página y luego determinamos sus dimensiones exactas, que luego se almacenan en las variables capWidth y capHeight.

Una vez que se ha agregado el título a la página (y solo después) podemos establecer el ancho, el alto y la posición correctos de cada título, que establecemos usando el método css () una vez más. Los subtítulos en realidad están completamente separados de las imágenes; se insertan directamente después de cada imagen y luego se colocan para que parezcan superponerse a las imágenes; después de todo, no podemos agregar el <span> como elemento secundario del <img>.

Esto está bien, hasta que se cambie el tamaño del navegador, en cuyo punto las imágenes se mueven pero los subtitulos no, porque están absolutamente posicionados. Para remediar esto, hemos utilizado un controlador de cambio de tamaño básico conectado a la ventana que simplemente reposiciona cada título en la nueva posición de su imagen. Este controlador de eventos es lo último en nuestro método de inicialización. 

Otro método que nuestro complemento debería exponer es el método destroy () que es común a todos los complementos de jQuery UI. Debemos proporcionar una implementación de este método para limpiar después de nuestro complemento.  Para nuestro plugin de ejemplo, el método puede ser tan simple como esto: 

1
destroy: function() {			
2
	this.element.next().remove();
3
			
4
	$(window).unbind("resize");
5
},

Todo lo que tenemos que hacer es eliminar los títulos y desvincular nuestro controlador de cambio de tamaño de ventana.  Este método puede ser invocado por un implementador utilizando el complemento, por lo que no deberíamos comenzar este nombre de método con un guión bajo.  Para invocar este método, el implementador usaría $ ("element_caption_attached_to"). Captionator ("destroy"); que es como se llamaría cualquiera de nuestros métodos públicos.

Necesitamos proporcionar otro método controlado / ejecutado por la fábrica de widgets; vimos anteriormente cómo un desarrollador puede cambiar una opción configurable antes de la inicialización, pero ¿qué sucede después de la inicialización? Esto se hace usando el método de opción usando la siguiente sintaxis: $ ("element_caption_attached_to"). Captionator ("option", "location", "top"); entonces necesitamos agregar el método incorporado _setOption para manejar esto:

1
_setOption: function(option, value) {
2
	$.Widget.prototype._setOption.apply( this, arguments );
3
4
	var el = this.element,
5
		cap = el.next(),
6
		capHeight = cap.outerHeight() - parseInt(cap.css("paddingTop")) + parseInt(cap.css("paddingBottom"));
7
			
8
	switch (option) {
9
		case "location":
10
			(value === "top") ? cap.css("top", el.offset().top) : cap.css("top", el.offset().top + el.height() - capHeight);
11
			break;
12
		case "color":
13
			el.next().css("color", value);
14
			break;
15
		case "backgroundColor":
16
			el.next().css("backgroundColor", value);
17
			break;
18
	}
19
}

Comenzamos este método con un guión bajo porque el implementador usa la opción, no _setOption para cambiar realmente las opciones; no necesitamos preocuparnos sobre cómo se maneja esto, solo tenemos que proporcionar este método para tratar con algo específico de nuestro complemento. Como este método ya existe en la fábrica de widgets, deberíamos llamar al método original, lo que hacemos primero en nuestro método utilizando el prototipo del objeto Widget, especificando el nombre del método (_setOption en este caso, pero podríamos hacerlo para otro construido -en los métodos también) y use apply para llamarlo. A continuación, podemos proceder con el código específico de nuestro complemento.

La función recibirá automáticamente dos argumentos que son la opción para cambiar y el nuevo valor. Almacenamos en caché algunos elementos de uso común, como la imagen y el título, y obtenemos la altura actual de cada título. Luego usamos una declaración simple de mayúsculas y minúsculas para manejar cada una de las tres opciones que cambiamos. La reubicación de los títulos es la más compleja, pero sigue siendo bastante trivial y similar a cómo los posicionamos inicialmente.

Agregar eventos

Es importante agregar eventos que los desarrolladores que usan su complemento puedan agregar devoluciones de llamada para que puedan reaccionar a las diferentes cosas que suceden cuando los usuarios interactúan con el widget de alguna manera. La fábrica de widgets maneja la mayor parte de esta tarea para nosotros, todo lo que tenemos que hacer es activar el evento. Este complemento realmente no hace mucho, pero aún podríamos desencadenar un evento después de que cada título se agregue a la página; para hacer esto agregue el siguiente código directamente antes del controlador de eventos de cambio de tamaño:

1
self._trigger("added", null, cap);

¡Eso es todo lo que tenemos que hacer! Una sola línea de código y tenemos un evento personalizado al que se puede responder. Llamamos al método _trigger () de la instancia del complemento (que almacenamos en la variable self) y pasamos al método tres argumentos; el primero es el nombre del evento, el segundo es para el objeto del evento (no necesitamos usar esto en nuestro plugin de ejemplo, de ahí el valor nulo) y el tercero es una referencia al elemento de título. La fábrica de widgets pasará automáticamente el objeto de evento (si se incluye) y los datos que pasamos en el tercer parámetro a una función de devolución de llamada que usa el evento agregado. Un desarrollador podría enlazarse a este evento usando la siguiente sintaxis: $ ("element_caption_attached_to"). Captionator ({ añadido: function (e, ui) {// hacer cosas}

Diseñando el complemento

Solo necesitamos una hoja de estilo muy pequeña para nuestro complemento, literalmente tenemos solo tres estilos. ¡Casi no vale la pena crear un archivo separado para los estilos! Pero lo haremos, así que cree un nuevo archivo llamado ui.captionator.css, que es el formato requerido para las hojas de estilo del complemento, y guárdelo en el directorio css. Agregue los siguientes estilos a él:

1
.ui-caption { display:none; position:absolute; padding:10px; }

Eso es todo al respecto. Nuestro complemento ahora está completo funcional y visualmente. Los subtítulos deberían aparecer así:

Final ProductFinal ProductFinal Product

Resumen 

Al igual que el método de creación de complementos de jQuery fn.extend (), jQuery UI también tiene su propio mecanismo que permite a los desarrolladores escribir rápida y fácilmente plugins robustos y escalables que cumplen con los altos estándares de los proyectos jQuery UI, aunque en términos de lo que realmente hace por nosotros, es incluso mejor que jQuery. La fábrica de widgets se ha creado de tal manera que casi todo el trabajo duro se saca de la creación de plugins personalizados.

Es fácil trabajar con los métodos proporcionados por la fábrica de widgets para agregar métodos a nuestros complementos que son comunes en todos los widgets UI, como los métodos de destrucción y opción, que los desarrolladores de implementación esperarían encontrar en cualquier complemento. También vimos lo fácil que es desencadenar eventos personalizados que los desarrolladores pueden usar para reaccionar ante las interacciones o las ocurrencias con el widget.