Alors comme
ça petit padawan tu aimerais créer un plugin javascript pour cette merveilleuse librairie de fonctions?
Voici un tutoriel fort inspiré de la documentation officielle sur
les plugins jQuery en Anglais. Prêts à profiter
du meilleur de jQuery et gagner un maximum de temps
en développement pour davantage de sociabilité? Suivez le guide.
Pour commencer son plugin
Pour éviter
que notre super plugin n'entre en conflit avec d'autres plugins utilisant le
signe dollar il vaut mieux passer jQuery en fonction
auto invoquée (Immediately-Invoked Function Expression , ou IIFE).
(function( $ ) {
$.fn.monSuperPlugin
= function()
{
//
les instructions trop bien ici
};
})( jQuery );
Le contexte
Avec cette
base nous pouvons commencer à écrire notre contenu de plugin. Mais avant cela,
parlons un peu du mot clé this qui à
l'intérieur de notre fonction se réfère à l'objet jQuery
sur lequel le plugin est invoqué. this
se réfère au DOM (document object model) natif. Il
n'est donc pas besoin d'entourer this par les
parenthèses du sélécteur jQuery
dans ce contexte.
(function( $ ) {
$.fn.monSuperPlugin
= function()
{
//
les instructions trop bien ici
this.fadeIn('normal',
function(){
// le mot clé this est un élément du DOM
});
};
})( jQuery );
pour actionner
notre plugin on pourra donc l'appeler ainsi sur un #element
de votre choix ou plusieurs grâce à la puissance des sélecteurs CSS.
$('#element').myPlugin();
Les bases
Maintenant
que nous comprennons le contexte des plugins jQuery, écrivons un code qui fait réellement quelque chose.
(function( $ ){
$.fn.hauteurMax = function()
{
var max = 0;
this.each(function()
{
max = Math.max( max, $(this).height() );
});
return max;
};
})( jQuery );
Par exemple,
un simple plugin qui évalue les hauteurs pour retourner la plus grande dans le
jeu d'éléments sélectionnés.
var tallest = $('div').hauteurMax();
Ceci donne à
la variable tallest la valeur de la div la
plus haute de la page.
Maintenir la continuité
L'exemple
précédent retourne un nombre entier, mais bien souvent le but d'un plugin est
de modifier un jeu d'éléments et de les passer à la méthode suivante dans la
chaîne de fonctions. C'est ce qui fait la beauté du design de jQuery et explique sa popularité. Donc, pour maintenir la
continuité de la chaîne dans vos plugins, vous devez faire en sorte que les
retours de plugins comprennent le mot clé this.
(function( $ ){
$.fn.verrouTailles
= function(
type ) {
return
this.each(function() {
var $this = $(this);
if ( !type || type == 'width' ) {
$this.width(
$this.width() );
}
if ( !type || type == 'height' ) {
$this.height(
$this.height() );
}
});
};
})( jQuery );
Ce plugin
associe la largeur et la hauteur actuelle de chaque élément du jeu sélectionné.
Il sera ajouté dans le HTML de la page un attribut width
et height à chaque balise ainsi sélectionnée.
Nous pouvons donc y mettre une autre méthode à la suite, comme css().
Et pour le mettre en place dans une chaîne:
$('div').verrouTailles('width').css('color',
'red');
Parce que le
mot clé this est retourné dans la lunette de script
du plugin, la continuité est maintenue. Aussi, nous pouvons mettre des options
et des choix par défaut dans nos plugins.
Options et défauts
Les
configurations par défaut peuvent être étendues avec $.extend
http://docs.jquery.com/Utilities/jQuery.extend quand le plugin est invoqué. jQuery.extend( cible [, objet1] [, objetN])
extend sert à fusionner le contenu de plusieurs
objets dans le premier objet. Au lieu d'invoquer un plugin avec un grand nombre
d'arguments, vous pouvez passer un seul objet des options que vous voulez
modifier en argument.
(function( $
){
$.fn.tooltip = function( options ) {
// Créer quelques options par defaut,
les étendre comme nous voulons.
var settings
= $.extend( {
'location' : 'top',
'background-color' : 'blue'
}, options);
return this.each(function()
{
// code du plugin Tooltip ici
});
};
})( jQuery );
ce qui donne
en pratique avec une option définie dans un objet:
$('div').tooltip({
'location' : 'left'
});
Dans cet
exemple, après avoir appelé le plugin tooltip
avec les options choisies, la localisation par défaut topdevient
réécrite en left, alors que la configuration
de couleur d'arrière plan reste bleue car elle
n'a pas été spécifiée. la config settings de
l'objet devient donc comme ceci:
{
'location' : 'left',
'background-color' : 'blue'
}
C'est une
bonne pratique et un très bon moyen de rendre un plugin configurable sans avoir
besoin de donner toutes les options à chaque fois.
Espace de noms
Choisir un
espace de nommage est un moyen idéal pour éviter qu'un autre plugin chargé sur
la même page ne vienne remplacer le notre ou le modifier
contre notre gré. En tant que développeur ça nous rend la vie plus facile pour
mieux trier nos méthodes, évènements et données.
Il vaudrait
donc mieux ne pas mettre un seul espace de nom par plugin dans l'objet jQuery.fn mais plutôt stocker nos plugins dans un
objet qui agira comme pour la configuration par défaut que nous venons de voir.
Mais cette fois nous donnons par défaut non pas de simples variables mais des
noms associés à des méthodes.
(function( $
){
var methods = {
init : function( options ) {
// THIS
},
show : function( ) {
// IS
},
hide : function( ) {
// GOOD
},
update : function( content ) {
// !!!
}
};
$.fn.tooltip = function( method ) {
// logique d'appel de méthode
if
( methods[method] ) {
return methods[method].apply(
this, Array.prototype.slice.call( arguments, 1 ));
} else if ( typeof method ===
'object' || ! method ) {
return methods.init.apply( this, arguments );
} else
{
$.error( 'La Méthode ' + method + ' n'existe pas dans jQuery.tooltip'
);
}
};
})( jQuery );
// appelle la méthode initiatrice
$('div').tooltip();
// appelle la méthode initiatrice avec une option
$('div').tooltip({
foo
: 'bar'
});
// appelle la méthode hide
$('div').tooltip('hide');
// appelle la méthode update
avec une option
$('div').tooltip('update',
'This is the new tooltip content!');
c'est une façon
standard d'encapsuler ses méthodes de plugins dans la communauté jQuery, c'est aussi le cas pour jQueryUI.
http://jqueryui.com/
Évènements
la méthode bind()
permet de donner un espace de nom à des évènements liés. Si votre plugin lie un
évènement, c'est une bonne pratique de lui donner un espace de nom. ainsi, si
vous avez besoin de le délier avec unbind() sans interférer avec les autres évènements
qui pourraient avoir été liés avec le même type d'évènement. Vous pouvez
ajouter le nom de l'espace nom_de_namespace au
type d'évènement que vous liez, comme ceci.
(function( $
){
var methods = {
init : function( options ) {
return this.each(function(){
$(window).bind('resize.tooltip',
methods.reposition);
});
},
destroy : function( ) {
return this.each(function(){
$(window).unbind('.tooltip');
})%%
},
reposition : function( ) {
// ...
},
show : function( ) {
// ...
},
hide : function( ) {
// ...
},
update : function( content ) {
// ...
}
};
$.fn.tooltip = function( method ) {
if ( methods[method] ) {
return methods[method].apply( this, Array.prototype.slice.call(
arguments, 1 ));
} else if ( typeof method ===
'object' || ! method ) {
return methods.init.apply( this, arguments );
} else {
$.error( 'Method ' + method + '
does not exist on jQuery.tooltip' );
}
};
})( jQuery );
$('#fun').tooltip();
// et un peu plus tard...
$('#fun').tooltip('destroy');
Dans cet
exemple, quand tooltip est initialisé avec la méthode
init la méthode reposition
est liée à l'évènement de redimension de la fenêtre
sous l'espace de nom tooltip. Plus loin, si le
développeur a besoin de détruire tooltip, nous
pouvons délier les évènements liés à ce plugin en lui passant le nom de
l'espace, ici tooltip, à la méthode unbind. Cela nous permet de délier les évènements
d'un plugin en toute sécurité sans délier d'autres évènements liés en dehors du
plugin.
Data
Quand nous
avons besoin de maintenir un état ou de vérifier que notre plugin a été
initialisé sur un certain élément, la méthode jQuery data
est un très bon moyen de garder une trace des variables sur les éléments.
Cependant, au lieu de garder une trace de quelques appels de données séparés
avec des noms différents, il vaut mieux utiliser un objet pour héberger toutes
les variables et accéder à cet objet par un seul espace de nom.
(function( $
){
var methods = {
init : function( options ) {
return this.each(function(){
var $this = $(this),
data = $this.data('tooltip'),
tooltip = $('<div />', {
text : $this.attr('title')
});
// si le plugin n'a
pas encore été initialisé
if ( ! data ) {
/*
faire des trucs ici
*/
$(this).data('tooltip', {
target : $this,
tooltip : tooltip
});
}
});
},
destroy : function( ) {
return this.each(function(){
var $this = $(this),
data = $this.data('tooltip');
// Namespacing FTW
$(window).unbind('.tooltip');
data.tooltip.remove();
$this.removeData('tooltip');
})
},
reposition : function( ) { // ... },
show : function( ) { // ... },
hide : function( ) { // ... },
update : function( content ) { // ...}
};
$.fn.tooltip = function( method ) {
if ( methods[method] ) {
return methods[method].apply( this, Array.prototype.slice.call(
arguments, 1 ));
} else if ( typeof method ===
'object' || ! method ) {
return methods.init.apply( this, arguments );
} else {
$.error( 'Method ' + method + '
does not exist on jQuery.tooltip' );
}
};
})( jQuery );
Résumé et meilleures pratiques
Écrire des
plugins jQuery vous permet à tirer le meilleur profit
de la bibliothèque et abstraire vos plus intelligentes et utiles fonctions à
travers un code réutilisable pouvant vous faire faire un grand gain de temps et
rendre votre développement encore plus efficace. Voici un bref résumé de cet
article et ce que vous devez garder à l'esprit quand vous développerez votre
prochain plugin jQuery:
Comme le
conseille Paul Irish un des auteurs de Boiler Plate, consulter la source commentée de jQuery pour comprendre comment elle fonctionne est un
excellent moyen d'apprendre à manier le javascript en
profondeur et développer ses propres solutions.
http://code.jquery.com/jquery.js
Mettez la en
marque page :) à vous de jouer maintenant!