Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen RevisionVorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
de:create:dynamic [16.12.2020 19:14] – Korrektur adminde:create:dynamic [13.09.2023 21:29] (aktuell) admin
Zeile 4: Zeile 4:
  
 Prinzipiell sind mit JavaScript und dem Document Object Model (DOM) sehr umfassende Modifikationen innerhalb einer Fragebogenseite möglich, allerdings erfordert dies mitunter fortgeschrittene Programmier-Kenntnisse. Diese Anleitung beschränkt sich darauf, wie man damit eine Frage in Abhängigkeit einer Antwort ein- bzw. ausblendet. Prinzipiell sind mit JavaScript und dem Document Object Model (DOM) sehr umfassende Modifikationen innerhalb einer Fragebogenseite möglich, allerdings erfordert dies mitunter fortgeschrittene Programmier-Kenntnisse. Diese Anleitung beschränkt sich darauf, wie man damit eine Frage in Abhängigkeit einer Antwort ein- bzw. ausblendet.
 +
 +**Tipp:** Falls der JavaScript-Code nicht auf Anhieb funktioniert, nutzen Sie bitte zur Fehlersuche die [[:de:general:browser-tools]].
 +
  
 ===== Grundwissen ===== ===== Grundwissen =====
  
-  - In JavaScript gibt es so genannte //Event Handler//. Das sind Funktionen, die ausgeführt werden, wenn der Benutzer irgend etwas auf der Seite macht -- wenn also Ereignisse (//Events//) auf der Seite passierenSolche Ereignisse können ein Klick des Teilnehmers sein (''click''), die Änderung einer Dropdown-Auswahl oder einer offenen Textangabe (''onchange''), die Berührung eines Bildelements mit der Maus (''mouseover'')etc.+  - In JavaScript gibt es so genannte //Event Handler//. Das sind Funktionen, die durch Aktionen des Nutzers auf der Seite ausgelöst werden. Die Aktionen erzeugt ein //Event//, und dieses löst die verbundene JavaScript-Funktion, den //EventHandler// ausMögliche Events sind ... 
 +    * ''%%'click'%%'' -- der Klick auf ein Element, 
 +    * ''%%'mouseover'%%'' -- das Bewegen der Maus über ein Element, 
 +    * ''%%'change'%%'' -- die Auswahl einer Option in einem Dropdown oder die Änderung eines Texteingabefelds, 
 +    * ''%%'keypressed'%%'' -- ein Tastendruck 
 +    * und viele andere.
   - Jedes Element einer (HTML-)Internetseite hat eine ganze Reihe von Eigenschaften. SoSci Survey erstellt die einzelne Fragebogen-Seite als HTML-Seite -- und alle Fragen und Eingabefelder sind ihrerseits HTML-Elemente, deren Eigenschaften durch JavaScript beeinflusst werden können. Eine solche Eigenschaft ist der Darstellungsstil (''style'') und ein Teil davon ist der Anzeigemodus (''display''). Der Anzeigemodus definiert, wie ein Element angezeigt wird (''block'' oder ''inline'') oder dass es eben nicht angezeigt wird (''none'').   - Jedes Element einer (HTML-)Internetseite hat eine ganze Reihe von Eigenschaften. SoSci Survey erstellt die einzelne Fragebogen-Seite als HTML-Seite -- und alle Fragen und Eingabefelder sind ihrerseits HTML-Elemente, deren Eigenschaften durch JavaScript beeinflusst werden können. Eine solche Eigenschaft ist der Darstellungsstil (''style'') und ein Teil davon ist der Anzeigemodus (''display''). Der Anzeigemodus definiert, wie ein Element angezeigt wird (''block'' oder ''inline'') oder dass es eben nicht angezeigt wird (''none'').
   - Die Elemente einer HTML-Seite lassen sich am einfachsten anhand ihrer HTML-ID ansprechen. SoSci Survey vergibt für alle Eingabefelder automatisch HTML IDs, die sich an der Frage- bzw. Itemkennung orientieren.   - Die Elemente einer HTML-Seite lassen sich am einfachsten anhand ihrer HTML-ID ansprechen. SoSci Survey vergibt für alle Eingabefelder automatisch HTML IDs, die sich an der Frage- bzw. Itemkennung orientieren.
