简体   繁体   中英

jQuery autocomplete: characters missing in user input

I am debugging a jQuery autocomple instance (v1.1) on a "city" input field.

The autocomplete data binding is set on the keyup event of the field, only if the field value length is at least 2 and only if the value has changed.

The data binding, the hints list and the autocomplete are working fine. But something is wrong. In the log I see that many times the 3rd and some times even the 4th character is missing in the city input value posted to the server. Some examples:

"trpani" instead of "trapani"
"fienze" instead of "firenze"
"scndicci" instead of "scandicci"
"brdisi" instead of "brindisi"
"paermo" instead of "palermo"
"caliari" instead of "cagliari"

I do not succeed in replicate the bug, but I am sure it cannot be by chance! The error occurs just at the 3rd character. It seems that during the insert, Javascript processing collides with the keyboard buffer.

So, I guess but I am not sure, people type firenze , but eventually the r character is missed, and the final value of the input is fienze that is eventually posted to the server.

Question

What is happening? Why I do not succeed in replicate the error? What is wrong?

Here is the code used to set the autocomplete:

/*
 * here I store the previous value
 */
var storeCity;
$('#City').keydown(function(){
    var val = $(this).val();
    storeCity = (val.length >=2 ? val.substring(0,2):"");
});

/*
 * the autocomplete is set only if
 * - the City value has changed compared to the storeCity value
 * - the City value has lenght at least 2
 * - remark: using the keypress does not solve the issue
 */
$('#City').keyup(function(){
    var val = $(this).val();
    if(val.length>=2 && val.substring(0,2)!=storeCity){
        getLocations('#City');
    }
});

function getLocations(cityId){
    var hint = $(cityId).val().substring(0,2);

    $.ajax({
        type: "GET",
        url: "/include/getLocations.asp",
        data: ({location : hint}),
        async: false,
        error: function() {},
        success: function(dataget) {
            var result = dataget.split("\n");

            $(cityId).flushCache();
            $(cityId).autocomplete(result, {
                pleft: 100px,
                minChars: 2,
                matchContains: true,
                max: 3000,
                delay: 100,
                formatItem: function(row){...},
                formatMatch: function(row){ return row[0]; },
                formatResult: function(row){ return row[0]; }
            });

            $(cityId).result(function(event,data){...});
        }
    });
}

It looks like the order of initialization should reverse. The initialization of the autocomplete component should happen only once, when the page is loaded. See example attached:

  $( "#city" ).autocomplete({
        source: function( request, response ) {
           // Put your ajax request here
        }
  });

Eventually I resolved with some heuristics. I thought that the problem is due to events conflict. So I tryed to get better performance.

  • initialize the autocomplete once , outside the getLocation() method
  • store the $('#city') object in a variable
  • put the $city.result method outside the getLocation() method

Here is the result code:

var $city = $('#City');
var storeCity;

$city.keypress(function(){
    var val = $(this).val();
    storeCity = (val.length >=2 ? val.substring(0,2):"");
});

/*
 * the autocomplete is set only if
 * - the City value has changed compared to the storeCity value
 * - the City value has lenght at least 2
 * - remark: using the keypress does not solve the issue
 */
$city.keyup(function(){
    var val = $(this).val();
    if(val.length>=2 && val.substring(0,2)!=storeCity){
        getLocations('#' + $city[0].id);
    }
});

$city.autocomplete({
    pleft: 100px,
    minChars: 2,
    matchContains: true,
    max: 3000,
    delay: 50
});

$city.result(function(event,data){...});

function getLocations(cityId){
    var hint = $(cityId).val().substring(0,2);

    $.ajax({
        type: "GET",
        url: "/include/getLocations.asp",
        data: ({location : hint}),
        async: false,
        error: function() {...},
        success: function(dataget) {
            var result = dataget.split("\n");

            $(cityId).flushCache();
            $(cityId).autocomplete(result, {
                formatItem: function(row){...},
                formatMatch: function(row){ return row[0]; },
                formatResult: function(row){ return row[0]; }
            });
        }
    });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM