Qualtrics, Javascript: how to implement a pause and show previously hidden choices? - javascript

I design a new survey and in one of my multiple choice questions, the alternatives are supposed to be hidden for 1 sec and so that the user is inclined to spend more attention to the question before answering.
So far my code is only able to hide the choices but waiting and showing is still missing. (code below)
Thanks for any help or suggestions on how to solve this issue.
Qualtrics.SurveyEngine.addOnload(function () {
this.hideNextButton();
this.hideChoices();
//HERE I WOULD LIKE THE CODE TO WAIT FOR 1 sec
//HERE I WOULD LIKE THE CHOICES TO REAPPEAR ON THE SCREEN
this.questionclick = function (event, element) {
if (this.getChoiceValue(4) == true) {
this.clickNextButton();
} else if (this.getChoiceValue(5) == true) {
this.clickNextButton();
}
}
});

There are two parts of the problem here.
How to wait one second? That's done with setTimeout() and a callback function.
How to make sure the callback function works on the right object? - That's done by storing the object we want to work on in a variable.
So, without knowing anything about Qualtrics SurveyEngine, it is clear from your code that this inside the onLoad callback refers to your survey object. We will need that object later in the setTimeout callback, so let's store it. The rest is easy:
Qualtrics.SurveyEngine.addOnload(function () {
var survey = this;
// attach click event handler
self.questionclick = function (event, element) {
// using `survey` instead of `this` would work here, too
if (this.getChoiceValue(4) || this.getChoiceValue(5)) {
this.clickNextButton();
}
};
// hide buttons
survey.hideNextButton();
survey.hideChoices();
// after 1000ms, show buttons again
setTimeout(function () {
survey.showNextButton();
survey.showChoices();
}, 1000);
});

Related

JavaScript setInterval only works once

I hope you are doing well.
I'm working on a minigame based on JS and want to prevent the user from shooting infinite bullets, so I created this condition. Which only works for the first time and then breaks for the next clicks
also to mention this whole section is inside the loop so shooting works well with or without setInterval
let shootController = true
canvas.addEventListener("click", () => {
if (shootController) {
//shooting code goes here
shootController = false;
}
});
if (shootController === false) {
setInterval(() => {
shootController = true;
}, 1000);
}
Thanks for your replies beforehand
Somehow, I defined the 'setInterval' before and outside the loop and then called that function below and outside. This one WORKS
But from curiosity, I didn't define it at the top as a function and only used it below the loop. This one didn't work.
The problem is solved, but I don't know why.

Wait until an element has a value - not just exists

I have a set of dynamic dropdown menus which are populated using JQuery/Javascript via a javascript array. As you select different parent dropdown values the children change. Fairly basic stuff.
We have an issue where a another javascript function needs to use a child dropdownlist value in order to process.
As the scripts run asyncronously there are situations where the value is not populated by the time the second script needs the value.
I was hoping to use setTimeout to 'wait' for the value to be set by the first script before continuing the second script.
I lifted the code below from another thread but it only ever seems to wait 'once', it never waits 50ms and then wait again if the condition is not set.
var waitForEl = function(selector, callback) {
if (($('#'+selector).val())) {
console.log('good to go');
callback();
} else {
setTimeout(function() {
console.log('paused for thought');
waitForEl(selector,callback);
},50);
}
};
$('[id^="currentcontainersizeid"]').each(function() {
thisId = $(this).attr('id').replace(/^\D+/g, "")
if (($('#currentcontainersizeid'+thisId).length > 0) && ($('#currentcontainersizeid'+thisId).val())) {
waitForEl('containersizeid'+thisId, function() {
console.log('FIRE TRIGGER');
$('#containersizeid'+thisId).trigger('change');
});
}
});
I am not sure whether it is my test that is wrong or the timeout logic. Should I be checking whether the element is 'selected' rather than has a 'val'. If so how would I do that?
Does the code above look correct to achive what I want?
Thoughts/help appreciated.

NW.js have a "loading" icon while processing request

I have an app created with NW?js that works fine.
However, it does a lot of processing (loading, save file, reload it and processing, ...) All of that is done by functions.
While I see that it is doing something (because when I click on the "button" that execute the function, the button remains "clicked" until it is finished), it seems impossible to get a spinner instead.
I have 2 functions that are used to respectively show and hide a spinner, but when I use them at start and end of the function, they are executed almost immediately (normal for show, but not foe hide) and I can't find the reason why
Any idea how I could have a spinner while my function are still processing and hide it when done ?
Thank you
In JavaScript, functions can't "sleep", all the code is executed without any stop, they return immediately. If you want to delay the execution of a function, you need a callback :
var button = document.getElementById("button");
var spinner = document.getElementById("spinner");
button.onclick = function () {
startSpinning();
button.setAttribute("disabled", "disabled");
doSomethingTimeConsumingThen(function () {
button.removeAttribute("disabled");
stopSpinning();
});
}
function doSomethingTimeConsumingThen (onDone) {
setTimeout(onDone, 1000);
}
function startSpinning () {
spinner.innerHTML = "Spinning...";
}
function stopSpinning () {
spinner.innerHTML = "Not spinning.";
}
<button id="button">Do something time consuming</button>
<div id="spinner">Not spinning.</div>
A callback is called when something happens, for example when a time consuming task is done. In the above snippet the callback is :
function () {
button.removeAttribute("disabled");
stopSpinning();
}
There must be something similar in your API.

