onChange for dropdown and timeouts - javascript

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.

Related

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

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

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.

jQuery onchange event, how to ignore too frequently changes?

I want to implement an auto completion function on my text input, using jQuery by monitoring the change event and query my database on every change.
I know there are some autocompletion plugins but I'm doing something like fuzzy search, so keyword 'ad' may result in words like 'abort' or 'and'. Correct me if I'm wrong, I found most plugins do exact search.
However, I don't want to do database query too frequently, that is, I want to do query only when the text input is updated but haven't been updated for a small amount of time like 200ms. So that I can ignore the constantly high speed inputs by users.
Can anyone tell me how to do that?
You can use something like that to make queries.
var timeouted=null;
$(e).on('change',function(){
clearTimeout(timeouted);
timeouted = setTimeout(function(){
//database query
}, 200)
})
Use setTimeout() stored as a variable, then on input clear the timeout and reset. If elapsed time is >= desired timeout, make DB query.
Working example here: https://jsfiddle.net/c2s1sj6f/7/

onkeyup Event Firing delay

I have a input textbox for people to enter a username, it has a onkeyup event attribute attached which fires off an AJAX request to check if the username is taken.
What is the delay between the first key to the second ? Meaning if I type a 5 letter word one letter after the other. Does the AJAX fire 5 times ?
If there is no delay, would this be "computationally expensive" since there would so many database queries ? Or would there be no noticeable difference ?
If there is a difference in performance, what methods could I take using Javascript to check if the user is actually "done" typing. I still want it to automatically check after typing. Thus ruling out onblur attributes etc.
My Code: http://pastebin.com/hXfgk7nL
(code indentation wasn't working for me on stack overflow)
Yes it will fire EVERYTIME you type a character and you're not going to like that in terms of your page performance. You can implement delays on executing the call back if you like ie. it will not be executed until the user stopped typing. Here's an example:
$(document).ready(function(){
$('#txtboxid').keyup(function(){
clearTimeout(timer);
timer = setTimeout(function(){
//call your function here
}, 250) // you can change the 250 here to a higher number if you want the delay to be longer. In this case, 250 means a quarter of a second.
});});
Following are my replies/suggestion for your queries:
Yes , it will fire 5 fives because 5 times key-up event will be triggered.
it will be a performance issue, resulting in slow response from server,also since your making multiple ajax request sequentially, the response from each request may not be sequential.your code will suffer from logic issue.
instead of making ajax call for key-up, you can use it for blur event.
Suggestion: before making a ajax call validate the field for basic errors like blank string, numbers etc.,(depending on your requirement).
Yes it will fire multiple times, one for each keystroke. You are triggering multiple AJAX calls, so you are wasting network and server resources.
Additionally, you are not guaranteed on the order in which the calls will return, so if for some network reason, the first call issued return last, it will overwrite the results of the most recent request.
To tackle the problem, you are looking for something like this plugin: https://github.com/cowboy/jquery-throttle-debounce.
From the plugin usage example:
function ajax_lookup( event ) {
// Perform an AJAX lookup on $(this).val();
};
// Console logging happens on keyup, for every single key
// pressed, which is WAAAY more often than you want it to.
$('input:text').keyup( ajax_lookup );
// Console logging happens on window keyup, but only after
// the user has stopped typing for 250ms.
$('input:text').keyup( $.debounce( 250, ajax_lookup ) );
Note that despite the name the plugin can also be used stand alone, without jquery.
Yes, it will fire every key-up event. You can reduce the performance hit using following approach.
I am sure you must have a minimum character length for username. Wait until user type that number of characters to query the database.
You could always bring all the usernames starting with user typed username and process in local memory. This may not be real time but would reduce the number database queries. Also it would depend on the size of your current user list.
Double check the existence of the username before saving it to the database.
yes it will fire. if you don't need that means, you have to check conditions with a flag. check the given value with the previous value which is stored in a variable.
You can try to check if your input is modified in 500 ms. Is is not, then make only one ajax request. If the input is modified again than you must repeat the process again.
I suggest to use setInterval for that.

Javascript table on the fly

I've got some issues with javascript. Which causes some problems.
I'm using DevExpress MVC GridView, ASP.Net MVC 3 and javascript.
This my problem:
I've got a gridview, with for example customers.
I want them to select the customers, and show them in a table generated by javascript so we dont get all those refreshes. And they can then add other information so that they can be saved again to another table, but thats not really important.
I perform some calculations before generating the table row from the selected customer. Another problem is, the devexpress gridview has an event that calls on each selection change instead of a nice ~100 ms wait so that the user can multiselect quick without triggering method 3/4 times.
Im keeping track of my own table through an array. And the GridView from DevExpress got his own events that can give me the right information, so no need to worry about that.
So I got a method receiveSelectionFields(Values){ //do something } where I receive that information from the gridview on every selection.
Then I check my array to see if they added or removed a selection, and which.
Then I call addtablerow(customer) or removetablerow(customer). Which removes the customer from my table and then from my array.
Because I make some heavy calculations in between, there is a ~60ms delay before the calculation is done (on mine computer). So if the users makes 2 selections in 60 ms. My array will have the wrong value (not being modified by the first call that adds/removes a customer) and my javascript will cause an error e.g. the table row is not deleted. I check on length of my own array and on the length of the received array to see if something has been added or removed.
So what did I try?
Making my method a recursive method, that when the problem occurs it waites 60 ms and then redo the method. But this isn't working properly.
I tried adding a global variable busy, which is true when the method is still busy. And false when it ends. But my browser just quits when doing that. This was the code:
while (true) {
setTimeout(function () {
if (busy === false) {
break;
}
}, 50);
}
But I got the feeling it just endlessly loops.
And these are all workarounds, there must be a nice way to solve this. Any thoughts?
In short:
I want a way to let the functions go off in synch. even if their being called asynch. by the user so that my array doesn't mess up.
Found the answer why my problem exists:
Since javascript is a synch. language (1 thread). the functions should've triggered at the right time. The problem is the callback from DevExpress Gridview for MVC Extensions. It makes a callback to the server, which responds in for example ~150ms with the selected field values. This will give an error if you quickly trigger the devexpress function twice. The second trigger has a window to return FASTER then the first trigger. Which would mean my coding of the table get ruined since I check if something has been added or removed. So when the first trigger (which returns after the second trigger) and my table gets updated. It shows the table prior to my last selection. Thus missing 1 row or has 1 more row then it should've.
So I got to make a function that retrieves all the events, and then place them in an order ~200 ms after each order. To make sure there is enough time for the callback to retrieve. Though this is ofcourse still not reliable, I think I will just change the requirements on this.
Your while loop condition is true, therefore the loop will just continue endlessly. You may want to try the following:
var int = setInterval(function () {
if(busy === false) {
clearInterval(int);
}
}, 50);
Try this instead of looping through the setTimeout over and over. If I had to guess, the break is breaking the if statement but not the while loop causing your browser to get stuck in an endless loop. With the above code, you can set an interval at which to run the code. In this instance, the code runs every 50ms. Once the condition inside the if statement is true, the setInterval is cleared causing the browser to continue executing its normal functionality.
Hope this helps.

Categories

Resources