1// Copyright (c) 2013 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 5cr.define('cr.ui', function() { 6 /** 7 * An image button that brings up an informative bubble when activated by 8 * keyboard or mouse. 9 * @constructor 10 * @extends {HTMLSpanElement} 11 * @implements {EventListener} 12 */ 13 var BubbleButton = cr.ui.define('span'); 14 15 BubbleButton.prototype = { 16 __proto__: HTMLSpanElement.prototype, 17 18 /** 19 * Decorates the base element to show the proper icon. 20 */ 21 decorate: function() { 22 this.className = 'bubble-button'; 23 this.location = cr.ui.ArrowLocation.TOP_END; 24 this.image = document.createElement('div'); 25 this.image.tabIndex = 0; 26 this.image.setAttribute('role', 'button'); 27 this.image.addEventListener('click', this); 28 this.image.addEventListener('keydown', this); 29 this.image.addEventListener('mousedown', this); 30 this.appendChild(this.image); 31 }, 32 33 /** 34 * Whether the button is currently showing a bubble. 35 * @type {boolean} 36 */ 37 get showingBubble() { 38 return this.image.classList.contains('showing-bubble'); 39 }, 40 set showingBubble(showing) { 41 this.image.classList.toggle('showing-bubble', showing); 42 }, 43 44 /** 45 * Handle mouse and keyboard events, allowing the user to open and close an 46 * informative bubble. 47 * @param {Event} event Mouse or keyboard event. 48 */ 49 handleEvent: function(event) { 50 switch (event.type) { 51 // Toggle the bubble on left click. Let any other clicks propagate. 52 case 'click': 53 if (event.button != 0) 54 return; 55 break; 56 // Toggle the bubble when <Return> or <Space> is pressed. Let any other 57 // key presses propagate. 58 case 'keydown': 59 switch (event.keyCode) { 60 case 13: // Return. 61 case 32: // Space. 62 break; 63 default: 64 return; 65 } 66 break; 67 // Blur focus when a mouse button is pressed, matching the behavior of 68 // other Web UI elements. 69 case 'mousedown': 70 if (document.activeElement) 71 document.activeElement.blur(); 72 event.preventDefault(); 73 return; 74 } 75 this.toggleBubble(); 76 event.preventDefault(); 77 event.stopPropagation(); 78 }, 79 80 /** 81 * Abstract method: subclasses should overwrite it. There is no way to mark 82 * method as abstract for Closure Compiler, as of 83 * https://github.com/google/closure-compiler/issues/104. 84 * @type {!Function|undefined} 85 * @protected 86 */ 87 toggleBubble: assertNotReached, 88 }; 89 90 // Export. 91 return { 92 BubbleButton: BubbleButton 93 }; 94}); 95