Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / ui / file_manager / file_manager / foreground / js / ui / search_box.js
1 // Copyright 2013 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 'use strict';
6
7 /**
8  * Search box.
9  *
10  * @param {element} element Root element of the search box.
11  * @constructor
12  */
13 function SearchBox(element) {
14   /**
15    * Autocomplete List.
16    * @type {AutocompleteList}
17    */
18   this.autocompleteList = new SearchBox.AutocompleteList(element.ownerDocument);
19
20   /**
21    * Root element of the search box.
22    * @type {HTMLElement}
23    */
24   this.element = element;
25
26   /**
27    * Text input of the search box.
28    * @type {HTMLElement}
29    */
30   this.inputElement = element.querySelector('input');
31
32   /**
33    * Clear button of the search box.
34    * @type {HTMLElement}
35    */
36   this.clearButton = element.querySelector('.clear');
37
38   Object.freeze(this);
39
40   // Register events.
41   this.inputElement.addEventListener('input', this.updateStyles_.bind(this));
42   this.inputElement.addEventListener('keydown', this.onKeyDown_.bind(this));
43   this.inputElement.addEventListener('focus', this.onFocus_.bind(this));
44   this.inputElement.addEventListener('blur', this.onBlur_.bind(this));
45   this.inputElement.ownerDocument.addEventListener('dragover',
46                                                    this.onDragEnter_.bind(this),
47                                                    true);
48   this.inputElement.ownerDocument.addEventListener('dragend',
49                                                    this.onDragEnd_.bind(this),
50                                                    true);
51   element.parentNode.appendChild(this.autocompleteList);
52 }
53
54 /**
55  * Autocomplete list for search box.
56  * @param {HTMLDocument} document Document.
57  * @constructor
58  */
59 SearchBox.AutocompleteList = function(document) {
60   var self = cr.ui.AutocompleteList.call(this);
61   self.__proto__ = SearchBox.AutocompleteList.prototype;
62   self.id = 'autocomplete-list';
63   self.autoExpands = true;
64   self.itemConstructor = SearchBox.AutocompleteListItem_.bind(null, document);
65   self.addEventListener('mouseover', self.onMouseOver_.bind(self));
66   return self;
67 };
68
69 SearchBox.AutocompleteList.prototype = {
70   __proto__: cr.ui.AutocompleteList.prototype
71 };
72
73 /**
74  * Do nothing when a suggestion is selected.
75  * @override
76  */
77 SearchBox.AutocompleteList.prototype.handleSelectedSuggestion = function() {};
78
79 /**
80  * Change the selection by a mouse over instead of just changing the
81  * color of moused over element with :hover in CSS. Here's why:
82  *
83  * 1) The user selects an item A with up/down keys (item A is highlighted)
84  * 2) Then the user moves the cursor to another item B
85  *
86  * If we just change the color of moused over element (item B), both
87  * the item A and B are highlighted. This is bad. We should change the
88  * selection so only the item B is highlighted.
89  *
90  * @param {Event} event Event.
91  * @private
92  */
93 SearchBox.AutocompleteList.prototype.onMouseOver_ = function(event) {
94   if (event.target.itemInfo)
95     this.selectedItem = event.target.itemInfo;
96 };
97
98 /**
99  * ListItem element for autocomplete.
100  *
101  * @param {HTMLDocument} document Document.
102  * @param {Object} item An object representing a suggestion.
103  * @constructor
104  * @private
105  */
106 SearchBox.AutocompleteListItem_ = function(document, item) {
107   var li = new cr.ui.ListItem();
108   li.itemInfo = item;
109
110   var icon = document.createElement('div');
111   icon.className = 'detail-icon';
112
113   var text = document.createElement('div');
114   text.className = 'detail-text';
115
116   if (item.isHeaderItem) {
117     icon.setAttribute('search-icon', '');
118     text.innerHTML =
119         strf('SEARCH_DRIVE_HTML', util.htmlEscape(item.searchQuery));
120   } else {
121     var iconType = FileType.getIcon(item.entry);
122     icon.setAttribute('file-type-icon', iconType);
123     // highlightedBaseName is a piece of HTML with meta characters properly
124     // escaped. See the comment at fileManagerPrivate.searchDriveMetadata().
125     text.innerHTML = item.highlightedBaseName;
126   }
127   li.appendChild(icon);
128   li.appendChild(text);
129   return li;
130 };
131
132 /**
133  * Clears the search query.
134  */
135 SearchBox.prototype.clear = function() {
136   this.inputElement.value = '';
137   this.updateStyles_();
138 };
139
140 /**
141  * Handles a focus event of the search box.
142  * @private
143  */
144 SearchBox.prototype.onFocus_ = function() {
145   this.element.classList.toggle('has-cursor', true);
146   this.inputElement.tabIndex = '99';  // See: go/filesapp-tabindex.
147   this.autocompleteList.attachToInput(this.inputElement);
148 };
149
150 /**
151  * Handles a blur event of the search box.
152  * @private
153  */
154 SearchBox.prototype.onBlur_ = function() {
155   this.element.classList.toggle('has-cursor', false);
156   this.inputElement.tabIndex = '-1';
157   this.autocompleteList.detach();
158 };
159
160 /**
161  * Handles a keydown event of the search box.
162  * @private
163  */
164 SearchBox.prototype.onKeyDown_ = function() {
165   // Handle only Esc key now.
166   if (event.keyCode != 27 || this.inputElement.value)
167     return;
168   this.inputElement.blur();
169 };
170
171 /**
172  * Handles a dragenter event and refuses a drag source of files.
173  * @param {DragEvent} event The dragenter event.
174  * @private
175  */
176 SearchBox.prototype.onDragEnter_ = function(event) {
177   // For normal elements, they does not accept drag drop by default, and accept
178   // it by using event.preventDefault. But input elements accept drag drop
179   // by default. So disable the input element here to prohibit drag drop.
180   if (event.dataTransfer.types.indexOf('text/plain') === -1)
181     this.inputElement.style.pointerEvents = 'none';
182 };
183
184 /**
185  * Handles a dragend event.
186  * @private
187  */
188 SearchBox.prototype.onDragEnd_ = function() {
189   this.inputElement.style.pointerEvents = '';
190 };
191
192 /**
193  * Updates styles of the search box.
194  * @private
195  */
196 SearchBox.prototype.updateStyles_ = function() {
197   this.element.classList.toggle('has-text',
198                                 !!this.inputElement.value);
199 };