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 cr.define('ntp4', function() { | 5 cr.define('ntp4', function() { |
6 'use strict'; | 6 'use strict'; |
7 | 7 |
8 var localStrings = new LocalStrings; | 8 var localStrings = new LocalStrings; |
9 | 9 |
10 var APP_LAUNCH = { | 10 var APP_LAUNCH = { |
(...skipping 17 matching lines...) Expand all Loading... | |
28 var DRAG_SOURCE_LIMIT = DRAG_SOURCE.OUTSIDE_NTP + 1; | 28 var DRAG_SOURCE_LIMIT = DRAG_SOURCE.OUTSIDE_NTP + 1; |
29 | 29 |
30 /** | 30 /** |
31 * App context menu. The class is designed to be used as a singleton with | 31 * App context menu. The class is designed to be used as a singleton with |
32 * the app that is currently showing a context menu stored in this.app_. | 32 * the app that is currently showing a context menu stored in this.app_. |
33 * @constructor | 33 * @constructor |
34 */ | 34 */ |
35 function AppContextMenu() { | 35 function AppContextMenu() { |
36 this.__proto__ = AppContextMenu.prototype; | 36 this.__proto__ = AppContextMenu.prototype; |
37 this.initialize(); | 37 this.initialize(); |
38 }; | 38 } |
39 cr.addSingletonGetter(AppContextMenu); | 39 cr.addSingletonGetter(AppContextMenu); |
40 | 40 |
41 AppContextMenu.prototype = { | 41 AppContextMenu.prototype = { |
42 initialize: function() { | 42 initialize: function() { |
43 var menu = new cr.ui.Menu; | 43 var menu = new cr.ui.Menu; |
44 cr.ui.decorate(menu, cr.ui.Menu); | 44 cr.ui.decorate(menu, cr.ui.Menu); |
45 menu.classList.add('app-context-menu'); | 45 menu.classList.add('app-context-menu'); |
46 this.menu = menu; | 46 this.menu = menu; |
47 | 47 |
48 this.launch_ = this.appendMenuItem_(); | 48 this.launch_ = this.appendMenuItem_(); |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
268 | 268 |
269 /** | 269 /** |
270 * Sets the color of the favicon dominant color bar. | 270 * Sets the color of the favicon dominant color bar. |
271 * @param {string} color The css-parsable value for the color. | 271 * @param {string} color The css-parsable value for the color. |
272 */ | 272 */ |
273 set stripeColor(color) { | 273 set stripeColor(color) { |
274 this.querySelector('.color-stripe').style.backgroundColor = color; | 274 this.querySelector('.color-stripe').style.backgroundColor = color; |
275 }, | 275 }, |
276 | 276 |
277 /** | 277 /** |
278 * Removes the app tile from the page. Should be called after the app has | |
279 * been uninstalled. | |
280 */ | |
281 remove: function() { | |
282 // Unset the ID immediately, because the app is already gone. But leave | |
283 // the tile on the page as it animates out. | |
284 this.id = ''; | |
285 this.tile.doRemove(); | |
286 }, | |
287 | |
288 /** | |
289 * Set the URL of the icon from |appData_|. This won't actually show the | 278 * Set the URL of the icon from |appData_|. This won't actually show the |
290 * icon until loadIcon() is called (for performance reasons; we don't want | 279 * icon until loadIcon() is called (for performance reasons; we don't want |
291 * to load icons until we have to). | 280 * to load icons until we have to). |
292 */ | 281 */ |
293 setIcon: function() { | 282 setIcon: function() { |
294 var src = this.useSmallIcon_ ? this.appData_.icon_small : | 283 var src = this.useSmallIcon_ ? this.appData_.icon_small : |
295 this.appData_.icon_big; | 284 this.appData_.icon_big; |
296 if (!this.appData_.enabled || | 285 if (!this.appData_.enabled || |
297 (!this.appData_.offline_enabled && !navigator.onLine)) { | 286 (!this.appData_.offline_enabled && !navigator.onLine)) { |
298 src += '?grayscale=true'; | 287 src += '?grayscale=true'; |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
582 canBeRemoved: function() { | 571 canBeRemoved: function() { |
583 return this.appData_.can_uninstall; | 572 return this.appData_.can_uninstall; |
584 }, | 573 }, |
585 | 574 |
586 /** | 575 /** |
587 * Uninstalls the app after it's been dropped on the trash. | 576 * Uninstalls the app after it's been dropped on the trash. |
588 */ | 577 */ |
589 removeFromChrome: function() { | 578 removeFromChrome: function() { |
590 chrome.send('uninstallApp', [this.appData_.id, true]); | 579 chrome.send('uninstallApp', [this.appData_.id, true]); |
591 this.tile.tilePage.removeTile(this.tile, true); | 580 this.tile.tilePage.removeTile(this.tile, true); |
592 | |
593 if (this.currentBubbleShowing_) | 581 if (this.currentBubbleShowing_) |
594 currentBubbleShowing_.hide(); | 582 currentBubbleShowing_.hide(); |
595 }, | 583 }, |
596 | 584 |
597 /** | 585 /** |
598 * Called when a drag is starting on the tile. Updates dataTransfer with | 586 * Called when a drag is starting on the tile. Updates dataTransfer with |
599 * data for this tile. | 587 * data for this tile. |
600 */ | 588 */ |
601 setDragData: function(dataTransfer) { | 589 setDragData: function(dataTransfer) { |
602 dataTransfer.setData('Text', this.appData_.title); | 590 dataTransfer.setData('Text', this.appData_.title); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
640 | 628 |
641 AppsPage.prototype = { | 629 AppsPage.prototype = { |
642 __proto__: TilePage.prototype, | 630 __proto__: TilePage.prototype, |
643 | 631 |
644 initialize: function() { | 632 initialize: function() { |
645 this.classList.add('apps-page'); | 633 this.classList.add('apps-page'); |
646 | 634 |
647 this.addEventListener('cardselected', this.onCardSelected_); | 635 this.addEventListener('cardselected', this.onCardSelected_); |
648 }, | 636 }, |
649 | 637 |
638 /** @inheritDoc */ | |
639 addTileAt: function(contents, index, animate) { | |
Evan Stade
2011/12/08 02:34:56
would rather you create an event 'tileAdded' that
Dan Beam
2011/12/08 04:46:18
Done.
| |
640 if (contents instanceof App && this.classList.contains('selected-card')) | |
Evan Stade
2011/12/08 02:34:56
when is the first half of this ever false? probabl
Dan Beam
2011/12/08 04:46:18
Done.
Yeah, I mistakenly thought we allowed non-A
| |
641 contents.loadIcon(); | |
642 TilePage.prototype.addTileAt.call(this, contents, index, animate); | |
643 }, | |
644 | |
650 /** | 645 /** |
651 * Creates an app DOM element and places it at the last position on the | 646 * Creates an app DOM element and places it at the last position on the |
652 * page. | 647 * page. |
653 * @param {Object} appData The data object that describes the app. | 648 * @param {Object} appData The data object that describes the app. |
654 * @param {?boolean} animate If true, the app tile plays an animation. | 649 * @param {boolean=} animate If true, the app tile plays an animation. |
655 */ | 650 */ |
656 appendApp: function(appData, animate) { | 651 appendApp: function(appData, animate) { |
657 if (animate) { | 652 if (animate) { |
658 // Select the page and scroll all the way down so the animation is | 653 // Select the page and scroll all the way down so the animation is |
659 // visible. | 654 // visible. |
660 ntp4.getCardSlider().selectCardByValue(this); | 655 ntp4.getCardSlider().selectCardByValue(this); |
661 this.content_.scrollTop = this.content_.scrollHeight; | 656 this.content_.scrollTop = this.content_.scrollHeight; |
662 } | 657 } |
663 var app = new App(appData); | 658 this.appendTile(new App(appData), animate); |
664 if (this.classList.contains('selected-card')) | |
665 app.loadIcon(); | |
666 this.appendTile(app, animate); | |
667 }, | 659 }, |
668 | 660 |
669 /** | 661 /** |
670 * Handler for 'cardselected' event, fired when |this| is selected. The | 662 * Handler for 'cardselected' event, fired when |this| is selected. The |
671 * first time this is called, we load all the app icons. | 663 * first time this is called, we load all the app icons. |
672 * @private | 664 * @private |
673 */ | 665 */ |
674 onCardSelected_: function(e) { | 666 onCardSelected_: function(e) { |
675 var apps = this.querySelectorAll('.app.icon-loading'); | 667 var apps = this.querySelectorAll('.app.icon-loading'); |
676 for (var i = 0; i < apps.length; i++) { | 668 for (var i = 0; i < apps.length; i++) { |
(...skipping 18 matching lines...) Expand all Loading... | |
695 (e.dataTransfer && e.dataTransfer.types.indexOf('url') != -1); | 687 (e.dataTransfer && e.dataTransfer.types.indexOf('url') != -1); |
696 }, | 688 }, |
697 | 689 |
698 /** @inheritDoc */ | 690 /** @inheritDoc */ |
699 addDragData: function(dataTransfer, index) { | 691 addDragData: function(dataTransfer, index) { |
700 var sourceId = -1; | 692 var sourceId = -1; |
701 var currentlyDraggingTile = ntp4.getCurrentlyDraggingTile(); | 693 var currentlyDraggingTile = ntp4.getCurrentlyDraggingTile(); |
702 if (currentlyDraggingTile) { | 694 if (currentlyDraggingTile) { |
703 var tileContents = currentlyDraggingTile.firstChild; | 695 var tileContents = currentlyDraggingTile.firstChild; |
704 if (tileContents.classList.contains('app')) { | 696 if (tileContents.classList.contains('app')) { |
705 sourceId = currentlyDraggingTile.tilePage == this ? | 697 var originalPage = currentlyDraggingTile.tilePage; |
706 DRAG_SOURCE.SAME_APPS_PANE : DRAG_SOURCE.OTHER_APPS_PANE; | 698 var samePageDrag = originalPage == this; |
707 this.tileGrid_.insertBefore( | 699 sourceId = samePageDrag ? DRAG_SOURCE.SAME_APPS_PANE : |
708 currentlyDraggingTile, | 700 DRAG_SOURCE.OTHER_APPS_PANE; |
709 this.tileElements_[index]); | 701 this.tileGrid_.insertBefore(currentlyDraggingTile, |
702 this.tileElements_[index]); | |
710 this.tileMoved(currentlyDraggingTile); | 703 this.tileMoved(currentlyDraggingTile); |
704 if (!samePageDrag) | |
705 originalPage.fireRemovedEvent(true); | |
706 if (originalPage) | |
707 originalPage.cleanupDrag(); | |
711 } else if (currentlyDraggingTile.querySelector('.most-visited')) { | 708 } else if (currentlyDraggingTile.querySelector('.most-visited')) { |
712 this.generateAppForLink(tileContents.data); | 709 this.generateAppForLink(tileContents.data); |
713 sourceId = DRAG_SOURCE.MOST_VISITED_PANE; | 710 sourceId = DRAG_SOURCE.MOST_VISITED_PANE; |
714 } | 711 } |
715 } else { | 712 } else { |
716 this.addOutsideData_(dataTransfer, index); | 713 this.addOutsideData_(dataTransfer, index); |
717 sourceId = DRAG_SOURCE.OUTSIDE_NTP; | 714 sourceId = DRAG_SOURCE.OUTSIDE_NTP; |
718 } | 715 } |
719 | 716 |
720 assert(sourceId != -1); | 717 assert(sourceId != -1); |
(...skipping 25 matching lines...) Expand all Loading... | |
746 } | 743 } |
747 | 744 |
748 // Make sure title is >=1 and <=45 characters for Chrome app limits. | 745 // Make sure title is >=1 and <=45 characters for Chrome app limits. |
749 if (!title) | 746 if (!title) |
750 title = url; | 747 title = url; |
751 if (title.length > 45) | 748 if (title.length > 45) |
752 title = title.substring(0, 45); | 749 title = title.substring(0, 45); |
753 var data = {url: url, title: title}; | 750 var data = {url: url, title: title}; |
754 | 751 |
755 // Synthesize an app. | 752 // Synthesize an app. |
756 this.generateAppForLink(data); | 753 this.generateAppForLink(data, index); |
757 }, | 754 }, |
758 | 755 |
759 /** | 756 /** |
760 * Creates a new crx-less app manifest and installs it. | 757 * Creates a new crx-less app manifest and installs it. |
761 * @param {Object} data The data object describing the link. Must have |url| | 758 * @param {Object} data The data object describing the link. Must have |url| |
762 * and |title| members. | 759 * and |title| members. |
763 * TODO(estade): pass along an index. | 760 * @param {number} index The index at which to insert the newly generated |
Evan Stade
2011/12/08 02:34:56
just remove the todo
Dan Beam
2011/12/08 02:40:54
Done. (see newer patch set)
| |
761 * app (when it's done being created). | |
764 */ | 762 */ |
765 generateAppForLink: function(data) { | 763 generateAppForLink: function(data, index) { |
766 assert(data.url != undefined); | 764 assert(data.url != undefined); |
767 assert(data.title != undefined); | 765 assert(data.title != undefined); |
768 var pageIndex = ntp4.getAppsPageIndex(this); | 766 chrome.send('generateAppForLink', |
769 chrome.send('generateAppForLink', [data.url, data.title, pageIndex]); | 767 [data.url, data.title, ntp4.getAppsPageIndex(this), index]); |
770 }, | 768 }, |
771 | 769 |
772 /** @inheritDoc */ | 770 /** @inheritDoc */ |
773 tileMoved: function(draggedTile) { | 771 tileMoved: function(draggedTile) { |
774 if (!(draggedTile.firstChild instanceof App)) | 772 if (!(draggedTile.firstChild instanceof App)) |
775 return; | 773 return; |
776 | 774 |
777 var pageIndex = ntp4.getAppsPageIndex(this); | 775 chrome.send('setPageIndex', [draggedTile.firstChild.appId, |
778 chrome.send('setPageIndex', [draggedTile.firstChild.appId, pageIndex]); | 776 ntp4.getAppsPageIndex(this)]); |
Evan Stade
2011/12/08 02:34:56
don't make this kind of stylistic change. You're n
Dan Beam
2011/12/08 04:46:18
Done.
Dan Beam
2011/12/08 04:46:18
OK, I didn't mean to do this I just re-wrote this
| |
779 | 777 |
780 var appIds = []; | 778 var appIds = []; |
781 for (var i = 0; i < this.tileElements_.length; i++) { | 779 for (var i = 0; i < this.tileElements_.length; i++) { |
782 var tileContents = this.tileElements_[i].firstChild; | 780 var tileContents = this.tileElements_[i].firstChild; |
783 if (tileContents instanceof App) | 781 if (tileContents instanceof App) |
784 appIds.push(tileContents.appId); | 782 appIds.push(tileContents.appId); |
785 } | 783 } |
786 | 784 |
787 chrome.send('reorderApps', [draggedTile.firstChild.appId, appIds]); | 785 chrome.send('reorderApps', [draggedTile.firstChild.appId, appIds]); |
788 }, | 786 }, |
(...skipping 14 matching lines...) Expand all Loading... | |
803 store.setAppsPromoData(data); | 801 store.setAppsPromoData(data); |
804 }; | 802 }; |
805 | 803 |
806 /** | 804 /** |
807 * Launches the specified app using the APP_LAUNCH_NTP_APP_RE_ENABLE | 805 * Launches the specified app using the APP_LAUNCH_NTP_APP_RE_ENABLE |
808 * histogram. This should only be invoked from the AppLauncherHandler. | 806 * histogram. This should only be invoked from the AppLauncherHandler. |
809 * @param {String} appID The ID of the app. | 807 * @param {String} appID The ID of the app. |
810 */ | 808 */ |
811 function launchAppAfterEnable(appId) { | 809 function launchAppAfterEnable(appId) { |
812 chrome.send('launchApp', [appId, APP_LAUNCH.NTP_APP_RE_ENABLE]); | 810 chrome.send('launchApp', [appId, APP_LAUNCH.NTP_APP_RE_ENABLE]); |
813 }; | 811 } |
814 | 812 |
815 function appNotificationChanged(id, notification) { | 813 function appNotificationChanged(id, notification) { |
816 var app = $(id); | 814 var app = $(id); |
817 // The app might have been uninstalled, or notifications might be disabled. | 815 // The app might have been uninstalled, or notifications might be disabled. |
818 if (app && !app.appData.notifications_disabled) | 816 if (app && !app.appData.notifications_disabled) |
819 app.setupNotification_(notification); | 817 app.setupNotification_(notification); |
820 }; | 818 } |
821 | 819 |
822 return { | 820 return { |
823 APP_LAUNCH: APP_LAUNCH, | 821 APP_LAUNCH: APP_LAUNCH, |
824 appNotificationChanged: appNotificationChanged, | 822 appNotificationChanged: appNotificationChanged, |
825 AppsPage: AppsPage, | 823 AppsPage: AppsPage, |
826 launchAppAfterEnable: launchAppAfterEnable, | 824 launchAppAfterEnable: launchAppAfterEnable, |
827 }; | 825 }; |
828 }); | 826 }); |
829 | 827 |
830 // TODO(estade): update the content handlers to use ntp namespace instead of | 828 // TODO(estade): update the content handlers to use ntp namespace instead of |
831 // making these global. | 829 // making these global. |
832 var appNotificationChanged = ntp4.appNotificationChanged; | 830 var appNotificationChanged = ntp4.appNotificationChanged; |
833 var launchAppAfterEnable = ntp4.launchAppAfterEnable; | 831 var launchAppAfterEnable = ntp4.launchAppAfterEnable; |
OLD | NEW |