Header Ads Widget

Ticker

6/recent/ticker-posts

Cosas que aprendí creando un complemento jQuery

jQuery es una de las bibliotecas de JavaScript más utilizadas, si no la más utilizada, que permite hacer grandes cosas con el gran conjunto de pequeñas herramientas que ofrece a los desarrolladores web: manipulación HTML / DOM, manipulación CSS, métodos de eventos HTML, efectos y animaciones, AJAX, utilidades,…

Uno de los aspectos clave de jQuery es la posibilidad de ampliarlo con nuevas funcionalidades, los denominados complementos . Para aquellos que tienen un conocimiento básico de jQuery y quieren o necesitan crear un nuevo complemento de jQuery, esta publicación intenta ser un resumen útil de las cosas buenas a tener en cuenta.

Antes de empezar

Debido a la flexibilidad y el poder del lenguaje, la comunidad de Perl está orgullosa de su lema Tim Today , que es:

Hay más de una forma de hacerlo

Puede considerar lo mismo para JavaScript, eso es cierto. El hecho de que JavaScript no sea un lenguaje orientado a objetos sino un lenguaje basado en prototipos permite seguir el paradigma OOP de muchas formas diferentes. Buscando un código de plantilla para crear un complemento de jQuery, encontré toneladas y no todas siguiendo las mismas convenciones e ideas.

Aquí les presento una mezcla de las plantillas más aceptadas y sus aspectos clave.

El código

Junto al artículo, puede encontrar la versión auto documentada del código repetitivo en mi repositorio de GitHub .

Donde empezar

Si planea crear un complemento jQuery, los primeros lugares en los que le sugiero que comience a leer es la sección Complementos / Autorización de la documentación del proyecto. Es un gran recurso para comenzar, pero en la vida real pronto descubrirás que necesitas saber un poco más de eso.

Usando un complemento de jQuery

Supongamos que tenemos un complemento jQuery llamado beautyLink, que transforma un enlace normal (el <a>elemento) en uno realmente agradable cambiando la familia de fuentes, el texto y el color de fondo. Por lo que debemos incluirlo en nuestra página antes de comenzar a usarlo:

1
2
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery-beautylink.js"></script>

La forma convencional de crearlo y aplicarlo sobre un elemento sería:

1
$('#linkID').beautyLink();

o, si desea postularse en cada enlace de la página actual:

1
$('a').beautyLink();

Más tarde, para cambiar el color del texto a rojo, podríamos invocar el método público de un complemento como:

1
$('#linkID').beautyLink('color', 'red');

o para recuperar el color del texto actual:

1
$('#linkID').beautyLink('color');

es decir, el colormétodo puede actuar como setter o getter dependiendo de si pasamos un valor o no.

Creando un nuevo complemento

De acuerdo, sabemos cómo usar un complemento pero queremos crear uno nuevo. El primer paso que debemos hacer es crear un nuevo archivo JavaScript donde colocar nuestro código. Como buena práctica, este archivo debe contener una sección de encabezado de documentación con el nombre del complemento, la versión, la información de contacto del autor, la licencia, etc.

Cuando incluimos el archivo JavaScript en una página web, necesitamos que el código se ejecute automáticamente para que el complemento pueda registrarse dentro de jQuery. Para hacerlo, todo el código JavaScript del archivo debe estar dentro del código:

1
2
3
(function($, window, document, undefined) {
  // The code here
})(jQuery, window, document);

De esta manera, el código de nuestro complemento recibirá una referencia a la biblioteca jQuery, la ventana y el documento y, además, una referencia indefinida sobre el undefinedparámetro que podemos usar para comparar valores indefinidos (guau, eso era demasiado indefinido en un frase).

La función de envoltura

Para crear un complemento de jQuery, necesitamos registrar una nueva función en el jQuery.fnobjeto. Esta es una matriz donde jQuery almacena referencias a todos los complementos disponibles o incluidos en la página actual. Para agregar uno nuevo, simplemente escriba algo como:

1
2
3
jQuery.fn.myPlugin = function(options) {
  // Do your awesome plugin stuff here
};

o

1
2
3
jQuery.fn['myPlugin'] = function(options) {
  // Do your awesome plugin stuff here
};

La función que defina aquí es el punto de entrada a su complemento. Es una función contenedora que debe manejar la inicialización o invocación de complementos al método de cualquier complemento.

¿Cómo distinguir la acción?

La pregunta es, ¿cómo implementamos la función de envoltorio del complemento para distinguir si debe inicializar el complemento o llamar a un método? La respuesta está en el optionsparámetro.

Cuando creamos una instancia de un complemento sin pasar ningún argumento, el optionsparámetro es undefined:

1
$('#linkID').beautyLink();

Si instanciamos pasando cualquier argumento, el optionsparámetro es un Object:

1
2
3
4
$('#linkID').beautyLink({
  someOption: 'a',
  someOther: 123
});

Finalmente, si estamos llamando al método de un complemento como:

1
$('#linkID').beautyLink('color', 'red');

entonces el optionsparámetro es una matriz con dos elementos['color', 'red']

El código de inicio para la función contenedora

