Autocomplete do JQuery - Busca no banco em toda letra digitada!

Front-end

30/09/2015

Olá.

Estou usando o plugin autocomplete do JQuery para autocompletar uma combobox.

Estou usando o código abaixo para que, ao selecionar uma opção na lista da combobox, seja feita uma busca po ajax no banco e popule o campo ${"#valorCombinado"}.

	 <!-- INICIO ENTREGA VALOR DO PLANO -->	
	  $(function(){
      $(document).on("click", "li", function() {
		  //Pega o id (value) do select atrelado à li escolhida
		  planoEscolhido = $("#plano").val();
		  //Pega o texto do select atrelado à li escolhida
		  planoEscolhidoTexto = $("#plano option:selected").text();
		  
		  $.getJSON('planos.ajax.php?search=',{plano: planoEscolhido, ajax: 'true'}, function(resultado){
			  novoValor = formataMoeda(resultado['valorPlano'],2, ',', '.');
			  $('#valorCombinado').val(novoValor);
		  });		  
			  
    	});           
	  });         
	 <!-- FINAL ENTREGA VALOR DO PLANO -->

Agora gostaria de encontrar uma forma de a cada letra digitada, no momento em que o autocomplete acontece, se houver uma combinação do que foi digitado até o momento com alguma opção da comboboxo, também disparar o ajax para popular o ${"valorCombinado"}.

Porém, não encontro no plugin onde é que o autocoplete ocorre para eu colocar o ajax ali.

Podem me ajudar?

Esse é o plugin funcionando:

http://jsfiddle.net/swqwLfxu/40/

Qualquer coisa, segue todo o código abaixo:

	(function( $ ) {
		$.widget( "custom.combobox", {
			_create: function() {
				this.wrapper = $( "<span>" )
					.addClass( "custom-combobox" )
					.insertAfter( this.element );

				this.element.hide();
				this._createAutocomplete();
				this._createShowAllButton();
			},

			_createAutocomplete: function() {
				var selected = this.element.children( ":selected" ),
					value = selected.val() ? selected.text() : "";

				this.input = $( "<input>" )
					.appendTo( this.wrapper )
					.val( value )
					.attr( "title", "" )
					.addClass( "custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left" )
					.autocomplete({
						delay: 0,
						minLength: 0,
						source: $.proxy( this, "_source" )
					})
					.tooltip({
						tooltipClass: "ui-state-highlight"
					});

				this._on( this.input, {
					autocompleteselect: function( event, ui ) {
						ui.item.option.selected = true;
						this._trigger( "select", event, {
							item: ui.item.option
						});
					},

					autocompletechange: "_removeIfInvalid"
				});
			},

			_createShowAllButton: function() {
				var input = this.input,
					wasOpen = false;

				$( "<a>" )
					.attr( "tabIndex", -1 )
					.attr( "title", "Mostrar todos os Registros" )
					.tooltip()
					.appendTo( this.wrapper )
					.button({
						icons: {
							primary: "ui-icon-triangle-1-s"
						},
						text: false
					})
					.removeClass( "ui-corner-all" )
					.addClass( "custom-combobox-toggle ui-corner-right" )
					.mousedown(function() {
						wasOpen = input.autocomplete( "widget" ).is( ":visible" );
					})
					.click(function() {
						input.focus();

						// Close if already visible
						if ( wasOpen ) {
							return;
						}

						// Pass empty string as value to search for, displaying all results
						input.autocomplete( "search", "" );
					});
			},

			_source: function( request, response ) {
				var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
				response( this.element.children( "option" ).map(function() {
					var text = $( this ).text();
					if ( this.value && ( !request.term || matcher.test(text) ) )
						return {
							label: text,
							value: text,
							option: this
						};
				}) );
			},

			_removeIfInvalid: function( event, ui ) {

				// Selected an item, nothing to do
				if ( ui.item ) {
					return;
				}

				// Search for a match (case-insensitive)
				var value = this.input.val(),
					valueLowerCase = value.toLowerCase(),
					valid = false;
				this.element.children( "option" ).each(function() {
					if ( $( this ).text().toLowerCase() === valueLowerCase ) {
						this.selected = valid = true;
						return false;
					}
				});

				// Found a match, nothing to do
				if ( valid ) {
					return;
				}

				// Remove invalid value
				this.input
					.val( "" )
					.attr( "title", value + " didn't match any item" )
					.tooltip( "open" );
				this.element.val( "" );
				this._delay(function() {
					this.input.tooltip( "close" ).attr( "title", "" );
				}, 2500 );
				this.input.autocomplete( "instance" ).term = "";
			},

			_destroy: function() {
				this.wrapper.remove();
				this.element.show();
			}
		});
	})( jQuery );

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

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

	});
     
	 <!-- INICIO ENTREGA VALOR DO PLANO -->	
	  $(function(){
      $(document).on("click", "li", function() {
		  //Pega o id (value) do select atrelado à li escolhida
		  planoEscolhido = $("#plano").val();
		  //Pega o texto do select atrelado à li escolhida
		  planoEscolhidoTexto = $("#plano option:selected").text();
		  
		  $.getJSON('planos.ajax.php?search=',{plano: planoEscolhido, ajax: 'true'}, function(resultado){
			  novoValor = formataMoeda(resultado['valorPlano'],2, ',', '.');
			  $('#valorCombinado').val(novoValor);
		  });		  
			  
    	});           
	  });         
	 <!-- FINAL ENTREGA VALOR DO PLANO -->
