IT-Academy Logo
Sign Up Login Help
Home - Programmieren - JavaScript - Javascript: Spaltenmenü



Javascript: Spaltenmenü

Ein Artikel der zeigt wie mit Javascript ein zweispaltiges Formularelement erstellt werden kann.


Autor: Patrick Faes (dreamer)
Datum: 11-08-2007, 20:47:46
Referenzen: siehe Text
Schwierigkeit: Fortgeschrittene
Ansichten: 3348x
Rating: Bisher keine Bewertung.

Hinweis:

Für den hier dargestellte Inhalt ist nicht der Betreiber der Plattform, sondern der jeweilige Autor verantwortlich.
Falls Sie Missbrauch vermuten, bitten wir Sie, uns unter missbrauch@it-academy.cc zu kontaktieren.

[Druckansicht] [Als E-Mail senden] [Kommentar verfassen]



1. Einführung

Formularen auf Webseiten gibt es schon seit einer Ewigkeit und machten das Internet zu dem was es heute ist: ein interaktives Medium dessen Möglichkeiten sich von Gästebüchern bis Internetshops und E-Banking ausstrecken.

Formulare erlauben es viele Informationen wie z.B. Text, eine Auswahl oder Dateien an einem Webserver zu senden und bieten daher viele verschiedene Formulartypen an. Jedoch fehlt da leider ein Formulartyp der bei Programmen eigentlich recht beliebt ist: ein Spaltenmenü.

Es handelt sich dabei um ein Menü dass aus zwei einzelne Listen besteht. Man kann dann eine Auswahl in der einen Liste machen und diese auf Knopfdruck der anderen Liste hinzufügen. Ein Beispiel sehen Sie hier:

Achtung Autoren: Beispielcode, bitte nicht ändern!

Achtung Autoren: ab hier kommt wieder der eigentliche Artikel Wie Sie sehen ist es eine praktische Lösung viele Auswahlmöglichkeiten übersichtlich darzustellen. Ebenso ist für den Benutzer sofort erkennbar welche Optionen er ausgewählt hat und welche nicht. Checkboxen, Radio-Buttons und Auswahllisten mit mehrfach-Auswahl sind da weit weniger praktisch.

Dieser Artikel möchte zeigen wie mit einer kleinen Prise Javascript ein derartiges Formular erstellt wird. Zuerst wird die theoretische Wirkung des Codes erklärt und dann erst wird der eigentliche Code analysiert. Abschließend kommt noch ein Abschnitt zur Implementierung des Skripts.


2. Theoretische Ausarbeitung

Da HTML keine eingebaute Unterstützung für ein derartiges Formular-Element bietet, verwenden wir die Elemente die HTML bietet und erweitern die Funktionalität mittels Javascript. Das obige Beispiel besteht dabei aus zwei Auswahlfeldern ( <SELECT> ), vorzugsweise mit oder ohne Mehrfachauswahl. Mittig stehen zwei Buttons womit Listeneinträge aus der linken Spalten der rechten Spalte hinzugefügt werden können (oder umgekehrt). Der ausgewählte Listeneintrag (oder Einträge, je nachdem) wird dann aus der Liste entfernt.

Das Skript muss dabei nachgehen welche Listeneinträge selektiert sind. Javascript bietet leider keine komfortable Methoden wie z.B. einige BASIC-Varianten es haben um einfach die ausgewählte Listeneinträge zu erkennen und zu lüschen. Deshalb müssen wir die Liste jeweils ganz durchlaufen und für jeden Eintrag einzeln überprüfen ob es selektiert ist.

Leider ist es in Javascript nicht möglich um einen selektierten Eintrag sofort zu löschen, dessen Wert zu bekommen und diese an einer anderen Liste hinzuzufügen. Deshalb werden die Daten in zwei unterschiedliche Arrays gespeichert: Eins für die selektierten Einträge und Eins für die anderen Einträge. Nachdem wird die Liste geleert und wieder aufgefüllt mit den Einträgen die nicht selektiert waren. Die selektierte Einträge werden dann die andere Liste hinzugefügt.

Dabei wird aber Eins auffallen: die Einträge stehen nicht mehr in ihrer alphabetischen (oder numerischen) Reihenfolge. Deshalb müssen diese Daten noch sortiert werden, bevor sie der Liste hinzugefügt werden.

Ein anderer Punkt ist dass in Javascript ein Listeneintrag zwei Eigenschaften hat: text und value. Der Text ist der eigentliche, sichtbare Text des Eintrags, während der Value der Wert ist der tatsächlich am Server gesendet wird.

Dabei kommen wir zu unserer letzten (aber sehr wichtigen Frage): wie werden die Ausgewählte Optionen am Server gesendet? Ein Browser sendet jeweils nur die im Formular angedeuteten Werte. Um die Werte aus der rechten Spalte (oder Liste) am Server zu senden, müssten wir alle Werte in der Liste nochmal selektieren. Dabei geht aber der ganze Sinn unseres Vorhabens verloren, nl. ein einfaches Menü zu erstellen.

Die Lösung besteht darin alle Werte aus der rechten Spalte des Menüs an einander zu hängen und diesen Text dann in ein extra Textfeld zu stellen. Dies wird dann am Server geschickt der diese einzelne Werte wieder von einander trennt. Danach steht die Auswahl auf dem Server zur Verfügung.


