Skip to content

Extending jQuery UI Widgets

Last modified February 10, 2015.

This page is obsolete; current versions are on my github pages at github.bililite.com/extending-widgets.html. This page is being kept here for historical purposes.

Avoiding Bloat in Widgets

A while back, Justin Palmer wrote an excellent article on "Avoiding Bloat in Widgets." The basic premise (no suprise to anyone whose ever dealt with object-oriented programming) is that your widgets should not do everything possible; they should do one thing well but be flexible enough to allow others to modify them.

He describes two ways of extending objects: subclassing and aspect-oriented programming (AOP). Subclassing creates new classes, while AOP modfies the methods of a single object. Both can be useful.

So let's make Palmer's Superbox widget (it just moves randomly about the screen with mouse clicks):


var Superbox = {
	_init: function(){
		var self = this;
		this.element.click(function(){
			self.move();
		});
	},
	move: function(){
		this.element.css (this._newPoint());
	},
	_newPoint: function(){
		return {top: this._distance(), left: this._distance()};
	},	
	_distance: function(){
		return Math.round (Math.random()*this.options.distance);
	},
	options: {
		distance: 200
	}
};
$.widget ('ui.superbox', Superbox);

I've factored apart a lot of the code, so we have plenty of "hooks" to use to extend the method without copying code. Note that none of the code refers to "superbox" directly, so we can create subclasses that don't know the superclass's name.

Experiment 1 (Click Me)

Subclassing Widgets

Note that jQuery UI 1.9 incorporates most of these ideas, so you may not need to use $.ui.widget.subclass at all; it is built in. Use $.widget('ui.subclass', $.ui.baseclass);. See my post on this.

Download the code.

The widget factory ($.widget) allows you to use one widget as the base for another, but that's not the same as subclassing; it copies all the methods from one widget to the next.