Carlos Rocha

Carlos Rocha

Curtidas 1

Respostas

Marcio Araujo

Marcio Araujo

30/09/2015

Boa tarde Carlos Rocha, ainda não conheço bem o JQuery, existe um post com praticamente sua mesma duvida.

[url]https://www.devmedia.com.br/forum/como-fazer-autocomplete-puxando-do-banco-mysql/433945[/url]
GOSTEI 0
Carlos Rocha

Carlos Rocha

30/09/2015

Boa tarde! Já tinha visto este post Mas ele também não informa onde ocorre o autocomplete letra por letra digitada!
GOSTEI 0
Marcio Araujo

Marcio Araujo

30/09/2015

Desculpa, como disse não conheço bem o JQuery.
ultima tentativa: [url]http://blog.idealmind.com.br/desenvolvimento-web/javascript/simple-autocomplete-jquery-plugin/[/url]
GOSTEI 0
Carlos Rocha

Carlos Rocha

30/09/2015

Não tem essa informação lá!

Parece que esse plugin foi modificado para utilização com selec's!
GOSTEI 0
Carlos Rocha

Carlos Rocha

30/09/2015

Não tem essa informação lá!

Parece que esse plugin foi modificado para utilização com selec's!
GOSTEI 0
Marcio Araujo

Marcio Araujo

30/09/2015

Então peço desculpas por não poder te ajudar mais, nem na documentação do JQuery tem essa informação?
GOSTEI 0
Carlos Rocha

Carlos Rocha

30/09/2015

Mexer no plugin em si não mexi. Mas acho que deve ser uma das configurações (interfaces) do script que postei na pergunta. Testei todas mas não achei!

Gostaria de achar a parte do código que ajunta cada um digito já digitado e vai autocompletando com as combinações.
GOSTEI 0
Marcio Araujo

Marcio Araujo

30/09/2015

Mais um link para analise.

[url]https://jqueryui.com/autocomplete/[/url]
GOSTEI 0
Carlos Rocha

Carlos Rocha

30/09/2015

Marcio, esse ai autocompleta um type["text"] existente. Não é o mesmo não!

No que estou usando, os inputs são criados dinamicamente e não consigo achar onde e nem onde ocorre o autocomplete!
GOSTEI 0
Marcio Araujo

Marcio Araujo

30/09/2015

Ahh, pensei que esse ultimo fosse o mais certo para o seu problema, vamos aguardar alguem com experiencia no JQuery. Abraço.
GOSTEI 0
Carlos Rocha

Carlos Rocha

30/09/2015

Esse ai foi bem fácil para entender.

Diferente desse meu$ que é preciso ter uma Select Option.

Se a Select Option aceitasse digitação na caixa de texto dela. mas quando clicka lá abre a combo. Aff! Saudades do Delphi!

Olha o caso desse que funciona normal:

$(document).ready(function(){
	  var source = [{
	  label: "Tom Smith",
	  value: "1234"
  }, {
	  label: "Tommy Smith",
	  value: "12321"
  }];
  
  $("#descricao").autocomplete({
	  source: source,
	  minLength: 3, //quantidade de caracteres para começar a buscar
	  select: function (event, ui) {
		  //evento de quando você seleciona uma opções        
		  $("#descricao").val(ui.item.label); //seto a descrição para aparecer para usuario no input text
		  $("#id").val(ui.item.value); //seto o id para ir para seu backend :D
		  event.preventDefault();
	  }
  });  
});

