4

I am using jQuery autocomplete which is working fine with existing element but not with dynamically added element.

Here is my autocomplete code (Which I have changed a bit)

$(function() {

        (function( $ ) {
        $.widget( "ui.combobox", {
            _create: function() {
                var self = this,
                    select = this.element.hide(),
                    selected = select.children( ":selected" ),
                    value = selected.val() ? selected.text() : "";
                var input = this.input = $( ".editableCombobox" )    // your input box
                    //.insertAfter( select )
                    .val( value )
                    .autocomplete({
                        delay: 0,
                        minLength: 0,
                        source: function( request, response ) {
                            var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
                            response( select.children( "option" ).map(function() {
                                var text = $( this ).text();
                                if ( this.value && ( !request.term || matcher.test(text) ) )
                                    return {
                                        label: text.replace(
                                            new RegExp(
                                                "(?![^&;]+;)(?!<[^<>]*)(" +
                                                $.ui.autocomplete.escapeRegex(request.term) +
                                                ")(?![^<>]*>)(?![^&;]+;)", "gi"
                                            ), "$1" ),
                                        value: text,
                                        option: this
                                    };
                            }) );
                        },
                        select: function( event, ui ) {
                            ui.item.option.selected = true;
                            self._trigger( "selected", event, {
                                item: ui.item.option
                            });
                        },
                        change: function( event, ui ) {
                            if ( !ui.item ) {
                            var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $(this).val() ) + "$", "i" ),
                                valid = false;
                                select.children( "option" ).each(function() {
                                if ( $( this ).text().match( matcher ) ) {
                                this.selected = valid = true;
                                return false;
                                }
                                });
                                //if ( !valid ) {
                                    // remove invalid value, as it didn't match anything
                                    //$( this ).val( "" );
                                    //select.val( "" );
                                    //input.data( "autocomplete" ).term = "";
    //return false;
        //                      }
                            }
                        }
                    })
                    .addClass( "ui-widget ui-widget-content ui-corner-left" );

                input.data( "autocomplete" )._renderItem = function( ul, item ) {
                    return $( "<li></li>" )
                        .data( "item.autocomplete", item )
                        .append( "<a>" + item.label + "</a>" )
                        .appendTo( ul );
                };

                this.button = $( "<button type='button'>&nbsp;</button>" )
                    .attr( "tabIndex", -1 )
                    .attr( "title", "Show All Items" )
                    .insertAfter( input )
                    .button({
                        icons: {
                            primary: "ui-icon-triangle-1-s"
                        },
                        text: false
                    })
                    .removeClass( "ui-corner-all" )
                    //.addClass( "ui-corner-right ui-button-icon" )
                    .live('click',function() {
                        // close if already visible
                        if ( $(this).prev().autocomplete( "widget" ).is( ":visible" ) ) {
                            $(this).prev().autocomplete( "close" );
                            return;
                        }

                        // work around a bug (likely same cause as #5265)
                        $( this ).blur();

                        // pass empty string as value to search for, displaying all results
                         $(this).prev().autocomplete( "search", "" );
                         $(this).prev().focus();
                    });
            },

            destroy: function() {
                this.input.remove();
                this.button.remove();
                this.element.show();
                $.Widget.prototype.destroy.call( this );
            }
        });
    })( jQuery );

        $( "#combobox" ).combobox();
        $( "#toggle" ).live('click',function() {
            $( "#combobox" ).toggle();
        });

        });  

Here is my code which adds new element

var selectedRow = $('#contactGroup'+rowId);
    var clonedRow = selectedRow.clone();  
selectedRow.after(clonedRow);   

After reading many similar questions I think .live might help but not sure where to use it.

EDIT:

I tried removing live.

New code for Autocomplete

