(function() {

// MAXB.NET LABS

})();

javascript, jquery, tutorial

Autocomplete con jQuery

Posted on by Massimiliano Balestrieri | Comments

NB: ci sono novità al fondo del post

Pubblico le mie 3 implementazioni del plugin jQuery Autocomplete di Jörn Zaefferer.

Queste implementazioni servono ad attivare campi form con suggest automatico senza scrivere una sola riga di javascript.

La prima implementazione autoattiva il plugin originale (con supporto ai metadata):

La seconda implementazione aggiunge “magicamente” un campo “hidden” e in fase di invio del “form” spedisce al server anche la chiave associata al valore selezionato nel suggest.

La terza invece crea un suggest “tabellare”. E’ stato necessario modificare lo script.

Per le demo ho usato:

HEAD HTML

Includere le librerie e i css necessari.

	<link href="lib/jquery.autocomplete.css" rel="stylesheet" type="text/css" media="screen" />
	<script src="lib/jquery-1.3.2.min.js" type="text/javascript"></script>
    <script src="lib/jquery.metadata.js" type="text/javascript"></script>
    <script src="lib/jquery.autocomplete.js" type="text/javascript"></script>
	<script src="autocomplete.custom.js" type="text/javascript"></script>

DOWNLOAD DEMO

SUGGEST BASE

Per attivare un suggest base è sufficiente

  • assegnare al campo input la classe suggest.
  • valorizzare l’attributo alt del campo input inserendo un url relativo es: “php/mesi.php”

Lo script php d’esempio che restituisce alle chiamate ajax l’elenco dei valori:

$q = strtolower($_GET["q"]);
if (!$q) return;
$items = array(
	'gennaio',
	'febbraio',
	'marzo',
	'aprile',
	'maggio',
	'giugno',
	'luglio',
	'agosto',
	'settembre',
	'ottobre',
	'novembre',
	'dicembre'
);

foreach ($items as $value) {
    if (strpos(strtolower($value), $q) !== false) {
        echo "$value\n";
    }
}

Chiaramente nelle applicazioni reali i dati non verranno presi da un array ma da un database

ESEMPIO 1

<input type="text" name="suggest1" id="suggest1" class="suggest" alt="php/mesi.php" />

ESEMPIO 2

Grazie all’uso di jQuery metadata le opzioni dell’autocomplete possono essere settate direttamente nell’html (quindi senza scrivere codice javascript).
L’elenco delle opzioni che modificano il comportamento del plugin si trova qui.

<input type="text" name="suggest2" id="suggest2" class="suggest {multiple:true}" alt="php/mesi.php" />

ESEMPIO 3

<input type="text" name="suggest3" id="suggest3" class="suggest {minChars:3, max:3}" alt="php/search.php" />

SUGGEST CHIAVE VALORE

La seconda implementazione di jQuery Autocomplete crea un campo hidden per la chiave legata al valore visualizzato in suggest in modo da poter inviare al server sia la chiave sia il valore in fase di submit.

Per attivare un suggest chiave/valore è sufficiente

  • assegnare al campo input la classe suggest_keys.
  • valorizzare l’attributo alt del campo input inserendo un url relativo es: “php/keys.php”

Lo script php d’esempio che restituisce alle chiamate ajax l’elenco di chiavi|valori:

$q = strtolower($_GET["q"]);
if (!$q) return;
$items = array(
	"10024" => "Moncalieri",
	"20000" => "Monza",
	"10100"	=> "Torino"
);

foreach ($items as $key=>$value) {
    if (strpos(strtolower($value), $q) !== false) {
        echo "$key|$value\n";
    }
}

ESEMPIO 4

<input type="text" name="suggest4" id="suggest4" class="suggest_keys" alt="php/keys.php" />

Se utilizzate firebug potrete vedere che viene creato un campo nascosto. Es:

<input type="hidden" value="" id="suggest4_hidden" name="suggest4_hidden"/>

ESEMPIO 5

<input type="text" name="entita[campo]" id="entita_campo" class="suggest_keys" alt="php/keys.php" />