html
<!doctype html>
<html lang="en">
  <head>
      <meta charset="utf-8">
      <title>jQuery UI Autocomplete - Text</title>
      
      <link rel="stylesheet" type="text/css" href="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.14/themes/black-tie/jquery-ui.css">
      
      <script src="http://code.jquery.com/jquery-1.6.2.js"></script>
      <script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.14/jquery-ui.min.js"></script>      
      <script src="jqueryChamada.js"></script>
      
  </head>
  <body>
  
  <input type="text" id="descricao" />
  <input type="hidden" name="id" id="id" />
  
  </body>
</html>

Lugar algum pego o evento da digitação
GOSTEI 0
Carlos Rocha

Carlos Rocha

30/09/2015

Olha quer coisa estranha ocorre:

fiz:

  this.input.on("keydown", function () {
        alert($("this.input").val());
   });


O keydown ocorre dentro do campo. mas o alert diz que o campo é indefinido
GOSTEI 0
William

William

30/09/2015

Carlos dá uma olha nesse exemplo do meu blog http://www.devwilliam.com.br/php/autocomplete-com-jquery-ui-php-mysql
GOSTEI 0
Carlos Rocha

Carlos Rocha

30/09/2015

Oi William, valeu. Mas não consegui encontrar o evento keyUp nem como capturar o que esta escrito na caixa de texto. É isso que eu preciso. Do texto que foi digitado na caixa de texto.
GOSTEI 0
William

William

30/09/2015

Na documentação oficial desse plugin jQuery UI, existem alguns eventos relacionados ao componente que podem lhe ajudar, cito principalmente "search" e "change":
http://api.jqueryui.com/autocomplete/
GOSTEI 0
Marcio Araujo

Marcio Araujo

30/09/2015

Poxa, como eu queria ajudar mais, na sua ultima mensagem, eu entendi que deseja um historico do que foi digitado mas não obrigatoriamente que vem do banco?
GOSTEI 0
Carlos Rocha

Carlos Rocha

30/09/2015

Márcio, não é histórico não. Queria pegar o texto que já foi digitado a cada vez que se pressiona uma tecla dentro da caixa de texto. Ou seja, quando o evento onkeydown acontece
GOSTEI 0
Carlos Rocha

Carlos Rocha

30/09/2015

Vê ai!

JQuery
GOSTEI 0
Carlos Rocha

Carlos Rocha

30/09/2015

Obrigado a todos:
Resolvido!
Criei um array textos do select option:
function preencheValorPlano(valor) {	

		  $.getJSON('planos.ajaxTexto.php?search=',{plano: valor, ajax: 'true'}, function(resultado){
			  novoValor = formataMoeda(resultado['valorPlano'],2, ',', '.');
			  $('#valorCombinado').val(novoValor);
		  });		  
			  
}

