session destroy after count down timer reach 0 - javascript

use countdown timer for logout user,if user is inactive for 2hrs..
function Timer(duration, display) {
var timer = duration, hours, minutes, seconds;
setInterval(function () {
hours = parseInt((timer /3600)%24, 10)
minutes = parseInt((timer / 60)%60, 10)
seconds = parseInt(timer % 60, 10);
hours = hours < 10 ? "0" + hours : hours;
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
display.text(hours +":"+minutes + ":" + seconds);
if(hours == 0 && minutes == 0 && seconds == 0){
$.ajax({
url:'../ajax/logoutuser.php',
success: function(data){
console.log('logout');
}
});
}else{
--timer;
}
}, 1000);
}
window.onload = function () {
var twentyFourHours = 1 * 1 * 3;
var display = $('#time');
Timer(twentyFourHours, display);
};
and since i cant call session destroy on jquery function i use ajax to make request..
<?php
require_once '../config/database.php';
require_once '../includes/dboperations/user.php';
$database = new Database();
$conn = $database->getConnection();
$db = new User($conn);
$user = json_decode($_SESSION["user"]);
$db->offlineStatus($user->user_id);
session_destroy();
echo "<script>window.location.href = '../index.php'</script>";
?>
but what happens is, it doesnt call the session destroy function after making request. it runs the console.log inside success function..
is there a way to log out user if inactive for 2hrs

You can achieve by php way. Something like
$expiry = 1800 ;//session expiry required after 30 mins
if (isset($_SESSION['LAST']) && (time() - $_SESSION['LAST'] > $expiry)) {
session_unset();
session_destroy();
}
$_SESSION['LAST'] = time();

Instead of echo script from php file out it in success function of ajax code
success: function(data){
console.log('logout');
window.location.href = '../index.php';
}

Related

How to make countdown instaed of count up