-    * Am einfachsten ermitteln Sie die ID eines Elements mit den "Entwickler-Werkzeugen" Ihres Browsers (je nach Browser an unterschiedlicher Stelle zu finden). Diese Werkzeuge können Ihnen den HTML-Code eines Elements (z.B. eines Auswahlfeldes) zeigen -- inkl. der HTML-ID (''%%id="AB01_01"%%''). Wenn Sie in den Entwickler-Werkezugen den "Inspektor" auswählen, können Sie ein Element der Seite einfach anklicken, um die passenden Informationen zu finden. Alternativ können Sie sich den Quelltext der HTML-Seite im Browser anzeigen lassen und dort das entsprechende Element suchen.+    * Am einfachsten ermitteln Sie die ID eines Elements mit den [[:de:general:browser-tools]]. Diese Werkzeuge können Ihnen den HTML-Code eines Elements (z.B. eines Auswahlfeldes) zeigen -- inkl. der HTML-ID (''%%id="AB01_01"%%''). Wenn Sie in den Entwickler-Werkezugen den "Inspektor" auswählen, können Sie ein Element der Seite einfach anklicken, um die passenden Informationen zu finden. Alternativ können Sie sich den Quelltext der HTML-Seite im Browser anzeigen lassen und dort das entsprechende Element suchen.
     * Für Fragen vergibt SoSci Survey jeweils eine HTML-ID bestehend aus der Frage-Kennung, einem Unterstrich (''_'') und ''qst'' (z.B. ''AB01_qst'' für Frage "AB01").     * Für Fragen vergibt SoSci Survey jeweils eine HTML-ID bestehend aus der Frage-Kennung, einem Unterstrich (''_'') und ''qst'' (z.B. ''AB01_qst'' für Frage "AB01").
   - In SoSci Survey kann man beliebige Inhalte in eine Fragebogenseite aufnehmen. Also auch JavaScript Code. Dies geschieht am einfachsten, indem man den Code unter **Textbausteine u. Beschriftung** als Textbaustein speichert (für die //Darstellung// muss man "HTML-Code" auswählen) und diesen Textbaustein beim **Fragebogen zusammenstellen** in die Seite zieht. Und zwar __unter__ die jeweilige Frage(n).   - In SoSci Survey kann man beliebige Inhalte in eine Fragebogenseite aufnehmen. Also auch JavaScript Code. Dies geschieht am einfachsten, indem man den Code unter **Textbausteine u. Beschriftung** als Textbaustein speichert (für die //Darstellung// muss man "HTML-Code" auswählen) und diesen Textbaustein beim **Fragebogen zusammenstellen** in die Seite zieht. Und zwar __unter__ die jeweilige Frage(n).
Zeile 21: Zeile 29:
  
 **Hinweis:** Einige Fragetypen verwenden in der Standard-Einstellung je nach Bildschirm eine andere Darstellung (responsive Layout). In seltenen Fällen wird die Darstellung nicht korrekt gewählt, wenn Sie solch eine Frage per JavaScript einblenden. In diesem Fall stellen Sie für //Darstellung// in der Frage bitte eine andere Option als "dynamisch" ein. **Hinweis:** Einige Fragetypen verwenden in der Standard-Einstellung je nach Bildschirm eine andere Darstellung (responsive Layout). In seltenen Fällen wird die Darstellung nicht korrekt gewählt, wenn Sie solch eine Frage per JavaScript einblenden. In diesem Fall stellen Sie für //Darstellung// in der Frage bitte eine andere Option als "dynamisch" ein.
 +
 +**Hinweis:** Wenn Sie eine einfache Auswahl oder Skala (also keine Mehrfachauswahl) als Filterfrage verwenden und im Fragebogen die Option "Kreuzchen in einfacher Auswahl oder Skala abwählbar" aktiviert haben, so liefert die Eigenschaft ''checked'' nach dem Abwählen einer Option weiterhin ''true'' statt ''false''. Verwenden Sie in diesem Fall das Event ''change'' statt ''click''.
  
 **Tipp:** Wenn der Teilnehmer sieht, dass eine der Auswahloptionen mit zusätzlicher Arbeit verbunden ist, dann könnte dies sein Antwortverhalten beeinflussen. Ein klassischer [[filters|Filter]] mit Abfrage der zweiten Frage auf der Folgeseite kann hier sinnvoller sein. **Tipp:** Wenn der Teilnehmer sieht, dass eine der Auswahloptionen mit zusätzlicher Arbeit verbunden ist, dann könnte dies sein Antwortverhalten beeinflussen. Ein klassischer [[filters|Filter]] mit Abfrage der zweiten Frage auf der Folgeseite kann hier sinnvoller sein.
  
  
-===== Beispiel 1: Sichtbare Auswahl =====+===== Beispiel 1a: Sichtbare Auswahl =====
  
 Abhängig von einer Ja/Vielleicht/Nein-Frage ("JN01", sichtbare Auswahl) soll eine offene Textfrage ("TX01") angezeigt werden. Abhängig von einer Ja/Vielleicht/Nein-Frage ("JN01", sichtbare Auswahl) soll eine offene Textfrage ("TX01") angezeigt werden.
Zeile 39: Zeile 49:
 var frage = document.getElementById("TX01_qst");  // HTML-ID der Texteingabe var frage = document.getElementById("TX01_qst");  // HTML-ID der Texteingabe
  
-function toogle() {+function toggle() {
   // Die zwei Pipes (||) sind ein logisches "Oder"   // Die zwei Pipes (||) sind ein logisches "Oder"
   // Die Bedingung prüft also: Ist Option A ausgewählt oder ist B ausgewählt?   // Die Bedingung prüft also: Ist Option A ausgewählt oder ist B ausgewählt?
Zeile 53: Zeile 63:
  
 // Die Funktion soll jedesmal ausgeführt werden, wenn eine der drei Optionen angeklickt wird // Die Funktion soll jedesmal ausgeführt werden, wenn eine der drei Optionen angeklickt wird
-SoSciTools.attachEvent(optionA, "click", toogle); +SoSciTools.attachEvent(optionA, "click", toggle); 
-SoSciTools.attachEvent(optionB, "click", toogle); +SoSciTools.attachEvent(optionB, "click", toggle); 
-SoSciTools.attachEvent(optionC, "click", toogle);+SoSciTools.attachEvent(optionC, "click", toggle);
  
 // Und jetzt gleich soll sie auch ausgeführt werden, damit die Anzeige zu Beginn korrekt ist // Und jetzt gleich soll sie auch ausgeführt werden, damit die Anzeige zu Beginn korrekt ist
 // (z.B. ausblenden der Texteingabe zu Beginn) // (z.B. ausblenden der Texteingabe zu Beginn)
-toogle();+toggle();
 // --> // -->
 </script> </script>
 </code> </code>
 +
 +===== Beispiel 1b: Mehrere gleichartige Fragen =====
 +
 +Mitunter kommt es vor, dass dieselbe Funktion auf einer Fragebogen-Seite mehrfach zum Einsatz kommt. Wenn wir das vorige Beispiel nehmen: Nehmen wir einmal an, dass auf der Seite nicht nur eine Auswahl mit Zusatzfrage ist, sondern vier Auswahlfragen mit vier Zusatzfragen.
 +
 +Die naheliegende Lösung wäre es, den JavaScript-Code zu kopieren. Das funktioniert aber nicht ohne weiteres, weil die Variablen (''optionA'', ''optionB'') und auch der Name der Funktion (''toggle()'') sich dann gegenseitig in die Quere kommen. Wenn Sie sich für das Kopieren entscheiden, müssten Sie also bei jeder Kopie andere Namen für die Variablen und Funktionen verwenden. Aber es geht auch eleganter.
 +
 +Nachfolgend wird der JavaScript-Code von oben in eine Funktion bzw. Klasse ''DynamicFilter()'' gekapselt. Die 4 Auswahl-Zusatzfrage-Tupel unterscheiden sich in den Kennungen von Auswahlfrage und Zusatzfrage. Entsprechend hat die Funktion zwei Parameter ''auswahlID'' und ''frageID''. Diese Parameter werden für die Kennungen in den ersten Zeilen verwendet: Aus ''"JN01_01a"'' wird dann ''auswahlID + "_01"''.
 +
 +Diese Anleitung lässt das ''<script>''-Tag zu Beginn weg, wenn Sie den Code verwenden, müssen Sie natürlich ganz zu Beginn das ''<script type="text/javascript">'' und am Ende das ''</script>'' ergänzen.
 +
 +<code javascript>
 +function DynamicFilter(auswahlID, frageID) {
 +    var optionA = document.getElementById(auswahlID  + "_01a");  // JN01_01a ist die HTML-ID der Auswahloption "Ja"
 +    var optionB = document.getElementById(auswahlID  + "_02a");  // Option "Vielleicht"
 +    var optionC = document.getElementById(auswahlID  + "_03a");  // Option "Nein"
 +    var frage = document.getElementById(frageID + "_qst");  // HTML-ID der Texteingabe
 + 
 +    function toggle() {
 +      // Die zwei Pipes (||) sind ein logisches "Oder"
 +      // Die Bedingung prüft also: Ist Option A ausgewählt oder ist B ausgewählt?
 +      if (optionA.checked || optionB.checked) {
 +        // Wurde "Ja" oder "Vielleicht" ausgewählt, dann wird die Frage angezeigt
 +        // Keine Angabe ("") verwendet die Standard-Einstellung (normal anzeigen)
 +        frage.style.display = "";
 +      } else {
 +        // Mit der Anzeigeoption "none" wird die Frage ausgeblendet
 +        frage.style.display = "none";
 +      }
 +    }
 + 
 +    // Die Funktion soll jedesmal ausgeführt werden, wenn eine der drei Optionen angeklickt wird
 +    SoSciTools.attachEvent(optionA, "click", toggle);
 +    SoSciTools.attachEvent(optionB, "click", toggle);
 +    SoSciTools.attachEvent(optionC, "click", toggle);
 + 
 +    // Und jetzt gleich soll sie auch ausgeführt werden, damit die Anzeige zu Beginn korrekt ist
 +    // (z.B. ausblenden der Texteingabe zu Beginn)
 +    toggle();
 +}
 +
 +
 +// -->
 +</script>
 +</code>
 +
 +Alles andere bleibt gleich. Nun muss diese Klassen-Funktion noch aufgerufen werden, um eine neue Instanz der Klasse zu initialisieren. Dafür benötigt man das Schlüsselwort ''new''.
 +
 +<code>
 +new DynamicFilter("JN01", "TX01");
 +</code>
 +
 +Mit diesem Aufruf zusammen funktioniert der Code wie im vorigen Beispiel. Aber natürlich kann man diese eine Zeil mit weiteren Kennungen mehrfach wiederholen:
 +
 +<code>
 +new DynamicFilter("JN02", "TX02");
 +new DynamicFilter("JN03", "TX03");
 +new DynamicFilter("JN04", "TX04");
 +</code>
 +
 +So lässt sich derselbe Filter sehr übersichtlich mehrfach auf einer Seite verwenden. So einfach funktioniert das natürlich nur dann, wenn alle Filterfragen und Folgefragen dieselbe Struktur haben. Durch das Kapseln in einer Funktion kann man aber generell das Problem umgehen, dass die Variablen unterschiedliche benannt sein müssen.
  
  
Zeile 75: Zeile 146:
 var frage = document.getElementById("DD02_qst");  // Die Frage DD02, die ein-/auszublenden ist var frage = document.getElementById("DD02_qst");  // Die Frage DD02, die ein-/auszublenden ist
  
-function toogle() {+function toggle() {
   if (dropdown.value == "7") {  // Hier den Wert (Antwortcode) eintragen, bei dem das zweite Dropdown eingeblendet werden soll   if (dropdown.value == "7") {  // Hier den Wert (Antwortcode) eintragen, bei dem das zweite Dropdown eingeblendet werden soll
     frage.style.display = "";     frage.style.display = "";
Zeile 83: Zeile 154:
 } }
  
-SoSciTools.attachEvent(dropdown, "change", toogle);  // Bei einer Änderung der Auswahl die Anzeige anpassen +SoSciTools.attachEvent(dropdown, "change", toggle);  // Bei einer Änderung der Auswahl die Anzeige anpassen 
-SoSciTools.attachEvent(dropdown, "click", toogle);  // Auch beim Klick prüfen - sonst wird die Änderung evtl. erst beim Verlassen des Dropdowns wirksam +SoSciTools.attachEvent(dropdown, "click", toggle);  // Auch beim Klick prüfen - sonst wird die Änderung evtl. erst beim Verlassen des Dropdowns wirksam 
-toogle();  // Und zu Beginn auch die korrekte Anzeige sicherstellen+toggle();  // Und zu Beginn auch die korrekte Anzeige sicherstellen
 // --> // -->
 </script> </script>
Zeile 157: Zeile 228:
  
 // --> // -->
 +</script>
 +</code>
 +
 +
 +===== Beispiel 4: Skala =====
 +
 +In diesem Beispiel soll ein Skalenitem mit 5 Auswahlmöglichkeiten (1="überhaupt nicht" bis 5="sehr häufig") mit einem Textfeld gekoppelt werden. Das Textfeld soll nur angezeigt werden, wenn mindestens 3 ("hin und wieder") ausgewählt wurde.
 +
 +Außerdem soll die Lösung nicht nur für ein Item-Pärchen genutzt werden, sondern gleich für eine ganze Batterie (10 Skalen-Items und 10 Texteingabefelder, welche als [[:de:create:combine]] dargestellt werden). Damit das funktioniert, ohne dass der komplette Code 10-mal wiederholt werden muss, wird die JavaScript-Funktionnalität als Klasse (''function'') gekapselt. Diese Klasse wir dann für jedes der 10 Items genau einmal aufgerufen.
 +
 +Im folhenden Beispiel haben die Items folgende Kennungen:
 +
 +  * Skala: SK01_01 bis SK01_10
 +  * Texteingabe: TE01_01 bis TE01_10
 +
 +Der JavaScript-Code für die 10 Item-Pärchen würde wie folgt aussehen. Ein großer Teil des Codes entfällt dabei (ganz oben) darauf, erst einmal die Auswahlfelder eines jeden Skalenitems zu finden. Das hat den Vorteil, dass der Code unabhängig vom eingestellten Skalenniveau und unabhängig von Ausweichoptionen funktioniert.
 +
 +Der Kern der Funktion, welcher das Eingabefeld ein- und ausblendet ist wieder das ''%%element.style.display = "none";%%''
 +
 +<code javascript>
 +<script type="text/javascript">
 +
 +/**
 + * Auswahlfelder (radio) der Skala mit der
 + * Kennung itemID finden und auflisten.
 + */
 +function getScaleInputs(itemID) {
 +    var inputs = {};
 +    // Einmal die regulären Auswahlfelder
 +    for (var i=1; i<100; i++) {
 +        var inputID = itemID + i;
 +        var input = document.getElementById(inputID);
 +        if (input) {
 +            inputs[i] = input;
 +        } else {
 +            break;
 +        }
 +    }
 +    // Und dann könnte es noch Ausweichoptionen geben
 +    for (var i=-1; i>=-3; i--) {
 +        var inputID = itemID + "DK" + (-i);
 +        if (i == -1) {
 +            inputID = itemID + "DK";
 +        }
 +        var input = document.getElementById(inputID);
 +        if (input) {
 +            inputs[i] = input;
 +        }
 +    }
 +
 +    return inputs;
 +}
 +
 +/**
 + * Die Klasse, welche das Skalenitem (Kennung itemID) mit
 + * einem Eingabefeld (o.ä.) mit der Kennung inputID verbindet.
 + * In dem Array show wird definiert, bei welchen Werten das
 + * Eingabefeld oder Element angezeigt werden soll.
 + */
 +function linkScaleToInput(itemID, inputID, show) {
 +    // Wir benötigen zunächst alle Auswahldfelder des Skalenitems
 +    var radio = getScaleInputs(itemID);
 +    var element = document.getElementById(inputID);
 +
 +    // Wir brauchen eine Funktion, um den
 +    // in der Skala ausgewählten Wert zu ermitteln.
 +    function getValue() {
 +        for (var value in radio) {
 +            if (radio[value].checked) {
 +                return parseInt(value);
 +            }
 +        }
 +        return -9;
 +    }
 +
 +    // Und dann benötigen wir eine Funktion,
 +    // welche auf eine Auswahl reagiert
 +    function onSelect() {
 +        var value = getValue();
 +
 +        // Anzeigen, wenn der Wert in show gelistet wurde,
 +        // oder mittels display=none verbergen
 +        if (show.indexOf(value) > -1) {
 +            element.style.display = "";
 +        } else {
 +            element.style.display = "none";
 +        }
 +    }
 +
 +    for (var value in radio) {
 +        radio[value].addEventListener("click", onSelect);
 +    }
 +
 +    // Zu Beginn die Anzeige korrekt wählen
 +    onSelect();
 +}
 +
 +// Eine Instanz der Klasse für jedes Item der Skala
 +new linkScaleToInput("SK01_01", "TE01_01", [3,4,5]);
 +new linkScaleToInput("SK01_02", "TE01_02", [3,4,5]);
 +new linkScaleToInput("SK01_03", "TE01_03", [3,4,5]);
 +new linkScaleToInput("SK01_04", "TE01_04", [3,4,5]);
 +new linkScaleToInput("SK01_05", "TE01_05", [3,4,5]);
 +new linkScaleToInput("SK01_06", "TE01_06", [3,4,5]);
 +new linkScaleToInput("SK01_07", "TE01_07", [3,4,5]);
 +new linkScaleToInput("SK01_08", "TE01_08", [3,4,5]);
 +new linkScaleToInput("SK01_09", "TE01_09", [3,4,5]);
 +new linkScaleToInput("SK01_10", "TE01_10", [3,4,5]);
 +
 </script> </script>
 </code> </code>
de/create/dynamic.1608142456.txt.gz · Zuletzt geändert: 16.12.2020 19:14 von admin
 
Falls nicht anders bezeichnet, ist der Inhalt dieses Wikis unter der folgenden Lizenz veröffentlicht: CC Attribution-Share Alike 4.0 International
Driven by DokuWiki