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 (302k 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)
Super, vielen Dank!

Leider komme ich noch nicht zum Ziel. Ihre Lösung sieht elegant aus, ich schätze ich habe sie noch nicht ganz richtig umgesetzt. Es wird derzeit noch keine Zeit aufgezeichnet. Im Moment habe ich das hier:

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

//Wie wird in Ihrem Beispiel das "SV01_SVG" übersetzt? in XXX_SVG oder XXX_XX so wie unten?
 
var iFrame = document.getElementById("EV01_01");

// Ich habe in google nichts zu dieser Funktion S2SVGSelect gefunden, können Sie eine gute Ressource empfehlen, wo so etwas dokumentiert ist?
var svg = S2SVGSelect.iframeRef(iFrame);

// Zur Vereinfachung habe ich das Preset "Blickrichtung 180° Aufsicht" genommen, ist der ID Knoten, der in Sosci bzw. Inkscape angezeigt wird hier anzugeben. Oder muss zusätzlich auf eine Überliegende Struktur verwiesen werden?
var svgNode = svg.getElementById("path4153");

svgNode.addEventListener("click", function() {
    document.getElementById("EV02_01").value = Date.now();
}
);
 
// -->
</script>
by SoSci Survey (302k points)
Was sagt denn die JavaScript-Fehlerkonsole Ihres Browsers?
https://www.soscisurvey.de/help/doku.php/de:create:javascript#fehler_finden
by s185719 (160 points)
Die Konsole ist eine klasse Sache, guter Tipp!. Sie gab zuerst aus:

Uncaught TypeError: svg is undefined

Das heißt also, dass es erstmal so heißen muss

var iFrame = document.getElementById("EV01_SVG");

Der nächste Error betrifft  entweder var svg = S2SVGSelect.iframeRef(iFrame) oder die ID richtig?:

Uncaught TypeError: svgNode is null
by SoSci Survey (302k points)
Das iframeRef() ist eine Methode, die für die SVG-Auswahl das DVG im <iframe> findet. Das sollte passen. Wenn Sie "svg" in die Konsole tippen, dann sollte das <iframe> dort angezeigt werden.

> svgNode is null

Das könnte bedeuten, dass folgende Zeile nicht funktioniert:

svg.getElementById("path4153");

Geben Sie zuerst "svg" in die Konsole ein und prüfen Sie was angezeigt wird und anschließend nochmal die obige Zeile.
by s185719 (160 points)
Bei Eingabe von "svg" in der Ausführen-Konsole von Firefox, gibt er mir eine lange html und folgende Warnings:

onmozfullscreenchange sollte nicht mehr verwendet werden. svg-select.direction.svg

onmozfullscreenerror sollte nicht mehr verwendet werden. svg-select.direction.svg

"get" oder "set" einer Eigenschaft mit [LenientThis] ignoriert, weil das "this"-Objekt fehlerhaft ist. svg-select.direction.svg
by SoSci Survey (302k points)
Das klingt gut, das svg scheint demnach gefunden zu werden. Wenn

svg.getElementById("path4153");

anschließend nicht funktioniert, dann könnte es sein, dass die ID des Elements im SVG nicht korrekt ist. Verwenden Sie in der Entwicklerkonsole doch einmal den Inspektor, um das zu prüfen.

Sie können gerne auch mal einen Pretest-Link direkt (!) zur betroffenen Seite posten.
by s185719 (160 points)
Im Inspektor finde ich das gewünschte Element, dort wird auch die ID "path4153" angezeigt.

Ich vermute, dass als Referenz noch der umgebene "layer1" angegeben werden muss?

Der Pretestink lautet: https://www.soscisurvey.de/test266448/?act=oFURrbRs3tnRA4ZUe294ReZ6

Diesen Code finde ich im Inspektor:

<g xmlns="http://www.w3.org/2000/svg" inkscape:label="Ebene 1" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" inkscape:groupmode="layer" id="layer1" transform="translate(0,-938.36218)">
    <path inkscape:transform-center-y="-38.296844" inkscape:transform-center-x="-38.237731" style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 169.93259,969.78465 a 11.519366,11.519207 45 0 0 -16.29141,-5e-5 11.519366,11.519207 45 0 0 -2.69358,12.00362 l -23.02983,26.39328 -24.79778,28.4157 28.41577,-24.7978 26.39191,-23.02843 a 11.519366,11.519207 45 0 0 12.00504,-2.69484 11.519366,11.519207 45 0 0 -1.2e-4,-16.29148 z" id="path4147" inkscape:connector-curvature="0"/>
    <path inkscape:connector-curvature="0" id="path4149" d="m 99.933926,940.82489 a 11.519366,11.519207 0 0 0 -11.519802,11.51973 11.519366,11.519207 0 0 0 6.583193,10.39249 l 2.378332,34.94743 2.558256,37.62756 2.558285,-37.62762 2.37833,-34.94547 a 11.519366,11.519207 0 0 0 6.5833,-10.39439 11.519366,11.519207 0 0 0 -11.519894,-11.51973 z" style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" inkscape:transform-center-x="0.04176616" inkscape:transform-center-y="-51.732131"/>
    <path inkscape:transform-center-y="-38.237763" inkscape:transform-center-x="38.296858" style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 29.959752,969.84378 a 11.519207,11.519366 45 0 0 -5.1e-5,16.29141 11.519207,11.519366 45 0 0 12.00362,2.69358 l 26.3933,23.02983 28.415677,24.7977 -24.797777,-28.4157 -23.028445,-26.3919 a 11.519207,11.519366 45 0 0 -2.694848,-12.00504 11.519207,11.519366 45 0 0 -16.291476,1.2e-4 z" id="path4151" inkscape:connector-curvature="0"/>
    <path inkscape:connector-curvature="0" id="path4153" d="m 0.99999238,1039.8424 a 11.519207,11.519366 0 0 0 11.51973062,11.5198 11.519207,11.519366 0 0 0 10.39249,-6.5832 l 34.947444,-2.3783 37.62754,-2.5583 -37.62761,-2.5582 -34.945476,-2.3784 a 11.519207,11.519366 0 0 0 -10.39439,-6.5833 11.519207,11.519366 0 0 0 -11.51972862,11.5199 z" style="color: rgb(0, 0, 0); clip-rule: nonzero; display: inline; overflow: visible; visibility: visible; opacity: 1; isolation: auto; mix-blend-mode: normal; color-interpolation: srgb; color-interpolation-filters: linearrgb; fill: rgb(255, 255, 255); fill-opacity: 1; fill-rule: nonzero; stroke: rgb(0, 0, 0); stroke-width: 2px; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-dasharray: none; stroke-dashoffset: 0px; stroke-opacity: 1; image-rendering: auto; shape-rendering: auto; text-rendering: auto;" inkscape:transform-center-x="51.732145" inkscape:transform-center-y="0.04173366"><title>erste Nadel</title></path>
    <path inkscape:transform-center-y="-0.041766732" inkscape:transform-center-x="-51.732103" style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 198.95148,1039.7588 a 11.519207,11.519366 0 0 0 -11.51973,-11.5198 11.519207,11.519366 0 0 0 -10.39249,6.5832 l -34.9474,2.3783 -37.62766,2.5583 37.62766,2.5583 34.94551,2.3783 a 11.519207,11.519366 0 0 0 10.39438,6.5833 11.519207,11.519366 0 0 0 11.51973,-11.5199 z" id="path4155" inkscape:connector-curvature="0"/>
    <path inkscape:connector-curvature="0" id="path4157" d="m 191.40869,1001.9032 a 11.519366,11.519207 67.51103 0 0 -15.05007,-6.23737 11.519366,11.519207 67.51103 0 0 -7.08407,10.05777 l -31.38005,15.565 -33.78763,16.7565 35.74476,-12.029 33.19773,-11.1694 a 11.519366,11.519207 67.51103 0 0 12.12207,2.1067 11.519366,11.519207 67.51103 0 0 6.23726,-15.0502 z" style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" inkscape:transform-center-x="-48.220155" inkscape:transform-center-y="-23.383254"/>
    <path inkscape:transform-center-y="-48.245388" inkscape:transform-center-x="-23.322363" style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 137.83108,948.35026 a 11.519366,11.519207 22.51103 0 0 -15.05251,6.2315 11.519366,11.519207 22.51103 0 0 2.10274,12.12113 l -11.18293,33.19509 -12.04283,35.74012 16.76958,-33.7811 15.57638,-31.3723 a 11.519366,11.519207 22.51103 0 0 10.06126,-7.08194 11.519366,11.519207 22.51103 0 0 -6.23169,-15.0525 z" id="path4159" inkscape:connector-curvature="0"/>
    <path inkscape:connector-curvature="0" id="path4161" d="m 62.078329,948.36768 a 11.519207,11.519366 67.51103 0 0 -6.237396,15.05007 11.519207,11.519366 67.51103 0 0 10.057795,7.08407 l 15.564997,31.38008 16.756479,33.7876 -12.028961,-35.74482 -11.169416,-33.19767 a 11.519207,11.519366 67.51103 0 0 2.106697,-12.12207 11.519207,11.519366 67.51103 0 0 -15.050195,-6.23726 z" style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" inkscape:transform-center-x="23.383264" inkscape:transform-center-y="-48.220147"/>
    <path inkscape:transform-center-y="-23.322364" inkscape:transform-center-x="48.245376" style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" d="m 8.5253604,1001.9453 a 11.519207,11.519366 22.51103 0 0 6.2315016,15.0525 11.519207,11.519366 22.51103 0 0 12.121129,-2.1028 l 33.195197,11.183 35.740061,12.0428 -33.781122,-16.7696 -31.372324,-15.5764 a 11.519207,11.519366 22.51103 0 0 -7.081939,-10.0612 11.519207,11.519366 22.51103 0 0 -15.0525036,6.2317 z" id="path4163" inkscape:connector-curvature="0"/>
  </g>