3. Die Praxis

3.1. Das Formular erstellen

Wie schon gesagt, verfügt HTML nicht über ein derartiges Formular-Element wie wir es jetzt bauen möchten. Wir verwenden einfach zwei verschiedene Formular-Elemente: Buttons und Auswahllisten. (Später kommt noch ein drittes hinzu.)

Wir verwenden dann eine gefüllte Liste und eine leere Liste. Der Code sieht dann so aus:

<select name="linke_spalte" size="8">
	<option value="Wert 1">Text 1</option>
	<option value="Wert 2">Text 2</option>
	<option value="Wert 3">Text 3</option>
	<option value="Wert 4">Text 4</option>
</select>

<select name="rechte_spalte" size="8">
</select>

Die Listen nennen sich hier "linke_spalte" und "rechte_spalte", aber an sich sind deren Namen egal.

Das Skript unterstützt auch Listen mit Mehrfachauswahl. Der Code sieht so aus:

<select name="linke_spalte" size="8" multiple>

XHTML-konform wäre dann aber

<select name="linke_spalte" size="8" multiple="multiple">

Dazu kommen noch zwei Buttons die das Skript aufrufen:

<input type="button" value="-<>"
	onClick="Selektion(this.form.linke_spalte , this.form.rechte_spalte);">

<input type="button" value="<>-"
	onClick="Selektion(this.form.rechte_spalte , this.form.linke_spalte);">

Wir definieren hier zwei Input-Elemente vom Typ "button". Der "value" bestimmt die Beschriftung der Buttons. Hier wurde dafür gewählt Pfeile zu verwenden um die Richtung des Listenwechsels erkennbar zu gestalten, aber an sich ist die Beschriftung egal. Um das Skript funktionieren zu lassen, brauchen die Buttons das Ereignis "onclick". Dies bestimmt was geschehen soll wenn mit der Maus auf dem Button geklickt wird.

Wir bestimmen dass die Funktion "Selektion()" aufgerufen werden soll und die zwei Listen (die zusammen das Formular bilden) werden als Parameter übergeben.

Selektion(this.form.linke_spalte , this.form.rechte_spalte);

Die Reihenfolge der Parameter (angegeben zwischen den Klammern) bestimmt aus welcher Liste die selektierte Optionen entnommen werden und welcher Liste diese hinzugefügt werden. Im obigen Beispiel werden die selektierte Optionen der Liste "linke_spalte" entnommen und an der Liste "rechte_spalte" hinzugefügt.

Umgekehrt sieht das so aus:

Selektion(this.form.rechte_spalte , this.form.linke_spalte);

Es ist ebenso möglich zwei Spalten zu verwenden die unter einander stehen oder weit aus einander. Das Einzige was geändert werden muss, sind die Listennamen, hier in Fettschrift angegeben.

Selektion(this.form.rechte_spalte , this.form.linke_spalte);

Mit "this.form" wird auf das aktuelle Formular (dasselbe Formular in dem sich auch die Buttons befinden) referenziert. Es kann aber auch auf einem anderen Formular referenziert werden:

Selektion(document.forms[3].liste , document.forms['meinFormular'].liste);

Ebenso ist es möglich um auf Formulare in andere Fenstern oder Frames zu referenzieren:

Selektion(this.form.liste , parent.frames['meinFrame'].document.forms[0].liste);



3.2. Die Auswahl auslesen

Insgesamt brauchen wir vier (selbstdefinierte) Funktionen um das ganze zum Laufen zu bringen. Der Anfang macht die Funktion "Selektion()", dessen Definition so aussieht:

function Selektion(ursprungListe, zielListe)
{

}

Die Funktion erwartet zwei Parameter: ursprungListe und zielListe, welche Referenzen zu den Listen enthalten.

Die Funktion wird untersuchen welche Auswahlmöglichkeiten in der Ursprungsliste ausgewählt wurden und diese aus der Ursprungsliste enfernen um diese dann an der Zielliste hinzuzufügen. Leider bietet Javascript aber keine Funktionen um herauszufinden welche Listeneinträge ausgewählt wurden. Die Eigenschaft "selectedIndex" funktioniert nur bei Auswahllisten mit Mehrfachauswahl und ist deshalb für unser Vorhaben nicht zu gebrauchen.

Die Funktion durchläuft daher alle Listeneinträge einzeln und überprüft ob der Eintrag ausgewählt worden ist. Wenn dies der Fall ist, wird der Wert zeitlich in einem Array gespeichert. Die nicht-ausgewählte Optionen werden in einem anderen Array gespeichert. Zum Schluss noch werden die Einträge aus der Zielliste auch in einem dritten Array gespeichert. Dies dient dazu die Daten später zusammenzufügen und zu sortieren, bevor sie in der Liste gestellt werden. Aber dazu später mehr.

Zuerst definieren wir die Variablen die die Daten speichern werden:

var erhalten = new Array();
var selektiert = new Array();
var andereListe = new Array();