Se utilizzate firebug potrete vedere che viene creato un campo nascosto. Es:

<input type="hidden" value="" id="entita_campo_hidden" name="entita[campo_hidden]"/>

SUGGEST TABELLARE

La terza implementazione di jQuery Autocomplete è un po’ più complessa e prevede l’utilizzo di una versione modificata di jquery autocomplete.

Per attivare un suggest tabellare è sufficiente

  • Includere nell’head la versione modificata di jQuery Autocomplete
  • assegnare al campo input la classe suggest_table.
  • personalizzare le intestazioni di colonna nell’attributo class (vedi sotto l’esempio)
  • valorizzare l’attributo alt del campo input inserendo un url relativo es: “php/table.php”
  • Includere le seguenti istruzioni css personalizzando “le larghezze” che nell’esempio settano le 3 colonne della tabella
.ac_results ul li div.tbl{clear:both;}
.ac_results ul li div.tbl div{float:left;width:30%;overflow-x:hidden;}
.ac_intestazione{position:absolute;left:0px;top:-0px;z-index:1000;background:#000;color:#fff;}

/*PERSONALIZZA*/
.ac_results ul li div.tbl div.fld_1, #int_1{width:150px;}
.ac_results ul li div.tbl div.fld_2, #int_2{width:70px;}
.ac_results ul li div.tbl div.fld_3, #int_3{width:70px;}

Lo script php d’esempio che restituisce alle chiamate ajax l’elenco dei valori della tabella.

$q = strtolower($_GET["q"]);
if (!$q) return;
$items = array(
	"10024" => array(
		"Moncalieri",
		"Torino",
		"Piemonte"
	),
	"20000" => array(
		"Conegliano",
		"Treviso",
		"Veneto"
	),
	"10100"	=> array(
		"Alba",
		"Cuneo",
		"Piemonte"
	)
);

foreach ($items as $key=>$array) {
	$str = join($array,"#");
    if (strpos(strtolower($str), $q) !== false) {
        echo "$key|$str\n";
    }
}

ESEMPIO TABELLARE

<input type="text" id="suggest1" name="suggest1" class="suggest_table {th : ['città', 'provincia', 'regione']}" alt="php/table.php" style="width:300px;" />

AGGIORNAMENTO 13-11-2009:

Ho aggiornato lo ZIP con le demo e gli script di questo post.

Ho aggiornato in particolare

Ho aggiunto questa DEMO per il passaggio delle opzioni autocomplete al plugin base (jquery.autocomplete.mod.js).

Le porzioni di jquery.autocomplete.js modificate sono a questo punto due, entrambe nel metodo/funzione fillList:

var li = $("<li/>").html( options.highlight(formatted, term) ).addClass(i%2 == 0 ? "ac_even" : "ac_odd").appendTo(list)[0];
//PATCH
if(i == 0 &amp;&amp; $(input).is(".suggest_table")){
	$(li).addClass("ac_first");
	var _ie_sucks = typeof document.body.style.maxHeight === "undefined" || //IE6
					(document.all &amp;&amp; !window.opera &amp;&amp; window.XMLHttpRequest); //IE7
	if (_ie_sucks || max == 1) {
		$(li).attr("style", "padding-top:20px");
	}
}
//PATCH
$.data(li, "ac_data", data[i]);
listItems = list.find("li");
if ( options.selectFirst ) {
	//PATCH
	//listItems.slice(0, 1).addClass(CLASSES.ACTIVE);
	listItems.slice(1, 2).addClass(CLASSES.ACTIVE);
	//PATCH
	active = 0;
}

Per questa seconda modifica, ringrazio Mansportivo che nei commenti qui sotto mi ha segnalato l’anomalia.

This entry was posted in javascript, jquery, tutorial and tagged , , , , . Bookmark the permalink.

39 Comments

  1. Posted 28 September 2009 at 11:29 | Permalink

    Ottima guida. Grazie!!!

  2. mansportivo
    Posted 30 September 2009 at 16:25 | Permalink

    nell’esempio tabellare se inserisci alb non fa vedere nulla, probabilmente c’è un errore

    magari puoi risolverlo

    ciao e grazie comunque per il tuo ottimo lavoro

  3. Posted 30 September 2009 at 16:52 | Permalink

    @mansportivo
    grazie della segnalazione. ho corretto la patch

    http://maxb.net/scripts/autocomplete/table.html

  4. mansportivo
    Posted 1 October 2009 at 10:01 | Permalink

    grazie mille

  5. mansportivo
    Posted 7 October 2009 at 11:08 | Permalink

    }).result(function(event, item) {
    alert (item);
    valori_selezionati=item;
    var _hidden_id = this.id + “_hidden”;
    $(“#” + _hidden_id).val(item[0]);
    });

    scusa se ti disturbo ma ho riscontrato questo problema: voglio riuscire ad intercettare il valore restituito dal codice sopra esposto appartenente al file “autocomplete.cutom.js” per qunto riguarda l’utilizzo tabellare

    se però scrivo valori_selezionati=item; e cerco di utilizzare la variabile valori_selezionati sul campo interessato son onchange o onblur mi restituisce un errore dicendo di che la variabile non esiste

    sai per caso come posso ottenere quello che voglio

    ciao e grazie anticipatamente

  6. Posted 7 October 2009 at 15:22 | Permalink

    @mansportivo

    non ho capito benissimo il problema (soprattutto la parte onchange/onblur).
    comunque se vuoi assegnare item ad una variabile GLOBALE (anche se non è proprio una bella pratica) devi dichiarare la variabile globalmente

    in pratica devi scrivere

    var valori_selezionati;

    fuori dallo script autocomplete.cutom.js

    se non ho capito il problema magari pubblicami da qualche parte una demo. proverò a guardare.

    ciao Max

  7. mansportivo
    Posted 7 October 2009 at 15:45 | Permalink

    sostanzialmente mi serve leggere cosa restituisce la procedura una volta selezionata la voce interessata e poi vorrei gestirla con
    una cosa del genere (qui c’è l’alert ma devo ovviamente fare altro):

  8. Posted 7 October 2009 at 17:14 | Permalink

    @mansportivo

    ti ho aggiunto un evento. così non devi modificare il file autocomplete.custom.js.
    guarda qui (l’head):
    http://maxb.net/scripts/autocomplete/table2.html

    fai il bind all’evento e usa i dati come vuoi.

    *naturalmente aggiorna il file autocomplete.custom.js che ho dovuto modificare per crearti l’evento

  9. mansportivo
    Posted 8 October 2009 at 10:11 | Permalink

    gentilissimo, grazie mille

  10. mansportivo
    Posted 14 October 2009 at 15:14 | Permalink

    nell’esempio tabellare mi sembra che non venga selezionato in automatico il primo valore, nemmeno utilizzando l’apposito flag selectFirst impostato a true

    sbaglio qualcosa o è un piccolo bug?

    ciao, grazie

  11. Posted 14 October 2009 at 15:58 | Permalink

    @mansportivo

    appena trovo il tempo provo a guardare come aggirare il problema

    ciao Max

  12. Enrico Carrara
    Posted 13 November 2009 at 10:16 | Permalink

    ho visto che al punto 2
    >@mansportivo
    >grazie della segnalazione. ho corretto la patch
    hai corretto il problema, ma i file in download presentano sempre lo stesso difetto.
    Puoi modificare anche i file per il download?
    grazie
    Enrico

  13. Posted 13 November 2009 at 10:23 | Permalink

    @enrico & mansportivo
    datemi qualche ora.
    provo a guardare anche la questione del seleziona primo valore nella versione tabellare.
    e aggiorno lo zip

  14. Posted 13 November 2009 at 12:45 | Permalink

    @ALL (mansportivo e enrico)

    1) ho corretto l’opzione selectFirst (da aggiornare jquery.autocomplete.mod.js)
    2) ho aggiornato autocomplete.custom.js (ora l’esempio tabellare accetta anche opzioni per sovrascrivere autocomplete)

    guardate questa demo:

    http://maxb.net/scripts/autocomplete/table_opzioni_autocomplete.html

    3) ho aggiornato lo zip

  15. Enrico Carrara
    Posted 14 November 2009 at 00:33 | Permalink

    funziona
    grazie

  16. Posted 9 January 2010 at 16:08 | Permalink

    Utilissima la versione tabellare!

    è troppo chiederti di fare un esempio dello script di come prelevare i valori da una tbl db aggiungendo un button che restituisce l’id … mi ci sto perdendo e credo sarebbe utile a tutti

    Grazie in anticipo

    Nik

  17. Posted 28 January 2010 at 17:18 | Permalink

    Ciao nel tabellare ho notato che quando scende la tendina, alla prima pressione della freccetta sulla tastiera, il record evidenziato non si muove mentre dalla seconda in poi funziona correttamente. Un’altra anomalia è se si tenta di muovere l’evidenziatore utilizzando da subito la freccetta verso l’alto, vengono evidenziati 2 record. Comunque al dilà di queste due piccole anomalie complimenti per l’ottimo lavoro svolto!

  18. Max
    Posted 19 February 2010 at 20:06 | Permalink

    Sarebbe splendido avere una versione con i suggerimenti forzati, in modo che ad esempio, in una tabella di città del piemonte, l’utente non inserisca ‘Saluzo’ ecc

  19. Arnaldo
    Posted 24 February 2010 at 12:47 | Permalink

    Ciao Max e complimenti sinceri per lo script.
    una domanda forse banale:
    nel caso “SUGGEST CHIAVE VALORE”
    Come posso fare in modo che i suggerimenti siano link alla chiave o al valore?

    grazie mille del tuo tempo

  20. Posted 24 February 2010 at 13:07 | Permalink

    @arnaldo

    va un po’ oltre le responsabilità che dovrebbe avere un suggest… cmq se guardi nello script

    http://maxb.net/scripts/autocomplete/autocomplete.custom.js

    alla riga 78-81 c’è la parte che si occupa di scrivere l’id nell “input:hidden”.

    se vuoi fare una location.href basta modificare quella parte.

    @max (scusa il ritardo della risposta)

    anche le combo di extjs

    http://www.extjs.com/deploy/ext-1.0.1/examples/form/combos.html

    mi sembra che ti lascino scrivere “saluzo”.
    quello che vuoi fare tu non è tanto un suggest quanto un “SELECT REPLACEMENT” in forma tabellare (select come tag html).

    Non è poi così difficile da realizzare. Alla fin fine sarebbe un div da mostrare/nascondere con delle righe selezionabili. Non un suggest quindi. Certo che se poi vuoi comandare la selezione con la tastiera (simulando il suggest) la cosa diventa complicata.

    @xeninweb questo script è un hack. non è un plugin che ho realizzato io. E’ un wrapper. Scusa i paroloni. Un qualcosa che si mette “sopra” e personalizza il comportamento. La versione tabellare con intestazione funziona così. Magari in rete ci sono dei suggest che partono più avanzati. Una soluzione potrebbe essere forse non avere la riga di intestazione (presupponendo che i dati non ne abbiano bisogno). Non so.

  21. Arnaldo
    Posted 24 February 2010 at 17:30 | Permalink

    grazie Massimiliano,
    ho velocemente risolto inserendo
    un
    document.location.href=item[0];
    (per me la hidden coincide con l’url)
    subito dopo la riga
    $(“#” + _hidden_id).val(item[0]);

    se vuoi vederlo online
    http://www.musicaitaliana.com

  22. Ros
    Posted 7 May 2010 at 12:25 | Permalink

    Ciao ho notato che hai aggiunto la possibilità di intercettare la voce selezionata e mi stavo chiedendo se è possibile anche intercettare il fatto che l’autocomplete non appare, perchè ho scritto un valore sbagliato. Io ho provato a farlo,ma non mi è riuscito.
    Grazie in anticipo.
    Complimenti, è davvero un’ottima guida.

  23. Posted 7 May 2010 at 12:36 | Permalink

    @ros
    Lato server controlli le voci da restituire. Se non ci sono record sei libera di inviare un “record finto” con un messaggio d’errore. L’effetto perverso è che poi questa voce sarebbe selezionabile e cliccabile. Bisogna vedere come usi il suggest.
    Ciao Massimiliano

  24. Fulvio
    Posted 18 June 2010 at 03:13 | Permalink

    E’ possibile utilizzarlo anche in progetto asp.net ? qualche riga di codice d’esempio per un neofita ?

  25. Posted 18 June 2010 at 09:29 | Permalink

    @Fulvio

    La parte server side è assolutamente indipendente.
    Ad esempio qui (nel post “esempio SUGGEST BASE”)
    http://maxb.net/scripts/autocomplete/1.html

    la parte server (php) – usa firebug per vedere le chiamate ajax
    http://maxb.net/scripts/autocomplete/php/mesi.php?q=a&limit=10&timestamp=1276847685260

    produce questo (il parametro GET q=a è il filtro)
    gennaio\nfebbraio\nmarzo\naprile\nmaggio\nagosto

    \n (a capo) è il separatore di “record”
    L’esempio di script che produce l’elenco di voci lo trovi nel post ed è veramente minimale. In .net non penso avrai alcuna difficoltà a riprodurlo.

    Ciao Max

  26. Alessandro
    Posted 14 September 2010 at 00:08 | Permalink

    Ciao Massimiliano,
    Innanzi tutto i miei complimenti per il bel lavoro…
    Ho notato un problema con windows explorer 8, in pratica la scelta multipla non funziona correttamente, inserendo un valore successivo al primo, questo si posiziona al posto del primo e non a seguire (dopo il separatore per intenderci), non so se e’ veramente un bug o ha qualche problemi il mio IE8, su chrome funziona bene.
    Grazie

  27. Posted 2 October 2010 at 15:06 | Permalink

    Ciao potresti postare un equivalente della pagina table.php che però legge i dati da un database. sto provando a crearla ma non riesco .
    e poi se è possibile filtrare la ricerca non per tutte le colonne ma solo per la prima

  28. Gianluca
    Posted 29 October 2010 at 12:32 | Permalink

    Complimenti per la guida e per le segnalazioni (tramite quelle ho risolto molto)!!!

  29. Posted 8 November 2010 at 00:37 | Permalink

    scusami ho trovato la tua guida molto interessante.. ma mi occorreva sapere come implemento una query per collegare lo script al mio database

    sono una novizia :)

    grazie

  30. Posted 8 November 2010 at 00:38 | Permalink

    e soprattuto dove lo inserisco… :) grazie mille anticipatamente

  31. Posted 8 November 2010 at 08:26 | Permalink

    @Marco e @Graziella

    provate a guardare qui.
    http://blog.themeforest.net/screencasts/diving-into-php-day-10/
    altrimenti investite qualche euro in un libro sul php.

  32. Peppe
    Posted 1 February 2011 at 23:07 | Permalink

    ciao,

    ho scaricato il file zip con i vari esempi. ho scompattato e ho testato il tutto in firefox, senza fare nessuna modifica..purtroppo nella casella di testo non appena scrivo una lettera appare il contenuto del file php linkato con l’alt. per esempio se uso 1.html nella casella di input mi appare il testo del file mese.php..
    c’è qualche errore di codice o cosa?
    spero riesci a rispondermi presto perchè il tuo tutorial ora mi è utile per fare una cosa simile.
    grazie.

  33. Posted 2 February 2011 at 09:17 | Permalink

    @Peppe

    Ciao Peppe
    Ho bisogno di una demo, per aiutarti.
    Passami un link, una url visitabile. A naso… da quello che dici, il file php che punti non è “interpretato” dal webserver, e ti viene servito come file di testo.
    Spero di esserti stato di aiuto.
    Ciao Max
    PS: il plugin autocomplete è dismesso dall’autore. Ora andrebbe usato jquery ui autocomplete.
    http://jqueryui.com/demos/autocomplete/

  34. Posted 23 February 2011 at 11:21 | Permalink

    Ciao Peppe …
    Anche io ho lo stesso problema … Se provo la demo TABELLARE nel tuo sito tutto funziona a meraviglia, ma se provo i file scaricati in locale mi ritorna un errore nel file autocomplete.custom.js

    1 e nullo o non è un oggetto linea 129 carattere 4

  35. Marcello
    Posted 13 March 2011 at 11:00 | Permalink

    Ciao Massimiliano, non sono molto pratico di jquery però grazie a te e alla tua chiara spiegazione sono riuscito subito a farlo funzionare,
    volevo chiederti solo una cosa.
    Quando io vado a popolare i risultati di autocomplete, devo per forza inserire solo testo, se invece metto qualcosa di particolare tipo immagini ecc, e poi clicco sul risultato di autocomplete, nel campo input mi mette tutto il codice html e quindi non solamente il nome…..non so se mi sono spiegato bene.
    Puoi aiutarmi?

  36. Posted 13 March 2011 at 11:29 | Permalink

    Ciao Marcello,

    devi usare la versione tabellare di questo post e modificare la funzione in autocomplete.custom.js

    function _table_format(options, row, pos)
    

    andando a inserire un tag img con l’attributo src valorizzato dal suggest.
    Ciao Max

  37. Posted 11 July 2011 at 14:57 | Permalink

    Ciao,
    mi dispiace scrivere su questo post, ma ho una domanda su l’autocomplete (http://maxb.net/blog/2009/09/14/autocomplete-con-jquery/) e ho visto che lì i commenti sono stati disattivati.

    La mia domanda è questa:
    Nella versione SUGGEST TABELLARE c’è un modo per cercare su più campi, ma esporne solo un numero limitato. Ad esempio ho ID|titolo titolo#codice codice#descrizione descrizione
    La ricerca dovrebbe avvenire su titolo, codice e descrizione, ma all’interno della tabella vorrei mostrare solo titolo e codice.

    Grazie mille in anticipo per ogni eventuale suggerimento.

  38. Marco
    Posted 11 July 2011 at 18:52 | Permalink

    Ciao Massimiliano scusa se posto quì una mia domanda,ma nell’articolo interessato non ne ho la possibilità quindi in primis,perdonami…
    Ho visto il tuo bellissimo ed esaustivo articolo sull’autocomplete
    http://maxb.net/blog/2009/09/14/autocomplete-con-jquery/
    e dato che va alla perfezione,volevo chiederti una cosa…
    Posso per caso abilitarlo e disabilitarlo a mio piacimento alla selezione di una determinata radio? non riesco a farlo…non è che magari mi potresti aiutare,sempre ovviamente se non è un disturbo… cosi potrei destinare la stessa text box per due tipi di ricerche e credo che possa essere utile anche ad altri…Ti ringrazio immensamente anche solo per l’attenzione prestatami. un salutone

  39. Posted 12 July 2011 at 08:39 | Permalink

    @Marco, @Luca

    Ciao e scusate il ritardo. Ho spostato il commento sul post corretto… spero riceviate ugualmente la notifica.
    Grazie per i complimenti sull’articolo.
    Il problema di questo autocomplete… è che è morto :)
    L’autore l’ha abbandonato, che io sappia.
    Perchè non provate a usare il nuovo autocomplete di jQuery UI?

    Nello specifico, non so veramente. Per la ricerca su più campi francamente non ricordo. Penso di si… ma a forza di martellate. Il plugin non nasce certo per quello!
    Per il radio, penso sia più semplice provare ad attivare due suggest magari giocando con position:absolute, sovrapporli, e rendere visibile solo quello che interessa.

    In ogni caso, io vi consiglio caldamente prima di provare a usare jquery UI.
    http://jqueryui.com/demos/autocomplete/

    Io l’ho usato qui (per attivare il suggest juv):
    http://maxb.net/scripts/fbsuggest/demos/1.html
    http://maxb.net/scripts/fbsuggest/demos/2.html
    http://maxb.net/scripts/fbsuggest/demos/3.html

    Sono customizzazioni. Quindi potete guardando il codice e il css, ispirarvi per il vostro lavoro.

    Più di così non riesco a aiutarvi
    ciao max :)