| Index: chrome/browser/resources/ntp4/page_list_view.js
|
| diff --git a/chrome/browser/resources/ntp4/page_list_view.js b/chrome/browser/resources/ntp4/page_list_view.js
|
| index f6da56bd1f1ac8747143513b259219f72dc04fe6..c36ff8b83ab0b50d273d806258b03c93795574ee 100644
|
| --- a/chrome/browser/resources/ntp4/page_list_view.js
|
| +++ b/chrome/browser/resources/ntp4/page_list_view.js
|
| @@ -172,6 +172,26 @@ cr.define('ntp4', function() {
|
| cr.ui.CardSlider.EventType.CARD_CHANGED,
|
| this.cardChangedHandler_.bind(this));
|
|
|
| + // Handle the end of cards being changed (useful if animated).
|
| + this.pageList.addEventListener(
|
| + cr.ui.CardSlider.EventType.CARD_CHANGE_ENDED,
|
| + this.cardChangeEndedHandler_.bind(this));
|
| +
|
| + // Handle cards being added to the card slider.
|
| + this.pageList.addEventListener(
|
| + cr.ui.CardSlider.EventType.CARD_ADDED,
|
| + this.cardAddedHandler_.bind(this));
|
| +
|
| + // Handle cards being removed from the card slider.
|
| + this.pageList.addEventListener(
|
| + cr.ui.CardSlider.EventType.CARD_REMOVED,
|
| + this.cardRemovedHandler_.bind(this));
|
| +
|
| + // Handle tiles being removed from tile pages.
|
| + this.pageList.addEventListener(
|
| + ntp4.TilePage.EventType.TILE_REMOVED,
|
| + this.tileRemovedHandler_.bind(this));
|
| +
|
| // Ensure the slider is resized appropriately with the window
|
| window.addEventListener('resize', this.onWindowResize_.bind(this));
|
|
|
| @@ -194,8 +214,12 @@ cr.define('ntp4', function() {
|
| * the page list.
|
| */
|
| appendTilePage: function(page, title, titleIsEditable, opt_refNode) {
|
| - // When opt_refNode is falsey, insertBefore acts just like appendChild.
|
| - this.pageList.insertBefore(page, opt_refNode);
|
| + if (opt_refNode) {
|
| + var refIndex = this.getTilePageIndex(opt_refNode);
|
| + this.cardSlider.insertCardAtIndex(page, refIndex);
|
| + } else {
|
| + this.cardSlider.appendCard(page);
|
| + }
|
|
|
| // Remember special MostVisitedPage.
|
| if (typeof ntp4.MostVisitedPage != 'undefined' &&
|
| @@ -227,15 +251,101 @@ cr.define('ntp4', function() {
|
| * the app.
|
| * @param {boolean} isUninstall True if the app is being uninstalled;
|
| * false if the app is being disabled.
|
| + * @param {boolean} fromPage If the removal was from the current page.
|
| */
|
| - appRemoved: function(appData, isUninstall) {
|
| + appRemoved: function(appData, isUninstall, fromPage) {
|
| var app = $(appData.id);
|
| assert(app, 'trying to remove an app that doesn\'t exist');
|
|
|
| - if (!isUninstall)
|
| + if (!isUninstall) {
|
| app.replaceAppData(appData);
|
| - else
|
| - app.remove();
|
| + } else {
|
| + // If the uninstall was from this page, run the blipout animation and
|
| + // the tile will be removed in TilePage#onContentsAnimationEnd_.
|
| + // Otherwise delete the tile without auto-deleting the page to avoid
|
| + // re-deleting the same page (or the page that slid in to take its
|
| + // place).
|
| + if (fromPage) {
|
| + // Unset the ID immediately, because the app is already gone. But
|
| + // leave the tile on the page as it animates out.
|
| + app.id = '';
|
| + app.classList.add('removing-tile-contents');
|
| + } else {
|
| + var tilePage = app.tile.tilePage;
|
| + tilePage.removeTile(app.tile, false, true);
|
| + this.removeAppsPageIfEmpty_(tilePage, false, true);
|
| + }
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * @return {boolean} If the page is still starting up.
|
| + * @private
|
| + */
|
| + isStartingUp_: function() {
|
| + return document.documentElement.classList.contains('starting-up');
|
| + },
|
| +
|
| + /**
|
| + * Returns a hashmap of apps pages keyed by page ordinal.
|
| + * @return {Object.<string, AppsPage>} Map of apps pages.
|
| + * @private
|
| + */
|
| + getAppsPageOrdinalMap_: function() {
|
| + var map = {};
|
| + for (var i = 0; i < this.appsPages.length; ++i)
|
| + map[this.appsPages[i].ordinal] = this.appsPages[i];
|
| + return map;
|
| + },
|
| +
|
| + /**
|
| + * Get an unsorted list of apps page ordinals.
|
| + */
|
| + getAppsPageOrdinals_: function() {
|
| + return Array.prototype.map.call(this.appsPages, function(page) {
|
| + return page.ordinal;
|
| + });
|
| + },
|
| +
|
| + /**
|
| + * Gets an apps page by string ordinal.
|
| + * @param {string} ordinal The page ordinal we're searching for.
|
| + * @return {?AppsPage} The apps page with corresponding ordinal or null.
|
| + * @private
|
| + */
|
| + getAppsPageByOrdinal_: function(ordinal) {
|
| + assert(typeof ordinal == 'string' && ordinal);
|
| + return this.getAppsPageOrdinalMap_()[ordinal] || null;
|
| + },
|
| +
|
| + /**
|
| + * Find an apps page index via ordinal.
|
| + * @return {number} The index of the ordinal or -1 if it doesn't exist.
|
| + */
|
| + getPageIndexFromOrdinal_: function(ordinal) {
|
| + return this.getAppsPageOrdinals_().indexOf(ordinal);
|
| + },
|
| +
|
| + /**
|
| + * Finds a position for a specific ordinal in an ordinal map.
|
| + * @param {Array} ordinalList An array of ordinals.
|
| + * @param {string} ordinal A specific ordinal to search for.
|
| + * @return {number} The position where the ordinal should be positioned.
|
| + */
|
| + getPositionForNewOrdinal_: function(ordinalList, ordinal) {
|
| + assert(Array.isArray(ordinal) && ordinalList.indexOf(ordinal) == -1);
|
| + var sorted = Array.prototype.concat.call(ordinalList).sort();
|
| + function split(num) {
|
| + return Math.floor(num << 1);
|
| + }
|
| + var size = split(sorted.length);
|
| + var pos = size;
|
| + while (size > 0) {
|
| + size = split(size);
|
| + // This just no-ops when size = 0.
|
| + pos = ordinal > sorted[pos] ? pos + size : pos - size;
|
| + }
|
| + return pos;
|
| },
|
|
|
| /**
|
| @@ -247,132 +357,74 @@ cr.define('ntp4', function() {
|
| * @param {Object} data An object with all the data on available
|
| * applications.
|
| */
|
| - getAppsCallback: function(data) {
|
| - var startTime = Date.now();
|
| -
|
| - // Clear any existing apps pages and dots.
|
| - // TODO(rbyers): It might be nice to preserve animation of dots after an
|
| - // uninstall. Could we re-use the existing page and dot elements? It
|
| - // seems unfortunate to have Chrome send us the entire apps list after an
|
| - // uninstall.
|
| - while (this.appsPages.length > 0) {
|
| - var page = this.appsPages[0];
|
| - var dot = page.navigationDot;
|
| -
|
| - this.eventTracker.remove(page);
|
| - page.tearDown();
|
| - page.parentNode.removeChild(page);
|
| - dot.parentNode.removeChild(dot);
|
| - }
|
| -
|
| - // Get the array of apps and add any special synthesized entries
|
| - var apps = data.apps;
|
| -
|
| - // Get a list of page names
|
| - var pageNames = data.appPageNames;
|
| -
|
| - function stringListIsEmpty(list) {
|
| - for (var i = 0; i < list.length; i++) {
|
| - if (list[i])
|
| - return false;
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - // Sort by launch ordinal
|
| - apps.sort(function(a, b) {
|
| - return a.app_launch_ordinal > b.app_launch_ordinal ? 1 :
|
| - a.app_launch_ordinal < b.app_launch_ordinal ? -1 : 0;
|
| - });
|
| -
|
| - // An app to animate (in case it was just installed).
|
| - var highlightApp;
|
| -
|
| - // Add the apps, creating pages as necessary
|
| - for (var i = 0; i < apps.length; i++) {
|
| - var app = apps[i];
|
| - var pageIndex = app.page_index || 0;
|
| - while (pageIndex >= this.appsPages.length) {
|
| - var pageName = localStrings.getString('appDefaultPageName');
|
| - if (this.appsPages.length < pageNames.length)
|
| - pageName = pageNames[this.appsPages.length];
|
| -
|
| - var origPageCount = this.appsPages.length;
|
| - this.appendTilePage(new ntp4.AppsPage(), pageName, true);
|
| - // Confirm that appsPages is a live object, updated when a new page is
|
| - // added (otherwise we'd have an infinite loop)
|
| - assert(this.appsPages.length == origPageCount + 1,
|
| - 'expected new page');
|
| - }
|
| -
|
| - if (app.id == this.highlightAppId)
|
| - highlightApp = app;
|
| - else
|
| - this.appsPages[pageIndex].appendApp(app);
|
| - }
|
| + getAppsCallback: function(data, measureTime) {
|
| + var startTime;
|
| + if (measureTime)
|
| + startTime = Date.now();
|
|
|
| + this.syncAppsPages(data);
|
| ntp4.AppsPage.setPromo(data.showPromo ? data : null);
|
|
|
| - // Tell the slider about the pages.
|
| + // Tell the slider/switchers about the pages.
|
| this.updateSliderCards();
|
| + this.updatePageSwitchers();
|
|
|
| if (highlightApp)
|
| this.appAdded(highlightApp, true);
|
|
|
| // Mark the current page.
|
| this.cardSlider.currentCardValue.navigationDot.classList.add('selected');
|
| - logEvent('apps.layout: ' + (Date.now() - startTime));
|
| +
|
| + if (measureTime)
|
| + logEvent('apps.layout: ' + (Date.now() - startTime));
|
|
|
| document.documentElement.classList.remove('starting-up');
|
| },
|
|
|
| /**
|
| - * Called by chrome when a new app has been added to chrome or has been
|
| - * enabled if previously disabled.
|
| - * @param {Object} appData A data structure full of relevant information for
|
| - * the app.
|
| + * @param {Object<>}
|
| */
|
| - appAdded: function(appData, opt_highlight) {
|
| - if (appData.id == this.highlightAppId) {
|
| - opt_highlight = true;
|
| - this.highlightAppId = null;
|
| - }
|
| -
|
| - var pageIndex = appData.page_index || 0;
|
| -
|
| - if (pageIndex >= this.appsPages.length) {
|
| - while (pageIndex >= this.appsPages.length) {
|
| - this.appendTilePage(new ntp4.AppsPage(),
|
| - localStrings.getString('appDefaultPageName'),
|
| - true);
|
| + syncAppsPages: function() {
|
| + // Remove pages that aren't in the data we were given.
|
| + var existingPages = this.getAppsPageOrdinalMap_();
|
| + for (var i in existingPages) {
|
| + if (existingPages.hasOwnProperty(i) &&
|
| + !(existingPages[i] in data.appsPages)) {
|
| + this.removeTilePageAndDot_(existingPages[i]);
|
| + delete existingPages[i];
|
| }
|
| - this.updateSliderCards();
|
| - }
|
| -
|
| - var page = this.appsPages[pageIndex];
|
| - var app = $(appData.id);
|
| - if (app)
|
| - app.replaceAppData(appData);
|
| - else
|
| - page.appendApp(appData, opt_highlight);
|
| - },
|
| -
|
| - /**
|
| - * Callback invoked by chrome whenever an app preference changes.
|
| - * @param {Object} data An object with all the data on available
|
| - * applications.
|
| - */
|
| - appsPrefChangedCallback: function(data) {
|
| - for (var i = 0; i < data.apps.length; ++i) {
|
| - $(data.apps[i].id).appData = data.apps[i];
|
| }
|
| -
|
| - // Set the App dot names. Skip the first dot (Most Visited).
|
| - var dots = this.dotList.getElementsByClassName('dot');
|
| - var start = this.mostVisitedPage ? 1 : 0;
|
| - for (var i = start; i < dots.length; ++i) {
|
| - dots[i].displayTitle = data.appPageNames[i - start] || '';
|
| + // Create or re-use pages or apps and ensure we're synced.
|
| + var pageOrdinals = Object.keys(data.appsPages).sort();
|
| + for (var i = 0; i < pageOrdinals.length; ++i) {
|
| + // Re-use previous pages or create new pages as necessary.
|
| + var appsPage = this.getOrCreateAppsPageAtOrdinal_(pageOrdinals[i]);
|
| + existingPages[pageOrdinals[i]] = appsPage;
|
| + var page = data.appsPages[pageOrdinals[i]];
|
| + appsPage.navigationDot.displayTitle = page.name;
|
| + var appOrdinals = Object.keys(page.apps).sort();
|
| + for (var j = 0; j < appOrdinals.length; ++j) {
|
| + var appData = page.apps[appOrdinals[j]];
|
| + var app = $(appData.id);
|
| + if (app) {
|
| + if (appData.page_ordinal != app.data.page_ordinal ||
|
| + appData.app_launch_ordinal != app.data.app_launch_ordinal) {
|
| + var originalPage = app.tile.tilePage;
|
| + var detached = originalPage.removeTile(app);
|
| + var index = this.getIndexForNewOrdinal_(
|
| + appOrdinals, appData.app_launch_ordinal);
|
| + existingPages[appData.page_ordinal].addTileAt(detached, index);
|
| + } else {
|
| + app.replaceAppData(appData);
|
| + }
|
| + } else {
|
| + var index = this.getIndexForNewOrdinal_(app.app_launch_ordinal);
|
| + appsPage.addTileAt(app, app.id == data.highlightId);
|
| + }
|
| + }
|
| }
|
| + for (var i = 0; i < this.appsPages.length; ++i)
|
| + this.appsPages[i].cleanupDrag();
|
| },
|
|
|
| /**
|
| @@ -380,21 +432,30 @@ cr.define('ntp4', function() {
|
| * the Slider knows about the new elements.
|
| */
|
| updateSliderCards: function() {
|
| - var pageNo = Math.min(this.cardSlider.currentCard,
|
| - this.tilePages.length - 1);
|
| - this.cardSlider.setCards(Array.prototype.slice.call(this.tilePages),
|
| - pageNo);
|
| + var index = -1;
|
| + var tiles = Array.prototype.slice.call(this.tilePages);
|
| + // Clamping this value each time helps self-heal unexpected input.
|
| + this.shownPageIndex = Math.max(0, Math.min(this.shownPageIndex,
|
| + this.appsPages.length - 1));
|
| switch (this.shownPage) {
|
| - case templateData['apps_page_id']:
|
| - this.cardSlider.selectCardByValue(
|
| - this.appsPages[Math.min(this.shownPageIndex,
|
| - this.appsPages.length - 1)]);
|
| + case templateData.apps_page_id:
|
| + index = tiles.indexOf(this.appsPages[this.shownPageIndex]);
|
| break;
|
| - case templateData['most_visited_page_id']:
|
| - if (this.mostVisitedPage)
|
| - this.cardSlider.selectCardByValue(this.mostVisitedPage);
|
| + case templateData.most_visited_page_id:
|
| + index = tiles.indexOf(this.mostVisitedPage);
|
| break;
|
| }
|
| + // If shownPage was saved as a page that's now disabled or the shownPage
|
| + // doesn't exist any more, index will be -1. Change to the preferred
|
| + // default page (first apps pane) in this case.
|
| + if (index < 0) {
|
| + this.shownPage = templateData.apps_page_id;
|
| + index = tiles.indexOf(this.appsPages[0]);
|
| + }
|
| + // Set the new cards and index.
|
| + this.cardSlider.setCards(tiles, index);
|
| +
|
| + chrome.send('pageSelected', [this.shownPage, this.shownPageIndex]);
|
| },
|
|
|
| /**
|
| @@ -404,13 +465,8 @@ cr.define('ntp4', function() {
|
| enterRearrangeMode: function() {
|
| var tempPage = new ntp4.AppsPage();
|
| tempPage.classList.add('temporary');
|
| - this.appendTilePage(tempPage,
|
| - localStrings.getString('appDefaultPageName'),
|
| - true);
|
| - var tempIndex = Array.prototype.indexOf.call(this.tilePages, tempPage);
|
| - if (this.cardSlider.currentCard >= tempIndex)
|
| - this.cardSlider.currentCard += 1;
|
| - this.updateSliderCards();
|
| + var pageName = localStrings.getString('appDefaultPageName');
|
| + this.appendTilePage(tempPage, pageName, true);
|
|
|
| if (ntp4.getCurrentlyDraggingTile().firstChild.canBeRemoved())
|
| $('footer').classList.add('showing-trash-mode');
|
| @@ -421,18 +477,14 @@ cr.define('ntp4', function() {
|
| */
|
| leaveRearrangeMode: function() {
|
| var tempPage = document.querySelector('.tile-page.temporary');
|
| - var dot = tempPage.navigationDot;
|
| - if (!tempPage.tileCount && tempPage != this.cardSlider.currentCardValue) {
|
| - dot.animateRemove();
|
| - var tempIndex = Array.prototype.indexOf.call(this.tilePages, tempPage);
|
| - if (this.cardSlider.currentCard > tempIndex)
|
| - this.cardSlider.currentCard -= 1;
|
| - tempPage.parentNode.removeChild(tempPage);
|
| - this.updateSliderCards();
|
| - } else {
|
| + // Either remove a temp page if it's empty or save the page name (as an
|
| + // app has just been dropped on it or created somehow).
|
| + // TODO(dbeam): Animated removal if currently on temp page.
|
| + if (tempPage && !this.removeAppsPageIfEmpty_(tempPage, true, true)) {
|
| + this.saveAppsPageName(tempPage,
|
| + tempPage.navigationDot.displayTitle,
|
| + true);
|
| tempPage.classList.remove('temporary');
|
| - this.saveAppPageName(tempPage,
|
| - localStrings.getString('appDefaultPageName'));
|
| }
|
|
|
| $('footer').classList.remove('showing-trash-mode');
|
| @@ -507,7 +559,7 @@ cr.define('ntp4', function() {
|
|
|
| // Don't change shownPage until startup is done (and page changes actually
|
| // reflect user actions).
|
| - if (!document.documentElement.classList.contains('starting-up')) {
|
| + if (!this.isStartingUp_()) {
|
| if (page.classList.contains('apps-page')) {
|
| this.shownPage = templateData['apps_page_id'];
|
| this.shownPageIndex = this.getAppsPageIndex(page);
|
| @@ -528,16 +580,129 @@ cr.define('ntp4', function() {
|
| this.updatePageSwitchers();
|
| },
|
|
|
| - /*
|
| - * Save the name of an app page.
|
| - * Store the app page name into the preferences store.
|
| - * @param {AppsPage} appPage The app page for which we wish to save.
|
| + /**
|
| + * Listen for card additions to update the page switchers or the current
|
| + * card accordingly.
|
| + * @param {Event} e A card removed or added event.
|
| + */
|
| + cardAddedHandler_: function(e) {
|
| + // When the second arg passed to insertBefore is falsey, it acts just like
|
| + // appendChild.
|
| + this.pageList.insertBefore(e.addedCard, this.tilePages[e.addedIndex]);
|
| + if (!this.isStartingUp_())
|
| + this.updatePageSwitchers();
|
| + },
|
| +
|
| + /**
|
| + * Listen for card removals to update the page switchers or the current card
|
| + * accordingly.
|
| + * @param {Event} e A card removed or added event.
|
| + */
|
| + cardRemovedHandler_: function(e) {
|
| + if (!this.isStartingUp_())
|
| + this.updatePageSwitchers();
|
| + assert(!e.removedCard.classList.contains('selected-card'));
|
| + e.removedCard.parentNode.removeChild(e.removedCard);
|
| + },
|
| +
|
| + /**
|
| + * Save the name of an apps page.
|
| + * Store the apps page name into the preferences store.
|
| + * @param {AppsPage} appsPage The app page for which we wish to save.
|
| * @param {string} name The name of the page.
|
| + * @param {boolean} notify If we should notify of when saving the pref.
|
| */
|
| - saveAppPageName: function(appPage, name) {
|
| - var index = this.getAppsPageIndex(appPage);
|
| + saveAppsPageName: function(appsPage, name, notify) {
|
| + var index = this.getAppsPageIndex(appsPage);
|
| assert(index != -1);
|
| - chrome.send('saveAppPageName', [name, index]);
|
| + chrome.send('saveAppsPageName', [name, index, notify]);
|
| + },
|
| +
|
| + /**
|
| + * An Array of callbacks to be called on the next CARD_CHANGE_ENDED event
|
| + * handled from the cardSlider.
|
| + * @private
|
| + */
|
| + cardChangeEndedCallbacks_: [],
|
| +
|
| + /**
|
| + * Handler for CARD_CHANGE_ENDED on cardSlider.
|
| + * @param {Event} e The CARD_CHANGE_ENDED event.
|
| + * @private
|
| + */
|
| + cardChangeEndedHandler_: function(e) {
|
| + if (!this.isStartingUp_()) {
|
| + for (var i = 0; i < this.cardChangeEndedCallbacks_.length; ++i) {
|
| + if (this.cardChangeEndedCallbacks_[i].call(this, e) !== false)
|
| + this.cardChangeEndedCallbacks_.splice(i--, 1);
|
| + }
|
| + }
|
| + },
|
| +
|
| + /**
|
| + * Happens when a tile is removed from a tile page.
|
| + * @param {Event} e An event dispatched from a tile when it is removed.
|
| + */
|
| + tileRemovedHandler_: function(e) {
|
| + if (e.tilePage instanceof ntp4.AppsPage)
|
| + this.removeAppsPageIfEmpty_(e.tilePage, e.wasAnimated);
|
| + },
|
| +
|
| + /**
|
| + * Remove an apps page if it now has no tiles (is empty).
|
| + * @param {AppsPage} appsPage A page to check for emptiness.
|
| + * @param {boolean=} opt_animate Whether the prospective removal should be
|
| + * animated.
|
| + * @param {boolean=} opt_dontNotify Whether this NTP's AppLauncherHandler
|
| + * shouldn't be notified of this pages' prospective removal (default is
|
| + * to notify).
|
| + * @return {boolean} If |appsPage| was removed or not.
|
| + */
|
| + removeAppsPageIfEmpty_: function(appsPage, opt_animate, opt_dontNotify) {
|
| + assert(appsPage instanceof ntp4.AppsPage,
|
| + '|appsPage| is not really an AppsPage');
|
| +
|
| + if (appsPage.tileCount !== 0)
|
| + return false;
|
| +
|
| + // If the user is currently on the empty apps page, avoid visual issues
|
| + // by selecting a different page before deleting. If the user isn't on
|
| + // the empty/deleting page, just delete it right away.
|
| + var whenOnCorrectPage = function() {
|
| + if (!opt_dontNotify)
|
| + chrome.send('deleteEmptyAppsPage', [appsPage.ordinal]);
|
| + this.removeTilePageAndDot_(appsPage, opt_animate);
|
| + };
|
| +
|
| + if (appsPage == this.cardSlider.currentCardValue) {
|
| + var index = this.getAppsPageIndex(appsPage);
|
| + assert(index != -1);
|
| + var tempPage = document.querySelector('.apps-page.temporary');
|
| + var tempOffset = tempPage.tileCount == 0 ? 1 : 0;
|
| + // If the apps page being deleted is the last apps page (excluding soon
|
| + // to be deleted temp pages), move backward one in the card slider.
|
| + // Otherwise, move forward one.
|
| + var change = index == this.appsPages.length - 1 - tempOffset ? -1 : 1;
|
| + var newIndex = this.cardSlider.currentCard + change;
|
| + this.cardSlider.selectCard(newIndex, opt_animate);
|
| + // In the case where |opt_animate| is truthy, the card selection is
|
| + // animated and asynchronous, so we simply append this callback to
|
| + // this.cardChangeEndedCallbacks_ to be done on the next animated
|
| + // CARD_CHANGE_ENDED event that switches to the proposed index.
|
| + if (opt_animate) {
|
| + this.cardChangeEndedCallbacks_.push(function(e) {
|
| + if (!e.wasAnimated || e.changedTo != newIndex)
|
| + return false;
|
| + whenOnCorrectPage.call(this);
|
| + });
|
| + } else {
|
| + whenOnCorrectPage.call(this);
|
| + }
|
| + } else {
|
| + whenOnCorrectPage.call(this);
|
| + }
|
| +
|
| + return true;
|
| },
|
|
|
| /**
|
| @@ -588,7 +753,65 @@ cr.define('ntp4', function() {
|
| this.cardSlider.selectCard(cardIndex, true);
|
|
|
| e.stopPropagation();
|
| - }
|
| + },
|
| +
|
| + /**
|
| + * Re-order apps on this inactive page when an active NTP gets re-ordered.
|
| + * @param {Object} data Position hashmap ordered by app id with indices:
|
| + * {id => {page_index: ##, app_launch_index: ##}}
|
| + */
|
| + appsReordered: function(data) {
|
| + },
|
| +
|
| + /**
|
| + * Ensure there is an apps page at the given |ordinal| by checking for an
|
| + * existing page or creating a new once.
|
| + * @param {string} ordinal A string ordinal for which to check.
|
| + * @private
|
| + */
|
| + getOrCreateAppsPageAtOrdinal_: function(ordinal) {
|
| + var map = this.getAppsPageOrdinalMap_();
|
| + if (ordinal in map)
|
| + return map[ordinal];
|
| +
|
| + var appsPage = new ntp4.AppsPage(ordinal);
|
| +
|
| + var index = this.getIndexForNewOrdinal_(Object.keys(map));
|
| + assert(index >= 0 && index <= this.appsPage.length);
|
| +
|
| + var origPageCount = this.appsPages.length;
|
| + this.appendTilePage(appsPage,
|
| + localStrings.getString('appDefaultPageName'),
|
| + true,
|
| + this.appsPages[index]);
|
| + // Confirm that appsPages is a live object, updated when a new page is
|
| + // added (otherwise we'd have an infinite loop)
|
| + assert(this.appsPages.length == origPageCount + 1,
|
| + 'expected new page');
|
| +
|
| + return appsPage;
|
| + },
|
| +
|
| + /**
|
| + * Returns the index of a given tile page.
|
| + * @param {TilePage} page The TilePage we wish to find.
|
| + * @return {number} The index of |page| or -1 if it is not in the
|
| + * collection.
|
| + */
|
| + getTilePageIndex: function(page) {
|
| + return Array.prototype.indexOf.call(this.tilePages, page);
|
| + },
|
| +
|
| + /**
|
| + * Removes a page and navigation dot (if the navdot exists).
|
| + * @param {TilePage} page The page to be removed.
|
| + * @param {boolean=} opt_animate If the removal should be animated.
|
| + */
|
| + removeTilePageAndDot_: function(page, opt_animate) {
|
| + if (page.navigationDot)
|
| + page.navigationDot.remove(opt_animate);
|
| + this.cardSlider.removeCard(page);
|
| + },
|
| };
|
|
|
| return {
|
|
|