0 votes
in SoSci Survey (dt.) by s209215 (175 points)
edited by s209215

Lieber SosciSurvey-Support

Ich würde gerne einen Schieberegler mit mehreren Ausweichmöglichkeiten kombinieren. Dabei soll ein Klick auf den Schieberegler möglicherweise bereits ausgewählte Ausweichmöglichkeiten aufheben. Andersherum soll natürlich auch ein Klick auf eine Auswahlmöglichkeit den Schiebereglerknopf verschwinden lassen.

Ich habe mich dazu auf die Erläuterung zur "Anbindung einer weiß nicht Option" beim Schieberegler gestützt. Leider funktioniert mein Skript nicht (d.h. Schieberegler/Ausweichmöglichkeit werden nicht abgewählt) und es gelingt mir nicht das Skript zu debuggen.

Der Link zur Pretest-Seite lautet:
https://survey.hochschule-rhein-waal.de/2semb2022/?act=5YegnGkgKXco5a3nQbyVTFsk

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

// Define questions
var sliderID = "KP09";  // BeispielID fürs erste Item: KP09_01_scale (class = slider); nur der Regler: KP09_01_button (class = sliderButton)
var scaleID = "KP08";	// BeispielID fürs dritte Item: KP08_03; Option 1: kenne ich nicht, Option 2: Weiß ich nicht --> KP08_031 / KP08_032

// Define items to tune
var items = [1,2,3,4,5,6,7,8]; // hier alle Zahlen entsprechend der Anzahl Items auflisten

/*
// Define number of items	// Versuch die Anzahl der items nur durch n_items anzugeben
var n_items = 8;
var item_i = 1

// Create list of items to tune
var items = [];
while ((item_i <= n_items){
	items.push(item_i++);
}
*/

// Define scale options to disable the slider
var scaleDK = [1,2]; 
//// Define scale options to enable the slider
//var scaleVA = [3];
// Remember slider values before disabling
var sliderValues = []
	 
// Convenience function [to build objectID]
function makeID(questionID, item, option) {
  var itemID = String(item); // item = Zahl zwischen 1 und 8 (= Anzahl der Items)
  if (itemID.length < 2) { // wenn item eine einstellige Zahl
	itemID = "0" + itemID; // füge 0 davor um zweistellige Zahl zu erhalten
  }
  var itemFull = questionID + "_" + itemID; // füge Slider/scaleIDs zusammen mit item Id: itemFull also jetzt sowas wie KP08_01 
  if (questionID == sliderID) {  //für SliderIDs brauche ich noch die Hinzufügung von "_scale"; deswegen Kontrolle, ob die an die Funktion gegebene questionID gleich der sliderID (KP09) ist, sonst handelt es sich um die Skala (KP08); 
	  return itemFull + "_scale"; // gib vollständige SliderId raus: KP09_01_scale
  } else {
  return itemFull + option;
  }
  
  /*if (!option) {	// Original code: wenn es keine Option gibt (wie beim Schieberegler) wird die fullId als KP09_01 rausgegeben; 
	return itemFull; 
  } */
}
	 
// Function to care about setting the correct values
function refreshSlider(item, status) {
  var slider = SoSciSliders.getSlider(makeID(sliderID, item));

  // Optionally reset slider value
  
  if (status) {
	if ((slider.value == -9) && sliderValues[item]) {
	  slider.value = sliderValues[item];
	}
  } else {
	sliderValues[item] = slider.value;
	slider.value = -9;
  }

  // Optionally disable slider
  slider.disabled = !status;
}

// Function to deselect the scale options if slider is used
function refreshScale(item) {
  /*if (scaleVA.length < 1) {
	return;
  }*/
  var slider = SoSciSliders.getSlider(makeID(sliderID, item));
  if (slider.value > 0) {
	  for (var ij=0; ij<scaleDK.length; ij++) {
		  var option = scaleDK[ij];
		  var scaleOption = document.getElementById(makeID(scaleID, item, option));
		  scaleOption.checked = false;
		  }
	 }
}


/* // Function to select the (first) enabled-option if slider is used
function refreshScale(item) {
  if (scaleVA.length < 1) {
	return;
  }
  var slider = SoSciSliders.getSlider(makeID(sliderID, item));
  if (slider.value > 0) {
	var option = scaleVA[0];
	var scaleOption = document.getElementById(makeID(scaleID, item, option));
	scaleOption.checked = true;
  }
}
*/


// Attach events to the scale
SoSciTools.attachEvent(window, "load", function() {
 
  for (var ii=0; ii<items.length; ii++) {
	var item = items[ii];
	for (var io=0; io<scaleDK.length; io++) {
	  var option = scaleDK[io];
	  var scaleOption = document.getElementById(makeID(scaleID, item, option));
	  // This one employs a closure
	  SoSciTools.attachEvent(scaleOption, "click", function(item, status) {
		return function(evt) {
		  refreshSlider(item, status);
		}
	  }(item, false));
	}
	
	/*
	// Same for enabling options
	for (var io=0; io<scaleVA.length; io++) {
	  var option = scaleVA[io];
	  var scaleOption = document.getElementById(makeID(scaleID, item, option));
	  // This one employs a closure
	  SoSciTools.attachEvent(scaleOption, "click", function(item, status) {
		return function(evt) {
		  refreshSlider(item, status);
		}
	  }(item, true));
	}
	*/
	
	// And also attach event to the sliders
	var slider = SoSciSliders.getSlider(makeID(sliderID, item));
	slider.addEventListener("click", function(item) {
	  return function(evt) {
		refreshScale(item);
	  }
	}(item));
  }
 
});

-->
</script>

Für Ihre Unterstützung wäre ich sehr dankbar.

by SoSci Survey (302k points)
Der Pretest-Link oben ist leider nicht gültig: https://www.soscisurvey.de/help/doku.php/de:survey:pretest

> es gelingt mir nicht das Skript zu debuggen.

Wenn die Fehlerkonsole im Browser stumm bleibt, dann liegt es i.d.R. daran, dass die Funktion überhaupt nicht aufgerufen wird. Schreiben Sie zur Kontrolle bei

