AJAX Autocompleter

Document Sample
scope of work template
							                         Praxis




    AJAX Autocompleter
    Durch das Web 2.0 wurden viele userfreundliche Widgets verfügbar, die
    so vorher nicht denkbar waren. Hierzu zählen vor allem Eingabeformulare,
    die, ohne die Seite neu laden zu müssen, den User informieren, ob seine
    Eingaben korrekt waren, aber auch, um bereits während der Eingabe die
    Daten abzugleichen – hierbei sei auf mootools secure form [2] verwiesen.
                                                                                                                                                          .
                                                                                                             Selektiert alle Elemente der Klasse ‚fooclass’
    In diesem Artikel erfahren Sie...                     Was Sie vorher wissen sollten...                   Gibt ein Array aller Elemente mit der entspre-
    • Wie man mit dem Mootools Framework und              • Erfahrung mit PHP / Javascript,(X) HTML, CSS     chenden Klasse zurück. Beachten Sie den dop-
      PHP ein Eingabefeld generiert, das während            und dem DOM ( Document Object Model )            pelten Selektor ( $$ ).
      des Tippens bereits Vorschläge, die zu seiner
      Eingabe passen, macht.                                                                                                            ,
                                                                                                             $('foo').addEvent('eventTyp' function(){
                                                                                                             …do something here…
                                                                                                             })
                                                          Tools realisieren lassen, welche ohne dies nur
                                                          sehr zeitaufwändig zu realisieren wären.           Weist dem Element foo einen Eventhand-
    Schwierigkeitsgrad:                                      Äußert praxisnah ist auch die Möglichkeit,      ler zu, der von den Standard Javascript Event-
                                                          nur Teile des Frameworks in eine JS Datei          handlern abgeleitet wird. Dabei entfällt je-
                                                          einzubinden. So sind alle Klassen des Frame-       doch das on im Eventnamen. Beispiel: onclick
                                                          works nach Anwendungsbereich getrennt; es          wird zu click. Innerhalb der Funktion des neu-


    S
            o fällt auch der AutoCompleter in die Ka-     ist schließlich möglich, dass der Programmierer    en Eventhandlers werden dann die Anweisun-
            tegorie brauchbarer und nützlicher Tools,     nur die XMLHttpRequest Funktionen benö-            gen abgearbeitet.
            die eine Website zur Interaktion mit dem      tigt, die nebenher erwähnt, auch noch Cross-          HINT: Manche Elemente, wie z.B. Links (<a
    User bereit stellen kann, abhängig vom Einsatzge-     Browser kompatibel sind, aber keine Effekte        href …), denen ein Event-Handler zugewiesen
    biet; so ist der AutoCompleter sicherlich sinnvoll    einbinden möchte. Mootools ermöglicht dies         wird, führen Ihren normalen Event trotz des
    bei Datenbeständen, die recht groß und somit          bereits beim Download. Weiterhin ist der Sour-     Überschreibens aus. Ein Klick auf einen Link
    meist nur schwer übersichtlich darstellbar sind       ce Code in verschiedenen Komprimierungsstu-        wird also trotzdem, dass er einen neuen Click-
    – wie z.B eine Produktsuche in einem Online           fen erhältlich – bis hin zum unkomprimierten       Handler erhält, auf den URL weiterleiten, der im
    Shop. Aber auch ein Intranet mit einer Mitarbei-      Source Code für Neugierige.                        href Attribut angegeben ist. Um dies zu vermei-
    ter- oder Email Suche ist so einfach zu realisieren      Sehr komfortabel sind hierbei die Selektoren    den, muss der Original-Event gestoppt werden:
    und profitiert von der Einfachheit des Systems.       für Elemente, Klassen und ID’s, die im DOM
       Zu erwähnen sei an dieser Stelle aber auch,        des Dokuments existieren – aber auch neue                                  ,function(el){
                                                                                                             $('foo').addEvent('click'
    dass eine Alternativlösung für User, die Java-        Elemente sind sehr schnell erstellt, gestylt und        new Event(el).stop();      - stoppt den
    script deaktiviert haben, zur Verfügung gestellt      an entsprechender Stelle ins Dokument einge-               Original Event
    werden sollte. Denn abseits des Hypes um Web          fügt. Zum besseren Verständnis der Selektoren           alert(“Hello”);
    2.0 und AJAX gibt es immer noch genug User,           und Effekte folgt hier nun ein kleines Tutorial:   })
    die eher auf Sicherheit bedacht sind, und akti-
    ve Inhalte in Ihrem Browser nicht zulassen; das       MooTorial – eine kurze                                                     ,
                                                                                                             $('foo').effect('opacity'    { duration:
    gleiche gilt für Firmen, die über einen Proxy         Einführung                                              500, wait:true, transition:
    ins Web gehen – auch hier sind meistens zum           Jeder, der bereits mit Javascript gearbeitet            Fx.Transitions.linear }).start(1,0.8);
    Schutze des Netzwerks aktive Inhalte verboten         hat, weiß, wie mühselig das Selektieren mit
    und deaktiviert.                                                                   )
                                                          document.getElementById(‚' sein kann. Dies         Beispiel eines Effekts. Hier wird durch
                                                          geht hier wesentlich leichter von der Hand.                         )
                                                                                                             effect( opacity' für das Element foo angege-
                                                                                                                   '
    Mootools [1] – das kompakte                           Shortcuts                                          ben, dass ein Transparenzeffekt erzielt wer-
    Framework                                                                                                den soll. In der geschweiften Klammer stehen
    Mootools ist ein modulares, kompaktes Fra-            $('foo')                                           dann die Optionen, wie der Effekt vonstatten
    mework, das dem Programmierer – wie der                                                                  gehen soll:
    Name schon sagt – optimale Rahmenbedin-               Selektiert ein Element mit der ID 'foo'
    gungen und ein in sich logisches Werkzeug an                                                             •    duration: 500    – Gibt die Millisekunden
    die Hand gibt, mit dem sich viele Effekte und         $$('fooclass')
                                                             .                                                    an, wie lang der Effekt dauern soll;


1                                                                                                                                                     3/2008
                                                                                                                           AJAX Autocompleter



•    transition:– Gibt die Art des Effekts             ner. Dieser soll bei einem keyup, also wenn der    Grund hierfür ist, daß man nicht während des
  an. Alle Effektarten unter [5];                      User seinen Finger von der Tastatur löst, die      Tippens für jeden zustäzlichen Buchstaben
• wait – Gibt an, ob ein vorhergehender Ef-            bis dato getätigten Eingaben weiterleiten.         eine neue Anfrage an die Datenbank sendet
  fekt erst beendet werden soll.                                                                          – was irgendwann zu Performanceproblemen
                                                       Event-Listener                                     führen könnte, je nach mySQL Abfrage-Metho-
Danach kommt der Aufruf start mit den Pa-                 Hier nun die Schritte, einzeln erklärt. Zu-     de und/oder vielen Usern gleichzeitig. Es wird
rametern 1 und 0.8 – dies bedeutet von nicht           erst wird die aktuelle Zeit in einen Timestamp     also ermittelt, ob der letzte Buchstabe vor we-
transparent (wie das Element beim initial sta-         umgerechnet, der als Ausgangspunkt für den         niger als 25 Millisekunden eingegeben wurde.
te wohl auch ist) zu 0.8, also leicht durchsich-       nächsten Tastenanschlag gilt, und in der Va-          Welchen Wert man hierfür am besten ein-
tig. Hier kann natürlich jeder andere Wert bis         riable >>timestamp<< gespeichert. Durch das        stellt, sei jedem selbst überlassen, jedoch hat
0.0 (komplett transparent) eingesetzt werden.          fehlende var vor der Variable, ist diese global    sich ein Wert zwischen 25 und 200 Millise-
                                                       verfügbar, und somit auch beim nächsten Auf-       kunden bewährt.
First approach                                         ruf – sprich Tastendruck – mit einem Wert be-         Wenn diese Bedingung erfüllt ist, wird
Was also benötigen wir alles, um diesen Auto-          legt. Siehe Listing 1.                             mit der nächsten Zeile der XMLHTTPRe-
completer zum Leben zu erwecken? Nun, da                  Die Zeile $('inp').addEvent... ist der ei-      quest ( AJAX request ) ausgeführt. Die Zeile
wäre zum einen natürlich das Eingabefeld in            gentliche Event-Listener. Dieser achtet nun auf    besagt, es soll ein neuer Request an die Datei
einer HTML Datei, auf dem der Autcompleter             die Eingabe, die im Textfeld getätigt wird. Dies   retriever.php gestellt werden, mittels der
funktionieren soll:                                    geschieht bei jedem Loslassen der gedrückten       GET Methode, wobei als Variablenname inp
                                                       Taste, solang der Focus auf dem Eingabeele-        übergeben werden soll. Der Inhalt dieser Va-
<form action=”” method=”post” enctype=”text/           ment ist.                                          riable ist der Wert der Variable p, die den ge-
    plain” id=”form1”>                                    Da man nicht bereits die Abfrage starten        tippten Text enhält. EvalScripts: true bedeu-
<input name=”inp” type=”text” id=”inp”                 möchte, wenn sich nur ein Zeichen im Feld          tet, daß Javascripts, die sich in der Zieldatei
    style=”width:200px;” />                            befindet, wird nun die Länge des eingegebenen      (retriever.php) befinden, ausgeführt werden
<input type=”submit” value=”ok” /></form>              Textes ermittelt – dies geschieht über die Zeile   sollen.
                                                       len= p.length. Vorher muß man das Objekt              request(); löst dann die Funktion aus.
Damit hätten wir unsere Form definiert. Der-           natürlich noch referenzieren – dies geschieht      Schlußendlich übergibt man der globalen Va-
zeit ist die Form Action noch leer – hier käme         mittels des Codestücks var p=$(’inp’).value        riable timestamp den Wert der zuletzt ausgele-
der Aufruf zur normalen Suche hinein, sofern           – damit wird der Inhalt des Textfelds ausgele-     senen Zeit, die in lasttimestamp gespeichert ist,
kein Javascript aktiviert ist...                       sen.                                               um einen neuen Startpunkt zu erhalten.
   Weiterhin benötigt man die enstprechenden              Ist die Länge des Strings nun größer als 3,
Scripte, um die Funktionalität zu erhalten, die        also mehr als 3 Buchstaben getippt, wird nun       Der XMLHttpRequest &
Grundvoraussetzung für dieses Script ist. Da-          ermittelt, ob sich ein Leerzeichen im Text be-     die mySQL Abfrage
zu bindet man im <HEAD></HEAD> Bereich die             findet. In diesem Beispiel soll davon ausgegan-    In der Datei >>retriever.php<<, die als Emp-
folgenden Zeilen ein (natürlich ist auf die rich-      gen werden, nur einzelne Wörter finden zu          fänger der übermittelten Daten fungiert, pas-
tige Pfadangabe zu achten):                            können. ( z.B. Staatsnamen etc ).                  sieren nun all die Aufrufe, die den Autocom-
                                                          Daher wird nun der Wert, der in der Va-         pleter ausmachen.
<script language=”javascript” type=”text/              riable p gespeichert ist, auf ein Leerzeichen         Zunächst wird erst einmal eine dauerhafte
    javascript src=”js/ajax.js></script>               geprüft – dies geschieht mittels der Zeile:        Verbindung zur Datenbank hergestellt und die
                                                       if(p.indexOf(“ “) == -1) – Sofern dies nicht       entsprechende Tabelle, die abgefragt werden
Um nun die Eingaben, die ein User in der               der Fall ist, wird als nächstes nun die aktuelle   soll, ausgewählt:
Text-Form eingibt, abzufangen und diese an             Zeit in einen Timestamp konvertiert.
das Script zur Auswertung weiter zu leiten,               Dieser Timestamp dient zur Berechnung,          mysql_pconnect(“HOST”,”USER”,”PASSWORD”)
benötigt man nun noch einen Event-Liste-               wie lange die letzte Eingabe zurückliegt. Der         or die(“Unable to connect to the
                                                                                                             database”);

    Listing 1. EventListener                                                                              mysql_select_db(“wordlist”) or die
                                                                                                             (“Unable to select table”);
    timestamp = Date.parse(new Date());
                                                                                                          Wenn alles korrekt eingetragen wurde, steht
    $(‘inp’).addEvent(‘keyup’,function(){                                                                 somit die Verbindung zur Datenbank. Es bie-
         var p = $(‘inp’).value;                                                                          tet sich an, eine persistente Verbindung zur
         len = p.length;                                                                                  Datenbank zu öffnen. Nun legt man ein neu-
         if(len > 3){                                                                                     es, leeres Array an, in dem später die gefunde-
             if(p.indexOf(“ “) == -1){                                                                    nen Einträge der Datenbank gespeichert wer-
                 var lasttimestamp = Date.parse(new Date());                                              den. Dann holt man den Wert der übergebe-
                 if(lasttimestamp - timestamp > 25){                                                      nen Variable, und fragt die Datenbank ab. Sie-
                 new Ajax(‘retriever.php?inp=’+p,{ method:’get’,data:this, evalScripts:true               he Listing 2.
                                 }).request();                                                               Was genau hier passiert: Zuerst wird ein Ar-
                 timestamp = lasttimestamp;                                                               ray mit $arr erstellt; dieses ist zu Beginn leer.
                 return false;                                                                            Danach werden per $inp = strip_tags($_
                 }                                                                                        GET[‘inp’]); die Daten eingelesen, $inp ent-
             }                                                                                            hält somit also den Text, den der User in die
         }                                                                                                Textbox getippt hatte.
    })                                                                                                       Nun wird eine Volltextsuche auf die Da-
                                                                                                          tenbank Tabelle initiiert. Wie man eine Voll-


www.phpsolmag.org/de                                                                                                                                          2
                        Praxis


    textsuche realisiert, ist unter [3] zu lesen. Die   wird dieser Wert, der ein Pixelwert (z.B. 12px)                           ,'mycontainer');
                                                                                                              div.setAttribute('id'
    entsprechende mySQL Datei befindet sich             darstellt, in einen Integer gewandelt, damit        – Der darauf folgende Code sehen Sie in Li-
    ebenfalls auf dieser CD. Sie können diese zu        dieser für die Funktion weiter nutzbar ist.         sting 4.
    Testzwecken mit Ihrem mySQL Editor ( myS-           Mit der Zeile top+=30 wird der spätere Con-            Die Variable old enthält den im Hauptdoku-
    QLAdmin, mySQLFront, etc. ) auf Ihrem Sy-           tainer 30 Pixel weiter unterhalb des errech-        ment vorhandenen DIV answer, der benutzt
    stem integrieren.                                   neten Punkts definiert. Dabei bestimmt die-         wird, um den Autocompleter einzublenden.
       Bei der Abfrage holt man sich per SELECT         ser Punkt nicht den Abstand zwischen unte-          Dieser residiert direkt unter dem Eingabe-
    words from words alle Worte, die dem Teil           rem Rand des Textfelds und dem Anfang des           formular. Ohne diesen wäre es etwas kompli-
    der Abfrage WHERE MATCH(words) AGAINST              Autocompleterfelds, sondern rechnet ab dem          zierter, den Container ins Dokument zu in-
    ('$inp*' IN BOOLEAN MODE) entsprechen.              oberen Rand des Textfelds ( da die Top-Eigen-       tegrieren. Als nächstes wird der Container
    Diese Art der Abfrage benötigt man nur bei          schaft abgefragt wurde) 30 Pixel hinzu. Bei         (div) geleert, damit etwaige vorherige Inhalte
    Volltextsuchen – entsprechend langsamere,           entsprechend hohen Eingabefeldern ist somit         gelöscht werden und nicht mit der aktuellen
    mit LIKE Statements, können Sie unter [4]           dieser Wert anzupassen.                             Abfrage kollidieren.
    nachlesen.                                             Die nächste Zeile ermittelt, ob ein Element         Die else Anweisung bezieht sich wiederum
       Hat mySQL nun Datensätze gefunden,               mit der ID mycontainer existiert – ist dies         auf unsere vorher im Dokument ausgeführte
    werden diese in der folgenden Schleife ausge-       nicht der Fall, greifen die nächsten Zeilen, die    Abfrage, ob denn ein Container existiert – dies
    lesen. Die Schleife bedeutet im Klartext: So-       den entsprechenden Container generieren.            war nicht der Fall in diesem Beispiel. Existiert
    lange Werte vorhanden sind, laufe durch diese          Diese Abfrage ist deswegen wichtig, da, ge-      er jedoch, wird einfach die Variable div darauf
    durch. Innerhalb der Schleife kommt nun un-         setzt dem Fall, daß eine solche Abfrage nicht       verweisen.
    ser Array zum Einsatz. Jeder gefundene Wert         existiert, bei jeder Anfrage an das Script erneut
    wird in das Array geschrieben; dies geschieht       ein Container erstellt werden würde – was zu        Der Content Container
    mittels array_push().                               einem sogenannten Flicker Effekt, also dem          Innerhalb des Containers wird nun ein
       Damit ist der erste Teil des PHP Scripts erle-   Aufblitzen und Verschwinden des Autocom-            Image eingeblendet, dass es ermöglicht,
    digt – die Daten sind vorhanden, und es geht        pleter-Containers führt.                            das Fenster wieder zu schließen – denn es
    nun daran, diese in entsprechende Form zu              Da beim ersten Aufruf kein Container vor-        kann ja vorkommen, daß man keinen Tref-
    bringen – in einem Stück Javascript.                handen ist, wird dieser nun mit der Funktion        fer erzielt, und der Container somit unnütz
       Zuerst muß nun der Container, der später         div = new Element(... erstellt. Den Code            wird. Diesem Image gibt man einige CSS In-
    unter der Eingabebox für den Text erscheint,        finden Sie in Listing 3.                            line-Styles mit, um es genau positionieren
    erstellt werden. Dies kann man auf zwei Wei-           Dabei wird angegeben, dass die Variable div      zu können. Der OnClick Handler des Bildes
    sen erreichen; hier wird die händische Vorge-       der neue Container sein wird. Dies wird mit         beinhaltet den Code, um den Container zu
    hensweise gezeigt:                                  new Element(‘typeof’,{ options } }) er-             entfernen.
                                                        ledigt. Da der Container ein bestimmtes Aus-           Nun kommt der eigentliche Teil, der die ge-
    <script language=”javascript”                       sehen und Größe benötigt, wird dies in den          fundenen Wörter in den Container schreibt.
       type=”text/ecmascript”>                          Optionen per styles angegeben.                      Durch div.innerHTML ist es möglich, den
                                                           Hier im Beispiel hat der Container eine          Container mit Inhalt zu füllen. Dabei wird im
    var top = $('inp').getCoordinates();                Höhe von 300px sowie eine Breite, die dem           Javascript PHP ausgeführt, was es ermöglicht,
    top = top['top'].toInt();                           des Textelements ( 200px ) entspricht. Die          das vorher erstellte Array nun auszugeben.
    top += 30;                                          Overflow Eigentschaft des Containers soll              Dazu wird erst einmal per count die Anzahl
                                                        verhindern, daß, sofern sich mehr Werte als in      an gefundenen Wortern eruiert. Nun wird die
    if(document.getElementById(‘mycontainer’)           der Liste darstellbar sind, dieser einfach abge-    Länge der Eingabe des Users berechnet – wozu
       == null){                                        schnitten wird – dies würde passieren, da der       sehen Sie gleich. Jetzt wird per $x = $arr[$i]
                                                        Container eine feste Höhe hat. Anders herum         das aktuell in der Schleife stehende Wort nach
    Hier wird nun zuerst einmal die Posi-               würde ein Container ohne feste Höhe bei sehr        $x geholt; den echten Array-Wert hingegen
    tion des Textfeldes ermittelt. Dies ist wich-       vielen Suchbegriffen lang werden, was sich in       schneidet man mit substr($arr[$i],$len) so
    tig, da der Autocompleter direkt darunter ge-       seitenlangem Scrollen niederschlagen und das        ab, dass die Länge des Werts dem der Userein-
    setzt werden soll. Das geschieht mit den Zei-       ganze System somit viel von seiner Userfreund-      gabe entspricht.
    len 1 bis 3. Die Mootools-eigene Funktion           lichkeit verlieren würde.
    getCoordinates(); holt sich die genauen Po-            Nachdem der Container erstellt wurde, wird         Listing 3. Container Element erstellen
    sitionen ( oben, links, Breite und Höhe ). Mit      diesem noch eine ID mitgegeben, um beim
    top[‘top’].toInt(); erhält man also die Po-         erneuten Aufruf prüfen zu können, ob dieser           div = new Element(‘div’,{
    sition, welches das Textelement vom oberen          bereits existiert oder nicht. Dies geschieht mit           ‘styles’: {
    Bildschirmrand her einnimmt. Mit toInt();           folgender Anweisung:                                               ‘width’:’200px’,
                                                                                                                           ‘height’:’300px’,

      Listing 2. Datenbank-Verbindung und Volltextsuche                                                                    ‘padding’:’5px’,
                                                                                                                           ‘background-color’:’#000’,
      $arr = array();                                                                                                      ‘color’:’#FFF’,
      $inp = strip_tags($_GET[‘inp’]);                                                                                     ‘margin-top’:’20px’,
      $res = mysql_query(“SELECT words FROM words WHERE MATCH(words) AGAINST(‘*$inp*’ IN                                   ‘visibility’:’hidden’,
                                BOOLEAN MODE) “) or die(mysql_error());                                                    ‘position’:’absolute’,
                                                                                                                           ‘border’:’1px solid #FFF’,
      while($row = mysql_fetch_row($res)){                                                                                 ‘top’:top,
          array_push($arr,$row[0]);                                                                                        ‘overflow’,’auto’}
      }                                                                                                       })




3                                                                                                                                                      3/2008
                                                                                                                         AJAX Autocompleter



  Die Idee dahinter ist simpel – die Ausgabe          blenden, und nicht einfach brutal in das Do-          Dieses Bild dient einfach dazu, dem User zu
im Container soll eingefärbt werden – und             kument setzen möchte – wobei das natürlich         zeigen, dass eine Operation im Gange ist (auch
zwar nur der Teil des gefundenen Wortes, den          Geschmackssache ist.                               wenn diese genau genommen eigentlich schon
der User eingegeben hat. So wird z.B. bei einer         Mootools bietet zu diesem Zweck eine gut         durchgeführt wurde; die Suchfunktion in die-
Eingabe von Webd das gefundene Wort Web-              ausgestattete Effekt-Bibliothek, mit der es sehr   sem Beispiel ist so schnell, daß es keinen Sinn
design angezeigt. Die Ausgabe erfolgt somit           einfach ist, den gewünschten Einblendeffekt        machen würde, den Container samt Bild zu-
mit einem simplen Echo und einem CSS Span-            zu erreichen.                                      erst anzeigen zu lassen).
Style, der eben diesen Teil einfärbt.                                                                       Der Effekt ist auch schnell hergestellt – da-
  Dem Titelattribut jedes Links wird das ge-          Container Effekt                                   zu sei angemerkt, daß ein Transparenz-Effekt
fundene Wort zugeordnet – dies ist, wie später        Bevor man den Container sichtbar macht, weist      den CSS Stil visiblity:hidden außer Kraft
zu sehen ist, sehr wichtig.                           man ihm eine weitere CSS Klasse zu – wait.         setzt. Mit div.effect wird der Effekt einge-
  Sobald die Schleife durchlaufen ist, wird per       Diese Klasse enthält nichts, außer einem trans-    leitet, die Optionen stehen dahinter, in die-
div.injectInside(old); der gesamte Container in       parenten, animiertem Hintergrund-GIF, das mit      sem Fall die Dauer von 100 Millisekunden.
den DIV des Hauptdokuments eingeblendet.              der background-position center – center ab-        Warten auf das Ende einer vorherigen Opera-
Da jedoch – wie sie im Erstellungscode des Ele-       solut zentriert wird. Weiterhin wird die Wieder-   tion wird verneint, und der Effekt selbst soll
ments div sehen können, ein display:hidden            holung des Hintergrundbilds mit background-        ein linearer Verlauf sein ( weitere Effekttypen
enthält, wird dieser nicht angezeigt. Das rührt       repeat:no-repeat abgeschalten, da es sich sonst    siehe [5] ).
daher, dass man den Container ja sanft ein-           im ganzen Container wiederholen würde.                Durch den .set() Befehl wird der Effekt
                                                                                                         unverzüglich durchgeführt. Eine weitere Me-
                                                                                                         thode wäre der Befehl .start(0,1) wobei von
  Im Internet                                                                                            opaque auf transparent im eingestellten Zeit-
  •    [1] http://www.mootools.net;                                                                      raum gefadet werden würde. Da dies jedoch
  •    [2] http://www.artviper.eu/mootoolssecureform;                                                    eine längere Zeitspanne als die vorgegebenen
  •    [3] http://dev.mysql.com/doc/refman/5.0/en/fulltext-boolean.html;                                 100ms dauern würde, um einen ansehnlichen
  •    [4] http://dev.mysql.com/doc/refman/5.0/en/pattern-matching.html;                                 Effekt zu erzielen, wird die set() Methode
  •    [5] http://docs.mootools.net/Effects/Fx-Transitions.js.
                                                                                                         hier vorgezogen.
                                                                                                            Somit wird also der Container in der Haut-
                                                                                                         pseite unterhalb des Eingabefelds angezeigt.
  Listing 4. Übertragen der Ergebnisse in den Container                                                  Doch wie kommt nun das Wort, welches der
                                                                                                         User auswählt, in das Eingabefeld? Dazu be-
       var old = $(‘answer’);                                                                            nötigt man eine weitere Funktion, die dies aus-
       div.innerHTML = ‘’;                                                                               führt. Siehe Listing 5.
  }else{                                                                                                    Wie bereits im Überblick dieses Artikels be-
       div = $(‘mycontainer’);                                                                           schrieben, verfügt Mootools über den Selektor
  }                                                                                                      $$, der ein Array aller zur Abfrage gehörenden
  div.innerHTML = ‘<img src=”closer.jpg” style=”margin-bottom:10px;clear:both;float:                     Elemente zurückgibt. Dieser findet hier nun
                              right” onclick=”div.remove()”/>                                            Verwendung.
  <?php                                                                                                     Es wird durch den Einsatz dieses Selektors
       for($i=0;$i<count($arr);$i++){                                                                    jedem Element, das gefunden wird (in die-
           $len = strlen($inp);                                                                          sem Fall eben alle Links in unserem Container
           $x = $arr[$i];                                                                                mycontainer) ein neuer Eventhandler mitge-
           $arr[$i] = substr($arr[$i],$len);                                                             geben – der Click-Event. Anders als beim üb-
           $p = “<span style=\”font-weight:bold;color:#FFF\”>$inp</span>$arr[$i]”;                       lichen Javascript heißt dieser tatsächlich nur
           echo “<a href=\”javascript:void(0)\” title=\”$x\”>$p</a><br/>”; }                             click und nicht onclick.
  ?>’;                                                                                                      Da der eigentliche Event eines Klicks auf
          div.injectInside(old);                                                                         einen Link grundsätzlich durchgeführt wer-
          div.addClass(‘wait’);                                                                          den, also auf das Ziel im href Attribut sprin-
          div.effect(‘opacity’,{ duration: 100, wait:false, transition:                                  gen würde, ist es notwendig diesen Event ab-
                              Fx.Transitions.linear   }).set(0.8);                                       zubrechen. Dies erreicht man mit der Zeile
                                                                                                         e=new Event(e).stop(); Wie zu sehen ist,
  Listing 5. EventListener für Links im Container                                                        beinhaltet die gesamte Funktion den Para-
                                                                                                         meter e, mit dem auf den Event zugegriffen
  $$(‘#mycontainer a’).addEvent(‘click’,function(e){                                                     werden kann.
             e = new Event(e).stop();                                                                       Bei einem Klick des Users auf einen der Wor-
              var x = this.getAttribute(‘title’);                                                        te im Ergebniscontainer holt sich die Funktion
              $(‘inp’).value = x;                                                                        nun den Inhalt des Titelattributs des Links, der
              $(‘mycontainer’).effect(‘opacity’,{ duration: 500, wait:true, transition:                  im Container das ausgesuchte Wort enthält
                              Fx.Transitions.linear }).chain(function(){                                 – deswegen die vorherige Information, daß
              $(‘mycontainer’).removeClass(‘wait’);                                                      das Titelattribut noch eine gewichtige Rolle
              $(‘mycontainer’).setStyle(‘visibility’,’hidden’);                                          spielen wird.
              }).start(1,0);                                                                                Der Inhalt des Attributs wird per $(‘inp’)
              return false;                                                                              ( wobei inp die ID des Textfeldes ist ) die-
  })                                                                                                     sem übergeben, so dass das gewählte Wort im
                                                                                                         Textfeld erscheint. Man könnte nun, nach der


