15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 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) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @fileoverview 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Class representing a menu button and its associated menu items. 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)'use strict'; 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** @suppress {duplicate} */ 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var remoting = remoting || {}; 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @constructor 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Element} container The element containing the <button> and <ul> 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * elements comprising the menu. It should have the "menu-button" class. 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {function():void=} opt_onShow Optional callback invoked before the 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * menu is shown. 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @param {function():void=} opt_onHide Optional callback after before the 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * menu is hidden. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)remoting.MenuButton = function(container, opt_onShow, opt_onHide) { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {HTMLElement} 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch this.button_ = /** @type {HTMLElement} */ 300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch (container.querySelector('button,.menu-button-activator')); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @type {HTMLElement} 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @private 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.menu_ = /** @type {HTMLElement} */ (container.querySelector('ul')); 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {undefined|function():void} 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this.onShow_ = opt_onShow; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @type {undefined|function():void} 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @private 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.onHide_ = opt_onHide; 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /** 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Create a "click-trap" div covering the entire document, but below the 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * menu in the z-order. This ensures the the menu can be closed by clicking 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * anywhere. Note that adding this event handler to <body> is not enough, 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * because elements can prevent event propagation; specifically, the client 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * plugin element does this. 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @type {HTMLElement} 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.clickTrap_ = /** @type {HTMLElement} */ (document.createElement('div')); 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.clickTrap_.classList.add('menu-button-click-trap'); 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci /** @type {remoting.MenuButton} */ 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var that = this; 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var closeHandler = function() { 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) that.button_.classList.remove(remoting.MenuButton.BUTTON_ACTIVE_CLASS_); 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci container.removeChild(that.clickTrap_); 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (that.onHide_) { 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) that.onHide_(); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var onClick = function() { 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (that.onShow_) { 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) that.onShow_(); 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci that.button_.classList.add(remoting.MenuButton.BUTTON_ACTIVE_CLASS_); 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci container.appendChild(that.clickTrap_); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.button_.addEventListener('click', onClick, false); 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.clickTrap_.addEventListener('click', closeHandler, false); 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.menu_.addEventListener('click', closeHandler, false); 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/** 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @return {HTMLElement} The button that activates the menu. 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)remoting.MenuButton.prototype.button = function() { 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return this.button_; 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/** 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @return {HTMLElement} The menu. 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)remoting.MenuButton.prototype.menu = function() { 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return this.menu_; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Set or unset the selected state of an <li> menu item. 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @param {Element} item The menu item to update. 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {boolean} selected True to select the item, false to deselect it. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {void} Nothing. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)remoting.MenuButton.select = function(item, selected) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (selected) { 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** @type {DOMTokenList} */(item.classList).add('selected'); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** @type {DOMTokenList} */(item.classList).remove('selected'); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** @const @private */ 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)remoting.MenuButton.BUTTON_ACTIVE_CLASS_ = 'active'; 117