/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ /* Copyright 2014 Mozilla Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* globals Promise */ 'use strict'; var OverlayManager = { overlays: {}, active: null, /** * @param {string} name The name of the overlay that is registered. This must * be equal to the ID of the overlay's DOM element. * @param {function} callerCloseMethod (optional) The method that, if present, * will call OverlayManager.close from the Object * registering the overlay. Access to this method is * necessary in order to run cleanup code when e.g. * the overlay is force closed. The default is null. * @param {boolean} canForceClose (optional) Indicates if opening the overlay * will close an active overlay. The default is false. * @returns {Promise} A promise that is resolved when the overlay has been * registered. */ register: function overlayManagerRegister(name, callerCloseMethod, canForceClose) { return new Promise(function (resolve) { var element, container; if (!name || !(element = document.getElementById(name)) || !(container = element.parentNode)) { throw new Error('Not enough parameters.'); } else if (this.overlays[name]) { throw new Error('The overlay is already registered.'); } this.overlays[name] = { element: element, container: container, callerCloseMethod: (callerCloseMethod || null), canForceClose: (canForceClose || false) }; resolve(); }.bind(this)); }, /** * @param {string} name The name of the overlay that is unregistered. * @returns {Promise} A promise that is resolved when the overlay has been * unregistered. */ unregister: function overlayManagerUnregister(name) { return new Promise(function (resolve) { if (!this.overlays[name]) { throw new Error('The overlay does not exist.'); } else if (this.active === name) { throw new Error('The overlay cannot be removed while it is active.'); } delete this.overlays[name]; resolve(); }.bind(this)); }, /** * @param {string} name The name of the overlay that should be opened. * @returns {Promise} A promise that is resolved when the overlay has been * opened. */ open: function overlayManagerOpen(name) { return new Promise(function (resolve) { if (!this.overlays[name]) { throw new Error('The overlay does not exist.'); } else if (this.active) { if (this.overlays[name].canForceClose) { this._closeThroughCaller(); } else if (this.active === name) { throw new Error('The overlay is already active.'); } else { throw new Error('Another overlay is currently active.'); } } this.active = name; this.overlays[this.active].element.classList.remove('hidden'); this.overlays[this.active].container.classList.remove('hidden'); window.addEventListener('keydown', this._keyDown); resolve(); }.bind(this)); }, /** * @param {string} name The name of the overlay that should be closed. * @returns {Promise} A promise that is resolved when the overlay has been * closed. */ close: function overlayManagerClose(name) { return new Promise(function (resolve) { if (!this.overlays[name]) { throw new Error('The overlay does not exist.'); } else if (!this.active) { throw new Error('The overlay is currently not active.'); } else if (this.active !== name) { throw new Error('Another overlay is currently active.'); } this.overlays[this.active].container.classList.add('hidden'); this.overlays[this.active].element.classList.add('hidden'); this.active = null; window.removeEventListener('keydown', this._keyDown); resolve(); }.bind(this)); }, /** * @private */ _keyDown: function overlayManager_keyDown(evt) { var self = OverlayManager; if (self.active && evt.keyCode === 27) { // Esc key. self._closeThroughCaller(); evt.preventDefault(); } }, /** * @private */ _closeThroughCaller: function overlayManager_closeThroughCaller() { if (this.overlays[this.active].callerCloseMethod) { this.overlays[this.active].callerCloseMethod(); } if (this.active) { this.close(this.active); } } };