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

Side by Side Diff: chrome/browser/resources/local_omnibox_popup/local_omnibox_popup.js

Issue 13905008: Merge local_omnibox_popup into local_ntp. Render the Google logo and fakebox if Google is the sear… (Closed) Base URL: https://git.chromium.org/chromium/src.git@master
Patch Set: Respond to Samarth's comments. Created 7 years, 8 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
OLDNEW
(Empty)
1 // Copyright 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 /**
6 * @fileoverview Support for omnibox behavior in offline mode or when API
7 * features are not supported on the server.
8 */
9
10 // ==========================================================
11 // Enums.
12 // ==========================================================
13
14 /**
15 * Possible behaviors for navigateContentWindow.
16 * @enum {number}
17 */
18 var WindowOpenDisposition = {
19 CURRENT_TAB: 1,
20 NEW_BACKGROUND_TAB: 2
21 };
22
23 /**
24 * The JavaScript button event value for a middle click.
25 * @type {number}
26 * @const
27 */
28 var MIDDLE_MOUSE_BUTTON = 1;
29
30 // =============================================================================
31 // Util functions
32 // =============================================================================
33
34 /**
35 * The maximum number of suggestions to show.
36 * @type {number}
37 * @const
38 */
39 var MAX_SUGGESTIONS_TO_SHOW = 5;
40
41 /**
42 * Assume any native suggestion with a score higher than this value has been
43 * inlined by the browser.
44 * @type {number}
45 * @const
46 */
47 var INLINE_SUGGESTION_THRESHOLD = 1200;
48
49 /**
50 * Suggestion provider type corresponding to a verbatim URL suggestion.
51 * @type {string}
52 * @const
53 */
54 var VERBATIM_URL_TYPE = 'url-what-you-typed';
55
56 /**
57 * Suggestion provider type corresponding to a verbatim search suggestion.
58 * @type {string}
59 * @const
60 */
61 var VERBATIM_SEARCH_TYPE = 'search-what-you-typed';
62
63 /**
64 * The omnibox input value during the last onnativesuggestions event.
65 * @type {string}
66 */
67 var lastInputValue = '';
68
69 /**
70 * The ordered restricted ids of the currently displayed suggestions. Since the
71 * suggestions contain the user's personal data (browser history) the searchBox
72 * API embeds the content of the suggestion in a shadow dom, and assigns a
73 * random restricted id to each suggestion which is accessible to the JS.
74 * @type {Array.<number>}
75 */
76
77 var restrictedIds = [];
78
79 /**
80 * The index of the currently selected suggestion or -1 if none are selected.
81 * @type {number}
82 */
83 var selectedIndex = -1;
84
85 /**
86 * Shortcut for document.getElementById.
87 * @param {string} id of the element.
88 * @return {HTMLElement} with the id.
89 */
90 function $(id) {
91 return document.getElementById(id);
92 }
93
94 /**
95 * Displays a suggestion.
96 * @param {Object} suggestion The suggestion to render.
97 * @param {HTMLElement} box The html element to add the suggestion to.
98 * @param {boolean} select True to select the selection.
99 */
100 function addSuggestionToBox(suggestion, box, select) {
101 var suggestionDiv = document.createElement('div');
102 suggestionDiv.classList.add('suggestion');
103 suggestionDiv.classList.toggle('selected', select);
104 suggestionDiv.classList.toggle('search', suggestion.is_search);
105
106 if (suggestion.destination_url) { // iframes.
107 var suggestionIframe = document.createElement('iframe');
108 suggestionIframe.className = 'contents';
109 suggestionIframe.src = suggestion.destination_url;
110 suggestionIframe.id = suggestion.rid;
111 suggestionDiv.appendChild(suggestionIframe);
112 } else {
113 var contentsContainer = document.createElement('div');
114 var contents = suggestion.combinedNode;
115 contents.classList.add('contents');
116 contentsContainer.appendChild(contents);
117 suggestionDiv.appendChild(contentsContainer);
118 suggestionDiv.onclick = function(event) {
119 handleSuggestionClick(suggestion.rid, event.button);
120 };
121 }
122
123 restrictedIds.push(suggestion.rid);
124 box.appendChild(suggestionDiv);
125 }
126
127 /**
128 * Renders the input suggestions.
129 * @param {Array} nativeSuggestions An array of native suggestions to render.
130 */
131 function renderSuggestions(nativeSuggestions) {
132 var box = document.createElement('div');
133 box.id = 'suggestionsBox';
134 $('suggestions-box-container').appendChild(box);
135
136 for (var i = 0, length = nativeSuggestions.length;
137 i < Math.min(MAX_SUGGESTIONS_TO_SHOW, length); ++i) {
138 // Don't add the search-what-you-typed suggestion if it's the top match.
139 if (i > 0 || nativeSuggestions[i].type != VERBATIM_SEARCH_TYPE)
140 addSuggestionToBox(nativeSuggestions[i], box, i == selectedIndex);
141 }
142 }
143
144 /**
145 * Clears the suggestions being displayed.
146 */
147 function clearSuggestions() {
148 $('suggestions-box-container').innerHTML = '';
149 restrictedIds = [];
150 selectedIndex = -1;
151 }
152
153 /**
154 * @return {number} The height of the dropdown.
155 */
156 function getDropdownHeight() {
157 return $('suggestions-box-container').offsetHeight;
158 }
159
160 /**
161 * @param {Object} suggestion A suggestion.
162 * @param {boolean} inVerbatimMode Are we in verbatim mode?
163 * @return {boolean} True if the suggestion should be selected.
164 */
165 function shouldSelectSuggestion(suggestion, inVerbatimMode) {
166 var isVerbatimUrl = suggestion.type == VERBATIM_URL_TYPE;
167 var inlinableSuggestion = suggestion.type != VERBATIM_SEARCH_TYPE &&
168 suggestion.rankingData.relevance > INLINE_SUGGESTION_THRESHOLD;
169 // Verbatim URLs should always be selected. Otherwise, select suggestions
170 // with a high enough score unless we are in verbatim mode (e.g. backspacing
171 // away).
172 return isVerbatimUrl || (!inVerbatimMode && inlinableSuggestion);
173 }
174
175 /**
176 * Updates selectedIndex, bounding it between -1 and the total number of
177 * of suggestions - 1 (looping as necessary), and selects the corresponding
178 * suggestion.
179 * @param {boolean} increment True to increment the selected suggestion, false
180 * to decrement.
181 */
182 function updateSelectedSuggestion(increment) {
183 var numSuggestions = restrictedIds.length;
184 if (!numSuggestions)
185 return;
186
187 var oldSelection = $('suggestionsBox').querySelector('.selected');
188 if (oldSelection)
189 oldSelection.classList.remove('selected');
190
191 if (increment)
192 selectedIndex = ++selectedIndex > numSuggestions - 1 ? -1 : selectedIndex;
193 else
194 selectedIndex = --selectedIndex < -1 ? numSuggestions - 1 : selectedIndex;
195 var apiHandle = getApiObjectHandle();
196 if (selectedIndex == -1) {
197 apiHandle.setValue(lastInputValue);
198 } else {
199 var newSelection = $('suggestionsBox').querySelector(
200 '.suggestion:nth-of-type(' + (selectedIndex + 1) + ')');
201 newSelection.classList.add('selected');
202 apiHandle.setRestrictedValue(restrictedIds[selectedIndex]);
203 }
204 }
205
206 // =============================================================================
207 // Handlers / API stuff
208 // =============================================================================
209
210 /**
211 * @return {Object} the handle to the searchBox API.
212 */
213 function getApiObjectHandle() {
214 if (window.cideb)
215 return window.cideb;
216 if (window.navigator && window.navigator.embeddedSearch &&
217 window.navigator.embeddedSearch.searchBox)
218 return window.navigator.embeddedSearch.searchBox;
219 if (window.chrome && window.chrome.embeddedSearch &&
220 window.chrome.embeddedSearch.searchBox)
221 return window.chrome.embeddedSearch.searchBox;
222 return null;
223 }
224
225 /**
226 * Updates suggestions in response to a onchange or onnativesuggestions call.
227 */
228 function updateSuggestions() {
229 var apiHandle = getApiObjectHandle();
230 lastInputValue = apiHandle.value;
231
232 clearSuggestions();
233 var nativeSuggestions = apiHandle.nativeSuggestions;
234 if (nativeSuggestions.length) {
235 nativeSuggestions.sort(function(a, b) {
236 return b.rankingData.relevance - a.rankingData.relevance;
237 });
238 if (shouldSelectSuggestion(nativeSuggestions[0], apiHandle.verbatim))
239 selectedIndex = 0;
240 renderSuggestions(nativeSuggestions);
241 }
242
243 var height = getDropdownHeight();
244 apiHandle.showOverlay(height);
245 }
246
247 /**
248 * Appends a style node for suggestion properties that depend on apiHandle.
249 */
250 function appendSuggestionStyles() {
251 var apiHandle = getApiObjectHandle();
252 var isRtl = apiHandle.rtl;
253 var startMargin = apiHandle.startMargin;
254 var style = document.createElement('style');
255 style.type = 'text/css';
256 style.id = 'suggestionStyle';
257 style.textContent =
258 '.suggestion, ' +
259 '.suggestion.search {' +
260 ' background-position: ' +
261 (isRtl ? '-webkit-calc(100% - 5px)' : '5px') + ' 4px;' +
262 ' -webkit-margin-start: ' + startMargin + 'px;' +
263 ' -webkit-margin-end: ' +
264 (window.innerWidth - apiHandle.width - startMargin) + 'px;' +
265 ' font: ' + apiHandle.fontSize + 'px "' + apiHandle.font + '";' +
266 '}';
267 document.querySelector('head').appendChild(style);
268 window.removeEventListener('resize', appendSuggestionStyles);
269 }
270
271 /**
272 * Extract the desired navigation behavior from a click button.
273 * @param {number} button The Event#button property of a click event.
274 * @return {WindowOpenDisposition} The desired behavior for
275 * navigateContentWindow.
276 */
277 function getDispositionFromClickButton(button) {
278 if (button == MIDDLE_MOUSE_BUTTON)
279 return WindowOpenDisposition.NEW_BACKGROUND_TAB;
280 return WindowOpenDisposition.CURRENT_TAB;
281 }
282
283 /**
284 * Handles suggestion clicks.
285 * @param {number} restrictedId The restricted id of the suggestion being
286 * clicked.
287 * @param {number} button The Event#button property of a click event.
288 *
289 */
290 function handleSuggestionClick(restrictedId, button) {
291 clearSuggestions();
292 getApiObjectHandle().navigateContentWindow(
293 restrictedId, getDispositionFromClickButton(button));
294 }
295
296 /**
297 * chrome.searchBox.onkeypress implementation.
298 * @param {Object} e The key being pressed.
299 */
300 function handleKeyPress(e) {
301 switch (e.keyCode) {
302 case 38: // Up arrow
303 updateSelectedSuggestion(false);
304 break;
305 case 40: // Down arrow
306 updateSelectedSuggestion(true);
307 break;
308 }
309 }
310
311 /**
312 * Handles the postMessage calls from the result iframes.
313 * @param {Object} message The message containing details of clicks the iframes.
314 */
315 function handleMessage(message) {
316 if (message.origin != 'null' || !message.data ||
317 message.data.eventType != 'click') {
318 return;
319 }
320
321 var iframes = document.getElementsByClassName('contents');
322 for (var i = 0; i < iframes.length; ++i) {
323 if (iframes[i].contentWindow == message.source) {
324 handleSuggestionClick(parseInt(iframes[i].id, 10),
325 message.data.button);
326 break;
327 }
328 }
329 }
330
331 /**
332 * chrome.searchBox.embeddedSearch.onsubmit implementation.
333 */
334 function onSubmit() {
335 }
336
337 /**
338 * Sets up the searchBox API.
339 */
340 function setUpApi() {
341 var apiHandle = getApiObjectHandle();
342 apiHandle.onnativesuggestions = updateSuggestions;
343 apiHandle.onchange = updateSuggestions;
344 apiHandle.onkeypress = handleKeyPress;
345 apiHandle.onsubmit = onSubmit;
346 $('suggestions-box-container').dir = apiHandle.rtl ? 'rtl' : 'ltr';
347 // Delay adding these styles until the window width is available.
348 window.addEventListener('resize', appendSuggestionStyles);
349 if (apiHandle.nativeSuggestions.length)
350 handleNativeSuggestions();
351 }
352
353 document.addEventListener('DOMContentLoaded', setUpApi);
354 window.addEventListener('message', handleMessage, false);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698