Index: chrome/browser/resources/ntp/apps.js |
diff --git a/chrome/browser/resources/ntp/apps.js b/chrome/browser/resources/ntp/apps.js |
deleted file mode 100644 |
index c965d4612225f393290308f74c9e2c5127e6a5c4..0000000000000000000000000000000000000000 |
--- a/chrome/browser/resources/ntp/apps.js |
+++ /dev/null |
@@ -1,909 +0,0 @@ |
-// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-var MAX_APPS_PER_ROW = []; |
-MAX_APPS_PER_ROW[LayoutMode.SMALL] = 4; |
-MAX_APPS_PER_ROW[LayoutMode.NORMAL] = 6; |
- |
-function getAppsCallback(data) { |
- logEvent('received apps'); |
- |
- // In the case of prefchange-triggered updates, we don't receive this flag. |
- // Just leave it set as it was before in that case. |
- if ('showPromo' in data) |
- apps.showPromo = data.showPromo; |
- |
- var appsSection = $('apps'); |
- var appsSectionContent = $('apps-content'); |
- var appsMiniview = appsSection.getElementsByClassName('miniview')[0]; |
- var appsPromo = $('apps-promo'); |
- var appsPromoLink = $('apps-promo-link'); |
- var appsPromoPing = APP_LAUNCH_URL.PING_WEBSTORE + '+' + apps.showPromo; |
- var webStoreEntry, webStoreMiniEntry; |
- |
- // Hide menu options that are not supported on the OS or windowing system. |
- |
- // The "Launch as Window" menu option. |
- $('apps-launch-type-window-menu-item').hidden = data.disableAppWindowLaunch; |
- |
- // The "Create App Shortcut" menu option. |
- $('apps-create-shortcut-command-menu-item').hidden = |
- $('apps-create-shortcut-command-separator').hidden = |
- data.disableCreateAppShortcut; |
- |
- // Hide the context menu, if there is any open. |
- cr.ui.contextMenuHandler.hideMenu(); |
- |
- appsMiniview.textContent = ''; |
- appsSectionContent.textContent = ''; |
- |
- data.apps.sort(function(a,b) { |
- return a.app_launch_index - b.app_launch_index; |
- }); |
- |
- // Determines if the web store link should be detached and place in the |
- // top right of the screen. |
- apps.detachWebstoreEntry = |
- !apps.showPromo && data.apps.length >= MAX_APPS_PER_ROW[layoutMode]; |
- |
- markNewApps(data.apps); |
- apps.data = data.apps; |
- |
- clearClosedMenu(apps.menu); |
- |
- // We wait for the app icons to load before displaying them, but never wait |
- // longer than 200ms. |
- apps.loadedImages = 0; |
- apps.imageTimer = setTimeout(apps.showImages.bind(apps), 200); |
- |
- data.apps.forEach(function(app) { |
- appsSectionContent.appendChild(apps.createElement(app)); |
- }); |
- |
- if (data.showPromo) { |
- // Add the promo content... |
- $('apps-promo-heading').textContent = data.promoHeader; |
- appsPromoLink.href = data.promoLink; |
- appsPromoLink.textContent = data.promoButton; |
- appsPromoLink.ping = appsPromoPing; |
- $('apps-promo').style.background = |
- "url('" + data.promoLogo + "') no-repeat"; |
- $('apps-promo-hide').textContent = data.promoExpire; |
- |
- // ... then display the promo. |
- document.documentElement.classList.add('apps-promo-visible'); |
- } else { |
- document.documentElement.classList.remove('apps-promo-visible'); |
- } |
- |
- // Only show the web store entry if there are apps installed or the promo |
- // is not available. |
- if (data.apps.length > 0 || !data.showPromo) { |
- webStoreEntry = apps.createWebStoreElement(); |
- webStoreEntry.querySelector('a').ping = appsPromoPing; |
- appsSectionContent.appendChild(webStoreEntry); |
- if (apps.detachWebstoreEntry) { |
- webStoreEntry.classList.add('loner'); |
- } else { |
- webStoreEntry.classList.remove('loner'); |
- apps.data.push('web-store-entry'); |
- } |
- } |
- |
- data.apps.slice(0, MAX_MINIVIEW_ITEMS).forEach(function(app) { |
- appsMiniview.appendChild(apps.createMiniviewElement(app)); |
- addClosedMenuEntryWithLink(apps.menu, apps.createClosedMenuElement(app)); |
- }); |
- if (data.apps.length < MAX_MINIVIEW_ITEMS) { |
- webStoreMiniEntry = apps.createWebStoreMiniElement(); |
- webStoreMiniEntry.querySelector('a').ping = appsPromoPing; |
- appsMiniview.appendChild(webStoreMiniEntry); |
- addClosedMenuEntryWithLink(apps.menu, |
- apps.createWebStoreClosedMenuElement()); |
- } |
- |
- if (!data.showLauncher) |
- hideSection(Section.APPS); |
- else |
- appsSection.classList.remove('disabled'); |
- |
- addClosedMenuFooter(apps.menu, 'apps', MENU_APPS, Section.APPS); |
- |
- apps.loaded = true; |
- |
- if (appsPromoLink) |
- appsPromoLink.ping = appsPromoPing; |
- maybeDoneLoading(); |
- |
- // Disable the animations when the app launcher is being (re)initailized. |
- apps.layout({disableAnimations:true}); |
- |
- if (isDoneLoading()) { |
- updateMiniviewClipping(appsMiniview); |
- layoutSections(); |
- } |
-} |
- |
-function markNewApps(data) { |
- var oldData = apps.data; |
- data.forEach(function(app) { |
- if (hashParams['app-id'] == app['id']) { |
- delete hashParams['app-id']; |
- app.isNew = true; |
- } else if (oldData && |
- !oldData.some(function(id) { return id == app.id; })) { |
- app.isNew = true; |
- } else { |
- app.isNew = false; |
- } |
- }); |
-} |
- |
-function appsPrefChangeCallback(data) { |
- // Currently the only pref that is watched is the launch type. |
- data.apps.forEach(function(app) { |
- var appLink = document.querySelector('.app a[app-id=' + app['id'] + ']'); |
- if (appLink) |
- appLink.setAttribute('launch-type', app['launch_type']); |
- }); |
-} |
- |
-function appNotificationChanged(id, lastNotification) { |
- // TODO(asargent/finnur): Don't update all apps at once, do it in a more |
- // fine grained way. |
- chrome.send('getApps'); |
-} |
- |
-// Launches the specified app using the APP_LAUNCH_NTP_APP_RE_ENABLE histogram. |
-// This should only be invoked from the AppLauncherHandler. |
-function launchAppAfterEnable(appId) { |
- chrome.send('launchApp', [appId, APP_LAUNCH.NTP_APP_RE_ENABLE]); |
-} |
- |
-// Shows the notification bubble for a given app (the one clicked on). |
-function showNotificationBubble(event) { |
- var item = findAncestorByClass(event.target, 'app-anchor'); |
- var title = item.getAttribute('notification-title'); |
- var message = item.getAttribute('notification-message'); |
- var link = item.getAttribute('notification-link'); |
- var link_message = item.getAttribute('notification-link-message'); |
- |
- if (!title || !message) |
- return; |
- |
- // Set the content to the right text. |
- $('app-notification-title').textContent = title; |
- $('app-notification-message').textContent = message; |
- $('app-notification-link').href = link; |
- $('app-notification-link').textContent = link_message; |
- |
- var target = event.target; |
- while (target.parentElement && target.tagName != "A") { |
- target = target.parentElement; |
- } |
- |
- // Move the bubble to the right location. |
- var bubble = $('app-notification-bubble'); |
- var x = target.parentElement.offsetLeft + |
- target.parentElement.offsetWidth - 20; |
- var y = target.parentElement.offsetTop + 20; |
- bubble.style.left = x + "px"; |
- bubble.style.top = y + "px"; |
- |
- // Move the arrow and shadow to the right location. |
- var arrow_container = $('arrow-container'); |
- y += 26; |
- x -= arrow_container.style.width + 25; |
- arrow_container.style.left = x + "px"; |
- arrow_container.style.top = y + "px"; |
- |
- // Animate the bubble into view. |
- bubble.classList.add("notification-bubble-opened"); |
- bubble.classList.remove("notification-bubble-closed"); |
- arrow_container.classList.add("notification-bubble-opened"); |
- arrow_container.classList.remove("notification-bubble-closed"); |
- |
- bubble.focus(); |
-} |
- |
-// Hide the notification bubble. |
-function hideNotificationBubble(event) { |
- // This will fade the bubble out of existence. |
- $('app-notification-bubble').classList.add("notification-bubble-closed"); |
- $('app-notification-bubble').classList.remove("notification-bubble-opened"); |
- $('arrow-container').classList.add("notification-bubble-closed"); |
- $('arrow-container').classList.remove("notification-bubble-opened"); |
-} |
- |
-var apps = (function() { |
- |
- function createElement(app) { |
- var div = document.createElement('div'); |
- div.className = 'app'; |
- |
- var a = div.appendChild(document.createElement('a')); |
- a.className = 'app-anchor'; |
- a.setAttribute('app-id', app['id']); |
- a.setAttribute('launch-type', app['launch_type']); |
- if (typeof(app['notification']) != "undefined") { |
- a.setAttribute('notification-title', app['notification']['title']); |
- a.setAttribute('notification-message', app['notification']['body']); |
- if (typeof(app['notification']['linkUrl']) != "undefined" && |
- typeof(app['notification']['linkText']) != "undefined") { |
- a.setAttribute('notification-link', app['notification']['linkUrl']); |
- a.setAttribute('notification-link-message', |
- app['notification']['linkText']); |
- } |
- } |
- a.draggable = false; |
- a.href = app['launch_url']; |
- |
- var span = a.appendChild(document.createElement('span')); |
- span.textContent = app['name']; |
- |
- span = a.appendChild(document.createElement('span')); |
- span.className = "app_notification"; |
- span.textContent = |
- typeof(app['notification']) != "undefined" && |
- typeof(app['notification']['title']) != "undefined" ? |
- app['notification']['title'] : ""; |
- span.onclick = handleClick; |
- |
- $("app-notification-close").onclick = hideNotificationBubble; |
- $("app-notification-bubble").setAttribute("tabIndex", 0); |
- $("app-notification-bubble").onblur = hideNotificationBubble; |
- |
- return div; |
- } |
- |
- /** |
- * Launches an application. |
- * @param {string} appId Application to launch. |
- * @param {MouseEvent} opt_mouseEvent Mouse event from the click that |
- * triggered the launch, used to detect modifier keys that change |
- * the tab's disposition. |
- */ |
- function launchApp(appId, opt_mouseEvent) { |
- var args = [appId, getAppLaunchType()]; |
- if (opt_mouseEvent) { |
- // Launch came from a click - add details of the click |
- // Otherwise it came from a 'command' event from elsewhere in the UI. |
- args.push(opt_mouseEvent.altKey, opt_mouseEvent.ctrlKey, |
- opt_mouseEvent.metaKey, opt_mouseEvent.shiftKey, |
- opt_mouseEvent.button); |
- } |
- chrome.send('launchApp', args); |
- } |
- |
- function isAppSectionMaximized() { |
- return getAppLaunchType() == APP_LAUNCH.NTP_APPS_MAXIMIZED && |
- !$('apps').classList.contains('disabled'); |
- } |
- |
- function isAppsMenu(node) { |
- return node.id == 'apps-menu'; |
- } |
- |
- function getAppLaunchType() { |
- // We determine if the apps section is maximized, collapsed or in menu mode |
- // based on the class of the apps section. |
- if ($('apps').classList.contains('menu')) |
- return APP_LAUNCH.NTP_APPS_MENU; |
- else if ($('apps').classList.contains('collapsed')) |
- return APP_LAUNCH.NTP_APPS_COLLAPSED; |
- else |
- return APP_LAUNCH.NTP_APPS_MAXIMIZED; |
- } |
- |
- /** |
- * @this {!HTMLAnchorElement} |
- */ |
- function handleClick(e) { |
- var appId = e.currentTarget.getAttribute('app-id'); |
- if (appId == null) { |
- showNotificationBubble(e); |
- e.stopPropagation(); |
- return false; |
- } |
- |
- if (!appDragAndDrop.isDragging()) |
- launchApp(appId, e); |
- return false; |
- } |
- |
- // Keep in sync with LaunchType in extension_prefs.h |
- var LaunchType = { |
- LAUNCH_PINNED: 0, |
- LAUNCH_REGULAR: 1, |
- LAUNCH_FULLSCREEN: 2, |
- LAUNCH_WINDOW: 3 |
- }; |
- |
- // Keep in sync with LaunchContainer in extension_constants.h |
- var LaunchContainer = { |
- LAUNCH_WINDOW: 0, |
- LAUNCH_PANEL: 1, |
- LAUNCH_TAB: 2 |
- }; |
- |
- var currentApp; |
- var promoHasBeenSeen = false; |
- |
- function addContextMenu(el, app) { |
- el.addEventListener('contextmenu', cr.ui.contextMenuHandler); |
- el.addEventListener('keydown', cr.ui.contextMenuHandler); |
- el.addEventListener('keyup', cr.ui.contextMenuHandler); |
- |
- Object.defineProperty(el, 'contextMenu', { |
- get: function() { |
- currentApp = app; |
- |
- $('apps-launch-command').label = app['name']; |
- $('apps-options-command').canExecuteChange(); |
- $('apps-uninstall-command').canExecuteChange(); |
- |
- var launchTypeEl; |
- if (el.getAttribute('app-id') === app['id']) { |
- launchTypeEl = el; |
- } else { |
- appLinkSel = 'a[app-id=' + app['id'] + ']'; |
- launchTypeEl = el.querySelector(appLinkSel); |
- } |
- |
- var launchType = launchTypeEl.getAttribute('launch-type'); |
- var launchContainer = app['launch_container']; |
- var isPanel = launchContainer == LaunchContainer.LAUNCH_PANEL; |
- |
- // Update the commands related to the launch type. |
- var launchTypeIds = ['apps-launch-type-pinned', |
- 'apps-launch-type-regular', |
- 'apps-launch-type-fullscreen', |
- 'apps-launch-type-window']; |
- launchTypeIds.forEach(function(id) { |
- var command = $(id); |
- command.disabled = isPanel; |
- command.checked = !isPanel && |
- launchType == command.getAttribute('launch-type'); |
- }); |
- |
- return $('app-context-menu'); |
- } |
- }); |
- } |
- |
- document.addEventListener('command', function(e) { |
- if (!currentApp) |
- return; |
- |
- var commandId = e.command.id; |
- switch (commandId) { |
- case 'apps-options-command': |
- window.location = currentApp['options_url']; |
- break; |
- case 'apps-launch-command': |
- launchApp(currentApp['id']); |
- break; |
- case 'apps-uninstall-command': |
- chrome.send('uninstallApp', [currentApp['id']]); |
- break; |
- case 'apps-create-shortcut-command': |
- chrome.send('createAppShortcut', [currentApp['id']]); |
- break; |
- case 'apps-launch-type-pinned': |
- case 'apps-launch-type-regular': |
- case 'apps-launch-type-fullscreen': |
- case 'apps-launch-type-window': |
- chrome.send('setLaunchType', |
- [currentApp['id'], |
- Number(e.command.getAttribute('launch-type'))]); |
- break; |
- } |
- }); |
- |
- document.addEventListener('canExecute', function(e) { |
- switch (e.command.id) { |
- case 'apps-options-command': |
- e.canExecute = currentApp && currentApp['options_url']; |
- break; |
- case 'apps-launch-command': |
- e.canExecute = true; |
- break; |
- case 'apps-uninstall-command': |
- e.canExecute = currentApp && currentApp['can_uninstall']; |
- break; |
- } |
- }); |
- |
- // Moves the element at position |from| in array |arr| to position |to|. |
- function arrayMove(arr, from, to) { |
- var element = arr.splice(from, 1); |
- arr.splice(to, 0, element[0]); |
- } |
- |
- // The autoscroll rate during drag and drop, in px per second. |
- var APP_AUTOSCROLL_RATE = 400; |
- |
- return { |
- loaded: false, |
- |
- menu: $('apps-menu'), |
- |
- showPromo: false, |
- |
- detachWebstoreEntry: false, |
- |
- scrollMouseXY_: null, |
- |
- scrollListener_: null, |
- |
- // The list of app ids, in order, of each app in the launcher. |
- data_: null, |
- get data() { return this.data_; }, |
- set data(data) { |
- this.data_ = data.map(function(app) { |
- return app.id; |
- }); |
- this.invalidate_(); |
- }, |
- |
- dirty_: true, |
- invalidate_: function() { |
- this.dirty_ = true; |
- }, |
- |
- visible_: true, |
- get visible() { |
- return this.visible_; |
- }, |
- set visible(visible) { |
- this.visible_ = visible; |
- this.invalidate_(); |
- }, |
- |
- maybePingPromoSeen_: function() { |
- if (promoHasBeenSeen || !this.showPromo || !isAppSectionMaximized()) |
- return; |
- |
- promoHasBeenSeen = true; |
- chrome.send('promoSeen', []); |
- }, |
- |
- // DragAndDropDelegate |
- |
- dragContainer: $('apps-content'), |
- transitionsDuration: 200, |
- |
- get dragItem() { return this.dragItem_; }, |
- set dragItem(dragItem) { |
- if (this.dragItem_ != dragItem) { |
- this.dragItem_ = dragItem; |
- this.invalidate_(); |
- } |
- }, |
- |
- // The dimensions of each item in the app launcher. |
- dimensions_: null, |
- get dimensions() { |
- if (this.dimensions_) |
- return this.dimensions_; |
- |
- var width = 124; |
- var height = 136; |
- |
- var marginWidth = 6; |
- var marginHeight = 10; |
- |
- var borderWidth = 0; |
- var borderHeight = 0; |
- |
- this.dimensions_ = { |
- width: width + marginWidth + borderWidth, |
- height: height + marginHeight + borderHeight |
- }; |
- |
- return this.dimensions_; |
- }, |
- |
- // Gets the item under the mouse event |e|. Returns null if there is no |
- // item or if the item is not draggable. |
- getItem: function(e) { |
- var item = findAncestorByClass(e.target, 'app'); |
- |
- // You can't drag the web store launcher. |
- if (item && item.classList.contains('web-store-entry')) |
- return null; |
- |
- return item; |
- }, |
- |
- // Returns true if |coordinates| point to a valid drop location. The |
- // coordinates are relative to the drag container and the object should |
- // have the 'x' and 'y' properties set. |
- canDropOn: function(coordinates) { |
- var cols = MAX_APPS_PER_ROW[layoutMode]; |
- var rows = Math.ceil(this.data.length / cols); |
- |
- var bottom = rows * this.dimensions.height; |
- var right = cols * this.dimensions.width; |
- |
- if (coordinates.x >= right || coordinates.x < 0 || |
- coordinates.y >= bottom || coordinates.y < 0) |
- return false; |
- |
- var position = this.getIndexAt_(coordinates); |
- var appCount = this.data.length; |
- |
- if (!this.detachWebstoreEntry) |
- appCount--; |
- |
- return position >= 0 && position < appCount; |
- }, |
- |
- setDragPlaceholder: function(coordinates) { |
- var position = this.getIndexAt_(coordinates); |
- var appId = this.dragItem.querySelector('a').getAttribute('app-id'); |
- var current = this.data.indexOf(appId); |
- |
- if (current == position || current < 0) |
- return; |
- |
- arrayMove(this.data, current, position); |
- this.invalidate_(); |
- this.layout(); |
- }, |
- |
- getIndexAt_: function(coordinates) { |
- var w = this.dimensions.width; |
- var h = this.dimensions.height; |
- |
- var appsPerRow = MAX_APPS_PER_ROW[layoutMode]; |
- |
- var row = Math.floor(coordinates.y / h); |
- var col = Math.floor(coordinates.x / w); |
- var index = appsPerRow * row + col; |
- |
- var appCount = this.data.length; |
- var rows = Math.ceil(appCount / appsPerRow); |
- |
- // Rather than making the free space on the last row invalid, we |
- // map it to the last valid position. |
- if (index >= appCount && index < appsPerRow * rows) |
- return appCount-1; |
- |
- return index; |
- }, |
- |
- scrollPage: function(xy) { |
- var rect = this.dragContainer.getBoundingClientRect(); |
- |
- // Here, we calculate the visible boundaries of the app launcher, which |
- // are then used to determine when we should auto-scroll. |
- var top = $('apps').getBoundingClientRect().bottom; |
- var bottomFudge = 15; // Fudge factor due to a gradient mask. |
- var bottom = top + maxiviewVisibleHeight - bottomFudge; |
- var left = rect.left + window.scrollX; |
- var right = Math.min(window.innerWidth, rect.left + rect.width); |
- |
- var dy = Math.min(0, xy.y - top) + Math.max(0, xy.y - bottom); |
- var dx = Math.min(0, xy.x - left) + Math.max(0, xy.x - right); |
- |
- if (dx == 0 && dy == 0) { |
- this.stopScroll_(); |
- return; |
- } |
- |
- // If we scroll the page directly from this method, it may be choppy and |
- // inconsistent. Instead, we loop using animation frames, and scroll at a |
- // speed that's independent of how many times this method is called. |
- this.scrollMouseXY_ = {dx: dx, dy: dy}; |
- |
- if (!this.scrollListener_) { |
- this.scrollListener_ = this.scrollImpl_.bind(this); |
- this.scrollStep_(); |
- } |
- }, |
- |
- scrollStep_: function() { |
- this.scrollStart_ = Date.now(); |
- window.webkitRequestAnimationFrame(this.scrollListener_); |
- }, |
- |
- scrollImpl_: function(time) { |
- if (!appDragAndDrop.isDragging()) { |
- this.stopScroll_(); |
- return; |
- } |
- |
- if (!this.scrollMouseXY_) |
- return; |
- |
- var step = time - this.scrollStart_; |
- |
- window.scrollBy( |
- this.calcScroll_(this.scrollMouseXY_.dx, step), |
- this.calcScroll_(this.scrollMouseXY_.dy, step)); |
- |
- this.scrollStep_(); |
- }, |
- |
- calcScroll_: function(delta, step) { |
- if (delta == 0) |
- return 0; |
- |
- // Increase the multiplier for every 50px the mouse is beyond the edge. |
- var sign = delta > 0 ? 1 : -1; |
- var scalar = APP_AUTOSCROLL_RATE * step / 1000; |
- var multiplier = Math.floor(Math.abs(delta) / 50) + 1; |
- |
- return sign * scalar * multiplier; |
- }, |
- |
- stopScroll_: function() { |
- this.scrollListener_ = null; |
- this.scrollMouseXY_ = null; |
- }, |
- |
- saveDrag: function(draggedItem) { |
- this.invalidate_(); |
- this.layout(); |
- |
- var draggedAppId = draggedItem.querySelector('a').getAttribute('app-id'); |
- var appIds = this.data.filter(function(id) { |
- return id != 'web-store-entry'; |
- }); |
- |
- // Wait until the transitions are complete before notifying the browser. |
- // Otherwise, the apps will be re-rendered while still transitioning. |
- setTimeout(function() { |
- chrome.send('reorderApps', [draggedAppId, appIds]); |
- }, this.transitionsDuration + 10); |
- }, |
- |
- layout: function(options) { |
- options = options || {}; |
- if (!this.dirty_ && options.force != true) |
- return; |
- |
- try { |
- var container = this.dragContainer; |
- if (options.disableAnimations) |
- container.setAttribute('launcher-animations', false); |
- var d0 = Date.now(); |
- this.layoutImpl_(); |
- this.dirty_ = false; |
- logEvent('apps.layout: ' + (Date.now() - d0)); |
- |
- } finally { |
- if (options.disableAnimations) { |
- // We need to re-enable animations asynchronously, so that the |
- // animations are still disabled for this layout update. |
- setTimeout(function() { |
- container.setAttribute('launcher-animations', true); |
- }, 0); |
- } |
- } |
- }, |
- |
- layoutImpl_: function() { |
- var apps = this.data || []; |
- var rects = this.getLayoutRects_(apps.length); |
- var appsContent = this.dragContainer; |
- |
- // Ping the PROMO_SEEN histogram only when the promo is maximized, and |
- // maximum once per NTP load. |
- this.maybePingPromoSeen_(); |
- |
- if (!this.visible) |
- return; |
- |
- for (var i = 0; i < apps.length; i++) { |
- var app = appsContent.querySelector('[app-id='+apps[i]+']').parentNode; |
- |
- // If the node is being dragged, don't try to place it in the grid. |
- if (app == this.dragItem) |
- continue; |
- |
- app.style.left = rects[i].left + 'px'; |
- app.style.top = rects[i].top + 'px'; |
- } |
- |
- // We need to set the container's height manually because the apps use |
- // absolute positioning. |
- var rows = Math.ceil(apps.length / MAX_APPS_PER_ROW[layoutMode]); |
- appsContent.style.height = (rows * this.dimensions.height) + 'px'; |
- }, |
- |
- getLayoutRects_: function(appCount) { |
- var availableWidth = this.dragContainer.offsetWidth; |
- var rtl = isRtl(); |
- var rects = []; |
- var w = this.dimensions.width; |
- var h = this.dimensions.height; |
- var appsPerRow = MAX_APPS_PER_ROW[layoutMode]; |
- |
- for (var i = 0; i < appCount; i++) { |
- var top = Math.floor(i / appsPerRow) * h; |
- var left = (i % appsPerRow) * w; |
- |
- // Reflect the X axis if an RTL language is active. |
- if (rtl) |
- left = availableWidth - left - w; |
- rects[i] = {left: left, top: top}; |
- } |
- return rects; |
- }, |
- |
- get loadedImages() { |
- return this.loadedImages_; |
- }, |
- |
- set loadedImages(value) { |
- this.loadedImages_ = value; |
- if (this.loadedImages_ == 0) |
- return; |
- |
- // Each application icon is loaded asynchronously. Here, we display |
- // the icons once they've all been loaded to make it look nicer. |
- if (this.loadedImages_ == this.data.length) { |
- this.showImages(); |
- return; |
- } |
- |
- // We won't actually have the visible height until the sections have |
- // been layed out. |
- if (!maxiviewVisibleHeight) |
- return; |
- |
- // If we know the visible height of the maxiview, then we can don't need |
- // to wait for all the icons. Instead, we wait until the visible portion |
- // have been loaded. |
- var appsPerRow = MAX_APPS_PER_ROW[layoutMode]; |
- var rows = Math.ceil(maxiviewVisibleHeight / this.dimensions.height); |
- var count = Math.min(appsPerRow * rows, this.data.length); |
- if (this.loadedImages_ == count) { |
- this.showImages(); |
- return; |
- } |
- }, |
- |
- showImages: function() { |
- $('apps-content').classList.add('visible'); |
- clearTimeout(this.imageTimer); |
- }, |
- |
- createElement: function(app) { |
- var container = document.createElement('div'); |
- var div = createElement(app); |
- container.appendChild(div); |
- var a = div.firstChild; |
- |
- a.onclick = handleClick; |
- a.ping = getAppPingUrl( |
- 'PING_BY_ID', this.showPromo, 'NTP_APPS_MAXIMIZED'); |
- a.style.backgroundImage = url(app['icon_big']); |
- if (app.isNew) { |
- div.setAttribute('new', 'new'); |
- // Delay changing the attribute a bit to let the page settle down a bit. |
- setTimeout(function() { |
- // Make sure the new icon is scrolled into view. |
- document.body.scrollTop = document.body.scrollHeight; |
- |
- // This will trigger the 'bounce' animation defined in apps.css. |
- div.setAttribute('new', 'installed'); |
- }, 500); |
- div.addEventListener('webkitAnimationEnd', function(e) { |
- div.removeAttribute('new'); |
- }); |
- } |
- |
- // CSS background images don't fire 'load' events, so we use an Image. |
- var img = new Image(); |
- img.onload = function() { this.loadedImages++; }.bind(this); |
- img.src = app['icon_big']; |
- |
- // User cannot change launch options or uninstall component extension. |
- if (!app['is_component']) { |
- var settingsButton = div.appendChild(new cr.ui.ContextMenuButton); |
- settingsButton.className = 'app-settings'; |
- settingsButton.title = localStrings.getString('appsettings'); |
- addContextMenu(div, app); |
- } |
- |
- if (app.notifications && app.notifications.length > 0) { |
- // Create the notification div below the app icon that is used to |
- // trigger the hidden notification bubble to appear. |
- var notification = document.createElement('div') |
- container.appendChild(notification); |
- var title = document.createElement('span'); |
- title.textContent = app.notifications[0].title; |
- notification.appendChild(title); |
- notification.appendChild(document.createElement('br')); |
- |
- var body = document.createElement('span'); |
- container.appendChild(body); |
- body.textContent = app.notifications[0].body; |
- notification.appendChild(body); |
- if (app.notifications[0].linkUrl) { |
- notification.appendChild(document.createElement('br')); |
- var link = document.createElement('a'); |
- link.href = app.notifications[0].linkUrl; |
- link.textContent = app.notifications[0].linkText ? |
- app.notifications[0].linkText : "link"; |
- notification.appendChild(link); |
- } |
- } |
- |
- return container; |
- }, |
- |
- createMiniviewElement: function(app) { |
- var span = document.createElement('span'); |
- var a = span.appendChild(document.createElement('a')); |
- |
- a.setAttribute('app-id', app['id']); |
- a.textContent = app['name']; |
- a.href = app['launch_url']; |
- a.onclick = handleClick; |
- a.ping = getAppPingUrl( |
- 'PING_BY_ID', this.showPromo, 'NTP_APPS_COLLAPSED'); |
- a.style.backgroundImage = url(app['icon_small']); |
- a.className = 'item'; |
- span.appendChild(a); |
- |
- // User cannot change launch options or uninstall component extension. |
- if (!app['is_component']) { |
- addContextMenu(span, app); |
- } |
- |
- return span; |
- }, |
- |
- createClosedMenuElement: function(app) { |
- var a = document.createElement('a'); |
- a.setAttribute('app-id', app['id']); |
- a.textContent = app['name']; |
- a.href = app['launch_url']; |
- a.onclick = handleClick; |
- a.ping = getAppPingUrl( |
- 'PING_BY_ID', this.showPromo, 'NTP_APPS_MENU'); |
- a.style.backgroundImage = url(app['icon_small']); |
- a.className = 'item'; |
- |
- // User cannot change launch options or uninstall component extension. |
- if (!app['is_component']) { |
- addContextMenu(a, app); |
- } |
- |
- return a; |
- }, |
- |
- createWebStoreElement: function() { |
- var elm = createElement({ |
- 'id': 'web-store-entry', |
- 'name': localStrings.getString('web_store_title'), |
- 'launch_url': localStrings.getString('web_store_url') |
- }); |
- elm.classList.add('web-store-entry'); |
- return elm; |
- }, |
- |
- createWebStoreMiniElement: function() { |
- var span = document.createElement('span'); |
- span.appendChild(this.createWebStoreClosedMenuElement()); |
- return span; |
- }, |
- |
- createWebStoreClosedMenuElement: function() { |
- var a = document.createElement('a'); |
- a.textContent = localStrings.getString('web_store_title'); |
- a.href = localStrings.getString('web_store_url'); |
- a.style.backgroundImage = url('chrome://theme/IDR_WEBSTORE_ICON_16'); |
- a.className = 'item'; |
- return a; |
- } |
- }; |
-})(); |
- |
-// Enable drag and drop reordering of the app launcher. |
-var appDragAndDrop = new DragAndDropController(apps); |