0

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 Answer 1

2

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/

Sign up to request clarification or add additional context in comments.

2 Comments

Makes perfect sense. However, as an extension to the original question, why does the 'something' object in the following example not behave the same? The only difference is it's not nested within another object. jsfiddle.net/NrKVP/11
Because that something is set directly on the object (this.something = ...) but this._glbl isn't on this, it comes from this's prototype. Add console.log('---->', this.hasOwnProperty('_glbl'), this.hasOwnProperty('something')); at the bottom of _create and read about hasOwnProperty.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.