forked from thorst/jquery-idletimer
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request thorst#37 from rustygeldmacher/rg-timer-sync
Support for syncing timers across tabs
- Loading branch information
Showing
10 changed files
with
444 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,314 @@ | ||
/*! Idle Timer - v1.1.0 - 2016-03-21 | ||
* https://github.com/thorst/jquery-idletimer | ||
* Copyright (c) 2016 Paul Irish; Licensed MIT */ | ||
/* | ||
mousewheel (deprecated) -> IE6.0, Chrome, Opera, Safari | ||
DOMMouseScroll (deprecated) -> Firefox 1.0 | ||
wheel (standard) -> Chrome 31, Firefox 17, IE9, Firefox Mobile 17.0 | ||
//No need to use, use DOMMouseScroll | ||
MozMousePixelScroll -> Firefox 3.5, Firefox Mobile 1.0 | ||
//Events | ||
WheelEvent -> see wheel | ||
MouseWheelEvent -> see mousewheel | ||
MouseScrollEvent -> Firefox 3.5, Firefox Mobile 1.0 | ||
*/ | ||
(function ($) { | ||
|
||
$.idleTimer = function (firstParam, elem) { | ||
var opts; | ||
if ( typeof firstParam === "object" ) { | ||
opts = firstParam; | ||
firstParam = null; | ||
} else if (typeof firstParam === "number") { | ||
opts = { timeout: firstParam }; | ||
firstParam = null; | ||
} | ||
|
||
// element to watch | ||
elem = elem || document; | ||
|
||
// defaults that are to be stored as instance props on the elem | ||
opts = $.extend({ | ||
idle: false, // indicates if the user is idle | ||
timeout: 30000, // the amount of time (ms) before the user is considered idle | ||
events: "mousemove keydown wheel DOMMouseScroll mousewheel mousedown touchstart touchmove MSPointerDown MSPointerMove" // define active events | ||
}, opts); | ||
|
||
var jqElem = $(elem), | ||
obj = jqElem.data("idleTimerObj") || {}, | ||
|
||
/* (intentionally not documented) | ||
* Toggles the idle state and fires an appropriate event. | ||
* @return {void} | ||
*/ | ||
toggleIdleState = function (e) { | ||
var obj = $.data(elem, "idleTimerObj") || {}; | ||
|
||
// toggle the state | ||
obj.idle = !obj.idle; | ||
|
||
// store toggle state date time | ||
obj.olddate = +new Date(); | ||
|
||
// create a custom event, with state and name space | ||
var event = $.Event((obj.idle ? "idle" : "active") + ".idleTimer"); | ||
|
||
// trigger event on object with elem and copy of obj | ||
$(elem).trigger(event, [elem, $.extend({}, obj), e]); | ||
}, | ||
/** | ||
* Handle event triggers | ||
* @return {void} | ||
* @method event | ||
* @static | ||
*/ | ||
handleEvent = function (e) { | ||
var obj = $.data(elem, "idleTimerObj") || {}; | ||
|
||
if (e.type === "storage" && e.originalEvent.key !== obj.timerSyncId) { | ||
return; | ||
} | ||
|
||
// this is already paused, ignore events for now | ||
if (obj.remaining != null) { return; } | ||
|
||
/* | ||
mousemove is kinda buggy, it can be triggered when it should be idle. | ||
Typically is happening between 115 - 150 milliseconds after idle triggered. | ||
@psyafter & @kaellis report "always triggered if using modal (jQuery ui, with overlay)" | ||
@thorst has similar issues on ios7 "after $.scrollTop() on text area" | ||
*/ | ||
if (e.type === "mousemove") { | ||
// if coord are same, it didn't move | ||
if (e.pageX === obj.pageX && e.pageY === obj.pageY) { | ||
return; | ||
} | ||
// if coord don't exist how could it move | ||
if (typeof e.pageX === "undefined" && typeof e.pageY === "undefined") { | ||
return; | ||
} | ||
// under 200 ms is hard to do, and you would have to stop, as continuous activity will bypass this | ||
var elapsed = (+new Date()) - obj.olddate; | ||
if (elapsed < 200) { | ||
return; | ||
} | ||
} | ||
|
||
// clear any existing timeout | ||
clearTimeout(obj.tId); | ||
|
||
// if the idle timer is enabled, flip | ||
if (obj.idle) { | ||
toggleIdleState(e); | ||
} | ||
|
||
// store when user was last active | ||
obj.lastActive = +new Date(); | ||
|
||
// update mouse coord | ||
obj.pageX = e.pageX; | ||
obj.pageY = e.pageY; | ||
|
||
// sync lastActive | ||
if (e.type !== "storage" && obj.timerSyncId) { | ||
if (typeof(localStorage) !== "undefined") { | ||
localStorage.setItem(obj.timerSyncId, obj.lastActive); | ||
} | ||
} | ||
|
||
// set a new timeout | ||
obj.tId = setTimeout(toggleIdleState, obj.timeout); | ||
}, | ||
/** | ||
* Restore initial settings and restart timer | ||
* @return {void} | ||
* @method reset | ||
* @static | ||
*/ | ||
reset = function () { | ||
|
||
var obj = $.data(elem, "idleTimerObj") || {}; | ||
|
||
// reset settings | ||
obj.idle = obj.idleBackup; | ||
obj.olddate = +new Date(); | ||
obj.lastActive = obj.olddate; | ||
obj.remaining = null; | ||
|
||
// reset Timers | ||
clearTimeout(obj.tId); | ||
if (!obj.idle) { | ||
obj.tId = setTimeout(toggleIdleState, obj.timeout); | ||
} | ||
|
||
}, | ||
/** | ||
* Store remaining time, stop timer | ||
* You can pause from an idle OR active state | ||
* @return {void} | ||
* @method pause | ||
* @static | ||
*/ | ||
pause = function () { | ||
|
||
var obj = $.data(elem, "idleTimerObj") || {}; | ||
|
||
// this is already paused | ||
if ( obj.remaining != null ) { return; } | ||
|
||
// define how much is left on the timer | ||
obj.remaining = obj.timeout - ((+new Date()) - obj.olddate); | ||
|
||
// clear any existing timeout | ||
clearTimeout(obj.tId); | ||
}, | ||
/** | ||
* Start timer with remaining value | ||
* @return {void} | ||
* @method resume | ||
* @static | ||
*/ | ||
resume = function () { | ||
|
||
var obj = $.data(elem, "idleTimerObj") || {}; | ||
|
||
// this isn't paused yet | ||
if ( obj.remaining == null ) { return; } | ||
|
||
// start timer | ||
if ( !obj.idle ) { | ||
obj.tId = setTimeout(toggleIdleState, obj.remaining); | ||
} | ||
|
||
// clear remaining | ||
obj.remaining = null; | ||
}, | ||
/** | ||
* Stops the idle timer. This removes appropriate event handlers | ||
* and cancels any pending timeouts. | ||
* @return {void} | ||
* @method destroy | ||
* @static | ||
*/ | ||
destroy = function () { | ||
|
||
var obj = $.data(elem, "idleTimerObj") || {}; | ||
|
||
//clear any pending timeouts | ||
clearTimeout(obj.tId); | ||
|
||
//Remove data | ||
jqElem.removeData("idleTimerObj"); | ||
|
||
//detach the event handlers | ||
jqElem.off("._idleTimer"); | ||
}, | ||
/** | ||
* Returns the time until becoming idle | ||
* @return {number} | ||
* @method remainingtime | ||
* @static | ||
*/ | ||
remainingtime = function () { | ||
|
||
var obj = $.data(elem, "idleTimerObj") || {}; | ||
|
||
//If idle there is no time remaining | ||
if ( obj.idle ) { return 0; } | ||
|
||
//If its paused just return that | ||
if ( obj.remaining != null ) { return obj.remaining; } | ||
|
||
//Determine remaining, if negative idle didn't finish flipping, just return 0 | ||
var remaining = obj.timeout - ((+new Date()) - obj.lastActive); | ||
if (remaining < 0) { remaining = 0; } | ||
|
||
//If this is paused return that number, else return current remaining | ||
return remaining; | ||
}; | ||
|
||
|
||
// determine which function to call | ||
if (firstParam === null && typeof obj.idle !== "undefined") { | ||
// they think they want to init, but it already is, just reset | ||
reset(); | ||
return jqElem; | ||
} else if (firstParam === null) { | ||
// they want to init | ||
} else if (firstParam !== null && typeof obj.idle === "undefined") { | ||
// they want to do something, but it isnt init | ||
// not sure the best way to handle this | ||
return false; | ||
} else if (firstParam === "destroy") { | ||
destroy(); | ||
return jqElem; | ||
} else if (firstParam === "pause") { | ||
pause(); | ||
return jqElem; | ||
} else if (firstParam === "resume") { | ||
resume(); | ||
return jqElem; | ||
} else if (firstParam === "reset") { | ||
reset(); | ||
return jqElem; | ||
} else if (firstParam === "getRemainingTime") { | ||
return remainingtime(); | ||
} else if (firstParam === "getElapsedTime") { | ||
return (+new Date()) - obj.olddate; | ||
} else if (firstParam === "getLastActiveTime") { | ||
return obj.lastActive; | ||
} else if (firstParam === "isIdle") { | ||
return obj.idle; | ||
} | ||
|
||
/* (intentionally not documented) | ||
* Handles a user event indicating that the user isn't idle. namespaced with internal idleTimer | ||
* @param {Event} event A DOM2-normalized event object. | ||
* @return {void} | ||
*/ | ||
jqElem.on($.trim((opts.events + " ").split(" ").join("._idleTimer ")), function (e) { | ||
handleEvent(e); | ||
}); | ||
|
||
if (opts.timerSyncId) { | ||
$(window).bind("storage", handleEvent); | ||
} | ||
|
||
// Internal Object Properties, This isn't all necessary, but we | ||
// explicitly define all keys here so we know what we are working with | ||
obj = $.extend({}, { | ||
olddate : +new Date(), // the last time state changed | ||
lastActive: +new Date(), // the last time timer was active | ||
idle : opts.idle, // current state | ||
idleBackup : opts.idle, // backup of idle parameter since it gets modified | ||
timeout : opts.timeout, // the interval to change state | ||
remaining : null, // how long until state changes | ||
timerSyncId : opts.timerSyncId, // localStorage key to use for syncing this timer | ||
tId : null, // the idle timer setTimeout | ||
pageX : null, // used to store the mouse coord | ||
pageY : null | ||
}); | ||
|
||
// set a timeout to toggle state. May wish to omit this in some situations | ||
if (!obj.idle) { | ||
obj.tId = setTimeout(toggleIdleState, obj.timeout); | ||
} | ||
|
||
// store our instance on the object | ||
$.data(elem, "idleTimerObj", obj); | ||
|
||
return jqElem; | ||
}; | ||
|
||
// This allows binding to element | ||
$.fn.idleTimer = function (firstParam) { | ||
if (this[0]) { | ||
return $.idleTimer(firstParam, this[0]); | ||
} | ||
|
||
return this; | ||
}; | ||
|
||
})(jQuery); |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.