172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvar MAX_APPS_PER_ROW = []; 6731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickMAX_APPS_PER_ROW[LayoutMode.SMALL] = 4; 7731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickMAX_APPS_PER_ROW[LayoutMode.NORMAL] = 6; 8731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochfunction getAppsCallback(data) { 103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick logEvent('received apps'); 11ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch 12ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch // In the case of prefchange-triggered updates, we don't receive this flag. 13ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch // Just leave it set as it was before in that case. 14ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch if ('showPromo' in data) 15ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch apps.showPromo = data.showPromo; 16ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch 173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var appsSection = $('apps'); 18731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick var appsSectionContent = $('apps-content'); 193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var appsMiniview = appsSection.getElementsByClassName('miniview')[0]; 20731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick var appsPromo = $('apps-promo'); 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var appsPromoLink = $('apps-promo-link'); 22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var appsPromoPing = APP_LAUNCH_URL.PING_WEBSTORE + '+' + apps.showPromo; 23ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch var webStoreEntry, webStoreMiniEntry; 24731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 25201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Hide menu options that are not supported on the OS or windowing system. 26201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 27201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // The "Launch as Window" menu option. 28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen $('apps-launch-type-window-menu-item').hidden = data.disableAppWindowLaunch; 29201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 30201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // The "Create App Shortcut" menu option. 31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen $('apps-create-shortcut-command-menu-item').hidden = 32dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen $('apps-create-shortcut-command-separator').hidden = 33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen data.disableCreateAppShortcut; 34201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Hide the context menu, if there is any open. 36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen cr.ui.contextMenuHandler.hideMenu(); 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick appsMiniview.textContent = ''; 39731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick appsSectionContent.textContent = ''; 40731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 41731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick data.apps.sort(function(a,b) { 424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return a.app_launch_index - b.app_launch_index; 43731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick }); 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Determines if the web store link should be detached and place in the 4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // top right of the screen. 4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen apps.detachWebstoreEntry = 4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen !apps.showPromo && data.apps.length >= MAX_APPS_PER_ROW[layoutMode]; 4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 50dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen markNewApps(data.apps); 5172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen apps.data = data.apps; 5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 53731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick clearClosedMenu(apps.menu); 54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 55dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // We wait for the app icons to load before displaying them, but never wait 56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // longer than 200ms. 57dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen apps.loadedImages = 0; 58dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen apps.imageTimer = setTimeout(apps.showImages.bind(apps), 200); 59dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 60ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch data.apps.forEach(function(app) { 61ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch appsSectionContent.appendChild(apps.createElement(app)); 62ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch }); 633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (data.showPromo) { 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Add the promo content... 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen $('apps-promo-heading').textContent = data.promoHeader; 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen appsPromoLink.href = data.promoLink; 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen appsPromoLink.textContent = data.promoButton; 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen appsPromoLink.ping = appsPromoPing; 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen $('apps-promo-hide').textContent = data.promoExpire; 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // ... then display the promo. 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen document.documentElement.classList.add('apps-promo-visible'); 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen document.documentElement.classList.remove('apps-promo-visible'); 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Only show the web store entry if there are apps installed, since the promo 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // is sufficient otherwise. 80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (data.apps.length > 0) { 81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen webStoreEntry = apps.createWebStoreElement(); 82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen webStoreEntry.querySelector('a').ping = appsPromoPing; 83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen appsSectionContent.appendChild(webStoreEntry); 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (apps.detachWebstoreEntry) { 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen webStoreEntry.classList.add('loner'); 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen webStoreEntry.classList.remove('loner'); 88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen apps.data.push('web-store-entry'); 89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 92ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch data.apps.slice(0, MAX_MINIVIEW_ITEMS).forEach(function(app) { 93ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch appsMiniview.appendChild(apps.createMiniviewElement(app)); 94ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch addClosedMenuEntryWithLink(apps.menu, apps.createClosedMenuElement(app)); 95ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch }); 96ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch if (data.apps.length < MAX_MINIVIEW_ITEMS) { 97ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch webStoreMiniEntry = apps.createWebStoreMiniElement(); 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen webStoreMiniEntry.querySelector('a').ping = appsPromoPing; 99ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch appsMiniview.appendChild(webStoreMiniEntry); 100ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch addClosedMenuEntryWithLink(apps.menu, 101ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch apps.createWebStoreClosedMenuElement()); 102ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch } 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 10472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!data.showLauncher) 105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen hideSection(Section.APPS); 10672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen else 107ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch appsSection.classList.remove('disabled'); 10872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 10972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen addClosedMenuFooter(apps.menu, 'apps', MENU_APPS, Section.APPS); 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick apps.loaded = true; 11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (appsPromoLink) 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen appsPromoLink.ping = appsPromoPing; 1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick maybeDoneLoading(); 1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Disable the animations when the app launcher is being (re)initailized. 11872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen apps.layout({disableAnimations:true}); 119731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 12072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (isDoneLoading()) { 1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick updateMiniviewClipping(appsMiniview); 1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick layoutSections(); 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction markNewApps(data) { 127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var oldData = apps.data; 128dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen data.forEach(function(app) { 129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (hashParams['app-id'] == app['id']) { 130dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delete hashParams['app-id']; 131dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen app.isNew = true; 132dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else if (oldData && 133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen !oldData.some(function(id) { return id == app.id; })) { 134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen app.isNew = true; 135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 136dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen app.isNew = false; 137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen }); 139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickfunction appsPrefChangeCallback(data) { 1423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Currently the only pref that is watched is the launch type. 1433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick data.apps.forEach(function(app) { 1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var appLink = document.querySelector('.app a[app-id=' + app['id'] + ']'); 1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (appLink) 1463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick appLink.setAttribute('launch-type', app['launch_type']); 1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }); 1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 150dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Launches the specified app using the APP_LAUNCH_NTP_APP_RE_ENABLE histogram. 151dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// This should only be invoked from the AppLauncherHandler. 152dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenfunction launchAppAfterEnable(appId) { 153dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen chrome.send('launchApp', [appId, APP_LAUNCH.NTP_APP_RE_ENABLE]); 154dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 155dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvar apps = (function() { 1573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick function createElement(app) { 1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var div = document.createElement('div'); 1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick div.className = 'app'; 1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var a = div.appendChild(document.createElement('a')); 1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick a.setAttribute('app-id', app['id']); 1643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick a.setAttribute('launch-type', app['launch_type']); 16572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen a.draggable = false; 1663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick a.xtitle = a.textContent = app['name']; 1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick a.href = app['launch_url']; 1683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return div; 1703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 17272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen /** 17372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * Launches an application. 17472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @param {string} appId Application to launch. 17572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * @param {MouseEvent} opt_mouseEvent Mouse event from the click that 17672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * triggered the launch, used to detect modifier keys that change 17772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen * the tab's disposition. 17872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen */ 17972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen function launchApp(appId, opt_mouseEvent) { 180dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var args = [appId, getAppLaunchType()]; 18172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (opt_mouseEvent) { 182dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Launch came from a click - add details of the click 183dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Otherwise it came from a 'command' event from elsewhere in the UI. 184dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen args.push(opt_mouseEvent.altKey, opt_mouseEvent.ctrlKey, 185dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen opt_mouseEvent.metaKey, opt_mouseEvent.shiftKey, 186dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen opt_mouseEvent.button); 18772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 188dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen chrome.send('launchApp', args); 189dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 190dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen function isAppSectionMaximized() { 192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return getAppLaunchType() == APP_LAUNCH.NTP_APPS_MAXIMIZED && 193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen !$('apps').classList.contains('disabled'); 194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 196dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen function isAppsMenu(node) { 197dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return node.id == 'apps-menu'; 198dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 199dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 200dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen function getAppLaunchType() { 201dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // We determine if the apps section is maximized, collapsed or in menu mode 202dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // based on the class of the apps section. 203dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if ($('apps').classList.contains('menu')) 204dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return APP_LAUNCH.NTP_APPS_MENU; 205dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen else if ($('apps').classList.contains('collapsed')) 206dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return APP_LAUNCH.NTP_APPS_COLLAPSED; 207dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen else 208dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return APP_LAUNCH.NTP_APPS_MAXIMIZED; 2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick /** 2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick * @this {!HTMLAnchorElement} 2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick */ 2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick function handleClick(e) { 2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var appId = e.currentTarget.getAttribute('app-id'); 21672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!appDragAndDrop.isDragging()) 21772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen launchApp(appId, e); 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Keep in sync with LaunchType in extension_prefs.h 2223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var LaunchType = { 2233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LAUNCH_PINNED: 0, 2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LAUNCH_REGULAR: 1, 225201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch LAUNCH_FULLSCREEN: 2, 226201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch LAUNCH_WINDOW: 3 2273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }; 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 229201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Keep in sync with LaunchContainer in extension_constants.h 2303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var LaunchContainer = { 2313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LAUNCH_WINDOW: 0, 2323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LAUNCH_PANEL: 1, 2333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LAUNCH_TAB: 2 2343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }; 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var currentApp; 237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var promoHasBeenSeen = false; 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick function addContextMenu(el, app) { 2403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick el.addEventListener('contextmenu', cr.ui.contextMenuHandler); 2413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick el.addEventListener('keydown', cr.ui.contextMenuHandler); 2423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick el.addEventListener('keyup', cr.ui.contextMenuHandler); 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Object.defineProperty(el, 'contextMenu', { 2453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick get: function() { 2463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick currentApp = app; 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick $('apps-launch-command').label = app['name']; 2493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick $('apps-options-command').canExecuteChange(); 2503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 251201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch var launchTypeEl; 252201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (el.getAttribute('app-id') === app['id']) { 253201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch launchTypeEl = el; 254201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } else { 255201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch appLinkSel = 'a[app-id=' + app['id'] + ']'; 256201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch launchTypeEl = el.querySelector(appLinkSel); 257201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 259201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch var launchType = launchTypeEl.getAttribute('launch-type'); 2603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var launchContainer = app['launch_container']; 2613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var isPanel = launchContainer == LaunchContainer.LAUNCH_PANEL; 2623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Update the commands related to the launch type. 2643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var launchTypeIds = ['apps-launch-type-pinned', 2653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 'apps-launch-type-regular', 266201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 'apps-launch-type-fullscreen', 267201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 'apps-launch-type-window']; 2683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick launchTypeIds.forEach(function(id) { 2693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var command = $(id); 2703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick command.disabled = isPanel; 2713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick command.checked = !isPanel && 2723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick launchType == command.getAttribute('launch-type'); 2733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }); 2743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return $('app-context-menu'); 2763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }); 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick document.addEventListener('command', function(e) { 2813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!currentApp) 2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 2833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var commandId = e.command.id; 2853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick switch (commandId) { 2863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case 'apps-options-command': 2873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick window.location = currentApp['options_url']; 2883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 2893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case 'apps-launch-command': 2903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick launchApp(currentApp['id']); 2913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 2923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case 'apps-uninstall-command': 2933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick chrome.send('uninstallApp', [currentApp['id']]); 2943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 295201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch case 'apps-create-shortcut-command': 296201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch chrome.send('createAppShortcut', [currentApp['id']]); 297201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch break; 2983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case 'apps-launch-type-pinned': 2993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case 'apps-launch-type-regular': 3003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case 'apps-launch-type-fullscreen': 301201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch case 'apps-launch-type-window': 3023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick chrome.send('setLaunchType', 30372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen [currentApp['id'], 30472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen Number(e.command.getAttribute('launch-type'))]); 3053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 3063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 3073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }); 3083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick document.addEventListener('canExecute', function(e) { 3103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick switch (e.command.id) { 3113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case 'apps-options-command': 3123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick e.canExecute = currentApp && currentApp['options_url']; 3133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 3143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case 'apps-launch-command': 3153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick e.canExecute = true; 3163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case 'apps-uninstall-command': 318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen e.canExecute = !currentApp['can_uninstall']; 319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 3203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 3213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }); 3223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 32372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Moves the element at position |from| in array |arr| to position |to|. 32472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen function arrayMove(arr, from, to) { 32572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var element = arr.splice(from, 1); 32672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen arr.splice(to, 0, element[0]); 32772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 32872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 32972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // The autoscroll rate during drag and drop, in px per second. 33072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var APP_AUTOSCROLL_RATE = 400; 33172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 3323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return { 3333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick loaded: false, 3343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 335731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick menu: $('apps-menu'), 336731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 3374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch showPromo: false, 3384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 33972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen detachWebstoreEntry: false, 34072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 34172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scrollMouseXY_: null, 34272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 34372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scrollListener_: null, 34472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 34572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // The list of app ids, in order, of each app in the launcher. 34672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen data_: null, 34772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen get data() { return this.data_; }, 34872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen set data(data) { 34972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.data_ = data.map(function(app) { 35072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return app.id; 35172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }); 35272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.invalidate_(); 35372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, 35472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 35572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen dirty_: true, 35672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen invalidate_: function() { 35772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.dirty_ = true; 35872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, 35972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 36072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen visible_: true, 36172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen get visible() { 36272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return this.visible_; 36372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, 36472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen set visible(visible) { 36572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.visible_ = visible; 36672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.invalidate_(); 36772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, 36872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 369ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen maybePingPromoSeen_: function() { 370ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (promoHasBeenSeen || !this.showPromo || !isAppSectionMaximized()) 371ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 372ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 373ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen promoHasBeenSeen = true; 374ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen chrome.send('promoSeen', []); 375ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, 376ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 37772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // DragAndDropDelegate 37872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 37972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen dragContainer: $('apps-content'), 38072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen transitionsDuration: 200, 38172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 38272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen get dragItem() { return this.dragItem_; }, 38372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen set dragItem(dragItem) { 38472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (this.dragItem_ != dragItem) { 38572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.dragItem_ = dragItem; 38672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.invalidate_(); 38772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 38872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, 38972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 39072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // The dimensions of each item in the app launcher. 39172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen dimensions_: null, 39272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen get dimensions() { 39372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (this.dimensions_) 39472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return this.dimensions_; 39572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 39672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var width = 124; 39772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var height = 136; 39872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 39972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var marginWidth = 6; 40072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var marginHeight = 10; 40172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 40272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var borderWidth = 0; 40372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var borderHeight = 0; 40472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 40572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.dimensions_ = { 40672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen width: width + marginWidth + borderWidth, 40772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen height: height + marginHeight + borderHeight 40872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }; 40972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 41072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return this.dimensions_; 41172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, 41272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 41372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Gets the item under the mouse event |e|. Returns null if there is no 41472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // item or if the item is not draggable. 41572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen getItem: function(e) { 41672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var item = findAncestorByClass(e.target, 'app'); 41772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 41872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // You can't drag the web store launcher. 41972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (item && item.classList.contains('web-store-entry')) 42072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return null; 42172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 42272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return item; 42372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, 42472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 42572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Returns true if |coordinates| point to a valid drop location. The 42672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // coordinates are relative to the drag container and the object should 42772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // have the 'x' and 'y' properties set. 42872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen canDropOn: function(coordinates) { 42972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var cols = MAX_APPS_PER_ROW[layoutMode]; 43072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var rows = Math.ceil(this.data.length / cols); 43172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 43272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var bottom = rows * this.dimensions.height; 43372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var right = cols * this.dimensions.width; 43472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 43572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (coordinates.x >= right || coordinates.x < 0 || 43672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen coordinates.y >= bottom || coordinates.y < 0) 43772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 43872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 43972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var position = this.getIndexAt_(coordinates); 44072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var appCount = this.data.length; 44172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 44272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!this.detachWebstoreEntry) 44372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen appCount--; 44472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 44572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return position >= 0 && position < appCount; 44672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, 44772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 44872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen setDragPlaceholder: function(coordinates) { 44972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var position = this.getIndexAt_(coordinates); 45072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var appId = this.dragItem.querySelector('a').getAttribute('app-id'); 45172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var current = this.data.indexOf(appId); 45272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 45372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (current == position || current < 0) 45472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 45572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 45672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen arrayMove(this.data, current, position); 45772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.invalidate_(); 45872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.layout(); 45972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, 46072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 46172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen getIndexAt_: function(coordinates) { 46272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var w = this.dimensions.width; 46372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var h = this.dimensions.height; 46472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 46572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var appsPerRow = MAX_APPS_PER_ROW[layoutMode]; 46672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 46772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var row = Math.floor(coordinates.y / h); 46872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var col = Math.floor(coordinates.x / w); 46972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var index = appsPerRow * row + col; 47072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 47172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var appCount = this.data.length; 47272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var rows = Math.ceil(appCount / appsPerRow); 47372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 47472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Rather than making the free space on the last row invalid, we 47572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // map it to the last valid position. 47672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (index >= appCount && index < appsPerRow * rows) 47772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return appCount-1; 47872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 47972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return index; 48072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, 48172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 48272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scrollPage: function(xy) { 48372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var rect = this.dragContainer.getBoundingClientRect(); 48472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 48572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Here, we calculate the visible boundaries of the app launcher, which 48672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // are then used to determine when we should auto-scroll. 48772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var top = $('apps').getBoundingClientRect().bottom; 48872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var bottomFudge = 15; // Fudge factor due to a gradient mask. 48972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var bottom = top + maxiviewVisibleHeight - bottomFudge; 49072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var left = rect.left + window.scrollX; 49172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var right = Math.min(window.innerWidth, rect.left + rect.width); 49272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 49372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var dy = Math.min(0, xy.y - top) + Math.max(0, xy.y - bottom); 49472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var dx = Math.min(0, xy.x - left) + Math.max(0, xy.x - right); 49572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 49672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (dx == 0 && dy == 0) { 49772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.stopScroll_(); 49872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 49972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 50072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 50172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // If we scroll the page directly from this method, it may be choppy and 50272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // inconsistent. Instead, we loop using animation frames, and scroll at a 50372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // speed that's independent of how many times this method is called. 50472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.scrollMouseXY_ = {dx: dx, dy: dy}; 50572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 50672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!this.scrollListener_) { 50772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.scrollListener_ = this.scrollImpl_.bind(this); 50872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.scrollStep_(); 50972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 51072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, 51172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 51272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scrollStep_: function() { 51372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.scrollStart_ = Date.now(); 51472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen window.webkitRequestAnimationFrame(this.scrollListener_); 51572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, 51672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 51772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scrollImpl_: function(time) { 51872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!appDragAndDrop.isDragging()) { 51972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.stopScroll_(); 52072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 52172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 52272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 52372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!this.scrollMouseXY_) 52472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 52572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 52672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var step = time - this.scrollStart_; 52772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 52872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen window.scrollBy( 52972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.calcScroll_(this.scrollMouseXY_.dx, step), 53072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.calcScroll_(this.scrollMouseXY_.dy, step)); 53172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 53272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.scrollStep_(); 53372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, 53472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 53572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen calcScroll_: function(delta, step) { 53672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (delta == 0) 53772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return 0; 53872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 53972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Increase the multiplier for every 50px the mouse is beyond the edge. 54072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var sign = delta > 0 ? 1 : -1; 54172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var scalar = APP_AUTOSCROLL_RATE * step / 1000; 54272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var multiplier = Math.floor(Math.abs(delta) / 50) + 1; 54372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 54472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return sign * scalar * multiplier; 54572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, 54672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 54772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen stopScroll_: function() { 54872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.scrollListener_ = null; 54972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.scrollMouseXY_ = null; 55072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, 55172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 552dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen saveDrag: function(draggedItem) { 55372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.invalidate_(); 55472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.layout(); 55572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 556dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var draggedAppId = draggedItem.querySelector('a').getAttribute('app-id'); 55772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var appIds = this.data.filter(function(id) { 55872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return id != 'web-store-entry'; 55972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }); 56072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 56172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Wait until the transitions are complete before notifying the browser. 56272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Otherwise, the apps will be re-rendered while still transitioning. 56372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen setTimeout(function() { 564dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen chrome.send('reorderApps', [draggedAppId, appIds]); 56572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, this.transitionsDuration + 10); 56672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, 56772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 56872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen layout: function(options) { 56972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen options = options || {}; 57072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!this.dirty_ && options.force != true) 57172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 57272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 57372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen try { 57472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var container = this.dragContainer; 57572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (options.disableAnimations) 57672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen container.setAttribute('launcher-animations', false); 57772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var d0 = Date.now(); 57872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.layoutImpl_(); 57972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this.dirty_ = false; 58072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen logEvent('apps.layout: ' + (Date.now() - d0)); 58172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 58272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } finally { 58372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (options.disableAnimations) { 58472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // We need to re-enable animations asynchronously, so that the 58572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // animations are still disabled for this layout update. 58672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen setTimeout(function() { 58772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen container.setAttribute('launcher-animations', true); 58872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, 0); 58972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 59072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 59172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, 59272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 59372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen layoutImpl_: function() { 594ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen var apps = this.data || []; 59572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var rects = this.getLayoutRects_(apps.length); 59672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var appsContent = this.dragContainer; 59772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 598ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Ping the PROMO_SEEN histogram only when the promo is maximized, and 599ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // maximum once per NTP load. 600ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen this.maybePingPromoSeen_(); 601ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 60272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!this.visible) 60372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 60472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 60572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (var i = 0; i < apps.length; i++) { 60672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var app = appsContent.querySelector('[app-id='+apps[i]+']').parentNode; 60772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 60872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // If the node is being dragged, don't try to place it in the grid. 60972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (app == this.dragItem) 61072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen continue; 61172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 61272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen app.style.left = rects[i].left + 'px'; 61372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen app.style.top = rects[i].top + 'px'; 61472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 61572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 61672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // We need to set the container's height manually because the apps use 61772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // absolute positioning. 61872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var rows = Math.ceil(apps.length / MAX_APPS_PER_ROW[layoutMode]); 61972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen appsContent.style.height = (rows * this.dimensions.height) + 'px'; 62072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, 62172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 62272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen getLayoutRects_: function(appCount) { 62372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var availableWidth = this.dragContainer.offsetWidth; 62472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var rtl = isRtl(); 62572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var rects = []; 62672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var w = this.dimensions.width; 62772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var h = this.dimensions.height; 62872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var appsPerRow = MAX_APPS_PER_ROW[layoutMode]; 62972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 63072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (var i = 0; i < appCount; i++) { 63172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var top = Math.floor(i / appsPerRow) * h; 63272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen var left = (i % appsPerRow) * w; 63372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 63472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Reflect the X axis if an RTL language is active. 63572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rtl) 63672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen left = availableWidth - left - w; 63772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rects[i] = {left: left, top: top}; 63872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 63972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return rects; 64072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen }, 64172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 642dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen get loadedImages() { 643dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return this.loadedImages_; 644dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen }, 645dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 646dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen set loadedImages(value) { 647dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen this.loadedImages_ = value; 648dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (this.loadedImages_ == 0) 649dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 650dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 651dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Each application icon is loaded asynchronously. Here, we display 652dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // the icons once they've all been loaded to make it look nicer. 653dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (this.loadedImages_ == this.data.length) { 654dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen this.showImages(); 655dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 656dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 657dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 658dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // We won't actually have the visible height until the sections have 659dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // been layed out. 660dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!maxiviewVisibleHeight) 661dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 662dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 663dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // If we know the visible height of the maxiview, then we can don't need 664dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // to wait for all the icons. Instead, we wait until the visible portion 665dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // have been loaded. 666dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var appsPerRow = MAX_APPS_PER_ROW[layoutMode]; 667dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var rows = Math.ceil(maxiviewVisibleHeight / this.dimensions.height); 668dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var count = Math.min(appsPerRow * rows, this.data.length); 669dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (this.loadedImages_ == count) { 670dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen this.showImages(); 671dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 672dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 673dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen }, 674dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 675dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen showImages: function() { 676dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen $('apps-content').classList.add('visible'); 677dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen clearTimeout(this.imageTimer); 678dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen }, 679dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 6803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick createElement: function(app) { 6813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var div = createElement(app); 6823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var a = div.firstChild; 6833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 6843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick a.onclick = handleClick; 685ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen a.ping = getAppPingUrl( 686ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 'PING_BY_ID', this.showPromo, 'NTP_APPS_MAXIMIZED'); 6873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick a.style.backgroundImage = url(app['icon_big']); 688dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (app.isNew) { 6893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick div.setAttribute('new', 'new'); 6903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Delay changing the attribute a bit to let the page settle down a bit. 6913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick setTimeout(function() { 692731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Make sure the new icon is scrolled into view. 693731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick document.body.scrollTop = document.body.scrollHeight; 694731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 6953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // This will trigger the 'bounce' animation defined in apps.css. 6963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick div.setAttribute('new', 'installed'); 6973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }, 500); 6983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick div.addEventListener('webkitAnimationEnd', function(e) { 6993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick div.removeAttribute('new'); 7003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }); 7013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 7023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 703dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // CSS background images don't fire 'load' events, so we use an Image. 704dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen var img = new Image(); 705dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen img.onload = function() { this.loadedImages++; }.bind(this); 706dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen img.src = app['icon_big']; 707dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 7083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var settingsButton = div.appendChild(new cr.ui.ContextMenuButton); 7093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick settingsButton.className = 'app-settings'; 7103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick settingsButton.title = localStrings.getString('appsettings'); 7113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 7123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick addContextMenu(div, app); 7133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 7143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return div; 7153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }, 7163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 7173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick createMiniviewElement: function(app) { 7183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var span = document.createElement('span'); 7193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick var a = span.appendChild(document.createElement('a')); 7203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 7213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick a.setAttribute('app-id', app['id']); 7223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick a.textContent = app['name']; 7233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick a.href = app['launch_url']; 7243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick a.onclick = handleClick; 725ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen a.ping = getAppPingUrl( 726ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 'PING_BY_ID', this.showPromo, 'NTP_APPS_COLLAPSED'); 7273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick a.style.backgroundImage = url(app['icon_small']); 7283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick a.className = 'item'; 7293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick span.appendChild(a); 7303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 7313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick addContextMenu(span, app); 7323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 7333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return span; 7343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }, 7353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 736731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick createClosedMenuElement: function(app) { 737731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick var a = document.createElement('a'); 738731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick a.setAttribute('app-id', app['id']); 739731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick a.textContent = app['name']; 740731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick a.href = app['launch_url']; 741731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick a.onclick = handleClick; 742ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen a.ping = getAppPingUrl( 743ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 'PING_BY_ID', this.showPromo, 'NTP_APPS_MENU'); 744731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick a.style.backgroundImage = url(app['icon_small']); 745731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick a.className = 'item'; 746201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 747201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch addContextMenu(a, app); 748201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 749731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return a; 750731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick }, 751731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 7523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick createWebStoreElement: function() { 753731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick var elm = createElement({ 7543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 'id': 'web-store-entry', 7553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 'name': localStrings.getString('web_store_title'), 7563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 'launch_url': localStrings.getString('web_store_url') 7573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }); 75872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen elm.classList.add('web-store-entry'); 759731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return elm; 760ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch }, 761ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch 762ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch createWebStoreMiniElement: function() { 763ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch var span = document.createElement('span'); 764ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch span.appendChild(this.createWebStoreClosedMenuElement()); 765ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch return span; 766ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch }, 767ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch 768ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch createWebStoreClosedMenuElement: function() { 769ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch var a = document.createElement('a'); 770ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch a.textContent = localStrings.getString('web_store_title'); 771ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch a.href = localStrings.getString('web_store_url'); 772ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch a.style.backgroundImage = url('chrome://theme/IDR_PRODUCT_LOGO_16'); 773ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch a.className = 'item'; 774ac1e49eb6695f711d72215fcdf9388548942a00dBen Murdoch return a; 7753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 7763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }; 7773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick})(); 77872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 77972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Enable drag and drop reordering of the app launcher. 78072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvar appDragAndDrop = new DragAndDropController(apps); 781