Javascript: Do processing when user has stopped typing

I have a text box on a web page, whose value I want to send to a XMLHttpRequest. Now I want the user to just type the value, without pressing a button. But If i just send the request int he keyboard events, it will fire every time a key is pressed.
So basically I want something liek this
function KeyUpEvent()
{
if (user is still typing)
return;
else
//do processing
}
It would be great if the solution could come from plain javascript or mootools. I dont want to use any other library.
The way this is usually done is by restarting a timer on the keyup event. Something like this:
var keyupTimer;
function keyUpEvent(){
clearTimeout(keyupTimer);
keyupTimer = setTimeout(sendInput,1000); // will activate when the user has stopped typing for 1 second
}
function sendInput(){
alert("Do AJAX request");
}
Basically, you want to start a timer on KeyUp, and when KeyUp starts again, reset the timer. When the user stops typing, the timer runs out, and your request can go at that point.
Example:
var timout_id;
function keyup_handler(event) {
if (timout_id) {
clearTimeout(timout_id);
}
timout_id = setTimeout(function(){
alert('sending data: \n' + event.target.value)
}, 800);
}
Just attach the function to the input using your preferred method, and replace the alert with your preferred action.
Of course there are many ways you could generalize this approach and make it more reusable, etc, but I think this illustrates the basic idea.
I always use this simple function to handle a timer, that will fire a callback function, after the user has stopped typing for a specified amount of time:
var typewatch = (function(){
var timer = 0;
return function(callback, ms){
clearTimeout (timer);
timer = setTimeout(callback, ms);
}
})();
Usage (example with MooTools):
$('textInput').addEvent('keyup', function(e){
typewatch(function () {
// executed only 500 ms after the last keyup event
// make Ajax request
}, 500);
});
The main difference between this solution and solutions from other answers is that all the timer logic is handled by the typewatch function itself, the event handler doesn't need to know anything about the timer, it just invokes the function. Also, there are no global variables to take care (the timer id is not stored on a global variable).
You never know when a user is really "finished" typing. The user might take a sneeze break, or a stretch break, or a coffee break, and then continue typing.
However, if you're implementing something like an autocomplete mechanism, you can set a timer (cf. window.setTimeout(...)) to see if the user hasn't typed anything in a certain amount of time. If you get another key-up event while the timer is running, you can start the timer over.
var keyTimer;
function onKeyUp(){
clearTimeout(keyTimer);
setTimeout(stoppedTyping,1500);
}
function stoppedTyping(){
// Profit! $$$
}
EDIT: Damn ninjas
I wrote a custom jQuery event because I use this logic a lot:
jQuery.event.special.stoppedtyping = {
setup: function(data, namespaces) {
jQuery(this).bind('keyup', jQuery.event.special.stoppedtyping.keyuphandler);
},
teardown: function(namespaces) {
jQuery(this).bind('keyup', jQuery.event.special.stoppedtyping.keyuphandler);
},
keyuphandler: function(e) {
var interval = 1000;
var el = this;
if (jQuery.data(this, 'checklastkeypress') != null) {
clearTimeout(jQuery.data(this, 'checklastkeypress'));
}
var id = setTimeout(function() {
jQuery(el).trigger('stoppedtyping');
}, interval);
jQuery.data(this, 'checklastkeypress', id);
}
};
You can use it like this:
$('input.title').bind('stoppedtyping', function() {
// run some ajax save operation
});
For some reason I could never get it to work with .live( ... ). I'm not sure why...
Use onBlur and maybe an onKeyDown to check for the user pressing the return/enter key.

dojo mouseover with delay

I wish to do something like as follows:
When the mouse goes over to some element, record it
If the mouse stays there for 3 seconds, then execute some action f() for that element
If the mouse leaves that element before 3 seconds, then the action should not be executed.
How can I implement this delayed execution with possible cancellation? An answer using DOJO library would be nicer since I am using DOJO toolkit in my project.
Try the following:
var delay = 3000;
dojo.forEach(dojo.query(".some-element-set"), function(element) {
dojo.connect(element, "onmouseover", function() {
// dojo.partial(f, this.id) will apply `this.id` to `f`, but it
// will not execute it and will only a new function
this._timer = setTimeout(dojo.partial(f, this.id), delay);
});
dojo.connect(element, "onmouseout", function() {
// this._timer was set as an element attribute in the above event
// handler so we don't have to keep track of them separately in
// some silly array/object
clearTimeout(this._timer);
});
});
See the query, forEach, connect and partial documentation for more information.
Edit: I've update my answer per the OP's comment

Categories