Dynamische Darstellung von Daten mit Parameterübergabe (Fortgeschritten)

Bei Ilias finden Sie einen Ordner namens Ajax_JSON_3Beispiele. Dort befinden sich neben den Dateien für das Beispiel aus der letzten Sitzung (Beispiel1.html und Beispiel1.js) und für das Beispiel mit der Filterfunktion (Beispiel2.html und Beispiel2.js) die Dateien für eine Lösung, mit der einzelne Inhalte ein- und ausgeblendet werden können. Da hierbei Code geschrieben wird, der nicht immer ganz einfach nachzuvollziehen ist, gilt dieser Ansatz für Studierende, die gerne über das eigentliche Ziel hinaus noch etwas mehr machen möchten.

Wie auch das letzte Beispiel baut der Code auf dem vorherigen Beispiel auf und ist in der js-Datei kommentiert.

Hier eine strukturierte Erklärung des hinzugefügten Codes:

In der bereits vorhandenen Funktion GetHeroesOfUniverse() werden zu der for-Schleife, die für die Ausgabe sorgt, einzelne Elemente hinzugefügt:

1. Der Datencontainer

Um den bisherigen Aufbau der Daten einzuteilen, muss ein zusätzliches Element erstellt werden, welches ein- und ausgeblendet werden kann. Hierbei bietet sich ein div-Element an, da dies nicht vorformatiert ist, im Gegensatz zu beispielsweise einem p-Element, das den enthaltenen Text in einer Zeile ausgeben und danach einen Zeilenumbruch verursachen würde.

var myAddOnContainer = document.createElement('div');

In dieses Element können nun die Daten gelegt werden, mit denen wir separat arbeiten wollen.

myAddOnContainer.appendChild(paraAge);
myAddOnContainer.appendChild(paraSuperpower);
myAddOnContainer.appendChild(myPowerList);

Anschließend wird der Container an das bereits angelegte article-Element gehängt.

myMainArticle.appendChild(myAddOnContainer);

2. Der Mehr-anzeigen-Button

Auch hier muss erst wieder das entsprechende Element erstellt werden.

var moreButton = document.createElement('button');

Dieser Button kann mit .innerHtml mit Text gefüllt

moreButton.innerHTML = "Show more";

und ebenfalls zu dem vorhandenen article-Element hinzugefügt werden.

myMainArticle.appendChild(moreButton);

3. Vorbereitung für die Afrage

Um später auf die einzelnen Daten der erstellten Buttons und Datencontainer zugreifen zu können, werden sie in geordneter Form in einem Array gespeichert. Dazu müssen die Arrays erstmal am Anfang der Datei deklariert

var buttonArray = [];
var objectArray = [];

und innerhalb der Funktion gefüllt werden. Durch die Methode .push() wird der Wert der Variable in den Klammern in das vorangestellte Array kopiert. Dabei wird immer der letzte leere Platz genommen.

buttonArray.push(moreButton);
objectArray.push(myAddOnContainer);

Außerdem wird der div-Conteiner ausgeblendet, indem auf die Style-Informationen der Variable zugegriffen wird. Innerhalb der css-Datei würde man disply: none; schreiben, hätte jedoch die selbe Funktion.

myAddOnContainer.style.display = 'none';

In einer weiteren for-Schleife wird nun zu jedem Button innerhalb des Arrays buttonArray ein Event hinzugefügt, das durch einen Klick ausgeführt wird. Dabei ist es egal, dass sich diese Schleife innerhalb der GetHeroesOfUniverse()-Funktion befindet. Das Event wird aufgerufen, sobald einer der Buttons angeklickt wird.

Der Zähler zählt durch das Array, wie in den restlichen for-Schleifen auch. Die Zählervariable wurde hier zur besseren Kenntlichkeit umbenannt, ist jedoch das Gleiche wie i oder j.

for (var indexOfButton = 0; indexOfButton < buttonArray.length; indexOfButton++) { }

Zu jedem Button, der in diesem Array gefunden wird, wird ein Click-Event hinzugefügt und sofort aufgerufen. Die Methode .bind() sorgt dafür, dass der aktuelle Wert (sprich, der gedrückte Button) weitergegeben wird. Es wird quasi der aktuelle Wert an diese Funktion gebunden und alle anderen (gleichen) Werte, wie die restlichen Buttons, werden ignoriert. Etwas ausführlicher: Innerhalb dieser for-Schleife werden alle Buttons innerhalb des Arrays erkannt und ihnen wird das Event hinzugefügt. Die Methode bind() setzt beim Aufruf ihr this-Keyword auf den ersten übergebenen Wert (also 0, da dies die erste Stelle im Array ist). Da bei dieser Methode jedoch alle weiteren Argumente (in diesem Fall indexOfButton) den beim Funktionsaufruf übergebenen Werten vorangestellt werden, bleibt schlussendlich nur der indexOfButton übrig, durch den wir wissen, welcher Button gerade gedrückt wird.

buttonArray[indexOfButton].addEventListener('click', function(indexOfButton) {
}.bind(this, indexOfButton));

Mit diesem Event wird eine Funktion aufgerufen, die den indexButton und den aktuellen Button als Parameter haben. Parameter werden durch Komma getrennt und können grundsätzlich verschiedene Datentypen haben. In diesem Fall ist es zum Einen die Position des entsprechenden Buttons (indexOfButton) und zum Anderen das Button-Element, das sich an der angegebenen Stelle im Array befindet (buttonArray[indexOfButton]).

ShowMore(indexOfButton, buttonArray[indexOfButton]);

Die Funktion ShowMore() beinhaltet eine weitere for-Schleife (die vorerst letzte ;) ), die das Array, in dem sich die unterschiedlichen div-Container befinden, durchgeht und jede Zählerzahl (in diesem Fall heißt die Zählerzahl positionInArray) mit dem Index des aktuellen Buttons (indexOfButton) vergleicht. Die Zählerzahl entspricht der Position im Array, da durch ein Array immer von vorne nach hinten durchiteriert wird.

    for(var positionInArray = 0; positionInArray < objectArray.length; positionInArray++) {
        if(positionInArray === indexOfCurrentButton) {

        }
    }

Haben die beiden Variablen die gleichen Werte (in diesem Fall 0, 1 oder 2), werden weitere Bedingungen geprüft. Wenn der zusätzliche Inhalt nicht angezeigt wird, wird er mit der Aussage objectArray[positionInArray].style.display = 'block'; eingeblendet und der Text des Buttons wird geändert. Wird der zusätzliche Inhalt bereits angezeigt, wird er wieder ausgeblendet. So kann durch ein einziges Klick-Event das Ein- sowie das Ausblenden realisiert werden.

            if(objectArray[positionInArray].style.display === 'none') {
                objectArray[positionInArray].style.display = 'block';
                currentButton.innerHTML = "Show less";
            } else if(objectArray[positionInArray].style.display === 'block') {
                objectArray[positionInArray].style.display = 'none';
                currentButton.innerHTML = "Show more";
            }