(function( $ ) {
    $.widget( "custom.combobox", {
      _create: function() {
        this.wrapper = $( "<span>" )
          .addClass( "custom-combobox" )
          .insertAfter( this.element );

        this.element.hide();
        this._createAutocomplete();
        this._createShowAllButton();
      },

      _createAutocomplete: function() {
        var selected = this.element.children( ":selected" ),
          value = selected.val() ? selected.text() : "";

          var timeout = ''; //VARIÁVEL EXTERNA PARA CONTROLE DO TIMEOUT
          
        this.input = $( "<input>" )
          .appendTo( this.wrapper )
          .val( value )
          .attr( "title", "" )
          .addClass( "custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left" )
          .autocomplete({
            delay: 0,
            minLength: 0,
            source: $.proxy( this, "_source" )
          })
          .tooltip({
            tooltipClass: "ui-state-highlight"
          })
          .on( 'keyup', function() { // Evento após digitar uma letra
            var valor = $(this).val(); // Pega o valor do campo

            clearTimeout(timeout); // Cancela o timeout anterior
           
            timeout = setTimeout( function() {
				//alert(planosJson[0]);
				for (i=0; i < planosJson.length; i++) {
				  if(planosJson[i].toLowerCase() == valor.toLowerCase() )
				  {
					  preencheValorPlano(valor);
				  }
				}
            }, 500 ); // apos digitar uma sequencia, espera 500ms antes de executar o ajax

          });


          /* Explicando: Ao digitar algo, após o tempo de espera (em ms), ele executará o ajax que busca no BD. Assim, se você digitar uma letra, e em seguida, em menos de 500ms digitar outra, o ajax não será executado, ou seja, isso evita que ao se escrever uma palavra rapidamente, ele fique desnecessariamente pesquisando cada letra que foi digitada e sobrecarregar a pesquisa. Resumindo, dá a possibilidade de digitar uma sequencia de letras e pesquisar uma vez só no BD */
          
          
        this._on( this.input, {
          autocompleteselect: function( event, ui ) {
            ui.item.option.selected = true;
            this._trigger( "select", event, {
              item: ui.item.option
            });
          },

          autocompletechange: "_removeIfInvalid"
        });
      },

      _createShowAllButton: function() {
        var input = this.input,
          wasOpen = false;

        $( "<a>" )
          .attr( "tabIndex", -1 )
          .attr( "title", "Exibir todos os ítens" )
          .tooltip()
          .appendTo( this.wrapper )
          .button({
            icons: {
              primary: "ui-icon-triangle-1-s"
            },
            text: false
          })
          .removeClass( "ui-corner-all" )
          .addClass( "custom-combobox-toggle ui-corner-right" )
          .mousedown(function() {
            wasOpen = input.autocomplete( "widget" ).is( ":visible" );
          })
          .click(function() {
            input.focus();

            // Close if already visible
            if ( wasOpen ) {
              return;
            }

            // Pass empty string as value to search for, displaying all results
            input.autocomplete( "search", "" );
          });
      },

      _source: function( request, response ) {
        var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
        response( this.element.children( "option" ).map(function() {
          var text = $( this ).text();
          if ( this.value && ( !request.term || matcher.test(text) ) )
            return {
              label: text,
              value: text,
              option: this
            };
        }) );
      },

      _removeIfInvalid: function( event, ui ) {

        // Selected an item, nothing to do
        if ( ui.item ) {
          return;
        }

        // Search for a match (case-insensitive)
        var value = this.input.val(),
          valueLowerCase = value.toLowerCase(),
          valid = false;
        this.element.children( "option" ).each(function() {
          if ( $( this ).text().toLowerCase() === valueLowerCase ) {
            this.selected = valid = true;
            return false;
          }
        });

        // Found a match, nothing to do
        if ( valid ) {
          return;
        }

        // Remove invalid value
        this.input
          .val( "" )
          .attr( "title", value + " didn't match any item" )
          .tooltip( "open" );
        this.element.val( "" );
        this._delay(function() {
          this.input.tooltip( "close" ).attr( "title", "" );
        }, 2500 );
        this.input.autocomplete( "instance" ).term = "";
      },

      _destroy: function() {
        this.wrapper.remove();
        this.element.show();
      }
    });
  })( jQuery );

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

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

	});
     
	 <!-- INICIO ENTREGA VALOR DO PLANO -->	
	  $(function(){
      $(document).on("click", "li", function() {
		  //Pega o id (value) do select atrelado à li escolhida
		  planoEscolhido = $("#plano").val();
		  //Pega o texto do select atrelado à li escolhida
		  planoEscolhidoTexto = $("#plano option:selected").text();
		  
		  $.getJSON('planos.ajaxId.php?search=',{plano: planoEscolhido, ajax: 'true'}, function(resultado){
			  novoValor = formataMoeda(resultado['valorPlano'],2, ',', '.');
			  $('#valorCombinado').val(novoValor);
		  });		  
			  
    	});           
	  });         
	 <!-- FINAL ENTREGA VALOR DO PLANO -->
GOSTEI 0
Carlos Rocha

Carlos Rocha

30/09/2015

Obrigado a todos:
Resolvido!
Criei um array textos do select option:
function preencheValorPlano(valor) {	

		  $.getJSON('planos.ajaxTexto.php?search=',{plano: valor, ajax: 'true'}, function(resultado){
			  novoValor = formataMoeda(resultado['valorPlano'],2, ',', '.');
			  $('#valorCombinado').val(novoValor);
		  });		  
			  
}