SoSciTools.attachEvent(scaleOption, "click", function(item, status) {

doch mal ein

console.log("Hallo!");

mit hinein.
by s209215 (175 points)

Vielen Dank für die Antwort. Ich habe den Pretestlink in der ursprünglichen Frage überarbeitet und er sollte jetzt funktionieren.
Tatsächlich scheint das Skript gar nicht bis zur entsprechenden Stelle zu kommen. Die erste Fehlermeldung, die ich bekomme ist "There is no display position [none] preset", aber ganz erklären kann ich sie mir nicht. Bedeutet dies, dass ich zu Beginn des Skripts explizit angeben muss, dass Schieberegler und Skala angezeigt werden, obwohl sie dies bereits tun?

by SoSci Survey (302k points)
Danke für den korrigierten Link. An der Fehlermeldung ist SoSci Survey schuld. Auf www.soscisurvey.de haben wir diesen Fehler nun behoben - auf Ihrem Server eilt es aber nicht, denn auf die korrekte Script-Ausführung hat er keinen Einfluss.

Der Knackpunkt im Script ist aktuell an dieser Stelle, korrekt?

console.log("Nichts sollte angekreuzt sein");

Bitte ergänzen Sie das einmal wie folgt:

console.log("Nichts sollte angekreuzt sein", scaleOptionA, scaleOptionB);

Dann können wir mal prüfen, ob da die richtigen Auswahlfelder geprüft werden.

1 Answer

+1 vote
by s209215 (175 points)
edited by s209215

Ich habe es mittlerweile geschafft meine Frage zu programmieren. Da ich erst jetzt mit Javascript in Berührung kam, ist das Skript wahrscheinlich nicht das sauberste. Um anderen aber auch die Möglichkeit zu geben, einen Schieberegler mit mehreren Ausweichmöglichkeiten (im Sinne einer vollbeschrifteten Skala) zu kombinieren, füge ich anbei mein Skript an (aufbauend auf dem Beispielskript von SoSci Survey zum Schieberegler mit Skala) .

Was ist anders, als bei dem Skript von SoSci Survey:
- Der Schieberegler wird nicht deaktiviert; es scheint für die Respondenten nur so. Tatsächlich wird der Schiebereglerknopf einfach nur unsichtbar gemacht. Das hat den Vorteil, dass...
- ...Der Schieberegler wieder erscheint/aktiv ist, sobald ein Respondent draufklickt.
- Schieberegler und Ausweichoptionen hängen voneinander ab. Wird eines angeklickt, wird das jeweils andere Element 'abgewählt' und die Werte entsprechend gespeichert.
- Die Operationalisierung der Items, Fragekennungen und Anzahl der Ausweichkategorien passiert nicht im Javascript, sondern über Placeholder im PHP code auf der entsprechenden Fragebogenseite selbst. Dadurch kann ich man den gleichen Textbaustein bei allen enstprechenden Kombifragen verwenden. Dies sieht bei mir folgendermaßen aus:

replace('%sliderID%', '\'AB01\'', 'text');
replace('%scaleID%', '\'AB02\'', 'text');
replace('%optout%', '1,2', 'text'); //bei zwei Ausweichoptionen
replace('%items%', '1,2,4,5,6,7', 'text'); //hier können auch einzelne Items weggelassen werden; vor allem relevant, wenn durch Filterführungen nicht alle Items gezeigt werden sollen
question('AB01','combine=AB02');

Damit das Skript funktioniert, sollte in den Einstellungen vom Fragebogen das Häkchen bei der Option gesetzt werden, dass Skalenitems durch einen erneuten Klick auch wieder abgewählt werden können. Das Skript wurde überarbeitet und berücksichtigt mittlerweile alle Kommentare, die noch unter dieser Antwort gepostet wurden.

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

//Combine slider and scale (e.g. to offer multiple opt out categories)
	//Answer on slider is hidden (by simply hiding the slider button), if opt-out category is selected
	//Answer on slider is re-shown (making the button visible again), if opt-out category is deselcted
	//Opt out category is deselected if respondent clicks on slider again
	//NB: Script doesn't work with onclick or attachEvent


// Define questions flexible via placeholder in PHP code
var sliderID = %sliderID%;	// alternatively, fixed in javascript: var sliderID = "EZ21";
var scaleID = %scaleID%;	// alternatively fixed in javascript: var scaleID = "EZ22";

// Define items flexible via placeholder in PHP code
var items = [];
items.push(%items%); //take items defined in PHP code (%items% is the placeholder) and push them into the javascript array 

// Define scale options as opt out categories
var optout = [];
optout.push(%optout%);

// Remember slider values for re-appearing slider button
var sliderValues = [];

// Attach events to interactive elements
SoSciTools.attachEvent(window, 'load', function() {
	
	// loop through all items of question 
	for (let ii=0; ii<items.length; ii++) {
		let item = items[ii];  //important: "let item" NOT "var item"! var item references to the last index of item after looping through all items
		refreshSlider(item);
		
		//loop through all opt out categoris of the scale
		for (let io=0; io<optout.length; io++) {
			var option = optout[io];
			
			//Set correct ID (option only necessary if more than one opt out category)
			if (optout.length < 2){
				var scaleOption = document.getElementById(makeID(scaleID, item));
			} else {
				var scaleOption = document.getElementById(makeID(scaleID, item, option));	
			}
			
			// Attach event to click on scale options:
				// Via AddEventListener & anonymous funcion
			scaleOption.addEventListener('click', () => {
				refreshSlider(item);
			});
	
				// Via AddEventListener & bind
			//scaleOption.addEventListener('click', refreshSlider.bind(this, item));
		}
		
		// Attach event to click on slider 
		var slidername = makeID(sliderID, item) + "_" + "scale";  //Id's are: EZ21_01_scale ... 
		console.log(slidername);
		var slider = document.getElementById(slidername);
		
			// Via AddEventListener & anonymous funcion
		slider.addEventListener('click', () => {
			refreshScale(item);
		});
	
			// Via AddEventListener & bind	
		//slider.addEventListener('click', refreshScale.bind(this, item));	
	}
	
});

//-----FUNCTIONS-----

//Function to create appropriate ID to access the correct element
function makeID(questionID, item, option) {
	var itemID = String(item);
	if (itemID.length < 2) {
		itemID = "0" + itemID;
	}
	var itemFull = questionID + "_" + itemID;
	if (!option) {
		return itemFull;
	}
	return itemFull + option; 
}

//Refresh slider function (called after click on opt out category)
function refreshSlider(item) {
	var slider = SoSciSliders.getSlider(makeID(sliderID, item));
	console.log("I am in the slider loop");
	console.log("item is:", item);

	//Check whether opt out categories are "unselected" after a click (respondents might deselect an opt-out category)
	//Loop through all opt out categories
	for (let i=0; i<optout.length; i++) {
		var option = optout[i];
		
		//Set correct ID (option only necessary if more than one opt out category)
		if (optout.length < 2){
			var scaleOption = document.getElementById(makeID(scaleID, item));
		} else {
			var scaleOption = document.getElementById(makeID(scaleID, item, option));	
		}
				
		//Check whether opt out category is NOT selected
		if (scaleOption.checked == false){
			//Check whether a slider value was stored previously for that item (i.e. the sliderValues array is not empty at the corresponding slot of the item and thus returns "true") 
			if (sliderValues[item-1]){
				//replace -9 by former slider value 
				slider.value = sliderValues[item-1];			
			}
		
			//Make slider button visible again
			var buttonID = makeID(sliderID, item) + "_" + "button";
			var sliderbutton = document.getElementById(buttonID);
			sliderbutton.style.visibility = "visible";
			console.log("no scale option is checked");
			
		//If an opt out category is selected		
		} else {
			//Hide slider button
			var buttonID = makeID(sliderID, item) + "_" + "button";
			var sliderbutton = document.getElementById(buttonID);
			sliderbutton.style.visibility = "hidden";
			console.log("A scale option is checked");
		
			//Set slider value to -9
			slider.value = -9; 
			return; //important; function is interrupted as soon as an opt out category is identified as checked/selected 
		}	
	}		
}	
	
//Refresh scale function (called after click on slider) 
function refreshScale(item) {
	var slider = SoSciSliders.getSlider(makeID(sliderID, item));  	
	var buttonID = makeID(sliderID, item) + "_" + "button";	
	
	console.log("I am in the scale loop");
	console.log("item is:", item);
	console.log(slider.value);

	//Deselect opt out categories
	for (let ix=0; ix<optout.length; ix++) {
		var option = optout[ix];
		
		//Set correct ID (option only necessary if more than one opt out category)
		if (optout.length < 2){
			var scaleOption = document.getElementById(makeID(scaleID, item));
		} else {
			var scaleOption = document.getElementById(makeID(scaleID, item, option));	
		}
		
		var Optioncheck = scaleOption.checked;
		if (Optioncheck == true){
			scaleOption.checked = false;
		}
	}	
	
	//Make slider button visible
	var sliderbutton = document.getElementById(buttonID);
	sliderbutton.style.visibility = "visible";
	
	//Store slider value (to remember it, in case opt out categories are deselected) 
	sliderValues[item-1] = slider.value;
}

</script>
by SoSci Survey (302k points)
edited by SoSci Survey
Drei Kommentare noch zur aktuellen Lösung:

Wenn man auf einen deaktivierten Schieberegler klickt, wird die Ausweichoption dadurch nicht (!) automatisch abgewählt. Das könnte man noch ergänzen, wenn die Befragten nicht verstehen, dass man die Ausweichoption wieder abwählen kann.

Wenn auf dem Schieberegler erst etwas ausgewählt wird und dann die Ausweichoption gewählt wird, dann wird der Schieberegler zwar optisch deaktiviert - der ausgewählte Wert bleibt aber sicht bar und (!) wird auch im Datensatz gespeichert. Darauf muss man in der Auswertung achten.

Wenn man auf "Zurück" klickt, dann werden die Schieberegler nicht automatisch deaktiviert. Dafür müsste das Script die OnOff()-Funktion nach dem Laden der Seite einmal für alle Items durchlaufen lassen.
by s209215 (175 points)
Vielen Dank für die Rückmeldung.

Den ersten Punkt fände ich fantastisch, habe aber mit meinen sehr begrenzten und gerade neu erlernten Javaskript-Fertigkeiten keine Möglichkeit gefunden das umzusetzen. Sobald ich den Schieberegler deaktiviere, registriert der event handler keine Mausklicks mehr auf dem Regler. Falls Sie wissen, wie ich das umsetzten könnte, ist die Lösung herzlich willkommen.

Der zweite Punkt ist mir bewusst und tatsächlich im Nachgang bei der Analyse durch eine entsprechende Filterung der Daten einfach umzusetzen. Ich persönlich finde es auch gerade gut, dass der alte Wert angezeigt bleibt, sollte sich jemand von einer Ausweichoption wieder umentscheiden.

Vielen Dank für den Hinweis mit dem Zurück-Knopf. Das hatte ich noch gar nicht beachtet. Ich  habe das Skript entsprechend angepasst und oben aktualisiert.
by SoSci Survey (302k points)
Die aus meiner Sicht sinnvolle Lösung für das erste Problem wäre, dass Sie den Schieberegler nicht deaktivieren - sondern dann Sie stattdessen den Wert -9 (nicht beantwortet) setzen, wenn das Auswahlfeld aktiviert wird.

Umgekehrt würden Sie das Auswahlfeld deaktivieren, wenn im Schieberegler ein Wert > 0 ausgewählt wird. Wenn er nicht deaktiviert ist, dann ist das ja möglich.

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

...