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

Side by Side Diff: chrome/browser/resources/ntp_search/thumbnail_page.js

Issue 10823052: Refactoring the NTP. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 4 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 (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('ntp', function() {
6 'use strict';
7
8 var Tile = ntp.Tile2;
9 var TilePage = ntp.TilePage2;
10
11 /**
12 * A counter for generating unique tile IDs.
13 */
14 var tileID = 0;
15
16 /**
17 * Creates a new Most Visited object for tiling.
jeremycho_google 2012/07/31 03:09:16 Rename references to Most Visited in the comments
pedrosimonetti2 2012/08/03 18:14:01 Done.
18 * @constructor
19 * @extends {HTMLAnchorElement}
20 */
21 function Thumbnail(gridValues) {
22 var el = cr.doc.createElement('a');
23 el.__proto__ = Thumbnail.prototype;
24 el.initialize(gridValues);
25
26 return el;
27 }
28
29 Thumbnail.prototype = Tile.subclass({
30 __proto__: HTMLAnchorElement.prototype,
31
32 // TODO(pedrosimonetti): document
33 isRemovable: true,
34
35 initialize: function(gridValues) {
36 Tile.prototype.initialize.apply(this, arguments);
37 this.reset();
38
39 this.addEventListener('click', this.handleClick_);
40 this.addEventListener('keydown', this.handleKeyDown_);
41 },
42
43 get index() {
44 assert(this.tile);
45 return this.tile.index;
46 },
47
48 get data() {
49 return this.data_;
50 },
51
52 /**
53 * Clears the DOM hierarchy for this node, setting it back to the default
54 * for a blank thumbnail.
55 */
56 reset: function() {
57 this.className = 'tile-content most-visited real';
58 this.innerHTML =
59 '<span class="thumbnail-wrapper fills-parent">' +
60 (this.isRemovable ? '<div class="close-button"></div>' : '') +
61 '<span class="thumbnail fills-parent">' +
62 // TODO(pedrosimonetti): remove all references (HTML+CSS+JS)
63 // thumbnail-shield provides a gradient fade effect.
64 //'<div class="thumbnail-shield fills-parent"></div>' +
65 '</span>' +
66 // TODO(pedrosimonetti): remove all references (HTML+CSS+JS)
67 //'<span class="favicon"></span>' +
68 '</span>' +
69 // TODO(pedrosimonetti): remove all references (HTML+CSS+JS)
70 //'<div class="color-stripe"></div>' +
71 '<span class="title"></span>';
72
73 if (this.isRemovable) {
74 this.querySelector('.close-button').title =
75 loadTimeData.getString('removethumbnailtooltip');
76 }
77
78 this.tabIndex = -1;
79 this.data_ = null;
80 this.removeAttribute('id');
81 this.title = '';
82 },
83
84 /**
85 * Update the appearance of this tile according to |data|.
86 * @param {Object} data A dictionary of relevant data for the page.
87 */
88 updateForData: function(data) {
89 if (this.classList.contains('blacklisted') && data) {
90 // Animate appearance of new tile.
91 this.classList.add('new-tile-contents');
92 }
93 this.classList.remove('blacklisted');
94
95 if (!data || data.filler) {
96 if (this.data_)
97 this.reset();
98 return;
99 }
100
101 var id = tileID++;
102 // TODO(pedrosimonetti): refactor
103 this.id = 'most-visited-tile-' + id;
104 this.data_ = data;
105 this.classList.add('focusable');
106
107 // TODO(pedrosimonetti): remove all references (HTML+CSS+JS)
108 //var faviconDiv = this.querySelector('.favicon');
109 //var faviconUrl = 'chrome://favicon/size/16/' + data.url;
110 //faviconDiv.style.backgroundImage = url(faviconUrl);
111 //chrome.send('getFaviconDominantColor', [faviconUrl, this.id]);
112
113 var title = this.querySelector('.title');
114 title.textContent = data.title;
115 title.dir = data.direction;
116
117 // Sets the tooltip.
118 this.title = data.title;
119
120 var thumbnailUrl = ntp.getThumbnailUrl(data.url);
121 this.querySelector('.thumbnail').style.backgroundImage =
122 url(thumbnailUrl);
123
124 this.href = data.url;
125
126 this.classList.remove('filler');
127 },
128
129 /**
130 * Sets the color of the favicon dominant color bar.
131 * @param {string} color The css-parsable value for the color.
132 */
133 // TODO(xci) delete
134 //set stripeColor(color) {
135 // this.querySelector('.color-stripe').style.backgroundColor = color;
136 //},
137
138 /**
139 * Handles a click on the tile.
140 * @param {Event} e The click event.
141 */
142 handleClick_: function(e) {
143 debugger;
144 if (e.target.classList.contains('close-button')) {
145 this.blacklist_();
146 e.preventDefault();
147 } else {
148 // Records an app launch from the most visited page (Chrome will decide
149 // whether the url is an app). TODO(estade): this only works for clicks;
150 // other actions like "open in new tab" from the context menu won't be
151 // recorded. Can this be fixed?
152 chrome.send('recordAppLaunchByURL',
153 [encodeURIComponent(this.href),
154 ntp.APP_LAUNCH.NTP_MOST_VISITED]);
155 // Records the index of this tile.
156 chrome.send('metricsHandler:recordInHistogram',
157 ['NewTabPage.Thumbnail', this.index, 8]);
158 chrome.send('mostVisitedAction',
159 [ntp.NtpFollowAction.CLICKED_TILE]);
160 }
161 },
162
163 /**
164 * Allow blacklisting most visited site using the keyboard.
jeremycho_google 2012/07/31 03:09:16 Is MostVisited the only type of tile that will be
pedrosimonetti2 2012/08/03 18:14:01 Done.
165 */
166 handleKeyDown_: function(e) {
167 if (!cr.isMac && e.keyCode == 46 || // Del
168 cr.isMac && e.metaKey && e.keyCode == 8) { // Cmd + Backspace
169 this.blacklist_();
170 }
171 },
172
173 /**
174 * Permanently removes a page from Most Visited.
175 */
176 blacklist_: function() {
177 this.showUndoNotification_();
178 chrome.send('blacklistURLFromThumbnail', [this.data_.url]);
179 this.reset();
180 chrome.send('getThumbnail');
181 this.classList.add('blacklisted');
182 },
183
184 showUndoNotification_: function() {
185 var data = this.data_;
186 var self = this;
187 var doUndo = function() {
188 chrome.send('removeURLsFromThumbnailBlacklist', [data.url]);
189 self.updateForData(data);
190 }
191
192 var undo = {
193 action: doUndo,
194 text: loadTimeData.getString('undothumbnailremove'),
195 };
196
197 var undoAll = {
198 action: function() {
199 chrome.send('clearThumbnailURLsBlacklist');
200 },
201 text: loadTimeData.getString('restoreThumbnailsShort'),
202 };
203
204 ntp.showNotification(
205 loadTimeData.getString('thumbnailremovednotification'),
206 [undo, undoAll]);
207 },
208
209 /**
210 * Returns whether this element can be 'removed' from chrome (i.e. whether
211 * the user can drag it onto the trash and expect something to happen).
212 * @return {boolean} True, since most visited pages can always be
213 * blacklisted.
214 */
215 canBeRemoved: function() {
216 return this.isRemovable;
217 },
218
219 /**
220 * Removes this element from chrome, i.e. blacklists it.
221 */
222 removeFromChrome: function() {
223 this.blacklist_();
224 this.parentNode.classList.add('finishing-drag');
225 },
226
227 /**
228 * Called when a drag of this tile has ended (after all animations have
229 * finished).
230 */
231 finalizeDrag: function() {
232 this.parentNode.classList.remove('finishing-drag');
233 },
234
235 /**
236 * Called when a drag is starting on the tile. Updates dataTransfer with
237 * data for this tile (for dragging outside of the NTP).
238 */
239 setDragData: function(dataTransfer) {
240 dataTransfer.setData('Text', this.data_.title);
241 dataTransfer.setData('URL', this.data_.url);
242 },
243 });
244
245 var THUMBNAIL_COUNT = 8; // TODO(xci)
jeremycho_google 2012/07/31 03:09:16 I still see the bug where 10 thumbnails are being
pedrosimonetti2 2012/08/03 18:14:01 Yes, I'll address it in another CL. I took another
246
247 /**
248 * Creates a new ThumbnailPage object.
249 * @constructor
250 * @extends {TilePage}
251 */
252 function ThumbnailPage() {
253 var el = new TilePage();
254 el.__proto__ = ThumbnailPage.prototype;
255 el.initialize();
256
257 return el;
258 }
259
260 ThumbnailPage.prototype = {
261 __proto__: TilePage.prototype,
262
263 gridValues_: {
264 tileWidth: 130,
265 tileHeight: 78,
266 tileHorMargin: 18, // TODO margin with CSS / there's no margin in first co l
267 tileVerMargin: 22,
268 tileBorderWidth: 1,
269 bottomPanelHorMargin: 100,
270
271 tileCount: 10, // debug
272 tileClassName: 'thumbnail',
273 reinforceStyles: true,
jeremycho_google 2012/07/31 03:09:16 Please document.
pedrosimonetti2 2012/08/03 18:14:01 Done.
274
275 // debug
276 slowFactor: 1,
277 debug: false
278 },
279
280 // TODO(pedrosimonetti): document
281 ThumbnailClass: Thumbnail,
282
283 initialize: function() {
284 this.classList.add('most-visited-page');
jeremycho_google 2012/07/31 03:09:16 Should this be renamed, given that other classes m
pedrosimonetti2 2012/08/03 18:14:01 Yes. I renamed it to 'thumbnail-page' and override
285 this.data_ = null;
286 this.mostVisitedTiles_ = this.getElementsByClassName('most-visited real');
287
288 this.addEventListener('carddeselected', this.handleCardDeselected_);
289 this.addEventListener('cardselected', this.handleCardSelected_);
290 },
291
292 /**
293 * Create blank (filler) tiles.
294 * @private
295 */
296 createTiles_: function() {
297 for (var i = 0; i < THUMBNAIL_COUNT; i++) {
298 this.appendTile(new this.ThumbnailClass(this.gridValues_));
299 }
300 },
301
302 /**
303 * Update the tiles after a change to |data_|.
304 */
305 updateTiles_: function() {
306 for (var i = 0; i < THUMBNAIL_COUNT; i++) {
307 var page = this.data_[i];
308 var tile = this.mostVisitedTiles_[i];
309
310 // TODO(pedrosimonetti): what do we do when there's no tile here?
311 if (!tile) {
312 return;
313 }
314
315 if (i >= this.data_.length)
316 tile.reset();
317 else
318 tile.updateForData(page);
319 }
320 },
321
322 /**
323 * Handles the 'card deselected' event (i.e. the user clicked to another
324 * pane).
325 * @param {Event} e The CardChanged event.
326 */
327 handleCardDeselected_: function(e) {
328 if (!document.documentElement.classList.contains('starting-up')) {
329 chrome.send('mostVisitedAction',
330 [ntp.NtpFollowAction.CLICKED_OTHER_NTP_PANE]);
331 }
332 },
333
334 /**
335 * Handles the 'card selected' event (i.e. the user clicked to select the
336 * Most Visited pane).
337 * @param {Event} e The CardChanged event.
338 */
339 handleCardSelected_: function(e) {
340 if (!document.documentElement.classList.contains('starting-up'))
341 chrome.send('mostVisitedSelected');
342 },
343
344 /**
345 * Array of most visited data objects.
346 * @type {Array}
347 */
348 get data() {
349 return this.data_;
350 },
351 set data(data) {
352 var startTime = Date.now();
353
354 // The first time data is set, create the tiles.
355 if (!this.data_) {
356 this.createTiles_();
357 this.data_ = data.slice(0, THUMBNAIL_COUNT);
358 } else {
359 this.data_ = refreshData(this.data_, data);
360 }
361
362 this.updateTiles_();
363 logEvent('mostVisited.layout: ' + (Date.now() - startTime));
364 },
365
366 /** @inheritDoc */
367 shouldAcceptDrag: function(e) {
368 return false;
369 },
370 };
371
372 /**
373 * Executed once the NTP has loaded. Checks if the Most Visited pane is
374 * shown or not. If it is shown, the 'mostVisitedSelected' message is sent
375 * to the C++ code, to record the fact that the user has seen this pane.
376 */
377 // TODO(pedrosimonetti) is it possible to keep this inside Thumbnail class?
378 /*
379 ThumbnailPage.onLoaded = function() {
380 if (ntp.getCardSlider() &&
381 ntp.getCardSlider().currentCardValue &&
382 ntp.getCardSlider().currentCardValue.classList
383 .contains('most-visited-page')) {
384 chrome.send('mostVisitedSelected');
385 }
386 }
387 */
388
389 return {
390 Thumbnail: Thumbnail,
391 ThumbnailPage: ThumbnailPage
392 };
393 });
394
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698