JQuery Plugin Development, how to keep variables and methods private

For exercise purposes, I create a jQuery plugin, a simple image slider. I use the template from the Boilerplate - jQuery plugins .

During the initialization process, everything works as expected, each instance receives the correct values โ€‹โ€‹(width and height, as well as event bindings) needed for configuration.

The problem starts when I try to pass the calculated width of the slides to the function that performs the animation (the next button is pressed). Each value that I tried to save was overwritten with the last instance - well, that is what prototype inheritance does as I found out.

I googled a lot and found (not only) this solution in shareoverflow: global or local variables in jquery-plugin . The accepted answer suggests storing values โ€‹โ€‹that should be private in the HTML markup, the data-whatever attribute.

This works very well, but not very nice.

The second answer seemed more elegant, preserving the real private variables within each instance:

(function($) { $.pluginName = function(element, options) { .... var plugin = this; .... // a public method plugin.foo_public_method = function() { .... } // private methods var foo_private_method = function() { .... } plugin.init(); } .... 

I looked quite simply - but I can not implement this solution!

So my question is: how do I implement a private variable in the following plugin template? (And how do I properly name it from inside Plugin.prototype ...)

I created Fiddle with my plugin. Code Summary:

 (function ($, window, document, undefined) { var pluginName = "easyCarousel"; // default configuration object defaults = { ... default values here, css etc } }; // The actual plugin constructor function Plugin(element, options) { this.element = element; this.options = $.extend({}, defaults, options); this._defaults = defaults; this._name = pluginName; this.init(); } Plugin.prototype = { init: function () { var options = this.options; this.options.stage = $(this.element); .... calling/starting views and controllers }, buildCollectionView: function (options, Helper) { .... setting markup, applying css, calulating dimensions }, buildStageView: function (options, Helper) { .... setting markup, applying css .... storing calculated slide width in data Attribute stage.attr({ 'data-slidewidth': width, 'data-stagewidth': setWidth }); }, buildTheatreView: function (options, Helper) { .... setting markup, applying css }, buildNavigationView: function (options) { .... setting markup }, navigationController: function (options, slideForward, slideBackward) { .... event binding pubSub.on("navigation:arrownext:click", function (e) { slideForward(options, e); }); $('.carousel__arrownext', options.theatre) .bind('click', function () { pubSub.trigger("navigation:arrownext:click", this); }); }, slideForwardAnimation: function (options, e) { .... reading stored width value from data Attribute $element.animate({ "left": "-=" + slideWidth }) }, setDimensionsHelper: function (options) { .... calculating an returning dimensions of the slider }, eventBusHelper: function (options) { // integrating third party eventbus } }; $.fn[pluginName] = function (options) { return this.each(function () { if (!$.data(this, "plugin_" + pluginName)) { $.data(this, "plugin_" + pluginName, new Plugin(this, options)); } }); }})(jQuery, window, document); 

I hope my sample code will not be complicated / long to view.

As you can see, I'm new to advanced Javascript templates - and now I'm really stuck. I spend many hours on this problem. Therefore, every attempt to help is greatly appreciated. Also, of course, every code review.

Thank you in advance:)

+6
source share
1 answer

All you have to do is define the variables in your prototype (directly or from within the method in the prototype), and not do it in your constructor. The variables defined in the constructor will be shared between all instances of your plugin, while the variables defined in the prototype will be for each instance.

In addition, you do not have the keyword โ€œvarโ€ before your definition of โ€œdefaultโ€, so you are actually creating a global variable called โ€œdefaultโ€, not one that is bound to your closure.

This is what I recommend:

 // default configuration object var defaults = { ... default values here, css etc } }; // The actual plugin constructor function Plugin(element, options) { this._defaults = defaults; this._name = pluginName; this.init(element, options); } Plugin.prototype = { init: function (element, options) { this.element = element; this.options = $.extend({}, this._defaults, options); this.options.stage = $(this.element); .... calling/starting views and controllers }, 

or even better:

 // The actual plugin constructor function Plugin(element, options) { this.init(element, options); } Plugin.prototype = { _name: 'put your name here', _defaults: { // just define them here, no need for an outside variable }, init: function (element, options) { this.element = element; this.options = $.extend({}, this._defaults, options); // why are you saving stage as an option? That doesn't make sense. this.options.stage = $(this.element); // Makes more sense to just do this ($el is a more standard name for this) this.$el = $(this.element); // .... calling/starting views and controllers }, 
+3
source

Source: https://habr.com/ru/post/989290/


All Articles