Is it good or bad practise writing plugins this way(using class and prototypes), what are disadvatages of this code?
function PluginName(jqueryObject, options) {
First, as Spycho said, always wrap your plugin in
(function( $ ){
$.fn.PluginName = function() {
// plugin goes here
};
})( jQuery );
to avoid conflict with other libraries that use the dollar sign.
Second, if you extend the jQuery.fn
object the selection called with something like $("#myDiv")
is passed to the plugin as this
. This way you don't have to pass the selection as a parameter to the plugin as you've done.
Third, this you did correctly, they suggest that you pass options to the plugin as an object rather than individual parameters, this is so you can easily have and override defaults:
(function( $ ){
$.fn.PluginName = function(options) {
var settings = { myOption: 1 };
if (options) {
$.extend( settings, options );
}
// plugin goes here
};
})( jQuery );
Fourth, the way you've created your _privateMethod
doesn't actually make it private, to do so you could follow the pattern jQuery suggests in the plugin authoring guidelines
(function( $ ){
var methods = {
publicMethod: function(options) {
var settings = { myOption: 1 };
if (options) {
$.extend( settings, options );
}
},
_privateMethod: function() {}
}
$.fn.PluginName = function(methodName, options) {
// use some logic to control what methods are public
if (methodName == "publicMethod") {
return publicMethod.apply(this, Array.prototype.slice.call( arguments, 1 ));
}
};
})( jQuery );
This uses apply
and call
which are fancy built-in methods of functions for setting the scope of function calls, see the MDN reference to understand what is going on there. This way you actually have control over which methods are public versus private.
EDIT: Finally, if you want to completely maintain jQuery's fluid interface and have your plugin both accept the selection passed by $()
and pass it on, in other words, be chainable, your methods need to return the collection of objects they were given:
(function( $ ){
var methods = {
publicMethod: function(options) {
var settings = { myOption: 1 };
if (options) {
$.extend( settings, options );
}
return this.each(function() {
this.value = (this.value * 1) + settings.myOption;
});
},
_privateMethod: function() {}
}
$.fn.PluginName = function(methodName, options) {
// use some logic to control what methods are public
if (methodName == "publicMethod") {
return methods.publicMethod.apply(this, Array.prototype.slice.call( arguments, 1 ));
}
};
})( jQuery );
See this jsFiddle for the final working example.
The easiest way to write jQuery plugins (especially if they have some internal state) is to use jQuery UI Widget Factory.
I wouldn't recommend to reinvent the wheel and write lots of boilerplate code by yourself.
https://learn.jquery.com/jquery-ui/widget-factory/why-use-the-widget-factory/ https://learn.jquery.com/plugins/stateful-plugins-with-widget-factory/
See the jQuery docs on plugin authoring for best practices:
(function( $ ){ // plugin goes here })( jQuery );
(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 );
Usage:
$('div').tooltip(); // calls the init method
$('div').tooltip({ // calls the init method
foo : 'bar'
});
$('div').tooltip('hide'); // calls the hide method
$('div').tooltip('update', 'This is the new tooltip content!'); // calls the update method
(function( $ ){
$.fn.tooltip = function( options ) {
var settings = {
'location' : 'top',
'background-color' : 'blue'
};
return this.each(function() {
// If options exist, lets merge them
// with our default settings
if ( options ) {
$.extend( settings, options );
}
// Tooltip plugin code here
});
};
})( jQuery );
Usage:
$('div').tooltip({
'location' : 'left'
});