jQuery UI widget 'change' event - jquery-ui

I'm trying to maintain a widget that triggers events using one of these two lines of code:
this.element.trigger('change'); // or...
stop: function (event, ui) { that.element.change(); }
The word 'change' occurs only 4 times in the code, in one of the 2 forms above. However, I've got no idea what's going on here. There's no event handler in the change call, and there are no bind, delegate, on, or live calls, so something external is presumably setting this up. Can anyone fill me in? Are there any docs on this? Thanks.

Those two lines of code simply trigger a change event to this.element using two different allowed syntax.
Using .trigger():
this.element.trigger('change');
Or using a shorthand method .change():
that.element.change();
You can actually bind an event handler to the element represented by this.element to handle this event.
Without knowing your plugin, it is difficult to answer you precisely on what is this.element.
But take the example of the autocomplete plugin. In this one, this.element is actually the input field the autocomplete plugin is applied to. If the change event was triggered like supposedly done in your question, you could bind an event handler to the input like this:
$('#myinput')
.autocomplete()
.bind('change', function() { });
Now if this plugin relies on the jQuery UI Widget Factory, it is advisable to use the method _trigger() to trigger events instead of the jquery .trigger().
Using _trigger() will make sure to execute any callback defined in the plugin's option with a correct context and also trigger that event for this.element (like above). So you could have:
$('#myinput')
.somePlugin({
change: function(e, someData) {
// "this" here will be `this.element´
}
})
.bind('change', function() { ... });

The answer turned out to be simple - there was no event handler, there were no bind/etc calls, jQuery does nothing behind the scenes, so the trigger calls did nothing. I commented them out and the widget behaved exactly the same. Doh.

Related

Syntax for using a plugin's custom event method

I'm having trouble figuring out the correct syntax to use when a plugin/widget requires using a custom 'event' method instead of the standard jQuery events.
The jQuery UI MultiSelect Widget doesn't support the change method, and instead provides a click event which is fired when a checkbox is checked or unchecked. I'm trying to use the syntax supplied in the widget's documentation for the click event so that I can replace several change functions including the one shown below, but I'm having trouble figuring out the correct syntax. The structure for the click event is:
$("[name=Item]").on("multiselectclick", function (event, ui) {...});
I've tried inserting the function in between the curly brackets, and I've also tried .on("multiselectclick", function () {...}); without success, so I'm assuming that I need to insert something here: (event, ui)
I've managed to get the functions partially working by using a slightly different method $("[name=Item]").multiselect({ click: function (event, ui) {...}, but I'd really like to understand how to use the plugin's custom event so that I can get the functions working properly. I posted a fiddle with a very simple example here http://jsfiddle.net/chayacooper/cZRy9/5/, and included notes to indicate what wasn't working properly.
One of the functions where I'm trying to replace a change event with the widget's click event:
$("[name=Item]").change(function(){
$("#Styles1, #Styles2").hide();
$(".accordion").accordion("option", "active", false);
if( $("[name=Item]").val() === "Dresses"){
$("#Styles1").show();
$(".accordion").accordion("option", "active", 0);
$('varItem').val('Dresses');
}
else {...}
});
First issue about not hiding the Styles element when dresses is unchecked is straightforward. There is nothing in code to check state of the checkbox, only the value
Fix with:
if ((ui.value) === "Dresses" && ui.checked)
Using the ui object within a jQuery UI patterned widget is usually best source for your data or state , rather than using jQuery selector to look for the same thing.
I have never used this plugin, so to figure out what was available to me, I simply used console.log(ui) within the click handler so I could inspect the ui object to see what properties it contained, and found the checked property to add to above if conditional
If you do the same on a more complex widget like jQueryUI datepicker will see quite a significant number of ui properties , some of which are also method functions
DEMO (using custom event)
http://jsfiddle.net/cZRy9/2/

Zeptojs on() not triggering

I have build a plugin (pluginA) based on zeptojs and inside this plugin I fetch data using ajax and attach a list of
How do I bind an event to these anchors? I was going for something globally like and then use $('[data-key]').pluginB() and then inside pluginB() have something like
$(this).on('click', function (e) { e.preventDefault(); ... }); but I am not able to bind the click event to anchors created dynamically.
I tried adding $('a').on('click', ...) before I call pluginA() but it's not firing.
What I really would like would be to use the bind() trigger() approach in order to decouple the two plugins, but I am having trouble finding a good example.
Use the delegating form of on to bind all desired links in a particular area (in this example, the entire body):
$(body).on('click', 'a[data-key]', function(e) {e.preventDefault();...});
Now all links with data-key will trigger your function, regardless of whether or not they were present at the time you called on; subsequently-added links will automatically get the behavior, and removed links won't leak memory by holding dangling handler references.

How and where is the slidechange event raised?