by SoSci Survey (302k points)
Danke für den Pretest-Link. Das Problem scheint die Zeit zu sein ... also der Zeitverlauf. Das SVG ist noch nicht geladen, wenn Ihr Code läuft. Sorgen Sie bitte mit nachfolgendem Code dafür, dass Ihr Code erst nach dem laden der Seite ausgeführt wird.

window.addEventListener("load", function() {
    var iFrame = document.getElementById("EV01_SVG");
    var svg = S2SVGSelect.iframeRef(iFrame);
    var svgNode = svg.getElementById("path4153");
    console.log(svgNode);
    // Hier dann weiterer Code, wenn das soweit läuft
});


> // Ich habe in google nichts zu dieser Funktion S2SVGSelect gefunden, können Sie eine gute Ressource empfehlen, wo so etwas dokumentiert ist?

Das ist die interne Bibliothek der SVG-Auswahl, die Sie hier zur Vereinfachung nutzen können. Hinter dem Suchen und Finden des SVGs im iFrame steckt ein wenig mehr Code.
by s185719 (160 points)
Super, das klappt! Vielen Dank. Der Code sieht nun so aus und ich mache mich jetzt noch daran ihn weiter anzupassen (für mehrere svgNodes, nur x-mal klickbar, Zeiten anzeigen, etc.).

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

window.addEventListener("load", function() {
    var iFrame = document.getElementById("EV01_SVG");
    var svg = S2SVGSelect.iframeRef(iFrame);
    var svgNode = svg.getElementById("path4153");
    
    // Funktion die beim Klicken auf das Element svgNode ausgelöst wird    

    svgNode.addEventListener("click", function() {
        
        // Die aktuelle Zeit in die Variable date schreiben

        var date = new Date();

        // Aus der Variable date die Stunden, Minuten und Sekunden auslesen und in einem String kombinieren

        var hours = String(date.getHours());
        if (hours.length < 2) hours = "0" + hours;
        var minutes = String(date.getMinutes());
        if (minutes.length < 2) minutes = "0" + minutes;
        var seconds = String(date.getSeconds());
        if (seconds.length < 2) seconds = "0" + seconds;
        var time = hours + ":" + minutes + ":" + seconds;

        // die interne Variable EV02_02 finden und als Variable input definieren

        var input = document.getElementById("EV02_02");
 
        // Den Wert von time in input hineinschreiben
        input.value = time;

        // Alternative um die Systemzeit unformatiert in die Variable EV02_01 zu schreiben

        document.getElementById("EV02_01").value = Date.now();
    }
    )
}
);
 
// -->
</script>
by s185719 (160 points)
Ich habe mir Ihren Tipp zu Herzen genommen und näher mit Javascript befasst. Es reicht nur noch nicht zu verstehen, warum folgender Code nur eine Zeit in die interne Variablen schreibt. Es handelt sich um die Zeit an der die Seite fertig lud.

