Home | History | Annotate | Download | only in js
      1 // Copyright (c) 2012 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 'use strict';
      6 
      7 /**
      8  * @fileoverview This implements a combobutton control.
      9  */
     10 
     11 cr.define('cr.ui', function() {
     12   /**
     13    * Creates a new combobutton element.
     14    * @param {Object=} opt_propertyBag Optional properties.
     15    * @constructor
     16    * @extends {HTMLUListElement}
     17    */
     18   var ComboButton = cr.ui.define(cr.ui.MenuButton);
     19 
     20 
     21   ComboButton.prototype = {
     22     __proto__: cr.ui.MenuButton.prototype,
     23 
     24     defaultItem_: null,
     25 
     26     /**
     27      * Truncates drop-down list.
     28      */
     29     clear: function() {
     30       this.menu.clear();
     31       this.multiple = false;
     32     },
     33 
     34     addDropDownItem: function(item) {
     35       this.multiple = true;
     36       var menuitem = this.menu.addMenuItem(item);
     37       menuitem.data = item;
     38       if (item.iconType) {
     39         menuitem.style.backgroundImage = '';
     40         menuitem.setAttribute('file-type-icon', item.iconType);
     41       }
     42       if (item.bold) {
     43         menuitem.style.fontWeight = 'bold';
     44       }
     45       return menuitem;
     46     },
     47 
     48     /**
     49      * Adds separator to drop-down list.
     50      */
     51     addSeparator: function() {
     52       this.menu.addSeparator();
     53     },
     54 
     55     /**
     56      * Default item to fire on combobox click
     57      */
     58     get defaultItem() {
     59       return this.defaultItem_;
     60     },
     61     set defaultItem(defaultItem) {
     62       this.defaultItem_ = defaultItem;
     63 
     64       this.actionNode_.textContent = defaultItem.label || '';
     65 
     66       if (defaultItem.iconType) {
     67         this.actionNode_.style.backgroundImage = '';
     68         this.actionNode_.setAttribute('file-type-icon', defaultItem.iconType);
     69       } else if (defaultItem.iconUrl) {
     70         this.actionNode_.style.backgroundImage =
     71             'url(' + defaultItem.iconUrl + ')';
     72       } else {
     73         this.actionNode_.style.backgroundImage = '';
     74       }
     75     },
     76 
     77     /**
     78      * Initializes the element.
     79      */
     80     decorate: function() {
     81       cr.ui.MenuButton.prototype.decorate.call(this);
     82 
     83       this.classList.add('combobutton');
     84 
     85       this.actionNode_ = this.ownerDocument.createElement('div');
     86       this.actionNode_.classList.add('action');
     87       this.appendChild(this.actionNode_);
     88 
     89       var triggerIcon = this.ownerDocument.createElement('span');
     90       triggerIcon.className = 'disclosureindicator';
     91       this.trigger_ = this.ownerDocument.createElement('div');
     92       this.trigger_.classList.add('trigger');
     93       this.trigger_.appendChild(triggerIcon);
     94 
     95       this.appendChild(this.trigger_);
     96 
     97       this.addEventListener('click', this.handleButtonClick_.bind(this));
     98 
     99       this.trigger_.addEventListener('click',
    100           this.handleTriggerClicked_.bind(this));
    101 
    102       this.menu.addEventListener('activate',
    103           this.handleMenuActivate_.bind(this));
    104 
    105       // Remove mousedown event listener created by MenuButton::decorate,
    106       // and move it down to trigger_.
    107       this.removeEventListener('mousedown', this);
    108       this.trigger_.addEventListener('mousedown', this);
    109     },
    110 
    111     /**
    112      * Handles the keydown event for the menu button.
    113      */
    114     handleKeyDown: function(e) {
    115       switch (e.keyIdentifier) {
    116         case 'Down':
    117         case 'Up':
    118           if (!this.isMenuShown())
    119             this.showMenu();
    120           e.preventDefault();
    121           break;
    122         case 'Esc':
    123         case 'U+001B': // Maybe this is remote desktop playing a prank?
    124           this.hideMenu();
    125           break;
    126       }
    127     },
    128 
    129     handleTriggerClicked_: function(event) {
    130       event.stopPropagation();
    131     },
    132 
    133     handleMenuActivate_: function(event) {
    134       this.dispatchSelectEvent(event.target.data);
    135     },
    136 
    137     handleButtonClick_: function() {
    138       this.dispatchSelectEvent(this.defaultItem_);
    139     },
    140 
    141     dispatchSelectEvent: function(item) {
    142       var selectEvent = new Event('select');
    143       selectEvent.item = item;
    144       this.dispatchEvent(selectEvent);
    145     }
    146   };
    147 
    148   cr.defineProperty(ComboButton, 'disabled', cr.PropertyKind.BOOL_ATTR);
    149   cr.defineProperty(ComboButton, 'multiple', cr.PropertyKind.BOOL_ATTR);
    150 
    151   return {
    152     ComboButton: ComboButton
    153   };
    154 });
    155