Una sinfonía en C#

Un pequeño aporte a la comunidad de habla hispana.

Cómo crear un plugin para jQuery?

Yo creo firmemente que la potencia de jQuery está en los selectores, el resto es aplicar funciones sobre el conjunto afectado, cuando las funciones que el framework trae incorporado no son suficientes podemos acudir a repositorio de plugins y buscar uno que nos soluciones el problema, pero en ocasiones necesitamos hacer nuestros propios plugin, entonces vamos a ver unos tips iniciales sobre ello.

Algunas reglas de estilo

Una de las primeras cosas que tenemos que tener en cuenta es que nuestros plugins tiene que residir en un archivo .js cuyo nombre siga el siguiente patrón jquery.nombre. js

Ahora si, a hacer el plugin

Para este primer intento vamos a hacer un plugin bien sencillo (tal vez no tan útil) pero que nos va a permitir ejemplificar algunos detalles, nuestro plugin nos va a permitir seleccionar una caja de texto y que tenga la apariencia de las cajas de búsqueda que tiene un texto por defecto y cuando escribimos se borra, si le quitamos el foro y no hemos escrito nada queda tal cual como cuando empezó

image

Algo asi, empecemos.

Manos a la obra

Un plugin de jQuery no es más que una función que se agrega al prototipo del objeto jQuery, algo así

jQuery.prototype.searchBox = function(){
	//código de implentación
};

esto está muy bien, es semánticamente correcto, sin embargo la forma correcta de hacerlo es utilizando la propiedad fn de jQuery, que apunta al prototipo, así:

jQuery.fn.searchBox = function(){
	//código de implentación
};

perfecto, primer paso listo, declaramos la nueva funcionalidad, ahora podemos hacer así

$(":text").searchBox();	

ok, no hace nada, pero la función existe y está agregada a jQuery.

Evitando conflictos con otras librerías

Esto es bien sencillo, sin embargo falta un detalle: es bastante incómodo utilizar el nombre jQuery cada vez que queremos utilizar una funcionalidad dentro del código del plugin, lo primero que vamos a querer hacer es utilizar $ en lugar de jQuery, sin embargo esto puede no se una buena idea, si nuestro plugin convive con otras librerías de javascript como Mootools, Prototype y demás veremos que estas también utilizar $ para llamar a sus clases con lo cual podemos tener un conflicto, cómo resolvermos esto?, bien, así:

