Search code examples
javascriptjquerylive

using .live() to .autocomplete() won't fire on domchange


I have this autocomplete

    $( "#tags" )
                // don't navigate away from the field on tab when selecting an item
                .bind( "keydown", function( event ) {
                    if ( event.keyCode === $.ui.keyCode.TAB && $( this ).data( "autocomplete" ).menu.active ) {
                        event.preventDefault();
                    }
                })
                .autocomplete({
                    minLength: 2,
                    /*source: function( request, response ) {
                        // delegate back to autocomplete, but extract the last term
                        response( $.ui.autocomplete.filter(
                            availableTags, extractLast( request.term ) ) );
                    },*/
                    source: function( request, response ) {
                        $.getJSON( "json.php", {
                            term: extractLast( request.term )
                        }, response );
                    }
                    

/*all the options omitted*/
            });

Which works great on dom.ready, but if I dynamically remove and add again the same form, the autosuggest feature wont get enabled, so I thought about using .live() but its giving me the same behavior

 $( "#tags" )
                // don't navigate away from the field on tab when selecting an item
                .live( "keydown", function( event ) {
                    if ( event.keyCode === $.ui.keyCode.TAB && $( this ).data( "autocomplete" ).menu.active ) {
                        event.preventDefault();
                    }
                })
                .autocomplete({
                    minLength: 2,
                    /*source: function( request, response ) {
                        // delegate back to autocomplete, but extract the last term
                        response( $.ui.autocomplete.filter(
                            availableTags, extractLast( request.term ) ) );
                    },*/
                    source: function( request, response ) {
                        $.getJSON( "json.php", {
                            term: extractLast( request.term )
                        }, response );
                    }
                    

/*all the options omitted*/
            });

shouldn't .live() handle the dom change?


Solution

  • Yes, you should use on (although live is still available). And you may want to initialize the autocomplete upon the first keystroke:

    $( document ).on( "keydown", "#tags", function( event ) {
        if ( $.type( $( this ).data( "autocomplete" ) ) == "undefined" ) {
            $( this ).autocomplete({
                minLength: 2,
                source: function( request, response ) {
                    $.getJSON( "json.php", {
                        term: extractLast( request.term )
                    }, response );
                }
            });
        }
        if ( event.keyCode === $.ui.keyCode.TAB && $( this ).data( "autocomplete" ).menu.active ) {
                event.preventDefault();
        }
    });
    

    Note: instead of $( document ).on it is preferrable to use the closest "#tags" parent which is always in the DOM (never is removed or reloaded). document is parent of all, and is always present, that's why it always works for on. But we should avoid attaching all event handlers in the document, if possible.


    Also, what other users answered is correct. When you do:

    $( '#tags' ).live( ... ).autocomplete( ... );
    

    This is the same as:

    $( '#tags' ).live( ... );
    $( '#tags' ).autocomplete( ... );
    

    It means: the live call is not attached to the autocomplete call.


    Also, as other users answered, instead of the solution above, a better place to initialize the autocomplete would be in the AJAX success event handler, i.e., right AFTER the "#tags" element is included in the DOM:

    $('div#something').load('new_content_from_server', function() {
        // the tags arrived! let's initialize the autocomplete
        $( '#tags' ).autocomplete( ... );
    });
    

    I hope this helps.