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
11cr.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