OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * @fileoverview | 6 * @fileoverview |
7 * Class representing the client tool-bar. | 7 * Class representing the client tool-bar. |
8 */ | 8 */ |
9 | 9 |
10 'use strict'; | 10 'use strict'; |
11 | 11 |
12 /** @suppress {duplicate} */ | 12 /** @suppress {duplicate} */ |
13 var remoting = remoting || {}; | 13 var remoting = remoting || {}; |
14 | 14 |
15 /** | 15 /** |
16 * @param {Element} toolbar The HTML element representing the tool-bar. | 16 * @param {Element} toolbar The HTML element representing the tool-bar. |
17 * @constructor | 17 * @constructor |
18 */ | 18 */ |
19 remoting.Toolbar = function(toolbar) { | 19 remoting.Toolbar = function(toolbar) { |
20 /** | 20 /** |
21 * @type {Element} | 21 * @type {Element} |
22 * @private | 22 * @private |
23 */ | 23 */ |
24 this.toolbar_ = toolbar; | 24 this.toolbar_ = toolbar; |
25 /** | 25 /** |
26 * @type {boolean} False if the tool-bar is currently hidden, or should be | 26 * @type {Element} |
27 * hidden once the over-shoot timer expires; true otherwise. | 27 * @private |
28 */ | 28 */ |
29 this.visible = false; | 29 this.stub_ = toolbar.querySelector('.toolbar-stub'); |
30 /** | 30 /** |
31 * @type {number?} The id of the current timer, if any. | 31 * @type {number?} The id of the preview timer, if any. |
| 32 * @private |
32 */ | 33 */ |
33 this.timerId = null; | 34 this.timerId_ = null; |
| 35 /** |
| 36 * @type {number} The left edge of the tool-bar stub, updated on resize. |
| 37 * @private |
| 38 */ |
| 39 this.stubLeft_ = 0; |
| 40 /** |
| 41 * @type {number} The right edge of the tool-bar stub, updated on resize. |
| 42 * @private |
| 43 */ |
| 44 this.stubRight_ = 0; |
34 | 45 |
35 /** @type {remoting.Toolbar} */ | 46 /** @type {remoting.Toolbar} */ |
36 var that = this; | 47 var that = this; |
37 | 48 |
38 /** | 49 window.addEventListener('mousemove', remoting.Toolbar.onMouseMove, false); |
39 * @param {Event} event The mouseout event, used to determine whether or | 50 window.addEventListener('resize', function() { that.center(); }, false); |
40 * not the mouse is leaving the tool-bar or (due to event-bubbling) | 51 |
41 * one of its children. | 52 // Prevent the preview canceling if the user is interacting with the tool-bar. |
42 */ | 53 var stopTimer = function() { |
43 var onMouseOut = function(event) { | 54 if (that.timerId_) { |
44 for (var e = event.toElement; e != null; e = e.parentElement) { | 55 window.clearTimeout(that.timerId_); |
45 if (e == that.toolbar_) { | 56 that.timerId_ = null; |
46 return; // Still over a child element => ignore. | |
47 } | |
48 } | 57 } |
49 that.hide_(); | 58 } |
50 }; | 59 this.toolbar_.addEventListener('mousemove', stopTimer, false); |
51 this.toolbar_.onmouseout = onMouseOut; | |
52 | |
53 this.toolbar_.onmouseover = function() { | |
54 that.showForAtLeast_(1000); | |
55 }; | |
56 | |
57 window.addEventListener('resize', function() { that.center(); }, false); | |
58 }; | 60 }; |
59 | 61 |
60 /** | 62 /** |
61 * Preview the tool-bar functionality by showing it for 3s if it is not | 63 * Preview the tool-bar functionality by showing it for 3s. |
62 * already visible. | |
63 * @return {void} Nothing. | 64 * @return {void} Nothing. |
64 */ | 65 */ |
65 remoting.Toolbar.prototype.preview = function() { | 66 remoting.Toolbar.prototype.preview = function() { |
66 this.showForAtLeast_(3000); | 67 addClass(this.toolbar_, remoting.Toolbar.VISIBLE_CLASS_); |
67 this.visible = false; | 68 if (this.timerId_) { |
| 69 window.clearTimeout(this.timerId_); |
| 70 this.timerId_ = null; |
| 71 } |
| 72 /** @type {remoting.Toolbar} */ |
| 73 var that = this; |
| 74 var endPreview = function() { |
| 75 removeClass(that.toolbar_, remoting.Toolbar.VISIBLE_CLASS_); |
| 76 }; |
| 77 this.timerId_ = window.setTimeout(endPreview, 3000); |
68 }; | 78 }; |
69 | 79 |
70 /** | 80 /** |
71 * Center the tool-bar horizonally. | 81 * Center the tool-bar horizonally. |
72 */ | 82 */ |
73 remoting.Toolbar.prototype.center = function() { | 83 remoting.Toolbar.prototype.center = function() { |
74 var toolbarX = (window.innerWidth - this.toolbar_.clientWidth) / 2; | 84 var toolbarX = (window.innerWidth - this.toolbar_.clientWidth) / 2; |
75 this.toolbar_.style['left'] = toolbarX + 'px'; | 85 this.toolbar_.style['left'] = toolbarX + 'px'; |
| 86 var r = this.stub_.getBoundingClientRect(); |
| 87 this.stubLeft_ = r.left; |
| 88 this.stubRight_ = r.right; |
76 }; | 89 }; |
77 | 90 |
78 /** | 91 /** |
79 * If the tool-bar is not currently visible, show it and start a timer to | 92 * Toggle the tool-bar visibility. |
80 * prevent it from being hidden again for a short time. This is to guard | |
81 * against users over-shooting the tool-bar stub when trying to access it. | |
82 * | |
83 * @param {number} timeout The minimum length of time, in ms, for which to | |
84 * show the tool-bar. If the hide_() method is called within this time, | |
85 * it will not take effect until the timeout expires. | |
86 * @return {void} Nothing. | |
87 * @private | |
88 */ | 93 */ |
89 remoting.Toolbar.prototype.showForAtLeast_ = function(timeout) { | 94 remoting.Toolbar.prototype.toggle = function() { |
90 if (this.visible) { | 95 if (hasClass(this.toolbar_.className, |
91 return; | 96 remoting.Toolbar.VISIBLE_CLASS_)) { |
92 } | 97 removeClass(this.toolbar_, remoting.Toolbar.VISIBLE_CLASS_); |
93 addClass(this.toolbar_, remoting.Toolbar.VISIBLE_CLASS_); | 98 } else { |
94 this.visible = true; | 99 addClass(this.toolbar_, remoting.Toolbar.VISIBLE_CLASS_); |
95 if (this.timerId) { | |
96 window.clearTimeout(this.timerId); | |
97 this.timerId = null; | |
98 } | |
99 /** @type {remoting.Toolbar} */ | |
100 var that = this; | |
101 var checkVisibility = function() { that.checkVisibility_(); }; | |
102 this.timerId = window.setTimeout(checkVisibility, timeout); | |
103 }; | |
104 | |
105 /** | |
106 * Hide the tool-bar if it is visible. If there is a visibility timer running, | |
107 * the tool-bar will not be hidden until it expires. | |
108 * | |
109 * @return {void} Nothing. | |
110 * @private | |
111 */ | |
112 remoting.Toolbar.prototype.hide_ = function() { | |
113 if (!this.visible) { | |
114 return; | |
115 } | |
116 this.visible = false; | |
117 if (!this.timerId) { | |
118 this.checkVisibility_(); | |
119 } | 100 } |
120 }; | 101 }; |
121 | 102 |
122 /** | 103 /** |
123 * Hide the tool-bar if it is visible and should not be. | 104 * Test the specified co-ordinate to see if it is close enough to the stub |
| 105 * to activate it. |
124 * | 106 * |
125 * @return {void} Nothing. | 107 * @param {number} x The x co-ordinate. |
| 108 * @param {number} y The y co-ordinate. |
| 109 * @return {boolean} True if the position should activate the tool-bar stub, or |
| 110 * false otherwise. |
126 * @private | 111 * @private |
127 */ | 112 */ |
128 remoting.Toolbar.prototype.checkVisibility_ = function() { | 113 remoting.Toolbar.prototype.hitTest_ = function(x, y) { |
129 this.timerId = null; | 114 var threshold = 50; |
130 if (!this.visible) { | 115 return (x >= this.stubLeft_ - threshold && |
131 removeClass(this.toolbar_, remoting.Toolbar.VISIBLE_CLASS_); | 116 x <= this.stubRight_ + threshold && |
| 117 y < threshold); |
| 118 }; |
| 119 |
| 120 /** |
| 121 * Called whenever the mouse moves in the document. This is used to make the |
| 122 * active area of the tool-bar stub larger without making a corresponding area |
| 123 * of the host screen inactive. |
| 124 * |
| 125 * @param {Event} event The mouse move event. |
| 126 * @return {void} Nothing. |
| 127 */ |
| 128 remoting.Toolbar.onMouseMove = function(event) { |
| 129 if (remoting.toolbar) { |
| 130 if (remoting.toolbar.hitTest_(event.x, event.y)) { |
| 131 addClass(remoting.toolbar.stub_, remoting.Toolbar.STUB_EXTENDED_CLASS_); |
| 132 } else { |
| 133 removeClass(remoting.toolbar.stub_, |
| 134 remoting.Toolbar.STUB_EXTENDED_CLASS_); |
| 135 } |
| 136 } else { |
| 137 document.removeEventListener('mousemove', |
| 138 remoting.Toolbar.onMouseMove, false); |
132 } | 139 } |
133 }; | 140 }; |
134 | 141 |
135 /** @type {remoting.Toolbar} */ | 142 /** @type {remoting.Toolbar} */ |
136 remoting.toolbar = null; | 143 remoting.toolbar = null; |
137 | 144 |
138 /** @private */ | 145 /** @private */ |
| 146 remoting.Toolbar.STUB_EXTENDED_CLASS_ = 'toolbar-stub-extended'; |
| 147 /** @private */ |
139 remoting.Toolbar.VISIBLE_CLASS_ = 'toolbar-visible'; | 148 remoting.Toolbar.VISIBLE_CLASS_ = 'toolbar-visible'; |
OLD | NEW |