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