Object in jquery widget behaving as only one instance

334 views Asked by At

I've been developing a jQuery widget using the widget factory.

All is well except I've noticed that if I instantiate the widget on more then one DOM element on the same page, any object within the widget is shared between the DOM elements EXCEPT for the options object.

I thought that all objects and functions had their own instance within the widget. I'm obviously missing something and would appreciate some guidance.

For example:

(function($) {
  $.widget("a07.BearCal", {
    options: { className : "test" },
    _glbl: { something: "" },
    _create: function() {
      this._glbl.something = this.element.attr('class');
      this.options.className = this.element.attr('class');
    },
  });
})(jQuery);

// Instantiate widget on .full
$('.full').BearCal();

//Should output full
console.log($('.full').data('BearCal')._glbl.something);

//Should output full
console.log($('.full').data('BearCal').options.className);

// Instantiate widget on .mini
$('.mini').BearCal();

//Should output mini
console.log($('.mini').data('BearCal')._glbl.something);

//Should output mini
console.log($('.mini').data('BearCal').options.className);

//Should output full but outputs mini
console.log($('.full').data('BearCal')._glbl.something);

//Should output full
console.log($('.full').data('BearCal').options.className);​

Working example of this: http://jsfiddle.net/NrKVP/4/

Thanks in advance!

1

There are 1 answers

2
mu is too short On BEST ANSWER

The properties of your widget:

$.widget("a07.BearCal", {
  // The stuff in here...
});

get attached to your widget's prototype. The widget factory knows about options and knows that it needs to duplicate them per-widget: your options are behaving as you expect because the widget factory arranges for this behavior. The widget factory doesn't know anything about _glbl so it gets left on the prototype and thus shared by all instances of your widget.

You can duplicate your _glbl yourself if you want per-widget copies:

  this._glbl = { something: this.element.attr('class') };

That will give you a different _glbl object on each widget.

Demo: http://jsfiddle.net/ambiguous/UX5Zg/

If your _glbl is more complicated, then you can use $.extend to copy it and merge something in:

this._glbl = $.extend(
  { },
  this._glbl,
  { something: this.element.attr('class') }
);

You'll want to use true as the first argument to $.extend if you need a deep copy. The empty object, { }, is needed as $.extend will merge everything into its first object argument and you want a fresh copy.

Demo: http://jsfiddle.net/ambiguous/pyUmz/1/