Creare un campo di testo che si autocompleti non è banale, presuppone eseguire delle query ad un db ogni volta che l'utente digita un carattere sulla tastiere. Ma andiamo per ordine:
Prima di tutto ci serve un campo di input:
<form id="search" action="search/index.php" method="get">
<label for="search-text">search the site</label>
<input type="text" name="search-text" id="search-text" />
</form>
Inoltre ci serve il file php cui inviare il valore del nostro campo di testo e da cui recuperare i match nel database:
<?php
if (strlen($_REQUEST['search-text']) < 1) {
print '[]';
exit;
}
$terms = array(
'access', 'action', 'active',
'step-by-step',
'stores',
'struts',
'sugarcrm',
'sysadmins',
'systems',
'tcp/ip',
'techniques',
'telefonia',
'telefonici',
'telefónicos',
'telephony'
);
$possibilities = array();
foreach ($terms as $term) {
if (strpos($term, strtolower($_REQUEST['search-text'])) === 0) {
$possibilities[] = "'". str_replace("'", "\\'", $term) ."'";
}
}
print ('['. implode(', ', $possibilities) .']');
Analizziamo il php:
Proviamo a cercare un termine: autocomplete step 1
E se voglio chiamare il file php con AJAX?
Javascript code:
$(document).ready(function() {
var $autocomplete = $('<ul class="autocomplete"></ul>').hide().
insertAfter('#search-text');
$('#search-text').keyup(function() {
$.ajax({
'url': 'search/index.php',
'data': {'search-text': $('#search-text').val()},
'dataType': 'json',
'type': 'POST',
'success': function(data) {
if (data.length) {
$autocomplete.empty();
$.each(data, function(index, term) {
$('<li></li>').text(term).appendTo($autocomplete);
});
$autocomplete.show();
}
}
});
});
});
Analizziamo il codice:
var $autocomplete = $('<ul class="autocomplete"></ul>').hide().insertAfter('#search-text');creo il contenitore per la mia lista e la aggiungo dopo il campo di input$.ajax({
'url': 'search/index.php',
'data': {'search-text': $('#search-text').val()},
'dataType': 'json',
'type': 'POST',
'success': function(data) {
if (data.length) {
$autocomplete.empty();
$.each(data, function(index, term) {
$('<li></li>').text(term).appendTo($autocomplete);
});
$autocomplete.show();
}
}
});chiamo attraverso ajax il file php, pulisco la lista, creo tanti li per ciascun risultatoRiproviamo adesso: autocomplete step 2
Adesso dobbiamo rendere cliccabile gli items della lista ed inseriri il valore selezionato nel campo di input:
Javascript code:
[...]
.appendTo($autocomplete).click(function() {
$('#search-text').val(term);
$autocomplete.hide();
});
Ed ecco il risultato: autocomplete step 3
Adesso evidenziamo il primo risultato e l'item correntemente sotto al mouse.
Per fare ciò abbiamo sempre bisogno di sapere l'item selezionato o su cui siamo sopra (il suo indice insomma)
Per fare ciò scriveremo una funzione:
Javascript code:
var selectedItem = null;
var setSelectedItem = function(item) {
selectedItem = item;
if (selectedItem === null) {
$autocomplete.hide();
return;
}
if (selectedItem < 0) {
selectedItem = 0;
}
if (selectedItem >= $autocomplete.find('li').length) {
selectedItem = $autocomplete.find('li').length - 1;
}
$autocomplete.find('li').removeClass('selected').eq(selectedItem).addClass('selected');
$autocomplete.show();
};
Analizziamo il codice:
Qualche ulteriore aggiustamento al codice:
$('#search-text').attr('autocomplete', 'off').keyup(function() {
$.ajax({
'url': 'search/index.php',
'data': {'search-text': $('#search-text').val()},
'dataType': 'json',
'type': 'POST',
'success': function(data) {
if (data.length) {
$autocomplete.empty();
$.each(data, function(index, term) {
$('<li></li>').text(term)
.appendTo($autocomplete).mouseover(function() {
setSelectedItem(index);
}).click(function() {
$('#search-text').val(term);
$autocomplete.hide();
});
});
setSelectedItem(0);
}
else {
setSelectedItem(null);
}
}
});
});
Ed ecco il risultato: autocomplete step 4
Adesso vogliamo aggiungere interattività con la tastiera. Cioè fare in modo di poter scorrere la lista con le arrow key up e down
Javascript code:
$('#search-text').attr('autocomplete', 'off').keyup(function(event) {
if (event.keyCode > 40 || event.keyCode == 8) {
// Keys with codes 40 and below are special
// (enter, arrow keys, escape, etc.).
// Key code 8 is backspace.
$.ajax({
'url': 'search/index.php',
'data': {'search-text': $('#search-text').val()},
'dataType': 'json',
'type': 'POST',
'success': function(data) {
if (data.length) {
$autocomplete.empty();
$.each(data, function(index, term) {
$('<li></li>').text(term)
.appendTo($autocomplete).mouseover(function() {
setSelectedItem(index);
}).click(function() {
$('#search-text').val(term);
$autocomplete.hide();
});
});
setSelectedItem(0);
}
else {
setSelectedItem(null);
}
}
});
}
else if (event.keyCode == 38 && selectedItem !== null) {
// User pressed up arrow
setSelectedItem(selectedItem - 1);
event.preventDefault();
}
else if (event.keyCode == 40 && selectedItem !== null) {
// User pressed down arrow.
setSelectedItem(selectedItem + 1);
event.preventDefault();
}
});
In questo caso il codice è rimasto invariato. Abbiamo solo specificato le condizioni rispetto a quali tasti prma l'utente. Nel caso l'utente prma le frecce, chiamiamo ogni volta la funzione setSelectedItem che ci siamo scritti
Ed ecco il risultato finale: autocomplete step 5