$(function() {

        (function( $ ) {
        $.widget( "ui.combobox", {
            _create: function() {
                var self = this,
                    select = this.element.hide(),
                    selected = select.children( ":selected" ),
                    value = selected.val() ? selected.text() : "";
                var input = this.input = $( ".editableCombobox" )    // your input box
                    //.insertAfter( select )
                    .val( value )
                    .autocomplete({
                        delay: 0,
                        minLength: 0,
                        source: function( request, response ) {
                            var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
                            response( select.children( "option" ).map(function() {
                                var text = $( this ).text();
                                if ( this.value && ( !request.term || matcher.test(text) ) )
                                    return {
                                        label: text.replace(
                                            new RegExp(
                                                "(?![^&;]+;)(?!<[^<>]*)(" +
                                                $.ui.autocomplete.escapeRegex(request.term) +
                                                ")(?![^<>]*>)(?![^&;]+;)", "gi"
                                            ), "$1" ),
                                        value: text,
                                        option: this
                                    };
                            }) );
                        },
                        select: function( event, ui ) {
                            ui.item.option.selected = true;
                            self._trigger( "selected", event, {
                                item: ui.item.option
                            });
                        },
                        change: function( event, ui ) {
                            if ( !ui.item ) {
                            var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $(this).val() ) + "$", "i" ),
                                valid = false;
                                select.children( "option" ).each(function() {
                                if ( $( this ).text().match( matcher ) ) {
                                this.selected = valid = true;
                                return false;
                                }
                                });
                                //if ( !valid ) {
                                    // remove invalid value, as it didn't match anything
                                    //$( this ).val( "" );
                                    //select.val( "" );
                                    //input.data( "autocomplete" ).term = "";
    //return false;
        //                      }
                            }
                        }
                    })
                    .addClass( "ui-widget ui-widget-content ui-corner-left" );

                input.data( "autocomplete" )._renderItem = function( ul, item ) {
                    return $( "<li></li>" )
                        .data( "item.autocomplete", item )
                        .append( "<a>" + item.label + "</a>" )
                        .appendTo( ul );
                };

                this.button = $( "<button type='button'>&nbsp;</button>" )
                    .attr( "tabIndex", -1 )
                    .attr( "title", "Show All Items" )
                    .insertAfter( input )
                    .button({
                        icons: {
                            primary: "ui-icon-triangle-1-s"
                        },
                        text: false
                    })
                    .removeClass( "ui-corner-all" )
                    .addClass( "ui-corner-right ui-button-icon" )
                    .click(function() {
                        // close if already visible
                        if ( $(this).prev().autocomplete( "widget" ).is( ":visible" ) ) {
                            $(this).prev().autocomplete( "close" );
                            return;
                        }

                        // work around a bug (likely same cause as #5265)
                        $( this ).blur();

                        // pass empty string as value to search for, displaying all results
                         $(this).prev().autocomplete( "search", "" );
                         $(this).prev().focus();
                    });
            },

            destroy: function() {
                this.input.remove();
                this.button.remove();
                this.element.show();
                $.Widget.prototype.destroy.call( this );
            }
        });
    })( jQuery );

        $( "#combobox" ).combobox();
        $( "#toggle" ).click(function() {
            $( "#combobox" ).toggle();
        });

        });

Binding newly added element in clone method

 var selectedRow = $('#contactGroup'+rowId);
        var clonedRow = selectedRow.clone();  
    selectedRow.after(clonedRow);   
 $(('#contactGroup'+rowId) .editableCombobox).autocomplete( "search", "" );
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Ajinkya
  • 22,324
  • 33
  • 110
  • 161
  • Whats the problem? Do you get an error? Where are you enabling the automcomplete for the cloned row?` – Jan Nov 21 '11 at 11:39
  • @Jan: I tried Thorsten answer. The events are not bind to Autocomplete. – Ajinkya Nov 21 '11 at 12:10
  • Can you show a complete example? Again: How do you bind autocomplete to your cloned inputs? Thorstens jsFiddle works for me! – Jan Nov 21 '11 at 12:13

2 Answers2

9

You can't use 'live' on autocomplete, as far as I know.

Place your autocomplete options in a function that expects the field as parameter, on which you want to apply the autocomplete method.

function enable_autocomplete(InputField) {
    $(InputField).autocomplete({
        source: availableTags
    });
}

Then, after cloning the field, call this function with the cloned field.

enable_autocomplete(ClonedField);

I've written you an easy example, what makes it much easier to understand what I am trying to say ;-)

Edit: I've written another example based on the combobox example from jQueryUIs website.

Thorsten
  • 5,634
  • 6
  • 35
  • 33
  • Thanks for the suggestion. I removed all `live` method and added following code in clone method `$(('#contactGroup'+rowId) .editableCombobox).autocomplete( "search", "" );` but still got the same result. Any other thing I should try ? – Ajinkya Nov 21 '11 at 12:21
  • I've added another fiddle, check it out. – Thorsten Nov 21 '11 at 12:55
  • I have multiple autocomplete elements and I am using only select element to retrieve suggestions for all autocomplete element. I am confused in which method I should invoke to bind events to newly added elements. – Ajinkya Nov 21 '11 at 13:03
  • 1
    Sorry, I don't get you problem. Maybe you should provide a fiddle that shows the problem and explain what behavior you expect. – Thorsten Nov 21 '11 at 13:05
1

You can use 'live', although these days you should be using the 'on' method.

See this thread for working examples (including one that uses 'on' if you drill down in to some of the hidden answers): Bind jQuery UI autocomplete using .live()

Cheers Matt

Community
  • 1
  • 1
Matty J
  • 3,116
  • 32
  • 31