I have a custom binding for Knockout which attaches to the "slidechange" event on a jquery UI slider.
What I can't figure out is where this event is raised - a text search for "slidechange" within the jquery UI source code pulls up nothing!
So I'm guessing this is a convention based approach - the question is:
What is the convention with jquery UI for events?
The slidechange event is fired whenever the position of the slider is changed by the user. In the code if you look in the _change method in jquery.ui.slider.js this is the line of code that triggers the event.
this._trigger( "change", event, uiHash );
_trigger is a method in jQuery UI's widget factory that will prefix the first parameter with the widget's defined widgetEventPrefix (in this case slide). Therefore when that line of code is invoked all handlers bound to the slidechange event will be triggered.
There are two ways to subscribe to the event. One is by passing in a function in when creating the slider.
$('my-selector').slider({
change: function() {
console.log('change');
}
});
The other is to subscribe to the slidechange event using jQuery's bind or on method.
$('my-selector').on('slidechange', function() {
console.log('change');
});
You can see both of these events being fired in this example - http://jsfiddle.net/tj_vantoll/XUyKs/
jQuery UI's API site documents all events that each widget fires as well as provides examples how you can subscribe to them. For example, here's the documentation on the slidechange event - http://jqueryui.com/demos/slider/#event-change.

Backbone.js focus event fires two events focus and focusin

The view part of my code using Backbone.js is something like this:
var myView = Backbone.View.extend({
events: {
'focus .cell input' : "updateCurrentCell"
},
updateCurrentCell: function(event) {
console.log('updateCurrentCell called');
// Update the current cell.
}
}
Whenever the input element gets focus, the function is called twice. I tried printing the stack trace using console.trace(). It shows that once the function call originated from focus event while the next time from focusin.
My attempts to find out how to prevent one of these events getting fired lead me nowhere.
How can I fix this?
Backbone.View uses delegateEvents to bind the events listed in your events object. If you take a look at the source, you'll see that delegateEvents uses jQuery.delegate to do so.
There's a note in the jquery docs for .focus() that's probably relevant:
The focus event does not bubble in Internet Explorer. Therefore,
scripts that rely on event delegation with the focus event will
not work consistently across browsers. As of version 1.4.2, however,
jQuery works around this limitation by mapping focus to the focusin
event in its event delegation methods, .live() and .delegate().
In theory, this should just work fine, but since you're getting both, perhaps you could try to just listen for the .focusin() event, as it supports the kind of event bubbling .delegate() listens for and is what jQuery is trying to map 'focus' to anyway.

How to derive a custom widget from jquery-ui dialog

I want to build a jquery-ui widget and I am unsure of the best way to approach this.
The widget will manage the sate of some data that is hosted inside of a jquery-ui dialog.
Should I build a custom widget, in the widget create function add some elements to the widget target and then call the dialog widget on my widgets target.
Or
Is there a way to inherit from the jquery-ui dialog and just override the content part of it?
There is a way to extend other widgets:
$.widget("ui.customwidget", $.ui.dialog, {
options: {
// your options
},
_create: function() {
$.ui.dialog.prototype._create.apply(this);
// constructor
},
destroy: function() {
// destructor
$.ui.dialog.prototype.destroy.apply(this);
},
_setOption: function(key, value) {
$.ui.dialog.prototype._setOption.apply(this, arguments);
// process the setting of options
}
// other methods
});
But I'd not encourage using it on a dialog, slider etc. because e.g. buttonset relies on the existence of the button widget and will (and can) not recognize if the element is an instance of a widget that extended button. Therefore it just creates new pure button widgets, what leads to a messed up layout and DOM. Overriding parts of a widget is also critical: The extending mechanism for widgets was introduced not so long ago, when some widgets already existed. The developers of them did not have this feature in mind, so there may still be issues with this.
I aggregate my widgets (your first option): Just extend the $.Widget and make the element a dialog too. Then add event listeners for the properties that need to be synchronized between the dialog and your custom widget.
$.widget("ui.customwidget", $.Widget, {
// ...
_create: function() {
$.Widget.prototype._create.apply(this);
this.element.dialog();
}
// ...
});
This way more robust than extending other widgets (except you built the parent and know what you are doing), but it has it's disadvantages too. E.g. do you accept setting options of the aggregated widget too, or just parts of it? Or do you do none of these and force the user to call the dialog for everything that is not handled in your custom widget? I prefer the second option: It's at least honest, because your widget does't promise things it can't hold, but it's ugly too, because you may once call one, then the other widget.
I'm still not that happy with my solution, but extending widgets put me in front of a whole load of new problems whose solutions would have been either to patch the jQuery UI source or to write an ugly hack.
(I just noticed that this question is about a year old, and the asker may not have this problem anymore. But I'd written all the stuff above already and think it's not that bad to not be posted.)

Resources