I have this code that displays the timer for the exam. Which made by the admin side. the timer is counting the time in count up but i want to make it display in countdown. Unfortunately i could not figure out how to make it display in countdown.
if someone can help me i will be appreciated.
ajax.php
if(isset($_POST['subId']) && isset($_POST['userId'])){
$subId = $_POST['subId'];
$id = $_POST['userId'];
require_once('../admin/inc/db.php');
$subQuery = "SELECT * FROM subject WHERE id = '$subId' AND exam = 'on' ";
$subRun = mysqli_query($con, $subQuery);
if(mysqli_num_rows($subRun) > 0){
$subRow = mysqli_fetch_array($subRun);
$time = $subRow['time'];
$query = "SELECT * FROM timer WHERE user = '$id' AND subject = '$subId' ";
$run = mysqli_query($con, $query);
if(mysqli_num_rows($run) == 0){
$insert = "INSERT INTO timer(user, subject, spent) VALUES('$id', '$subId', 1)";
$insertRun = mysqli_query($con, $insert);
} else{
$row = mysqli_fetch_array($run);
$spent = $row['spent'];
if($spent < $time){
$count = $spent + 1;
$update = "UPDATE timer SET spent = '$count' WHERE user = '$id' AND subject = '$subId' ";
$updateRun = mysqli_query($con, $update);
echo $count;
} else{
echo "Time out!";
}
}
} else{
echo "Time out!";
}
timer.js
$(document).ready(function(){
var subId = $('#subId').val();
var userId = $('#userId').val();
var myVar = setInterval(myTimer, 1000);
function myTimer(){
$.ajax({
type: 'POST',
url: 'inc/ajax.php',
data: { subId: subId, userId: userId },
success: function(res) {
if(res == 'Time out!'){
clearInterval(myVar);
$('#timer').html('Time over!');
$('#exampleModal').modal({
backdrop: 'static',
keyboard: false
});
} else{
var time = res;
if(time < 60){
$('#timer').html('0:' + time);
} else if(time == 60){
$('#timer').html('1:00');
} else{
var min = Math.floor(time/60);
var sec = time % 60;
if(min < 10 && sec < 10){
$('#timer').html(min + ':' + '0' + sec);
} else if(min >= 10 && sec < 10){
$('#timer').html(min + ':' + '0' + sec);
} else{
$('#timer').html(min + ':' + sec);
}
}
}
},
error: function(jqXHR, textStatus, errorThrown){
if(jqXHR){
$('#timer').html('<span class="animated flash infinite">Exam Paused!</span>');
}
}
});
}
});
To make the timer countdown instead of counting up, you need to change the way the time variable is calculated in the success function of the AJAX request. Instead of subtracting the current time from the start time, you need to subtract the start time from the maximum time and display the remaining time.
Here's an updated version of the code that should count down:
$(document).ready(function(){
var subId = $('#subId').val();
var userId = $('#userId').val();
var totalTime = 60; // or whatever maximum time you want to set
var remainingTime = totalTime;
var myVar = setInterval(myTimer, 1000);
function myTimer(){
$.ajax({
type: 'POST',
url: 'inc/ajax.php',
data: { subId: subId, userId: userId },
success: function(res) {
if(res == 'Time out!'){
clearInterval(myVar);
$('#timer').html('Time over!');
$('#exampleModal').modal({
backdrop: 'static',
keyboard: false
});
} else{
remainingTime = totalTime - res; // calculate remaining time
if(remainingTime < 0){
remainingTime = 0; // prevent negative values
}
var min = Math.floor(remainingTime/60);
var sec = remainingTime % 60;
var timeStr = min + ':' + (sec < 10 ? '0' : '') + sec; // format time string
$('#timer').html(timeStr); // display remaining time
}
},
error: function(jqXHR, textStatus, errorThrown){
if(jqXHR){
$('#timer').html('<span class="animated flash infinite">Exam Paused!</span>');
}
}
});
}
});
Note that this code assumes that the maximum time is known and fixed, and that the >res variable returned by the AJAX request represents the time elapsed since the >start of the exam. You may need to adjust the code if these assumptions don't hold >for your use case.

How to show real timer clock in pubnub publish and subscribe method

let timer =0;
function showTime() {
var d = new Date();
document.getElementById("demo").innerHTML = d.toLocaleTimeString();
}
function letsGo(duration) {
const pubnub = new PubNub({
publishKey: 'pub-c-1bda0482-9e4d-4ae7-b95d-232b2d452050',
subscribeKey: 'sub-c-e515c58a-69e0-11eb-b914-eedc703588a5',
uuid: "myUniqueUUID"
});
var timer = duration;
function publishSampleMessage(){
var publishPayload ={
channel : "game-time",
message: {
data:setInterval(function () {
var minutes, seconds;
if(timer>0)
{
minutes = parseInt(timer / 60, 10);
seconds = parseInt(timer % 60, 10);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
//console.log(minutes+":"+seconds);
document.getElementById("demo").innerHTML = minutes + "m " + seconds + "s ";
timer--;
if (timer==0) {
document.getElementById("demo").innerHTML ="Game is Over";
document.getElementById("game").innerHTML ="";
}
//timesender(timer);
}
}, 1000),
mytime: --timer
}
}
pubnub.publish(publishPayload, function(status, response) {
console.info("status publish function "+status);
console.info("response publish function "+ response.timetoken);
console.info(publishPayload);
})
}
pubnub.addListener({
status: function(statusEvent) {
if (statusEvent.category === "PNConnectedCategory") {
publishSampleMessage();
}
},
message: function(msg) {
console.log("sanu ki "+msg.message.data);
if(msg.message.mytime>0) {
console.log("tanu ki " + msg.message.mytime);
msg.message.mytime--;
}
},
presence: function(presenceEvent) {
// This is where you handle presence. Not important for now :)
console.log("presence "+presenceEvent.action);
}
})
console.log("Subscribing...");
pubnub.subscribe({
channels: ['game-time'],
withPresence: true
});
}
function timesender(time){
console.log("time is this : "+time);
}
I am trying to publish a real-time countdown timer in PubNub through javascript but whenever I publish a message it appears something like a fixed number like 6 and it never appears like a countdown clock but in the console log it is appearing like a countdown clock. Please suggest me how to publish the countdown timer clock as an admin so that other users get listen to it. The basic idea is I have created an admin portal in PHP and JS where I am starting a countdown timer and unity mobile game users will be listening to that timer
Updated code after Stephen help:
function letsGo(duration) {
const channel = 'game-time';
const pubnub = new PubNub({ publishKey : 'pub-c-1bda0482-9e4d-4ae7-b95d-232b2d452050', subscribeKey : 'sub-c-e515c58a-69e0-11eb-b914-eedc703588a5' });
let countdown = 65; // seconds
const countdownId = setInterval( countdownUpdate, 1000 );
function countdownUpdate() {
pubnub.publish({
channel : channel,
message : { 'countdown' : --countdown },
});
if (countdown <= 0) clearInterval(countdownId);
}
console.log("Subscribing...");
// Public user receiving updates on the countdown
pubnub.subscribe({
channels: [channel]
});
pubnub.addListener({ message: event => {
const timeLeft = event.message.countdown;
console.log("time left "+timeLeft)
const minutes = Math.floor(timeLeft / 60) + '';
const seconds = Math.floor(timeLeft % 60) + '';
let dd = `${minutes.padStart(2,'0')}:${seconds.padStart(2,'0')}`;
document.querySelector('#demo').innerHTML =
`${minutes.padStart(2,'0')}:${seconds.padStart(2,'0')}`;
}});
}
I am getting a minor problem now. As basically I have created a letsGo function on a click button so whenever I am opening a timer page in another browser I am getting two clocks one is the continuation of the previous browser but there is another one that is getting started from beginning again
JavaScript Countdown Timer
The bug in the code: an int eventId value is published via PubNub. This isn't the intended design. The reason for this is explained following usage of setInterval function returning the eventId for the interval timer.
let eventId = setInterval(...) returns an integer that references the setInterval eventId on the browser's event loop stack. The idea is that you can use the eventId to stop the interval later on with clearInterval(eventId).
Recommended Approach:
(()=>{
'use strict';
const channel = 'game-time';
const pubnub = new PubNub({ publishKey : 'demo', subscribeKey : 'demo' });
let countdown = 65; // seconds
const countdownId = setInterval( countdownUpdate, 1000 );
// Secure Server --> this should be running on your node.js server.
function countdownUpdate() {
pubnub.publish({
channel : channel,
message : { 'countdown' : --countdown },
});
if (countdown <= 0) clearInterval(countdownId);
}
// Public user receiving updates on the countdown
pubnub.subscribe({
channels: [channel]
});
pubnub.addListener({ message: event => {
const timeLeft = event.message.countdown;
const minutes = Math.floor(timeLeft / 60) + '';
const seconds = Math.floor(timeLeft % 60) + '';
document.querySelector('#timer').innerHTML =
`${minutes.padStart(2,'0')}:${seconds.padStart(2,'0')}`;
}});
})();
#timer {
font-size: 60px;
}
<script src="https://cdn.pubnub.com/sdk/javascript/pubnub.4.29.11.min.js"></script>
<div id="timer">00:00</div>

