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

Side by Side Diff: chrome/browser/resources/ntp4/page_list_view.js

Issue 9116037: [NTP4] Make TilePage and CardSlider evented to simplify code and fix page switcher bug (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: removing struct/enum/object/etc. of event names 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @fileoverview PageListView implementation. 6 * @fileoverview PageListView implementation.
7 * PageListView manages page list, dot list, switcher buttons and handles apps 7 * PageListView manages page list, dot list, switcher buttons and handles apps
8 * pages callbacks from backend. 8 * pages callbacks from backend.
9 * 9 *
10 * Note that you need to have AppLauncherHandler in your WebUI to use this code. 10 * Note that you need to have AppLauncherHandler in your WebUI to use this code.
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 160
161 this.tilePages = this.pageList.getElementsByClassName('tile-page'); 161 this.tilePages = this.pageList.getElementsByClassName('tile-page');
162 this.appsPages = this.pageList.getElementsByClassName('apps-page'); 162 this.appsPages = this.pageList.getElementsByClassName('apps-page');
163 163
164 // Initialize the cardSlider without any cards at the moment 164 // Initialize the cardSlider without any cards at the moment
165 this.sliderFrame = cardSliderFrame; 165 this.sliderFrame = cardSliderFrame;
166 this.cardSlider = new cr.ui.CardSlider(this.sliderFrame, this.pageList, 166 this.cardSlider = new cr.ui.CardSlider(this.sliderFrame, this.pageList,
167 this.sliderFrame.offsetWidth); 167 this.sliderFrame.offsetWidth);
168 this.cardSlider.initialize(); 168 this.cardSlider.initialize();
169 169
170 // Handle the page being changed 170 // Handle events from the card slider.
171 this.pageList.addEventListener( 171 this.pageList.addEventListener('cardSlider:card_changed',
172 cr.ui.CardSlider.EventType.CARD_CHANGED, 172 this.onCardChanged_.bind(this));
173 this.cardChangedHandler_.bind(this)); 173 this.pageList.addEventListener('cardSlider:card_added',
174 this.onCardAdded_.bind(this));
175 this.pageList.addEventListener('cardSlider:card_removed',
176 this.onCardRemoved_.bind(this));
177
178 // Handle tiles being removed from tile pages.
179 this.pageList.addEventListener('tilePage:tile_removed',
180 this.onTileRemoved_.bind(this));
174 181
175 // Ensure the slider is resized appropriately with the window 182 // Ensure the slider is resized appropriately with the window
176 window.addEventListener('resize', this.onWindowResize_.bind(this)); 183 window.addEventListener('resize', this.onWindowResize_.bind(this));
177 184
178 // Update apps when online state changes. 185 // Update apps when online state changes.
179 window.addEventListener('online', 186 window.addEventListener('online',
180 this.updateOfflineEnabledApps_.bind(this)); 187 this.updateOfflineEnabledApps_.bind(this));
181 window.addEventListener('offline', 188 window.addEventListener('offline',
182 this.updateOfflineEnabledApps_.bind(this)); 189 this.updateOfflineEnabledApps_.bind(this));
183 }, 190 },
184 191
185 /** 192 /**
186 * Appends a tile page. 193 * Appends a tile page.
187 * 194 *
188 * @param {TilePage} page The page element. 195 * @param {TilePage} page The page element.
189 * @param {string} title The title of the tile page. 196 * @param {string} title The title of the tile page.
190 * @param {bool} titleIsEditable If true, the title can be changed. 197 * @param {bool} titleIsEditable If true, the title can be changed.
191 * @param {TilePage} opt_refNode Optional reference node to insert in front 198 * @param {TilePage} opt_refNode Optional reference node to insert in front
192 * of. 199 * of.
193 * When opt_refNode is falsey, |page| will just be appended to the end of 200 * When opt_refNode is falsey, |page| will just be appended to the end of
194 * the page list. 201 * the page list.
195 */ 202 */
196 appendTilePage: function(page, title, titleIsEditable, opt_refNode) { 203 appendTilePage: function(page, title, titleIsEditable, opt_refNode) {
197 // When opt_refNode is falsey, insertBefore acts just like appendChild. 204 if (opt_refNode) {
198 this.pageList.insertBefore(page, opt_refNode); 205 var refIndex = this.getTilePageIndex(opt_refNode);
206 this.cardSlider.insertCardAtIndex(page, refIndex);
207 } else {
208 this.cardSlider.appendCard(page);
209 }
199 210
200 // Remember special MostVisitedPage. 211 // Remember special MostVisitedPage.
201 if (typeof ntp4.MostVisitedPage != 'undefined' && 212 if (typeof ntp4.MostVisitedPage != 'undefined' &&
202 page instanceof ntp4.MostVisitedPage) { 213 page instanceof ntp4.MostVisitedPage) {
203 assert(this.tilePages.length == 1, 214 assert(this.tilePages.length == 1,
204 'MostVisitedPage should be added as first tile page'); 215 'MostVisitedPage should be added as first tile page');
205 this.mostVisitedPage = page; 216 this.mostVisitedPage = page;
206 } 217 }
207 218
208 // If we're appending an AppsPage and it's a temporary page, animate it. 219 // If we're appending an AppsPage and it's a temporary page, animate it.
(...skipping 11 matching lines...) Expand all
220 this.eventTracker.add(page, 'pagelayout', this.onPageLayout_.bind(this)); 231 this.eventTracker.add(page, 'pagelayout', this.onPageLayout_.bind(this));
221 }, 232 },
222 233
223 /** 234 /**
224 * Called by chrome when an existing app has been disabled or 235 * Called by chrome when an existing app has been disabled or
225 * removed/uninstalled from chrome. 236 * removed/uninstalled from chrome.
226 * @param {Object} appData A data structure full of relevant information for 237 * @param {Object} appData A data structure full of relevant information for
227 * the app. 238 * the app.
228 * @param {boolean} isUninstall True if the app is being uninstalled; 239 * @param {boolean} isUninstall True if the app is being uninstalled;
229 * false if the app is being disabled. 240 * false if the app is being disabled.
241 * @param {boolean} fromPage True if the removal was from the current page.
230 */ 242 */
231 appRemoved: function(appData, isUninstall) { 243 appRemoved: function(appData, isUninstall, fromPage) {
232 var app = $(appData.id); 244 var app = $(appData.id);
233 assert(app, 'trying to remove an app that doesn\'t exist'); 245 assert(app, 'trying to remove an app that doesn\'t exist');
234 246
235 if (!isUninstall) 247 if (!isUninstall)
236 app.replaceAppData(appData); 248 app.replaceAppData(appData);
237 else 249 else
238 app.remove(); 250 app.remove(!!fromPage);
239 }, 251 },
240 252
241 /** 253 /**
254 * @return {boolean} If the page is still starting up.
255 * @private
256 */
257 isStartingUp_: function() {
258 return document.documentElement.classList.contains('starting-up');
259 },
260
261 /**
242 * Callback invoked by chrome with the apps available. 262 * Callback invoked by chrome with the apps available.
243 * 263 *
244 * Note that calls to this function can occur at any time, not just in 264 * Note that calls to this function can occur at any time, not just in
245 * response to a getApps request. For example, when a user 265 * response to a getApps request. For example, when a user
246 * installs/uninstalls an app on another synchronized devices. 266 * installs/uninstalls an app on another synchronized devices.
247 * @param {Object} data An object with all the data on available 267 * @param {Object} data An object with all the data on available
248 * applications. 268 * applications.
249 */ 269 */
250 getAppsCallback: function(data) { 270 getAppsCallback: function(data) {
251 var startTime = Date.now(); 271 var startTime = Date.now();
252 272
253 // Clear any existing apps pages and dots. 273 // Clear any existing apps pages and dots.
254 // TODO(rbyers): It might be nice to preserve animation of dots after an 274 // TODO(rbyers): It might be nice to preserve animation of dots after an
255 // uninstall. Could we re-use the existing page and dot elements? It 275 // uninstall. Could we re-use the existing page and dot elements? It
256 // seems unfortunate to have Chrome send us the entire apps list after an 276 // seems unfortunate to have Chrome send us the entire apps list after an
257 // uninstall. 277 // uninstall.
258 while (this.appsPages.length > 0) { 278 while (this.appsPages.length > 0)
259 var page = this.appsPages[0]; 279 this.removeTilePageAndDot_(this.appsPages[0]);
260 var dot = page.navigationDot;
261
262 this.eventTracker.remove(page);
263 page.tearDown();
264 page.parentNode.removeChild(page);
265 dot.parentNode.removeChild(dot);
266 }
267 280
268 // Get the array of apps and add any special synthesized entries 281 // Get the array of apps and add any special synthesized entries
269 var apps = data.apps; 282 var apps = data.apps;
270 283
271 // Get a list of page names 284 // Get a list of page names
272 var pageNames = data.appPageNames; 285 var pageNames = data.appPageNames;
273 286
274 function stringListIsEmpty(list) { 287 function stringListIsEmpty(list) {
275 for (var i = 0; i < list.length; i++) { 288 for (var i = 0; i < list.length; i++) {
276 if (list[i]) 289 if (list[i])
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 } 410 }
398 }, 411 },
399 412
400 /** 413 /**
401 * Called whenever tiles should be re-arranging themselves out of the way 414 * Called whenever tiles should be re-arranging themselves out of the way
402 * of a moving or insert tile. 415 * of a moving or insert tile.
403 */ 416 */
404 enterRearrangeMode: function() { 417 enterRearrangeMode: function() {
405 var tempPage = new ntp4.AppsPage(); 418 var tempPage = new ntp4.AppsPage();
406 tempPage.classList.add('temporary'); 419 tempPage.classList.add('temporary');
407 this.appendTilePage(tempPage, 420 var pageName = localStrings.getString('appDefaultPageName');
408 localStrings.getString('appDefaultPageName'), 421 this.appendTilePage(tempPage, pageName, true);
409 true);
410 var tempIndex = Array.prototype.indexOf.call(this.tilePages, tempPage);
411 if (this.cardSlider.currentCard >= tempIndex)
412 this.cardSlider.currentCard += 1;
413 this.updateSliderCards();
414 422
415 if (ntp4.getCurrentlyDraggingTile().firstChild.canBeRemoved()) 423 if (ntp4.getCurrentlyDraggingTile().firstChild.canBeRemoved())
416 $('footer').classList.add('showing-trash-mode'); 424 $('footer').classList.add('showing-trash-mode');
417 }, 425 },
418 426
419 /** 427 /**
420 * Invoked whenever some app is released 428 * Invoked whenever some app is released
421 */ 429 */
422 leaveRearrangeMode: function() { 430 leaveRearrangeMode: function() {
423 var tempPage = document.querySelector('.tile-page.temporary'); 431 var tempPage = document.querySelector('.tile-page.temporary');
424 var dot = tempPage.navigationDot; 432 var dot = tempPage.navigationDot;
425 if (!tempPage.tileCount && tempPage != this.cardSlider.currentCardValue) { 433 if (!tempPage.tileCount && tempPage != this.cardSlider.currentCardValue) {
426 dot.animateRemove(); 434 this.removeTilePageAndDot_(tempPage, true);
427 var tempIndex = Array.prototype.indexOf.call(this.tilePages, tempPage);
428 if (this.cardSlider.currentCard > tempIndex)
429 this.cardSlider.currentCard -= 1;
430 tempPage.parentNode.removeChild(tempPage);
431 this.updateSliderCards();
432 } else { 435 } else {
433 tempPage.classList.remove('temporary'); 436 tempPage.classList.remove('temporary');
434 this.saveAppPageName(tempPage, 437 this.saveAppPageName(tempPage,
435 localStrings.getString('appDefaultPageName')); 438 localStrings.getString('appDefaultPageName'));
436 } 439 }
437 440
438 $('footer').classList.remove('showing-trash-mode'); 441 $('footer').classList.remove('showing-trash-mode');
439 }, 442 },
440 443
441 /** 444 /**
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
492 * Returns the index of the given apps page. 495 * Returns the index of the given apps page.
493 * @param {AppsPage} page The AppsPage we wish to find. 496 * @param {AppsPage} page The AppsPage we wish to find.
494 * @return {number} The index of |page| or -1 if it is not in the 497 * @return {number} The index of |page| or -1 if it is not in the
495 * collection. 498 * collection.
496 */ 499 */
497 getAppsPageIndex: function(page) { 500 getAppsPageIndex: function(page) {
498 return Array.prototype.indexOf.call(this.appsPages, page); 501 return Array.prototype.indexOf.call(this.appsPages, page);
499 }, 502 },
500 503
501 /** 504 /**
502 * Handler for CARD_CHANGED on cardSlider. 505 * Handler for cardSlider:card_changed events from this.cardSlider.
503 * @param {Event} e The CARD_CHANGED event. 506 * @param {Event} e The cardSlider:card_changed event.
504 * @private 507 * @private
505 */ 508 */
506 cardChangedHandler_: function(e) { 509 onCardChanged_: function(e) {
507 var page = e.cardSlider.currentCardValue; 510 var page = e.cardSlider.currentCardValue;
508 511
509 // Don't change shownPage until startup is done (and page changes actually 512 // Don't change shownPage until startup is done (and page changes actually
510 // reflect user actions). 513 // reflect user actions).
511 if (!document.documentElement.classList.contains('starting-up')) { 514 if (!this.isStartingUp_()) {
512 if (page.classList.contains('apps-page')) { 515 if (page.classList.contains('apps-page')) {
513 this.shownPage = templateData.apps_page_id; 516 this.shownPage = templateData.apps_page_id;
514 this.shownPageIndex = this.getAppsPageIndex(page); 517 this.shownPageIndex = this.getAppsPageIndex(page);
515 } else if (page.classList.contains('most-visited-page')) { 518 } else if (page.classList.contains('most-visited-page')) {
516 this.shownPage = templateData.most_visited_page_id; 519 this.shownPage = templateData.most_visited_page_id;
517 this.shownPageIndex = 0; 520 this.shownPageIndex = 0;
518 } else { 521 } else {
519 console.error('unknown page selected'); 522 console.error('unknown page selected');
520 } 523 }
521 chrome.send('pageSelected', [this.shownPage, this.shownPageIndex]); 524 chrome.send('pageSelected', [this.shownPage, this.shownPageIndex]);
522 } 525 }
523 526
524 // Update the active dot 527 // Update the active dot
525 var curDot = this.dotList.getElementsByClassName('selected')[0]; 528 var curDot = this.dotList.getElementsByClassName('selected')[0];
526 if (curDot) 529 if (curDot)
527 curDot.classList.remove('selected'); 530 curDot.classList.remove('selected');
528 page.navigationDot.classList.add('selected'); 531 page.navigationDot.classList.add('selected');
529 this.updatePageSwitchers(); 532 this.updatePageSwitchers();
530 }, 533 },
531 534
532 /* 535 /**
533 * Save the name of an app page. 536 * Listen for card additions to update the page switchers or the current
534 * Store the app page name into the preferences store. 537 * card accordingly.
535 * @param {AppsPage} appPage The app page for which we wish to save. 538 * @param {Event} e A card removed or added event.
539 */
540 onCardAdded_: function(e) {
541 // When the second arg passed to insertBefore is falsey, it acts just like
542 // appendChild.
543 this.pageList.insertBefore(e.addedCard, this.tilePages[e.addedIndex]);
544 if (!this.isStartingUp_())
545 this.updatePageSwitchers();
546 },
547
548 /**
549 * Listen for card removals to update the page switchers or the current card
550 * accordingly.
551 * @param {Event} e A card removed or added event.
552 */
553 onCardRemoved_: function(e) {
554 e.removedCard.parentNode.removeChild(e.removedCard);
555 if (!this.isStartingUp_())
556 this.updatePageSwitchers();
557 },
558
559 /**
560 * Save the name of an apps page.
561 * Store the apps page name into the preferences store.
562 * @param {AppsPage} appsPage The app page for which we wish to save.
536 * @param {string} name The name of the page. 563 * @param {string} name The name of the page.
537 */ 564 */
538 saveAppPageName: function(appPage, name) { 565 saveAppPageName: function(appPage, name) {
539 var index = this.getAppsPageIndex(appPage); 566 var index = this.getAppsPageIndex(appPage);
540 assert(index != -1); 567 assert(index != -1);
541 chrome.send('saveAppPageName', [name, index]); 568 chrome.send('saveAppPageName', [name, index]);
542 }, 569 },
543 570
544 /** 571 /**
545 * Window resize handler. 572 * Window resize handler.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 direction = 1; 609 direction = 1;
583 else 610 else
584 return; 611 return;
585 612
586 var cardIndex = 613 var cardIndex =
587 (this.cardSlider.currentCard + direction + 614 (this.cardSlider.currentCard + direction +
588 this.cardSlider.cardCount) % this.cardSlider.cardCount; 615 this.cardSlider.cardCount) % this.cardSlider.cardCount;
589 this.cardSlider.selectCard(cardIndex, true); 616 this.cardSlider.selectCard(cardIndex, true);
590 617
591 e.stopPropagation(); 618 e.stopPropagation();
592 } 619 },
620
621 /**
622 * Happens when a tile is removed from a tile page.
Evan Stade 2012/01/18 00:19:51 at first glance this looks like a tile is being re
Dan Beam 2012/01/18 01:20:08 Done. (It's both. I didn't make an explicit even
623 * @param {Event} e An event dispatched from a tile when it is removed.
624 */
625 onTileRemoved_: function(e) {
626 // TODO(dbeam): Remove empty apps pages.
627 this.updateSliderCards();
628 },
629
630 /**
631 * Returns the index of a given tile page.
632 * @param {TilePage} page The TilePage we wish to find.
633 * @return {number} The index of |page| or -1 if it is not in the
634 * collection.
635 */
636 getTilePageIndex: function(page) {
637 return Array.prototype.indexOf.call(this.tilePages, page);
638 },
639
640 /**
641 * Removes a page and navigation dot (if the navdot exists).
642 * @param {TilePage} page The page to be removed.
643 * @param {boolean=} opt_animate If the removal should be animated.
644 */
645 removeTilePageAndDot_: function(page, opt_animate) {
646 if (page.navigationDot)
647 page.navigationDot.remove(opt_animate);
648 this.cardSlider.removeCard(page);
649 },
593 }; 650 };
594 651
595 return { 652 return {
596 PageListView: PageListView 653 PageListView: PageListView
597 }; 654 };
598 }); 655 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698