Live Search med Prototype JS og PHP

Mar 9, 2008

I forbindelse med det sidste nye redesign, har jeg oprettet en "Live search". Nåhhh ja, den er måske ikke så live som en definition vil have det - men det er da en fed feature - og funktionaliteten bag den, vil jeg da gerne dele med jer.

Live SearchDenne post består således af en gennemgang, af de vigtigste punkter i implementeringen, det være sig lidt XHTML, CSS, Javascript samt PHP.

For at benytte koden i denne post kræves det, at du har downloaded og inkluderet Javascript frameworket Prototype JS, samt effektbiblioteket script.aculo.us. Disse skal inkluderes i sidens -sektion, som med et hvert andet Javascript.

XHTML

Jeg har gjort det til god skik, at oprette en "container"-div. Dette div er ikke nødvendig, men her er det taget med for at få bare en smule design med.

Inde i denne container findes et billede, som er stylet til at være skjuldt. Dette er hvad jeg bruger som loading animation - altså en animation der skal vise, at et script arbejder. Input feltet skulle gerne tale for sig selv. Straks herunder er der, i endnu et div, oprettet en ul/li-liste - det er denne vi vil fremvise resultater i. Resultaterne skal ligeledes fremkommet/tilføjes som li-elementer til listen.

<div id="container">
    <img src="loading.gif" id="lsloading" align="right" alt="" style="display:none;"  />
    <input type="text" value="Type and you´ll find..." id="lsquery"  />
    <br  />
    <div id="lsresults" style="display:none;">
        <ul id="lsResList">
            <li><i>Type and you´ll find...</i></li>
        </ul>
    </div>
</div>

CSS

CSS delen af dette script, taler også lidt for sig selv. Det er muligt, at designer kan laves en hel del nemmere (læs: med mind css), men her er indsat hvad du finder i demoen.

Det vigtigste her, vil nok være at påpege, at resultatlisten er sat til absolut positionering. Dvs. vi kan vise den ovenpå andre elementer, hvorfor den ikke skal til at "skubbe" rundt på designet. Du har måske bemærket at resultatlisten er en smule gennemsigtigt - Dette ER en CSS feature, men den bliver udført gennem Javascript-delen.

body {
    font-family: "Trebuchet MS";
    font-size: 1em;
    background: #333;
}
#container {
    background: #fff;
    width: 400px;
    padding: 20px;
    margin: 0 auto;
}
#container #lsloading {
    position: relative;
    top: 5px;
}
#container input {
    font-family: "Trebuchet MS";
    font-size: 1em;
    width: 350px;
    margin-left: 20px;
}
#container #lsresults {
    position: absolute;
    background: #fff;
    color: #333;
    width: 354px;
    margin-left: 20px;
}
#container #lsresults ul {
    list-style: none;
    margin: 0px;
    padding: 0px;
}
#container #lsresults ul li {
    list-style: none;
    margin: 10px;
    padding: 0px;
}

Javascript

Javascriptet er den største del af denne "applikation". JS-delen består af et Live Search objekt (ls) med metoderne init(), search(), showResults() og hideResults(). Derudover bliver der, når en side er loaded, initialiseret nogle observer eventhandlers på søgefelter.

Humlen ligger i init() og search() metoderne. init() bliver kaldt hver gang der tastes i søgefeltet, og denne kalder search() som udføre et AJAX-kald til serveren, som levere selve søgningen. For ikke at spamme serveren er der indbygget en timer i init() metoden som gør, at search() metoden kun bliver kaldt hvis der ikke er tastet noget i søgefeltet i 0.5 sekunder.

/**
 * Live search
 */
var ls = {
    queryField: "lsquery", //id name of queru input-field
    results: "lsresults", //id name of result-list
    loading: "lsloading", //id name for loading animation
    timer: null,
/** * Initialize a search: * reset timer, and performe search * if nothing has been typed in 0.5 sec. */ init: function(event) { var query = Event.element(event).value; ls.timer = clearTimeout(ls.timer); if(query != "" || query != "Type and you´ll find...") { ls.timer = setTimeout("ls.search(" query ");", 500); } },
//start a search using AJAX search: function(query) { if(query != "") { $(ls.loading).show(); var done = function(t) { $(ls.loading).hide(); } var url = php-backend.php; var pars = action=search&query= query; new Ajax.Updater(lsResList, url, { method: post, parameters: pars, onSuccess:done, onFailure:done, inserting:Insertion.Before }); } },
//show the result list showResults: function() { if($(ls.results).getStyle(opacity) != 0.9) new Effect.Appear(ls.results, {duration:0.2, from:0.0, to:0.9}); },
//hide the result list hideResults: function() { new Effect.Opacity(ls.results, {duration:0.2, from:0.9, to:0.0}); } }
/** * Initialize key-observers for search input field. */ Event.observe(window, load, function() { $(ls.queryField).observe(keyup, ls.init); $(ls.queryField).observe(keydown, ls.init);
//remove input field value when first focused $(ls.queryField).onfocus = function() { if($(ls.queryField).value == "Type and you´ll find...") $(ls.queryField).value = ""; ls.showResults(); }
//reset input field when not focused and value is "" $(ls.queryField).onblur = function() { if($(ls.queryField).value == "") $(ls.queryField).value = "Type and you´ll find..."; ls.hideResults(); } });

PHP

PHP delen, er hvad jeg ovenfor har kaldt "serveren". Hvordan du vil udføre selve søgningen er mere eller mindre op til dig selv. Vælger du at benytte dette script, skal resultaterne dog returneres som én streng. Hvert resultat skal, for at designet holder stik, leveres som et element.

Bare for at give en ide, leveres scriptet med følgende PHP backend.

<?php
/************************************************************************
 * Here you would probably perform som DB-search.
 * In this example, you will only find a hit, when typing a string that -
 * is in the array $results.
 ************************************************************************/
if($_POST["action"] == "search") :
    $query = utf8_decode(urldecode($_POST["query"]));
    $results = array("","webprogrammering","blog","ajax","javascript","php","css");
    $key = array_search($query, $results);
    if($key) :
        echo "<li><a href="#">"".utf8_encode($results[$key])."" found with key: ".$key."</a></li>";
    else :
        echo "<li><i>Intet resultat</i></li>";
    endif;
endif;
?>

Som beskrevet i kommentaren, vil man selvfølgelig lave en reel database søgning eller lignende, hvilket lige nøjagtig er hvad jeg gør her på sitet.Sååå - uden yderligere forklaringer skal du være velkommen til at downloade, modificere osv. følgende version af Live Search. Skulle der opstå problemer, eller mangler du yderligere forklaring, skal du endelig kommentere nedenfor.

Comments

comments powered by Disqus