Wir werden in einer Schleife alle Optionen aus der ersten Liste ( ursprungListe ) durchlaufen und checken ob diese ausgewählt worden sind. Wenn dies der Fall ist, fügen wir sie der Variable selektiert hinzu. Im anderen Fall (die Option wurde nicht ausgewählt) wird sie der Variable selektiert hinzugefügt (weil sie in der ersten Liste erhalten bleiben soll). Dabei werden die Daten jeweils als Text-, Wertpaare gespeichert. (Der Text ist der sichtbare Teil, der Wert ist das was der Browser letztendlich am Server sendet.)

Mit der Anweisung "with (Objekt)" nimmt das Skript Bezug auf ein Objekt, in diesem Fall also jenes Element in ursprungListe. Mit der "Push()"-Methode des Arrays werden die Daten hinzugefügt.

for (var i = 0; i < ursprungListe.options.length; i++)
{
	with (ursprungListe.options[i])
	{
		if (selected == true)
		{
			selektiert.push(new Array(text, value));
		}
		else
		{
			erhalten.push(new Array(text, value));
		}
	}
}

Jetzt haben wir bereits zwei Arrays gefüllt: Eins enthält alle selektierte Elementen aus der ersten Liste, das andere Array enthält dann natürlich alle Elementen die nicht selektiert sind. Aber da bleibt noch die zweite Liste, welche ja auch Elemente enthält. Diese werden wir jetzt auslesen und in ein drittes Array speichern, nl. andereSpalte.

for (var i = 0; i < zweiteSpalte.options.length; i++)
{
	with (zweiteSpalte.options[i])
	{
		andereSpalte.push(new Array(text, value));
	}
}

Der Code ist derselbe wie weiter oben, als wir die erste Liste ausgelesen haben, mit dem Unterschied dass jetzt nicht geprüft werden soll ob die Optionen selektiert worden sind.

Wir fügen dann die Auswahl aus der ersten Liste die zweite Liste hinzu. Dies erreichen wir dadurch dass wir einfach nur die zwei Arrays (eins mit der Auswahl aus der ersten Liste und das Zweite mit allen Elementen aus der zweiten Liste) zusammenfügen.

for (var x in selektiert) andereSpalte.push(selektiert[x]);



3.3. Die Listen füllen

Das einzige was wir jetzt noch tun müssen, ist die Daten an den Listen hinzufügen. Die Daten aus dem Array erhalten müssen in der ersten Spalte, die Inhalte aus dem zweiten Array andereSpalte müssen in der zweiten Liste. Leider verfügt Javascript - wie schon gesagt - nicht über jegliche Methode um die Daten sofort an der Liste hinzuzufügen.

Eine Lösung besteht darin die Listen, nachdem wir die Daten gespeichert haben, zu leeren und neu zu füllen. Dabei werden die Daten in der Zielliste nicht mehr in der richtigen (alphabetischen) Reihenfolge stehen. Die Daten müssen daher zuvor sortiert werden. Wir erstellen dazu unsere eigene Funktion "Sortieren()", welche im nächsten Abschnitt vorgestellt wird.

erhalten = Sortieren(erhalten);
andereSpalte = Sortieren(andereSpalte);

Hiermit werden die Daten nochmal sortiert.
Danach werden wir zuerst die Listen entleeren. Dazu stellen wir die Eigenschaft "length" (Anzahl der Einträge) einfach auf null.

ersteSpalte.options.length = 0;
zweiteSpalte.options.length = 0;

Jetzt müssen wir nur noch die sortierte Optionen hinzufügen. Dazu durchlaufen wir mit der so genannten For-in-Schleife jedes einzelne Elemente der Arrays die die sortierten Daten enthalten. Die einzelnen Optionen erstellen wir mit der Anweisung "new Option()".
for (var x in erhalten)
{
	var myText = erhalten[x][0];
	var myValue = erhalten[x][1];
	
	if (myValue == '') myValue = myText;
	ersteSpalte.options[x] = new Option(myText, myValue);
}

for (var x in andereSpalte)
{
	var myText = andereSpalte[x][0];
	var myValue = andereSpalte[x][1];

	if (myValue == '') myValue = myText;
	zweiteSpalte.options[x] = new Option(myText, myValue);
}



3.4. Die Daten sortieren

Um die Daten zu sortieren, verwenden wir einen so genannten "Bubble Sort". Dabei werden alle Daten durchlaufen, wobei ein Element mit das jeweils Nächste verglichen wird. Wenn das zweite Element vor das Erste kommen soll, so werden Sie vom Platz getauscht. Dieser Vorgang wiederholt sich, bis alle Daten in einer korrekten (sprich alphabetischen) Reihenfolge stehen. Ein Bubble Sort ist recht träge, ist für kurze Listen jedoch ausreichend.

Die Funktion Sortieren() bekommt als Parameter das jeweilige Array welches wir sortieren wollen.

function Sortieren(liste)
{
	sortierteListe = liste;
}

Diese als Parameter übertragene Liste speichern wir erneut in ein anderes Array, welches wir dann sortieren und anschließend zurückgeben werden.
var sortierteListe = liste;
Jetzt gehen wir das eigenltiche Sortierverfahren an. Dazu brauchen wir eine Variable die wir verwenden um zu überprüfen ob der Sortiervorgang nochmal erneut durchlaufen werden soll. Sie bekommt den Namen erneut.