undefined from arrValue.start_date

I am trying to get from my database the start_date and end_date, however, I am getting "undefined" in console from arrValue.start_date or arrValue.(x) regardless of input.
unavailabletimes = [];
is_conflict = false
$.ajax({
url: '<%= preload_parking_path(#parking) %>',
dataTyp: 'json',
success: function(data) {
$.each(data, function(arrID, arrValue){
unavailabletimes.push([moment(moment.utc(arrValue.start_date).format('YYYY-MM-DD HH:mm')), moment(moment.utc(arrValue.end_date).format('YYYY-MM-DD HH:mm'))] );
console.log(arrValue.start_date);
})
var prestart_date = $('#reservation_start_date').datetimepicker('viewDate');
var start_date = moment(moment(prestart_date).format('YYYY-MM-DD HH:mm'));
var preend_date = $('#reservation_end_date').datetimepicker('viewDate');
var end_date = moment(moment(preend_date).format('YYYY-MM-DD HH:mm'));
if(end_date.diff(start_date, 'minutes') < 60){
var duration = 60;
}else{
if((end_date.diff(start_date, 'minutes') % 60) == 0){
var duration = end_date.diff(start_date, 'minutes');
}else{
var duration = ((end_date.diff(start_date, 'minutes') - (end_date.diff(start_date, 'minutes') % 60)) + 60);
}
}
unavailabletimes.forEach((unavailabletime)=> {
// unavailabletime = [moment, moment]
// check with start time and end time
if (start_date <= unavailabletime[0] && end_date >= unavailabletime[1]) {
is_conflict = true
}
});
if(is_conflict) {
$('#message').text("Cannot overlap existing bookings!");
$('#preview').hide();
$('#btn_book').attr('disabled', true);
} else {
var total = duration/60 * <%= #parking.price %>;
$('#message').text("");
$('#preview').show();
$('#btn_book').attr('disabled', false);
$('#reservation_hours').text(duration/60);
$('#reservation_total').text(total);
}
}
});
arrValue on itself works and it returns the database entries but adding the .(x) i.e start_date or end_date.
This is my console for arrValue
What could be the cause of this? What I am trying to do is setup a booking system that does not allow overlapped booking down to the hour. I am trying to retrieve the time interval between start_date and end_date. Push it into unavailabletimes to find conflict. I am new to coding so I apologize if its a little messy.

Count down timer not working with AJAX

I am trying to make a counter with JS. So far I've managed to pull that off, however I now encounter a problem. While using AJAX to retreive the time to count down I can't make it work. It's weird because it works on my original file but not with a php file called by AJAX.
This works fine :
https://jsfiddle.net/6kvp25vv/
I have no idea what the problem is. This is the HTML page :
<button onclick="upgrade('meat_max')" id="up_meat_max">+</button>
When I click on the button, it runs the function inside this js file which creates a GET request on upgrade.php :
function upgrade(building) {
var file = 'upgrade.php?building=' + building;
ajax(file, function(response) {
document.getElementById('construction').innerHTML += response;
})
}
function ajax(file, fn) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
fn(xmlhttp.responseText);
}
};
xmlhttp.open('GET', file, true);
xmlhttp.send();
}
And this is the code from upgrade.php (variables sent to this file with AJAX are not used for the purpose of testing the code) :
<div class="time">Time: <span id="timer">?</span></div>
var hour = 2;
var minute = 46;
var second = 45;
// function to make a counter
function clockIt() {
function clockO(digit) {
if(digit<10) {
return '0';
} else {
return '';
}
}
document.getElementById('timer').textContent = hour + ':' + clockO(minute) + minute + ':' + clockO(second) + second;
if(second>0) {
second -= 1;
} else if(minute>0) {
minute -= 1;
second += 59;
} else if(hour>0) {
hour -= 1;
minute += 59;
}
}
// runs the function every seconds
clockIt();
setInterval(function (){clockIt()}, 1000);
innerHTML does not execute ajax loaded scripts, what I would do in your case is to return a JSON encoded string with the variables that you need and have a function on your main script (the one thats already loaded) with this provided script, that way you already have the function ready and only pass parameters with the ajax response.
You can decode a json string with:
obj = JSON.parse(jsonString);
For example:
Ajax JSON response string:
{"time": {"hour":2, "minute":46, "second": 45}, "html": "<div class=\"time\">Time: <span id=\"timer\"></span></div>"}
Modified upgrade function:
function upgrade(building) {
var file = 'upgrade.php?building=' + building;
ajax(file, function(response) {
obj = JSON.parse(response);
time = obj.time;
document.getElementById('construction').innerHTML += obj.html;
startCountdown(time.hour, time.minute, time.second);
})
}
New function
function startCountdown(hour, minute, second) {
// function to make a counter
function clockIt() {
function clockO(digit) {
if(digit<10) {
return '0';
} else {
return '';
}
}
document.getElementById('timer').textContent = hour + ':' + clockO(minute) + minute + ':' + clockO(second) + second;
if(second>0) {
second -= 1;
} else if(minute>0) {
minute -= 1;
second += 59;
} else if(hour>0) {
hour -= 1;
minute += 59;
}
}
// runs the function every seconds
clockIt();
setInterval(function (){clockIt()}, 1000);
}
My problem was with the method for the countdown timer. When you specify an interval of 1000 milliseconds, you can't count on it being 1000 milliseconds. It's actually as soon as the timer loop gets to it after 1000 milliseconds have passed. Over a period of time, there are going to be some delays. What you want to do, if you want accurate timing, is to store the initial settings and then measure the time from when the countdown was started to the current time. See the code below which bases the timer on the internal clock rather than the interval counter. Once you have the number of seconds, you can easily it convert it to hours, minutes, and seconds by dividing by 3600 for the hours and using division and modulo arithmetic for the minute and second.
See https://www.sitepoint.com/creating-accurate-timers-in-javascript/
How to create an accurate timer in javascript?
<!DOCTYPE html />
<html>
<head>
<meta encoding="UTF-8" />
<title>Testing XMLHttpRequest</title>
<script>
var request;
var button1;
var display1;
var display2;
var display3;
var start;
var counter;
function second() {
display2.value = display2.value + "\r\nreadyState=" + request.readyState + " status=" + request.status + "\r\n";;
if (request.readyState == 4 && request.status == 200) {
display1.value = display1.value + request.responseText + "\r\n";
}
}
function first() {
display2.value = display2.value + "\r\n" +
"Starting page \r\n";
request = new XMLHttpRequest();
request.onreadystatechange = second;
var file = "http://localhost:80/";
request.open('GET', file, true);
request.send();
setInterval(timed, 1000);
}
function starter() {
display1 = document.getElementById("display1");
display2 = document.getElementById("display2");
display3 = document.getElementById("display3");
button1 = document.getElementById("button1");
button1.onclick = first;
start = new Date();
counter = 60;
}
function timed() {
var duration = (start.getTime() - new Date().getTime()) / 1000.0;
display3.value = (duration + counter).toFixed(0);
}
window.onload = starter;
</script>
</head>
<body>
<form>
<p>
<input type="button" id="button1" value="Start" />Timer:
<input type="text" readonly="readonly" id="display3" />
</p>
<p>Status:
<textarea rows="5" cols="30" id="display2"></textarea>
</p>
<p>Response:
<textarea rows="60" cols="80" id="display1"></textarea>
</p>
</form>
</body>
</html>
Found a way to compensate the delays, using the original version :
function upgrade(building) {
var file = 'upgrade.php?building=' + building;
ajax(file, function(response) {
var obj = JSON.parse(response);
var time = obj.time;
document.getElementById('construction').innerHTML += obj.html;
run_clockIt(time.hour, time.minute, time.second);
})
}
// general AJAX launcher
function ajax(file, fn) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
fn(xmlhttp.responseText);
}
};
xmlhttp.open('GET', file, true);
xmlhttp.send();
}
// count down timer with adjustments to compensate delay
function clockIt(hour, minute, second, finished, nbOfLoop) {
// every 5 seconds, run a delay correction
if(nbOfLoop%5 == 0) {
var actualTimeLeft = adjustClock(finished);
minute = actualTimeLeft[0];
second = actualTimeLeft[1];
}
nbOfLoop += 1;
// add a string "0" if necessary
function clockO(digit) {
if(digit<10) {
return '0';
} else {
return '';
}
}
document.getElementById('timer').textContent = hour + ':' + clockO(minute) + minute + ':' + clockO(second) + second;
// update displayed timer
if(second>0) {
second -= 1;
} else if(minute>0) {
minute -= 1;
second += 59;
} else if(hour>0) {
hour -= 1;
minute += 59;
}
// waits 1 sec before launching the next one
setTimeout(function() {
clockIt(hour, minute, second, finished, nbOfLoop);
}, 1000);
}
// runs the function for the first time
function run_clockIt(hour, minute, second) {
var finished = new Date();
finished.setUTCHours(finished.getUTCHours() + hour);
finished.setUTCMinutes(finished.getUTCMinutes() + minute);
finished.setUTCSeconds(finished.getUTCSeconds() + second);
clockIt(hour, minute, second, finished, 1);
}
function adjustClock(finished) {
var now = new Date();
var diff = new Date(Math.abs(now - finished));
return [diff.getUTCMinutes(), diff.getUTCSeconds()];
}
This way, the count down timer is smooth, no lagging and most of all you can define the interval on which the adjust function will run and correct the timer.
This is the php file, preparing the JSON object (thanks #Miguel) :
<?php
header('Content-Type: application/json');
// retreive variables from AJAX call
$building = $_REQUEST['building'];
// processing variable with database...
// prepare JSON object
$jsonData = '
{
"time":{"hour":2, "minute":46, "second": 45},
"html": "<div class=\"time\">Time: <span id=\"timer\"></span></div>"
}
';
echo $jsonData;

passing current timer's timing to the next page

How would i pass my current timer's timing into the next page?
Timer code
var expires = new Date();
expires.setSeconds(expires.getSeconds() + 60); // set timer to 60 seconds
var counter = setInterval(timer, 1);
function timer() {
var timeDiff = expires - new Date();
if (timeDiff <= 0) {
clearInterval(counter);
document.getElementById("timer").innerHTML = "00:00";
return;
}
var seconds = new Date(timeDiff).getSeconds();
var milliSeconds = (new Date(timeDiff).getMilliseconds()/10).toFixed(0);
var seconds = seconds < 10 ? "0" + seconds: seconds;
var milliSeconds = milliSeconds < 10 ? "0" + milliSeconds: milliSeconds;
document.getElementById("timer").innerHTML = seconds + ":" + milliSeconds; // watch for spelling
}
I'm using
<h3 style="color: #ff0000; margin: 0; padding: 0; font-size: 100%;font-weight:normal; font-family: robotolight;"> You have <div id="timer"></div> to complete the game!
in my html.
Is there a way to pass div id='timer'> into the next page?
Thanks.
Reloading the page or loading a new page means reloading javascript since it is runs in the context of the current page. There is good way to pass along javascript variables to a new page; it requires some form of data persistence. Cookies and localStorage are two of the most common ways of persisting data client-side.
Client cookies are written to the browser cache and are transparent in HTTP headers. LocalStorage is a newer mechanism but well supported, allowing up to 5MB of browser storage without passing in headers.
In your use case, instead of storing the timer it would probably make sense to store the timestamp when the timer was started. That way it can be recalculated in the next page from this one static start value.
var timerStart;
var expireDate = new Date();
function displayTimer(){
var now = new Date().getTime();
var timerStart = timerStart || cookieTimer();
val timeDiff = now - timerStart;
document.getElementById("timer").innerHTML = timeDiff.toString();
if(timeDiff > expireDate.getTime()) clearInterval(timerInterval);
}
val timerInterval = setInterval(displayTimer, 1);
// Using cookies
function cookieTimer(){
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for(var i=0; i<ca.length; i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1);
if (c.indexOf(name) != -1) return c.substring(name.length,c.length);
}
return "";
}
function setCookie(cname, cvalue, expireDate) {
var d = new Date();
d.setTime(d.getTime() + expireDate.getTime());
var expires = "expires="+d.toUTCString();
document.cookie = cname + "=" + cvalue + "; " + expires;
}
var timerCookie = getCookie("timer");
if(timerCookie !== "") return new Date(timerCookie).getTime());
else {
setCookie("timer", timerStart, expireDate);
return new Date().getTime();
}
}
// Using localStorage
function localStorageTimer(){
function setLocalStorageObject(key, obj, expireDate){
obj.expires = expireDate.getTime();
localStorage.setItem(key, JSON.stringify(obj));
}
function getLocalStorageObject(key){
val item = localStorage.getItem(key);
if(item) return JSON.parse(item);
else return {};
}
var timerLocal = getLocalStorageObject("timer");
var now = new Date().getTime();
if(timerLocal && timerLocal.startTime && timerLocal.expires > now) return timerLocal.startTime;
else {
setLocalStorageObject("timer", { startTime: now });
return now;
}
}

Categories

Resources