/** * @file * JavaScript for autologout. */ (function ($, Drupal) { 'use strict'; /** * Attaches the batch behavior for autologout. * * @type {Drupal~behavior} */ Drupal.behaviors.autologout = { attach: function (context, settings) { if (context !== document) { return; } var paddingTimer; var theDialog; var t; var localSettings; // Activity is a boolean used to detect a user has // interacted with the page. var activity; // Timer to keep track of activity resets. var activityResetTimer; // Prevent settings being overridden by ajax callbacks by cloning it. localSettings = jQuery.extend(true, {}, settings.autologout); // Add timer element to prevent detach of all behaviours. var timerMarkup = $('
').hide(); $('body').append(timerMarkup); if (localSettings.refresh_only) { // On pages where user shouldn't be logged out, don't set the timer. t = setTimeout(keepAlive, localSettings.timeout); } else { // Set no activity to start with. activity = false; // Bind formUpdated events to preventAutoLogout event. $('body').bind('formUpdated', function (event) { $(event.target).trigger('preventAutologout'); }); // Bind formUpdated events to preventAutoLogout event. $('body').bind('mousemove', function (event) { $(event.target).trigger('preventAutologout'); }); // Support for CKEditor. if (typeof CKEDITOR !== 'undefined') { CKEDITOR.on('instanceCreated', function (e) { e.editor.on('contentDom', function () { e.editor.document.on('keyup', function (event) { // Keyup event in ckeditor should prevent autologout. $(e.editor.element.$).trigger('preventAutologout'); }); }); }); } $('body').bind('preventAutologout', function (event) { // When the preventAutologout event fires, we set activity to true. activity = true; // Clear timer if one exists. clearTimeout(activityResetTimer); // Set a timer that goes off and resets this activity indicator after // a minute, otherwise sessions never timeout. activityResetTimer = setTimeout(function () { activity = false; }, 60000); }); // On pages where the user should be logged out, set the timer to popup // and log them out. t = setTimeout(init, localSettings.timeout); } function init() { var noDialog = settings.autologout.no_dialog; if (activity) { // The user has been active on the page. activity = false; refresh(); } else { // The user has not been active, ask them if they want to stay logged // in and start the logout timer. paddingTimer = setTimeout(confirmLogout, localSettings.timeout_padding); // While the countdown timer is going, lookup the remaining time. If // there is more time remaining (i.e. a user is navigating in another // tab), then reset the timer for opening the dialog. Drupal.Ajax['autologout.getTimeLeft'].autologoutGetTimeLeft(function (time) { if (time > 0) { clearTimeout(paddingTimer); t = setTimeout(init, time); } else { // Logout user right away without displaying a confirmation dialog. if (noDialog) { logout(); return; } theDialog = dialog(); } }); } } function dialog() { var buttons = {}; buttons[Drupal.t('Yes')] = function () { $(this).dialog("destroy"); clearTimeout(paddingTimer); refresh(); }; buttons[Drupal.t('No')] = function () { $(this).dialog("destroy"); logout(); }; return $('
' + localSettings.message + '
').dialog({ modal: true, closeOnEscape: false, width: "auto", dialogClass: 'autologout-dialog', title: localSettings.title, buttons: buttons, close: function (event, ui) { logout(); } }); } // A user could have used the reset button on the tab/window they're // actively using, so we need to double check before actually logging out. function confirmLogout() { $(theDialog).dialog('destroy'); Drupal.Ajax['autologout.getTimeLeft'].autologoutGetTimeLeft(function (time) { if (time > 0) { t = setTimeout(init, time); } else { logout(); } }); } function logout() { if (localSettings.use_alt_logout_method) { window.location = drupalSettings.path.baseUrl + "autologout_ahah_logout"; } else { $.ajax({ url: drupalSettings.path.baseUrl + "autologout_ahah_logout", type: "POST", beforeSend: function (xhr) { xhr.setRequestHeader('X-Requested-With', { toString: function (){ return ''; } }); }, success: function () { window.location = localSettings.redirect_url; }, error: function (XMLHttpRequest, textStatus) { if (XMLHttpRequest.status === 403 || XMLHttpRequest.status === 404) { window.location = localSettings.redirect_url; } } }); } } /** * Get the remaining time. * * Use the Drupal ajax library to handle get time remaining events * because if using the JS Timer, the return will update it. * * @param function callback(time) * The function to run when ajax is successful. The time parameter * is the time remaining for the current user in ms. */ Drupal.Ajax.prototype.autologoutGetTimeLeft = function (callback) { var ajax = this; if (ajax.ajaxing) { return false; } ajax.options.success = function (response, status) { if (typeof response == 'string') { response = $.parseJSON(response); } if (typeof response[0].command === 'string' && response[0].command === 'alert') { // In the event of an error, we can assume user has been logged out. window.location = localSettings.redirect_url; } callback(response[1].settings.time); response[0].data = ''; // Let Drupal.ajax handle the JSON response. return ajax.success(response, status); }; try { $.ajax(ajax.options); } catch (e) { ajax.ajaxing = false; } }; Drupal.Ajax['autologout.getTimeLeft'] = Drupal.ajax({ base: null, element: document.body, url: drupalSettings.path.baseUrl + 'autologout_ajax_get_time_left', event: 'autologout.getTimeLeft', error: function (XMLHttpRequest, textStatus) { // Disable error reporting to the screen. } }); /** * Handle refresh event. * * Use the Drupal ajax library to handle refresh events because if using * the JS Timer, the return will update it. * * @param function timerFunction * The function to tell the timer to run after its been restarted. */ Drupal.Ajax.prototype.autologoutRefresh = function (timerfunction) { var ajax = this; if (ajax.ajaxing) { return false; } ajax.options.success = function (response, status) { if (typeof response === 'string') { response = $.parseJSON(response); } if (typeof response[0].command === 'string' && response[0].command === 'alert') { // In the event of an error, we can assume the user has been logged out. window.location = localSettings.redirect_url; } t = setTimeout(timerfunction, localSettings.timeout); activity = false; // Wrap response data in timer markup to prevent detach of all behaviors. response[0].data = ''; // Let Drupal.ajax handle the JSON response. return ajax.success(response, status); }; try { $.ajax(ajax.options); } catch (e) { ajax.ajaxing = false; } }; Drupal.Ajax['autologout.refresh'] = Drupal.ajax({ base: null, element: document.body, url: drupalSettings.path.baseUrl + 'autologout_ahah_set_last', event: 'autologout.refresh', error: function (XMLHttpRequest, textStatus) { // Disable error reporting to the screen. } }); function keepAlive() { Drupal.Ajax['autologout.refresh'].autologoutRefresh(keepAlive); } function refresh() { Drupal.Ajax['autologout.refresh'].autologoutRefresh(init); } // Check if the page was loaded via a back button click. var $dirty_bit = $('#autologout-cache-check-bit'); if ($dirty_bit.length !== 0) { if ($dirty_bit.val() === '1') { // Page was loaded via back button click, we should refresh the timer. refresh(); } $dirty_bit.val('1'); } } }; })(jQuery, Drupal);