1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 2007, 2009, 2010, 2012, 2013, 2014, 2015, 2016 Synacor, Inc. 5 * 6 * The contents of this file are subject to the Common Public Attribution License Version 1.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at: https://www.zimbra.com/license 9 * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15 10 * have been added to cover use of software over a computer network and provide for limited attribution 11 * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B. 12 * 13 * Software distributed under the License is distributed on an "AS IS" basis, 14 * WITHOUT WARRANTY OF ANY KIND, either express or implied. 15 * See the License for the specific language governing rights and limitations under the License. 16 * The Original Code is Zimbra Open Source Web Client. 17 * The Initial Developer of the Original Code is Zimbra, Inc. All rights to the Original Code were 18 * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015. 19 * 20 * All portions of the code are Copyright (C) 2007, 2009, 2010, 2012, 2013, 2014, 2015, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * @class 26 * Simple manager for "idle" events. Add a handler like this: 27 * 28 * <pre> 29 * var idleTimer = new DwtIdleTimer(10000, new AjxCallback(obj, obj.handler)); 30 * 31 * obj.handler = function(idle) { 32 * if (idle) { 33 * // do idle stuff here 34 * } else { 35 * // user is back 36 * } 37 * } 38 * </pre> 39 * 40 * With this code, when the user is idle for 10 seconds obj.handler(true) will 41 * be called. When the user gets back from idle, obj.handler(false) will be 42 * called and the timer restarted. 43 * </p> 44 * <p> 45 * To cancel a timer, call <code>idleTimer.kill()</code>. To restart it later, you can 46 * <code>idleTimer.resurrect(timeout)</code>. The timeout parameter is optional, pass it only if you 47 * want to modify it. 48 * </p> 49 * <p> 50 * You can create multiple handlers, each with its own callback and timeout. A 51 * new {@link DwtIdleTimer} will start running right away and will continue to do so 52 * until you <code>kill()</code> it. 53 * </p> 54 * 55 * @param {number} [timeout] the timeout 56 * @param {AjxCallback} handler the callback 57 * 58 * @private 59 */ 60 DwtIdleTimer = function(timeout, handler) { 61 DwtIdleTimer._initEvents(); 62 this.timeout = timeout; 63 this.handler = handler; 64 this.idle = false; 65 this._onIdle = AjxCallback.simpleClosure(this.setIdle, this); 66 this._startTimer(); 67 DwtIdleTimer.getHandlers().add(this); 68 }; 69 70 DwtIdleTimer.idleHandlers = 0; 71 72 DwtIdleTimer.prototype.toString = 73 function() { 74 return "DwtIdleTimer"; 75 }; 76 77 DwtIdleTimer.prototype.kill = 78 function() { 79 this._stopTimer(); 80 this.idle = false; 81 DwtIdleTimer.getHandlers().remove(this); 82 }; 83 84 DwtIdleTimer.prototype.resurrect = 85 function(timeout) { 86 this.idle = false; // make sure we start "unidle" 87 DwtIdleTimer.getHandlers().add(this, null, true); 88 if (timeout != null) { 89 this.timeout = timeout; 90 } 91 this._startTimer(); 92 }; 93 94 DwtIdleTimer.prototype.setIdle = 95 function() { 96 if (!this.idle) { 97 DwtIdleTimer.idleHandlers++; 98 this.idle = true; 99 this.handler.run(true); 100 } 101 }; 102 103 DwtIdleTimer.prototype.resume = 104 function() { 105 if (this.idle) { 106 this.idle = false; 107 this.handler.run(false); 108 DwtIdleTimer.idleHandlers--; 109 } 110 }; 111 112 DwtIdleTimer.prototype._startTimer = 113 function() { 114 this._stopTimer(); 115 this._timer = setTimeout(this._onIdle, this.timeout); 116 }; 117 118 DwtIdleTimer.prototype._stopTimer = 119 function() { 120 if (this._timer) { 121 clearTimeout(this._timer); 122 this._timer = null; 123 } 124 }; 125 126 DwtIdleTimer._initEvents = 127 function() { 128 // execute only once per session 129 if (!DwtIdleTimer._initialized) { 130 if (window.addEventListener) { 131 window.addEventListener("keydown", DwtIdleTimer.resetIdle, true); 132 window.addEventListener("mousemove", DwtIdleTimer.resetIdle, true); 133 window.addEventListener("mousedown", DwtIdleTimer.resetIdle, true); 134 window.addEventListener("focus", DwtIdleTimer.resetIdle, true); 135 } 136 else if (window.attachEvent) { 137 document.body.attachEvent("onkeydown", DwtIdleTimer.resetIdle); 138 document.body.attachEvent("onkeyup", DwtIdleTimer.resetIdle); 139 document.body.attachEvent("onmousedown", DwtIdleTimer.resetIdle); 140 document.body.attachEvent("onmousemove", DwtIdleTimer.resetIdle); 141 document.body.attachEvent("onmouseover", DwtIdleTimer.resetIdle); 142 document.body.attachEvent("onmouseout", DwtIdleTimer.resetIdle); 143 window.attachEvent("onfocus", DwtIdleTimer.resetIdle); 144 } 145 DwtIdleTimer._initialized = true; 146 } 147 }; 148 149 DwtIdleTimer.getHandlers = 150 function() { 151 var a = DwtIdleTimer.HANDLERS; 152 if (!a) { 153 a = DwtIdleTimer.HANDLERS = new AjxVector(); 154 } 155 return a; 156 }; 157 158 DwtIdleTimer.resetIdle = 159 function() { 160 var a = DwtIdleTimer.getHandlers(); 161 a.foreach("_startTimer"); // we need to restart timers anyway... 162 if (DwtIdleTimer.idleHandlers > 0) { 163 a.foreach("resume"); 164 } 165 }; 166