Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(87)

Side by Side Diff: chrome/browser/resources/file_manager/js/combobutton.js

Issue 10391184: [FileBrowser] Migrated ComboButton to menu as dropdown. (Closed) Base URL: improved-actions-menu-126927
Patch Set: Removed shared/menu stuff changes. Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @fileoverview This implements a combobutton control. 6 * @fileoverview This implements a combobutton control.
7 */ 7 */
8 8
9 cr.define('cr.ui', function() { 9 cr.define('cr.ui', function() {
10 /** 10 /**
11 * Sets minWidth for the target, so it's visually as large as source.
12 * @param {HTMLElement} target Element which min-width to tune.
13 * @param {HTMLElement} source Element, which width to use.
14 */
15 function enlarge(target, source) {
16 var cs = target.ownerDocument.defaultView.getComputedStyle(target);
17 target.style.minWidth = (source.getBoundingClientRect().width -
18 parseFloat(cs.borderLeftWidth) -
19 parseFloat(cs.borderRightWidth)) + 'px';
20 }
21
22 /**
23 * Creates a new combobutton element. 11 * Creates a new combobutton element.
24 * @param {Object=} opt_propertyBag Optional properties. 12 * @param {Object=} opt_propertyBag Optional properties.
25 * @constructor 13 * @constructor
26 * @extends {HTMLUListElement} 14 * @extends {HTMLUListElement}
27 */ 15 */
28 var ComboButton = cr.ui.define('div'); 16 var ComboButton = cr.ui.define(cr.ui.MenuButton);
17
29 18
30 ComboButton.prototype = { 19 ComboButton.prototype = {
31 __proto__: HTMLDivElement.prototype, 20 __proto__: cr.ui.MenuButton.prototype,
21
22 defaultItem_: null,
32 23
33 /** 24 /**
34 * The items list. 25 * Truncates drop-down list.
35 */ 26 */
36 items_: null,
37
38 clear: function() { 27 clear: function() {
39 if (this.items_.length > 0) 28 this.menu.clear();
40 // Remove default combobox item if we have added it at addItem.
41 this.removeChild(this.firstChild);
42
43 this.items_ = [];
44 this.popup_.textContent = '';
45 this.multiple = false; 29 this.multiple = false;
46 this.popup_.style.minWidth = '';
47 }, 30 },
48 31
49 addItem: function(item) { 32 addItem: function(item) {
dgozman 2012/05/18 13:15:14 This method does not add the initially shown item
Dmitry Zvorygin 2012/05/21 10:51:01 Done.
50 this.items_.push(item); 33 this.multiple = true;
51 if (this.items_.length == 1) { 34 this.menu.addMenuItem(item).data = item;
52 // Set first added item as default on combobox.
53 // First item should be the first element to prepend drop-down arrow and
54 // popup layer.
55 this.insertBefore(item, this.firstChild);
56 } else {
57 this.multiple = true;
58 if (this.popup_.hasChildNodes())
59 this.popup_.insertBefore(item, this.popup_.firstChild);
60 else
61 this.popup_.appendChild(item);
62 if (this.visible)
63 this.setPopupSize_();
64 }
65 }, 35 },
66 36
67 setPopupSize_: function() { 37 /**
68 this.popup_.style.bottom = (this.clientHeight + 1) + 'px'; 38 * Default item to fire on combobox click
69 enlarge(this.popup_, this); 39 */
40 get defaultItem() {
41 return this.defaultItem_;
42 },
43 set defaultItem(defaultItem) {
44 this.defaultItem_ = defaultItem;
45 if (defaultItem.label) {
46 this.labelNode_.textContent = defaultItem.label;
47 } else {
48 this.labelNode_.textContent = '';
49 }
50
51 if (defaultItem.iconUrl) {
52 this.iconNode_.src = defaultItem.iconUrl;
53 } else {
54 this.iconNode_.src = '';
55 }
70 }, 56 },
71 57
72 /** 58 /**
73 * Initializes the element. 59 * Initializes the element.
74 */ 60 */
75 decorate: function() { 61 decorate: function() {
76 this.items_ = []; 62 cr.ui.MenuButton.prototype.decorate.call(this);
77 63
78 this.classList.add('combobutton'); 64 this.classList.add('combobutton');
79 65
66 this.iconNode_ = this.ownerDocument.createElement('img');
67 this.appendChild(this.iconNode_);
68
69 this.labelNode_ = this.ownerDocument.createElement('span');
70 this.appendChild(this.labelNode_);
71
80 var triggerIcon = this.ownerDocument.createElement('span'); 72 var triggerIcon = this.ownerDocument.createElement('span');
81 triggerIcon.className = 'disclosureindicator'; 73 triggerIcon.className = 'disclosureindicator';
82 this.trigger_ = this.ownerDocument.createElement('div'); 74 this.trigger_ = this.ownerDocument.createElement('div');
83 this.trigger_.appendChild(triggerIcon); 75 this.trigger_.appendChild(triggerIcon);
84 76
85 this.popup_ = this.ownerDocument.createElement('div'); 77 this.appendChild(this.trigger_);
86 this.popup_.className = 'popup';
87 78
88 this.appendChild(this.trigger_); 79 this.addEventListener('click', this.handleButtonClick_.bind(this));
89 this.appendChild(this.popup_);
90 80
91 this.addEventListener('click',
92 this.handleButtonClick_.bind(this));
93 this.popup_.addEventListener('click',
94 this.handlePopupClick_.bind(this));
95 this.trigger_.addEventListener('click', 81 this.trigger_.addEventListener('click',
96 this.handleTriggerClicked_.bind(this)); 82 this.handleTriggerClicked_.bind(this));
97 this.addEventListener('mouseout', this.handleMouseOut_.bind(this));
98 83
99 this.visible = true; 84 this.menu.addEventListener('activate',
85 this.handleMenuActivate_.bind(this));
86
87 // Remove mousedown event listener created by MenuButton::decorate,
dgozman 2012/05/18 13:15:14 I don't like this dependency on internals of MenuB
Dmitry Zvorygin 2012/05/21 10:51:01 I don't like this complex logic too, but if we mak
88 // and move it down to trigger_.
89 this.removeEventListener('mousedown', this);
90 this.trigger_.addEventListener('mousedown', this);
91 },
92
93 /**
94 * Handles the keydown event for the menu button.
95 */
96 handleKeyDown: function(e) {
97 switch (e.keyIdentifier) {
98 case 'Down':
99 case 'Up':
100 if (!this.isMenuShown())
101 this.showMenu();
102 e.preventDefault();
103 break;
104 case 'Esc':
105 case 'U+001B': // Maybe this is remote desktop playing a prank?
106 this.hideMenu();
107 break;
108 }
100 }, 109 },
101 110
102 handleTriggerClicked_: function(event) { 111 handleTriggerClicked_: function(event) {
103 this.open = !this.open;
104 event.stopPropagation(); 112 event.stopPropagation();
105 }, 113 },
106 114
107 handleMouseOut_: function(event) { 115 handleMenuActivate_: function(event) {
108 var x = event.x; 116 this.dispatchSelectEvent(event.target.data);
109 var y = event.y;
110
111 var children = this.childNodes;
112 for (var i = 0; i < children.length; i++)
113 {
114 var r = this.children[i].getBoundingClientRect();
115 if (x >= r.left && x <= r.right && y >= r.top && y <= r.bottom)
116 return;
117 }
118
119 this.open = false;
120 }, 117 },
121 118
122 handleButtonClick_: function(event) { 119 handleButtonClick_: function() {
123 this.dispatchSelectEvent(this.items_[0]); 120 this.dispatchSelectEvent(this.defaultItem_);
124 },
125
126 handlePopupClick_: function(event) {
127 var item = event.target;
128 while (item && item.parentNode != this.popup_)
129 item = item.parentNode;
130 if (!item)
131 return;
132
133 this.open = false;
134 this.dispatchSelectEvent(item);
135 event.stopPropagation();
136 }, 121 },
137 122
138 dispatchSelectEvent: function(item) { 123 dispatchSelectEvent: function(item) {
139 var selectEvent = new Event('select'); 124 var selectEvent = new Event('select');
140 selectEvent.item = item; 125 selectEvent.item = item;
141 this.dispatchEvent(selectEvent); 126 this.dispatchEvent(selectEvent);
142 },
143
144 get visible() {
145 return this.hasAttribute('visible');
146 },
147 set visible(value) {
148 if (value) {
149 this.setAttribute('visible', 'visible');
150 setTimeout(this.setPopupSize_.bind(this), 0);
151 } else {
152 this.removeAttribute('visible');
153 }
154 } 127 }
155 }; 128 };
156 129
157 cr.defineProperty(ComboButton, 'disabled', cr.PropertyKind.BOOL_ATTR); 130 cr.defineProperty(ComboButton, 'disabled', cr.PropertyKind.BOOL_ATTR);
158 cr.defineProperty(ComboButton, 'open', cr.PropertyKind.BOOL_ATTR);
159 cr.defineProperty(ComboButton, 'multiple', cr.PropertyKind.BOOL_ATTR); 131 cr.defineProperty(ComboButton, 'multiple', cr.PropertyKind.BOOL_ATTR);
160 132
133 cr.defineProperty(ComboButton, 'label', cr.PropertyKind.ATTR);
dgozman 2012/05/18 13:15:14 Why do you need this?
Dmitry Zvorygin 2012/05/21 10:51:01 Removed. Just some stuff from research has been le
134 cr.defineProperty(ComboButton, 'iconUrl', cr.PropertyKind.ATTR);
135
161 return { 136 return {
162 ComboButton: ComboButton 137 ComboButton: ComboButton
163 }; 138 };
164 }); 139 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698