Inhaltsverzeichnis

Navigation im Fragebogen

Üblicherweise starten Teilnehmer auf der ersten Seite und füllen den Fragebogen dann sequenziell aus. Mitunter wird der Ablauf durch ein setPageOrder() oder goToPage() verändert, aber auch dann folgen die Teilnehmer dem vom Projektleiter vorgegeben Ablauf.

Diese Anleitung beschreibt, wie man ein Menü bzw. eine Navigation im Fragebogen ergänzt, sodass Teilnehmer nach Belieben zwischen den Seiten/Abschnitten springen können. Dies ist vor allem dann sinnvoll, wenn man ein Formular in SoSci Survey zur Abfrage von Informationen einsetzt (s. auch Formulare mit unterschiedlichen Eingabeformaten).

Beispiel für ein Navigationsmenü im Fragebogen

Grundlagen

Im ersten Schritt werden unter Fragebogen zusammenstellen Seitenkennungen für alle Seiten eingetragen, zu denen der Teilnehmer springen kann. Der Titel der Seite wird als Notiz eingetragen.

Seitenkennung und Notiz eintragen

Die eigentlichen Navigationsknöpfe werden von der Funktion buttonToPage() erzeugt. Diese Funktion erzeugt HTML-Code, den man mittels html() in der Fragebogen-Seite einbinden kann. Mit folgendem PHP-Code würde man auf einer Fragebogen-Seite Knöpfe zu unterschiedlichen Seiten anbieten.

html(
  '<div>'.
  buttonToPage('start').
  buttonToPage('kontakt').
  buttonToPage('studium').
  buttonToPage('leistungen').
  buttonToPage('dokumente').
  buttonToPage('notizen').
  buttonToPage('abschicken').
  '</div>'
);

Knöpfe zur Navigation zwischen unterschiedlichen Seiten

Der PHP-Code müsste nun auf jeder einzelnen Seite des Fragebogens (z.B. oben auf der Seite) eingefügt werden. Dies ist natürlich unpraktisch und erschwert nachträgliche Änderungen. Deshalb wird unter Fragebogen zusammenstellen im Karteireiter *PHP-Funktionen* eine neue Funktion definiert, welche sich um die Navigation und ggf. weitere Anpassungen kümmert.

function navigation() {
    // Navigation
    html(
      '<div>'.
      buttonToPage('start').
      buttonToPage('kontakt').
      buttonToPage('studium').
      buttonToPage('leistungen').
      buttonToPage('dokumente').
      buttonToPage('notizen').
      buttonToPage('abschicken').
      '</div>'
    );
    // Beschriftung des Weiter-Knopfes
    option('nextbutton', 'Nächstes Formular');
}

Auf den einzelnen Seiten des Fragebogens muss dann nur noch ein PHP-Code eingebunden werden, welcher diese Funktion aufruft:

navigation();

Darstellung anpassen

Mittels CSS lassen sich die Anordnung auf der Seite und die Darstellung der Knöpfe anpassen. Zunächst werden im HTML-Code einige Ergänzungen vorgenommen:

html(
  '<div style="border: 2px solid #CCCCCC; border-left: 0 none; border-right: 0 none; padding: 20px 0 12px 0; margin-bottom: 3em;">'.
  '<div class="s2flex NavButtons" style="flex-wrap: wrap; margin-right: -8px">'.NL.
  buttonToPage('start').
  buttonToPage('kontakt').
  buttonToPage('studium').
  buttonToPage('leistungen').
  buttonToPage('dokumente').
  buttonToPage('notizen').
  '<div style="width: 2em;"></div>'.
  buttonToPage('abschicken').
  '</div>'.
  '</div>'
);

Dazu passend werden im Fragebogen-Layout in der HTMLVorlage im <style>-Bereich CSS-Anweisungen ergänzt:

div.NavButtons button {
  border: 2px solid %color.4%;
  border-radius: 5px;
  padding: 7px 6px;
  margin-bottom: 8px;
  flex-grow: 1;
  margin-right: 8px;
}
div.NavButtons button.currentPage {
  background-color: %color.4%;
  color: white;
}

Der zweite Block (button.currentPage) sorgt dafür, dass der Navigationsknopf der aktuellen Seite farblich hervorgehoben wird. Der Befehl buttonToPage() belegt den Knopf, welcher auf die aktuelle Seite verweist, mit der CSS-Klasse currentPage.

Ausfüllstatus anzeigen

Wenn die Reihenfolge zum Ausfüllen nicht vorgegeben ist, möchte man dem Teilnehmer vielleicht den aktuellen Bearbeitungstatus anzeigen – also welche Seiten bereits vollständig ausgefüllt sind und welche noch nicht.

Navigation mit Anzeige des Ausfüllstatus

