Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / resources / options / deletable_item_list.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 cr.define('options', function() {
6   /** @const */ var List = cr.ui.List;
7   /** @const */ var ListItem = cr.ui.ListItem;
8
9   /**
10    * Creates a deletable list item, which has a button that will trigger a call
11    * to deleteItemAtIndex(index) in the list.
12    * @constructor
13    * @extends {cr.ui.ListItem}
14    */
15   var DeletableItem = cr.ui.define('li');
16
17   DeletableItem.prototype = {
18     __proto__: ListItem.prototype,
19
20     /**
21      * The element subclasses should populate with content.
22      * @type {HTMLElement}
23      * @private
24      */
25     contentElement_: null,
26
27     /**
28      * The close button element.
29      * @type {HTMLElement}
30      * @private
31      */
32     closeButtonElement_: null,
33
34     /**
35      * Whether or not this item can be deleted.
36      * @type {boolean}
37      * @private
38      */
39     deletable_: true,
40
41     /** @override */
42     decorate: function() {
43       ListItem.prototype.decorate.call(this);
44
45       this.classList.add('deletable-item');
46
47       this.contentElement_ = /** @type {HTMLElement} */(
48           this.ownerDocument.createElement('div'));
49       this.appendChild(this.contentElement_);
50
51       this.closeButtonElement_ = /** @type {HTMLElement} */(
52           this.ownerDocument.createElement('button'));
53       this.closeButtonElement_.className =
54           'raw-button row-delete-button custom-appearance';
55       this.closeButtonElement_.addEventListener('mousedown',
56                                                 this.handleMouseDownUpOnClose_);
57       this.closeButtonElement_.addEventListener('mouseup',
58                                                 this.handleMouseDownUpOnClose_);
59       this.closeButtonElement_.addEventListener('focus',
60                                                 this.handleFocus_.bind(this));
61       this.closeButtonElement_.tabIndex = -1;
62       this.closeButtonElement_.title =
63           loadTimeData.getString('deletableItemDeleteButtonTitle');
64       this.appendChild(this.closeButtonElement_);
65     },
66
67     /**
68      * Returns the element subclasses should add content to.
69      * @return {HTMLElement} The element subclasses should popuplate.
70      */
71     get contentElement() {
72       return this.contentElement_;
73     },
74
75     /**
76      * Returns the close button element.
77      * @return {HTMLElement} The close |<button>| element.
78      */
79     get closeButtonElement() {
80       return this.closeButtonElement_;
81     },
82
83     /* Gets/sets the deletable property. An item that is not deletable doesn't
84      * show the delete button (although space is still reserved for it).
85      */
86     get deletable() {
87       return this.deletable_;
88     },
89     set deletable(value) {
90       this.deletable_ = value;
91       this.closeButtonElement_.disabled = !value;
92     },
93
94     /**
95      * Called when a focusable child element receives focus. Selects this item
96      * in the list selection model.
97      * @private
98      */
99     handleFocus_: function() {
100       // This handler is also fired when the child receives focus as a result of
101       // the item getting selected by the customized mouse/keyboard handling in
102       // SelectionController. Take care not to destroy a potential multiple
103       // selection in this case.
104       if (this.selected)
105         return;
106
107       var list = this.parentNode;
108       var index = list.getIndexOfListItem(this);
109       list.selectionModel.selectedIndex = index;
110       list.selectionModel.anchorIndex = index;
111     },
112
113     /**
114      * Don't let the list have a crack at the event. We don't want clicking the
115      * close button to change the selection of the list or to focus on the close
116      * button.
117      * @param {Event} e The mouse down/up event object.
118      * @private
119      */
120     handleMouseDownUpOnClose_: function(e) {
121       if (e.target.disabled)
122         return;
123       e.stopPropagation();
124       e.preventDefault();
125     },
126   };
127
128   /**
129    * @constructor
130    * @extends {cr.ui.List}
131    */
132   var DeletableItemList = cr.ui.define('list');
133
134   DeletableItemList.prototype = {
135     __proto__: List.prototype,
136
137     /** @override */
138     decorate: function() {
139       List.prototype.decorate.call(this);
140       this.addEventListener('click', this.handleClick);
141       this.addEventListener('keydown', this.handleKeyDown_);
142     },
143
144     /**
145      * Callback for onclick events.
146      * @param {Event} e The click event object.
147      * @override
148      */
149     handleClick: function(e) {
150       if (this.disabled)
151         return;
152
153       var target = e.target;
154       if (target.classList.contains('row-delete-button')) {
155         var listItem = this.getListItemAncestor(
156             /** @type {HTMLElement} */(target));
157         var idx = this.getIndexOfListItem(listItem);
158         this.deleteItemAtIndex(idx);
159       }
160     },
161
162     /**
163      * Callback for keydown events.
164      * @param {Event} e The keydown event object.
165      * @private
166      */
167     handleKeyDown_: function(e) {
168       // Map delete (and backspace on Mac) to item deletion (unless focus is
169       // in an input field, where it's intended for text editing).
170       if ((e.keyCode == 46 || (e.keyCode == 8 && cr.isMac)) &&
171           e.target.tagName != 'INPUT') {
172         this.deleteSelectedItems_();
173         // Prevent the browser from going back.
174         e.preventDefault();
175       }
176     },
177
178     /**
179      * Deletes all the currently selected items that are deletable.
180      * @private
181      */
182     deleteSelectedItems_: function() {
183       var selected = this.selectionModel.selectedIndexes;
184       // Reverse through the list of selected indexes to maintain the
185       // correct index values after deletion.
186       for (var j = selected.length - 1; j >= 0; j--) {
187         var index = selected[j];
188         if (this.getListItemByIndex(index).deletable)
189           this.deleteItemAtIndex(index);
190       }
191     },
192
193     /**
194      * Called when an item should be deleted; subclasses are responsible for
195      * implementing.
196      * @param {number} index The index of the item that is being deleted.
197      */
198     deleteItemAtIndex: function(index) {
199     },
200   };
201
202   return {
203     DeletableItemList: DeletableItemList,
204     DeletableItem: DeletableItem,
205   };
206 });