stop the timer function from executing when form is submitted - javascript

I have an online quiz program where user needs to complete it within a time period. When user runs out of time,I show an alert saying that your time is up and he is redirected to result page. I get the same alert when user completes the quiz before the time expires and is inside result page. I have modified the code like following but its not working. I am calling the function initTimer(1,1) inside an ajax requested page named questions.php.
In index.php
function initTimer(periodInSeconds, status) {
if (status == 0) {
return false;
}
var end = Date.now() + periodInSeconds * 1000 * 60;
var x = window.setInterval(function() {
var timeLeft = Math.floor((end - Date.now()) / 1000);
if (timeLeft < 0) {
clearInterval(x);
alert("Time's Up!");
timeExpired = true;
var completed = 1;
$.ajax({
type: "POST",
url: "success.php",
data: {
'userID': <?php echo $_SESSION['userID'];?>
},
success: function(hasil) {
$('.response_div').html(hasil);
}
});
}
$(document).find('#timerspan').html('00:' + (timeLeft < 10 ? '0' + timeLeft : timeLeft));
}, 200);
}
//when user submits the form before time expires
$(document).on('submit', '.form_choice', function() {
initTimer(1, 0)
$.ajax({
type: "POST",
url: "result.php",
data: data,
success: function(hasil) {
$('.response_div').html(hasil);
}
})
});
I dont want the init function() to execute when user submits the form before time expires.Please help me

Declare the variable holding the timer outside the initTimer function, then you can clear the timer by calling it with status = 0
var timer;
function initTimer(periodInSeconds, status) {
if (status == 0) {
clearInterval(timer);
return;
}
var end = Date.now() + periodInSeconds * 1000 * 60;
timer = window.setInterval(function() {
var timeLeft = Math.floor((end - Date.now()) / 1000);
if (timeLeft < 0) {
clearInterval(timer);
alert("Time's Up!");
timeExpired = true;
var completed = 1;
$.ajax({
type: "POST",
url: "success.php",
data: {
'userID': <?php echo $_SESSION['userID'];?>
},
success: function(hasil) {
$('.response_div').html(hasil);
}
});
}
$(document).find('#timerspan').html('00:' + (timeLeft < 10 ? '0' + timeLeft : timeLeft));
}, 200);
}
//when user submits the form before time expires
$(document).on('submit', '.form_choice', function() {
initTimer(1, 0)
$.ajax({
type: "POST",
url: "result.php",
data: data,
success: function(hasil) {
$('.response_div').html(hasil);
}
})
});

Related

How to run a function that a on form submit ajax with automatic click button

