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.