Home | History | Annotate | Download | only in webapp
      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