I am trying to submit a form with just automatic click button.
so I have a timer which is if the timer is already 0, it should submit the form automatically.
here is the code that I have.
function tick() {
var timeDisplay = document.getElementById('question_timer');
var isTimeLimit = true;
var min = Math.floor(secondsRemaining / 60);
var sec = secondsRemaining - (min * 60);
if (sec < 10) {
sec = '0' + sec;
}
var message = min.toString() + ':' + sec;
timeDisplay.innerHTML = message;
//stop if down to zero
if (secondsRemaining === 0 && isTimeLimit == true) {
clearInterval(intervalHandle);
displayQuestion();
} else {
//boolean is false
if (secondsRemaining === 0) {
submitAnswer();
clearInterval(intervalHandle);
}
}
secondsRemaining--;
}
function startCountdown() {
clearInterval(intervalHandle);
secondsRemaining = 5;
intervalHandle = setInterval(tick, 1000);
}
function submitAnswer() {
$('#form_question_scenario').on('submit', function(e) {
$.ajax({
method: "post",
url: url,
data: new FormData(this),
dataType: "json",
contentType: false,
cache: false,
processData: false,
success: function(data) {
},
error: function(jqXHR, textStatus, errorThrown) {
alert('Error adding / update data');
}
});
});
}
How can I run the submitAnswer function if the timer is already 0. any help would be really appreciated.
The submitAnswer() function just attaches the event handler, it doesn't actually submit the form.
To achieve what you require attach the submit event handler when the page loads, then when you want to submit the form trigger that event on it. Try this:
// attach submit event handler when the page loads
$('#form_question_scenario').on('submit', function(e) {
$.ajax({
// ajax settings here...
});
});
function tick() {
var timeDisplay = document.getElementById('question_timer');
var isTimeLimit = true;
var min = Math.floor(secondsRemaining / 60);
var sec = ('00' + (secondsRemaining - (min * 60))).slice(-2); // note tidied the logic here
var message = min.toString() + ':' + sec;
timeDisplay.innerHTML = message;
// stop if down to zero
if (secondsRemaining === 0 && isTimeLimit == true) {
clearInterval(intervalHandle);
displayQuestion();
} else {
if (secondsRemaining === 0) {
$('#form_question_scenario').trigger('submit'); // submit the form here
clearInterval(intervalHandle);
}
}
secondsRemaining--;
}
function startCountdown() {
clearInterval(intervalHandle);
secondsRemaining = 5;
intervalHandle = setInterval(tick, 1000);
}
You don't need submit event at all, just call the function like you did when 0 sec is left, get id of form and create new form data, and do Ajax request...
function submitAnswer() {
let myForm = document.getElementById('form_question_scenario');
$.ajax({
method: "post",
url: url,
data: new FormData(myForm),
dataType: "json",
contentType: false,
cache: false,
processData: false,
success: function(data) {
},
error: function(jqXHR, textStatus, errorThrown) {
alert('Error adding / update data');
}
});
}
EXAMPLE:
Form data is populated without submit event just by calling the function:
function submitAnswer() {
let myForm = document.getElementById('form_question_scenario');
let data = new FormData(myForm)
formObj = {};
for (var pair of data.entries()) {
formObj[pair[0]] = pair[1]
}
console.log(formObj)
}
submitAnswer()
<form id="form_question_scenario">
<input type="text" value="test" name="test">
</form>

set and clear interval by ajax

