Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(188)

Side by Side Diff: chrome/browser/resources/options/autocomplete_list.js

Issue 9168026: Move autocomplete_list.js from options and options2 to shared/js (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: copyright year 2012 Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | chrome/browser/resources/options/browser_options.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 ArrayDataModel = cr.ui.ArrayDataModel;
7 const List = cr.ui.List;
8 const ListItem = cr.ui.ListItem;
9
10 /**
11 * Creates a new autocomplete list item.
12 * @param {Object} pageInfo The page this item represents.
13 * @constructor
14 * @extends {cr.ui.ListItem}
15 */
16 function AutocompleteListItem(pageInfo) {
17 var el = cr.doc.createElement('div');
18 el.pageInfo_ = pageInfo;
19 AutocompleteListItem.decorate(el);
20 return el;
21 }
22
23 /**
24 * Decorates an element as an autocomplete list item.
25 * @param {!HTMLElement} el The element to decorate.
26 */
27 AutocompleteListItem.decorate = function(el) {
28 el.__proto__ = AutocompleteListItem.prototype;
29 el.decorate();
30 };
31
32 AutocompleteListItem.prototype = {
33 __proto__: ListItem.prototype,
34
35 /** @inheritDoc */
36 decorate: function() {
37 ListItem.prototype.decorate.call(this);
38
39 var title = this.pageInfo_['title'];
40 var url = this.pageInfo_['displayURL'];
41 var titleEl = this.ownerDocument.createElement('span');
42 titleEl.className = 'title';
43 titleEl.textContent = title || url;
44 this.appendChild(titleEl);
45
46 if (title && title.length > 0 && url != title) {
47 var separatorEl = this.ownerDocument.createTextNode(' - ');
48 this.appendChild(separatorEl);
49
50 var urlEl = this.ownerDocument.createElement('span');
51 urlEl.className = 'url';
52 urlEl.textContent = url;
53 this.appendChild(urlEl);
54 }
55 },
56 };
57
58 /**
59 * Creates a new autocomplete list popup.
60 * @constructor
61 * @extends {cr.ui.List}
62 */
63 var AutocompleteList = cr.ui.define('list');
64
65 AutocompleteList.prototype = {
66 __proto__: List.prototype,
67
68 /**
69 * The text field the autocomplete popup is currently attached to, if any.
70 * @type {HTMLElement}
71 * @private
72 */
73 targetInput_: null,
74
75 /**
76 * Keydown event listener to attach to a text field.
77 * @type {Function}
78 * @private
79 */
80 textFieldKeyHandler_: null,
81
82 /**
83 * Input event listener to attach to a text field.
84 * @type {Function}
85 * @private
86 */
87 textFieldInputHandler_: null,
88
89 /**
90 * A function to call when new suggestions are needed.
91 * @type {Function}
92 * @private
93 */
94 suggestionUpdateRequestCallback_: null,
95
96 /** @inheritDoc */
97 decorate: function() {
98 List.prototype.decorate.call(this);
99 this.classList.add('autocomplete-suggestions');
100 this.selectionModel = new cr.ui.ListSingleSelectionModel;
101
102 this.textFieldKeyHandler_ = this.handleAutocompleteKeydown_.bind(this);
103 var self = this;
104 this.textFieldInputHandler_ = function(e) {
105 if (self.suggestionUpdateRequestCallback_)
106 self.suggestionUpdateRequestCallback_(self.targetInput_.value);
107 };
108 this.addEventListener('change', function(e) {
109 var input = self.targetInput;
110 if (!input || !self.selectedItem)
111 return;
112 input.value = self.selectedItem['url'];
113 // Programatically change the value won't trigger a change event, but
114 // clients are likely to want to know when changes happen, so fire one.
115 var changeEvent = document.createEvent('Event');
116 changeEvent.initEvent('change', true, true);
117 input.dispatchEvent(changeEvent);
118 });
119 // Start hidden; adding suggestions will unhide.
120 this.hidden = true;
121 },
122
123 /** @inheritDoc */
124 createItem: function(pageInfo) {
125 return new AutocompleteListItem(pageInfo);
126 },
127
128 /**
129 * The suggestions to show.
130 * @type {Array}
131 */
132 set suggestions(suggestions) {
133 this.dataModel = new ArrayDataModel(suggestions);
134 this.hidden = !this.targetInput_ || suggestions.length == 0;
135 },
136
137 /**
138 * A function to call when the attached input field's contents change.
139 * The function should take one string argument, which will be the text
140 * to autocomplete from.
141 * @type {Function}
142 */
143 set suggestionUpdateRequestCallback(callback) {
144 this.suggestionUpdateRequestCallback_ = callback;
145 },
146
147 /**
148 * Attaches the popup to the given input element. Requires
149 * that the input be wrapped in a block-level container of the same width.
150 * @param {HTMLElement} input The input element to attach to.
151 */
152 attachToInput: function(input) {
153 if (this.targetInput_ == input)
154 return;
155
156 this.detach();
157 this.targetInput_ = input;
158 this.style.width = input.getBoundingClientRect().width + 'px';
159 this.hidden = false; // Necessary for positionPopupAroundElement to work.
160 cr.ui.positionPopupAroundElement(input, this, cr.ui.AnchorType.BELOW)
161 // Start hidden; when the data model gets results the list will show.
162 this.hidden = true;
163
164 input.addEventListener('keydown', this.textFieldKeyHandler_, true);
165 input.addEventListener('input', this.textFieldInputHandler_);
166 },
167
168 /**
169 * Detaches the autocomplete popup from its current input element, if any.
170 */
171 detach: function() {
172 var input = this.targetInput_
173 if (!input)
174 return;
175
176 input.removeEventListener('keydown', this.textFieldKeyHandler_, true);
177 input.removeEventListener('input', this.textFieldInputHandler_);
178 this.targetInput_ = null;
179 this.suggestions = [];
180 },
181
182 /**
183 * Makes sure that the suggestion list matches the width of the input it is.
184 * attached to. Should be called any time the input is resized.
185 */
186 syncWidthToInput: function() {
187 var input = this.targetInput_
188 if (input)
189 this.style.width = input.getBoundingClientRect().width + 'px';
190 },
191
192 /**
193 * The text field the autocomplete popup is currently attached to, if any.
194 * @return {HTMLElement}
195 */
196 get targetInput() {
197 return this.targetInput_;
198 },
199
200 /**
201 * Handles input field key events that should be interpreted as autocomplete
202 * commands.
203 * @param {Event} event The keydown event.
204 * @private
205 */
206 handleAutocompleteKeydown_: function(event) {
207 if (this.hidden)
208 return;
209 var handled = false;
210 switch (event.keyIdentifier) {
211 case 'U+001B': // Esc
212 this.suggestions = [];
213 handled = true;
214 break;
215 case 'Enter':
216 // If the user has already selected an item using the arrow keys then
217 // presses Enter, clear the suggestions but also keep
218 // |handled| = false, so the input field can handle the event as well.
219 this.suggestions = [];
220 break;
221 case 'Up':
222 case 'Down':
223 var newEvent = new cr.Event(event.type);
224 newEvent.keyIdentifier = event.keyIdentifier;
225 this.dispatchEvent(newEvent);
226 handled = true;
227 break;
228 }
229 // Don't let arrow keys affect the text field, or bubble up to, e.g.,
230 // an enclosing list item.
231 if (handled) {
232 event.preventDefault();
233 event.stopPropagation();
234 }
235 },
236 };
237
238 return {
239 AutocompleteList: AutocompleteList
240 };
241 });
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/resources/options/browser_options.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698