sobota 24. března 2012

Našeptávač pomocí jQuery a Grails

Jak udělat podobnou funkcionalitu našeptávače, jako má Google při vyhledávání, že vám zobrazí ty podobné výrazy? Zrovna včera jsem něco takového udělal.
Šlo o to, že při zadávání část rodného čísla server automaticky vyhledá ty RČ, která obsahují zadávaná čísla a vloží je za uživatele do textboxu. Pro zhotovení jsem použil jQuery UI Autocomplete: http://jqueryui.com/demos/autocomplete/ a serverová část je naprogramovaná v Grails 2.0.1.

Serverová část:
Tato část zahrnuje přijímání parametru z requestu, vyhledávání dle RČ a generování JSON.

První je potřeba udělat vyhledávání pacienta (aplikace je pro zdravotnictví) podle RČ:

List patientList = Patient.createCriteria().list() {
ilike('RC', "%${params.RC}%")
}

Protože je RC uložena jako text, lze vyhledávat pomocí LIKE v SQL.

Tento výsledek pak připravíme pro generování JSON:

def resultList = [] // výsledný list
patientList.each {patient ->
def patientMap = [:] // add to map. jQuery autocomplete expects the JSON object to be with id/label/value.
patientMap.put("id", patient.id)
patientMap.put("label", patient.fullName) // to, co se zobrazí v našeptávači
patientMap.put("value", patient.RC) // to, co se vyplní do vyhledávaného pole
patientMap.put("rc", patient.RC)
patientMap.put("firstName", patient.firstName)
patientMap.put("lastName", patient.lastName)
patientMap.put("insuranceCompany.acronym", patient?.insuranceCompany?.acronym)
resultList.add(patientMap) // add to the arraylist
}
render patientList as JSON // generování JSON v Grails

Jak vidíme, lze zobrazit uživateli něco jiného, než co se vloží pak po vyhledání - zde uživateli zobrazím při zadání části RČ možného pacienta se stejným RČ, ale vložím zase RČ do pole pro RČ.

Klientská část:
Prvně je nutné získat RČ z textboxu - pomocí jQuery:

var rc = $('#patient\\.RC').val(); // za předpokladu, že id textboxu je "patient.RC"

Pak je potřeba vytvořit autocomplete plugin:

$("#patient\\.RC").autocomplete({
delay:500,
minLength:3,
source:contextPath + "/patient/autocompletePatient?rc=" + rc,
select:function (event, ui) { // event handler when user selects a company from the list.
$("#patient\\.id").val(ui.item.id);
$("#patient\\.RC").val(ui.item.rc);
$("#patient\\.firstName").val(ui.item.firstName);
$("#patient\\.lastName").val(ui.item.lastName);
$("#patient\\.insuranceCompany\\.acronym").val(ui.item["insuranceCompany.acronym"]);
}
});

Parametr delay je nastaven na 500 ms, díky tomu server nebude přetěžován dotazy - posílá se až za 500 ms od té doby, kdy klient přestal psát. Minimální délka omezuje vyhledávání až do té chvíle, kdy jsou zadány min. 3 znaky - nevrací se tolik výsledků. Source určuje, kde lze získat zdroj pro zobrazování našeptávač - zde je zdroj vzdálený. Select je event listener, který říká, co se má provést, pokud uživatel klikne na jeden z našeptávaných výrazů - chci, aby se nejen doplnil zbytek RČ, ale také jméno, příjmení a zkratku pojišťovny u daného pacienta.
Pak je nutné, aby se source aktualizoval pokaždé, kdy uživatel něco napíše - lze použít keyup event v jQuery. Celý kód vypadá takto:

$("#patient\\.RC").keyup(function () {
var rc = $('#patient\\.RC').val();
$("#patient\\.RC").autocomplete({
delay:500,
minLength:3,
source:contextPath + "/patient/autocompletePatient?rc=" + rc,
select:function (event, ui) { // event handler when user selects a company from the list.
$("#patient\\.id").val(ui.item.id);
$("#patient\\.RC").val(ui.item.rc);
$("#patient\\.firstName").val(ui.item.firstName);
$("#patient\\.lastName").val(ui.item.lastName); $("#patient\\.insuranceCompany\\.acronym").val(ui.item["insuranceCompany.acronym"]);
}
});
});

Zdroje inspirace:

Žádné komentáře:

Okomentovat