Anfangs hat diese Variable den Wert "true". Dies bedeutet dass das Sortierverfahren durchlaufen werden muss. Beim jeden Durchgang der Sortierverfahrens, bekommt die Variable den Wert "false", was bewirkt dass der Sortiervorgang nicht nochmal durchlaufen werden muss. Wenn während des Sortiervorgangs aber noch mindestens einmal zwei Elemente vom Platz getauscht werden müssen, bedeutet dies dass nicht sicher ist dass danach alle Elemente in einer richtigen Reihenfolge stehen. Deshalb würde in einem solchen Fall die Variable wieder auf dem Wert "true" gesetzt. Nachdem das Sortierverfahren endgültig abgelaufen ist, wird die Variable zurückgegeben.

var erneut = true;

while (erneut)
{
	erneut = false;

	//setze die Variable wieder auf true
	//falls weiter sortiert werden muss
}
	
return sortierteListe;

Kommen wir nun zum eigentlichen Sortierverfahren. Wir durchlaufen alle Elemente im Array und vergleichen sie jeweils mit dem Nächsten. Wenn dieses Element "größer" ist als das Nächste (sprich, alphabetisch gesehen danach kommen soll), so werden diese vom Platz getauscht.

Wir verwenden dazu eine FOR-Schleife. Schleifen dienen dazu einen einzigen Programmauftrag wiederholt auszuführen, abhängig von einer oder mehrereren Bedingungen. Die FOR-Schleife wird meistens dazu verwendet einen bestimmten Auftrag so oft auszuführen wie von einem Zähler angegeben wird. Folgendes Beispiel demonstriert dies:

for (var i = 0; i < 23; i++)
{

}

Im Beispiel hat der Zähler i anfangs den Wert 0. Dieser wird bei jedem Durchlauf um eins erhöht. ("i++" ist eine verkürzte Schreibweise für "i = i + 1".) Die Schleife wird dabei so lange erneut durchlaufen wie der Zähler kleiner ist als 23, insgesamt also 23 mal.

So kann man auch alle Elemente eines Arrays durchlaufen. Der Zähler fägt nämlich an bei 0 und geht weiter bis einschließlich 22. Das stimmt überein mit einem Array (dessen Index bei 0 anfängt) mit 23 Elementen.

Wir werden in unserem Skript allerdings das Array nur vom ersten bis zum vorletzten Element durchlaufen. Was der Sinn davon sei? Das liegt darin begründet dass wir auch jeweils das nächste Element nehmen werden. Die Indexzahl dieses zweiten Elements währe dann jeweils um eins höher als der aktuelle Wert des Zählers. Wenn wir dann beim letzten Element des Arrays angelangt währen, würde das Skript für das zweite Element auf ein nicht Existierendes zugreifen wollen (das sich dann außerhalb der Array-Grenze befinden würde).

Unsere Schleifendefinition sieht dann so aus:

for (var i = 0; i < sortierteListe.length  - 1; i++)
{

}

Da die Anzahl der Elemente in unserem Array variabel ist, können wir keine feste Zahl in der Schleifendefinition aufnehmen. Anstatt nehmen wir die aktuelle Zahl der Elemente die in die Eigenschaft "length" des Arrays gespeichert ist. Beachten Sie nochmal dass die Variable sortierteListe anfangs die unsortierte Liste speichert die als Parameter an der Funktion übergeben wurde. Auf unsere Elemente greifen wir dann wie folgt zu:

for (var i = 0; i < sortierteListe.length  - 1; i++)
{
	var a = sortierteListe[i][0];
	var b = sortierteListe[i+1][0];
}

Erinnern wir uns daran dass der Parameter liste zweispaltig war: die erste Spalte enthielt den sichtbaren Text, die Zweite den Value der Option.

Diese werden wir gleich mit einander vergleichen. Jedoch gibt es bei der alphabetischen Sortierung so einige Probleme. Das wichtigste ist dabei wohl dass Daten an erster Stelle nicht alphabetisch, sondern nach Schriftgröße sortiert werden. Um dies zu verhindern, werden wir die Texte alle in Kleinbuchstaben umwandeln, jedoch nur beim Sortiervorgang, sie werden danach also nicht in Kleinschrift gespeichert.

for (var i = 0; i < sortierteListe.length  - 1; i++)
{
	var a = sortierteListe[i][0];
	var b = sortierteListe[i+1][0];

	a = a.toLowerCase();
	b = b.toLowerCase();
}

Jetzt müssen wir diese Elemente nur noch vergleichen und, falls sie nicht in einer korrekten alphabetischen Reihenfolge stehen, vom Platz tauschen.

for (var i = 0; i < sortierteListe.length  - 1; i++)
{
	var a = sortierteListe[i][0];
	var b = sortierteListe[i+1][0];

	a = a.toLowerCase();
	b = b.toLowerCase();
	
	if (a > b)
	{
		var speicher = sortierteListe[i+1];
		sortierteListe[i+1] = sortierteListe[i];
		sortierteListe[i] = speicher;

		erneut = true;
	}
}

Um zu testen ob zwei Textvariablen (auch Strings genannt) in einer richtigen alphabetischen Reihenfolge stehen, können wir testen ob die erste Textvariable "größer" ist als die Zweite. Javascript interpretiert dies bei Texten automatisch als Überprüfung einer alphabetischen Reihenfolge.

