12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)cr.define('cr.ui', function() {
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /**
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   * An image button that brings up an informative bubble when activated by
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   * keyboard or mouse.
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   * @constructor
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   * @extends {HTMLSpanElement}
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci   * @implements {EventListener}
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   */
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  var BubbleButton = cr.ui.define('span');
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BubbleButton.prototype = {
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    __proto__: HTMLSpanElement.prototype,
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /**
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Decorates the base element to show the proper icon.
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     */
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    decorate: function() {
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this.className = 'bubble-button';
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this.location = cr.ui.ArrowLocation.TOP_END;
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this.image = document.createElement('div');
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this.image.tabIndex = 0;
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this.image.setAttribute('role', 'button');
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this.image.addEventListener('click', this);
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this.image.addEventListener('keydown', this);
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this.image.addEventListener('mousedown', this);
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this.appendChild(this.image);
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    },
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /**
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Whether the button is currently showing a bubble.
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * @type {boolean}
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     */
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    get showingBubble() {
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return this.image.classList.contains('showing-bubble');
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    },
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    set showingBubble(showing) {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this.image.classList.toggle('showing-bubble', showing);
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    },
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /**
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Handle mouse and keyboard events, allowing the user to open and close an
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * informative bubble.
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * @param {Event} event Mouse or keyboard event.
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     */
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    handleEvent: function(event) {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      switch (event.type) {
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Toggle the bubble on left click. Let any other clicks propagate.
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case 'click':
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (event.button != 0)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return;
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Toggle the bubble when <Return> or <Space> is pressed. Let any other
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // key presses propagate.
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case 'keydown':
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          switch (event.keyCode) {
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            case 13:  // Return.
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            case 32:  // Space.
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              break;
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            default:
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              return;
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Blur focus when a mouse button is pressed, matching the behavior of
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // other Web UI elements.
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        case 'mousedown':
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (document.activeElement)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            document.activeElement.blur();
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          event.preventDefault();
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          return;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      this.toggleBubble();
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      event.preventDefault();
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      event.stopPropagation();
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    },
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    /**
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     * Abstract method: subclasses should overwrite it. There is no way to mark
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     *     method as abstract for Closure Compiler, as of
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     *     https://github.com/google/closure-compiler/issues/104.
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     * @type {!Function|undefined}
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     * @protected
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci     */
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    toggleBubble: assertNotReached,
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Export.
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return {
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BubbleButton: BubbleButton
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)});
95