1 // Copyright (c) 2010 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 cr.define('cr.ui', function() { 6 const Command = cr.ui.Command; 7 8 /** 9 * Creates a new menu item element. 10 * @param {Object=} opt_propertyBag Optional properties. 11 * @constructor 12 * @extends {HTMLDivElement} 13 */ 14 var MenuItem = cr.ui.define('div'); 15 16 /** 17 * Creates a new menu separator element. 18 * @return {cr.ui.MenuItem} 19 */ 20 MenuItem.createSeparator = function() { 21 var el = cr.doc.createElement('hr'); 22 MenuItem.decorate(el); 23 return el; 24 }; 25 26 MenuItem.prototype = { 27 __proto__: HTMLButtonElement.prototype, 28 29 /** 30 * Initializes the menu item. 31 */ 32 decorate: function() { 33 var commandId; 34 if ((commandId = this.getAttribute('command'))) 35 this.command = commandId; 36 37 this.addEventListener('mouseup', this.handleMouseUp_); 38 }, 39 40 /** 41 * The command associated with this menu item. If this is set to a string 42 * of the form "#element-id" then the element is looked up in the document 43 * of the command. 44 * @type {cr.ui.Command} 45 */ 46 command_: null, 47 get command() { 48 return this.command_; 49 }, 50 set command(command) { 51 if (this.command_) { 52 this.command_.removeEventListener('labelChange', this); 53 this.command_.removeEventListener('disabledChange', this); 54 this.command_.removeEventListener('hiddenChange', this); 55 this.command_.removeEventListener('checkedChange', this); 56 } 57 58 if (typeof command == 'string' && command[0] == '#') { 59 command = this.ownerDocument.getElementById(command.slice(1)); 60 cr.ui.decorate(command, Command); 61 } 62 63 this.command_ = command; 64 if (command) { 65 if (command.id) 66 this.setAttribute('command', '#' + command.id); 67 68 this.label = command.label; 69 this.disabled = command.disabled; 70 this.hidden = command.hidden; 71 72 this.command_.addEventListener('labelChange', this); 73 this.command_.addEventListener('disabledChange', this); 74 this.command_.addEventListener('hiddenChange', this); 75 this.command_.addEventListener('checkedChange', this); 76 } 77 }, 78 79 /** 80 * The text label. 81 * @type {string} 82 */ 83 get label() { 84 return this.textContent; 85 }, 86 set label(label) { 87 this.textContent = label; 88 }, 89 90 /** 91 * @return {boolean} Whether the menu item is a separator. 92 */ 93 isSeparator: function() { 94 return this.tagName == 'HR'; 95 }, 96 97 /** 98 * Handles mouseup events. This dispatches an active event and if there 99 * is an assiciated command then that is executed. 100 * @param {Event} The mouseup event object. 101 * @private 102 */ 103 handleMouseUp_: function(e) { 104 if (!this.disabled && !this.isSeparator()) { 105 // Dispatch command event followed by executing the command object. 106 if (cr.dispatchSimpleEvent(this, 'activate', true, true)) { 107 var command = this.command; 108 if (command) 109 command.execute(); 110 } 111 } 112 }, 113 114 /** 115 * Handles changes to the associated command. 116 * @param {Event} e The event object. 117 */ 118 handleEvent: function(e) { 119 switch (e.type) { 120 case 'disabledChange': 121 this.disabled = this.command.disabled; 122 break; 123 case 'hiddenChange': 124 this.hidden = this.command.hidden; 125 break; 126 case 'labelChange': 127 this.label = this.command.label; 128 break; 129 case 'checkedChange': 130 this.checked = this.command.checked; 131 break; 132 } 133 } 134 }; 135 136 /** 137 * Whether the menu item is disabled or not. 138 * @type {boolean} 139 */ 140 cr.defineProperty(MenuItem, 'disabled', cr.PropertyKind.BOOL_ATTR); 141 142 /** 143 * Whether the menu item is hidden or not. 144 * @type {boolean} 145 */ 146 cr.defineProperty(MenuItem, 'hidden', cr.PropertyKind.BOOL_ATTR); 147 148 /** 149 * Whether the menu item is selected or not. 150 * @type {boolean} 151 */ 152 cr.defineProperty(MenuItem, 'selected', cr.PropertyKind.BOOL_ATTR); 153 154 /** 155 * Whether the menu item is checked or not. 156 * @type {boolean} 157 */ 158 cr.defineProperty(MenuItem, 'checked', cr.PropertyKind.BOOL_ATTR); 159 160 // Export 161 return { 162 MenuItem: MenuItem 163 }; 164 }); 165