I simply want to clear previous interval and set a new one when an ajax call is made.
The current code is:
$("#title-form").change(function () {
var title = $(this).val().trim();
$.ajax({
url: '/ajax/timing_check/',
type: "get",
data: {
'title': title
},
dataType: 'json',
success: function (data) {
var interval = null;
if(data.count_down){
var _second = 1000;
var _minute = _second * 60;
var timer;
var end = data.count_down
mins = Math.floor(end / 60);
secs = end % 60;
var interval = setInterval(count,1000)
function count(){
console.log(parseInt(secs))
secs -= 1
}}
else{
var stop = function(){
clearInterval(interval);}
}
}
})
})
I tryed many recommended variations to be able to clear the interval from outside of the function. Such as;
setting the "interval" variable to null or to false,
window.setInterval,
writing the count function inside of setInterval,
writing the count function as a separate function outside of the ajax function,
But neither of the variations cleared the interval.
Later on I'll also need to clear the interval on keydown.
From your code, I will do like below (P.S. didn't test):
var interval = null,
secs = 0;
function count() {
console.log(secs);
secs -= 1;
}
function deal_data(data) {
if(interval == null && data.count_down){
var end = data.count_down
secs = end % 60;
interval = setInterval(count, 1000);
else if (interval != null) {
clearInterval(interval);
}
}
$("#title-form").change(function () {
var title = $(this).val().trim();
$.ajax({
url: '/ajax/timing_check/',
type: "get",
data: { 'title': title },
dataType: 'json',
success: function (data) {
deal_data(data);
}
})
})
After several changes to MarshalSHI's answer the code ended up like this:
$("#title-form").change(function () {
var title = $(this).val().trim();
$.ajax({
url: '/ajax/timing_check/',
type: "get",
data: { 'title': title },
dataType: 'json',
success: function (data) {
deal_data(data);
}
})
})
var interval = null;
function deal_data(data) {
if(interval == null && data.count_down){
var end = data.count_down
secs = end % 60;
interval = setInterval(count, 1000);}
else if (interval != null) {
clearInterval(interval);
interval = null;
}
}
function count() {
console.log(secs);
secs -= 1;
}

trying to get knockout js to check if data has come every 10 seconds

I am trying to call the function which posts the ajax request to check the database, every 10 seconds to see if the required information I want has arrived or not, if the required information has not arrived for 60 seconds, I just want to exit the function.
The problem I am having right now is that, my function doesnt call self.startInstantorCheck every 10 seconds, and then exits to the end after 60 seconds.
Here is the function
self.startInstatorCheck = function(){
self.instatorStarts(true);
var MAX_WAIT_TIME_MS = 1 * 60 * 1000;
var POST_INTERVAL_MS = 10 * 1000;
var timeoutTime = null;
$.ajax({
type: 'POST',
url: BASEURL + 'index.php/moneyexchange/check_instantor_field/' + auth,
contentType: 'application/json; charset=utf-8'
})
.done(function(userinfo) {
if (timeoutTime == null) {
// Start of the timeout cycle:
timeoutTime = Date.now() + MAX_WAIT_TIME_MS;
}
if (userinfo.instantor_request > 12) {
self.allInstantorCheckMessages('Instantor data gathered');
} else {
if (Date.now() < MAX_WAIT_TIME_MS) {
setTimeout(self.startInstatorCheck(), POST_INTERVAL_MS);
} else {
self.allInstantorCheckMessages('Please go through instantor to ');
self.instatorStarts(true);
self.magicInstantorbtn2(true);
}
}
})
.fail(function(jqXHR, textStatus, errorThrown) {
self.errorMessage(errorThrown);
})
.always(function(data){
});
}
I am using knockout js, so would be great if the answers or help are related to knockout js.
First of all, here's your code simplified to reduce nesting and provide clarity through naming.
self.startInstatorCheck = function(){
self.instatorStarts(true);
var MAX_WAIT_TIME_MS = 1 * 60 * 1000;
var POST_INTERVAL_MS = 10 * 1000;
var timeoutTime = null;
$.ajax({
type: 'POST',
url: BASEURL + 'index.php/moneyexchange/check_instantor_field/' + auth,
contentType: 'application/json; charset=utf-8'
})
.done(function(userinfo) {
// please use === not ==
// == doesn't always do what you want it to do, NEVER use it
timeoutTime = timeoutTime === null ?
Date.now() + MAX_WAIT_TIME_MS :
timeoutTime;
var pleaseNameMe = userinfo.instantor_request > 12
if (pleaseNameMe) {
return self.allInstantorCheckMessages('Instantor data gathered');
}
var expired = Date.now() < MAX_WAIT_TIME_MS
if (!expired) {
return setTimeout(self.startInstatorCheck(), POST_INTERVAL_MS);
}
self.allInstantorCheckMessages('Please go through instantor to ');
self.instatorStarts(true);
self.magicInstantorbtn2(true);
})
.fail(function(jqXHR, textStatus, errorThrown) {
self.errorMessage(errorThrown);
})
.always(function(data){
});
}
Secondly, your question has been solved before, knockoutjs or not. Here is a wonderful article that explains how to do polling in javascript using timeout. It recommends using promises. I strongly agree. (They can and should be used in conjunction with knockout js.) A contrived example directly from the blog:
// The polling function
function poll(fn, timeout, interval) {
var dfd = new Deferred();
var endTime = Number(new Date()) + (timeout || 2000);
interval = interval || 100;
(function p() {
// If the condition is met, we're done!
if(fn()) {
dfd.resolve();
}
// If the condition isn't met but the timeout hasn't elapsed, go again
else if (Number(new Date()) < endTime) {
setTimeout(p, interval);
}
// Didn't match and too much time, reject!
else {
dfd.reject(new Error('timed out for ' + fn + ': ' + arguments));
}
})();
return dfd.promise;
}
// Usage: ensure element is visible
poll(function() {
return document.getElementById('lightbox').offsetWidth > 0;
}, 2000, 150);
there are few mistakes in your code.
compare this with yours to see the changes
self.startInstatorCheck = function() {
self.instatorStarts(true);
var t = new Date();
var timeoutTime = t.setSeconds(t.getSeconds() + 60)
var interval = 10 * 1000;
function instatorCheck() {
$.ajax({
type: 'POST',
url: BASEURL + 'index.php/moneyexchange/check_instantor_field/' + auth,
contentType: 'application/json; charset=utf-8'
})
.done(function(userinfo) {
if (userinfo.instantor_request > 12) {
self.allInstantorCheckMessages('Instantor data gathered');
} else {
if (new Date() < timeoutTime) {
setTimeout(instatorCheck, interval);
} else {
self.allInstantorCheckMessages('Please go through instantor to ');
self.instatorStarts(true);
self.magicInstantorbtn2(true);
}
}
})
.fail(function(jqXHR, textStatus, errorThrown) {
self.errorMessage(errorThrown);
})
.always(function(data) {});
}
instatorCheck();
}

Logic in customizing timer in java script

I have an pop up dialog that appears after every one minute and in that pop up, I have a timer that count it's time starting from 1 minute, till 0. If user presses yes in the popup dialog, the modalpop is again reset to call again after one minute.
My problem is that it was working fine until I have not introduced startBackCountDown() which creates a timer inside that modal popup. Can somebody please help me. I am stucked here.
var mins = 1;
var secs = 0;
var timer;
//240000-Four minutes
// 120000- two minutes
//60000-OneMinute
var myVar = setInterval(function () { myTimer() }, 60000);
function myTimer() {
startBackCountDown();
$("#dialog").dialog("open");
}
function startBackCountDown() {
timer = setInterval('update()', 1000);
}
function update() {
var timeField = document.getElementById('Showtime');
if (secs == 0) {
if (mins == 0) {
timeField.innerHTML = "Time's up!";
clearInterval(timer);
//alert("Time's up");
return;
}
mins--;
secs = 59;
} else {
secs--;
}
if (secs < 10) {
timeField.innerHTML = 'Time left: ' + mins + ':0' + secs;
} else {
timeField.innerHTML = 'Time left: ' + mins + ':' + secs;
}
}
function ClearTimerValues() {
window.clearInterval(myVar);
clearInterval(timer);
}
function SetTimerValuesAgain() {
var client_Name = '#Session["ClientFullName"]';
var Client_Id = '#Session["Client_LoginID"]';
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "../Account/ResetUser",
data: "{'User_ID':'" + Client_Id + "','Client_Name':'" + client_Name + "'}",
dataType: "json",
success: function (data) {
if (data.Data == '1') {
myVar = setInterval(function () { myTimer() }, 60000);
//window.clearInterval(timer);
mins = 1;
secs = 0;
}
else {
window.clearInterval(myVar);
window.location = "/Account/login";
}
},
error: function (xhr) {
}
});
}
$(function () {
$("#dialog").dialog({
resizable: false,
height: 140,
modal: true,
autoOpen: false,
show: "blind",
hide: "blind",
buttons: {
"Yes": function () {
SetTimerValuesAgain();
$(this).dialog("close");
},
"No": function () {
ClearTimerValues();
$(this).dialog("close");
}
}
});
});