Wenn die Bedingung "true" ergibt (es also wahr ist dass Text a "größer" ist als Text b), dann sollen diese vom Platz getauscht werden. Dazu speichern wir das zweite Array-Element in einer Variable speicher. Danach überschreiben wir das zweite Array-Element mit dem Wert des Ersten. An der Position des ersten Array-Elements kommt dann der gespeicherte Wert (die Variable speicher). Zum Schluss soll dann noch die Variable erneut den Wert "true" bekommen, so dass der ganze Vorgang nochmal durchlaufen wird um sicher zu stellen dass die Reihenfolge schon stimmt.

Folgende Artikel können zum Sortierverfahren noch interessant sein:
- Der BlubbeSort-Algorithmus
- Können Computer alphabetisch sortieren?


3.5 Die Daten am Server senden

Da wir jetzt ein funktionierendes Formular haben, müssen wir nur noch dafür sorgen dass die Daten am Server geschickt werden (können). Normalerweise sendet ein Browser ein Formular als ganzes ab. Für uns bedeutet dies dass beide Listen abgeschickt werden, aber auch nur die ausgewählte Optionen. Daran lässt sich nichts ändern.

Aber es ist ja nicht der Sinn unseres Formulars dass der User, nachdem er seine Auswahl schon in der zweiten Liste gestellt hat, nochmal erneut alle Optionen anklickt um sie am Server ermitteln zu können. Mit Javascript können wir dieses Problem umgehen. Dazu werden wir alle Elemente einer Liste in ein zusätzliches Feld speichern und so abschicken. Damit werden zwar die ausgewählte Optionen ebenfalls separat mitgeschickt, jedoch soll dies uns nicht stören.

Zuerst erstellen wir dazu einen Button der die Daten an ein weiteres Skript übergibt.

<input type="button" value="Abschicken">

Dieser Code erstellt einen Button mit der Beschriftung "Abschicken", der aber bei einer Betätigung noch nichts macht. Alternativ können Sie auch den <BUTTON>-Tag einsetzen oder sogar eine Graphik verwenden.

Um eine Aktion auszulösen, verwenden wir das onclick-Ereignis, welches Sie bereits kennen. Die Frage ist nur welche Daten das Skript braucht um die Formulardaten senden zu können. Um diese Frage beantworten zu können, müssen wir zuerst darauf eingehen wie das Skript funktioniert.

Der User hat aus einer bestimmten Liste eine oder mehrere Optionen ausgewählt. Das Ziel ist also alle Optionen aus dieser Liste am Server zu senden. Jedoch werden, wie schon angesprochen, nur alle Optionen am Server gesendet die vom User nochmal selektiert worden sind. Was wir also tun müssen, ist alle Optionen aus der Liste auslesen und diese irgendwie am Server senden.

Das geht auch ganz einfach: wir verketten diese und stellen zwischen den verschiedenen Optionen jeweils ein Trennzeichen. Das Resultat könnte etwa so aussehen:

Option 1|-|-|-|Option 2|-|-|-|Option 3|-|-|-|Option 4

Anstatt eines Trennzeichens kann auch, wie oben, eine Zeichenkombination verwendet werden. Wichtig ist dabei nur dass es sich dabei handelt um ein Zeichen (oder eine Zeichenkombination) die ansonsten nie verwendet wird.

Das Resultat speichern wir in ein separates verstecktes Formularfeld ab und senden es so am Server. Serverseitig trennen wir die Daten wieder von einander und schon ist unser Ziel vollbracht.

Ein verstecktes Formularfeld wird wie folgt definiert:

<input name="absendewert" type="hidden">

Der Typ "hidden" gibt an dass es sich um ein verstecktes Feld handelt. Das Feld trägt den Namen "absendewert", die Daten werden auf dem Server also verfügbar sein unter genau diesen Namen. (Allerdings müssen die einzelnen Werte dann noch getrennt werden.)

Wir könnten ja das Feld vorab erstellen und die Listenelemente darin einlesen. Jedoch könnte es sein dass Elemente von mehreren Listen am Server gesendet werden sollen. Das Skript ist darauf ausgelegt die Werte aus beliebig viele Listen am Server senden zu können. Deshalb werden wir die versteckten Felder zur Laufzeit generieren.

Dazu brauchen wir für jede Liste zwei Informationen anzugeben:
1) eine Referenz auf die Liste
2) den Namen des Feldes das die Daten bekommen wird um am Server zu senden

Zusätzlich müssen wir noch eine Referenz geben auf dem Formular das abgeschickt werden soll.

Das ergibt also folgende Parameter: ein Array das Daten zu den Listen gibt die abgeschickt werden sollen (jedes Element ist dabei selbst ein Array das eine Referenz auf die Liste und einen Namen für das Feld enthält) und eine Referenz auf das Formular.

Die Informationen pro Liste nehmen wir jeweils auf in ein assoziatives Array, worin mit Zeichenketten als Schlüssel auf die Elemente zugegriffen wird. Da der Javascript-Code im onclick-Event einzeilig sein muss (also keine Zeilenumbrüche enthalten darf), verwenden wir eine verkürzte Notation. Ein Beispiel:

{'liste':this.form.rechte_spalte, 'speicher':'rechteSpalte'}

