OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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; |
garykac
2012/02/01 18:24:48
I have concerns that this threshold might be too l
Jamie
2012/02/01 19:22:20
You may be right. I'm certainly happy to iterate o
| |
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 |