first - jquery selector
Funciones públicas desde dentro de un plugin jQuery (4)
Me encanta la arquitectura de plugins jQuery, sin embargo, me parece frustrante (probablemente debido a una falta de comprensión de mi parte) cuando quiero retener una referencia a la instancia del complemento para acceder a las propiedades o métodos más adelante en mi código.
Editar: Quiero aclarar que lo que realmente estoy tratando de hacer es retener una referencia a los métodos y propiedades utilizados en el complemento, para que pueda usarlos más tarde.
Tomemos el caso de un icono de carga de AJAX. En un entorno OOP más tradicional, podría hacer:
var myIcon = new AJAXIcon();
myIcon.start();
//some stuff
myIcon.stop();
Los métodos y las propiedades de mi objeto se almacenan en una variable para su uso posterior. Ahora, si quiero tener la misma funcionalidad en un plugin de jQuery, lo llamaría desde mi código principal algo como esto:
$("#myId").ajaxIcon()
Por convención, mi complemento necesita devolver el objeto jQuery original pasado a mi complemento, lo que permite la capacidad de ocultación, pero si lo hago, pierdo la posibilidad de acceder a los métodos y las propiedades de la instancia del complemento.
Ahora, sé que puedes declarar una función pública en mi complemento, algo así como
$.fn.ajaxIcon = function(options) {
return this.each(function () {
//do some stuff
}
}
$.fn.ajaxIcon.stop = function() {
//stop stuff
}
Sin embargo, sin romper la convención de devolver el objeto jQuery original, no puedo retener una referencia a la instancia específica del complemento al que deseo hacer referencia.
Me gustaría poder hacer algo como esto:
var myIcon = $("myId").ajaxIcon(); //myIcon = a reference to the ajaxIcon
myIcon.start();
//some stuff
myIcon.stop();
¿Alguna idea?
Creo que puedes lograr lo que estás buscando con algo como esto:
var myIcon = $("myId").ajaxIcon(); //myIcon = a reference to the ajaxIcon
$.ajaxIcon.start(myIcon);//some stuff
$.ajaxIcon.stop(myIcon);
Aunque no lo he probado, no tengo acceso a un entorno en el que pueda hacer ese cajero automático
La mayoría de los complementos de jQuery que veo tratando de lograr esto usarán un alcance anónimo y cierres para hacer referencia a las funciones y variables exclusivas de esa instancia. Por ejemplo, usando el siguiente patrón:
;(function ($) {
// your code
})(jQuery);
Entre el comienzo y el final del módulo, puede declarar las funciones que desee. No contaminará el espacio de nombres global y podrá retener el acceso a variables locales a través de cierres, que podrían resolver muchos de sus problemas. Además, no tema utilizar las funciones $.data
.
Ok, descubrí cómo hacer esto:
Código de complemento:
$.ajaxIcon.init = function(element, options) {
//your initialization code
this.start = function() {
//start code
}
this.stop = function() {
//stop code
}
}
$.fn.ajaxIcon = function(options) {
this.each(function () {
//This is where the magic happens
jQuery(this).data(''ajaxIcon'', new jQuery.ajaxIcon.init(this, opts));
});
return this;
}
Luego, para usarlo en otro lugar de tu código:
var myIcon = $("#myId").ajaxIcon.data(''ajaxIcon'')
// myIcon: a reference to the ''init'' object specific to this plugin instance
myIcon.start();
myIcon.stop();
voila, respondió mi propia pregunta :)
Si haces algo como lo siguiente:
(function($){
$.fn.myPlugin = function(options) {
// support multiple elements
if (this.length > 1){
this.each(function() { $(this).myPlugin(options) });
return this;
}
// private variables
var pOne = '''';
var pTwo = '''';
// ...
// private methods
var foo = function() {
// do something ...
}
// ...
// public methods
this.initialize = function() {
// do something ...
return this;
};
this.bar = function() {
// do something ...
};
return this.initialize();
}
})(jQuery);
Luego puede acceder a cualquiera de sus métodos públicos:
var myPlugin = $(''#id'').myPlugin();
myPlugin.bar();
Esto se toma de este artículo muy útil (mayo de 2009) de trulyevil.com, que a su vez es una extensión de este artículo (octubre de 2007) de learningjquery.com.