<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");

    let date;
    let hours;
    let minutes;
    let seconds;
    let time;
    let ZeitSpeicher;

    console.info("Inhalt nach Variablen Definition:", EV02_01, EV02_02);

    function ZeitKonvertieren(date) {
        // Aus der Variable date die Stunden, Minuten und Sekunden 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;
        time = hours + ":" + minutes + ":" + seconds;
    };

    console.info("Inhalt nach Zeitkonvertieren Funktionsdefinition:", EV02_01, EV02_02);

    function ZeitInVariable(InterneVariable) {
        // Die aktuelle Zeit in die Variable date schreiben
        date = new Date();
        ZeitSpeicher = document.getElementById(InterneVariable);
        // Da die Funktion ZeitKonvertieren die schon bestehende übergeordnete Variable time befüllt, kann diese gleich weiterverwendet werden
        ZeitKonvertieren(date);
        // Den Wert von time in input hineinschreiben
        ZeitSpeicher.value = time;
     };

    console.info("Inhalt nach ZeitInVariable Funktionsdefinition:", EV02_01, EV02_02);
    
    // Funktion die beim Klicken auf das Element svgNode ausgelöst wird    

    svgNode01.addEventListener("click", ZeitInVariable("EV02_01"));
    svgNode02.addEventListener("click", ZeitInVariable("EV02_02"));

    console.info("Inhalt nach EventListener Funktion:", EV02_01, EV02_02);
}
);
 
// -->
</script>
by SoSci Survey (302k points)
Wenn ich den Fehler scuhen wollte, würde ich als erstes prüfen, ob die "click" Events für svgNode01 und svgNode02 überhaupt ausgelöst werden. Also würde ich unten ergänzen:

    svgNode01.addEventListener("click", function() { console.log("click1"); });
    svgNode02.addEventListener("click", function() { console.log("click2"); });

Wenn das klappt, dann kann man innerhalb der Funktion ZeitInVariable() weitersuchen.
by s185719 (160 points)
Ja das klappt, die Klicks werden ausgelöst.

Mir ist noch nicht klar, wie aber vor dem Auslösen der Klicks schon die Variablen befüllt werden können. Die Funktion ZeitInVariable kann doch erst richtig ausgeführt werden, wenn der Platzhalter InterneVariable spezifiziert mitgegeben wird oder?
by s185719 (160 points)
Ich habe Ihren Tipp übertragen und dabei festgestellt, dass sobald ich die Funktion ZeitInVariable nochmals in eine function() direkt in die Funktion addEventListener schreibe, wie gewünscht einzelne Zeiten in die interne Variable gespeichert werden. Mir erschließt sich nur wirklich nicht, was daran anders sein soll, als die Funktion direkt aufzurufen.

Hier der letzte Codezusatz:

    svgNode01.addEventListener("click", function() {ZeitInVariable("EV02_01");});
    svgNode02.addEventListener("click", function() {ZeitInVariable("EV02_02");});

    svgNode01.addEventListener("click", function() {console.info("Inhalt nach EventListener Funktion:", EV02_01, EV02_02);});
by SoSci Survey (302k points)
Ah, jetzt verstehe ich die Problematik erst richtig.

Okay ... dann habe ich für Sie noch was über JavaScript zu lernen. Etwas ziemlich gemeines. Sehen wir uns diese Zeile man an:

svgNode01.addEventListener("click", ZeitInVariable("EV02_01"));

Was passiert hier? Es wird eine Funktion addEventListener() aufgerufen und eine Funktion ZeitInVariable(). Wie bitte? Ja, genau, weil da eine Klammer dahinter steht, wird die Funktion tatsächlich direkt aufgerufen. Sie gibt nichts zurück, deshalb passiert beim Klick später dann auch nichts mehr.

Die Lösung ist, dass Sie keinen Funktionsaufruf, sondern eine Funktion übergeben. Das könnte z.B: so aussehen:

function store1() {
  ZeitInVariable("EV02_01")
}
svgNode01.addEventListener("click", store1);

Hier steht das "store1" ohne Klammern in dem Aufruf von addEventListener(). Es wird also die Funktion übergeben und beim Klick wird diese dann ausgeführt. Aber der Name store1 ist natürlich überflüssig, deshalb kann man es auch wie folgt schreiben:

svgNode01.addEventListener("click", function() {
  ZeitInVariable("EV02_01")
});

Nicht übrsichtlich, aber man gewöhnt sich daran. Es gäbe auch nich eine schicke Möglichkeit, die Sie unter dem Namen "JavaScript Closure" finden. Aber dafür ist hier unten in den Kommentaren nicht genug Platz.

So ... habe ich zu viel versprochen? :)
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 (302k 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 (302k 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

...