Dafür werden im Fragebogen-Layout zunächst weitere CSS-Anweisungen ergänzt, welche hinter vollständigen Seiten einen grünen Haken und hinter unvollständigen Seiten ein rotes Kreuz anzeigen. Die beiden Symbole sind im UTF-8-Zeichensatz definiert und können (nebst Similies und anderen Symbolen) über ihre Zeichen-Codes (2713 und 274C) verwendet werden. Die aktuelle Seite soll kein Symbol zeigen.

div.NavButtons button.complete:after { content: " \2713"; }
div.NavButtons button.incomplete:after { content: " \274C"; }
div.NavButtons button.currentPage:after { content: none; }

Ob die Seite vollständig ausgefüllt ist oder nicht, das muss der PHP-Code unter Zuhilfenahme von value() oder getItems() jeweils überprüfen. Die CSS-Klassen complete und incomplete können dann als vierter Parameter in der Funktion buttonToPage() angegeben werden. Der zweite und dritte Parameter bleibt mit NULL leer.

Der PHP-Code dafür wird in den *PHP-Funktionen* des Fragebogens abgespeichert und könnte wie folgt aussehen:

function navigation() {
    // Completion check
    $cKontakt = (count(array_merge(
        checkItem('KD02', 'KD01_01'),
        checkQst('KD01', [2,3,4,5,6,8]),
        checkItem('KD03', 'KD01_07')
    )) === 0);
 
    $cStart = (
      (count(array_intersect(getItems('KD01', 'valid'), [2,3,4,5,6,8])) == 6) and
      (value('KD02', 'code:ifany') > 0) and
      ((value('KD03', 'code:ifany') > 0) or (value('KD03', 'code:ifany') == -2))
    );
 
    // Hier können weitere Überprüfungen für ...
    // "studium"    -> $cStudium
    // "leistungen" -> $cLeistungen
    // "dokumente"  -> $cDokumente
    // ... ergänzt werden.
 
 
    // Navigation
    html('<div style="border: 2px solid #CCCCCC; border-left: 0 none; border-right: 0 none; padding: 20px 0 12px 0; margin-bottom: 3em;">'.
      '<div class="s2flex NavButtons" style="flex-wrap: wrap; margin-right: -8px">'.NL.
      buttonToPage('start').
      buttonToPage('kontakt', NULL, NULL, ($cKontakt ? 'complete' : 'incomplete')).
      buttonToPage('studium', NULL, NULL, ($cStudium ? 'complete' : 'incomplete')).
      buttonToPage('leistungen', NULL, NULL, ($cLeistungen ? 'complete' : 'incomplete')).
      buttonToPage('dokumente', NULL, NULL, ($cDokumente ? 'complete' : 'incomplete')).
      buttonToPage('notizen').
      '<div style="width: 2em;"></div>'.
      buttonToPage('abschicken').
      '</div>'.
      '</div>'
    );
    option('nextbutton', 'Nächstes Formular');
}
 
 
function checkQst($qID, $items) {
  $fail = [];
  foreach ($items as $item) {
    $answer = value(id($qID, $item), 'code:ifany');
    if (($answer < -3) or ($answer === '')) {
      $text = preg_replace('/:.*/', '', getItemtext($qID, $item));
      $fail[] = $text;
    }
  }
  return $fail;
}
 
function checkItem($varIDs, $textID) {
  $fail = [];
  if (!is_array($varIDs)) {
    $varIDs = [$varIDs];
  }
  foreach ($varIDs as $varID) {
    $answer = value($varID, 'code:ifany');
    if (($answer < -3) or ($answer === '')) {
      $text = preg_replace('/:.*/', '', getItemtext($textID));
      $fail[] = $text;
      // Only one of them
      break;
    }
  }
  return $fail;
}

Hinweis: Das 'code:ifany' im value()-Befehl sorgt dafür, dass keine Fehlermeldung erscheint, wenn die entsprechende Frage noch nicht im Fragebogen abgefragt wurde.

Für das Zuweisen der CSS-Klasse complete oder incomplete ist folgender Code-Schnipsel verantwortlich, der in variierter Form jeweils als vierter Parameter in der Funktion buttonToPage() eingetragen steht:

    ($cKontakt ? 'complete' : 'incomplete')

Die Knöpfe für „start“, „notizen“ und „abschicken“ erhalten in diesem Beispiel keine Statusanzeige.

Wie der PHP-Code zur Überprüfung der Vollständigkeit konkret aussieht, hängt vom Einzelfall ab. Die Funktionen checkQst() und checkItem() können hier hilfreich sein. Diese Funktionen sind außerdem so ausgelegt, dass sie eine Liste fehlender Angaben liefern. So lässt sich auf der Seite „abschicken“ eine Übersicht anzeigen, was noch ausgefüllt werden muss.

Eventuell werden einzelne Überprüfungen auch komplizierter und müssen in separate Funktionen ausgelagert werden.

    $cStudium = (count(checkStudium()) === 0);
    $cLeistungen = (count(checkECTS()) === 0);
    $cDokumente = (count(checkDocs()) === 0);