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.
5 cr.define('options', function() {
6 /** @const */ var List = cr.ui.List;
7 /** @const */ var ListItem = cr.ui.ListItem;
10 * Creates a deletable list item, which has a button that will trigger a call
11 * to deleteItemAtIndex(index) in the list.
13 * @extends {cr.ui.ListItem}
15 var DeletableItem = cr.ui.define('li');
17 DeletableItem.prototype = {
18 __proto__: ListItem.prototype,
21 * The element subclasses should populate with content.
25 contentElement_: null,
28 * The close button element.
32 closeButtonElement_: null,
35 * Whether or not this item can be deleted.
42 * Whether or not the close button can ever be navigated to using the
47 closeButtonFocusAllowed: false,
50 decorate: function() {
51 ListItem.prototype.decorate.call(this);
53 this.classList.add('deletable-item');
55 this.contentElement_ = /** @type {HTMLElement} */(
56 this.ownerDocument.createElement('div'));
57 this.appendChild(this.contentElement_);
59 this.closeButtonElement_ = /** @type {HTMLElement} */(
60 this.ownerDocument.createElement('button'));
61 this.closeButtonElement_.className =
62 'raw-button row-delete-button custom-appearance';
63 this.closeButtonElement_.addEventListener('mousedown',
64 this.handleMouseDownUpOnClose_);
65 this.closeButtonElement_.addEventListener('mouseup',
66 this.handleMouseDownUpOnClose_);
67 this.closeButtonElement_.addEventListener('focus',
68 this.handleFocus.bind(this));
69 this.closeButtonElement_.tabIndex = -1;
70 this.closeButtonElement_.title =
71 loadTimeData.getString('deletableItemDeleteButtonTitle');
72 this.appendChild(this.closeButtonElement_);
76 * Returns the element subclasses should add content to.
77 * @return {HTMLElement} The element subclasses should popuplate.
79 get contentElement() {
80 return this.contentElement_;
84 * Returns the close button element.
85 * @return {HTMLElement} The close |<button>| element.
87 get closeButtonElement() {
88 return this.closeButtonElement_;
91 /* Gets/sets the deletable property. An item that is not deletable doesn't
92 * show the delete button (although space is still reserved for it).
95 return this.deletable_;
97 set deletable(value) {
98 this.deletable_ = value;
99 this.closeButtonElement_.disabled = !value;
103 * Called when a focusable child element receives focus. Selects this item
104 * in the list selection model.
107 handleFocus: function() {
108 // This handler is also fired when the child receives focus as a result of
109 // the item getting selected by the customized mouse/keyboard handling in
110 // SelectionController. Take care not to destroy a potential multiple
111 // selection in this case.
115 var list = this.parentNode;
116 var index = list.getIndexOfListItem(this);
117 list.selectionModel.selectedIndex = index;
118 list.selectionModel.anchorIndex = index;
122 * Don't let the list have a crack at the event. We don't want clicking the
123 * close button to change the selection of the list or to focus on the close
125 * @param {Event} e The mouse down/up event object.
128 handleMouseDownUpOnClose_: function(e) {
129 if (e.target.disabled)
138 * @extends {cr.ui.List}
140 var DeletableItemList = cr.ui.define('list');
142 DeletableItemList.prototype = {
143 __proto__: List.prototype,
146 decorate: function() {
147 List.prototype.decorate.call(this);
148 this.addEventListener('click', this.handleClick);
149 this.addEventListener('keydown', this.handleKeyDown_);
153 * Callback for onclick events.
154 * @param {Event} e The click event object.
157 handleClick: function(e) {
161 var target = e.target;
162 if (target.classList.contains('row-delete-button')) {
163 var listItem = this.getListItemAncestor(
164 /** @type {HTMLElement} */(target));
165 var idx = this.getIndexOfListItem(listItem);
166 this.deleteItemAtIndex(idx);
171 * Callback for keydown events.
172 * @param {Event} e The keydown event object.
175 handleKeyDown_: function(e) {
176 // Map delete (and backspace on Mac) to item deletion (unless focus is
177 // in an input field, where it's intended for text editing).
178 if ((e.keyCode == 46 || (e.keyCode == 8 && cr.isMac)) &&
179 e.target.tagName != 'INPUT') {
180 this.deleteSelectedItems_();
181 // Prevent the browser from going back.
187 * Deletes all the currently selected items that are deletable.
190 deleteSelectedItems_: function() {
191 var selected = this.selectionModel.selectedIndexes;
192 // Reverse through the list of selected indexes to maintain the
193 // correct index values after deletion.
194 for (var j = selected.length - 1; j >= 0; j--) {
195 var index = selected[j];
196 if (this.getListItemByIndex(index).deletable)
197 this.deleteItemAtIndex(index);
202 * Called when an item should be deleted; subclasses are responsible for
204 * @param {number} index The index of the item that is being deleted.
206 deleteItemAtIndex: function(index) {
211 DeletableItemList: DeletableItemList,
212 DeletableItem: DeletableItem,