javascript, jquery, tutorial

Autocomplete con jQuery

09.14.09 | 25 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 && $(input).is(".suggest_table")){
	$(li).addClass("ac_first");
	var _ie_sucks = typeof document.body.style.maxHeight === "undefined" || //IE6
					(document.all && !window.opera && 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.

Popularity: 56% [?]

25 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

Post a Comment

Your email is never shared. Required fields are marked *

*
*