Zeilen-Duplizierer mit AutoComplete Felder nutzen
ich bekam heute in einem Kommentar die Frage gestellt, ob mein Zeilen-Duplizierer aus dem Beitrag: Einfacher Zeilen-Duplizierer mit Prototype auch auf Feldern funktioniert, die die Scriptaculous Ajax.AutoCompleter Funktion verwenden.
Ich nutze den Duplizierer selbst in einem Formular, das solche Felder enthält. Meine erste Fassung entsprach dabei dem Einzeiler aus dem vorherigen Beitrag. Das Problem dabei ist allerdings, dass die AutoCompleter Funktion beim Erzeugen mit dem Felder verknüpft wird, auf das sie angewendet werden soll. Wenn man nun dieses Feld kopiert wird nicht eine neue Instanz des Ajax.AutoCompleter erzeugt, sondern die Referenz auf das alte Feld mit kopiert. Ein Eintrag im neu erzeugten Feld aktiviert also die AutoCompleter Funktion des vorherigen Feldes.
Um dieses Problem zu lösen hatte ich die erweiterte Funktion mit den beiden Callback-Funktionen erstellt. Damit ist es möglich die Referenz zum vorherigen Feld zu lösen und eine neue Instanz des Ajax.AutoCompleter nach dem Erzeugen der Kopie zu erstellen. Hier aber zuerst noch einmal die Funktion selbst. Ich habe mittlerweile auch eine Option zum Fokussieren des ersten Feldes in der Kopie hinzugefügt:
function addRow(selector, options){
var lastRow = $$(selector).last();
var newRow = lastRow.cloneNode(true);
if (options.reset) {
newRow.select('select', 'textarea', 'input').each(function(elm){
elm.clear().checked = '';
});
}
if(options.beforeInsert) options.beforeInsert(newRow);
lastRow.insert({'after': newRow});
if(options.afterInsert) options.afterInsert(newRow);
if (options.focusFirst) {
newRow.select('input', 'select', 'textarea').first().focus();
}
}
Um die Ajax.Autocompleter Funktion nutzen zu können benötigt jedes Feld eine eindeutige ID. Nehmen wir also an, wir haben folgendes erstes Feld für unser Formular (hier ein Beispiel aus dem Artikel: Google Maps Suggest – Adress-Autovervollständigung mit Scriptaculous):
<form id="addressform" action="address_save.php" class="niceform">
<fieldset>
<legend>Choose an address</legend>
<dl>
<dt><label for="address">Address:</label></dt>
<dd><input type="text" id="address" name="address[]" style="width: 300px;" /></dd>
</dl>
</fieldset>
<fieldset>
<input type="submit" value="Send!" />
</fieldset>
</form>
<div id="adresse_choices" class="autocomplete"></div>
<script type="text/javascript">
new Ajax.Autocompleter('address', 'adresse_choices', 'get_addresses.php');
</script>
Wichtig sind hierbei natürlich die eckigen Klammern am Ende des Name Attributs, damit auch alle kopierten Werte mitübertragen werden. Damit wir einer Kopie dieses Feldes eine neue Instanz hinzufügen können, müssen wir beim Kopieren auch die ID verändern. Dazu schreiben wir uns eine kleine Callback-Funktion, die genau das erledigt:
function activateAutocomplete(newRow){
var addressInput = $A(newRow.select('input')).first();
addressInput.id += 1;
addressInput.stopObserving();
new Ajax.Autocompleter(addressInput.id, 'adresse_choices', 'get_addresses.php');
}
In der 2. Zeile selektieren wir das erste Element innerhalb der neuen Zeile (wir nehmen hier also an, dass es sich dabei um das AutoCompleter Feld handelt). Diesem fügen wir in der 3. Zeile zusätzlich zur ID eine 1 hinzu. Es entstehen also Felder nach dem Muster "address1", "address11" usw. Das reicht aus um die Felder genau zu referenzieren.
In der 4. Zeile kommt die schon angesprochene Funktion zum Einsatz, die das Autocomplete für das Feld deaktiviert. Zu guter Letzt erzeugen wir eine neue Instanz des Ajax.Autocompleter. Wir können dabei als zweiten Parameter dasselbe DIV Element für die Vorschläge verwenden, da es ja nicht möglich ist, gleichzeitig in zwei Felder etwas einzutippen. Das DIV wird automatisch durch Scriptaculous unter das Feld positioniert, in dem es verwendet wird.
Damit das ganze nun auch dupliziert werden kann, fügen wir noch einen entsprechenden Link ein. Dieser muss dann die Callback-Funktion als zweiten Parameter in der Funktion erhalten. Ich verwende hier ein SPAN Element mit einem onclick Event. Es geht aber auch mit einem gewöhnlichen Link:
<span class="add" onclick="addRow('#addressform dl', {reset : true, afterInsert: activateAutocomplete})">Adresse hinzufügen</span>
Es wird durch den Selektor "#addressform dl" die gesamte Definition inklusive des Label kopiert. Ihr könnt aber auch eine andere HTML Struktur wie z.B. eine unsortierte Liste verwenden.
Das war auch schon alles. Das Beispiel könnt ihr euch hier ansehen und auch den Quellcode dazu runterladen:
Ich hoffe, dass euch die erweiterte Anwendung gefallen hat und vielleicht auf neue Ideen gebracht hat. Wenn ihr eine andere Anwendung kennt, bei der Ihr nicht weiterkommt würde ich mich wie immer über einen Kommentar sehr freuen.
Arrays und andere komplexe Daten mit PHP in einer MySQL-Datenbank speichern
Viele von euch werden wohl schon einmal vor dem Problem gestanden haben, dass sie ein Array oder ein Objekt in der Datenbank speichern mussten. Hier möchte ich ein paar Vorschläge unterbreiten, wie man das Problem nicht lösen sollte und wie es besser gehen kann.
Der schlechte Weg
Die einfachste und gleichzeitig auch schlechteste Methode wäre es, für jeden Index eines Arrays oder jede Eigenschaft eines Objekts eine neue Spalte zu erzeugen. Bei diesem Ansatz werden unter Umständen viele Zeilen erzeugt, die nicht immer einen Wert enthalten. Das ist zwar nicht so gravierend, aber durch diesen Ansatz erhöht sich auch die Anzahl der Spalten schnell auf eine unübersichtliche Anzahl. Zuletzt ist es hierbei bei jeder Änderung des Arrays oder Objekts notwendig die Datenbanktabelle anzupassen.
Google Maps Suggest – Adress-Autovervollständigung mit Scriptaculous
Viele nutzen Autovervollständigungen auf ihrer Website. Es ist nicht nur eine sehr beeindruckende Technik, sondern zudem eine sehr nutzerfreundliche. Zusätzlich kann sie dazu dienen, dass in einem Formular möglichst gültige Werte gespeichert werden. Selbstverständlich müssen alle Daten serverseitig erneut überprüft werden.
Ich möchte heute zeigen, wie einfach es mit Scriptaculous möglich ist, eine Autovervollständigung mit Google-Maps-Adressen umzusetzen. Da man per AJAX nicht auf fremde Website einen AJAX-Request durchführen kann, müssen wir ein Skript als Schnittstelle zwischen Google Maps und unserer Website verwenden. Fangen wir also dieses Mal mit der serverseitigen Script an:









