0

I have modal box that should show if warning timer is triggered. Here is example of my code:

var sessionMinutes = 5, // Session length in minutes.
  secondsToModal = 120, // Set number of seconds until modal shows on the screen.
  sessionBox, // Session timeout warning box. 
  nextPoll = false, // Flag to set next timeout.
  showModal = false, // Flag to show/hide modal warning.
  sessionTimedOut = false, // Set flag for session timeout.
  timerSeconds, // Interval function for count down number of seconds.
  lastActivity = null,
  pingTime = 1; // Set the ping time in minutes.

function TimeOut() {
  sessionBox = $('<div id="sessiontimeoutwarning" class="modal fade" role="dialog"><div class="modal-dialog modal-lg"><div class="modal-content"><div class="modal-header"><h2 class="modal-title warning"><span class="glyphicon glyphicon-warning-sign"></span> Your session is about to expire</h2></div><div class="modal-body"><div class="alert alert-warning warning"><strong>Warning!</strong> Click the Continue button to extend your session. Session will expire in <span id="showSeconds"></span> second(s) left.</div></div><div class="modal-footer"><button type="button" id="continueButton" class="btn btn-primary" data-dismiss="modal">Continue</button></div></div></div></div>');
  $(document.body).append(sessionBox);
  $('body').on('mousedown keydown', function(event) {
    lastActivity = new Date();
    if (timerSeconds) {
      clearInterval(timerSeconds);
    }
  });

  pingTimer(); // Start ping timer function.
}

function pingTimer() {
  if (sessionTimedOut) { // Check if session timedout and prevent function to run in that case.
    return;
  }

  if (nextPoll) {
    clearTimeout(nextPoll);
  }

  var wakeUpMillis = pingTime * 60 * 1000;
  nextPoll = setTimeout(isActive, wakeUpMillis);
  log('pingTimer: ' + wakeUpMillis);
}

function isActive() {
  var currentTime = new Date(),
    wakeUpMillis;

  if (lastActivity !== null && currentTime > lastActivity) {
    log('Send Ping/Keep session alive for another ' + sessionMinutes + ' minute(s).');
    sendPing();
  } else {
    // Subtract ping time and seconds to modal from total session time. 
    wakeUpMillis = (sessionMinutes * 60 * 1000) - (pingTime * 60 * 1000) - (secondsToModal * 1000);
    log('Warning modal will show up in ' + wakeUpMillis / 1000 + ' second(s)');
    nextPoll = setTimeout(showWarning, wakeUpMillis)
  }
}

function sendPing() {
  if (lastActivity !== null) {
    pingTimer(); // Run ping function
    lastActivity = null; // Set last activity to null that way we can keep track of user activity fresh.
    /* Commented out for stack overfllow
    $.ajax({
      type: 'POST',
      url: "AjaxFunctions.cfc?method=keepSessionAlive",
      dataType: 'json'
    }).done(function(obj) {
      pingTimer(); // Run ping function
      lastActivity = null; // Set last activity to null that way we can keep track of user activity fresh.
    }).fail(function(jqXHR, textStatus, errorThrown) {
      alert("Error: " + errorThrown);
    }).always(function(jqXHR) {
      if (jqXHR.status == 401) {
        timedOut();
      }
    });
    */
  }
}

function showWarning() {
  var seconds = secondsToModal,
    untilTimeout = secondsToModal * 1000;

  $('#sessiontimeoutwarning').modal('show');
  showModal = true;
  log('untilTimeout: ' + untilTimeout);

  nextPoll = setTimeout(timedOut, untilTimeout);

  $('#showSeconds').text(120);
  timerSeconds = setInterval(function() {
    seconds--;

    if (seconds == 0) {
      clearInterval(timerSeconds);
    } else {
      $('#showSeconds').text(seconds);
    }
  }, 1000);

  sessionBox.find('#continueButton').on('click', function() {
    lastActivity = new Date();
    sendPing();
    showModal = false;
  });
}

function timedOut() {
  $("#main-container").empty().html("<div class='panel panel-default'><div class='panel-heading'><h2><span class='glyphicon glyphicon-lock'></span> You've been signed out</h2></div><div class='panel-body'><div class='alert alert-info'><p>Click <a href='Login.cfm'><b><u>here</u></b></a> to return to login page.</p></div></div></div>"); // Clear all elements from the screen and show the message.
  $('#sessiontimeoutwarning').modal('hide'); // Close modal box;
  sessionTimedOut = true; // If session timed out then do not reset anything.

  /* Commented out for stack overfllow
  window.onbeforeunload = null;
  $.ajax({
    type: 'POST',
    url: 'AjaxFunctions.cfc?method=LogOut',
    data: {
      'timedOut': '1'
    },
    dataType: 'json'
  }).done(function(obj) {
    if (obj.STATUS == "200") {
      showModal = false;
    } else {
      alert(obj.MESSAGE);
    }
  }).fail(function(jqXHR, textStatus, errorThrown) {
    alert("Error: " + errorThrown);
  });
  */
}

function log(msg) {
  if (window.console && console.log)
    console.log(new Date().toLocaleTimeString() + " :: " + msg);
}
<!DOCTYPE html>
<html lang="en">

<head>
  <title>My Application</title>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
  <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
  <script>
    $(document).ready(function(){
      TimeOut(); // Call session timeout function.
    });
  </script>
</head>

<body>
  <div id="main-container">App Body</div>
</body>

</html>

I have tested this on all browsers on my laptop and worked fine but when I tested on my iPad (Safari) and my Samsung Galaxy S8 (Chrome) modal box didn't show up. I'm wondering if there is any issue with Bootstrap or tere might be some other problem? Here is example of how I show/hide modal box:

$('#sessiontimeoutwarning').modal('show');
$('#sessiontimeoutwarning').modal('hide');

If anyone knows what could be the problem please let me know. Thank you.

espresso_coffee
  • 5,076
  • 9
  • 53
  • 124
  • @Sphinx How to deal with that issue? Any work around solution? – espresso_coffee Mar 26 '18 at 23:44
  • Can you show your codes how to determinate the session expires or not? – Sphinx Mar 26 '18 at 23:46
  • @Sphinx Working example is posted. Please take a look. Thanks. – espresso_coffee Mar 26 '18 at 23:48
  • Your current mechanism (`setTimeout(function(){}, 1*60*1000`) may not work properly as some mobile system may suspend the threads that causes the setTimeout stay at the same stage as it was locked. Just like the clock stops, so setTimeout will not be triggered even the user unlock in one minute). My idea, you should create one `setTImeout(function(){}, 1*1000)`, and save the current datetime, then check isActive with current datetime with previous datetime. – Sphinx Mar 27 '18 at 00:04
  • check this:[https://stackoverflow.com/questions/16521768/automatic-session-timeout-iphone](https://stackoverflow.com/questions/16521768/automatic-session-timeout-iphone) – Sphinx Mar 27 '18 at 00:05
  • @Sphinx Can you update my example and show how to change/modify the code to work on mobile device when screen is locked? – espresso_coffee Mar 27 '18 at 00:22
  • check this [automatic session timeout iphone](https://stackoverflow.com/questions/15959244/is-it-possible-in-javascript-to-detect-when-the-screen-is-turned-off-in-the-an), it provides some working samples ( I recommended the answer from @Nathan Friedly). – Sphinx Mar 27 '18 at 00:35
  • @Sphinx I think that will be the way to go. Probably end the user session once their phone is locked or not run my timer function in that case and relay on server side session timeout.? – espresso_coffee Mar 27 '18 at 00:40

0 Answers0