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 3 // found in the LICENSE file. 4 5 /** 6 * @fileoverview 7 * Class representing a menu button and its associated menu items. 8 */ 9 10 'use strict'; 11 12 /** @suppress {duplicate} */ 13 var remoting = remoting || {}; 14 15 /** 16 * @constructor 17 * @param {Element} container The element containing the <button> and <ul> 18 * elements comprising the menu. It should have the "menu-button" class. 19 * @param {function():void=} opt_onShow Optional callback invoked before the 20 * menu is shown. 21 */ 22 remoting.MenuButton = function(container, opt_onShow) { 23 /** 24 * @type {HTMLElement} 25 * @private 26 */ 27 this.button_ = /** @type {HTMLElement} */ (container.querySelector('button')); 28 29 /** 30 * @type {undefined|function():void} 31 * @private 32 */ 33 this.onShow_ = opt_onShow; 34 35 /** @type {remoting.MenuButton} */ 36 var that = this; 37 38 // Create event handlers to show and hide the menu, attached to the button 39 // and the document <html> tag, respectively. These handlers are added and 40 // removed depending on the state of the menu. To prevent both triggering 41 // for one click, they are added by a timer. 42 /** 43 * @type {function(Event):void} 44 * @private 45 */ 46 this.onClick_ = function(event) { 47 if (that.onShow_) { 48 that.onShow_(); 49 } 50 that.button_.classList.add(remoting.MenuButton.BUTTON_ACTIVE_CLASS_); 51 that.button_.removeEventListener('click', that.onClick_, false); 52 window.setTimeout( 53 function() { 54 // Attach the click handler to the <html> node so that it includes 55 // the document area outside the plugin, which is not covered by 56 // the <body> node. 57 var htmlNode = document.body.parentNode; 58 htmlNode.addEventListener('click', that.closeHandler_, true); 59 }, 60 100); 61 }; 62 63 /** 64 * @type {function(Event):void} 65 * @private 66 */ 67 this.closeHandler_ = function(event) { 68 that.button_.classList.remove(remoting.MenuButton.BUTTON_ACTIVE_CLASS_); 69 document.body.removeEventListener('click', that.closeHandler_, true); 70 window.setTimeout( 71 function() { 72 that.button_.addEventListener('click', that.onClick_, false); 73 }, 74 100); 75 }; 76 77 this.button_.addEventListener('click', this.onClick_, false); 78 }; 79 80 /** 81 * Set or unset the selected state of an <li> menu item. 82 * @param {HTMLElement} item The menu item to update. 83 * @param {boolean} selected True to select the item, false to deselect it. 84 * @return {void} Nothing. 85 */ 86 remoting.MenuButton.select = function(item, selected) { 87 if (selected) { 88 item.classList.add('selected'); 89 } else { 90 item.classList.remove('selected'); 91 } 92 }; 93 94 /** @const @private */ 95 remoting.MenuButton.BUTTON_ACTIVE_CLASS_ = 'active'; 96