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