var Autocomplete = {
// Connette un input a una sorgente dati e fornisce una funzione di autocompletamento
// @param selector selettore CSS per l'input
// @param datasource URL dove vengono richiesti i dati
// @options (opzionale) permette di specificare:
// delay => quanto tempo deve passare prima che la richiesta alla sorgente venga inviata (calcolata dall'ultima battitura)
// params => parametri da passare alla sorgente
// timeout => numero di millisecondi prima che la richiesta ajax fallisca
Bind: function(selector, datasource, options){
if (options === undefined) options = {};
var $item = $(selector);
if ($item.length > 0){
// Parametri di default
var delay = options.delay || 500;
var params = options.params || {};
var timeout = options.timeout || 10000;
var data = {
"term" : ""
};
// Copia i parametri in options.param per la richiesta
for(var p in params){
data[p] = params[p];
}
// Wrappa l'elemento
if (!$item.parent().hasClass("absolute-container")){
$item.wrap('<div class="absolute-container"></div>');
}
// Se non c'e' l'elemento nel DOM...
if (!$item.$autocompleteList){
var $autocompleteList = $('<ul class="autocomplete-list"></ul>');
// Definiamo la nostra funzione per cancellare la lista (invece di usare empty)
// siccome teniamo traccia dell'elemento selezionato al momento tramite tastiera KEY_UP|KEY_DOWN
$autocompleteList.clear = function(){
this.empty();
this.currentItemIndex = null;
};
// inserisci la lista (e linkala all'oggetto jquery padre)
$item.after($autocompleteList);
$item.$autocompleteList = $autocompleteList;
$item.$autocompleteList.clear(); // inizializza
}
// non inviare le richieste subito
var timeoutHandle = 0;
$item.lastSearchedTerm = "";
$item.keyup(function(event){
if (event.which == 13){
// Premuto il tasto invio
var $selected = $item.$autocompleteList.children(".hover");
if ($selected.length > 0){
$item.val($selected.html());
$item.$autocompleteList.clear();
}
}else{
if ($item.val() != ""){
clearTimeout(timeoutHandle);
timeoutHandle = setTimeout(function(){
var newTerm = $item.val();
// Non mandare se l'utente non ha cambiato il termine di ricerca
if ($item.lastSearchedTerm != newTerm){
data["term"] = newTerm;
$.ajax({
type: "POST",
url: datasource,
data: data,
timeout: timeout,
success: function(data){
if (data.success){
$item.lastSearchedTerm = newTerm;
$item.$autocompleteList.clear();
for (var i in data.results){
$suggestion = $("<li>" + data.results + "</li>");
$item.$autocompleteList.prepend($suggestion);
// On click
$suggestion.click(function(){
$item.val($(this).html());
$item.$autocompleteList.clear();
});
}
}
},
dataType: 'json'
});
}
}, delay);
}else{
$item.$autocompleteList.clear();
}
}
});
// Gestione dell'input da tastiera. Gestisce se l'utente preme la freccia giu/su e ESC
$item.keydown(function(event){
var KEY_UP = 38;
var KEY_DOWN = 40;
var KEY_ESC = 27;
if (event.which == KEY_UP || event.which == KEY_DOWN){
// Andiamo su di uno o giu di uno?
var delta = null;
if (event.which == KEY_DOWN) delta = 1;
else if (event.which == KEY_UP) delta = -1;
var itemsCount = $item.$autocompleteList.children().length;
// Primo evento? (Non abbiamo ancora selezionato un elemento tramite tastiera)
if ($item.$autocompleteList.currentItemIndex == null){
$item.$autocompleteList.currentItemIndex = (event.which == KEY_DOWN ? 0 : itemsCount - 1);
delta = 0; // muovi di zero, usa il valore di inizio
}
// Ci sono elementi da selezionare?
if (itemsCount > 0){
// Trova il prossimo
var selectItemIndex = $item.$autocompleteList.currentItemIndex + delta;
if (selectItemIndex > itemsCount - 1) selectItemIndex = 0;
else if (selectItemIndex < 0) selectItemIndex = itemsCount - 1;
// Seleziona il nuovo elemento e tieni traccia del nuovo indice
$item.$autocompleteList.children().removeClass("hover");
$item.$autocompleteList.children(":nth-child(" + (selectItemIndex + 1) + ")").addClass("hover");
$item.$autocompleteList.currentItemIndex = selectItemIndex;
event.preventDefault();
}
}else if (event.which == KEY_ESC){
$item.$autocompleteList.clear();
}
});
}
}
};
|