www.phpsolmag.org/de                                                                                                                                        4
                          Praxis


    Auswahl, den Submit Event sofort auslösen,
    damit das ausgewählte Wort automatisch ge-
    sucht wird – dies findet hier allerdings keine
    Anwendung.
      Da das gewünschte Wort ausgewählt wur-
    de, kann der Container nun ausgeblendet,
    und die CSS Klasse wait enfernt werden.
    Dies erreicht man wiederum mit einem Ef-
    fekt der Mootools Klassen. Da jedoch meh-
    rere Effekte bzw. Funktionen hintereinan-
    der ausführt werden sollen, diese jedoch erst
    nach dem Haupteffekt aktiv werden dürfen,
    wird hier die Funktion chain() verwendet,
    die die Effekte in eine Reihe stellt. Zu beach-
    ten ist hierbei, daß die Effekte, die inner-
    halb von chain() stehen, erst am Ende des
    Haupteffekts (hier der Transparenzeffekt
    von opak hin zur Volltransparenz) ausge-
    führt werden.
      Innerhalb der chain() Funktion entfernt
    man sowohl das Hintergrundbild mit dem
    Aufruf .removeClass(‘wait’) – hierbei muß
    das CSS Klassenelement angegeben werden,
    welches entfernt werden soll, da ein HTML
    Element ja bekanntlich mehrere Klassen ver-
    erbt bekommen kann.
      Danach wird der Container auf visibility:
    hidden gesetzt; jedoch erst, nachdem der Trans-
    parenzeffekt beendet ist. Dies wird dann als


                                                             reklama
    sanftes Ausblenden wahrgenommen.

    Fazit
    Wie man sieht, ist so ein Autocompleter recht
    schnell und einfach zu programmieren – der
    erhöhte Nutzen rechtfertigt den Aufwand je-
    denfalls allemal, noch dazu, daß User, die Ihre
    Seite besuchen, einen solchen Komfort sicher
    zu schätzen wissen.
       Natürlich ist es möglich, diesem Autocom-
    pleter noch weitere Funktionen mitzugeben,
    doch für den Anfang, und um einen Einstieg in
    die Integration von AJAX und PHP zu finden,
    ist dieses Script ideal.

    FRANK HERGET
    Autor: Frank Herget (artViper designstudio), geb.
    1976, C++ Programmierer, seit 1995 spezialisiert
    auf Web- und Grafikdesign, besonderes Augen-
    merk liegt seit Beginn des Internets bei den techni-
    schen Neuheiten, die das World Wide Web täglich
    mit sich bringt.
    Als Geschäftsführer und Leiter des IT Developments
    von artViper designstudio, agiert er ebenfalls als IT-
    und Webberater eines deutschen Großkonzerns.
    Schwerpunkte in seinem Leistungsspektrum lie-
    gen bei der Realisierung komplexer, kundenspezifi-
    scher Weblösungen auf Basis von PHP, MySQL, XHT-
    ML CSS und AJAX. Zahlreiche freie Tools, wie z.B. ei-
    ner der größten Thumbnail Services, der täglich
    mehr als 7 GB an Bilddaten an verschiedenste Do-
    mains überträgt, tagCloud.de – der automatische
    tagCloud Service, sowie weitere auf mootools ba-
    sierende Widgets findet man auf dessen Homepa-
    ge www.artViper.net.


5                                                                      3/2008

						
Related docs