ubilabs / geocomplete

jQuery Geocoding and Places Autocomplete Plugin
http://ubilabs.github.com/geocomplete/
MIT License
1.22k stars 406 forks source link

Conflict on click when blur is set to true #128

Open ldanielduarte opened 10 years ago

ldanielduarte commented 10 years ago

Hi all!

I have an input box ( like in this example: http://ubilabs.github.io/geocomplete/examples/simple.html ) only that I want to use the blur. So, in my code blur is set to true.

What happens is that, when a user clicks on a suggestion, the find() function is called twice, on click and on blur. Leading to, in some situations, to return a result that it wasn't the clicked one.

What I understood was that, when we bind the blur event to the geocomplete input we then have two events that are triggered when the user clicks in an option from the suggestions list.

What happens: 1 - mouse down on the suggestion option 2 - blur (input looses focus): geocomplete.find() function is activated. It will return the closest option for the text inserted in the input 3 - mouse up: geocomplete.find() function is activated. It selects the option the user clicked

I think that we can reach a solution if when there is a mouse down in the suggestion option we tell the script that the blur can't take effect (change a control variable). Maybe it's possible to bind a mouseDown event to the geocomplete the same way we are doing with the blur?

Can someone help me out to fix this please? Thank you very much.

rnuernberg commented 10 years ago

+1 I can confirm this - we have the exact same problem when blur is enabled.

tamanti commented 10 years ago

I managed to solve the issue disabling blur on mousedown and arrow down/up if an item is selected. I passed blur=false as option and implemented a new function (here called blurFunction). $('#inputText') is the input text to apply the geocomplete plugin.

var blurFunction = function(event, status){
 $('#inputText').trigger("geocode");
}

$('#inputText').focus(function() {
  $('#inputText').off("blur"); // To prevent against multiple binding
  $('#inputText').bind("blur", blurFunction);
});

$('#inputText').keyup(function(e) {
  if (e.keyCode == 40 || e.keyCode == 38) {  // Down arrow - up arrow
    if ($(".pac-item-selected").html()) {
      $('#inputText').off("blur");
    } else if ($(".pac-item-selected").html() == null) {
      $('#inputText').bind("blur", blurFunction);
    }
  }
});

// Remove event before clicking on menu
$(".pac-container").live("mousedown", function(event, status){
  $('#inputText').off("blur");
  //$('#anotherInputText').off("blur"); // if more than 1 geocode component in the same page
});
ldanielduarte commented 10 years ago

Hello tamanti,

Already tried your code and it works! It solves the multiple blur event. Thank you and gratz. But, now I face another problem (maybe someone can help): I have to force the user to select a valid field.

Sometimes the user writes only half word and then change the focus (by clicking or tab); Then the find function is called and it searches for the closest word match; Result: it doesn't return any of the words presented on the DropDownList (the nearer spots). (in some cases it doesn't even return any word. Eg.: When we type "Lisb" for Lisbon and we loose focus).

I created a function to return the first result of the list but this is not a clean way to do it! After the geocode function "geocode: function(request){" from the jquery.geocomplete.js script, I've added a custom function to search the first item of the list:

    // Get the selected result. If no result is selected on the list, then get the first result from the list.
    selectFirstResult: function() {
      var selected = '';
      // Check if any result is selected.
      if ($(".pac-item-selected")['0']) {
        selected = '-selected';
      }

      // Get the first suggestion's text.
      var $span1 = $(".pac-container .pac-item" + selected + ":first span:nth-child(2)").text();
      var $span2 = $(".pac-container .pac-item" + selected + ":first span:nth-child(3)").text();

      // Adds the additional information, if available.
      var firstResult = $span1;
      if ($span2) {
        firstResult += " - " + $span2;
      }

      return firstResult;
    },

Then we can call the function with something like:

    $('#inputText').focus(function() {
        $(this).unbind("blur"); // To prevent against multiple binding
        $(this).bind("blur", function(){
                setTimeout(function(){
                        var autoSelection = $('#inputText').trigger("selectFirstResult");
                        $('#inputText').val( $('#inputText').trigger("find",autoSelection) );
                },300);
        });
    });

Notice the "setTimeout()", it waits for the list to exists so that the selectFirstResult() function is able return a result. This is not a clean way to do this... If someone have some idea of how this can be done, Please help!

Thank you in advance.

adrienrn commented 9 years ago

We've been experiencing the same. Thank you for explaining what was happening.

@ldanielduarte Your selectFirstResult seems to have been added to the project and the only fix we've done was the one explained here: https://github.com/ubilabs/geocomplete/issues/119 by seanbfuller.