(function( $ ) {
    $.widget( "custom.combobox", {
      _create: function() {
        this.wrapper = $( "<span>" )
          .addClass( "custom-combobox" )
          .insertAfter( this.element );

        this.element.hide();
        this._createAutocomplete();
        this._createShowAllButton();
      },

      _createAutocomplete: function() {
        var selected = this.element.children( ":selected" ),
          value = selected.val() ? selected.text() : "";

          var timeout = ''; //VARIÁVEL EXTERNA PARA CONTROLE DO TIMEOUT
          
        this.input = $( "<input>" )
          .appendTo( this.wrapper )
          .val( value )
          .attr( "title", "" )
          .addClass( "custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left" )
          .autocomplete({
            delay: 0,
            minLength: 0,
            source: $.proxy( this, "_source" )
          })
          .tooltip({
            tooltipClass: "ui-state-highlight"
          })
          .on( 'keyup', function() { // Evento após digitar uma letra
            var valor = $(this).val(); // Pega o valor do campo

            clearTimeout(timeout); // Cancela o timeout anterior
           
            timeout = setTimeout( function() {
				//alert(planosJson[0]);
				for (i=0; i < planosJson.length; i++) {
				  if(planosJson[i].toLowerCase() == valor.toLowerCase() )
				  {
					  preencheValorPlano(valor);
				  }
				}
            }, 500 ); // apos digitar uma sequencia, espera 500ms antes de executar o ajax

          });


          /* Explicando: Ao digitar algo, após o tempo de espera (em ms), ele executará o ajax que busca no BD. Assim, se você digitar uma letra, e em seguida, em menos de 500ms digitar outra, o ajax não será executado, ou seja, isso evita que ao se escrever uma palavra rapidamente, ele fique desnecessariamente pesquisando cada letra que foi digitada e sobrecarregar a pesquisa. Resumindo, dá a possibilidade de digitar uma sequencia de letras e pesquisar uma vez só no BD */
          
          
        this._on( this.input, {
          autocompleteselect: function( event, ui ) {
            ui.item.option.selected = true;
            this._trigger( "select", event, {
              item: ui.item.option
            });
          },

          autocompletechange: "_removeIfInvalid"
        });
      },

      _createShowAllButton: function() {
        var input = this.input,
          wasOpen = false;

        $( "<a>" )
          .attr( "tabIndex", -1 )
          .attr( "title", "Exibir todos os ítens" )
          .tooltip()
          .appendTo( this.wrapper )
          .button({
            icons: {
              primary: "ui-icon-triangle-1-s"
            },
            text: false
          })
          .removeClass( "ui-corner-all" )
          .addClass( "custom-combobox-toggle ui-corner-right" )
          .mousedown(function() {
            wasOpen = input.autocomplete( "widget" ).is( ":visible" );
          })
          .click(function() {
            input.focus();

            // Close if already visible
            if ( wasOpen ) {
              return;
            }

            // Pass empty string as value to search for, displaying all results
            input.autocomplete( "search", "" );
          });
      },

      _source: function( request, response ) {
        var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
        response( this.element.children( "option" ).map(function() {
          var text = $( this ).text();
          if ( this.value && ( !request.term || matcher.test(text) ) )
            return {
              label: text,
              value: text,
              option: this
            };
        }) );
      },

      _removeIfInvalid: function( event, ui ) {

        // Selected an item, nothing to do
        if ( ui.item ) {
          return;
        }

        // Search for a match (case-insensitive)
        var value = this.input.val(),
          valueLowerCase = value.toLowerCase(),
          valid = false;
        this.element.children( "option" ).each(function() {
          if ( $( this ).text().toLowerCase() === valueLowerCase ) {
            this.selected = valid = true;
            return false;
          }
        });

        // Found a match, nothing to do
        if ( valid ) {
          return;
        }

        // Remove invalid value
        this.input
          .val( "" )
          .attr( "title", value + " didn't match any item" )
          .tooltip( "open" );
        this.element.val( "" );
        this._delay(function() {
          this.input.tooltip( "close" ).attr( "title", "" );
        }, 2500 );
        this.input.autocomplete( "instance" ).term = "";
      },

      _destroy: function() {
        this.wrapper.remove();
        this.element.show();
      }
    });
  })( jQuery );

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

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

	});
     
	 <!-- INICIO ENTREGA VALOR DO PLANO -->	
	  $(function(){
      $(document).on("click", "li", function() {
		  //Pega o id (value) do select atrelado à li escolhida
		  planoEscolhido = $("#plano").val();
		  //Pega o texto do select atrelado à li escolhida
		  planoEscolhidoTexto = $("#plano option:selected").text();
		  
		  $.getJSON('planos.ajaxId.php?search=',{plano: planoEscolhido, ajax: 'true'}, function(resultado){
			  novoValor = formataMoeda(resultado['valorPlano'],2, ',', '.');
			  $('#valorCombinado').val(novoValor);
		  });		  
			  
    	});           
	  });         
	 <!-- FINAL ENTREGA VALOR DO PLANO -->
GOSTEI 0
Marcio Araujo

Marcio Araujo

30/09/2015

Conseguiu! show, não respondi mais por não poder realmente contribuir.
GOSTEI 0
POSTAR