1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Copyright (c) 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)'use strict'; 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * A controller class detects mouse inactivity and hides "tool" elements. 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Element} container The main DOM container. 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {number=} opt_timeout Hide timeout in ms. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {function():boolean=} opt_toolsActive Function that returns |true| 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * if the tools are active and should not be hidden. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @constructor 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function MouseInactivityWatcher(container, opt_timeout, opt_toolsActive) { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_ = container; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.timeout_ = opt_timeout || MouseInactivityWatcher.DEFAULT_TIMEOUT; 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.toolsActive_ = opt_toolsActive || function() { return false; }; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.onTimeoutBound_ = this.onTimeout_.bind(this); 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.timeoutID_ = null; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.mouseOverTool_ = false; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.clientX_ = 0; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.clientY_ = 0; 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /** 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Indicates if the inactivity watcher is enabled or disabled. Use getters 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * and setters. 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @type {boolean} 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @private 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) **/ 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.disabled_ = false; 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.__defineSetter__('disabled', function(value) { 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.disabled_ = value; 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (value) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.kick(); 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.check(); 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }); 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.__defineGetter__('disabled', function() { 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return this.disabled_; 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }); 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_.addEventListener('mousemove', this.onMouseMove_.bind(this)); 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch var tools = this.container_.querySelector('.tool'); 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (var i = 0; i < tools.length; i++) { 49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch tools[i].addEventListener('mouseover', this.onToolMouseOver_.bind(this)); 50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch tools[i].addEventListener('mouseout', this.onToolMouseOut_.bind(this)); 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Show tools when the user touches the screen. 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.container_.addEventListener( 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'touchstart', this.activityStarted_.bind(this)); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var initiateFading = this.activityStopped_.bind(this, this.timeout_); 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.container_.addEventListener('touchend', initiateFading); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.container_.addEventListener('touchcancel', initiateFading); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Default inactivity timeout. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MouseInactivityWatcher.DEFAULT_TIMEOUT = 3000; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {boolean} on True if show, false if hide. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MouseInactivityWatcher.prototype.showTools = function(on) { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (on) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_.setAttribute('tools', 'true'); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.container_.removeAttribute('tools'); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * To be called when the user started activity. Shows the tools 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and cancels the countdown. 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @private 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MouseInactivityWatcher.prototype.activityStarted_ = function() { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.showTools(true); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.timeoutID_) { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clearTimeout(this.timeoutID_); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.timeoutID_ = null; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called when user activity has stopped. Re-starts the countdown. 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {number=} opt_timeout Timeout. 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @private 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MouseInactivityWatcher.prototype.activityStopped_ = function(opt_timeout) { 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (this.disabled_ || this.mouseOverTool_ || this.toolsActive_()) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.timeoutID_) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clearTimeout(this.timeoutID_); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.timeoutID_ = setTimeout( 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.onTimeoutBound_, opt_timeout || this.timeout_); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Called when a user performed a short action (such as a click or a key press) 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * that should show the tools if they are not visible. 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {number=} opt_timeout Timeout. 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MouseInactivityWatcher.prototype.kick = function(opt_timeout) { 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.activityStarted_(); 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.activityStopped_(opt_timeout); 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Check if the tools are active and update the tools visibility accordingly. 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)MouseInactivityWatcher.prototype.check = function() { 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (this.toolsActive_()) 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.activityStarted_(); 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.activityStopped_(); 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Mouse move handler. 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Event} e Event. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MouseInactivityWatcher.prototype.onMouseMove_ = function(e) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this.clientX_ == e.clientX && this.clientY_ == e.clientY) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The mouse has not moved, must be the cursor change triggered by 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // some of the attributes on the root container. Ignore the event. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.clientX_ = e.clientX; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.clientY_ = e.clientY; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (this.disabled_) 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this.kick(); 145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}; 146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/** 148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * Mouse over handler on a tool element. 149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * 150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * @param {Event} e Event. 151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * @private 152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch */ 153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochMouseInactivityWatcher.prototype.onToolMouseOver_ = function(e) { 154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this.mouseOverTool_ = true; 155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!this.disabled_) 156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this.kick(); 157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}; 158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/** 160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * Mouse out handler on a tool element. 161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * 162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * @param {Event} e Event. 163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * @private 164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch */ 165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochMouseInactivityWatcher.prototype.onToolMouseOut_ = function(e) { 166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this.mouseOverTool_ = false; 167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (!this.disabled_) 168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch this.kick(); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Timeout handler. 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MouseInactivityWatcher.prototype.onTimeout_ = function() { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.timeoutID_ = null; 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!this.disabled_ && !this.toolsActive_()) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.showTools(false); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 180