So let's use real inheritance to make a new class, supererbox, that moves rather than jumps to its new location. I'll use Richard Cornford's variation on Douglas Crockford's prototypal inheritance pattern to simplify subclassing (you could use a fancier one like Dean Edward's Base, or manipulate prototypes yourself). I'll use Dean Edward's technique for calling overridden superclass functions.


var object = (function(){
    function F(){}
    return (function(o){
        F.prototype = o;
        return new F();
    });
})();

And create an empty "base" widget class.


$.widget('ui.widget',{});

And add a method to create subclasses that inherit from the base.


var OVERRIDE = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/; 
$.ui.widget.subclass = function subclass (name){
	$.widget(name,{}); // Slightly inefficient to create a widget only to discard its prototype, but it's not too bad
	name = name.split('.');
	var widget = $[name[0]][name[1]], superclass = this, superproto = superclass.prototype;
	
	
	var args = $.makeArray(arguments); // get all the add-in methods
	var proto = args[0] = widget.prototype = object(superproto); // and inherit from the superclass
	$.extend.apply(null, args); // and add them to the prototype
	widget.subclass = subclass;
	
	// Subtle point: we want to call superclass _create, _init and _destroy if they exist
	// (otherwise the user of this function would have to keep track of all that)
	// and we want to extend the options with the superclass's options. We copy rather than subclass
	// so changing a default in the subclass won't affect the superclass
	for (key in proto) if (proto.hasOwnProperty(key)) switch (key){
		case '_create':
			var create = proto._create;
			proto._create = function(){
				superproto._create.apply(this);
				create.apply(this);
			};
		break;
		case '_init':
			var init = proto._init;
			proto._init = function(){
				superproto._init.apply(this);
				init.apply(this);
			};
		break;
		case 'destroy':
			var destroy = proto.destroy;
			proto.destroy = function(){
				destroy.apply(this);
				superproto.destroy.apply(this);
			};
		break;
		case 'options':
			var options = proto.options;
			proto.options = $.extend ({}, superproto.options, options);
		break;
		default:
			if ($.isFunction(proto[key]) && $.isFunction(superproto[key]) && OVERRIDE.test(proto[key])){
				proto[key] = (function(name, fn){
					return function() {
						var tmp = this._super;
						this._super = superproto[name];
						try { var ret = fn.apply(this, arguments); }   
						finally { this._super = tmp; }					
						return ret;
					};
				})(key, proto[key]);
			}
		break;
	}
};

And use it like this to create a new, subclassable superbox and a subclass of that:


$.ui.widget.subclass('ui.superbox',{
	_init: function(){
		var self = this;
		this.element.click(function(){
			self.move();
		});
	},
	move: function(){
		this.element.css (this._newPoint());
	},
	_newPoint: function(){
		return {top: this._distance(), left: this._distance()};
	},	
	_distance: function(){
		return Math.round (Math.random()*this.options.distance);
	},
	options: {
		distance: 200
	}
});

$.ui.superbox.subclass ('ui.supererbox', {
	// overriding and new methods
	move: function(){
		this.element.animate(this._newPoint(), this.options.speed);
	},
	home: function(){
		this.element.animate({top:0, left:0}, this.options.speed);
	},
	options: {
		speed: 'normal'
	}
});

The function signature is $.namespace.widget.subclass(name <String>, [newMethods <Object>]*), where you can use as many newMethod objects as you want. This lets you use mixin objects, like $.ui.mouse, that add a specific set of methods.

We now have a new widget called supererbox that is just like superbox but moves smoothly.

Experiment 2 (Click Me)

Calling Superclass Methods

If we want to use the superclass methods in our method, we use this._super:


$.ui.supererbox.subclass('ui.superboxwithtext', {
	move: function(){
		this.options.count = this.options.count || 0;
		++this.options.count;
		this.element.text('Move number '+this.options.count);
		this._super(); 
	}
});
Experiment 3 (Click Me)

Aspect Oriented Programming

Aspect oriented programming allows the user of an object to modify its behavior after it has been instantiated. New methods don't so much override the old ones as supplement them, adding code before or after (or both) the original code, without hacking at the original class definition.

We'll add methods for widgets that are stolen straight from Justin Palmer's article:


$.extend($.ui.widget.prototype, { // note that we could extend $.Widget.prototype to add these to all widgets, rather than ones descended from $.ui.widget
	yield: null,
	returnValues: { },
	before: function(method, f) {
		var original = this[method];
		this[method] = function() {
			f.apply(this, arguments);
			return original.apply(this, arguments);
		};
	},
	after: function(method, f) {
		var original = this[method];
		this[method] = function() {
			this.returnValues[method] = original.apply(this, arguments);
			return f.apply(this, arguments);
		}
	},
	around: function(method, f) {
		var original = this[method];
		this[method] = function() {
			var tmp = this.yield;
			this.yield = original;
			var ret = f.apply(this, arguments);
			this.yield = tmp;
			return ret;
		}
	}
});

And now we can use these methods in our code.

For example, let's say we have a cool plugin to make an element pulsate (I know, UI has a pulsate method that does this):


$.fn.pulse = function (opts){
	opts = $.extend ({}, $.fn.pulse.defaults, opts);
	for (i = 0; i < opts.times; ++i){
		this.animate({opacity: 0.1}, opts.speed).animate({opacity: 1}, opts.speed);
	}
	return this;
};
$.fn.pulse.defaults = {
	speed: 'fast',
	times: 2
};

And we'll create a supererbox object, then make it pulse before moving:


$('#experiment4').supererbox().supererbox('before','move', function() {
	this.element.pulse();
});
Experiment 4 (Click Me)

Or even make it pulse before and after moving:


$('#experiment5').supererbox().supererbox('around','move', function() {
	this.element.pulse();
	this.yield();
	this.element.pulse();
});
Experiment 5 (Click Me)

Note that we didn't create any new classes to get this new behavior; we added the behavior to each object after the object was created.

Note that I did not use the widget factory directly. It may be possible to make this more efficient, but I haven't analyzed the code in jQuery UI 1.8 closely enough.

{ 43 } Comments

  1. Ramin | March 7, 2009 at 11:51 am | Permalink

    Fantastic article. I feel +20 smarter now.

  2. inktri | March 7, 2009 at 2:12 pm | Permalink

    Hey,

    I’m having a problem extending a widget pre-defined in jQuery UI. I’ve tried this: $.ui.widget.subclass(‘ui.dialogSubclass’, $.ui.dialog.prototype); but I get an error in the UI js file: (this.uiDialogTitlebarCloseText = c(“”)).addClass(“ui-icon ui-icon-closethick”).text(m.closeText).appendTo is not a function.

  3. Danny | March 8, 2009 at 8:21 am | Permalink

    @inktri:
    That looks right, but I haven’t used ui.dialog so I don’t know anything about its internal code. Looking at the dialog code, there’s a line about this.uiDialogTitlebarCloseText = $('<span/>') but it ought to work. I don’t know what the c("") is from.

    -Danny

  4. Ethan | April 2, 2009 at 5:12 am | Permalink

    Thanks ! good job ! I am going to implement the inheritance in this way.

  5. Jeremy | April 21, 2009 at 10:50 am | Permalink

    This is very useful but I am having some trouble with the inheritance pattern. Let’s say I subclass a button class that I made (ui.button) to be a menubutton (ui.menuButton) that pops open a menu. The button superclass has a disable function that menubutton inherits. Later, I want to disable all the buttons but
    $(‘.Button’).button(‘disable’);
    doesn’t disable any of the menu buttons. I have to do:
    $(‘.Button’).menuButton(‘disable’);
    which means I cant use the menuButton as the superclass. But when I grab all the buttons that way I don’t know which one I have. Have you run into this? Any ideas for a workaround?

    Thanks,
    Jeremy

  6. Jeremy | April 21, 2009 at 12:36 pm | Permalink

    Okay, some more digging and it looks like the problem is the way the widget factory stores the reference to the widget in $.data. It uses the widget name as the secondary key so calling disable method like this:
    $(‘.Button’).button(‘disable’) leads to a
    $.data(element, ‘button’) call to get the instance. If it is actually a menuButton that call returns nothing.

    Changing ui.core to use a static key like ‘instance’ fixes the problem and I all my inheritance starts working.

    What I can’t figure out is what is gained from using the widget name as the key??

  7. Danny | April 22, 2009 at 7:19 pm | Permalink

    @Jeremy:
    You’re right; but it’s a feature, not a bug :). The idea is that you could have multiple widgets associated with a single element (say, $(selector).draggable().datepicker() so each needs its own key.
    One workaround (with its own set of potential problems) would be to set the ‘button’ data in the _init method:
    $.ui.widget.subclass(‘ui.button’, {
    _init: function() { this.element.data(‘button’, this) }
    }
    Now all subclasses will explicitly set the data with the ‘button’ key

  8. Jeremy | May 6, 2009 at 4:53 pm | Permalink

    Hmm… I still think of it as a bug. Inheritance is really important to me (much more important than being able to have compound widgets as you suggest was the reason for the “feature”) and it seems fundamentally broken right now. I guess I will try your solution rather than mine of modifying ui.core but I really hope there will be an elegant way to extend widgets soon. Maybe you could work your solution into your widget subclassing function??

  9. Danny | May 6, 2009 at 8:37 pm | Permalink

    @Jeremy:
    I hear you; I originally implemented it your way but changed when this way turned out to be more useful for what I wanted to do.
    You could modify the $.ui.widget.subclass function; before the for (key in proto) if (proto.hasOwnProperty(key)) switch (key){ line insert:

    var _init = proto._init;
    proto._init = function() { this.element.data(name, this); if (proto.hasOwnProperty('_init')) _init.apply(this); };

    This will make each base class add data under its own name. I think that will work.
    Good luck.
    –Danny

  10. Jon | May 12, 2009 at 10:07 am | Permalink

    I have been writing a series of widgets and I want to a method that is bound as an event like
    .bind(“click”, {self:this}, this.method)
    then in the this.method i can access the widget instance like
    method: function(event){var self = event.data.self;}
    this works ok. next i want to write a child widget class which has its own this.method bound as an event in the same way. but this time i want to call the super classes event method from inside the new method, i have discovered that
    method: function(event){var self = event.data.self;self._super(event)}
    does not work, is this possible to fix?

    Thank you
    Jon

  11. Danny | May 12, 2009 at 3:22 pm | Permalink

    @Jon:
    The _super method is magic; the subclassing code scans the methods for calls to it, and if found, creates a function that changes _super to refer to the superclass’s method. That means that you can’t use it in a function that is defined later.
    You have to call the superclass method directly: $.ui.superclass.methodName.apply(this, arguments), which does the same thing but is more verbose.
    –Danny

  12. Jon | May 13, 2009 at 7:06 am | Permalink

    Thanks for your help, it gave me somewhere to start looking, but $.ui.mysuperclass is a function (the constructor?) and doesnt have any of my widget methods.

    function (element, options) {
    var self = this;
    this.namespace = namespace;
    this.widgetName = name;
    this.widgetEventPrefix = $[namespace][name].eventPrefix || name;
    this.widgetBaseClass = namespace + “-” + name;
    this.options = $.extend({}, $.widget.defaults, $[namespace][name].defaults, $.metadata && $.metadata.get(element)[name], options);
    this.element = $(element).bind(“setData.” + name, function (event, key, value) {if (event.target == element) {return self._setData(key, value);}}).bind(“getData.” + name, function (event, key) {if (event.target == element) {return self._getData(key);}}).bind(“remove”, function () {return self.destroy();});
    }

    Jon

  13. Danny | May 13, 2009 at 7:53 am | Permalink

    @jon:
    I think I missed a phrase in there. Try:
    $.ui.mysuperclass.prototype.methodName.apply(this, arguments)
    –Danny

  14. Jeremy | May 20, 2009 at 5:24 pm | Permalink

    Just got back to this. Anyway, what you suggest seems to work (name should just be the second part of the name) but there are definitely issues. The one I am most bothered by is that every level of subclassing will result in a copy of the parent’s functions being added to $.data. So, if I subclass a widget that has a disable method 4 times there will be 4 disable methods hanging around.

    You mention that the way you ended up implementing it was more useful – I would be interested in hearing why.

    Thanks,
    Jeremy

  15. Danny | May 20, 2009 at 7:38 pm | Permalink

    @Jeremy:
    You are right about name; it should be name[1].
    The widget methods are part of the object’s prototype; they do not get copied when subclassed. That’s the part of the beauty of prototype-based inheritance. So:
    $.ui.widget.subclass('ui.thing1', { method1: function(){} });
    $ui.thing1.subclass('ui.thing2, {method2: function(){} });

    does not copy method1; $().thing2('method1') calls thing1‘s method1.
    In terms of copying the $.data, each this.element.data(name[1], this); does not create a new copy of this; it just adds a new element to the data pointing to the same this. So even if you subclass 4 times, when you execute _init the this.element.data line is referring to the same this (the widget object) 4 times, assigning a new name to the data each time.
    The way I implemented it, the widget object is only assigned to the data under its own name, not the parent classes. This allows me to use multiple widgets on the same element.
    –Danny

  16. Ethan | June 16, 2009 at 8:06 pm | Permalink

    Hey Danny,
    I ‘ve been using the way you implement inheritance for a while, it is amazing. however,I come across a problem when I override Function.prototype.toString to be :
    Function.prototype.toString = function() { return “function code hidden.”; };

    After I did this, this regular expression [test(function(){xyz;}) ? /\b_super\b/ : /.*/; ] doesn’t work correctly so that in the conditional expression below would return a false ,then finally the ‘this._super’ mechanism is gone.

    regular expression:
    [test(function(){xyz;}) ? /\b_super\b/ : /.*/;

    conditional expression:
    $.isFunction(proto[key]) && $.isFunction(superproto[key]) && OVERRIDE.test(proto[key])
    here the OVERRIDE.test(proto[key]) always return false when i override the Funtion.prototype.toString method

    due to i am not good at regular expression at all, i have no idea how to fix this.how can I solve this?

  17. Danny | June 17, 2009 at 8:51 am | Permalink

    @Ethan:
    The purpose of the regular expression is to see if _super is used, because if it is not, it’s inefficient to set it up in every widget. If you’re hiding the source (not sure why, but it’s your program) then that won’t work.
    Remove the && OVERRIDE.test(proto[key]) entirely. Each method will now go through a closure to create _super, so it may be slower, but it will work.
    –Danny

  18. Ethan | June 25, 2009 at 4:22 am | Permalink

    Thanks a lot Danny. Now I understand.
    Cheers . -:)

  19. Felix | July 4, 2009 at 6:19 am | Permalink

    Hey Danny,

    i tried to extend jQuery Tabs with the AOP method. Without succes.

    Could you provide a working example in a zip? Like you did for the superclass method. Would be very helpful to understand.

    greetings felix

  20. Danny | July 5, 2009 at 9:14 pm | Permalink

    @Felix:
    The code above is working with AOP. You can see other examples of it in the end of my post about flexcal.
    To get it to work with an existing widget, you would have to add the methods to the widget prototype. Try:

    
    $.extend($.ui.tabs.prototype, {
      yield: ...,
      returnValues: ...,
      before: ...,
      after: ...,
      around: ...,
    });
    

    before you use $().tabs().
    –Danny

  21. Soheil | September 3, 2009 at 8:03 am | Permalink

    Hey Danny,
    Thanks for the useful tutorial.
    I’m writing some widgets and would like to make subclasses, or inherit from the jQuery’s ui library components. e.g. I want to have a “pager” component which is a subclass of jQuery’s ui.tabs, and I would like to override the _init() or _tabify() methods in order to create a new look for my “pager” component.
    If I got your tutorial right, I’ll have to copy-paste all the “ui.tabs.js” codes into a new file like “ui.tabs.subclassable.js” (because I don’t want to change the original files) and use $.ui.widget.subclass(‘ui.tabs’, {}) instead of $.widget(‘ui.tabs’, {}) … now I have a problem with this, every time a new version of ui.tabs.js is released I’ll have to change the file or copy-paste codes into subclassable file again. Is there any way to avoid this? I mean is there a way for using subclasses without changing the original ui library files?
    Thanks…

  22. Soheil | September 3, 2009 at 11:21 am | Permalink

    about my previous comment; I tried this:
    $.widget(“ui.pager”, $.extend({}, $.ui.tabs.prototype, {…});
    It is working… so why should we use this subclass widget? Isn’t it easier just to extend the widget and override some of the methods?

  23. Danny | September 3, 2009 at 11:35 pm | Permalink

    @Soheil:
    You are right; there isn’t much difference between $.ui.widget.subclass ('ui.pager, $.ui.tabs.prototype, {...}) (using my code) and $.widget('ui.pager', $.extend({}, $.ui.tabs.prototype, {...})). The advantages are:

    1. Slightly shorter
    2. Ability to use _super rather than $.ui.tabs.prototype.methodName
    3. Actually uses the prototype chain rather than copying, so changes to $.ui.tabs.prototype and $.ui.tabs.defaults are reflected in $.ui.pager

    The aspect-oriented code you could mix in to your derived widget, just as with $.ui.mouse.
    Bottom line: you may find it useful; I certainly have. If you want to use it to subclass existing widgets, I would first do
    $.ui.widget.subclass('ui.subclassabletabs', $.ui.tabs.prototype) and then $.ui.subclassabletabs.subclass('ui.pager', {...}) to get all the advantages.

  24. Soheil | September 4, 2009 at 9:03 am | Permalink

    Thnaks Danny, that’s nice…

  25. andrew | February 17, 2010 at 1:47 am | Permalink

    @inktri: @danny and for anyone trying to use this to extend jquery ui.dialog i’ve found that you’ll need to fix the .text(undefined) being thrown by the line mentioned in your comment.

    for what it’s worth, it’s line 122 in v1.7.2 of ui.dialog.js
    from

    .text(options.closeText)
    to
    .text((options.closeText || ”)),

    maybe you can explain why exactly extension fails on this internally???

    i understand that .text(undefined) is returning a null therefore .appendTo() doesn’t exist and error, but what’s going on here under the hood?

    Thanks for the great article, i’ve learned tons tonight. With this small fix i’m able to extend the ui.dialog also

  26. Danny | February 19, 2010 at 12:17 pm | Permalink

    @andrew:
    Though I haven’t looked at it directly, I suspect we’ve got a problem that exists in many of the overloaded jQuery functions: .text('foo') sets the text and returns a jQuery object while .text() returns the text. .text(undefined) is probably interpreted as .text() and doing the wrong thing.
    That’s my guess.
    –Danny

  27. Valentino | February 28, 2010 at 4:21 am | Permalink

    Great article. I found it really helpfull.

    Just one note.

    I think that this part is incorrect: “The astute reader will have noticed that level is a class variable; the same variable is used for every green3 object. This is clearly not what we want; each instance should have its own copy”

    It looks to me that jQuery UI create an instance of our prototype for each object. So you coul safely use this.level, and it will be a different variable for each object.

    I noticed this because some jQuery UI widgets just store variables using this.name_variable.
    For instance, the accordion widget save the headers elements as “this.headers”

    Thanks anyway for this great article, it’s so usefull that there should be an official copy on the jQuery UI doc

    _Valentino

  28. Danny | February 28, 2010 at 4:17 pm | Permalink

    @Valentino:
    I think you actually meant this comment for the Widget Tutorial. Notwithstanding that, there’s a subtlety here about how javascript handles prototypal inheritance: level is a variable in the prototype, so it is not copied into each instance. this.level refers to the prototype’s level, which is shared with all instances. the general rule: when I refer to this.foo, Javascript searched the object for a property named foo, then the object’s prototype, then the prototype’s prototype, etc. If nothing is found, a new property is created in the individual object.
    –Danny

  29. Christoph | March 12, 2010 at 4:54 am | Permalink

    Hey Danny,
    just a minor quirk I encountered, when using Dojo Shrinksafe compression (don’t ask me why ;).

    In the line: widget.subclass = subclass;
    The “subclass” function reference is treated as an internal variable, and thus hashed to:
    widget.subclass = _10;

    Which of course fails at runtime.
    I fixed that by using the namespaced function ref:

    widget.subclass = $.ui.widget.subclass;

    Other than that, works great.

    Christoph

  30. Danny | March 14, 2010 at 1:38 am | Permalink

    @Christoph:
    That’s got to be one of those quirk about named functions that is so inconsistent between javascript implementations. This one works in all the major browsers but evidently Dojo’s Shrinksafe parses the javascript differently. Thanks for the heads up!
    (And why were you using Dojo? I had to ask! :) )
    –Danny

  31. alpha | March 24, 2010 at 2:52 pm | Permalink

    very nice tutorial.
    I got a issue when a call to destroy is made: $.widget.prototype.apply is not a function
    any clue?

  32. Danny | March 24, 2010 at 9:01 pm | Permalink

    @alpha:
    jQuery UI 1.8 just came out and broke everything. I’m going to have to rewrite this, sometime over the next two weeks, to use the new widget factory. I think it will be better, but don’t count on anything working (or go back to jQuery 1.7.2) until then.
    –Danny

  33. Lee | July 6, 2010 at 8:25 am | Permalink

    I can’t seem to catch any events I trigger in these widget subclasses. I call this._trigger as usual but can not seem to catch the event in the normal way.

  34. Danny | July 13, 2010 at 8:28 pm | Permalink

    @Lee:
    I haven’t had any problems with event triggering, but I may not be using the code the same way you are. Can you post some more details?
    –Danny

  35. Lee | July 19, 2010 at 6:58 am | Permalink

    @Danny:
    Hopefully this bit of code sums it up:

    $.ui.widget.subclass(‘ui.superwidget’,
    {
    _init: function()
    {
    // can’t catch this
    this._trigger(‘anevent’);

    // can catch this
    this.element.trigger(‘superwidgetanevent’);
    }
    });

    And creation and binding:
    $(‘#test’).bind(‘superwidgetanevent’, function()
    {
    console.log(‘an event happened’)
    });
    $(‘#test’).superwidget();

  36. Danny | July 22, 2010 at 4:04 pm | Permalink

    @Lee
    Unfortunately, my life is kind of busy now, but I’ll try to take a look at this. It looks like it ought to work, but there may be something going on where the event handler is being bound before the subclass really exists, so it’s binding to the superclass.
    Danny

  37. Saudi Jobs | September 10, 2010 at 5:39 pm | Permalink

    Nice work man.Thanks for sharing jQuery UI Widgets.

  38. darkside | September 15, 2011 at 4:18 pm | Permalink

    @inktri
    You should use $.extend(true, …, …) for recursive extending objects

  39. Nolege | January 7, 2013 at 7:13 pm | Permalink

    Worked Great for 1.8. Breaks for new 1.9 release. Just
    letting you know because I upgraded and need to fix the changes.
    Thanks.

  40. Danny | January 7, 2013 at 9:39 pm | Permalink

    @Nolege:
    I suspect that’s because 1.9 adds a _super method of its own, though it is not as sophisticated as mine—you have to explicitly give it the name of the method. Did you fix it? I hope that all I would have to do is to change my _super to $super or something. Google Library API is still serving 1.8.7, so I don’t feel the pressure yet.

    Have you gotten it to work? What did you do?
    –Danny

  41. Danny | January 8, 2013 at 8:53 am | Permalink

    @Nolege:
    I fixed it. Turns out 1.9’s _super method is my method; I’d been in contact with Scott Gonzalez a while back and he incorporated many of my ideas. So that’s not the conflict.
    The problem is that 1.9 changed to use the prototype passed to $.widget (the documentation always required that second parameter, just before this having it undefined did not throw an error), so just change any $.widget('name') to $.widget('name', {}) and you’re done. I think.
    –Danny

  42. Vikram Lele | December 31, 2013 at 11:21 pm | Permalink

    Hi Danny,

    Thanks for an excellent article on widget subclassing.

    I still have a bit of a confusion about how to achieve “virtual” function effect here. For example, in the subclass code

    $.ui.widget.subclass(‘ui.superbox’,{
    _init: function(){
    var self = this;
    this.element.click(function(){
    self.move();
    });
    },

    you have hooked the click again in the subclass. This is actually already hooked in the base widget. So, is there a way to provide a new implementation of move() in the derived widget and make it work without explicitly hooking into click once again?

  43. Danny | January 1, 2014 at 10:58 am | Permalink

    @Vikram Lele:
    The base widget, $.ui.widget that is created with $.widget('ui.widget',{}); does not hook into the click event. The only click handler is in the first subclass, $.ui.superbox, created with the code you quoted above. All of its subclasses just override move() but rely on the same event handler.

    I think your confusion is looking at the sample code at the very top of the page, when I create $.ui.superbox without using the subclassing code. That’s just a sample of how to create a simple widget; the code you quote is supposed to replace that. Note that the actual code is almost identical.

    Hope this helps,
    –Danny

{ 4 } Trackbacks

  1. […] jQuery UI Widget inheritance | fvrier 13, 2010 Je n’ai trouv que trs peu de ressources sur le web illustrant cette technique. Ma seule trouvaille fut celle-ci. […]

  2. […] ui factory. Insbesondere wre wohl die ui.progressbar fr dich interessanter. ui developer guide extending ui widgets richtig gutes Tutorial auf deutsch: ui factory am Beispiel einer canvas map I ui factory am […]

  3. […] http://bililite.nfshost.com/blog/extending-jquer&#8230; http://bililite.nfshost.com/blog/extending-jquery-ui-widgets/ […]

  4. links for 2010-11-14 at Here I Rule | November 14, 2010 at 6:36 pm | Permalink

    […] Hacking at 0300 : Extending jQuery UI Widgets (tags: extending jquery-ui widget howto) VN:F [1.9.6_1107]please wait…Rating: 0.0/10 (0 votes cast)VN:F [1.9.6_1107]Rating: 0 (from 0 votes) […]

Post a Comment

Your email is never published nor shared. Required fields are marked *