Ajax Chrome wont evaluate script immediately in success

I have this source:
$("#allDataForm").submit( function (e) {
e.stopPropagation();
var formData = $("#allDataForm").serialize();
var count = formData.substring(formData.indexOf('&count=')+7,formData.indexOf('&x='));
var x = parseInt(formData.substring(formData.indexOf('&x=')+3, formData.length));
if (formData.indexOf('=description&') > 0 &&
formData.indexOf('=name&') > 0 &&
formData.indexOf('=identifier&') > 0) {
var head = 0;
if (formData.indexOf('firstashead=on') > 0) {
head=1;
}
head = parseInt(head);
var imported = 0;
var updated = 0;
$("#assignTable").hide();
$("#send").hide();
$("#status").show();
var totalTime = 0;
if (count > 0) {
for (s=x; s<=count; s++) {
var startms = new Date().getTime();
$.ajax({
type: "POST",
data: formData,
dataType: "html",
url: "/import/universalimport/",
async: false,
success: function(msg, textStatus, XMLHttpRequest) {
console.log($.makeArray(arguments), 'success');
console.log(textStatus, 'success1');
console.log(XMLHttpRequest, 'success2');
if (msg == 'imported') {
imported = parseInt(imported)+1;
} else if (msg == 'updated') {
updated = parseInt(updated)+1;
}
var endms = new Date().getTime();
totalTime = totalTime + (endms-startms);
x = totalTime / 1000;
tSeconds = Math.abs((x % 60).toFixed(0));
if (tSeconds < 10) {
tSeconds = 0+String(tSeconds);
}
x /= 60;
tMinutes = Math.abs((x % 60).toFixed(0));
if (tMinutes < 10) {
tMinutes = 0+String(tMinutes);
}
x /= 60;
tHours = Math.abs((x % 24).toFixed(0));
if (tHours < 10) {
tHours = 0+String(tHours);
}
x = (totalTime*(count-s-head)/s) / 1000;
aSeconds = Math.abs((x % 60).toFixed(0));
if (aSeconds < 10) {
aSeconds = 0+String(aSeconds);
}
x /= 60;
aMinutes = Math.abs((x % 60).toFixed(0));
if (aMinutes < 10) {
aMinutes = 0+String(aMinutes);
}
x /= 60;
aHours = Math.abs((x % 24).toFixed(0));
if (aHours < 10) {
aHours = 0+String(aHours);
}
eval($("#bar").css('width', (parseInt(s)/parseInt(count)*100).toFixed(2) + '%'));
$("#bar").html((parseInt(s)/parseInt(count)*100).toFixed(2) + '%');
$("#imported").html(imported);
$("#updated").html(updated);
$("#summary").html(imported+updated);
$("#count").html(count-head);
$("#elapsed").html(tHours + ':' + tMinutes + ':' + tSeconds);
$("#remaining").html(aHours + ':' + aMinutes + ':' + aSeconds);
formData = formData.substring(0, formData.indexOf('&x=')+3) + parseInt(s);
}
});
}
}
} else {
alert('Pro provedení importu je nutno napárovat minimálně Název, Popis a Identifikátor!');
}
return false;
});
In Google Chrome it wont evaluate script inside success immediately but after all ajax calls it execute the last one. When I add alert() inside success it works fine and in Firefox it works well.
Async is a depreciated feature. Success is also on its way out. You should be using
$.ajax({
type: "POST",
data: formData,
dataType: "html",
url: "/import/universalimport/"
}).done(msg, textStatus, XMLHttpRequest) {
... rest of code when done here
Here is a jsfiddle showing a set of $.ajax() POSTs being sent all at once and coming back at different intervals:
<ul id='log'></ul>
<script>
var call,
log = $('#log');
for (call = 0; call < 10; call++) {
$.ajax({
type: 'POST',
url: '/echo/html/',
data: {
html: "ajax response #" + call,
delay: 3
},
success: function(data) {
log.append('<li>'+data+'</li>')
console.log(data);
},
dataType: 'html'
});
log.append('<li>'+('ajax request #' + call)+'</li>')
console.log('ajax request #' + call);
}
</script>
I've run this in Chrome and Firefox and the behavior appears to be the same (the ajax responses return out of order as though they had been submitted at different intervals). Does this model the problem you are talking about?
Solved by recursive calling asynchronous ajax. Thanks for help.

Categories

Resources