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

Side by Side Diff: chrome/browser/resources/local_ntp/most_visited_single.js

Issue 997203003: Adds a new NTP endpoint for the single frame of the fast NTP (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 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 2015 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 // Single iframe for NTP tiles.
6 (function() {
7 'use strict';
8
9 <include src="../../../../ui/webui/resources/js/util.js">
10
11 /**
12 * The different types of events that are logged from the NTP. This enum is
13 * used to transfer information from the NTP javascript to the renderer and is
14 * not used as a UMA enum histogram's logged value.
15 * Note: Keep in sync with common/ntp_logging_events.h
16 * @enum {number}
17 * @const
18 */
19 var LOGTYPE = {
20 // The suggestion is coming from the server.
21 NTP_SERVER_SIDE_SUGGESTION: 0,
22 // The suggestion is coming from the client.
23 NTP_CLIENT_SIDE_SUGGESTION: 1,
24 // Indicates a tile was rendered, no matter if it's a thumbnail, a gray tile
25 // or an external tile.
26 NTP_TILE: 2,
27 // The tile uses a local thumbnail image.
28 NTP_THUMBNAIL_TILE: 3,
29 // Used when no thumbnail is specified and a gray tile with the domain is used
30 // as the main tile.
31 NTP_GRAY_TILE: 4,
32 // The visuals of that tile are handled externally by the page itself.
33 NTP_EXTERNAL_TILE: 5,
34 // There was an error in loading both the thumbnail image and the fallback
35 // (if it was provided), resulting in a grey tile.
36 NTP_THUMBNAIL_ERROR: 6,
37 // Used a gray tile with the domain as the fallback for a failed thumbnail.
38 NTP_GRAY_TILE_FALLBACK: 7,
39 // The visuals of that tile's fallback are handled externally.
40 NTP_EXTERNAL_TILE_FALLBACK: 8,
41 // The user moused over an NTP tile or title.
42 NTP_MOUSEOVER: 9
43 };
44
45 /**
46 * The origin of this request.
47 * @const {string}
48 */
49 var DOMAIN_ORIGIN = '{{ORIGIN}}';
50
51 /**
52 * Counter for DOM elements that we are waiting to finish loading.
53 * @type {number}
54 */
55 var loadedCounter = 1;
56
57 /**
58 * DOM element containing the tiles we are going to present next.
59 * Works as a double-buffer that is shown when we receive a "show" postMessage.
60 * @type {DOM}
61 */
62 var tiles = null;
63
64 /**
65 * Log an event on the NTP
66 * @param {number} eventName Event from NTP_LOGGING_EVENT_TYPE.
67 */
68 var logEvent = function(eventName) {
69 chrome.embeddedSearch.newTabPage.logEvent(eventName);
70 };
71
72
73 /**
74 * Down count the DOM elements that we are waiting for the page to load.
75 * When we get to 0, we send a message to the parent window.
76 * This is usually used as an EventListener of onload/onerror.
77 */
78 var countLoad = function() {
79 loadedCounter--;
80 if (loadedCounter <= 0.0) {
huangs 2015/03/11 19:14:58 Why not just 0?
fserb 2015/03/11 19:30:58 Done.
81 window.parent.postMessage({cmd: 'loaded' }, DOMAIN_ORIGIN);
82 loadedCounter = 1;
83 }
84 };
85
86
87 /**
88 * Handle postMessages coming from the host page to the iframe.
89 * We try to keep the logic here to a minimum and just dispatch to the relevant
90 * functions.
91 **/
92 var handlePostMessage = function(event) {
93 var cmd = event.data.cmd;
94 var args = event.data;
95
96 if (cmd == 'tile') {
97 addTile(args);
98 } else if (cmd == 'show') {
99 showTiles();
100 countLoad();
101 } else {
102 console.error('Unknown command: ' + event.data);
103 }
104 };
105
106 /**
107 * Called when the host page has finished sending us tile information and
108 * we are ready to show the new tiles and drop the old ones.
109 */
110 var showTiles = function() {
111 // store the tiles on the current closure.
112 var cur = tiles;
113
114 // Create empty tiles until we have 8.
115 while (cur.childNodes.length < 8) {
116 addTile({});
117 }
118
119 var parent = $('most-visited');
120
121 // Mark old tile DIV for removal after the transition animation is done.
122 var old = parent.querySelector('#mv-tiles');
123 if (old) {
124 old.id = 'mv-tiles-old';
125 cur.addEventListener('webkitTransitionEnd', function(ev) {
126 if (ev.target != cur) return;
huangs 2015/03/11 19:14:58 if (ev.target === cur) { parent.removeChild(old)
fserb 2015/03/11 19:30:57 Done.
127 parent.removeChild(old);
128 });
129 }
130
131 // Add new tileset.
132 cur.id = 'mv-tiles';
133 parent.appendChild(cur);
134 // We want the CSS transition to trigger, so need to add to the DOM before
135 // setting the style.
136 setTimeout(function() {
137 cur.style.opacity = 1.0;
138 }, 0);
139
140 // Make sure the tiles variable contain the next tileset we may use.
141 tiles = document.createElement('div');
142 };
143
144
145 /**
146 * Called when the host page wants to add a suggestion tile.
147 * For Most Visited, it grabs the data from Chrome and pass on.
148 * For host page generated it just passes the data.
149 * @param {object} args Data for the tile to be rendered.
150 */
151 var addTile = function(args) {
152 if (args.rid) {
153 var data = chrome.embeddedSearch.searchBox.getMostVisitedItemData(args.rid);
154 tiles.appendChild(renderTile(data));
155 logEvent(LOGTYPE.NTP_CLIENT_SIDE_SUGGESTION);
156 } else {
157 tiles.appendChild(renderTile(null));
158 }
159 };
160
161
162 /**
163 * Called when the user decided to add a tile to the blacklist.
164 * It sets of the animation for the blacklist and sends the blacklisted id
165 * to the host page.
166 * @param {DOMNode} tile DOM node of the tile we want to remove.
167 */
168 var blacklistTile = function(tile) {
169 tile.className += ' blacklisted';
huangs 2015/03/11 19:14:57 Can use tile.classList.add('blacklisted'). Same b
fserb 2015/03/11 19:30:58 Done.
170 var sent = false;
171 tile.addEventListener('webkitTransitionEnd', function() {
172 if (sent) return;
173 sent = true;
174 window.parent.postMessage({cmd: 'tileBlacklisted',
175 rid: Number(tile.getAttribute('rid'))},
176 DOMAIN_ORIGIN);
177 });
178 };
179
180
181 /**
182 * Renders a MostVisited tile to the DOM.
183 * @param {object} data Object containing rid, url, title, favicon, thumbnail.
184 * data is null if you want to construct an empty tile.
185 */
186 var renderTile = function(data) {
187 var tile = document.createElement('a');
188 tile.className = 'mv-tile';
189
190 if (data == null) {
191 tile.className = 'mv-empty-tile';
192 return tile;
193 }
194
195 logEvent(LOGTYPE.NTP_TILE);
196
197 tile.setAttribute('rid', data.rid);
198 tile.innerHTML = '<div class="mv-favicon"></div>' +
199 '<div class="mv-title"></div><div class="mv-thumb"></div>' +
200 '<div title="Don\'t show on this page" class="mv-x"></div>';
201
202 tile.href = data.url;
203 tile.title = data.title;
204 tile.onkeypress = function(ev) {
205 if (ev.keyCode == 127) { // DELETE
206 blacklistTile(tile);
207 ev.stopPropagation();
208 return false;
209 }
210 };
211 tile.addEventListener('mouseover', function() {
212 logEvent(LOGTYPE.NTP_MOUSEOVER);
213 });
214
215 var title = tile.querySelectorAll('.mv-title')[0];
216 title.innerHTML = data.title;
217 title.style.direction = data.direction || 'ltr';
218
219 var thumb = tile.querySelectorAll('.mv-thumb')[0];
220
221 var img = document.createElement('img');
222 img.title = data.title;
223 if (data.thumbnailUrl) {
224 img.src = data.thumbnailUrl;
225 loadedCounter += 1;
226 img.addEventListener('load', countLoad);
227 img.addEventListener('error', countLoad);
228 img.addEventListener('error', function(ev) {
229 thumb.className += ' failed-img';
230 thumb.removeChild(img);
231 logEvent(LOGTYPE.NTP_THUMBNAIL_ERROR);
232 });
233 thumb.appendChild(img);
234 logEvent(LOGTYPE.NTP_THUMBNAIL_TILE);
235 } else {
236 thumb.className += ' failed-img';
237 }
238
239 var favicon = tile.querySelectorAll('.mv-favicon')[0];
240 if (data.faviconUrl) {
241 var fi = document.createElement('img');
242 fi.src = '../' + data.faviconUrl;
243 fi.title = '';
244 loadedCounter += 1;
245 fi.addEventListener('load', countLoad);
246 fi.addEventListener('error', countLoad);
247 fi.addEventListener('error', function(ev) {
248 favicon.className += ' failed-favicon';
249 });
250 favicon.appendChild(fi);
251 } else {
252 favicon.className += ' failed-favicon';
253 }
254
255 var mvx = tile.querySelectorAll('.mv-x')[0];
256 mvx.onclick = function(ev) {
257 blacklistTile(tile);
258 ev.stopPropagation();
259 return false;
260 };
261
262 return tile;
263 };
264
265
266 /**
267 * Do some initialization and parses the query arguments passed to the iframe.
268 */
269 var init = function() {
270 // Creates a new DOM element to hold the tiles.
271 tiles = document.createElement('div');
272
273 // Parse query arguments.
274 var query = window.location.search.substring(1).split('&');
275 var args = {};
276 for (var i = 0; i < query.length; ++i) {
277 var val = query[i].split('=');
278 if (val[0] == '') continue;
279 args[decodeURIComponent(val[0])] = decodeURIComponent(val[1]);
280 }
281
282 // Enable RTL.
283 if (args['rtl'] == '1') {
284 var html = document.querySelector('html');
285 html.dir = 'rtl';
286 }
287
288 window.addEventListener('message', handlePostMessage);
289 };
290
291 window.addEventListener('DOMContentLoaded', init);
292 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698