11540 sujets

JavaScript, DOM et API Web HTML5

Bonjour

j'ai acheté ce bouquin sur le développement de plugins jQuery et je suis un peu rebuté par l'approche abstraite de l'auteur et le manque de précisions qu'il apporte...

voici le squelette qu'il propose au début pour un plugin nommé helloWorld.


(function( $, window ) {
	var methods = {
		init : function( options ) {
			var defaults = {};

			options = $.extend( defaults, options );

			return this.each(function() {
				var $this = $(this),
					data = $this.data( 'helloWorld' );

				// If the plugin hasn't been initialized yet
				if ( ! data ) {
					$this.data( 'helloWorld', {
						target : $this
					});
					methods.print.apply( this );
				}
			});
		},

		destroy : function() {
			$(window).off( '.helloWorld' );

			return this.each(function() {
				var $this = $(this),
					data = $this.data( 'helloWorld' );

					$this.removeData( 'helloWorld' );
			});
		},

		print : function() {
			var $this = $(this);
			$this.text( 'Hello World!' );
		}
	};

	$.fn.helloWorld = 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.helloWorld' );
		}
	};
})( jQuery, window );





ça fonctionne, bien sur, en l'appelant par exemple sur un paragraphe de cette façon: $('p').helloWorld();


Maintenant c'est la fon du code que je ne comprends pas, dans cette partie:

	$.fn.helloWorld = 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.helloWorld' );
		}
	};


que vient faire le paramètre method, dans $.fn.helloWorld = function( method ) ??
puisque j'invoque le plugin sans paramètre, est ce le 1er else qui s'applique ? ( return methods.init.apply( this, arguments );)

dans tous les autres exemples de plugin jQuery que j'ai pu trouver, tout le code est à la suite du $.fn.nomDuPLugin = function ... etc





edit : le code s'affiche mal, voici la fin

$.fn.helloWorld = 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.helloWorld' );
}
};


le forum a rajouté 'smiley' dans le code, je sais pas pourquoi
Modifié par lionel_css3 (04 May 2013 - 17:12)
revoici le code, j'ai du mettre des espaces aux [ et aux ] dans les tableaux


(function( $, window ) {
	var methods = {
		init : function( options ) {
			var defaults = {};

			options = $.extend( defaults, options );

			return this.each(function() {
				var $this = $(this),
					data = $this.data( 'helloWorld' );

				// If the plugin hasn't been initialized yet
				if ( ! data ) {
					$this.data( 'helloWorld', {
						target : $this
					});
					methods.print.apply( this );
				}
			});
		},

		destroy : function() {
			$(window).off( '.helloWorld' );

			return this.each(function() {
				var $this = $(this),
					data = $this.data( 'helloWorld' );

					$this.removeData( 'helloWorld' );
			});
		},

		print : function() {
			var $this = $(this);
			$this.text( 'Hello World!' );
		}
	};

	$.fn.helloWorld = 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.helloWorld' );
		}
	};
})( jQuery, window );

oui, je lis l'anglais sans problème, je vais regarder l'article que tu me cites, en effet il me semble que cette syntaxe est utilisée, je t'en remercie.
Salut, en fait, c'est le deuxième cas du if/else qui s'applique puisque "!method" renvoi `true`. Alors en l'appellant comme ça tu lance la méthod `init`.

/* j'ai supprimé le reste, j'étais dans les vapes */
Modifié par SBoudrias (04 May 2013 - 21:50)
après avoir lu l'article sur la doc de jQuery, qui utilise la même syntaxe, je comprends un peu mieux, en fait c'est pour éviter de multiplier les namespaces dans l'appel de $.fn.nomDuPlugin que l'on regroupe les méthodes dans un objet littéral json

si je comprends bien, on appelle le plugin avec en argument le nom de la méthode et l'objet contenant les paramètres.

par contre prenons ce cas


(function( $ ){

  var methods = {
    init : function( options ) { 
      // THIS 
    },
    show : function( ) {
      // IS
    },
    hide : function( ) { 
      // GOOD
    },
    update : function( content ) { 
      // !!! 
    }
  };

  $.fn.tooltip = function( method ) {
    
    // Method calling logic
    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 );



si je fais $('div').tooltip('update', 'This is the new tooltip content!');
on comprends que j'invoque la méthode update avec l'argument 'This is the new tooltip content!'

mais si je fais $('div').tooltip('update'); qu'est ce qui l'empecherait de croire que je veux invoquer la méthode init avec la valeur 'update' ? c'est parce qu'il s'attend à avoir un objet littéral pour les arguments de la méthode?


et que si le plugin reçoit deux valeurs dans la parenthèse il considérera que la première est le nom d'une méthode et la deuxième l'argument de la méthode?
Modifié par lionel_css3 (04 May 2013 - 18:31)
Oui.

Le plugin gère trois actions/signature:

1- L'appel d'une méthode
Si le plugin a une méthode nommé comme le premier paramètre passé au plugin on appel cette méthode. À cette méthode, on passera tous les paramètres passé au plugin sauf le premier (qui est le nom de la méthode); c'est ce que fait cette méthode
Array.prototype.slice.call( arguments, 1 )


Sinon ->

2- L'initialisation d'un plugin
Si le premier paramètre passé au plugin est un objet, ou est vide, on initialise.

Sinon ->

3- Gèrer une signature invalide (lancer une erreur)
La configuration est invalide et on lance une erreur pour avertir le développeur.
ah oui, je comprends mieux comme ça mais alors quel est le mécanisme qui fait le tri dans ce qui est passé au plugin?

puisque quand on passe rien, ou un objet, il sait par exemple qu'il faut lancer la méthode init?
Modérateur
le mécanisme est là:

  // Si le premier argument (method) est le nom d'une méthode définie dans methods
  // alors on éxecute cette méthode en passant en paramètre le second argument
    if ( methods [ method ] ) {
      return methods [ method ] .apply( this, Array.prototype.slice.call( arguments, 1 ));
    }
  // Autrement si le premier argument est un objet (les options) ou si le premier argument
  // n'est pas défini on lance la méthode init en passant en arguments les arguments reçus
    else if ( typeof method === 'object' || ! method ) {
      return methods.init.apply( this, arguments );
    }
  // Si on arrive là c'est qu'on a fait une bourde ^^
    else {
      $.error( 'Method ' +  method + ' does not exist on jQuery.tooltip' );
    }  
d'accord, je vois mieux, mais quand on appelle le plugin, dans la parenthèse il peut y avoir 0, 1 ou 2 arguments... alors dans le plugin, à la ligne

$.fn.tooltip = function( method ) { ,

'method' correspond t'il à ce qui était contenu dans la parenthèse d'appel du plugin?

cel peut être un contenu variable... par exemple
si il y a ( 'init', { toto : 'bidule' } ) dans la parenthèse d'appel du plugin se retrouve t-on avec

$.fn.tooltip = function( 'init', { toto : 'bidule' } )

dans le plugin? et dans ce cas comment fait il sa soupe???

merci
Modérateur
method recevra le premier argument passé, dans ce cas 'init', ou si on utilise $.machin( { toto : 'bidule' }) il recevra l'objet { toto : 'bidule' }.

Le reste est récupéré grâce à arguments, qui est une variable contenant un tableau des arguments passés à la méthode, exemple:
function test(){
  if (arguments.length > 2) alert(arguments[2]);
}

test(1,'truc','bidule'); // affichera bidule