0 votes
in SoSci Survey (dt.) by s185719 (160 points)

Hallo,

Mein Ziel ist es eine Prozessbeobachtung mittels Sosci zu realisieren. Dabei wird das Flussdiagramm als SVG umgewandelt und mittels der "SVG als Auswahl (Mehrfachauswahl)" eingebunden. Das klappt auch.

Die registrierung von Zeiten für die einzelnen Elemente ist nicht so einfach. Ich habe dazu im Forum diese Beiträge gefunden:

https://support.soscisurvey.de/?qa=15856/zeitmessung-von-variablen&show=15907
https://support.soscisurvey.de/?qa=15918/zeit-von-variablen-nehmen-durch-click-event

Es scheint also prinzipiell möglich zu sein. Wie gehe ich am Besten vor?
Sie schrieben ja selbst, dass es bei der Mehrfachauswahl etwas schwieriger wird.

Am Ende würde ich gerne einen absoluten Zeitpunkt zu einem Klick auf ein Element in der SVG registrieren und in eine interne Variable schreiben.

Meine Idee ist`den Code aus Thread 15918 anzupassen. Bisher ohne Erfolg.

2 Answers

0 votes
by SoSci Survey (305k points)

Wie gehe ich am Besten vor?

Lesen Sie sich ein wenig in JavaScript ein - spezifisch in Events.

Und zwar müssen Sie an die Elemente, für die Sie sich interessieren, ein "click"-Event hängen. In Ihrem Fall sind das aber Bestandteile des SVG. Das SVG wiederum lädt in einem eigenen <frame>. Das Kunststück ist also, erst einmal das Element für JavaScipt verfügbar zu machen.

SoSci Survey nutzt dafür in der SVG-Auswahl folgenden Code:

var iFrame = document.getElementById("SV01_SVG");
var svg = S2SVGSelect.iframeRef(iFrame);
var svgNode = svg.getElementById("h13");

Die Kennungen für die Frage "SV01_SVG" und die ID des SVG-Elements "h13" müssen natürlich angepasst werden. Und an den svgNode kann man dann einen "click"-Eventhandler hängen:

svgNode.addEventListener("click", ...);

Oder Sie nutzen die Methode .registerElement() aus der LatencyTimer-Klasse:

var stopWatch = new LatencyTimer();
stopWatch.registerElement(svgNode, "RT01_01", false);

Hier würden Sie den Variablennamen für die interne Variable "RT01_01" natürlich wieder anpassen. Das "false" hinten bedeutet, dass der erste Klick auf der Seite nicht aufgezeichnet werden soll.

Wenn Sie lieber die absolute Zeit haben, können Sie aber auch direkt über den click gehen:

svgNode.addEventListener("click", function() {
    document.getElementById("RT01_01").value = Date.now();
});

Wie gesagt ... es ist nicht von Nachteil, sich ein wenig in JavaScript einzulesen :)

by s185719 (160 points)
edited by s185719
Ganz und gar nicht zu viel versprochen!

Interessant, ich freue mich auf den Tag an dem ich verstehe, warum sich dafür entschieden wurde, dass eine Funktion in einer Funktion unabhängig von der umliegenden Funktion abgearbeitet wird.
Ich vermute, dass die Klammern die Hierarchie abbilden {} > () und die () immer gleichwertig sind, egal ob sie verschachtelt sind.

Aber wenn man es weiß kann man ja damit umgehen. Vielen Dank für die Erklärung, warum die version mit function{} dann funktioniert.

Ich hab noch einiges vor mir. Gibt es einen Befehl ein SVG Element grafisch abzuwählen? Aus der Frageseite entnehme ich SelBox.svg.selected als Kanditaten. Die Idee ist eine Resetfunktion für die Variable anzubieten, die dann natürlich auch das noch markierte Feld abwählt... dann muss ich auch sicher mit Schleifen arbeiten, um das nochmalige unabsichtliche Verändern der Variable zu verhindern.
by SoSci Survey (305k points)
> Ich vermute, dass die Klammern die Hierarchie abbilden {} > ()

Nicht ganz, nein.

Eine runde Klammer ist entweder ein Funktionsaufruf oder (!) eine Schachtelung bei Berechnungen, also ganz klassiche wie in Mathe, aber da werden in JavaScript immer runde Klammern verwendet.

Die geschweiften Klammern schachteln JavaScript-Code. Diese werden z.B. nach einem IF und zur Definition einer Funktion (also deren Inhalt) eingesetzt.

> Gibt es einen Befehl ein SVG Element grafisch abzuwählen?

Das sollte eigentlich möglich sein, wenn Sie unter "Fragebogen zusammenstellen" -> "Einstellungen" das Häkchen setzen, dass ausgewählte Optionen wieder abgewählt werden können.
by s185719 (160 points)
edited by s185719
Ok die Eklärung ist einleuchtend.

Die Option in der Frage selbst, soweit ich es richtig verstehe, ermöglicht, dass eine einmal durch Mausinteraktion angewählte Option auch wieder sichtbar durch ein weiteres Klicken abgewählt werden kann. Gibt es eine Möglichkeit, die Option auch per javascript abzuwählen. Bzw. würde die Seite dynamisch angepasst, wenn ich die Fragenvariable über JS manipuliere? Das könnte ich wirklich gleich noch einmal ausprobieren. Allerdings bin ich von dieser Idee konzeptionell jetzt auch wieder weg. Das wäre eher eine kleine Fingerübung.

Vielmehr habe ich den Code etwas verkürzt und es läuft auch noch. Allerdings würde ich nun gerne die Clickzeiten in der internen Variable als Array speichern und nur den letzten Wert sichtbar für den Nutzer anzeigen.

document.getElementById(InterneVariable).push(time);

Allerding wird der Befehl wohl nicht gekannt:
Uncaught TypeError: document.getElementById(...).push is not a function

Kann ich / muss ich die interne Variable als array deklarieren?
by s185719 (160 points)
Ich habe es jetzt iterativ gelöst mit:

document.getElementById(InterneVariable).value = document.getElementById(InterneVariable).value + ";" + time;

Jetzt mache ich mich daran, dass der letzte Wert, also die letzten 8 Zeichen (hh:mm:ss) noch ausgegeben werden können.
by SoSci Survey (305k points)
push() gibt es nur für Arrays - aber der Wert einer internen Variable (hidden input) ist immer Text. Deshalb ist Ihre Lösung korrekt. Eine kürzere Schreibweise wäre das += (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Addition_assignment)

document.getElementById(InterneVariable).value += ";" + time;

Angesichts der länge der Kommentare zu der Frage würde ich vorschlagen, dass Sie neue JavaScript-Vorhaben in einer neuen Frage posten :)
0 votes
by s185719 (160 points)

Hier der laufende Code, falls jemand nach etwas Ähnlichem sucht:

enter <script type="text/javascript">
<!--

window.addEventListener("load", function() {
let iFrame = document.getElementById("EV01_SVG");
let svg = S2SVGSelect.iframeRef(iFrame);
let svgNode01 = svg.getElementById("path4153");
let svgNode02 = svg.getElementById("path4163");
//... und so weiter

let BegleitText01 = " (Event A)";  
let BegleitText02 = " (Event B)";
//... und so weiter

let date;
let hours; 
let minutes;
let seconds;
let milliseconds;
let time;

/* 
Verwendete Variablen:
question('EV01');  // Das ist das SVG
question('EV02');  // Das ist die Interne Variable, in der die felderspezifischen Zeiten abgespeichert werden. Im Code mit dem Platzhalter InterneVariable assoziiert.
question('EV03', 'number=no');  // Das ist eine Frage vom Fragetyp Texteingabe offen, in der die felderspezifischen Zeiten im Fragebogen werden (EV03_01) und das Ereignis kommentiert werden kann (EV03_02). Im Code mit dem Platzhalter EventLogTextfeldAnzeige assoziiert.
question('EV04');  // Das ist die Interne Variable, in der alle Ereignisse und Kommentare kontinuierlich abgespeichert werden (EV04_01.

*/

function ZeitKonvertieren(date) {
    // Aus der Variable date die Stunden, Minuten, Sekunden und Millisekunden auslesen und in einem String kombinieren
    hours = String(date.getHours());
    if (hours.length < 2) hours = "0" + hours;
    minutes = String(date.getMinutes());
    if (minutes.length < 2) minutes = "0" + minutes;
    seconds = String(date.getSeconds());
    if (seconds.length < 2) seconds = "0" + seconds;
    milliseconds = String(date.getMilliseconds());
    if (milliseconds.length < 2) milliseconds = "00" + milliseconds;
    if (milliseconds.length < 3) milliseconds = "0" + milliseconds;
    time = hours + ":" + minutes + ":" + seconds + ":" + milliseconds;
};
function ZeitInInterneVariable(InterneVariable) {
    // Die aktuelle Zeit in die Variable date schreiben
    date = new Date();
    // Da die Funktion ZeitKonvertieren die schon bestehende übergeordnete Variable time befüllt, kann diese gleich weiterverwendet werden 
    ZeitKonvertieren(date);
    // Den letzten Wert von time in an die schon bestehenden Werte in InterneVariable anhängen
    document.getElementById(InterneVariable).value = document.getElementById(InterneVariable).value + ";" + time;
};

function NurLetzteUhrzeit(InterneVariable) {
    // Gibt nur die letzte Zeit aus dem String von InterneVariable zurück
    return document.getElementById(InterneVariable).value.slice(document.getElementById(InterneVariable).value.length - 12);
};

function ZeitInEventLog(BegleitText, EventLogTextfeldAnzeige, InterneVariable) {
    //führt die Funktionen ZeitInInterneVariable und NurLetzteUhrzeit aus und zeigt auf dem Fragebogen unter EventLogTextfeldAnzeige das letzte Event an
    ZeitInInterneVariable(InterneVariable);
    document.getElementById(EventLogTextfeldAnzeige).value = NurLetzteUhrzeit(InterneVariable) + BegleitText;

};

function LogMitKommentaren() {
    //ließt die Felder von EV03_01 und EV03_02 aus, kombiniert sie und hängt sie dann an die bestehenden Werte von EV04_01 an
    document.getElementById("EV04_01").value = document.getElementById("EV04_01").value + ";" + document.getElementById("EV03_01").value + " Kommentar: " + document.getElementById("EV03_02").value;
    document.getElementById("EV03_02").value = "";
}
// Funktionen die beim Klicken auf das Element svgNode ausgelöst werden    
svgNode01.addEventListener("click", function() {LogMitKommentaren();});
svgNode02.addEventListener("click", function() {LogMitKommentaren();});
//... und so weiter
svgNode01.addEventListener("click", function() {ZeitInEventLog(BegleitText01, "EV03_01", "EV02_01");});
svgNode02.addEventListener("click", function() {ZeitInEventLog(BegleitText02, "EV03_01", "EV02_02");});
//... und so weiter

  }
 );

 // -->

by s185719 (160 points)
Und hier noch die xml für die verwendeten Fragen. Diese vor dem JavaSript mit z.B. PHP einfügen.:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE surveyContent SYSTEM "https://www.soscisurvey.de/templates/doctype.survey.dtd">
<surveyContent version="2.4">
<program>sosci</program>
<version>3.2.32</version>
<timestamp>2021-06-15 16:45:06</timestamp>
<title>SVG Events</title>
<description />
<language>ger</language>
<attributes.specific program="ofb">
<attr id="language">ger</attr>
</attributes.specific>
<section>
<title>SVG Events</title>
<attributes.specific program="ofb">
<attr id="id">EV</attr>
</attributes.specific>
<question>
<description>Boxen</description>
<class>svg-checkbox</class>
<title />
<explanation />
<inputPosition>right</inputPosition>
<order>default</order>
<attributes.specific program="ofb">
<attr id="id">1</attr>
<attr id="pos">1</attr>
<attr id="scale.metrics.width">200</attr>
<attr id="scale.metrics.height">114</attr>
<attr id="scale.graphics.scale">oFb://svg-select.direction</attr>
<attr id="shading">default</attr>
</attributes.specific>
<item>
<text>erste Nadel</text>
<attributes.specific program="ofb">
<attr id="id">1</attr>
<attr id="pos">1</attr>
<attr id="svgID">path4153</attr>
</attributes.specific>
</item>
<item>
<text>zweite Nadel</text>
<attributes.specific program="ofb">
<attr id="id">2</attr>
<attr id="pos">2</attr>
<attr id="svgID">path4163</attr>
</attributes.specific>
</item>
</question>
<question>
<description>Event Time Boxes</description>
<class>internal</class>
<title />
<explanation />
<inputPosition>right</inputPosition>
<order>default</order>
<attributes.specific program="ofb">
<attr id="id">2</attr>
<attr id="pos">2</attr>
</attributes.specific>
<item>
<text>BoxA</text>
<attributes.specific program="ofb">
<attr id="id">1</attr>
<attr id="pos">1</attr>
</attributes.specific>
</item>
<item>
<text>BoxB</text>
<attributes.specific program="ofb">
<attr id="id">2</attr>
<attr id="pos">2</attr>
</attributes.specific>
</item>
</question>
<question>
<description>Letzter Log Display</description>
<class>text</class>
<title />
<explanation />
<inputPosition>right</inputPosition>
<order>default</order>
<attributes.specific program="ofb">
<attr id="id">3</attr>
<attr id="pos">3</attr>
</attributes.specific>
<item>
<text>Letzter Log:</text>
<attributes.specific program="ofb">
<attr id="id">1</attr>
<attr id="pos">1</attr>
</attributes.specific>
</item>
<item>
<text>Kommentar:</text>
<attributes.specific program="ofb">
<attr id="id">2</attr>
<attr id="pos">2</attr>
</attributes.specific>
</item>
</question>
<question>
<description>kontinuierlicher Log mit Kommentaren</description>
<class>internal</class>
<title />
<explanation />
<inputPosition>right</inputPosition>
<order>default</order>
<attributes.specific program="ofb">
<attr id="id">4</attr>
<attr id="pos">4</attr>
</attributes.specific>
<item>
<text>Event Log für alle mit Kommentar</text>
<attributes.specific program="ofb">
<attr id="id">1</attr>
<attr id="pos">1</attr>
</attributes.specific>
</item>
</question>
</section>
</surveyContent>

Willkommen im Online-Support von SoSci Survey.

Hier bekommen Sie schnelle und fundierte Antworten von anderen Projektleitern und direkt von SoSci Survey.

→ Eine Frage stellen


Welcome to the SoSci Survey online support.

Simply ask a question to quickly get answers from other professionals, and directly from SoSci Survey.

→ Ask a Question

...