| 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 var MAX_APPS_PER_ROW = []; | 5 var MAX_APPS_PER_ROW = []; |
| 6 MAX_APPS_PER_ROW[LayoutMode.SMALL] = 4; | 6 MAX_APPS_PER_ROW[LayoutMode.SMALL] = 4; |
| 7 MAX_APPS_PER_ROW[LayoutMode.NORMAL] = 6; | 7 MAX_APPS_PER_ROW[LayoutMode.NORMAL] = 6; |
| 8 | 8 |
| 9 function getAppsCallback(data) { | 9 function getAppsCallback(data) { |
| 10 logEvent('received apps'); | 10 logEvent('received apps'); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 function appsPrefChangeCallback(data) { | 143 function appsPrefChangeCallback(data) { |
| 144 // Currently the only pref that is watched is the launch type. | 144 // Currently the only pref that is watched is the launch type. |
| 145 data.apps.forEach(function(app) { | 145 data.apps.forEach(function(app) { |
| 146 var appLink = document.querySelector('.app a[app-id=' + app['id'] + ']'); | 146 var appLink = document.querySelector('.app a[app-id=' + app['id'] + ']'); |
| 147 if (appLink) | 147 if (appLink) |
| 148 appLink.setAttribute('launch-type', app['launch_type']); | 148 appLink.setAttribute('launch-type', app['launch_type']); |
| 149 }); | 149 }); |
| 150 } | 150 } |
| 151 | 151 |
| 152 function appNotificationChanged(id, lastNotification) { | 152 function appNotificationChanged(id, lastNotification) { |
| 153 // TODO(asargent/finnur) use this when we hook up notifications into the NTP. | 153 // TODO(asargent/finnur): Don't update all apps at once, do it in a more |
| 154 // fine grained way. |
| 155 chrome.send('getApps'); |
| 154 } | 156 } |
| 155 | 157 |
| 156 // Launches the specified app using the APP_LAUNCH_NTP_APP_RE_ENABLE histogram. | 158 // Launches the specified app using the APP_LAUNCH_NTP_APP_RE_ENABLE histogram. |
| 157 // This should only be invoked from the AppLauncherHandler. | 159 // This should only be invoked from the AppLauncherHandler. |
| 158 function launchAppAfterEnable(appId) { | 160 function launchAppAfterEnable(appId) { |
| 159 chrome.send('launchApp', [appId, APP_LAUNCH.NTP_APP_RE_ENABLE]); | 161 chrome.send('launchApp', [appId, APP_LAUNCH.NTP_APP_RE_ENABLE]); |
| 160 } | 162 } |
| 161 | 163 |
| 164 // Shows the notification bubble for a given app (the one clicked on). |
| 165 function showNotificationBubble(event) { |
| 166 var item = findAncestorByClass(event.target, 'app-anchor'); |
| 167 var title = item.getAttribute('notification-title'); |
| 168 var message = item.getAttribute('notification-message'); |
| 169 var link = item.getAttribute('notification-link'); |
| 170 var link_message = item.getAttribute('notification-link-message'); |
| 171 |
| 172 if (!title || !message) |
| 173 return; |
| 174 |
| 175 // Set the content to the right text. |
| 176 $('app-notification-title').textContent = title; |
| 177 $('app-notification-message').textContent = message; |
| 178 $('app-notification-link').href = link; |
| 179 $('app-notification-link').textContent = link_message; |
| 180 |
| 181 var target = event.target; |
| 182 while (target.parentElement && target.tagName != "A") { |
| 183 target = target.parentElement; |
| 184 } |
| 185 |
| 186 // Move the bubble to the right location. |
| 187 var bubble = $('app-notification-bubble'); |
| 188 var x = target.parentElement.offsetLeft + |
| 189 target.parentElement.offsetWidth - 20; |
| 190 var y = target.parentElement.offsetTop + 20; |
| 191 bubble.style.left = x + "px"; |
| 192 bubble.style.top = y + "px"; |
| 193 |
| 194 // Move the arrow and shadow to the right location. |
| 195 var arrow = $('arrow-contents'); |
| 196 var border = $('arrow-border'); |
| 197 var shadow = $('arrow-shadow'); |
| 198 y += 26; |
| 199 x -= arrow.style.width + 23; |
| 200 arrow.style.left = x + "px"; |
| 201 arrow.style.top = y + "px"; |
| 202 x -= 1; |
| 203 border.style.left = x + "px"; |
| 204 border.style.top = y + "px"; |
| 205 x -= 1; |
| 206 shadow.style.left = x + "px"; |
| 207 shadow.style.top = y + "px"; |
| 208 |
| 209 // Animate the bubble into view. |
| 210 bubble.classList.add("notification-bubble-opened"); |
| 211 bubble.classList.remove("notification-bubble-closed"); |
| 212 arrow.classList.add("notification-bubble-opened"); |
| 213 arrow.classList.remove("notification-bubble-closed"); |
| 214 border.classList.add("notification-bubble-opened"); |
| 215 border.classList.remove("notification-bubble-closed"); |
| 216 shadow.classList.add("notification-bubble-opened"); |
| 217 shadow.classList.remove("notification-bubble-closed"); |
| 218 |
| 219 bubble.focus(); |
| 220 } |
| 221 |
| 222 // Hide the notification bubble. |
| 223 function hideNotificationBubble(event) { |
| 224 // This will fade the bubble out of existence. |
| 225 $('app-notification-bubble').classList.add("notification-bubble-closed"); |
| 226 $('app-notification-bubble').classList.remove("notification-bubble-opened"); |
| 227 $('arrow-border').classList.add("notification-bubble-closed"); |
| 228 $('arrow-border').classList.remove("notification-bubble-opened"); |
| 229 $('arrow-shadow').classList.add("notification-bubble-closed"); |
| 230 $('arrow-shadow').classList.remove("notification-bubble-opened"); |
| 231 $('arrow-contents').classList.add("notification-bubble-closed"); |
| 232 $('arrow-contents').classList.remove("notification-bubble-opened"); |
| 233 } |
| 234 |
| 162 var apps = (function() { | 235 var apps = (function() { |
| 163 | 236 |
| 164 function createElement(app) { | 237 function createElement(app) { |
| 165 var div = document.createElement('div'); | 238 var div = document.createElement('div'); |
| 166 div.className = 'app'; | 239 div.className = 'app'; |
| 167 | 240 |
| 168 var a = div.appendChild(document.createElement('a')); | 241 var a = div.appendChild(document.createElement('a')); |
| 242 a.className = 'app-anchor'; |
| 169 a.setAttribute('app-id', app['id']); | 243 a.setAttribute('app-id', app['id']); |
| 170 a.setAttribute('launch-type', app['launch_type']); | 244 a.setAttribute('launch-type', app['launch_type']); |
| 245 if (typeof(app['notification']) != "undefined") { |
| 246 a.setAttribute('notification-title', app['notification']['title']); |
| 247 a.setAttribute('notification-message', app['notification']['body']); |
| 248 if (typeof(app['notification']['linkUrl']) != "undefined" && |
| 249 typeof(app['notification']['linkText']) != "undefined") { |
| 250 a.setAttribute('notification-link', app['notification']['linkUrl']); |
| 251 a.setAttribute('notification-link-message', |
| 252 app['notification']['linkText']); |
| 253 } |
| 254 } |
| 171 a.draggable = false; | 255 a.draggable = false; |
| 172 a.xtitle = a.textContent = app['name']; | |
| 173 a.href = app['launch_url']; | 256 a.href = app['launch_url']; |
| 174 | 257 |
| 258 var span = a.appendChild(document.createElement('span')); |
| 259 span.textContent = app['name']; |
| 260 |
| 261 span = a.appendChild(document.createElement('span')); |
| 262 span.className = "app_notification"; |
| 263 span.textContent = |
| 264 typeof(app['notification']) != "undefined" && |
| 265 typeof(app['notification']['title']) != "undefined" ? |
| 266 app['notification']['title'] : ""; |
| 267 span.onclick = handleClick; |
| 268 |
| 269 $("app-notification-close").onclick = hideNotificationBubble; |
| 270 $("app-notification-bubble").setAttribute("tabIndex", 0); |
| 271 $("app-notification-bubble").onblur = hideNotificationBubble; |
| 272 |
| 175 return div; | 273 return div; |
| 176 } | 274 } |
| 177 | 275 |
| 178 /** | 276 /** |
| 179 * Launches an application. | 277 * Launches an application. |
| 180 * @param {string} appId Application to launch. | 278 * @param {string} appId Application to launch. |
| 181 * @param {MouseEvent} opt_mouseEvent Mouse event from the click that | 279 * @param {MouseEvent} opt_mouseEvent Mouse event from the click that |
| 182 * triggered the launch, used to detect modifier keys that change | 280 * triggered the launch, used to detect modifier keys that change |
| 183 * the tab's disposition. | 281 * the tab's disposition. |
| 184 */ | 282 */ |
| (...skipping 27 matching lines...) Expand all Loading... |
| 212 return APP_LAUNCH.NTP_APPS_COLLAPSED; | 310 return APP_LAUNCH.NTP_APPS_COLLAPSED; |
| 213 else | 311 else |
| 214 return APP_LAUNCH.NTP_APPS_MAXIMIZED; | 312 return APP_LAUNCH.NTP_APPS_MAXIMIZED; |
| 215 } | 313 } |
| 216 | 314 |
| 217 /** | 315 /** |
| 218 * @this {!HTMLAnchorElement} | 316 * @this {!HTMLAnchorElement} |
| 219 */ | 317 */ |
| 220 function handleClick(e) { | 318 function handleClick(e) { |
| 221 var appId = e.currentTarget.getAttribute('app-id'); | 319 var appId = e.currentTarget.getAttribute('app-id'); |
| 320 if (appId == null) { |
| 321 showNotificationBubble(e); |
| 322 e.stopPropagation(); |
| 323 return false; |
| 324 } |
| 325 |
| 222 if (!appDragAndDrop.isDragging()) | 326 if (!appDragAndDrop.isDragging()) |
| 223 launchApp(appId, e); | 327 launchApp(appId, e); |
| 224 return false; | 328 return false; |
| 225 } | 329 } |
| 226 | 330 |
| 227 // Keep in sync with LaunchType in extension_prefs.h | 331 // Keep in sync with LaunchType in extension_prefs.h |
| 228 var LaunchType = { | 332 var LaunchType = { |
| 229 LAUNCH_PINNED: 0, | 333 LAUNCH_PINNED: 0, |
| 230 LAUNCH_REGULAR: 1, | 334 LAUNCH_REGULAR: 1, |
| 231 LAUNCH_FULLSCREEN: 2, | 335 LAUNCH_FULLSCREEN: 2, |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 | 418 |
| 315 document.addEventListener('canExecute', function(e) { | 419 document.addEventListener('canExecute', function(e) { |
| 316 switch (e.command.id) { | 420 switch (e.command.id) { |
| 317 case 'apps-options-command': | 421 case 'apps-options-command': |
| 318 e.canExecute = currentApp && currentApp['options_url']; | 422 e.canExecute = currentApp && currentApp['options_url']; |
| 319 break; | 423 break; |
| 320 case 'apps-launch-command': | 424 case 'apps-launch-command': |
| 321 e.canExecute = true; | 425 e.canExecute = true; |
| 322 break; | 426 break; |
| 323 case 'apps-uninstall-command': | 427 case 'apps-uninstall-command': |
| 324 e.canExecute = !currentApp['can_uninstall']; | 428 e.canExecute = currentApp && !currentApp['can_uninstall']; |
| 325 break; | 429 break; |
| 326 } | 430 } |
| 327 }); | 431 }); |
| 328 | 432 |
| 329 // Moves the element at position |from| in array |arr| to position |to|. | 433 // Moves the element at position |from| in array |arr| to position |to|. |
| 330 function arrayMove(arr, from, to) { | 434 function arrayMove(arr, from, to) { |
| 331 var element = arr.splice(from, 1); | 435 var element = arr.splice(from, 1); |
| 332 arr.splice(to, 0, element[0]); | 436 arr.splice(to, 0, element[0]); |
| 333 } | 437 } |
| 334 | 438 |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 677 return; | 781 return; |
| 678 } | 782 } |
| 679 }, | 783 }, |
| 680 | 784 |
| 681 showImages: function() { | 785 showImages: function() { |
| 682 $('apps-content').classList.add('visible'); | 786 $('apps-content').classList.add('visible'); |
| 683 clearTimeout(this.imageTimer); | 787 clearTimeout(this.imageTimer); |
| 684 }, | 788 }, |
| 685 | 789 |
| 686 createElement: function(app) { | 790 createElement: function(app) { |
| 791 var container = document.createElement('div'); |
| 687 var div = createElement(app); | 792 var div = createElement(app); |
| 793 container.appendChild(div); |
| 688 var a = div.firstChild; | 794 var a = div.firstChild; |
| 689 | 795 |
| 690 a.onclick = handleClick; | 796 a.onclick = handleClick; |
| 691 a.ping = getAppPingUrl( | 797 a.ping = getAppPingUrl( |
| 692 'PING_BY_ID', this.showPromo, 'NTP_APPS_MAXIMIZED'); | 798 'PING_BY_ID', this.showPromo, 'NTP_APPS_MAXIMIZED'); |
| 693 a.style.backgroundImage = url(app['icon_big']); | 799 a.style.backgroundImage = url(app['icon_big']); |
| 694 if (app.isNew) { | 800 if (app.isNew) { |
| 695 div.setAttribute('new', 'new'); | 801 div.setAttribute('new', 'new'); |
| 696 // Delay changing the attribute a bit to let the page settle down a bit. | 802 // Delay changing the attribute a bit to let the page settle down a bit. |
| 697 setTimeout(function() { | 803 setTimeout(function() { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 712 img.src = app['icon_big']; | 818 img.src = app['icon_big']; |
| 713 | 819 |
| 714 // User cannot change launch options or uninstall component extension. | 820 // User cannot change launch options or uninstall component extension. |
| 715 if (!app['is_component']) { | 821 if (!app['is_component']) { |
| 716 var settingsButton = div.appendChild(new cr.ui.ContextMenuButton); | 822 var settingsButton = div.appendChild(new cr.ui.ContextMenuButton); |
| 717 settingsButton.className = 'app-settings'; | 823 settingsButton.className = 'app-settings'; |
| 718 settingsButton.title = localStrings.getString('appsettings'); | 824 settingsButton.title = localStrings.getString('appsettings'); |
| 719 addContextMenu(div, app); | 825 addContextMenu(div, app); |
| 720 } | 826 } |
| 721 | 827 |
| 722 return div; | 828 if (app.notifications && app.notifications.length > 0) { |
| 829 // Create the notification div below the app icon that is used to |
| 830 // trigger the hidden notification bubble to appear. |
| 831 var notification = document.createElement('div') |
| 832 container.appendChild(notification); |
| 833 var title = document.createElement('span'); |
| 834 title.innerText = app.notifications[0].title; |
| 835 notification.appendChild(title); |
| 836 notification.appendChild(document.createElement('br')); |
| 837 |
| 838 var body = document.createElement('span'); |
| 839 container.appendChild(body); |
| 840 body.innerText = app.notifications[0].body; |
| 841 notification.appendChild(body); |
| 842 if (app.notifications[0].linkUrl) { |
| 843 notification.appendChild(document.createElement('br')); |
| 844 var link = document.createElement('a'); |
| 845 link.href = app.notifications[0].linkUrl; |
| 846 link.innerText = app.notifications[0].linkText ? |
| 847 app.notifications[0].linkText : "link"; |
| 848 notification.appendChild(link); |
| 849 } |
| 850 } |
| 851 |
| 852 return container; |
| 723 }, | 853 }, |
| 724 | 854 |
| 725 createMiniviewElement: function(app) { | 855 createMiniviewElement: function(app) { |
| 726 var span = document.createElement('span'); | 856 var span = document.createElement('span'); |
| 727 var a = span.appendChild(document.createElement('a')); | 857 var a = span.appendChild(document.createElement('a')); |
| 728 | 858 |
| 729 a.setAttribute('app-id', app['id']); | 859 a.setAttribute('app-id', app['id']); |
| 730 a.textContent = app['name']; | 860 a.textContent = app['name']; |
| 731 a.href = app['launch_url']; | 861 a.href = app['launch_url']; |
| 732 a.onclick = handleClick; | 862 a.onclick = handleClick; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 785 a.href = localStrings.getString('web_store_url'); | 915 a.href = localStrings.getString('web_store_url'); |
| 786 a.style.backgroundImage = url('chrome://theme/IDR_WEBSTORE_ICON_16'); | 916 a.style.backgroundImage = url('chrome://theme/IDR_WEBSTORE_ICON_16'); |
| 787 a.className = 'item'; | 917 a.className = 'item'; |
| 788 return a; | 918 return a; |
| 789 } | 919 } |
| 790 }; | 920 }; |
| 791 })(); | 921 })(); |
| 792 | 922 |
| 793 // Enable drag and drop reordering of the app launcher. | 923 // Enable drag and drop reordering of the app launcher. |
| 794 var appDragAndDrop = new DragAndDropController(apps); | 924 var appDragAndDrop = new DragAndDropController(apps); |
| OLD | NEW |