Qualtrics: Save previous slider response and set as default in next slider - javascript

I was wondering if someone can help me out on the following issue:
Participants are presented different behaviours that they have to rate on a slider from -3,-2,-1,0,1,2,3. All behaviours are presented on separated pages. Now, I want each previous response to be the default function of the behaviour that is presented next.
For example:
Participant is shown first behaviour, default setting is "0". He/She rates the behaviour with "-2".
Participant is shown second behaviour, default setting is now "-2".
Etc.
I understand that I have to set an embedded data variable.
I was told to save the participants slider response and keep overwriting this. However, I'm very new to Javascript and I'm not sure how to save the participants' slider response.... Any help would be hugely appreciated!
I think for overwriting the embedded data variable 'Output', I use:
[Qualtrics.SurveyEngine.setEmbeddedData('Output', 'response_variable');
However, I am not sure how response_variable can capture the sliderresponse.

This 'response_variable' is just a placeholder from some instruction you received, you need to declare variable to store value of your slider and pass this variable as second parameter.
To save value (Docs:
getChoiceValue,
addOnPageSubmit,
setEmbeddedData):
Qualtrics.SurveyEngine.addOnPageSubmit(function(type)
{
if(type == "next")
{
var value = this.getChoiceValue(1); // assuming sliderId == 1
Qualtrics.SurveyEngine.setEmbeddedData("Output", value);
}
});
To set value in next question (Docs:
setChoiceValue
):
var lastValue = "${e://Field/Output}";
this.setChoiceValue ( 1, lastValue );
PS. You may also need to store information about direction (next/previous) and add condition to avoid setting value after click on "previous" button
PS2. In case this did't work see also this thread

Related

Local Storage not stored after page refresh

I'm having a really hard time understanding what I did wrong in my code in order to have a value saved in local storage.
I have a pretty big code project so I'll try to summarize what the program is tryin to do overall.
I am pulling news articles from the news API and displaying the articles; each article (depending on the publication it came from) pushes a different numeric value into an array allSource2.
I then take the sum of this array to arrive to a "score" (variable is called sum)
I basically want that score to be locally stored, so that it is available even after a page refresh.
I think something wrong might be happening because of where I put the localStorage function. Currently I put it under the click event that also pushes the numeric value in the array (when you click the article title).
I am super confused at where else it could be, so that it truly updates the sum every time that sum changes.
Also, it does work to store it (I checked localStorage on the console, after a refresh it still works, but after refreshing and then clicking on another article, it resets to whatever the value of this article is)
I didn't put the entire code, as it's insanely long. everything else is working fine, it's just that.
Also, the all of this is contained within one big function
I define let sum =0; at the beginning of the code.
Then, this is the click event.
document.getElementsByClassName('article-rating')[i]
.addEventListener('click', function(event) {
sum = allSource2.reduce((tempSum, val) => tempSum + val);
console.log("article score is now" + " " + sum);
var lastname = localStorage.getItem("overallsum");
localStorage.setItem("overallsum", sum);
});
I also tried to put the var lastname = localStorage.getItem("overallsum"); at the beginning of the code, when the first function but no luck.
Thanks a lot for your help!
and apologies for any formatting issues, I'm super new to this.
Each time you click the event the overallsum is getting set and that is the problem. If the overallsum is a one time store to the local storage then you can check if the value of overallsum is null, and if so store the value for the first time.
Example:
if (localStorage.getItem("overallsum") === null) {
localStorage.setItem("overallsum", sum);
}
Otherwise, if the overallsum is something, then for every individual article you could 2D array and then set the value with the same conditional check.

How can I update UI using loops in Javascript based on user input & timer?

Sounds complicated, but bear with me. I want to make a simple game in PHP/JS/Jquery. The data is being retrieved from the database in JSON. It is an array of questions, hints, answers & the correct answer.
I want to present all the questions on a single php page, one by one. The user can click any button, when he/she clicks the right answer, a green checkmark is shown & the score is updated. The next question is shown and so on. If the user runs out of time before attempting all 4 buttons, a red cross is shown, the score stays the same. The next question is shown.
Now, I can loop through the questions, but I cannot wait on user input, since JS is async, so I have to add callbacks. I can't think of a way to code it up in a way that makes verification easy without compromising the correct answer.
Here is some barebones code that gets the data from the db, and uses regular loops, no callbacks. How do I tweak this to get it to do what I want?
// Global variables
var QNAData = null;
var currentQuestionIndex = null;
$(document).ready(function(){
// Get question & answer data from the db
function reqListener () {
QNAData = jQuery.parseJSON(this.responseText);
StartGame(QNAData);
}
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.open("GET", "GetNewGameData.php", true);
oReq.send();
}); // end document.ready
function StartGame(QNAData)
{
// Loop through the questions
for (stageIndex=0; stageIndex < QNAData.length; stageIndex++) {
currentQuestionIndex = stageIndex;
// Populate the Question and Answer text containers
$("#QuestionTextContainer").html(QNAData[stageIndex]['QuestionText']);
$('#QuestionShortHintContainer').text(QNAData[stageIndex]['QuestionHintShort']);
$('#QuestionLongHintContainer').text(QNAData[stageIndex]['QuestionHintLong']);
$("#Answer1TextContainer").html(QNAData[stageIndex]['AllAnswersText'][0]);
$("#Answer2TextContainer").html(QNAData[stageIndex]['AllAnswersText'][1]);
$("#Answer3TextContainer").html(QNAData[stageIndex]['AllAnswersText'][2]);
$("#Answer4TextContainer").html(QNAData[stageIndex]['AllAnswersText'][3]);
// Set up the countdown timer after the answers have been displayed
$('#countdown-container').hide().fadeIn().ClassyCountdown();
}
First of all, using only one question and changing text and answers is very troublesome. I would recommend building HTML for all questions, and only show the current one (control via JS). Your life will be much easier having to just control visibility and not constantly updating text and values around. This will also help you in not changing values and text while user is clicking on answer, since the HTML is different.
Second, there's no way around callbacks in JS. Accept it. You'll need click handlers, change handlers, timeout handlers, ajax handler, all callbacks.
As for the user timeout problem, here's how I'd do it:
You want to use setTimeout. On the function for its callback, make it the function that displays the timeout cross.
The return value of it is a handler, which you can store in a variable.
In case the user press button to check answer for example, or to move to other questions, you can use clearTimeout and pass the stored timeout, so it won't run.
Then create a new one for the new question being displayed.

how to implement javascript localStorage

I want to implement localStorage for one of my values in my Achievements class. So basically what this class does is take player data from backend database and if a player clears certain tasks an achievement gets unlocked. For now I have just 1 achievement defined as follows
Achievements:{ 1:{name:'First_Achievement',status:1} },
The status field acts like a flag for my achievements. If status is 1 then achievement is still locked and if it goes 0 the achievement gets unlocked.
This is a skeleton code for when my achievement gets unlocked. This block of code is checked in my game every 10 seconds to see if a certain task is cleared to unlock an achievement
checkAchievements:function(){
this.probsSolved = this.getTeamProbSolved();
if( this.Achievements[1].status == 1 && this.probsSolved.length >=3)
this.triggerAchievement(1); // spawns achievement 1 on screen
this.Achievements[1].status = 0;
},
So this works fine when I run the game. The "this.Achievements[1].status" is set to 0 until I start my game again the next time. It sets the "this.Achievements[1].status" back to 1 and the if loop runs again as status is set back to 1 which I don't want because its obvious I want my achievement to be spawned or displayed just once and not every time I run the game.
So how do go about an implement localStorage here? I suppose I need to store my "Achievements.status" field in the localStorage so that the if loop runs just once and not everytime. Or is there any other way I can implement this?
I tried the following
localStorage.setItem(this.Achievements[1].status,0);
but it does not work
any help would be appreciated! Thanks!
First, I'd recommend reading the documentation on localStorage at MDN - https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage. Next, let's look at your call:
localStorage.setItem(this.Achievements[1].status,0);
This says: I want you to store a value, 0, and retrieve it by the key that is the value of this.achievements[1].status.
That seems to be booleans for you. So you basically did:
localStorage.setItem(true, 0)
The localStorage API expects a string for the keyname, so it will get the string value of true which is, true. So it probably did work for you, but you used a key that probably isn't what you want. You need to think of a key name scheme that makes sense for you.

Unable to save changes made to entity when calling javascript function through custom ribbon button event

I'm trying to create a simple function which, when ribbon button is pressed, sets entity attribute value to null.
Now the problem I am facing is, that the changes I make to the entity are not saved, form reloads and returns previous value.
To the button event I pass 'Task' activity attribute 'actualend'. 'Actual End' field is disabled by default.
ClearField: function (field) {
if (Xrm.Page.getAttribute(field) == null) return;
Xrm.Page.ui.controls.get(field).setDisabled(false);
Xrm.Page.getAttribute(field).setSubmitMode("always");
Xrm.Page.getAttribute(field).setValue(null);
if (Xrm.Page.data.entity.getIsDirty()) {
Xrm.Page.data.entity.save(); //also tried addOnSave(function)
}
}
Following debugger I was able to track that all changes are made correctly, except that on save() method they are 'discarded', then form reloads with previous value. This code works fine with CRM UR8 yet with CRM UR13 it does not.
Am I missing something?
As Guido mentions in his comment the code looks good which leads me to think that one of your two if statements is failing.
The first one obviously will fail if it is set to null. A little bit less obvious is that it will fail as well as if the field is not actually on the form (even though it may be a valid attribute of the entity). So step 1, ensure that your field exists on the form.
The second one I'm not sure of... I don't think getIsDirty() is keeps track of programmatic changes, so even though your programmatically updating a field and setting it to always submit, it may be returning false. Regardless of how exactly it's working, the if statement really isn't needed. The Xrm.Page.data.entity.save function will only actually save if it has some value that has changed, so I'd remove your dirty check regardless.
Eh, the problem with my issue all this time was that even though the field existed in the form, it never had an entity passed to it, therefore it was unable to save it. I've edited a ribbon button so to pass entity through CrmParameters and the issue was gone. Thank you both for supplying me with possible solutions regardless!

onChange for dropdown and timeouts

I have a dropdown menu which basically sends some data back to the server via onchange. The data is stored in the database and the primary table using seconds to avoid duplicates. What happens is if I scroll the dropdown via my keyboard, for example, using the up/down keys, my script returns an error because there is a duplicate entry now in the database.
here is part of the code for the dropdown in html
onchange="GetmySQLData();"
My question is can i just do a setTimeout and would it be correct to use it in this format:
onchange="setTimeout('GetmySQLData();', 1750);"
If you have a better approach, please feel free to let me know.
Thanks
The following versions are interchangeable:
setTimeout('myFunction()',1750);
setTimeout(myFunction,1750)
setTimeout(function() { /* some anonymous function */ },1750)
What you might want is
<script>
var tId = ""; // create a global var
</script>
and have
onchange="clearTimeout(tId); tId=setTimeout('GetmySQLData()',1750)"
which will only execute the onchange after the user does not change the dropdown for the duration of the timeout, but if the user changes within the timeout period, a new timeout is triggered
If you are planning to use the setTimeOut then it has to called in the following way:
onchange="setTimeout(GetmySQLData(), 1750);" providing single quotes aroung the arguments makes it to be treated as a string. and the timeout value is in milliseconds.

Categories

Resources