(function($){
	$.fn.searchBox = function(){
})(jQuery);

ponemos nuestro código dentro de una función autoejecutable, definimos en esta función un parámetro al cual llamamos $ (pero esto nombre es válido sólo en el ámbito de la función, con lo cual no hay conflicto) al final de la declaración de la función autoejecutable le pasamos el objeto jQuery y listo, tenemos la funcionalidad $ que apunta a jQuery y no hay posiblidad de conflicto.

Implementando el código

(function($){
	$.fn.searchBox = function(){
	//acá escribimos el código del plugin
	};
})(jQuery);

por el momento tenemos el esqueleto del plugin (el menos en uno de los modos posibles de hacer uno) ahora vamos a un truco sencillo pero que nos va a ahora problemas dentro de dos minutos

Quién es this?

Dentro del ámbito de la función searchbox this tiene el valor de los elementos afectados por el selector, por todos, encerrados en un wrapper de jQuery, es una muy buena idea ponerlo dentro de una variable para tenerlo a mano, otra gran idea es que el nombre de la varible comience con $ para recordar el wrapper

(function($){
	$.fn.searchBox = function(){
		var $el = this;
	};
})(jQuery);

bien, ahora empezamos, primero vamos a crear algunas opciones por defecto para el plugin, por ejemplo el texto que muestra la caja por defecto y la clase css que le da el efecto “marca de agua”

(function($){
	$.fn.searchBox = function(){
		var $el = this;
		var defaults = {defaultStyle: "gris", defaultText: "ingrese texto"};
	};
})(jQuery);

ponemos las opciones en una variable a la que llamamos defaults, con dos valores, por supuesto que tenemos una clase de css llamada “gris”.

Utilizando $.extend para combinar las opciones con los valores por defecto

Para dar mayor flexibilidad al plugin es interesante permitir que estos valores por defecto puedan ser cambiados por el usuario, la forma de hacerlo es recibirlos como parámetro en la función a la que apunta searchBox y recibir allí el parámetro, para que el usuario pueda configurar alguno, todos o ninguno de los parámetros vamos a valernos de la función extend de jQuery, el código quedaría así:

(function($){
	$.fn.searchBox = function(options){
		var $el = this;
		var defaults = {defaultStyle: "gris", defaultText: "ingrese texto"};
		$.extend(defaults, options);
	};
})(jQuery);

Perfecto, ahora empecemos a implementar la funcionalidad, lo primero es asignar el texto y el estilo, simple, son dos líneas con jQuery

(function($){
	$.fn.searchBox = function(options){
		var $el = this;
		var defaults = {defaultStyle: "gris", defaultText: "ingrese texto"};
		$.extend(defaults, options);

		$el.val(defaults.defaultText);
		$el.addClass(defaults.defaultStyle);
	};
})(jQuery);

Ahora la idea es que cuando tome el foco el control se borre el texto y se quite el estilo, con jQuery son nuevamente dos líneas

(function($){
	$.fn.searchBox = function(options){
		var $el = this;
		var defaults = {defaultStyle: "gris", defaultText: "ingrese texto"};
		$.extend(defaults, options);

		$el.val(defaults.defaultText);
		$el.addClass(defaults.defaultStyle);
		
		$el.focus(function(){
			$el.val("");
			$el.removeClass(defaults.defaultStyle);
		});
	};
})(jQuery);

por último, cuando el control pierda el foco debemos verificar si se ingresó un texto y en caso que no sea así nuevamente poner el texto por defecto y el estilo, por lo tanto vamos a agrupar las dos líneas que hacen esto en una función y llamarlas desde el evento blur en caso que no haya texto, nuestro plugin quedaría así:

(function($){
	$.fn.searchBox = function(options){
		var $el = this;
		var defaults = {defaultStyle: "gris", defaultText: "ingrese texto"};
		$.extend(defaults, options);

		function init(){
			$el.val(defaults.defaultText);
			$el.addClass(defaults.defaultStyle);
		}
		
		$el.focus(function(){
			$el.val("");
			$el.removeClass(defaults.defaultStyle);
		}).blur(function(){
			if($el.val().length==0)	init();
		});
	
		init();
	};
})(jQuery);

Permitiendo que se pueda usar la interfaz fluyente

Un detalle que falta, es que en caso que lo creamos necesario, podemos querer que después de llamar a nuestro plugin se pueden seguir concatenando funciones de jQuery así:

$(function(){
	$(":text").searchBox({defaultStyle: "gris", defaultText: "buscar..."})
	.click(function() { //hacer algo});
});

con la implementación como está no va a funcionar, necesitamos devolver el mismo objeto (el conjunto afectado por el selector encerrado en un objeto jQuery) para que se puedan seguir concatenando llamadas, finalmente el código queda así:

(function($){
	$.fn.searchBox = function(options){
		var $el = this;
		var defaults = {defaultStyle: "gris", defaultText: "ingrese texto"};
		$.extend(defaults, options);

		function init(){
			$el.val(defaults.defaultText);
			$el.addClass(defaults.defaultStyle);
		}
		
		$el.focus(function(){
			$el.val("");
			$el.removeClass(defaults.defaultStyle);
		}).blur(function(){
			if($el.val().length==0)	init();
		});
	
		init();		
		return $el;
	};
})(jQuery);

Listo, por supuesto que tiene algunos detalles de implementación, como que siempre borra el contenido al tomar el foco, pero es un ejemplo de un modo de hacer un plugin, espero sea útil.

Nos leemos.

Loading