Lukas S.
Lukas S.

Reputation: 5758

Extending jQuery UI widgets - override parent events?

I'm trying to extend the jQuery UI Autocomplete widget. In my custom widget, I need to be able to override the select event, while ideally also allowing the user of the widget to attach their own handler to that event as well.

Here's a jsfiddle of one of my attempts: http://jsfiddle.net/nN46R/

My first attempt (which is in the jsfiddle) was to bind to the event in _create:

$.widget("custom.myautocomplete", $.ui.autocomplete, {
    _create: function() {
        this._super("_create");

        // Doesn't work
        this.element.bind('autocompleteselect', function() {
            alert('Handling autocompleteselect!');
        });
    }
});

This didn't work. It will trigger if you change autocompleteselect to select, but only if you highlight any text within the textbox - but that's just jQuery's select handler firing, not jQuery UI's autocompleteselect. Not what I want.

Per this post, I tried defining a _select method within the widget:

$.widget("custom.myautocomplete", $.ui.autocomplete, {
    _create: function() {
        this._super("_create");
    },
    _select: function (event, ui) {
        alert('Handling select!');
    }
});

That also didn't work. I tried the same with just select (no underscore), but no luck.

The only thing that worked was to pass in a default handler using the options array, like so (jsfiddle):

$.widget("custom.myautocomplete", $.ui.autocomplete, {
    options: {
        select: function (event, ui) {
            alert('Handling select!');
        }
    }
});

But this has a couple problems. First, it doesn't look like it's possible to call any other methods in the custom widget from within the handler:

$.widget("custom.myautocomplete", $.ui.autocomplete, {
    options: {
        select: function (event, ui) {
            alert('Handling select!');

            // Doesn't work:
            // Uncaught TypeError: Object #<HTMLInputElement> has no method '_myCustomSelectHandler'
            this._myCustomSelectHandler();
        }
    },
    _myCustomSelectHandler: function (event, ui) {
        alert('In _myCustomSelectHandler!');
    }
});

Second, if the user defines their own select handler, then mine won't fire anymore:

$("#tags").myautocomplete({
    delay: 0,
    source: availableTags,
    select: function (e, ui) {
        alert("Muahaha! Me (the user) just overrode the select handler, and now yours won't get called!");
    }
});

So that doesn't really look like a solution.

So, is there any way I could extend the autocomplete widget and override the select handler?

Upvotes: 10

Views: 1924

Answers (1)

Lukas S.
Lukas S.

Reputation: 5758

Figured it out! In the first code sample, all I had to do is bind to the myautocompleteselect event instead of autocompleteselect:

http://jsfiddle.net/nN46R/1/

$.widget("custom.myautocomplete", $.ui.autocomplete, {
    _create: function() {
        this._super("_create");

        // Works! Bind to the "myautocompleteselect" event, not
        // "autocompleteselect".
        this.element.bind('myautocompleteselect', function() {
            alert('Something selected!');
        });
    }
});

Apparently, the full name of the event that gets raised is the name of the widget concatenated with the name of the event (select). This is a custom widget, so you're supposed to use the custom widget's name, which in my example is myautocomplete.

As a side note, this is also relevant for the widget user if they want to bind to any events in their code, such as the autocomplete menu opening or closing. If this was the base autocomplete widget, they would bind to the menu opening event using:

$('#tags').bind('autocompleteopen', function(event, ui) {
    console.log('autocomplete menu opening');
});

However, if they're using the custom widget myautocomplete (which extends autocomplete), they would need to bind to the myautocompleteopen event instead:

$('#tags').bind('myautocompleteopen', function(event, ui) {
    console.log('custom autocomplete menu opening');
});

The event names of jQuery UI widget events are namespaced - important to keep in mind!

Upvotes: 10

Related Questions