browser/metro/base/content/ContextUI.js

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 // Fired when the tabtray is displayed
michael@0 6 const kContextUITabsShowEvent = "MozContextUITabsShow";
michael@0 7 // add more as needed...
michael@0 8
michael@0 9 /*
michael@0 10 * Manages context UI (navbar, tabbar, appbar) and track visibility. Also
michael@0 11 * tracks events that summon and hide the context UI.
michael@0 12 */
michael@0 13 var ContextUI = {
michael@0 14 _expandable: true,
michael@0 15 _hidingId: 0,
michael@0 16
michael@0 17 /*******************************************
michael@0 18 * init
michael@0 19 */
michael@0 20
michael@0 21 init: function init() {
michael@0 22 Elements.browsers.addEventListener('URLChanged', this, true);
michael@0 23 Elements.browsers.addEventListener("AlertActive", this, true);
michael@0 24 Elements.browsers.addEventListener("AlertClose", this, true);
michael@0 25 Elements.tabList.addEventListener('TabSelect', this, true);
michael@0 26 Elements.panelUI.addEventListener('ToolPanelShown', this, false);
michael@0 27 Elements.panelUI.addEventListener('ToolPanelHidden', this, false);
michael@0 28
michael@0 29 Elements.tray.addEventListener("mousemove", this, false);
michael@0 30 Elements.tray.addEventListener("mouseleave", this, false);
michael@0 31
michael@0 32 window.addEventListener("touchstart", this, true);
michael@0 33 window.addEventListener("mousedown", this, true);
michael@0 34 window.addEventListener("MozEdgeUIStarted", this, true);
michael@0 35 window.addEventListener("MozEdgeUICanceled", this, true);
michael@0 36 window.addEventListener("MozEdgeUICompleted", this, true);
michael@0 37 window.addEventListener("keypress", this, true);
michael@0 38 window.addEventListener("KeyboardChanged", this, false);
michael@0 39 window.addEventListener("MozFlyoutPanelShowing", this, false);
michael@0 40
michael@0 41 Elements.tray.addEventListener("transitionend", this, true);
michael@0 42
michael@0 43 Appbar.init();
michael@0 44 },
michael@0 45
michael@0 46 /*******************************************
michael@0 47 * Context UI state getters & setters
michael@0 48 */
michael@0 49
michael@0 50 // any visiblilty
michael@0 51 get isVisible() {
michael@0 52 return this.navbarVisible || this.tabbarVisible || this.contextAppbarVisible;
michael@0 53 },
michael@0 54
michael@0 55 // navbar visiblilty
michael@0 56 get navbarVisible() {
michael@0 57 return (Elements.navbar.hasAttribute("visible") ||
michael@0 58 Elements.navbar.hasAttribute("startpage"));
michael@0 59 },
michael@0 60
michael@0 61 // tabbar visiblilty
michael@0 62 get tabbarVisible() {
michael@0 63 return Elements.tray.hasAttribute("expanded");
michael@0 64 },
michael@0 65
michael@0 66 // appbar visiblilty
michael@0 67 get contextAppbarVisible() {
michael@0 68 return Elements.contextappbar.isShowing;
michael@0 69 },
michael@0 70
michael@0 71 // currently not in use, for the always show tabs feature
michael@0 72 get isExpandable() { return this._expandable; },
michael@0 73 set isExpandable(aFlag) {
michael@0 74 this._expandable = aFlag;
michael@0 75 if (!this._expandable)
michael@0 76 this.dismiss();
michael@0 77 },
michael@0 78
michael@0 79 /*******************************************
michael@0 80 * Public api
michael@0 81 */
michael@0 82
michael@0 83 /*
michael@0 84 * Toggle the current nav UI state. Fires context ui events.
michael@0 85 */
michael@0 86 toggleNavUI: function () {
michael@0 87 // The navbar is forced open when the start page is visible. appbar.js
michael@0 88 // controls the "visible" property, and browser-ui controls the "startpage"
michael@0 89 // property. Hence we rely on the tabbar for current toggle state.
michael@0 90 if (this.tabbarVisible) {
michael@0 91 this.dismiss();
michael@0 92 } else {
michael@0 93 this.displayNavUI();
michael@0 94 }
michael@0 95 },
michael@0 96
michael@0 97 /*
michael@0 98 * Show the nav and tabs bar. Returns true if any non-visible UI
michael@0 99 * was shown. Fires context ui events.
michael@0 100 */
michael@0 101 displayNavUI: function () {
michael@0 102 let shown = false;
michael@0 103
michael@0 104 if (!this.navbarVisible) {
michael@0 105 BrowserUI.updateURI();
michael@0 106 this.displayNavbar();
michael@0 107 shown = true;
michael@0 108 }
michael@0 109
michael@0 110 if (!this.tabbarVisible) {
michael@0 111 this.displayTabs();
michael@0 112 shown = true;
michael@0 113 }
michael@0 114
michael@0 115 if (shown) {
michael@0 116 ContentAreaObserver.updateContentArea();
michael@0 117 }
michael@0 118
michael@0 119 return shown;
michael@0 120 },
michael@0 121
michael@0 122 /*
michael@0 123 * Dismiss any context UI currently visible. Returns true if any
michael@0 124 * visible UI was dismissed. Fires context ui events.
michael@0 125 */
michael@0 126 dismiss: function () {
michael@0 127 let dismissed = false;
michael@0 128
michael@0 129 this._clearDelayedTimeout();
michael@0 130
michael@0 131 // No assurances this will hide the nav bar. It may have the
michael@0 132 // 'startpage' property set. This removes the 'visible' property.
michael@0 133 if (this.navbarVisible) {
michael@0 134 BrowserUI.blurNavBar();
michael@0 135 this.dismissNavbar();
michael@0 136 dismissed = true;
michael@0 137 }
michael@0 138 if (this.tabbarVisible) {
michael@0 139 this.dismissTabs();
michael@0 140 dismissed = true;
michael@0 141 }
michael@0 142 if (Elements.contextappbar.isShowing) {
michael@0 143 this.dismissContextAppbar();
michael@0 144 dismissed = true;
michael@0 145 }
michael@0 146
michael@0 147 if (dismissed) {
michael@0 148 ContentAreaObserver.updateContentArea();
michael@0 149 }
michael@0 150
michael@0 151 return dismissed;
michael@0 152 },
michael@0 153
michael@0 154 /*
michael@0 155 * Briefly show the tab bar and then hide it. Fires context ui events.
michael@0 156 */
michael@0 157 peekTabs: function peekTabs(aDelay) {
michael@0 158 if (!this.tabbarVisible)
michael@0 159 this.displayTabs();
michael@0 160
michael@0 161 ContextUI.dismissTabsWithDelay(aDelay);
michael@0 162 },
michael@0 163
michael@0 164 /*
michael@0 165 * Dismiss tab bar after a delay. Fires context ui events.
michael@0 166 */
michael@0 167 dismissTabsWithDelay: function (aDelay) {
michael@0 168 aDelay = aDelay || kForegroundTabAnimationDelay;
michael@0 169 this._clearDelayedTimeout();
michael@0 170 this._lastTimeoutDelay = aDelay;
michael@0 171 this._hidingId = setTimeout(function () {
michael@0 172 ContextUI.dismissTabs();
michael@0 173 }, aDelay);
michael@0 174 },
michael@0 175
michael@0 176 /*
michael@0 177 * Display the nav bar.
michael@0 178 *
michael@0 179 * @return false if we were already visible, and didn't do anything.
michael@0 180 */
michael@0 181 displayNavbar: function () {
michael@0 182 if (Elements.chromeState.getAttribute("navbar") == "visible") {
michael@0 183 return false;
michael@0 184 }
michael@0 185
michael@0 186 Elements.navbar.show();
michael@0 187 Elements.chromeState.setAttribute("navbar", "visible");
michael@0 188 ContentAreaObserver.updateContentArea();
michael@0 189 return true;
michael@0 190 },
michael@0 191
michael@0 192 // Display the tab tray
michael@0 193 displayTabs: function () {
michael@0 194 this._clearDelayedTimeout();
michael@0 195 this._setIsExpanded(true);
michael@0 196 },
michael@0 197
michael@0 198 // Dismiss the navbar if visible.
michael@0 199 dismissNavbar: function dismissNavbar() {
michael@0 200 if (!BrowserUI.isStartTabVisible) {
michael@0 201 Elements.autocomplete.closePopup();
michael@0 202 Elements.navbar.dismiss();
michael@0 203 Elements.chromeState.removeAttribute("navbar");
michael@0 204 ContentAreaObserver.updateContentArea();
michael@0 205 }
michael@0 206 },
michael@0 207
michael@0 208 // Dismiss the tabstray if visible.
michael@0 209 dismissTabs: function dimissTabs() {
michael@0 210 this._clearDelayedTimeout();
michael@0 211 this._setIsExpanded(false);
michael@0 212 },
michael@0 213
michael@0 214 // Dismiss the appbar if visible.
michael@0 215 dismissContextAppbar: function dismissContextAppbar() {
michael@0 216 Elements.contextappbar.dismiss();
michael@0 217 },
michael@0 218
michael@0 219 /*******************************************
michael@0 220 * Internal utils
michael@0 221 */
michael@0 222
michael@0 223 // tabtray state
michael@0 224 _setIsExpanded: function _setIsExpanded(aFlag, setSilently) {
michael@0 225 // if the tray can't be expanded, don't expand it.
michael@0 226 if (!this.isExpandable || this.tabbarVisible == aFlag)
michael@0 227 return;
michael@0 228
michael@0 229 if (aFlag)
michael@0 230 Elements.tray.setAttribute("expanded", "true");
michael@0 231 else
michael@0 232 Elements.tray.removeAttribute("expanded");
michael@0 233
michael@0 234 if (!setSilently)
michael@0 235 this._fire(kContextUITabsShowEvent);
michael@0 236 },
michael@0 237
michael@0 238 _clearDelayedTimeout: function _clearDelayedTimeout() {
michael@0 239 if (this._hidingId) {
michael@0 240 clearTimeout(this._hidingId);
michael@0 241 this._hidingId = 0;
michael@0 242 this._delayedHide = false;
michael@0 243 }
michael@0 244 },
michael@0 245
michael@0 246 _resetDelayedTimeout: function () {
michael@0 247 this._hidingId = setTimeout(function () {
michael@0 248 ContextUI.dismissTabs();
michael@0 249 }, this._lastTimeoutDelay);
michael@0 250 },
michael@0 251
michael@0 252 /*******************************************
michael@0 253 * Events
michael@0 254 */
michael@0 255
michael@0 256 _onEdgeUIStarted: function(aEvent) {
michael@0 257 this._hasEdgeSwipeStarted = true;
michael@0 258 this._clearDelayedTimeout();
michael@0 259 this.toggleNavUI();
michael@0 260 },
michael@0 261
michael@0 262 _onEdgeUICanceled: function(aEvent) {
michael@0 263 this._hasEdgeSwipeStarted = false;
michael@0 264 this.dismiss();
michael@0 265 },
michael@0 266
michael@0 267 _onEdgeUICompleted: function(aEvent) {
michael@0 268 if (this._hasEdgeSwipeStarted) {
michael@0 269 this._hasEdgeSwipeStarted = false;
michael@0 270 return;
michael@0 271 }
michael@0 272
michael@0 273 this._clearDelayedTimeout();
michael@0 274 this.toggleNavUI();
michael@0 275 },
michael@0 276
michael@0 277 onDownInput: function onDownInput(aEvent) {
michael@0 278 if (!this.isVisible) {
michael@0 279 return;
michael@0 280 }
michael@0 281
michael@0 282 // Various ui element containers we do not update context ui for.
michael@0 283 let whitelist = [
michael@0 284 // Clicks on tab bar elements should not close the tab bar. the tabbar
michael@0 285 // handles this.
michael@0 286 Elements.tabs,
michael@0 287 // Don't let a click on an infobar button dismiss the appbar or navbar.
michael@0 288 // Note the notification box should always hover above these other two
michael@0 289 // bars.
michael@0 290 Browser.getNotificationBox()
michael@0 291 ];
michael@0 292
michael@0 293 if (whitelist.some(elem => elem.contains(aEvent.target))) {
michael@0 294 return;
michael@0 295 }
michael@0 296
michael@0 297 // If a start tab is visible only dismiss the tab bar.
michael@0 298 if (BrowserUI.isStartTabVisible) {
michael@0 299 ContextUI.dismissTabs();
michael@0 300 return;
michael@0 301 }
michael@0 302
michael@0 303 // content, dismiss anything visible
michael@0 304 if (aEvent.target.ownerDocument.defaultView.top == getBrowser().contentWindow) {
michael@0 305 this.dismiss();
michael@0 306 return;
michael@0 307 }
michael@0 308
michael@0 309 // dismiss tabs and context app bar if visible
michael@0 310 this.dismissTabs();
michael@0 311 this.dismissContextAppbar();
michael@0 312 },
michael@0 313
michael@0 314 onMouseMove: function (aEvent) {
michael@0 315 if (this._hidingId) {
michael@0 316 this._clearDelayedTimeout();
michael@0 317 this._delayedHide = true;
michael@0 318 }
michael@0 319 },
michael@0 320
michael@0 321 onMouseLeave: function (aEvent) {
michael@0 322 if (this._delayedHide) {
michael@0 323 this._delayedHide = false;
michael@0 324 this._resetDelayedTimeout();
michael@0 325 }
michael@0 326 },
michael@0 327
michael@0 328 handleEvent: function handleEvent(aEvent) {
michael@0 329 switch (aEvent.type) {
michael@0 330 case "URLChanged":
michael@0 331 // "aEvent.detail" is a boolean value that indicates whether actual URL
michael@0 332 // has changed ignoring URL fragment changes.
michael@0 333 if (aEvent.target == Browser.selectedBrowser && aEvent.detail) {
michael@0 334 this.displayNavbar();
michael@0 335 }
michael@0 336 break;
michael@0 337 case "MozEdgeUIStarted":
michael@0 338 this._onEdgeUIStarted(aEvent);
michael@0 339 break;
michael@0 340 case "MozEdgeUICanceled":
michael@0 341 this._onEdgeUICanceled(aEvent);
michael@0 342 break;
michael@0 343 case "MozEdgeUICompleted":
michael@0 344 this._onEdgeUICompleted(aEvent);
michael@0 345 break;
michael@0 346 case "keypress":
michael@0 347 if (String.fromCharCode(aEvent.which) == "z" &&
michael@0 348 aEvent.getModifierState("Win"))
michael@0 349 this.toggleNavUI();
michael@0 350 break;
michael@0 351 case "transitionend":
michael@0 352 setTimeout(function () {
michael@0 353 ContentAreaObserver.updateContentArea();
michael@0 354 }, 0);
michael@0 355 break;
michael@0 356 case "KeyboardChanged":
michael@0 357 this.dismissTabs();
michael@0 358 break;
michael@0 359 case "mousedown":
michael@0 360 if (aEvent.button != 0) {
michael@0 361 break;
michael@0 362 }
michael@0 363 this.onDownInput(aEvent);
michael@0 364 break;
michael@0 365 case "mousemove":
michael@0 366 this.onMouseMove(aEvent);
michael@0 367 break;
michael@0 368 case "mouseleave":
michael@0 369 this.onMouseLeave(aEvent);
michael@0 370 break;
michael@0 371 case "touchstart":
michael@0 372 this.onDownInput(aEvent);
michael@0 373 break;
michael@0 374 case "ToolPanelShown":
michael@0 375 case "ToolPanelHidden":
michael@0 376 this.dismiss();
michael@0 377 break;
michael@0 378 case "AlertActive":
michael@0 379 case "AlertClose":
michael@0 380 case "TabSelect":
michael@0 381 ContentAreaObserver.updateContentArea();
michael@0 382 break;
michael@0 383 case "MozFlyoutPanelShowing":
michael@0 384 if (BrowserUI.isStartTabVisible) {
michael@0 385 this.dismissTabs();
michael@0 386 this.dismissContextAppbar();
michael@0 387 } else {
michael@0 388 this.dismiss();
michael@0 389 }
michael@0 390 break;
michael@0 391 }
michael@0 392 },
michael@0 393
michael@0 394 _fire: function (name) {
michael@0 395 let event = document.createEvent("Events");
michael@0 396 event.initEvent(name, true, true);
michael@0 397 window.dispatchEvent(event);
michael@0 398 }
michael@0 399 };

mercurial