Alle Elemente des Arrays müssen zwischen den geschweiften Klammern stehen. Pro Element werden dessen Schlüssel und Wert von einem Doppelpunkt ( : ) getrennt. Das Element liste beinhaltet eine Referenz auf die Liste, während speicher den Namen ist für das versteckte Feldelement das die Daten bekommen wird und am Server geschickt werden soll. Die Daten werden dann später auch auf dem Server unter diesem Namen verfügbar sein.

Aber wie schon gesagt, das Skript ist darauf hinausgelegt mehrere Listen gleichzeitig am Server schicken zu können. Deshalb müssen die Informationen zu jeder Liste auch nochmal in ein anderes Array stehen.

new Array({'liste':this.form.rechte_spalte, 'speicher':'rechteSpalte'},
	{'liste':this.form.rechte_spalte, 'speicher':'zweiteListe'})

Dies müssen Sie auch so machen wenn Sie nur eine einzige Liste verwenden möchten. Es können aber beliebig viele sein. Beachten Sie noch dass im obigen Beispiel der Code nur aus Platzgründen über mehrere Zeilen verteilt ist. Der Code darf in Wirklichkeit keine Zeilenumbrüche enthalten.

Sie haben jetzt gesehen wie unser erster Parameter aussehen soll. Unser zweiter Parameter soll dann einfach eine Referenz auf das Formular sein das wir am Server senden wollen. Da unser Button ja genau in dem Formular steht (meistens doch), können wir sehr einfach eine Referenz erstellen mit der Anweisung "this.form" (wobei "this" auf unserem Button referenziert, und ".form" auf das Formular worin der Button sich befindet).

<input type="button" value="abschicken"
	onclick="Abschicken(new Array({'liste':this.form.rechte_spalte,
		'speicher':'rechteSpalte'},
	{'liste':this.form.rechte_spalte,
		'speicher':'zweiteListe'}),
	this.form);">

Die Funktion "Abschicken()" sieht so aus:

function Abschicken(daten, formular)
{
	for (var i = 0; i < daten.length; i++) VersandVorbereiten(daten[i], formular);

	formular.submit();
}

Die Funktion gibt die Daten pro Liste weiter an eine andere Funktion, VersandVorbereiten() und sendet danach das Formular ab mit der submit()-Methode. Die Funktion "VersandVorbereiten()" braucht als Parameter die Daten zu einer bestimmten Liste gehören und eine Referenz auf das Formular.

Die Funktion wird zuerst alle Daten aus der angegeben Liste auslesen und in einem Array speichern. Danach wird ein INPUT-Element vom Typ HIDDEN erstellt, das dem Formular hinzugefügt wird. Dieser bekommt den angegebenen Namen und eine Kette mit den Werten der Liste.

function VersandVorbereiten(daten, formular)
{
	var abschickwerte = new Array();

	for (var i = 0; i < daten['liste'].options.length; i++)
	{
		var wert = (daten['liste'].options[i].value != '') ?
			daten['liste'].options[i].value :
			daten['liste'].options[i].text ;
		abschickwerte.push(wert);
	}

	var speicherfeld = document.createElement('INPUT');
	speicherfeld.type = 'hidden';
	speicherfeld.name = daten['speicher'];
	formular.appendChild(speicherfeld);
	speicherfeld.value = abschickwerte.join('|-|-|-|');
}

Beachten Sie wiederum dass keine Zeilenumbrüche vorkommen dürfen.

In einer FOR-Schleife werden alle Optionen einer Liste (dessen Referenz sich im Parameter daten befindet, genauer gesagt in dessen Feld liste) durchlaufen. Den Wert einer Option wird in der Variable wert gespeichert. Zuerst wird überprüft ob das VALUE-Attribut nicht leer ist. Wenn es also einen Wert darin gibt, wird dieser gespeichert, ansonsten den sichtbaren Text. Danach wird die Variable wert dem Array hinzugefügt mittels die push()-Methode.

Um die Werte zu speichern, erstellen wir ein INPUT-Element mit der Methode createElement() des document-Objekts. Wir legen fest dass es sich um ein INPUT-Element vom Typ HIDDEN handelt und geben es den Namen der in daten['speicher'] steht. (Ist also auch der Namen und den der Wert am Server ankommt.) Das Feld fügen wir dem Formular hinzu mit der appendChild()-Methode. Zum Schluss bekommt es dann die verschiedenen Werte die mit der join()-Methode des Arrays zusammengefügt werden. Die Zeichenkombination die zwischen den runden Klammern angegeben wird, wird die einzelnen Werte trennen.

speicherfeld.value = abschickwerte.join('|-|-|-|');

Angekommen am Server, müssen die Daten noch getrennt werden. In der serverseitigen Skriptsprache PHP können Sie dies mittels der Funktion explode() machen.

<?php
$werte = explode('|-|-|-|', $_POST['rechteSpalte']);
?>

Die Funktion Explode erwartet als ersten Parameter die Zeichenkette der die Stellen kennzeichnet wo die Trennung erfolgen soll. Als zweiten Parameter muss die Variable angegeben werden die die Werte beinhaltet. In PHP sind Formulardaten als POST-Variablen verfügbar und haben als Namen den des Formularfeldes, in unserem Fall also den Namen den wir in Javascript an der Funktion Abschicken() übergeben haben. In unser Beispiel ist das also "rechteSpalte". Die einzelnen Werte werden dann zurückgegeben und in der Variable $werte gespeichert.


