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