How do you bind jQuery UI autocomplete using .on()?
Asked Answered
I

2

20

This question was answered for the live() method, but the live() method has been deprecated as of jQuery 1.7 and replaced with the .on() method and this answer does not work for on().

Here's where it was answered before: Bind jQuery UI autocomplete using .live()

Anyone know how to do the same thing with on()?

If you change the syntax to something like

$(document).on("keydown.autocomplete",[selector],function(){...});

from

$([selector]).live("keydown.autocomplete",function(){...});

It kind of works, but it interacts with the internal autocomplete events in a weird way. With live(), if you use the select event and access the event.target, it gives you the id of the input element. If you use on(), it gives you the id of the dropdown menu "ui-active-menuitem". Something like this:

$( ".selector" ).autocomplete({
   select: function(event, ui) { 
     console.log(event.target.id);
 }
});

But - if you use the "open" event, it will give you the id I'm looking for - just not at the right time (I need it after it is selected). At this point, I'm using a workaround of grabbing the ID of the input element in the open event function, storing it in a hidden field, then accessing it in the select method where I need it.

Irrelevant answered 13/3, 2012 at 23:27 Comment(2)
Can you post a working example in jsFiddle? I've answered a question that - from my understanding - is similar to your case, but I'm not sure I'm interpretting your question correctly (i.e. what you're trying to achieve).Tarsometatarsus
It will take some time for me to extract my code from the larger application, but I can try. To provide more context, I have a form with an input field with autocomplete running on it. I need to use the live/on functionality to allow additional input fields to be added dynamically by clicking an add button, with the same autocomplete running on them.Irrelevant
T
23

If I understood correctly, your problem looks very similar to one I saw in another topic. I'll adapt my answer to your case, let's see if it solves your problem:

$(document).on("focus",[selector],function(e) {
    if ( !$(this).data("autocomplete") ) { // If the autocomplete wasn't called yet:
        $(this).autocomplete({             //   call it
            source:['abc','ade','afg']     //     passing some parameters
        });
    }
});

Working example at jsFiddle. I used focus instead of keydown because I need to re-trigger the event, and I don't know how to do it with key/mouse events.

Update: You could also consider using clone, if your additional inputs will have the same autocomplete as an existing one:

var count = 0;
$(cloneButton).click(function() {
    var newid = "cloned_" + (count++); // Generates a unique id
    var clone = $(source) // the input with autocomplete your want to clone
        .clone()
        .attr("id",newid) // Must give a new id with clone
        .val("") // Clear the value (optional)
        .appendTo(target);
});

See the updated fiddle. There are also jQuery template plugins that might make this solution easier (although I haven't used one myself yet, so I can't talk from experience).

Tarsometatarsus answered 13/3, 2012 at 23:33 Comment(3)
Thanks, this almost works. The autocomplete works, but some of the inner workings don't. As mentioned above, I need access to the 'select' event. From the docs: $( ".selector" ).autocomplete({ select: function(event, ui) { ... } }); With live() the 'event' param in the select function correctly holds the autocomplete input element. Try printing/logging event.target.id to see. Using on() with this syntax, event.target.id will always be #ui-active-menuitem, no matter which one was used. But I need to know the id of the input field in use.Irrelevant
Also I don't think you need the if statement (if ( !$(this).data("autocomplete")) or the trigger and return false ( trigger("focus");return false;). I removed them and it works exactly the same as far as I can tell.Irrelevant
You're right, the re-trigger would only be necessary if autocomplete needed to act on focus. As in my comment to your answer below, where key events are only handled from the second key press onwards (since the plugin is not yet called when the first key press happens). As for the if, it tries to avoid (attempting to) recreate the plugin at every key press (a well-behaved plugin, such as autocomplete, doesn't break on that, but others could).Tarsometatarsus
I
12

This seems just to be some peculiarity of the interaction between .on() and autocomplete. If you want to do this:

$(function(){
  $('.search').live('keyup.autocomplete', function(){
    $(this).autocomplete({
      source : 'url.php'
    });
  });
});

This works with on():

$(function(){
  $(document).on("keydown.autocomplete",".search",function(e){
    $(this).autocomplete({
      source : 'url.php'
    });
  });
});

You can access the event.target.id of the element that the autocomplete was called on with the parameter of the on() callback function (e in the code above).

The difference is with on(), the event param in the internal events works differently, holding different values. With live(), the event.target.id in the select function will hold the ID of the selected input element. But with on(), the event.target.id in select will hold the ID of the list of autocomplete items (ui-active-menuitem). With on(), you can access the ID of the input element with event.target.id from the change and open functions.

Irrelevant answered 14/3, 2012 at 3:27 Comment(1)
I couldn't reproduce that behavior in my example, both live and on alerts ui-active-menuitem. Also, since the autocomplete is bound to keyup and keydown instead of focus, it only starts working after the second key press (which might be ok depending on your needs...)Tarsometatarsus

© 2022 - 2024 — McMap. All rights reserved.