Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 17 matching lines...) Expand all Loading... | |
| 28 } | 28 } |
| 29 | 29 |
| 30 PageListView.prototype = { | 30 PageListView.prototype = { |
| 31 /** | 31 /** |
| 32 * The CardSlider object to use for changing app pages. | 32 * The CardSlider object to use for changing app pages. |
| 33 * @type {CardSlider|undefined} | 33 * @type {CardSlider|undefined} |
| 34 */ | 34 */ |
| 35 cardSlider: undefined, | 35 cardSlider: undefined, |
| 36 | 36 |
| 37 /** | 37 /** |
| 38 * The frame div for cardSlider. | 38 * The frame div for this.cardSlider. |
| 39 * @type {!Element|undefined} | 39 * @type {!Element|undefined} |
| 40 */ | 40 */ |
| 41 sliderFrame: undefined, | 41 sliderFrame: undefined, |
| 42 | 42 |
| 43 /** | 43 /** |
| 44 * The 'page-list' element. | 44 * The 'page-list' element. |
| 45 * @type {!Element|undefined} | 45 * @type {!Element|undefined} |
| 46 */ | 46 */ |
| 47 pageList: undefined, | 47 pageList: undefined, |
| 48 | 48 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 137 new ntp4.Trash(this.trash); | 137 new ntp4.Trash(this.trash); |
| 138 | 138 |
| 139 this.pageSwitcherStart = opt_pageSwitcherStart; | 139 this.pageSwitcherStart = opt_pageSwitcherStart; |
| 140 if (this.pageSwitcherStart) | 140 if (this.pageSwitcherStart) |
| 141 ntp4.initializePageSwitcher(this.pageSwitcherStart); | 141 ntp4.initializePageSwitcher(this.pageSwitcherStart); |
| 142 | 142 |
| 143 this.pageSwitcherEnd = opt_pageSwitcherEnd; | 143 this.pageSwitcherEnd = opt_pageSwitcherEnd; |
| 144 if (this.pageSwitcherEnd) | 144 if (this.pageSwitcherEnd) |
| 145 ntp4.initializePageSwitcher(this.pageSwitcherEnd); | 145 ntp4.initializePageSwitcher(this.pageSwitcherEnd); |
| 146 | 146 |
| 147 this.shownPage = templateData['shown_page_type']; | 147 this.shownPage = templateData.shown_page_type; |
| 148 this.shownPageIndex = templateData['shown_page_index']; | 148 this.shownPageIndex = templateData.shown_page_index; |
| 149 | 149 |
| 150 // Request data on the apps so we can fill them in. | 150 // Request data on the apps so we can fill them in. |
| 151 // Note that this is kicked off asynchronously. 'getAppsCallback' will be | 151 // Note that this is kicked off asynchronously. 'getAppsCallback' will be |
| 152 // invoked at some point after this function returns. | 152 // invoked at some point after this function returns. |
| 153 chrome.send('getApps'); | 153 chrome.send('getApps'); |
| 154 | 154 |
| 155 document.addEventListener('keydown', this.onDocKeyDown_.bind(this)); | 155 document.addEventListener('keydown', this.onDocKeyDown_.bind(this)); |
| 156 // Prevent touch events from triggering any sort of native scrolling | 156 // Prevent touch events from triggering any sort of native scrolling |
| 157 document.addEventListener('touchmove', function(e) { | 157 document.addEventListener('touchmove', function(e) { |
| 158 e.preventDefault(); | 158 e.preventDefault(); |
| 159 }, true); | 159 }, true); |
| 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 the page being changed |
| 171 this.pageList.addEventListener( | 171 this.pageList.addEventListener( |
| 172 cr.ui.CardSlider.EventType.CARD_CHANGED, | 172 cr.ui.CardSlider.EventType.CARD_CHANGED, |
| 173 this.cardChangedHandler_.bind(this)); | 173 this.cardChangedHandler_.bind(this)); |
| 174 | 174 |
| 175 // Handle the end of cards being changed (useful if animated). | |
| 176 this.pageList.addEventListener( | |
| 177 cr.ui.CardSlider.EventType.CARD_CHANGE_ENDED, | |
| 178 this.cardChangeEndedHandler_.bind(this)); | |
| 179 | |
| 180 // Handle tiles being removed from tile pages. | |
| 181 this.pageList.addEventListener( | |
| 182 ntp4.TilePage.EventType.TILE_REMOVED, | |
| 183 this.tileRemovedHandler_.bind(this)); | |
| 184 | |
| 175 // Ensure the slider is resized appropriately with the window | 185 // Ensure the slider is resized appropriately with the window |
| 176 window.addEventListener('resize', this.onWindowResize_.bind(this)); | 186 window.addEventListener('resize', this.onWindowResize_.bind(this)); |
| 177 | 187 |
| 178 // Update apps when online state changes. | 188 // Update apps when online state changes. |
| 179 window.addEventListener('online', | 189 window.addEventListener('online', |
| 180 this.updateOfflineEnabledApps_.bind(this)); | 190 this.updateOfflineEnabledApps_.bind(this)); |
| 181 window.addEventListener('offline', | 191 window.addEventListener('offline', |
| 182 this.updateOfflineEnabledApps_.bind(this)); | 192 this.updateOfflineEnabledApps_.bind(this)); |
| 183 }, | 193 }, |
| 184 | 194 |
| 185 /** | 195 /** |
| 186 * Appends a tile page. | 196 * Appends a tile page. |
| 187 * | 197 * |
| 188 * @param {TilePage} page The page element. | 198 * @param {TilePage} page The page element. |
| 189 * @param {string} title The title of the tile page. | 199 * @param {string} title The title of the tile page. |
| 190 * @param {bool} titleIsEditable If true, the title can be changed. | 200 * @param {bool} titleIsEditable If true, the title can be changed. |
| 191 * @param {TilePage} opt_refNode Optional reference node to insert in front | 201 * @param {TilePage} opt_refNode Optional reference node to insert in front |
| 192 * of. | 202 * of. |
| 193 * When opt_refNode is falsey, |page| will just be appended to the end of | 203 * When opt_refNode is falsey, |page| will just be appended to the end of |
| 194 * the page list. | 204 * the page list. |
| 195 */ | 205 */ |
| 196 appendTilePage: function(page, title, titleIsEditable, opt_refNode) { | 206 appendTilePage: function(page, title, titleIsEditable, opt_refNode) { |
| 197 // When opt_refNode is falsey, insertBefore acts just like appendChild. | 207 // When opt_refNode is falsey, insertBefore acts just like appendChild. |
| 198 this.pageList.insertBefore(page, opt_refNode); | 208 this.pageList.insertBefore(page, opt_refNode); |
| 199 | 209 |
| 210 if (!document.documentElement.classList.contains('starting-up')) { | |
| 211 // If we're inserting a card in front of the current card, add 1 to the | |
| 212 // current index to adjust for the new card in the order. | |
| 213 var index = Array.prototype.indexOf.call(this.tilePages, page); | |
| 214 if (typeof this.cardSlider.currentCard != 'undefined' && | |
| 215 index <= this.cardSlider.currentCard) { | |
| 216 this.cardSlider.currentCard += 1; | |
| 217 } | |
| 218 if (page instanceof ntp4.AppsPage && | |
| 219 this.shownPage == templateData.apps_page_id && | |
| 220 this.getAppsPageIndex(page) <= this.shownPageIndex) { | |
| 221 this.shownPageIndex += 1; | |
| 222 } | |
| 223 } | |
| 224 | |
| 200 // Remember special MostVisitedPage. | 225 // Remember special MostVisitedPage. |
| 201 if (typeof ntp4.MostVisitedPage != 'undefined' && | 226 if (typeof ntp4.MostVisitedPage != 'undefined' && |
| 202 page instanceof ntp4.MostVisitedPage) { | 227 page instanceof ntp4.MostVisitedPage) { |
| 203 assert(this.tilePages.length == 1, | 228 assert(this.tilePages.length == 1, |
| 204 'MostVisitedPage should be added as first tile page'); | 229 'MostVisitedPage should be added as first tile page'); |
| 205 this.mostVisitedPage = page; | 230 this.mostVisitedPage = page; |
| 206 } | 231 } |
| 207 | 232 |
| 208 // If we're appending an AppsPage and it's a temporary page, animate it. | 233 // If we're appending an AppsPage and it's a temporary page, animate it. |
| 209 var animate = page instanceof ntp4.AppsPage && | 234 var animate = page instanceof ntp4.AppsPage && |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 220 this.eventTracker.add(page, 'pagelayout', this.onPageLayout_.bind(this)); | 245 this.eventTracker.add(page, 'pagelayout', this.onPageLayout_.bind(this)); |
| 221 }, | 246 }, |
| 222 | 247 |
| 223 /** | 248 /** |
| 224 * Called by chrome when an existing app has been disabled or | 249 * Called by chrome when an existing app has been disabled or |
| 225 * removed/uninstalled from chrome. | 250 * removed/uninstalled from chrome. |
| 226 * @param {Object} appData A data structure full of relevant information for | 251 * @param {Object} appData A data structure full of relevant information for |
| 227 * the app. | 252 * the app. |
| 228 * @param {boolean} isUninstall True if the app is being uninstalled; | 253 * @param {boolean} isUninstall True if the app is being uninstalled; |
| 229 * false if the app is being disabled. | 254 * false if the app is being disabled. |
| 255 * @param {boolean} fromPage If the removal was from the current page. | |
| 230 */ | 256 */ |
| 231 appRemoved: function(appData, isUninstall) { | 257 appRemoved: function(appData, isUninstall, fromPage) { |
| 232 var app = $(appData.id); | 258 var app = $(appData.id); |
| 233 assert(app, 'trying to remove an app that doesn\'t exist'); | 259 assert(app, 'trying to remove an app that doesn\'t exist'); |
| 234 | 260 |
| 235 if (!isUninstall) | 261 if (!isUninstall) { |
| 236 app.replaceAppData(appData); | 262 app.replaceAppData(appData); |
| 237 else | 263 } else { |
| 238 app.remove(); | 264 // Unset the ID immediately, because the app is already gone. But leave |
| 265 // the tile on the page as it animates out. | |
| 266 app.id = ''; | |
|
Evan Stade
2011/12/08 02:34:56
i think this can go inside the if (fromPage) case?
Dan Beam
2011/12/08 04:46:18
Done.
| |
| 267 // If the uninstall was from this page, run the blipout animation and | |
| 268 // the tile will be removed in TilePage#onContentsAnimationEnd_. | |
| 269 // Otherwise delete the tile without auto-deleting the page to avoid | |
| 270 // re-deleting the same page (or the page that slid in to take its | |
| 271 // place). | |
| 272 if (fromPage) { | |
| 273 app.classList.add('removing-tile-contents'); | |
| 274 } else { | |
| 275 var tilePage = app.tile.tilePage; | |
| 276 tilePage.removeTile(app.tile, false, true); | |
| 277 this.removeAppsPageIfEmpty_(tilePage, false, true); | |
| 278 } | |
| 279 } | |
| 239 }, | 280 }, |
| 240 | 281 |
| 241 /** | 282 /** |
| 242 * Callback invoked by chrome with the apps available. | 283 * Callback invoked by chrome with the apps available. |
| 243 * | 284 * |
| 244 * Note that calls to this function can occur at any time, not just in | 285 * 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 | 286 * response to a getApps request. For example, when a user |
| 246 * installs/uninstalls an app on another synchronized devices. | 287 * installs/uninstalls an app on another synchronized devices. |
| 247 * @param {Object} data An object with all the data on available | 288 * @param {Object} data An object with all the data on available |
| 248 * applications. | 289 * applications. |
| 249 */ | 290 */ |
| 250 getAppsCallback: function(data) { | 291 getAppsCallback: function(data) { |
| 251 var startTime = Date.now(); | 292 var startTime = Date.now(); |
| 252 | 293 |
| 253 // Clear any existing apps pages and dots. | 294 // Clear any existing apps pages and dots. |
| 254 // TODO(rbyers): It might be nice to preserve animation of dots after an | 295 // 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 | 296 // 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 | 297 // seems unfortunate to have Chrome send us the entire apps list after an |
| 257 // uninstall. | 298 // uninstall. |
| 258 while (this.appsPages.length > 0) { | 299 while (this.appsPages.length > 0) { |
| 259 var page = this.appsPages[0]; | 300 var page = this.appsPages[0]; |
| 260 var dot = page.navigationDot; | |
| 261 | 301 |
| 262 this.eventTracker.remove(page); | 302 this.eventTracker.remove(page); |
| 263 page.tearDown(); | 303 this.removeTilePageAndDot_(page); |
| 264 page.parentNode.removeChild(page); | |
| 265 dot.parentNode.removeChild(dot); | |
| 266 } | 304 } |
| 267 | 305 |
| 268 // Get the array of apps and add any special synthesized entries | 306 // Get the array of apps and add any special synthesized entries |
| 269 var apps = data.apps; | 307 var apps = data.apps; |
| 270 | 308 |
| 271 // Get a list of page names | 309 // Get a list of page names |
| 272 var pageNames = data.appPageNames; | 310 var pageNames = data.appsPageNames; |
| 273 | 311 |
| 274 function stringListIsEmpty(list) { | 312 function stringListIsEmpty(list) { |
| 275 for (var i = 0; i < list.length; i++) { | 313 for (var i = 0; i < list.length; i++) { |
| 276 if (list[i]) | 314 if (list[i]) |
| 277 return false; | 315 return false; |
| 278 } | 316 } |
| 279 return true; | 317 return true; |
| 280 } | 318 } |
| 281 | 319 |
| 282 // Sort by launch index | 320 // Sort by launch index |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 331 * @param {Object} appData A data structure full of relevant information for | 369 * @param {Object} appData A data structure full of relevant information for |
| 332 * the app. | 370 * the app. |
| 333 */ | 371 */ |
| 334 appAdded: function(appData, opt_highlight) { | 372 appAdded: function(appData, opt_highlight) { |
| 335 if (appData.id == this.highlightAppId) { | 373 if (appData.id == this.highlightAppId) { |
| 336 opt_highlight = true; | 374 opt_highlight = true; |
| 337 this.highlightAppId = null; | 375 this.highlightAppId = null; |
| 338 } | 376 } |
| 339 | 377 |
| 340 var pageIndex = appData.page_index || 0; | 378 var pageIndex = appData.page_index || 0; |
| 341 | 379 this.ensureAppsPageAtIndex_(pageIndex); |
| 342 if (pageIndex >= this.appsPages.length) { | |
| 343 while (pageIndex >= this.appsPages.length) { | |
| 344 this.appendTilePage(new ntp4.AppsPage(), | |
| 345 localStrings.getString('appDefaultPageName'), | |
| 346 true); | |
| 347 } | |
| 348 this.updateSliderCards(); | |
| 349 } | |
| 350 | 380 |
| 351 var page = this.appsPages[pageIndex]; | 381 var page = this.appsPages[pageIndex]; |
| 352 var app = $(appData.id); | 382 var app = $(appData.id); |
| 353 if (app) | 383 if (app) |
| 354 app.replaceAppData(appData); | 384 app.replaceAppData(appData); |
| 355 else | 385 else |
| 356 page.appendApp(appData, opt_highlight); | 386 page.appendApp(appData, opt_highlight); |
| 357 }, | 387 }, |
| 358 | 388 |
| 359 /** | 389 /** |
| 360 * Callback invoked by chrome whenever an app preference changes. | 390 * Callback invoked by chrome whenever an app preference changes. |
| 361 * @param {Object} data An object with all the data on available | 391 * @param {Object} data An object with all the data on available |
| 362 * applications. | 392 * applications. |
| 363 */ | 393 */ |
| 364 appsPrefChangedCallback: function(data) { | 394 appsPrefChangedCallback: function(data) { |
| 365 for (var i = 0; i < data.apps.length; ++i) { | 395 for (var i = 0; i < data.apps.length; ++i) |
| 366 $(data.apps[i].id).appData = data.apps[i]; | 396 $(data.apps[i].id).appData = data.apps[i]; |
| 367 } | |
| 368 | 397 |
| 369 // Set the App dot names. Skip the first dot (Most Visited). | 398 // Set the App dot names. Skip dots that don't belong to apps pages. |
| 370 var dots = this.dotList.getElementsByClassName('dot'); | 399 var dots = this.dotList.getElementsByClassName('dot'); |
| 371 var start = this.mostVisitedPage ? 1 : 0; | 400 var firstAppDot = this.getTilePageIndex(this.appsPages[0]); |
| 372 for (var i = start; i < dots.length; ++i) { | 401 for (var i = 0; i < data.appsPageNames.length; ++i) { |
| 373 dots[i].displayTitle = data.appPageNames[i - start] || ''; | 402 // When we drop an app on a navigation dot or new page we first move the |
| 403 // tile (which calls this), *then* save the page name so sometimes we'll | |
| 404 // be one short here. | |
| 405 var dot = dots[firstAppDot + i]; | |
| 406 if (dot) | |
| 407 dot.displayTitle = data.appsPageNames[i]; | |
| 374 } | 408 } |
| 375 }, | 409 }, |
| 376 | 410 |
| 377 /** | 411 /** |
| 378 * Invoked whenever the pages in apps-page-list have changed so that | 412 * Invoked whenever the pages in apps-page-list have changed so that |
| 379 * the Slider knows about the new elements. | 413 * the Slider knows about the new elements. |
| 380 */ | 414 */ |
| 381 updateSliderCards: function() { | 415 updateSliderCards: function() { |
| 382 var pageNo = Math.min(this.cardSlider.currentCard, | 416 var index = -1; |
| 383 this.tilePages.length - 1); | 417 var prevPage = this.shownPage; |
| 384 this.cardSlider.setCards(Array.prototype.slice.call(this.tilePages), | 418 var prevIndex = this.shownPageIndex; |
| 385 pageNo); | 419 var tiles = Array.prototype.slice.call(this.tilePages); |
| 420 // It doesn't hurt to clamp value this every time, even if it's only | |
| 421 // applicable to apps. It helps self-heal strange / un-expected data, i.e. | |
|
Evan Stade
2011/12/08 02:34:56
strange/unexepected data most likely comes from pr
Dan Beam
2011/12/08 04:46:18
Done. (changed comment)
| |
| 422 // going from an apps page to the most visited page directly without | |
| 423 // setting this.shownPageIndex = 0 somehow. | |
| 424 this.shownPageIndex = Math.max(0, Math.min(this.shownPageIndex, | |
| 425 this.appsPages.length - 1)); | |
| 386 switch (this.shownPage) { | 426 switch (this.shownPage) { |
| 387 case templateData['apps_page_id']: | 427 case templateData.apps_page_id: |
| 388 this.cardSlider.selectCardByValue( | 428 index = tiles.indexOf(this.appsPages[this.shownPageIndex]); |
| 389 this.appsPages[Math.min(this.shownPageIndex, | |
| 390 this.appsPages.length - 1)]); | |
| 391 break; | 429 break; |
| 392 case templateData['most_visited_page_id']: | 430 case templateData.most_visited_page_id: |
| 393 if (this.mostVisitedPage) | 431 index = tiles.indexOf(this.mostVisitedPage); |
| 394 this.cardSlider.selectCardByValue(this.mostVisitedPage); | |
| 395 break; | 432 break; |
| 396 } | 433 } |
| 434 // If shownPage was saved as a page that's now disabled or the shownPage | |
| 435 // doesn't exist any more, index will be -1. Change to the preferred | |
| 436 // default page (first apps pane) in this case. | |
| 437 if (index < 0) { | |
| 438 this.shownPage = templateData.apps_page_id; | |
| 439 index = tiles.indexOf(this.appsPages[0]); | |
| 440 } | |
| 441 // Set the new cards and index. | |
| 442 this.cardSlider.setCards(tiles, index); | |
| 443 // If we got new page or index, update the pref. | |
| 444 if (prevIndex != this.shownPageIndex || prevPage != this.shownPage) | |
|
Evan Stade
2011/12/08 02:34:56
you should just always do this. this.shownPageInde
Dan Beam
2011/12/08 04:46:18
Done. OK, I just noticed it was often doing this
| |
| 445 chrome.send('pageSelected', [this.shownPage, this.shownPageIndex]); | |
| 397 }, | 446 }, |
| 398 | 447 |
| 399 /** | 448 /** |
| 400 * Called whenever tiles should be re-arranging themselves out of the way | 449 * Called whenever tiles should be re-arranging themselves out of the way |
| 401 * of a moving or insert tile. | 450 * of a moving or insert tile. |
| 402 */ | 451 */ |
| 403 enterRearrangeMode: function() { | 452 enterRearrangeMode: function() { |
| 404 var tempPage = new ntp4.AppsPage(); | 453 var tempPage = new ntp4.AppsPage(); |
| 405 tempPage.classList.add('temporary'); | 454 tempPage.classList.add('temporary'); |
| 406 this.appendTilePage(tempPage, | 455 var pageName = localStrings.getString('appDefaultPageName'); |
| 407 localStrings.getString('appDefaultPageName'), | 456 this.appendTilePage(tempPage, pageName, true); |
| 408 true); | |
| 409 var tempIndex = Array.prototype.indexOf.call(this.tilePages, tempPage); | |
| 410 if (this.cardSlider.currentCard >= tempIndex) | |
| 411 this.cardSlider.currentCard += 1; | |
| 412 this.updateSliderCards(); | 457 this.updateSliderCards(); |
| 458 this.updatePageSwitchers(); | |
| 413 | 459 |
| 414 if (ntp4.getCurrentlyDraggingTile().firstChild.canBeRemoved()) | 460 if (ntp4.getCurrentlyDraggingTile().firstChild.canBeRemoved()) |
| 415 $('footer').classList.add('showing-trash-mode'); | 461 $('footer').classList.add('showing-trash-mode'); |
| 416 }, | 462 }, |
| 417 | 463 |
| 418 /** | 464 /** |
| 419 * Invoked whenever some app is released | 465 * Invoked whenever some app is released |
| 420 */ | 466 */ |
| 421 leaveRearrangeMode: function() { | 467 leaveRearrangeMode: function() { |
| 422 var tempPage = document.querySelector('.tile-page.temporary'); | 468 var tempPage = document.querySelector('.tile-page.temporary'); |
| 423 var dot = tempPage.navigationDot; | 469 // Either remove a temp page if it's empty or save the page name (as an |
| 424 if (!tempPage.tileCount && tempPage != this.cardSlider.currentCardValue) { | 470 // app has just been dropped on it or created somehow. |
|
Evan Stade
2011/12/08 02:34:56
close paren
Dan Beam
2011/12/08 04:46:18
Done. http://xkcd.com/859/
| |
| 425 dot.animateRemove(); | 471 if (tempPage && !this.removeAppsPageIfEmpty_(tempPage, true, true)) { |
| 426 var tempIndex = Array.prototype.indexOf.call(this.tilePages, tempPage); | 472 this.saveAppsPageName(tempPage, tempPage.navigationDot.displayTitle); |
| 427 if (this.cardSlider.currentCard > tempIndex) | |
| 428 this.cardSlider.currentCard -= 1; | |
| 429 tempPage.parentNode.removeChild(tempPage); | |
| 430 this.updateSliderCards(); | |
| 431 } else { | |
| 432 tempPage.classList.remove('temporary'); | 473 tempPage.classList.remove('temporary'); |
| 433 this.saveAppPageName(tempPage, | |
| 434 localStrings.getString('appDefaultPageName')); | |
| 435 } | 474 } |
| 436 | 475 |
| 437 $('footer').classList.remove('showing-trash-mode'); | 476 $('footer').classList.remove('showing-trash-mode'); |
| 438 }, | 477 }, |
| 439 | 478 |
| 440 /** | 479 /** |
| 441 * Callback for the 'pagelayout' event. | 480 * Callback for the 'pagelayout' event. |
| 442 * @param {Event} e The event. | 481 * @param {Event} e The event. |
| 443 */ | 482 */ |
| 444 onPageLayout_: function(e) { | 483 onPageLayout_: function(e) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 481 pageSwitcherRight.style.right = scrollbarWidth + 'px'; | 520 pageSwitcherRight.style.right = scrollbarWidth + 'px'; |
| 482 | 521 |
| 483 var offsetTop = page.querySelector('.tile-page-content').offsetTop + 'px'; | 522 var offsetTop = page.querySelector('.tile-page-content').offsetTop + 'px'; |
| 484 pageSwitcherLeft.style.top = offsetTop; | 523 pageSwitcherLeft.style.top = offsetTop; |
| 485 pageSwitcherRight.style.top = offsetTop; | 524 pageSwitcherRight.style.top = offsetTop; |
| 486 pageSwitcherLeft.style.paddingBottom = offsetTop; | 525 pageSwitcherLeft.style.paddingBottom = offsetTop; |
| 487 pageSwitcherRight.style.paddingBottom = offsetTop; | 526 pageSwitcherRight.style.paddingBottom = offsetTop; |
| 488 }, | 527 }, |
| 489 | 528 |
| 490 /** | 529 /** |
| 491 * Returns the index of the given page. | 530 * Returns the index of the given apps page. |
| 492 * @param {AppsPage} page The AppsPage for we wish to find. | 531 * @param {AppsPage} page The AppsPage we wish to find. |
| 493 * @return {number} The index of |page|, or -1 if it is not here. | 532 * @return {number} The index of |page| or -1 if it is not in the |
| 533 * collection. | |
| 494 */ | 534 */ |
| 495 getAppsPageIndex: function(page) { | 535 getAppsPageIndex: function(page) { |
| 496 return Array.prototype.indexOf.call(this.appsPages, page); | 536 return Array.prototype.indexOf.call(this.appsPages, page); |
| 497 }, | 537 }, |
| 498 | 538 |
| 499 /** | 539 /** |
| 500 * Handler for CARD_CHANGED on cardSlider. | 540 * Handler for CARD_CHANGED on cardSlider. |
| 501 * @param {Event} e The CARD_CHANGED event. | 541 * @param {Event} e The CARD_CHANGED event. |
| 502 * @private | 542 * @private |
| 503 */ | 543 */ |
| 504 cardChangedHandler_: function(e) { | 544 cardChangedHandler_: function(e) { |
| 505 var page = e.cardSlider.currentCardValue; | 545 var page = e.cardSlider.currentCardValue; |
| 506 | 546 |
| 507 // Don't change shownPage until startup is done (and page changes actually | 547 // Don't change shownPage until startup is done (and page changes actually |
| 508 // reflect user actions). | 548 // reflect user actions). |
| 509 if (!document.documentElement.classList.contains('starting-up')) { | 549 if (!document.documentElement.classList.contains('starting-up')) { |
| 550 var prevPage = this.shownPage; | |
| 551 var prevIndex = this.shownPageIndex; | |
| 510 if (page.classList.contains('apps-page')) { | 552 if (page.classList.contains('apps-page')) { |
| 511 this.shownPage = templateData['apps_page_id']; | 553 this.shownPage = templateData.apps_page_id; |
| 512 this.shownPageIndex = this.getAppsPageIndex(page); | 554 this.shownPageIndex = this.getAppsPageIndex(page); |
| 513 } else if (page.classList.contains('most-visited-page')) { | 555 } else if (page.classList.contains('most-visited-page')) { |
| 514 this.shownPage = templateData['most_visited_page_id']; | 556 this.shownPage = templateData.most_visited_page_id; |
| 515 this.shownPageIndex = 0; | 557 this.shownPageIndex = 0; |
| 516 } else { | 558 } else { |
| 517 console.error('unknown page selected'); | 559 console.error('unknown page selected'); |
| 518 } | 560 } |
| 519 chrome.send('pageSelected', [this.shownPage, this.shownPageIndex]); | 561 if (prevPage != this.shownPage || prevIndex != this.shownPageIndex) |
|
Dan Beam
2011/12/08 04:46:18
estade: I'm assuming you'll want me to remove the
| |
| 562 chrome.send('pageSelected', [this.shownPage, this.shownPageIndex]); | |
| 520 } | 563 } |
| 521 | 564 |
| 522 // Update the active dot | 565 // Update the active dot |
| 523 var curDot = this.dotList.getElementsByClassName('selected')[0]; | 566 var curDot = this.dotList.getElementsByClassName('selected')[0]; |
| 524 if (curDot) | 567 if (curDot) |
| 525 curDot.classList.remove('selected'); | 568 curDot.classList.remove('selected'); |
| 526 page.navigationDot.classList.add('selected'); | 569 page.navigationDot.classList.add('selected'); |
| 527 this.updatePageSwitchers(); | 570 this.updatePageSwitchers(); |
| 528 }, | 571 }, |
| 529 | 572 |
| 530 /* | 573 /** |
| 531 * Save the name of an app page. | 574 * Save the name of an apps page. |
| 532 * Store the app page name into the preferences store. | 575 * Store the apps page name into the preferences store. |
| 533 * @param {AppsPage} appPage The app page for which we wish to save. | 576 * @param {AppsPage} appsPage The app page for which we wish to save. |
| 534 * @param {string} name The name of the page. | 577 * @param {string} name The name of the page. |
| 535 */ | 578 */ |
| 536 saveAppPageName: function(appPage, name) { | 579 saveAppsPageName: function(appsPage, name) { |
| 537 var index = this.getAppsPageIndex(appPage); | 580 var index = this.getAppsPageIndex(appsPage); |
| 538 assert(index != -1); | 581 assert(index != -1); |
| 539 chrome.send('saveAppPageName', [name, index]); | 582 chrome.send('saveAppsPageName', [name, index]); |
| 540 }, | 583 }, |
| 541 | 584 |
| 542 /** | 585 /** |
| 586 * An Array of callbacks to be called on the next CARD_CHANGE_ENDED event | |
| 587 * handled from the cardSlider. | |
| 588 * @private | |
| 589 */ | |
| 590 cardChangeEndedCallbacks_: [], | |
| 591 | |
| 592 /** | |
| 593 * Handler for CARD_CHANGE_ENDED on cardSlider. | |
| 594 * @param {Event} e The CARD_CHANGE_ENDED event. | |
| 595 * @private | |
| 596 */ | |
| 597 cardChangeEndedHandler_: function(e) { | |
| 598 if (!document.documentElement.classList.contains('starting-up')) { | |
| 599 while (this.cardChangeEndedCallbacks_.length > 0) | |
| 600 this.cardChangeEndedCallbacks_.shift().call(this, e); | |
| 601 } | |
| 602 }, | |
| 603 | |
| 604 /** | |
| 605 * Happens when a tile is removed from a tile page. | |
| 606 * @param {Event} e An event dispatched from a tile when it is removed. | |
| 607 */ | |
| 608 tileRemovedHandler_: function(e) { | |
| 609 if (e.tilePage instanceof ntp4.AppsPage) | |
| 610 this.removeAppsPageIfEmpty_(e.tilePage, e.wasAnimated); | |
| 611 }, | |
| 612 | |
| 613 /** | |
| 614 * Remove an apps page if it now has no tiles (is empty). | |
| 615 * @param {AppsPage} appsPage A page to check for emptiness. | |
| 616 * @param {boolean=} opt_animate Whether the prospective removal should be | |
| 617 * animated. | |
| 618 * @param {boolean=} opt_dontNotify Whether this NTP's AppLauncherHandler | |
| 619 * shouldn't be notified of this pages' prospective removal (default is | |
| 620 * to notify). | |
| 621 * @return {boolean} If |appsPage| was removed or not. | |
| 622 */ | |
| 623 removeAppsPageIfEmpty_: function(appsPage, opt_animate, opt_dontNotify) { | |
| 624 assert(appsPage instanceof ntp4.AppsPage, | |
| 625 '|appsPage| is really an AppsPage'); | |
|
Evan Stade
2011/12/08 02:34:56
isn't the string an error message? Hence you would
Dan Beam
2011/12/08 04:46:18
Done.
| |
| 626 if (appsPage.tileCount == 0) { | |
| 627 var whenDone = function() { | |
|
Evan Stade
2011/12/08 02:34:56
some comment about whenDone is necessary
Dan Beam
2011/12/08 04:46:18
Done.
| |
| 628 if (!opt_dontNotify) { | |
|
Evan Stade
2011/12/08 02:34:56
no curlies
Dan Beam
2011/12/08 04:46:18
Done.
| |
| 629 chrome.send('deleteAppsPage', [this.getAppsPageIndex(appsPage)]); | |
| 630 } | |
| 631 this.removeTilePageAndDot_(appsPage, opt_animate); | |
| 632 this.updateSliderCards(); | |
| 633 this.updatePageSwitchers(); | |
| 634 }; | |
|
Evan Stade
2011/12/08 02:34:56
newline
Dan Beam
2011/12/08 04:46:18
Done.
| |
| 635 // If currently on the empty apps pane, move off of it before deleting. | |
| 636 if (appsPage === this.cardSlider.currentCardValue) { | |
| 637 this.cardChangeEndedCallbacks_.push(whenDone); | |
| 638 this.moveOffEmptyAppsPage(appsPage, opt_animate); | |
| 639 } else { | |
| 640 whenDone.call(this); | |
| 641 } | |
| 642 return true; | |
| 643 } | |
| 644 return false; | |
|
Evan Stade
2011/12/08 02:34:56
if (appsPage.tileCount != 0)
return false;
...
Dan Beam
2011/12/08 04:46:18
Done.
| |
| 645 }, | |
| 646 | |
| 647 /** | |
| 543 * Window resize handler. | 648 * Window resize handler. |
| 544 * @private | 649 * @private |
| 545 */ | 650 */ |
| 546 onWindowResize_: function(e) { | 651 onWindowResize_: function(e) { |
| 547 this.cardSlider.resize(this.sliderFrame.offsetWidth); | 652 this.cardSlider.resize(this.sliderFrame.offsetWidth); |
| 548 this.updatePageSwitchers(); | 653 this.updatePageSwitchers(); |
| 549 }, | 654 }, |
| 550 | 655 |
| 551 /** | 656 /** |
| 552 * Listener for offline status change events. Updates apps that are | 657 * Listener for offline status change events. Updates apps that are |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 580 direction = 1; | 685 direction = 1; |
| 581 else | 686 else |
| 582 return; | 687 return; |
| 583 | 688 |
| 584 var cardIndex = | 689 var cardIndex = |
| 585 (this.cardSlider.currentCard + direction + | 690 (this.cardSlider.currentCard + direction + |
| 586 this.cardSlider.cardCount) % this.cardSlider.cardCount; | 691 this.cardSlider.cardCount) % this.cardSlider.cardCount; |
| 587 this.cardSlider.selectCard(cardIndex, true); | 692 this.cardSlider.selectCard(cardIndex, true); |
| 588 | 693 |
| 589 e.stopPropagation(); | 694 e.stopPropagation(); |
| 590 } | 695 }, |
| 696 | |
| 697 /** | |
| 698 * Re-order apps on this inactive page when an active NTP gets re-ordered. | |
| 699 * @param {Object} data Position hashmap ordered by app id with indices: | |
| 700 * {id => {page_index: ##, app_launch_index: ##}} | |
| 701 */ | |
| 702 appsReordered: function(data) { | |
| 703 var pages = Object.keys(data); | |
| 704 for (var i = 0; i < pages.length; ++i) { | |
| 705 var page = data[pages[i]]; | |
| 706 var indices = Object.keys(page); | |
| 707 for (var j = 0; j < indices.length; ++j) { | |
| 708 var app = $(page[indices[j]]); | |
| 709 var originalPage = app.tile.tilePage; | |
| 710 if (i != this.getAppsPageIndex(originalPage) || j != app.tile.index) { | |
| 711 originalPage.removeTile(app.tile, false, true); | |
| 712 this.ensureAppsPageAtIndex_(i); | |
| 713 this.appsPages[i].addTileAt(app, j); | |
| 714 } | |
| 715 } | |
| 716 } | |
| 717 for (var i = 0; i < this.appsPages.length; ++i) { | |
| 718 // If a page is now empty, remove it and move backward one in our | |
|
Evan Stade
2011/12/08 02:34:56
comments are nice but this code is self-documentin
Dan Beam
2011/12/08 04:46:18
Done.
| |
| 719 // array-like object as it is a live NodeList and the length/indice | |
|
Evan Stade
2011/12/08 02:34:56
INDICE
Dan Beam
2011/12/08 04:46:18
DONE. (well, removed whole comment...)
| |
| 720 // change when you update it. Otherwise, make sure the tiles are in the | |
| 721 // right positions (just like after a user is done dragging). | |
| 722 if (this.removeAppsPageIfEmpty_(this.appsPages[i], false, true)) | |
| 723 --i; | |
| 724 else | |
| 725 this.appsPages[i].cleanupDrag(); | |
| 726 } | |
| 727 }, | |
| 728 | |
| 729 /** | |
| 730 * Ensure there is an apps page at the given |index|. If index is smaller | |
|
Evan Stade
2011/12/08 02:34:56
smaller??
Dan Beam
2011/12/08 04:46:18
Done.
| |
| 731 * than the current number of apps pages, additional apps pages will be | |
| 732 * created. | |
| 733 * @param {number} index An apps page index to ensure exists. | |
| 734 */ | |
| 735 ensureAppsPageAtIndex_: function(index) { | |
| 736 if (index >= this.appsPages.length) { | |
| 737 var pageName = localStrings.getString('appDefaultPageName'); | |
| 738 while (index >= this.appsPages.length) | |
| 739 this.appendTilePage(new ntp4.AppsPage(), pageName, true); | |
| 740 this.updateSliderCards(); | |
| 741 } | |
| 742 }, | |
| 743 | |
| 744 /** | |
| 745 * Returns the index of a given tile page. | |
| 746 * @param {TilePage} page The TilePage we wish to find. | |
| 747 * @return {number} The index of |page| or -1 if it is not in the | |
| 748 * collection. | |
| 749 */ | |
| 750 getTilePageIndex: function(page) { | |
| 751 return Array.prototype.indexOf.call(this.tilePages, page); | |
| 752 }, | |
| 753 | |
| 754 /** | |
| 755 * Move to a non-empty page before/while we delete an empty one. | |
| 756 * @param {AppsPage} appsPage An empty apps page that we want to move off of | |
| 757 * (probably because it's empty). | |
| 758 * @param {boolean=} opt_animate Whether we should animate or not. | |
| 759 */ | |
| 760 moveOffEmptyAppsPage: function(appsPage, opt_animate) { | |
| 761 assert(appsPage instanceof ntp4.AppsPage, | |
| 762 '|appsPage| is really an AppsPage'); | |
| 763 // Select the page further toward the end than the empty |appsPage|. If | |
| 764 // the empty |appsPage| is at the end, the apps page before it will be | |
| 765 // selected. | |
| 766 var index = this.getAppsPageIndex(appsPage); | |
| 767 assert(index >= 0, '|appsPage| is in this.appsPages'); | |
| 768 var direction = (index == this.appsPages.length - 1 ? -1 : 1); | |
|
Evan Stade
2011/12/08 02:34:56
no ()
Dan Beam
2011/12/08 04:46:18
Done. (but I still don't agree that this is easier
| |
| 769 this.cardSlider.selectCard(this.cardSlider.currentCard + direction, | |
| 770 opt_animate); | |
| 771 }, | |
| 772 | |
| 773 /** | |
| 774 * Removes a page and navigation dot (if the navdot exists). | |
| 775 * @param {TilePage} page The page to be removed. | |
| 776 * @param {boolean=} opt_animate If the removal should be animated. | |
| 777 */ | |
| 778 removeTilePageAndDot_: function(page, opt_animate) { | |
| 779 if (!document.documentElement.classList.contains('starting-up')) { | |
| 780 // If the card being deleted is before the current card, keep the same | |
| 781 // spot in the list by removing 1 from the current card index. | |
| 782 var index = Array.prototype.indexOf.call(this.tilePages, page); | |
| 783 if (index < this.cardSlider.currentCard) { | |
|
Evan Stade
2011/12/08 02:34:56
no curlies
Dan Beam
2011/12/08 04:46:18
Done.
| |
| 784 this.cardSlider.currentCard -= 1; | |
| 785 } | |
| 786 // If the page we're about to delete is in front of the current page, | |
| 787 // remove 1 from the shown page index. | |
| 788 if (page instanceof ntp4.AppsPage && | |
| 789 this.shownPage == templateData.apps_page_id && | |
| 790 this.getAppsPageIndex(page) < this.shownPageIndex) { | |
| 791 this.shownPageIndex -= 1; | |
|
Evan Stade
2011/12/08 02:34:56
this doesn't seem necessary. Wont the shownPageInd
Dan Beam
2011/12/08 04:46:18
cardSlider.currentCard is an ES5 getter but all it
Dan Beam
2011/12/08 07:27:52
Working on fixing this to be in cardSlider instead
| |
| 792 } | |
| 793 } | |
| 794 if (page.navigationDot) | |
| 795 page.navigationDot.remove(opt_animate); | |
| 796 page.remove(); | |
| 797 }, | |
| 591 }; | 798 }; |
| 592 | 799 |
| 593 return { | 800 return { |
| 594 PageListView: PageListView | 801 PageListView: PageListView |
| 595 }; | 802 }; |
| 596 }); | 803 }); |
| OLD | NEW |