Upstream version 7.36.149.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       var list = this.parentNode;
96       var index = list.getIndexOfListItem(this);
97       list.selectionModel.selectedIndex = index;
98       list.selectionModel.anchorIndex = index;
99     },
100
101     /**
102      * Don't let the list have a crack at the event. We don't want clicking the
103      * close button to change the selection of the list or to focus on the close
104      * button.
105      * @param {Event} e The mouse down/up event object.
106      * @private
107      */
108     handleMouseDownUpOnClose_: function(e) {
109       if (e.target.disabled)
110         return;
111       e.stopPropagation();
112       e.preventDefault();
113     },
114   };
115
116   var DeletableItemList = cr.ui.define('list');
117
118   DeletableItemList.prototype = {
119     __proto__: List.prototype,
120
121     /** @override */
122     decorate: function() {
123       List.prototype.decorate.call(this);
124       this.addEventListener('click', this.handleClick_);
125       this.addEventListener('keydown', this.handleKeyDown_);
126     },
127
128     /**
129      * Callback for onclick events.
130      * @param {Event} e The click event object.
131      * @private
132      */
133     handleClick_: function(e) {
134       if (this.disabled)
135         return;
136
137       var target = e.target;
138       if (target.classList.contains('row-delete-button')) {
139         var listItem = this.getListItemAncestor(target);
140         var selected = this.selectionModel.selectedIndexes;
141
142         // Check if the list item that contains the close button being clicked
143         // is not in the list of selected items. Only delete this item in that
144         // case.
145         var idx = this.getIndexOfListItem(listItem);
146         if (selected.indexOf(idx) == -1) {
147           this.deleteItemAtIndex(idx);
148         } else {
149           this.deleteSelectedItems_();
150         }
151       }
152     },
153
154     /**
155      * Callback for keydown events.
156      * @param {Event} e The keydown event object.
157      * @private
158      */
159     handleKeyDown_: function(e) {
160       // Map delete (and backspace on Mac) to item deletion (unless focus is
161       // in an input field, where it's intended for text editing).
162       if ((e.keyCode == 46 || (e.keyCode == 8 && cr.isMac)) &&
163           e.target.tagName != 'INPUT') {
164         this.deleteSelectedItems_();
165         // Prevent the browser from going back.
166         e.preventDefault();
167       }
168     },
169
170     /**
171      * Deletes all the currently selected items that are deletable.
172      * @private
173      */
174     deleteSelectedItems_: function() {
175       var selected = this.selectionModel.selectedIndexes;
176       // Reverse through the list of selected indexes to maintain the
177       // correct index values after deletion.
178       for (var j = selected.length - 1; j >= 0; j--) {
179         var index = selected[j];
180         if (this.getListItemByIndex(index).deletable)
181           this.deleteItemAtIndex(index);
182       }
183     },
184
185     /**
186      * Called when an item should be deleted; subclasses are responsible for
187      * implementing.
188      * @param {number} index The index of the item that is being deleted.
189      */
190     deleteItemAtIndex: function(index) {
191     },
192   };
193
194   return {
195     DeletableItemList: DeletableItemList,
196     DeletableItem: DeletableItem,
197   };
198 });