Con lo anterior en mente, podemos escribir el código base para la función contenedora:

01
02
03
04
05
06
07
08
09
10
11
12
$.fn[pluginName] = function(options) {
    var args = arguments;
 
    if (options === undefined || typeof options === 'object') {
        // Creates a new plugin instance
 
    } else if (typeof options === 'string' &amp;&amp; options[0] !== '_' &amp;&amp; options !== 'init') {
        // Call a public pluguin method (not starting with an underscore) and different
        // from the 'init' one
 
    }
};

Encadenable o no encadenable

jQuery es famoso (y poderoso) por su forma encadenable de trabajar, es decir, una llamada a un método devuelve una referencia al mismo elemento para que podamos realizar otra llamada. Por ejemplo:

1
2
3
$('#someID')
  .parents(".pane")
  .animate({ opacity: "hide" }, "slow");

o aplicado a nuestro complemento:

1
2
3
$('#linkID')
  .beautyLink('color', 'red')
  .beautyLink('backgroundColor', 'black');

Debemos pensar cuáles de nuestros métodos deben ser encadenables y cuáles no. Por ejemplo, los métodos getter deben romper la encadenabilidad . En nuestro caso queremos una llamada a:

1
$('#linkID').beautyLink('color');

devuelve el redvalor y no una referencia al elemento para realizar otra llamada.

Implementando encadenamiento

Cuando $.fn[pluginName]se llama a la función contenedora, esta referencia apunta a:

  • el elemento DOM seleccionado, como cuando se usa:
1
$('#linkID').beautyLink('color', 'red');

o

  • una lista de elementos DOM seleccionados, como cuando se usa:
1
$('a').beautyLink('color', 'red');

El siguiente código muestra una función contenedora muy básica que inicializa una instancia de complemento para cada elemento seleccionado. Esto da como resultado una llamada encadenable que devuelve una referencia al mismo elemento listo para realizar otra llamada encadenada:

1
2
3
4
5
$.fn[pluginName] = function(options) {
    return this.each(function() {
        new Plugin(this, options);
    });
}

Evitando la encadenamiento

La solución para evitar que un método sea encadenable es fácil, simplemente no escribe this.each()ni ejecuta el código en la primera aparición, es decir, el this[0].

Esto quedará más claro en el código final.

La función jQuery.data ()

Hacemos uso de la $.data()función en nuestro código, por lo que se requiere una breve explicación.
La $.data()función permite almacenar datos arbitrarios sobre un elemento (u obtener su valor).

Es importante porque almacenamos una referencia a la instancia del complemento en cada elemento que se aplica. Esto nos permite verificar si un elemento ya ha aplicado un complemento o necesitamos instanciarlo. Esto se aclarará en el código final de la función contenedora.

El código de la función del contenedor de la red troncal

Con todo lo anterior en mente, podemos escribir la función de envoltura de nuestro complemento final. Para resumir:

  • Si se llama al complemento sin argumentos, entonces el complemento se inicializa y se almacena una referencia en el elemento DOM.
  • Si se llama al método de un complemento y no es un método getter, entonces el método se llama manteniendo encadenamiento.
  • Si se llama al método de un complemento y es un método de obtención, devolvemos un valor y rompemos la capacidad de encadenamiento.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
dieciséis
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$.fn[pluginName] = function(options) {
    var args = arguments;
 
    if (options === undefined || typeof options === 'object') {
        // Creates a new plugin instance, for each selected element, and
        // stores a reference withint the element's data
        return this.each(function() {
            if (!$.data(this, 'plugin_' + pluginName)) {
                $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
            }
        });
    } else if (typeof options === 'string' &amp;&amp; options[0] !== '_' &amp;&amp; options !== 'init') {
        // Call a public pluguin method (not starting with an underscore) for each
        // selected element.
        if (Array.prototype.slice.call(args, 1).length == 0 &amp;&amp; $.inArray(options, $.fn[pluginName].getters) != -1) {
            // If the user does not pass any arguments and the method allows to
            // work as a getter then break the chainability so we can return a value
            // instead the element reference.
            var instance = $.data(this[0], 'plugin_' + pluginName);
            return instance[options].apply(instance, Array.prototype.slice.call(args, 1));
        } else {
            // Invoke the speficied method on each selected element
            return this.each(function() {
                var instance = $.data(this, 'plugin_' + pluginName);
                if (instance instanceof Plugin &amp;&amp; typeof instance[options] === 'function') {
                    instance[options].apply(instance, Array.prototype.slice.call(args, 1));
                }
            });
        }
    }
};

Tenga en cuenta que también hemos definido una matriz donde especificar qué método puede actuar como captador cuando se invoca sin ningún argumento:

1
$.fn[pluginName].getters = ['someGetterMethod'];

Continuará…

Hemos visto la base sobre cómo crear un complemento de jQuery y hemos aprendido sobre la importancia de la función de contenedor, que es el punto de entrada a nuestro complemento.
En el próximo post explicaré cómo podemos organizar nuestro código de plugin, los responsables de implementar la funcionalidad, cómo crear un método público y privado, etc.

Publicar un comentario

0 Comentarios