3.6 Eine Alternative ohne Javascript

Vielleicht sind Sie ja vom obigen Skript begeistert, jedoch gibt's da mit Javascript immer ein bestimmtes Problem: viele Leute haben Browser die kein Javascript unterstützen oder sie schalten es einfach ab, sei es nun aus Sicherheitsgründen oder weil man hasst dass der Browser die Kontrolle übernimmt. Deshalb muss auch etwas für gerade einen solchen Fall vorgesehen werden.

Ein User ohne Javascript soll auch in der Lage sein eine Auswahl zu treffen und diese am Server zu senden. Da kein Javascript verfügbar ist, gibt es auch keinen Sinn das Formular überhaupt anzuzeigen. Eine mögliche Lösung besteht darin das Formular mit Javascript in die Seite zu schreiben. Browser ohne (aktiviertem) Javascript zeigen das Formular also nicht mal an. An der Stelle wo das Formular stehen soll, schreiben Sie folgender Code:

<script type="text/javascript">
document.write('<select size="1">');
</script>

Mit der Methode document.write() müssen Sie den kompletten HTML-Code der Auswahlliste in der Seite einfügen. Der HTML-Code muss exact übernommen werden. Beachten Sie nur dass Sie vor einfache Anführungszeichen einen umgekehrten Schrägstrich schreiben müssen.

<script type="text/javascript">
document.write('Dieser Text beinhaltet ein \'.');
</script>

Ein alternatives Formular, z.B. Checkboxen, können Sie dann zwischen <NOSCRIPT>-Tags stellen, so dass es nur sichtbar ist für Leute die kein Javascript (aktiviert) haben.

<noscript>
<input type="checkbox">
	</noscript>

Das Gleiche könnten Sie mit dem Absende-Button machen. Alternativ könnten Sie auch den Rückgabewert "false" in der Funktion Abschicken() einbauen.

<input type="submit" onclick="return Abschicken()">

Der Submit-Button dient dazu ein Formular abzuschicken, ohne Javascript. Im onclick-Event wird mit der Anweisung "return Abschicken()" den Rückgabewert der Funktion Abschicken() zurückgeben. Dieser wird "false" sein, so dass die Betätigung des Buttons das Abschicken des Formulars nicht auslöst. Das übernimmt dann die Funktion Abschicken(). Natärlich müssen Sie im onclick-Event noch die Parameter einfügen und am Ende der Funktion Abschicken() fügen Sie noch die Anweisung "return false" ein.


4. Das Skript einbauen

Das Skript ist recht einfach einzubauen. Kopieren Sie zuerst folgende Skripte und speichern diese in Ihr HTML-Dokument oder Javascript-Datei:

function Selektion(ursprungListe, zielListe)
{
   var erhalten = new Array();
   var selektiert = new Array();
   var andereListe = new Array();

   //---------------------------------------------------------

   for (var i = 0; i < ursprungListe.options.length; i++)
   {
      with (ursprungListe.options[i])
      {
         if (selected == true)
         {
            selektiert.push(new Array(text, value));
         }
         else
         {
            erhalten.push(new Array(text, value));
         }
      }
   }

   for (var i = 0; i < zielListe.options.length; i++)
   {
      with (zielListe.options[i])
      {
         andereListe.push(new Array(text, value));
      }
   }

   for (var x in selektiert) andereListe.push(selektiert[x]);

   //--------------------------------------------------------------

   erhalten = Sortieren(erhalten);
   andereListe = Sortieren(andereListe);

   //--------------------------------------------------------------

   ursprungListe.options.length = 0;
   zielListe.options.length = 0;

   for (var x in erhalten)
   {
      var myText = erhalten[x][0];
      var myValue = erhalten[x][1];

      if (myValue == '') myValue = myText;
      ursprungListe.options[x] = new Option(myText, myValue);
   }

   for (var x in andereListe)
   {
      var myText = andereListe[x][0];
      var myValue = andereListe[x][1];

      if (myValue == '') myValue = myText;
      zielListe.options[x] = new Option(myText, myValue);
   }
}

function Sortieren(liste)
{
   var sortierteListe = liste;

   var erneut = true;

   while (erneut)
   {
      erneut = false;

      for (var i = 0; i < sortierteListe.length  - 1; i++)
      {
         var a = sortierteListe[i][0];
         var b = sortierteListe[i+1][0];

         a = a.toLowerCase();
         b = b.toLowerCase();

         if (a > b)
         {
            var speicher = sortierteListe[i+1];
            sortierteListe[i+1] = sortierteListe[i];
            sortierteListe[i] = speicher;

            erneut = true;
         }
      }
   }

   return sortierteListe;
}

function Abschicken(mehrere, daten, formular)
{
   if (!mehrere)
   {
      VersandVorbereiten(daten);
   }
   else
   {
      for (var i = 0; i < daten.length; i++) VersandVorbereiten(daten[i], formular);
   }

   formular.submit();
}

function VersandVorbereiten(daten, formular)
{
   var abschickwerte = new Array();

   for (var i = 0; i < daten['liste'].options.length; i++)
   {
      var myOption = daten['liste'].options[i];
      var wert = (myOption.value != '') ? myOption.value : myOption.text ;
      abschickwerte.push(wert);
   }

   var speicherfeld = document.createElement('INPUT');
   speicherfeld.type = 'hidden';
   speicherfeld.name = daten['speicher'];
   formular.appendChild(speicherfeld);
   speicherfeld.value = abschickwerte.join('|-|-|-|');
}

