OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 /** | |
6 * @fileoverview PageListView implementation. | |
7 * PageListView manages page list, dot list, switcher buttons and glue apps | |
8 * pages with backend. | |
9 */ | |
10 | |
11 cr.define('ntp4', function() { | |
12 'use strict'; | |
13 | |
14 /** | |
15 * Object for accessing localized strings. | |
16 * @type {!LocalStrings} | |
17 */ | |
18 var localStrings = new LocalStrings; | |
19 | |
20 /** | |
21 * Current live PageListView instance. | |
22 * @type {!Object|undefined} | |
23 */ | |
24 var instance; | |
Evan Stade
2011/11/07 23:59:20
I don't like the restriction that this class shoul
xiyuan
2011/11/08 21:09:18
Done.
| |
25 | |
26 /** | |
27 * Creates a PageListView object. | |
28 * @constructor | |
29 * @extends {Object} | |
30 */ | |
31 function PageListView() { | |
32 } | |
33 | |
34 PageListView.getInstance = function() { | |
35 return instance; | |
36 } | |
37 | |
38 PageListView.prototype = { | |
39 /** | |
40 * The CardSlider object to use for changing app pages. | |
41 * @type {CardSlider|undefined} | |
42 */ | |
43 cardSlider: undefined, | |
44 | |
45 /** | |
46 * The frame div for cardSlider. | |
47 * @type {!Element|undefined} | |
48 */ | |
49 sliderFrame: undefined, | |
50 | |
51 /** | |
52 * The 'page-list' element. | |
53 * @type {!Element|undefined} | |
54 */ | |
55 pageList: undefined, | |
56 | |
57 /** | |
58 * A list of all 'tile-page' elements. | |
59 * @type {!NodeList|undefined} | |
60 */ | |
61 tilePages: undefined, | |
62 | |
63 /** | |
64 * A list of all 'apps-page' elements. | |
65 * @type {!NodeList|undefined} | |
66 */ | |
67 appsPages: undefined, | |
68 | |
69 /** | |
70 * The Most Visited page. | |
71 * @type {!Element|undefined} | |
72 */ | |
73 mostVisitedPage: undefined, | |
74 | |
75 /** | |
76 * The Bookmarks page. | |
77 * @type {!Element|undefined} | |
78 */ | |
79 bookmarksPage: undefined, | |
80 | |
81 /** | |
82 * The 'dots-list' element. | |
83 * @type {!Element|undefined} | |
84 */ | |
85 dotList: undefined, | |
86 | |
87 /** | |
88 * The left and right paging buttons. | |
89 * @type {!Element|undefined} | |
90 */ | |
91 pageSwitcherStart: undefined, | |
92 pageSwitcherEnd: undefined, | |
93 | |
94 /** | |
95 * The 'trash' element. Note that technically this is unnecessary, | |
96 * JavaScript creates the object for us based on the id. But I don't want | |
97 * to rely on the ID being the same, and JSCompiler doesn't know about it. | |
98 * @type {!Element|undefined} | |
99 */ | |
100 trash: undefined, | |
101 | |
102 /** | |
103 * The type of page that is currently shown. The value is a numerical ID. | |
104 * @type {number} | |
105 */ | |
106 shownPage: 0, | |
107 | |
108 /** | |
109 * The index of the page that is currently shown, within the page type. | |
110 * For example if the third Apps page is showing, this will be 2. | |
111 * @type {number} | |
112 */ | |
113 shownPageIndex: 0, | |
114 | |
115 /** | |
116 * EventTracker for managing event listeners for page events. | |
117 * @type {!EventTracker} | |
118 */ | |
119 eventTracker: new EventTracker, | |
120 | |
121 /** | |
122 * If non-null, this is the ID of the app to highlight to the user the next | |
123 * time getAppsCallback runs. "Highlight" in this case means to switch to | |
124 * the page and run the new tile animation. | |
125 * @type {String} | |
126 */ | |
127 highlightAppId: null, | |
128 | |
129 /** | |
130 * Initializes page list view. | |
131 */ | |
132 initialize: function() { | |
133 instance = this; | |
134 | |
135 this.pageList = getRequiredElement('page-list'); | |
136 | |
137 this.dotList = getRequiredElement('dot-list'); | |
138 cr.ui.decorate(this.dotList, ntp4.DotList); | |
139 | |
140 this.trash = getRequiredElement('trash'); | |
141 new ntp4.Trash(this.trash); | |
142 | |
143 this.pageSwitcherStart = $('page-switcher-start'); | |
144 if (this.pageSwitcherStart) | |
145 ntp4.initializePageSwitcher(this.pageSwitcherStart); | |
146 | |
147 this.pageSwitcherEnd = $('page-switcher-end'); | |
148 if (this.pageSwitcherEnd) | |
149 ntp4.initializePageSwitcher(this.pageSwitcherEnd); | |
150 | |
151 this.shownPage = templateData['shown_page_type']; | |
152 this.shownPageIndex = templateData['shown_page_index']; | |
153 | |
154 // Request data on the apps so we can fill them in. | |
155 // Note that this is kicked off asynchronously. 'getAppsCallback' will be | |
156 // invoked at some point after this function returns. | |
157 chrome.send('getApps'); | |
158 | |
159 document.addEventListener('keydown', this.onDocKeyDown.bind(this)); | |
160 // Prevent touch events from triggering any sort of native scrolling | |
161 document.addEventListener('touchmove', function(e) { | |
162 e.preventDefault(); | |
163 }, true); | |
164 | |
165 this.tilePages = this.pageList.getElementsByClassName('tile-page'); | |
166 this.appsPages = this.pageList.getElementsByClassName('apps-page'); | |
167 | |
168 // Initialize the cardSlider without any cards at the moment | |
169 this.sliderFrame = getRequiredElement('card-slider-frame'); | |
170 this.cardSlider = new CardSlider(this.sliderFrame, this.pageList, | |
171 this.sliderFrame.offsetWidth); | |
172 this.cardSlider.initialize(); | |
173 | |
174 // Ensure the slider is resized appropriately with the window | |
175 window.addEventListener('resize', this.onWindowResize_.bind(this)); | |
176 | |
177 // Handle the page being changed | |
178 this.pageList.addEventListener( | |
179 CardSlider.EventType.CARD_CHANGED, | |
180 this.cardChangedHandler.bind(this)); | |
181 }, | |
182 | |
183 /** | |
184 * Appends a tile page (for bookmarks or most visited). | |
185 * | |
186 * @param {TilePage} page The page element. | |
187 * @param {string} title The title of the tile page. | |
188 * @param {bool} titleIsEditable If true, the title can be changed. | |
189 * @param {TilePage} opt_refNode Optional reference node to insert in front | |
190 * of. | |
191 * When opt_refNode is falsey, |page| will just be appended to the end of | |
192 * the page list. | |
193 */ | |
194 appendTilePage: function(page, title, titleIsEditable, opt_refNode) { | |
195 // If no opt_refNode given, use bookmarksPage (if any). | |
196 if (!opt_refNode) | |
197 opt_refNode = this.bookmarksPage; | |
198 | |
199 // When opt_refNode is falsey, insertBefore acts just like appendChild. | |
200 this.pageList.insertBefore(page, opt_refNode); | |
201 | |
202 // Remember special MostVisitedPage and BookmarksPage. | |
203 if (typeof ntp4.MostVisitedPage != 'undefined' && | |
204 page instanceof ntp4.MostVisitedPage) { | |
205 assert(this.tilePages.length == 1, | |
206 'MostVisitedPage should be added as first tile page'); | |
207 this.mostVisitedPage = page; | |
208 } | |
209 if (typeof ntp4.BookmarksPage != 'undefined' && | |
210 page instanceof ntp4.BookmarksPage) { | |
211 this.bookmarksPage = page; | |
212 } | |
213 | |
214 // If we're appending an AppsPage and it's a temporary page, animate it. | |
215 var animate = page instanceof ntp4.AppsPage && | |
216 page.classList.contains('temporary'); | |
217 // Make a deep copy of the dot template to add a new one. | |
218 var newDot = new ntp4.NavDot(page, title, titleIsEditable, animate); | |
219 page.navigationDot = newDot; | |
220 this.dotList.insertBefore(newDot, opt_refNode ? opt_refNode.navigationDot | |
221 : null); | |
222 // Set a tab index on the first dot. | |
223 if (this.dotList.dots.length == 1) | |
224 newDot.tabIndex = 3; | |
225 | |
226 this.eventTracker.add(page, 'pagelayout', this.onPageLayout_.bind(this)); | |
227 }, | |
228 | |
229 /** | |
230 * Callback invoked by chrome with the apps available. | |
231 * | |
232 * Note that calls to this function can occur at any time, not just in | |
233 * response to a getApps request. For example, when a user | |
234 * installs/uninstalls an app on another synchronized devices. | |
235 * @param {Object} data An object with all the data on available | |
236 * applications. | |
237 */ | |
238 getAppsCallback: function(data) { | |
239 var startTime = Date.now(); | |
240 | |
241 // Clear any existing apps pages and dots. | |
242 // TODO(rbyers): It might be nice to preserve animation of dots after an | |
243 // uninstall. Could we re-use the existing page and dot elements? It | |
244 // seems unfortunate to have Chrome send us the entire apps list after an | |
245 // uninstall. | |
246 while (this.appsPages.length > 0) { | |
247 var page = this.appsPages[0]; | |
248 var dot = page.navigationDot; | |
249 | |
250 this.eventTracker.remove(page); | |
251 page.tearDown(); | |
252 page.parentNode.removeChild(page); | |
253 dot.parentNode.removeChild(dot); | |
254 } | |
255 | |
256 // Get the array of apps and add any special synthesized entries | |
257 var apps = data.apps; | |
258 | |
259 // Get a list of page names | |
260 var pageNames = data.appPageNames; | |
261 | |
262 function stringListIsEmpty(list) { | |
263 for (var i = 0; i < list.length; i++) { | |
264 if (list[i]) | |
265 return false; | |
266 } | |
267 return true; | |
268 } | |
269 | |
270 // Sort by launch index | |
271 apps.sort(function(a, b) { | |
272 return a.app_launch_index - b.app_launch_index; | |
273 }); | |
274 | |
275 // An app to animate (in case it was just installed). | |
276 var highlightApp; | |
277 | |
278 // Add the apps, creating pages as necessary | |
279 for (var i = 0; i < apps.length; i++) { | |
280 var app = apps[i]; | |
281 var pageIndex = (app.page_index || 0); | |
282 while (pageIndex >= this.appsPages.length) { | |
283 var pageName = localStrings.getString('appDefaultPageName'); | |
284 if (this.appsPages.length < pageNames.length) | |
285 pageName = pageNames[this.appsPages.length]; | |
286 | |
287 var origPageCount = this.appsPages.length; | |
288 this.appendTilePage(new ntp4.AppsPage(), pageName, true); | |
289 // Confirm that appsPages is a live object, updated when a new page is | |
290 // added (otherwise we'd have an infinite loop) | |
291 assert(this.appsPages.length == origPageCount + 1, | |
292 'expected new page'); | |
293 } | |
294 | |
295 if (app.id == this.highlightAppId) | |
296 highlightApp = app; | |
297 else | |
298 this.appsPages[pageIndex].appendApp(app); | |
299 } | |
300 | |
301 ntp4.AppsPage.setPromo(data.showPromo ? data : null); | |
302 | |
303 // Tell the slider about the pages. | |
304 this.updateSliderCards(); | |
305 | |
306 if (highlightApp) | |
307 this.appAdded(highlightApp, true); | |
308 | |
309 // Mark the current page. | |
310 this.cardSlider.currentCardValue.navigationDot.classList.add('selected'); | |
311 logEvent('apps.layout: ' + (Date.now() - startTime)); | |
312 | |
313 document.documentElement.classList.remove('starting-up'); | |
314 }, | |
315 | |
316 /** | |
317 * Called by chrome when a new app has been added to chrome or has been | |
318 * enabled if previously disabled. | |
319 * @param {Object} appData A data structure full of relevant information for | |
320 * the app. | |
321 */ | |
322 appAdded: function(appData, opt_highlight) { | |
323 if (appData.id == this.highlightAppId) { | |
324 opt_highlight = true; | |
325 this.highlightAppId = null; | |
326 } | |
327 | |
328 var pageIndex = appData.page_index || 0; | |
329 | |
330 if (pageIndex >= this.appsPages.length) { | |
331 while (pageIndex >= this.appsPages.length) { | |
332 this.appendTilePage(new ntp4.AppsPage(), | |
333 localStrings.getString('appDefaultPageName'), | |
334 true); | |
335 } | |
336 this.updateSliderCards(); | |
337 } | |
338 | |
339 var page = this.appsPages[pageIndex]; | |
340 var app = $(appData.id); | |
341 if (app) | |
342 app.replaceAppData(appData); | |
343 else | |
344 page.appendApp(appData, opt_highlight); | |
345 }, | |
346 | |
347 /** | |
348 * Callback invoked by chrome whenever an app preference changes. | |
349 * @param {Object} data An object with all the data on available | |
350 * applications. | |
351 */ | |
352 appsPrefChangeCallback: function(data) { | |
353 for (var i = 0; i < data.apps.length; ++i) { | |
354 $(data.apps[i].id).appData = data.apps[i]; | |
355 } | |
356 | |
357 // Set the App dot names. Skip the first and last dots (Most Visited and | |
358 // Bookmarks). | |
359 var dots = this.dotList.getElementsByClassName('dot'); | |
360 // TODO(csilv): Remove this calcluation if/when we remove the flag for | |
361 // for the bookmarks page. | |
362 var start = this.mostVisitedPage ? 1 : 0; | |
363 var length = this.bookmarksPage ? dots.length - 1 : dots.length; | |
364 for (var i = start; i < length; ++i) { | |
365 dots[i].displayTitle = data.appPageNames[i - start] || ''; | |
366 } | |
367 }, | |
368 | |
369 /** | |
370 * Invoked whenever the pages in apps-page-list have changed so that | |
371 * the Slider knows about the new elements. | |
372 */ | |
373 updateSliderCards: function() { | |
374 var pageNo = Math.min(this.cardSlider.currentCard, | |
375 this.tilePages.length - 1); | |
376 this.cardSlider.setCards(Array.prototype.slice.call(this.tilePages), | |
377 pageNo); | |
378 switch (this.shownPage) { | |
379 case templateData['apps_page_id']: | |
380 this.cardSlider.selectCardByValue( | |
381 this.appsPages[Math.min(this.shownPageIndex, | |
382 this.appsPages.length - 1)]); | |
383 break; | |
384 case templateData['bookmarks_page_id']: | |
385 if (this.bookmarksPage) | |
386 this.cardSlider.selectCardByValue(this.bookmarksPage); | |
387 break; | |
388 case templateData['most_visited_page_id']: | |
389 if (this.mostVisitedPage) | |
390 this.cardSlider.selectCardByValue(this.mostVisitedPage); | |
391 break; | |
392 } | |
393 }, | |
394 | |
395 /** | |
396 * Called whenever tiles should be re-arranging themselves out of the way | |
397 * of a moving or insert tile. | |
398 */ | |
399 enterRearrangeMode: function() { | |
400 var tempPage = new ntp4.AppsPage(); | |
401 tempPage.classList.add('temporary'); | |
402 this.appendTilePage(tempPage, | |
403 localStrings.getString('appDefaultPageName'), | |
404 true); | |
405 var tempIndex = Array.prototype.indexOf.call(this.tilePages, tempPage); | |
406 if (this.cardSlider.currentCard >= tempIndex) | |
407 this.cardSlider.currentCard += 1; | |
408 this.updateSliderCards(); | |
409 | |
410 if (ntp4.getCurrentlyDraggingTile().firstChild.canBeRemoved()) | |
411 $('footer').classList.add('showing-trash-mode'); | |
412 }, | |
413 | |
414 /** | |
415 * Invoked whenever some app is released | |
416 * @param {Grabber.Event} e The Grabber RELEASE event. | |
417 */ | |
418 leaveRearrangeMode: function(e) { | |
419 var tempPage = document.querySelector('.tile-page.temporary'); | |
420 var dot = tempPage.navigationDot; | |
421 if (!tempPage.tileCount && tempPage != this.cardSlider.currentCardValue) { | |
422 dot.animateRemove(); | |
423 var tempIndex = Array.prototype.indexOf.call(this.tilePages, tempPage); | |
424 if (this.cardSlider.currentCard > tempIndex) | |
425 this.cardSlider.currentCard -= 1; | |
426 tempPage.parentNode.removeChild(tempPage); | |
427 this.updateSliderCards(); | |
428 } else { | |
429 tempPage.classList.remove('temporary'); | |
430 this.saveAppPageName(tempPage, | |
431 localStrings.getString('appDefaultPageName')); | |
432 } | |
433 | |
434 $('footer').classList.remove('showing-trash-mode'); | |
435 }, | |
436 | |
437 /** | |
438 * Callback for the 'pagelayout' event. | |
439 * @param {Event} e The event. | |
440 */ | |
441 onPageLayout_: function(e) { | |
442 if (Array.prototype.indexOf.call(this.tilePages, e.currentTarget) != | |
443 this.cardSlider.currentCard) { | |
444 return; | |
445 } | |
446 | |
447 this.updatePageSwitchers(); | |
448 }, | |
449 | |
450 /** | |
451 * Adjusts the size and position of the page switchers according to the | |
452 * layout of the current card. | |
453 */ | |
454 updatePageSwitchers: function() { | |
455 if (!this.pageSwitcherStart || !this.pageSwitcherEnd) | |
456 return; | |
457 | |
458 var page = this.cardSlider.currentCardValue; | |
459 | |
460 this.pageSwitcherStart.hidden = !page || | |
461 (this.cardSlider.currentCard == 0); | |
462 this.pageSwitcherEnd.hidden = !page || | |
463 (this.cardSlider.currentCard == this.cardSlider.cardCount - 1); | |
464 | |
465 if (!page) | |
466 return; | |
467 | |
468 var pageSwitcherLeft = isRTL() ? this.pageSwitcherEnd | |
469 : this.pageSwitcherStart; | |
470 var pageSwitcherRight = isRTL() ? this.pageSwitcherStart | |
471 : this.pageSwitcherEnd; | |
472 var scrollbarWidth = page.scrollbarWidth; | |
473 pageSwitcherLeft.style.width = | |
474 (page.sideMargin + 13) + 'px'; | |
475 pageSwitcherLeft.style.left = '0'; | |
476 pageSwitcherRight.style.width = | |
477 (page.sideMargin - scrollbarWidth + 13) + 'px'; | |
478 pageSwitcherRight.style.right = scrollbarWidth + 'px'; | |
479 | |
480 var offsetTop = page.querySelector('.tile-page-content').offsetTop + 'px'; | |
481 pageSwitcherLeft.style.top = offsetTop; | |
482 pageSwitcherRight.style.top = offsetTop; | |
483 pageSwitcherLeft.style.paddingBottom = offsetTop; | |
484 pageSwitcherRight.style.paddingBottom = offsetTop; | |
485 }, | |
486 | |
487 /** | |
488 * Returns the index of the given page. | |
489 * @param {AppsPage} page The AppsPage for we wish to find. | |
490 * @return {number} The index of |page|, or -1 if it is not here. | |
491 */ | |
492 getAppsPageIndex: function(page) { | |
493 return Array.prototype.indexOf.call(this.appsPages, page); | |
494 }, | |
495 | |
496 /** | |
497 * Handler for CARD_CHANGED on cardSlider. | |
498 * @param {Event} e The CARD_CHANGED event. | |
499 */ | |
500 cardChangedHandler: function(e) { | |
501 var page = e.cardSlider.currentCardValue; | |
502 | |
503 // Don't change shownPage until startup is done (and page changes actually | |
504 // reflect user actions). | |
505 if (!document.documentElement.classList.contains('starting-up')) { | |
506 if (page.classList.contains('apps-page')) { | |
507 this.shownPage = templateData['apps_page_id']; | |
508 this.shownPageIndex = this.getAppsPageIndex(page); | |
509 } else if (page.classList.contains('most-visited-page')) { | |
510 this.shownPage = templateData['most_visited_page_id']; | |
511 this.shownPageIndex = 0; | |
512 } else if (page.classList.contains('bookmarks-page')) { | |
513 this.shownPage = templateData['bookmarks_page_id']; | |
514 this.shownPageIndex = 0; | |
515 } else { | |
516 console.error('unknown page selected'); | |
517 } | |
518 chrome.send('pageSelected', [this.shownPage, this.shownPageIndex]); | |
519 } | |
520 | |
521 // Update the active dot | |
522 var curDot = this.dotList.getElementsByClassName('selected')[0]; | |
523 if (curDot) | |
524 curDot.classList.remove('selected'); | |
525 page.navigationDot.classList.add('selected'); | |
526 this.updatePageSwitchers(); | |
527 }, | |
528 | |
529 /* | |
530 * Save the name of an app page. | |
531 * Store the app page name into the preferences store. | |
532 * @param {AppsPage} appPage The app page for which we wish to save. | |
533 * @param {string} name The name of the page. | |
534 */ | |
535 saveAppPageName: function(appPage, name) { | |
536 var index = this.getAppsPageIndex(appPage); | |
537 assert(index != -1); | |
538 chrome.send('saveAppPageName', [name, index]); | |
539 }, | |
540 | |
541 /** | |
542 * Window resize handler. | |
543 * @private | |
544 */ | |
545 onWindowResize_: function(e) { | |
546 this.cardSlider.resize(this.sliderFrame.offsetWidth); | |
547 this.updatePageSwitchers(); | |
548 }, | |
549 | |
550 /** | |
551 * Handler for key events on the page. Ctrl-Arrow will switch the visible | |
552 * page. | |
553 * @param {Event} e The KeyboardEvent. | |
554 */ | |
555 onDocKeyDown: function(e) { | |
556 if (!e.ctrlKey || e.altKey || e.metaKey || e.shiftKey) | |
557 return; | |
558 | |
559 var direction = 0; | |
560 if (e.keyIdentifier == 'Left') | |
561 direction = -1; | |
562 else if (e.keyIdentifier == 'Right') | |
563 direction = 1; | |
564 else | |
565 return; | |
566 | |
567 var cardIndex = | |
568 (this.cardSlider.currentCard + direction + | |
569 this.cardSlider.cardCount) % this.cardSlider.cardCount; | |
570 this.cardSlider.selectCard(cardIndex, true); | |
571 | |
572 e.stopPropagation(); | |
573 } | |
574 }; | |
575 | |
576 /** | |
577 * Simple common assertion API | |
578 * @param {*} condition The condition to test. Note that this may be used to | |
579 * test whether a value is defined or not, and we don't want to force a | |
580 * cast to Boolean. | |
581 * @param {string=} opt_message A message to use in any error. | |
582 */ | |
583 function assert(condition, opt_message) { | |
Evan Stade
2011/11/07 23:59:20
some of these functions should go in util.js
xiyuan
2011/11/08 21:09:18
Done. Moved assert, getRequiredEleemnt and isRTL i
| |
584 'use strict'; | |
585 if (!condition) { | |
586 var msg = 'Assertion failed'; | |
587 if (opt_message) | |
588 msg = msg + ': ' + opt_message; | |
589 throw new Error(msg); | |
590 } | |
591 } | |
592 | |
593 /** | |
594 * Get an element that's known to exist by its ID. We use this instead of just | |
595 * calling getElementById and not checking the result because this lets us | |
596 * satisfy the JSCompiler type system. | |
597 * @param {string} id The identifier name. | |
598 * @return {!Element} the Element. | |
599 */ | |
600 function getRequiredElement(id) { | |
601 var element = document.getElementById(id); | |
602 assert(element, 'Missing required element: ' + id); | |
603 return element; | |
604 } | |
605 | |
606 /** | |
607 * Wrapper to forward the callback to corresponding PageListView member. | |
608 */ | |
609 function getAppsCallback(data) { | |
610 instance.getAppsCallback(data); | |
611 } | |
612 | |
613 /** | |
614 * Wrapper to forward the callback to corresponding PageListView member. | |
615 */ | |
616 function appAdded(appData, opt_highlight) { | |
617 instance.appAdded(appData, opt_highlight); | |
618 } | |
619 | |
620 /** | |
621 * Sets that an app should be highlighted if it is added. Called right before | |
622 * appAdded for new installs. | |
623 */ | |
624 function setAppToBeHighlighted(appId) { | |
625 instance.highlightAppId = appId; | |
626 } | |
627 | |
628 /** | |
629 * Called by chrome when an existing app has been disabled or | |
630 * removed/uninstalled from chrome. | |
631 * @param {Object} appData A data structure full of relevant information for | |
632 * the app. | |
633 * @param {boolean} isUninstall True if the app is being uninstalled; | |
634 * false if the app is being disabled. | |
635 */ | |
636 function appRemoved(appData, isUninstall) { | |
637 var app = $(appData.id); | |
638 assert(app, 'trying to remove an app that doesn\'t exist'); | |
639 | |
640 if (!isUninstall) | |
641 app.replaceAppData(appData); | |
642 else | |
643 app.remove(); | |
644 } | |
645 | |
646 /** | |
647 * Wrapper to forward the callback to corresponding PageListView member. | |
648 */ | |
649 function appsPrefChangeCallback(data) { | |
650 instance.appsPrefChangedCallback(data); | |
651 } | |
652 | |
653 /** | |
654 * Listener for offline status change events. Updates apps that are | |
655 * not offline-enabled to be grayscale if the browser is offline. | |
656 */ | |
657 function updateOfflineEnabledApps() { | |
658 var apps = document.querySelectorAll('.app'); | |
659 for (var i = 0; i < apps.length; ++i) { | |
660 if (apps[i].appData.enabled && !apps[i].appData.offline_enabled) { | |
661 apps[i].setIcon(); | |
662 apps[i].loadIcon(); | |
663 } | |
664 } | |
665 } | |
666 | |
667 function getCardSlider() { | |
668 return instance.cardSlider; | |
669 } | |
670 | |
671 /** | |
672 * Wrapper to forward the callback to corresponding PageListView member. | |
673 */ | |
674 function enterRearrangeMode() { | |
675 instance.enterRearrangeMode(); | |
676 } | |
677 | |
678 /** | |
679 * Wrapper to forward the callback to corresponding PageListView member. | |
680 */ | |
681 function leaveRearrangeMode(e) { | |
682 instance.leaveRearrangeMode(e); | |
683 } | |
684 | |
685 /** | |
686 * Check the directionality of the page. | |
687 * @return {boolean} True if Chrome is running an RTL UI. | |
688 */ | |
689 function isRTL() { | |
690 return document.documentElement.dir == 'rtl'; | |
691 } | |
692 | |
693 /** | |
694 * Wrapper to forward the callback to corresponding PageListView member. | |
695 */ | |
696 function getAppsPageIndex(page) { | |
697 instance.getAppsPageIndex(page); | |
698 } | |
699 | |
700 /** | |
701 * Wrapper to forward the callback to corresponding PageListView member. | |
702 */ | |
703 function saveAppPageName(appPage, name) { | |
704 instance.saveAppPageName(appPage, name); | |
705 } | |
706 | |
707 return { | |
708 appAdded: appAdded, | |
709 appendTilePage: appendTilePage, | |
710 appRemoved: appRemoved, | |
711 appsPrefChangeCallback: appsPrefChangeCallback, | |
712 assert: assert, | |
713 enterRearrangeMode: enterRearrangeMode, | |
714 getAppsCallback: getAppsCallback, | |
715 getAppsPageIndex: getAppsPageIndex, | |
716 getCardSlider: getCardSlider, | |
717 getRequiredElement: getRequiredElement, | |
718 isRTL: isRTL, | |
719 leaveRearrangeMode: leaveRearrangeMode, | |
720 saveAppPageName: saveAppPageName, | |
721 setAppToBeHighlighted: setAppToBeHighlighted, | |
722 updateOfflineEnabledApps: updateOfflineEnabledApps, | |
723 PageListView: PageListView | |
724 }; | |
725 }); | |
726 | |
727 var appendTilePage = ntp4.appendTilePage; | |
Evan Stade
2011/11/07 23:59:20
are you planning to use all of this in the aura ho
xiyuan
2011/11/08 21:09:18
I only need appsPrefChangeCallback and getAppsCall
| |
728 var appsPrefChangeCallback = ntp4.appsPrefChangeCallback; | |
729 var assert = ntp4.assert; | |
730 var getAppsCallback = ntp4.getAppsCallback; | |
731 var getRequiredElement = ntp4.getRequiredElement; | |
732 | |
733 window.addEventListener('online', ntp4.updateOfflineEnabledApps); | |
734 window.addEventListener('offline', ntp4.updateOfflineEnabledApps); | |
OLD | NEW |