Understanding jQuery UI widgets: A tutorial
This page is obsolete; current versions are on my github pages at github.bililite.com/understanding-widgets.html. This page is being kept here for historical purposes.
This was written largely to help me make sense of using UI to create my own widgets,
but I hope it may help others. "Widget" to me means a user-interface element, like
a button or something more complicated like a popup date picker, but in jQuery UI terms
it means a class, members of which are associated with HTML elements; things like
Draggable and
Sortable.
In fact, not everything that I would have called a widget uses $.widget
; the UI datepicker does not.
Dan Wellman has another tutorial that you may find helpful.
Modifying Elements: Plugins
That being as it may, let's use $.widget
.
Let's take a paragraph of class target:
<p class="target">This is a paragraph</p>
And lets make it green. We know how; $('.target').css({background: 'green'})
.
Now, make it more general-purpose: a plugin:
$.fn.green = function() {return this.css({background: 'green'})};
But this allows us to perform some behavior on the selected elements; it does not leave us with any way to
keep our plugin associated with that element, so we can do something with it later, like
$('.target').off()
to remove the green background, but only if we used green to
put it there in the beginning. We also have no way of associating
state with the element, to do $('.target').darker(), which would require knowing how green the element is now.
Keeping State in Plugins
We could create an object and associate it with an element using javascript expandos:element.myobject = new Myobject({'target': element})
. Sample code would be:
$.fn.green2 = function() {
return this.each(function(){
if (!this.green) this.green = new Green($(this)); // associate our state-keeping object with the element
this.green.setLevel(15);
});
};
$.fn.off = function() {
return this.each(function(){
if (this.green) this.green.setLevel(16);
delete this.green; // recover the memory
});
};
$.fn.darker = function() {
return this.each(function(){
if (this.green) this.green.setLevel(this.green.getLevel()-1);
});
};
$.fn.lighter = function() {
return this.each(function(){
if (this.green) this.green.setLevel(this.green.getLevel()+1);
});
};
function Green(target){
greenlevels = ['#000','#010','#020','#030','#040','#050','#060','#070','#080','#090','#0a0','#0b0','#0c0','#0d0','#0e0','#0f0','#fff'];
this.target = target; // associate the element with the object
this.level = 0;
this.getLevel = function() { return this.level; }
this.setLevel = function(x) {
this.level = Math.floor(Math.min(greenlevels.length-1, Math.max(0,x)));
this.target.css({background: greenlevels[this.level]});
}
};
But this pollutes the $.fn
namespace terribly, with off
, darker
and lighter
.
There are ways to create real namespaces within $.fn
, but the usual design pattern is to use a string to
specify which function to call. Thus, element.green2()
to instantiate the plugin,
element.green2('darker')
or element.green2('lighter')
to manipulate it:
$.fn.green2 = function(which){
return this.each(function(){
if (which === undefined){ // initial call
if (!this.green) this.green = new Green($(this)); // associate our state-keeping object with the element
this.green.setLevel(15);
}else if (which == 'off'){
if (this.green) this.green.setLevel(16);
delete this.green
}else if (which == 'darker'){
if (this.green) this.green.setLevel(this.green.getLevel()-1);
}else if (which == 'lighter'){
if (this.green) this.green.setLevel(this.green.getLevel()+1);
}
});
};
function Green(target){
greenlevels = ['#000','#010','#020','#030','#040','#050','#060','#070','#080','#090','#0a0','#0b0','#0c0','#0d0','#0e0','#0f0', '#fff'];
this.target = target; // associate the element with the object
this.level = 0;
this.getLevel = function() { return this.level; }
this.setLevel = function(x) {
this.level = Math.floor(Math.min(greenlevels.length-1, Math.max(0,x)));
this.target.css({background: greenlevels[this.level]});
}
};
<p class="target">This is a test paragraph</p>
The Problems with Associating an Object with a Plugin
But you get into trouble with circular
references (note that "this.green = new Green($(this))
" gives a DOM element a reference to a javascript object
and
"this.target = target
" gives a javascript object a reference to a DOM element) and
memory leaks:
browsers (notably Internet Explorer) uses different garbage collectors for DOM elements and javascript objects.
Circular references mean that each garbage collector thinks the other object is in use and won't delete them.
We also need to remember to reclaim the memory (with delete
) if we no longer need the plugin.
jQuery solves the circular reference problem with the $.fn.data
plugin:
$(element).data('myobject', new Myobject({'target': element}))
. But now we've got a lot of "paperwork" to
keep track of, and it hides the underlying program logic. As we know,
design patterns reflect language weakness.
If we are
constantly re-implementing a pattern, we need to abstract it and make it automatic.
Solving the Problem: $.widget
That's where$.widget
comes
in. It creates a plugin and an associated javascript class and ties an instance of that class with each
element so we can interact with the object and act on the element, without getting into trouble with
memory leaks.
You still need to create the constructor of your class, but instead of a real constructor function, you need
a prototype object with all the relevant methods. There are a few conventions: the function _create
is called on construction, _init
is called both on construction and for re-initializing
the function and destroy
is called on removal. All of these are predefined as empty functions but you can override them (and most likely
will need to override _init
). element
is the associated jQuery object (what we called target
above).
Widget methods that start with "_
" are pseudo-private; they cannot be called with the $(element).plugin('string') notation
var Green3 = {
_init: function() { this.setLevel(15); },
greenlevels: ['#000','#010','#020','#030','#040','#050','#060','#070','#080','#090','#0a0','#0b0','#0c0','#0d0','#0e0','#0f0', '#fff'],
level: 0,
getLevel: function() { return this.level; },
setLevel: function(x) {
this.level = Math.floor(Math.min(this.greenlevels.length-1, Math.max(0,x)));
this.element.css({background: this.greenlevels[this.level]});
},
darker: function() { this.setLevel(this.getLevel()-1); },
lighter: function() { this.setLevel(this.getLevel()+1); },
off: function() {
this.element.css({background: 'none'});
this.destroy(); // use the predefined function
}
};
Notice it's all program logic, no DOM or memory-related bookkeeping. Now we need to create a name, which must be preceded by a
namespace, like "ns.green
" . Unfortunately the namespacing is fake; the plugin is just called $().green()
. The constructor function
is $.ns.green
, but you never use that, so you might as well use the "official" namespace of "ui
". But defining the widget couldn't be easier:
$.widget("ui.green3", Green3); // create the widget
Manipulating Widgets
What about our manipulating functions? All the functions defined in the prototype that don't start with an underscore are exposed automatically:
$('.target').green3()
creates the widgets; $('.target').green3('darker')
manipulates them.
There are two kinds of plugin functions: getters and setters. Setters manipulate elements and can be chained in jQuery code; they just return the jQuery object they started with. For example, $('.demo').css({color: 'red'}).text('stuff')
. Getters return information and break the chain, like text = $('.demo').text()
. widget
distinguishes between the two by the return value: if your function returns any value other than undefined
, it assumes that it is a getter and returns that value (for the first element in the jQuery object, just like all jQuery getter functions). If it does not return a value, then it is assumed to be a setter and is called on each element in the jQuery object, and the jQuery object itself is returned for chaining.
<p class="target">This is a test paragraph.</p>
Pass arguments to the manipulating functions after the name: $('.target').green3('setLevel', 5)
.
Data for Each Widget
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.
$.widget defines an object
this.options
for per-widget data.
Thus:
var Green4 = {
getLevel: function () { return this.options.level; },
setLevel: function (x) {
var greenlevels = this.options.greenlevels;
var level = Math.floor(Math.min(greenlevels.length-1, Math.max(0,x)));
this.options.level = level;
this.element.css({background: greenlevels[level]});
},
_init: function() { this.setLevel(this.getLevel()); }, // grab the default value and use it
darker: function() { this.setLevel(this.getLevel()-1); },
lighter: function() { this.setLevel(this.getLevel()+1); },
off: function() {
this.element.css({background: 'none'});
this.destroy(); // use the predefined function
},
options: { // initial values are stored in the widget's prototype
level: 15,
greenlevels: ['#000','#010','#020','#030','#040','#050','#060','#070','#080','#090','#0a0','#0b0','#0c0','#0d0','#0e0','#0f0', '#fff']
}
};
$.widget("ui.green4", Green4);
And on creating an instance of a widget, pass an options object (the way most plugins do)
and override the defaults:
$('.target').green4({level: 8})
.
Note that I also put the list of colors into the defaults object, so it too can be overridden. This widget probably shouldn't be called "green" anymore!
<p class="target">This is a test paragraph.</p>
<p class="target">
This is a test paragraph called with .green4({
level:3,
greenlevels: ['#000','#00f','#088', '#0f0', '#880', '#f00', '#808', '#fff']
}).
</p>
Callbacks, or, Keeping the Lines of Communication Open
The programmer who is embedding our widget in his page may want to do other things when the widget changes state. There are two ways to alert the calling program that something has happened:
- Tightly Coupled
- The caller can provide a function to call at the critical point. jQuery jargon calls this a "callback;" it's used in
animations and
Ajax. We can create callback functions
that the widget calls at critical points, and pass them to the widget-constructing plugin like any other option:
var Green5 = { setLevel: function(x){ //... this.element.css({background: greenlevels[level]}); var callback = this.options.change; if ($.isFunction(callback)) callback(level); }, // ... rest of widget definition }; $.widget("ui.green5", Green5); $('.target').green5({change: function(x) { alert ("The color changed to "+x); } });
- Loosely Coupled
- Also called the Observer Design Pattern, the widget sends a signal to
the programming framework and the calling program informs the framework that it wants to know about the signal. Events like
clicks and keystrokes work like this, and jQuery allows the widget to create custom events and for the calling program to
bind an event handler to that custom event:
var Green5 = { setLevel: function(x){ //... this.element.css({background: greenlevels[level]}); this.element.trigger ('green5change', level); }, // ... rest of widget definition }; $.widget("ui.green5", Green5); $('.target').green5(); $('.target').bind("green5change", function(evt,x) { alert ("The color changed to "+x); });
$.widget
allows both forms with the _trigger
method. In a widget object,
this._trigger(type, event, data)
takes a type {String}
with the
name of the event you want (use some short verb, like 'change'
) and optionally a
$.Event object (if you want to pass things like timestamps and mouse locations.
Don't worry about event.type
; _trigger
changes it to the constructed event name), and any data to be passed
to the handler. _trigger
creates a custom event name of widgetName+type
, like green6change
(why it doesn't do naming events this way has been the subject of some discussion), sets type+'.'+widgetName
the way jQuery expects
is beyond meevent.type = custom event name
(creating a new $.Event
if it was not provided)
and calls this.element.trigger(event, data)
and then looks for a callback with
callback = this._getData(type)
and calls it with
callback.call(this.element[0], event, data)
.
Notice that this means the function signature is slightly different for the event handler and the callback if data
is an array. element.trigger()
uses apply
to turn each item in the array into a separate argument.
So this._trigger('change', 0, ['one', 'two'])
requires an event handler of the form function(event, a, b)
and a callback of the form
function(event, data)
.
In practice, it's not as complicated as it sounds. For example, using both methods:
var Green5 = {
getLevel: function () { return this.options.level; },
setLevel: function (x) {
var greenlevels = this.options.greenlevels;
var level = Math.floor(Math.min(greenlevels.length-1, Math.max(0,x)));
this.options.level = level;
this.element.css({background: greenlevels[level]});
this._trigger('change', 0, level);
},
_init: function() { this.setLevel(this.getLevel()); }, // grab the default value and use it
darker: function() { this.setLevel(this.getLevel()-1); },
lighter: function() { this.setLevel(this.getLevel()+1); },
off: function() {
this.element.css({background: 'none'});
this._trigger('done');
this.destroy(); // use the predefined function
},
options: {
level: 15,
greenlevels: ['#000','#010','#020','#030','#040','#050','#060','#070','#080','#090','#0a0','#0b0','#0c0','#0d0','#0e0','#0f0', '#fff']
}
};
$.widget("ui.green5", Green5);
<p class="target">This is a test paragraph with green level <span class="level">undefined</span>.</p>
// The on button above does the following:
$('.target').green5({
change: function(event, level) { $('.level', this).text(level); } // callback to handle change event
});
$('.target').bind('green5done', function() { $('.level', this).text('undefined');alert('bye!') }); // event handler for done event
Involving the Mouse
Now, a lot of what we want to do with widgets involves mouse tracking, so ui.core.js
provides a mixin object that
includes lots of useful methods for the mouse. All we need to do is add the $.ui.mouse
widget to our
widget prototype:
var Green6 = {mouse-overriding function and widget-specific functions};
$.widget ('ui.green6', $.ui.mouse, Green6);
And override $.ui.mouse
's functions (_mouseStart
,
_mouseDrag
,
_mouseStop
) to do something useful,
and call this._mouseInit
in your this._init
and this._mouseDestroy
in your this.destroy
. The mouse defaults are automagically including in your options object; see the mouse code for details.
Let's add some mouse control to our greenerizer:
Green6 = $.extend({}, $.ui.green5.prototype, { // leave the old Green5 alone; create a new object
_init: function(){
$.ui.green5.prototype._init.call(this); // call the original function
this._mouseInit(); // start up the mouse handling
},
destroy: function(){
this._mouseDestroy();
$.ui.green5.prototype.destroy.call(this); // call the original function
},
// need to override the mouse functions
_mouseStart: function(e){
// keep track of where the mouse started
this.xStart = e.pageX; // not in the options object; this is not something that can be initialized by the user
this.levelStart = this.options.level;
},
_mouseDrag: function(e){
this.setLevel (this.levelStart +(e.pageX-this.xStart)/this.options.distance);
},
options: {
level: 15,
greenlevels: ['#000','#010','#020','#030','#040','#050','#060','#070','#080','#090','#0a0','#0b0','#0c0','#0d0','#0e0','#0f0', '#fff'],
distance: 10
}
});
$.widget("ui.green6", $.ui.mouse, Green6);
<p class="target">This is a test paragraph with green level <span class="level">undefined</span>.</p>
The ever-alert reader will note what we've just done: subclassed green5 to make green6, including calls
to "super" methods. This ought to be abstracted out
into its own method, something like
$.ui.green5.subclass("green6", $.ui.mouse, {mouseStart: function(){}, mouseDrag: function(){}})
but that's a topic for another day.
Drew Wells says:
I have come upon a problem with my jQuery UI widget. I have a default set of options like, options.repeat = 0.
I initialize an instance setting repeat to 30. Later I reuse the same div and reinitialize my plugin again without specifying repeat. The value of options.repeat is still 30 instead of the default 0. I considered destroying the entire instance and rebuilding everything to recreate this automatic structure, but that seems like overkill.
April 7, 2010, 11:54 amDanny says:
@Drew Wells:
April 8, 2010, 4:30 pmYour reinitializing code (should be in
_init
) could setthis.options = $.extend({}, $.ui.mywidget.prototype.options, options)
to make sure all the options are reset. Just copy the defaults (stored in$.ui.mywidget.prototype.options
) rather than extending the old options.–Danny
Tips for Developing jQuery UI Widgets | Eric Hynds - Website Developer says:
[…] blog posts about widget […]
April 22, 2010, 6:33 ampThomas says:
Thanks for the tutorial, i just downloaded and started playin with the jQuery UI and your tut. surely helped to get me started. Also thanks to Charles Phillips for the updated UI Docs on default themes.
April 27, 2010, 10:41 amFox says:
Thanks!
May 13, 2010, 12:50 amTutorials and Resources for Learning jQuery UI « Ulancer says:
[…] Understanding jQuery UI widgets – A tutorial […]
May 24, 2010, 8:04 pmNaveen says:
Hi friends,
i just need to know that is their any suit function for 10-12-1200+100+1456 =>answer
i need a plugin or function to answer for the above one.is ther any jquery functions is ther ??
Thanks in advance
May 27, 2010, 9:37 amDanny says:
@Naveen:
May 27, 2010, 7:03 pmYou’re better off asking jQuery questions on the jQuery forum
czerasz says:
Great article! Thanks for sharing Your experience. Greetings from Poland.
July 14, 2010, 3:22 pmLes says:
Thanks Danny. This is a great quick intro to widgets.
July 26, 2010, 10:11 amDaniel Cricco says:
Great article!! It helps me a lot to start developing my own widgets
September 3, 2010, 8:41 amHackingHub says:
Some interesting stuff there! I love the fact that you can press ‘test’ and it shows you a small demo of the script (:
I’ll be using that ‘darker’ feature on one of my sites. almost exactly what I was looking for :D
Thanks!
September 26, 2010, 11:04 amRe : How to write my own Widget? - Jquery Home says:
[…] This tutorial was a great start for me:http://bililite.nfshost.com/blog/understanding-jquery-ui-widgets-a-tutorial/ […]
October 4, 2010, 3:18 amThaha says:
Wonderful article. Great that you covered all aspects of the work. Thank you very much.
October 12, 2010, 4:02 amsenthil.srinivasan says:
Good one , nice post for Widgets, keep doing .
October 14, 2010, 1:10 amJaime says:
Thanks you, I just finished my first plugin :D
October 14, 2010, 1:49 pmGiving jQuery UI another chance (and really liking it) – Giving jQuery UI another chance (and really liking it) – Bocoup Web Log says:
[…] .draggable()! Daniel Wachsstock wrote a gorgeous blog post about using the Widget Factory called “Understanding jQuery UI widgets: A Tutorial”. It was game-changing for […]
October 14, 2010, 3:34 pmjQuery plugin for Mozilla’s Audio API « Knirdy says:
[…] http://bililite.nfshost.com/blog/understanding-jquery-ui-widgets-a-tutorial/ […]
October 25, 2010, 3:49 amUsing jQuery says:
I have only used jQuery’s UI once before. Great tutorial
October 26, 2010, 11:45 pmDijit?jQuery UI Widget?? – Fan's blog says:
[…] ??????????????????????????????$(‘.target’).green3()??target element????widget????????DOM???????????JavaScript?????$(‘.target’).green3(‘darker’)???JS????darker??? […]
November 3, 2010, 1:36 amPraveen says:
I was trying to create a widget for very first time after reading this tutorial. it is working when i call
$(‘.demo’).green(); // returns output
but when i try to call
$(‘.demo’).green(‘darker’); nothing works out kindly suggest what is error
Since error console does not reflect any error checked on firefox,IE,chrome and opera. Plz rely
(function($){
November 19, 2010, 2:02 amvar Green3 = { _init: function() { this.setLevel(15); },
greenlevels: [‘#000′,’#010′,’#020′,’#030′,’#040′,’#050′,’#060′,’#070′,’#080′,’#090′,’#0a0′,’#0b0′,’#0c0′,’#0d0′,’#0e0′,’#0f0’, ‘#fff’],
level: 0,
getLevel: function() { return this.level; },
setLevel: function(x) { this.level = Math.floor(Math.min(this.greenlevels.length-1, Math.max(0,x))); this.element.css({background: this.greenlevels[this.level]}); },
darker: function() { this.setLevel(this.getLevel()-1); },
lighter: function() { this.setLevel(this.getLevel()+1); },
off: function() { this.element.css({background: ‘none’}); this.destroy(); }
};
$.widget(“ui.green3”, Green3);
})(jQuery);
Frank says:
Danny, you made my day with your post. Very thorough step-by-step description on what to do and what’s going on. If just more tutorials were like that.
Thx a lot
Greetings from 3N 11E, Central Africa
November 20, 2010, 5:54 pmFrank
Webbdesign says:
Now I have followed your examples, all of them :) Great tutorial and gave me some good insights
November 21, 2010, 9:17 amDanny says:
@Praveen:
November 21, 2010, 3:40 pmI don’t see anything wrong with what you wrote. Remember you have to initialize the widget first (with
$('demo').green3()
) before you manipulate it (with$('demo').green3('darker')
.–Danny
Creating Custom jQuery Widget « Rupesh kumar Tiwari says:
[…] Creating Custom jQuery Widget Posted: November 21, 2010 by Rupesh in jQuery Tags: JQuery 0 Hi I just came across a greate website http://bililite.nfshost.com/blog/understanding-jquery-ui-widgets-a-tutorial/ […]
November 21, 2010, 5:46 pmYounos Aboulnaga says:
Great article.. really helpful. I want to add a little warning about how _trigger() handles names of the custom events : AFTER ADDING THE PREFIX THAT EVERYBODY TALKS ABOUT, IT CALLS toLowerCase().. i don’t know the logic behind this, but what matters it, when you bind a function to this custom event, make sure to write all the name in lowercase, no matter what the real names are.
December 14, 2010, 7:18 amDanny says:
@Younos Aboulnaga:
December 14, 2010, 8:39 amThanks for the heads up. I’m surprised they bother doing this, though most names are lowercase.
–Danny
bruce says:
Great tutorial! Like some other commenters, I’m also new to jQuery, but I was able to follow along and it helped a lot.
I do have two small questions about this code in the Loosely Coupled example.
“setLevel = function(x){
//…
this.element.css({background: greenlevels[level]});
this.element.trigger (‘green5change’, [level]);”
Is there significance to putting an equals sign (instead of a colon) in between the text setLevel and function?
Also, in the last arg passed to trigger, do the square brackets around level do anything special? (I’d have guessed level would be passed in without brackets.)
Thanks!
December 18, 2010, 4:02 pmDanny says:
@Bruce:
December 18, 2010, 9:03 pm1. You’re right; the equals is a typo. I’ve corrected it. Thanks! That’s what I get for writing an example that isn’t actually implemented.
2. jQuery trigger takes an array for its second parameter, which is what
[level]
is: an array with one element. However, as I look at the source code rather than the documentation, it is clear thattrigger
will do that automatically, so you are right on that as well. Nice catch!–Danny
swap games says:
Very, very, very sick tutorial!
February 2, 2011, 12:46 pmCurrently experimenting with jQuery UI
Danny says:
@swap games
February 2, 2011, 7:27 pmI assume “sick” is a typo for slick or some some South African slang I’m not familiar with, because your comment sounds positive.
–Danny
amixyue says:
good essay and inspires me quite a lot . Thanks to bililite .
February 15, 2011, 12:13 amSamuel ROSSILLE says:
Hello and thanks for this good tutorial.
February 17, 2011, 11:26 amThere is still something I don’t understand about a widget’s instance-specific data. In the “Data for Each Widget” section, I understand that “this._myProperty” is shared between all instances of a given widget class.
This seems weird to me for the following reasons:
1/ Most of JQuery UI builtin widgets store a lot of instance-specific private data in “this” from their widget’s methods (see “jquery.ui.slider.js” for an example).
2/ I have written a simple test to check this, and it seems that there is no mix between 2 instance of same widget when i store properties using this._myProperty
3/ How could this.options refer to different objects for different instances, and this._yourPrivateProperty always refer to the same object for different instances… ?
Is there a mistake in your the “Data for Each Widget” section, or have i missed something ?
Danny says:
@Samuel Rossille:
You are right, things are more complicated and subtle than I presented it here. If you have:
Then if you just read
February 17, 2011, 12:22 pmobj.property
, you’re getting the prototype’s member, which is shared among all the objects. If you write to the property, likeobj.property='object property'
, then you create a new property ofobj
alone. In general, you never notice this and have no problems with shared data, since if you haven’t written to the property you want to use the shared one.However, if the
property
if an object, then you can get into trouble, sinceobj.prop.foo = 'new value'
readsobj.prop
and assigns a value to thefoo
property of the sharedobj.prop
.In the jQuery UI code,
this.options
is created anew for each instance (withthis.options = $.extend({}, this.options, options)
. Note how theoptions
property is overridden after being read from the shared version.).I hope this makes some sense (and I’ve gotten the details right! Thinking about this stuff makes my brain hurt; that’s why I write this blog: so I only have to think the hard thoughts once!).
–Danny
Ultimate Guide about jQuery UI – Tutorials, Tips, Resources and Examples | Designers' HQ says:
[…] 4- How to Use the jQuery UI Autocomplete Widget […]
March 17, 2011, 3:20 amPaul Schlereth says:
Getting errors when converting over from the entire jquery-ui-1.8.9.custom.min.js to just jquery.ui.widget.js. The error in Firebug reads ‘base is not a constructor’ and is telling me jquery.ui.widget.js is at fault. I’ve added jquery.ui.core.js prior to this in a failed attempt to fix. Help? Thanks again for the great tutorial!
April 8, 2011, 9:28 amDanny says:
@Paul Schlereth:
April 8, 2011, 11:48 amThe last example of the tutorial uses jquery.ui.mouse.js for the mouse handling routines. Is your error being called when you click those buttons?
–Danny
Paul Schlereth says:
@Danny
Actually it happens on load – but that did fix it! Thanks! Lastly, is there any reason why this doesn’t seem to return anything?:
April 8, 2011, 12:05 pm$(‘.distance’, this).text(distance);
Danny says:
@Paul Shlereth:
April 8, 2011, 12:56 pmI’d have to analyze the program flow, but I guess it’s creating the widget on load. Makes sense; glad it works.
$(…).text(distance) should set the text to the value of distance and return the jQuery object created with $(…). Does $(‘distance’, this) return anything?
–Danny
Florian says:
What’s best practice to overwrite standard jquery ui functions / methodes?
Right now we did it directly in the jquer.ui.js but this prevents us from
updating the library when bugfixes arrive. Any idea?
thx
April 11, 2011, 3:35 amFlorian
Danny says:
@Florian:
April 11, 2011, 8:50 amThat’s a question best addressed to the jQuery forum. That said, the usual way is with “Monkey Patching” to override the original routine. Something like:
Project Silk jQuery UI Widget QuickStart - MSDN Blogs says:
[…] http://bililite.nfshost.com/blog/understanding-jquery-ui-widgets-a-tutorial/ […]
April 12, 2011, 1:59 amchandru.v says:
i’m new to widget designing and jquery ,i’m using FireFox 4.0 when clicks the button it wont fires please check it
thank s in advance
April 21, 2011, 4:13 amDanny says:
@chandru.v:
April 21, 2011, 7:26 amI’m not at my computer (which is running Firefox 4) but I’ll check on it when I can. Can you run Firebug and see if you’re getting any JavaScript errors?
–Danny
Thomas says:
Thanks for the excellent tutorial.
I´ve ported the example to CoffeeScript – In my opinion it´s looking quite a bit cleaner and nicer…
http://stackoverflow.com/questions/6824428/how-to-improve-jquery-widgets-written-in-coffeescript
July 25, 2011, 9:00 pmDanny says:
@Thomas:
July 26, 2011, 9:13 amLooks interesting, though I’ve never been inspired to try CoffeeScript (no flame wars, please; I acknowledge it’s a matter of taste and experience). I can think about closures directly and I like semicolons; I suppose if I had more Python and Ruby experience I would be gushing with enthusiasm for CoffeeScript.
Danny
Taylan Karao?lu » User Interfaces and JQuery UI says:
[…] Hacking at 0300 : Understanding jQuery UI widgets: A tutorial […]
August 2, 2011, 8:06 pmjmtt – jQuery Minimal Tree Table « David Souther says:
[…] as possible. Since this was my first trip around the jQuery ui block, I found bililite.com’s jQuery UI Widget tutorial an invaluable […]
August 10, 2011, 4:26 pmDescargar says:
Excellent stuff ! i will suscribed to your RSS dude ;)
August 23, 2011, 12:43 pmGlen_Whitley says:
Thank, really usefull
September 18, 2011, 8:12 pm