Danach müssen Sie die zwei Listen erstellen. Erstellen Sie dazu ein Formular mit zwei Listen, die Sie "linke_spalte", bzw. "rechte_spalte" nennen. Unser Beispiel ganz oben besteht aus einer Tabelle mit drei Spalten. Die erste und die dritte Spalte enthalten jeweils eine Auswahlliste. Die mittlere Spalte enthält zwei Buttons. Die Buttons werden vertikal mittig ausgerichtet mit der Style-Eigenschaft "vertical-align: middle;". Die Tabelle wird von Formulartags umgeben.

<form action="zielseite.php" method="post">
<table>
  <tr>
    <td>
      <select size="8" name="linke_spalte">
        <option value=""></option>
        <option value=""></option>
        <option value=""></option>
        <option value=""></option>
        <option value=""></option>
      </select>
    </td>
    <td style="vertical-align: middle;">
      <input type="button" value="--->" onclick="">
      <br>
      <input type="button" value="<---" onclick="">
    </td>
    <td>
      <select size="8" name="rechte_spalte">
        <option value=""></option>
        <option value=""></option>
        <option value=""></option>
        <option value=""></option>
        <option value=""></option>
      </select>
    </td>
  </tr>
</table>
</form>

Im onclick-Event der Buttons rufen Sie dann die Funktion "Selektion()" auf und geben als Parameter die beiden Listen an. Die Reihenfolge ist nur davon abhänging aus welcher Liste Sie die selektierten Optionen entnehmen möchten und im welchen Sie diese einfügen möchten. Die Liste aus der die Auswahl entnommen werden soll, müssen Sie als ersten Parameter angeben, die Liste wo sie hinzugefügt werden sollen als zweiten Parameter.

 onclick="Selektion(this.form.linke_spalte, this.form.rechte_spalte);"

 onclick="Selektion(this.form.rechte_spalte, this.form.linke_spalte);"

Jetzt muss noch ein Absende-Button hinzukommen. Der Submit-Button von HTML können wir dazu nicht verwenden. Wir verwenden dazu einen Button der eine Javascript-Funktion aufruft.

 <input type="button" value="absenden" onclick="Absenden();">

Als Parameter geben wir Daten zu den Auswahllisten sowie eine Referenz auf das Formular mit. Für jede dessen Daten zum Server geschickt werden sollen (beliebig viele), geben wir eine Referenz auf die Liste mit sowie einen Namen unter den die Daten am Server ankommen.

Diese Daten geben Sie noch folgendem Muster an:

 new Array( {'liste' : Liste, 'speicher' : Namen } )

Bei mehreren Liste gleichzeitig sieht das dann so aus (ohne Zeilenumbrüche!):

 new Array( {'liste' : Liste, 'speicher' : Namen } ,
            {'liste' : Liste, 'speicher' : Namen } )

An den unterstrichenen Stellen kommen dann die Daten. Zu "liste" kommt eine Referenz auf das Formular. Dafür verwenden Sie die Anweisung "this.form", gefolgt vom Namen der Liste.

this.form.rechte_spalte

Zu "speicher" gehört der Name der Variable unter den die Daten am Server ankommen. Wenn Sie z.B. "meine_auswahl" angeben, werden die Daten eben unter jenem Namen auf dem Server verfügbar sein.

new Array( {'liste' : this.form.rechte_spalte, 'speicher' : 'auswahl' } )

Sie können beliebig viele Listen angeben mit dem obigen Muster. Diese kommen dann alle nochmal in ein anderes Array, wie es weiter oben schon gezeigt wurde.

Als zweiten Parameter muss dann noch eine Referenz auf die Liste angegeben werden. Das geht sehr einfach mit der Anweisung "this.form".

Abschicken(
   new Array( {'liste' : this.form.rechte_spalte, 'speicher' : 'auswahl' } ),
   this.form );

Obigen Code kommt dann im onclick-Event des Buttons.

Beachten Sie dass die Daten zusammengesetzt werden in einer Taxtvariable. Sie müssen die einzelnen Werte dann wieder von einander trennen. Als Trenner kommt (wenn Sie dies im Code nicht geändert haben) die Zeichenkombination "|-|-|-|" zum Einsatz. Mit PHP kann die Variable dann sehr einfach in ein Array umgewandelt werden mit der Funktion "explode()".

$werte = explode("|-|-|-|", $_POST['meine_auswahl']);

Achtung Autoren: Beispielcode, bitte nicht ändern!


[back to top]



Userdaten
User nicht eingeloggt

Gesamtranking
Werbung
Datenbankstand
Autoren:04508
Artikel:00815
Glossar:04116
News:13565
Userbeiträge:16552
Queueeinträge:06245
News Umfrage
Ihre Anforderungen an ein Online-Zeiterfassungs-Produkt?
Mobile Nutzung möglich (Ipone, Android)
Externe API Schnittstelle/Plugins dritter
Zeiterfassung meiner Mitarbeiter
Exportieren in CSV/XLS
Siehe Kommentar



[Results] | [Archiv] Votes: 1147
Comments: 0