| OLD | NEW | 
|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 // Helpers | 5 var loading = true; | 
| 6 | 6 | 
| 7 function findAncestorByClass(el, className) { | 7 function updateSimpleSection(id, section) { | 
| 8   return findAncestor(el, function(el) { | 8   if (shownSections & section) | 
| 9     return hasClass(el, className); | 9     $(id).classList.remove('hidden'); | 
| 10   }); | 10   else | 
|  | 11     $(id).classList.add('hidden'); | 
| 11 } | 12 } | 
| 12 | 13 | 
| 13 /** |  | 
| 14  * Return the first ancestor for which the {@code predicate} returns true. |  | 
| 15  * @param {Node} node The node to check. |  | 
| 16  * @param {function(Node) : boolean} predicate The function that tests the |  | 
| 17  *     nodes. |  | 
| 18  * @return {Node} The found ancestor or null if not found. |  | 
| 19  */ |  | 
| 20 function findAncestor(node, predicate) { |  | 
| 21   var last = false; |  | 
| 22   while (node != null && !(last = predicate(node))) { |  | 
| 23     node = node.parentNode; |  | 
| 24   } |  | 
| 25   return last ? node : null; |  | 
| 26 } |  | 
| 27 |  | 
| 28 // WebKit does not have Node.prototype.swapNode |  | 
| 29 // https://bugs.webkit.org/show_bug.cgi?id=26525 |  | 
| 30 function swapDomNodes(a, b) { |  | 
| 31   var afterA = a.nextSibling; |  | 
| 32   if (afterA == b) { |  | 
| 33     swapDomNodes(b, a); |  | 
| 34     return; |  | 
| 35   } |  | 
| 36   var aParent = a.parentNode; |  | 
| 37   b.parentNode.replaceChild(a, b); |  | 
| 38   aParent.insertBefore(b, afterA); |  | 
| 39 } |  | 
| 40 |  | 
| 41 function bind(fn, selfObj, var_args) { |  | 
| 42   var boundArgs = Array.prototype.slice.call(arguments, 2); |  | 
| 43   return function() { |  | 
| 44     var args = Array.prototype.slice.call(arguments); |  | 
| 45     args.unshift.apply(args, boundArgs); |  | 
| 46     return fn.apply(selfObj, args); |  | 
| 47   } |  | 
| 48 } |  | 
| 49 |  | 
| 50 const IS_MAC = /$Mac/.test(navigator.platform); |  | 
| 51 |  | 
| 52 var loading = true; |  | 
| 53 |  | 
| 54 function getAppsCallback(data) { | 14 function getAppsCallback(data) { | 
|  | 15   logEvent('recieved apps'); | 
| 55   var appsSection = $('apps-section'); | 16   var appsSection = $('apps-section'); | 
| 56   var debugSection = $('debug'); | 17   var debugSection = $('debug'); | 
| 57   appsSection.innerHTML = ''; | 18   appsSection.innerHTML = ''; | 
| 58 | 19 | 
| 59   data.forEach(function(app) { | 20   data.forEach(function(app) { | 
| 60     appsSection.appendChild(apps.createElement(app)); | 21     appsSection.appendChild(apps.createElement(app)); | 
| 61   }); | 22   }); | 
| 62 | 23 | 
| 63   // TODO(aa): Figure out what to do with the debug mode when we turn apps on | 24   // TODO(aa): Figure out what to do with the debug mode when we turn apps on | 
| 64   // for everyone. | 25   // for everyone. | 
| 65   if (data.length) { | 26   if (data.length) { | 
| 66     removeClass(appsSection, 'disabled'); | 27     appsSection.classList.remove('disabled'); | 
| 67     removeClass(debugSection, 'disabled'); | 28     debugSection.classList.remove('disabled'); | 
| 68   } else { | 29   } else { | 
| 69     addClass(appsSection, 'disabled'); | 30     appsSection.classList.add('disabled'); | 
| 70     addClass(debugSection, 'disabled'); | 31     debugSection.classList.add('disabled'); | 
| 71   } | 32   } | 
| 72 } | 33 } | 
| 73 | 34 | 
| 74 var apps = { | 35 var apps = { | 
| 75   /** | 36   /** | 
| 76    * @this {!HTMLAnchorElement} | 37    * @this {!HTMLAnchorElement} | 
| 77    */ | 38    */ | 
| 78   handleClick_: function() { | 39   handleClick_: function() { | 
| 79     var launchType = ''; | 40     var launchType = ''; | 
| 80     var inputElements = document.querySelectorAll( | 41     var inputElements = document.querySelectorAll( | 
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 189     el.dir = data.direction; | 150     el.dir = data.direction; | 
| 190     el.textContent = data.title; | 151     el.textContent = data.title; | 
| 191   } | 152   } | 
| 192   el.sessionId = data.sessionId; | 153   el.sessionId = data.sessionId; | 
| 193   el.xtitle = data.title; | 154   el.xtitle = data.title; | 
| 194   var wrapperEl = document.createElement('span'); | 155   var wrapperEl = document.createElement('span'); | 
| 195   wrapperEl.appendChild(el); | 156   wrapperEl.appendChild(el); | 
| 196   return wrapperEl; | 157   return wrapperEl; | 
| 197 } | 158 } | 
| 198 | 159 | 
| 199 function onShownSections(mask) { |  | 
| 200   logEvent('received shown sections'); |  | 
| 201   if (mask != shownSections) { |  | 
| 202     var oldShownSections = shownSections; |  | 
| 203     shownSections = mask; |  | 
| 204 |  | 
| 205     // Only invalidate most visited if needed. |  | 
| 206     if ((mask & Section.THUMB) != (oldShownSections & Section.THUMB)) { |  | 
| 207       mostVisited.invalidate(); |  | 
| 208     } |  | 
| 209 |  | 
| 210     mostVisited.updateDisplayMode(); |  | 
| 211     renderRecentlyClosed(); |  | 
| 212   } |  | 
| 213 } |  | 
| 214 |  | 
| 215 function saveShownSections() { | 160 function saveShownSections() { | 
| 216   chrome.send('setShownSections', [String(shownSections)]); | 161   chrome.send('setShownSections', [String(shownSections)]); | 
| 217 } | 162 } | 
| 218 | 163 | 
| 219 function url(s) { |  | 
| 220   // http://www.w3.org/TR/css3-values/#uris |  | 
| 221   // Parentheses, commas, whitespace characters, single quotes (') and double |  | 
| 222   // quotes (") appearing in a URI must be escaped with a backslash |  | 
| 223   var s2 = s.replace(/(\(|\)|\,|\s|\'|\"|\\)/g, '\\$1'); |  | 
| 224   // WebKit has a bug when it comes to URLs that end with \ |  | 
| 225   // https://bugs.webkit.org/show_bug.cgi?id=28885 |  | 
| 226   if (/\\\\$/.test(s2)) { |  | 
| 227     // Add a space to work around the WebKit bug. |  | 
| 228     s2 += ' '; |  | 
| 229   } |  | 
| 230   return 'url("' + s2 + '")'; |  | 
| 231 } |  | 
| 232 |  | 
| 233 /** |  | 
| 234  * Calls chrome.send with a callback and restores the original afterwards. |  | 
| 235  */ |  | 
| 236 function chromeSend(name, params, callbackName, callback) { |  | 
| 237   var old = global[callbackName]; |  | 
| 238   global[callbackName] = function() { |  | 
| 239     // restore |  | 
| 240     global[callbackName] = old; |  | 
| 241 |  | 
| 242     var args = Array.prototype.slice.call(arguments); |  | 
| 243     return callback.apply(global, args); |  | 
| 244   }; |  | 
| 245   chrome.send(name, params); |  | 
| 246 } |  | 
| 247 |  | 
| 248 var LayoutMode = { | 164 var LayoutMode = { | 
| 249   SMALL: 1, | 165   SMALL: 1, | 
| 250   NORMAL: 2 | 166   NORMAL: 2 | 
| 251 }; | 167 }; | 
| 252 | 168 | 
| 253 var layoutMode = useSmallGrid() ? LayoutMode.SMALL : LayoutMode.NORMAL; | 169 var layoutMode = useSmallGrid() ? LayoutMode.SMALL : LayoutMode.NORMAL; | 
| 254 | 170 | 
| 255 function handleWindowResize() { | 171 function handleWindowResize() { | 
| 256   if (window.innerWidth < 10) { | 172   if (window.innerWidth < 10) { | 
| 257     // We're probably a background tab, so don't do anything. | 173     // We're probably a background tab, so don't do anything. | 
| 258     return; | 174     return; | 
| 259   } | 175   } | 
| 260 | 176 | 
| 261   var oldLayoutMode = layoutMode; | 177   var oldLayoutMode = layoutMode; | 
| 262   layoutMode = useSmallGrid() ? LayoutMode.SMALL : LayoutMode.NORMAL | 178   var b = useSmallGrid(); | 
|  | 179   layoutMode = b ? LayoutMode.SMALL : LayoutMode.NORMAL | 
| 263 | 180 | 
| 264   if (layoutMode != oldLayoutMode){ | 181   if (layoutMode != oldLayoutMode){ | 
| 265     mostVisited.invalidate(); | 182     mostVisited.useSmallGrid = b; | 
| 266     mostVisited.layout(); | 183     mostVisited.layout(); | 
| 267     renderRecentlyClosed(); | 184     renderRecentlyClosed(); | 
| 268   } | 185   } | 
| 269 } | 186 } | 
| 270 | 187 | 
|  | 188 window.addEventListener('resize', handleWindowResize); | 
|  | 189 | 
|  | 190 var sectionToElementMap; | 
|  | 191 function getSectionElement(section) { | 
|  | 192   if (!sectionToElementMap) { | 
|  | 193     sectionToElementMap = {}; | 
|  | 194     for (var key in Section) { | 
|  | 195       sectionToElementMap[Section[key]] = | 
|  | 196           document.querySelector('.section[section=' + key + ']'); | 
|  | 197     } | 
|  | 198   } | 
|  | 199   return sectionToElementMap[section]; | 
|  | 200 } | 
|  | 201 | 
| 271 function showSection(section) { | 202 function showSection(section) { | 
| 272   if (!(section & shownSections)) { | 203   if (!(section & shownSections)) { | 
| 273     shownSections |= section; | 204     shownSections |= section; | 
| 274 | 205 | 
| 275     switch (section) { | 206     switch (section) { | 
| 276       case Section.THUMB: | 207       case Section.THUMB: | 
| 277         mostVisited.invalidate(); | 208         mostVisited.visible = true; | 
| 278         mostVisited.updateDisplayMode(); |  | 
| 279         mostVisited.layout(); | 209         mostVisited.layout(); | 
| 280         break; | 210         break; | 
| 281       case Section.RECENT: | 211       case Section.RECENT: | 
| 282         renderRecentlyClosed(); | 212         renderRecentlyClosed(); | 
| 283         break; | 213         break; | 
| 284       case Section.TIPS: |  | 
| 285         removeClass($('tip-line'), 'hidden'); |  | 
| 286         break; |  | 
| 287       case Section.DEBUG: |  | 
| 288         removeClass($('debug'), 'hidden'); |  | 
| 289         break; |  | 
| 290     } | 214     } | 
|  | 215 | 
|  | 216     getSectionElement(section).classList.remove('hidden'); | 
| 291   } | 217   } | 
| 292 } | 218 } | 
| 293 | 219 | 
| 294 function hideSection(section) { | 220 function hideSection(section) { | 
| 295   if (section & shownSections) { | 221   if (section & shownSections) { | 
| 296     shownSections &= ~section; | 222     shownSections &= ~section; | 
| 297 | 223 | 
| 298     switch (section) { | 224     switch (section) { | 
| 299       case Section.THUMB: | 225       case Section.THUMB: | 
| 300         mostVisited.invalidate(); | 226         mostVisited.visible = false; | 
| 301         mostVisited.updateDisplayMode(); |  | 
| 302         mostVisited.layout(); | 227         mostVisited.layout(); | 
| 303         break; | 228         break; | 
| 304       case Section.RECENT: | 229       case Section.RECENT: | 
| 305         renderRecentlyClosed(); | 230         renderRecentlyClosed(); | 
| 306         break; | 231         break; | 
| 307       case Section.TIPS: |  | 
| 308         addClass($('tip-line'), 'hidden'); |  | 
| 309         break; |  | 
| 310       case Section.DEBUG: |  | 
| 311         addClass($('debug'), 'hidden'); |  | 
| 312         break; |  | 
| 313     } | 232     } | 
|  | 233 | 
|  | 234     getSectionElement(section).classList.add('hidden'); | 
| 314   } | 235   } | 
| 315 } | 236 } | 
| 316 | 237 | 
| 317 // Recently closed | 238 // Recently closed | 
| 318 | 239 | 
| 319 function layoutRecentlyClosed() { | 240 function layoutRecentlyClosed() { | 
| 320   var recentShown = shownSections & Section.RECENT; | 241   var recentShown = shownSections & Section.RECENT; | 
| 321   updateSimpleSection('recently-closed', Section.RECENT); |  | 
| 322 | 242 | 
| 323   if (recentShown) { | 243   if (recentShown) { | 
| 324     var recentElement = $('recently-closed'); | 244     var recentElement = $('recently-closed'); | 
| 325     var style = recentElement.style; | 245     var style = recentElement.style; | 
| 326     // We cannot use clientWidth here since the width has a transition. | 246     // We cannot use clientWidth here since the width has a transition. | 
| 327     var spacing = 20; | 247     var spacing = 20; | 
| 328     var headerEl = recentElement.firstElementChild; | 248     var headerEl = recentElement.firstElementChild; | 
| 329     var navEl = recentElement.lastElementChild.lastElementChild; | 249     var navEl = recentElement.lastElementChild.lastElementChild; | 
| 330     var navWidth = navEl.offsetWidth; | 250     var navWidth = navEl.offsetWidth; | 
| 331     // Subtract 10 for the padding | 251     // Subtract 10 for the padding | 
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 434  * Returns the text used for a recently closed window. | 354  * Returns the text used for a recently closed window. | 
| 435  * @param {number} numTabs Number of tabs in the window. | 355  * @param {number} numTabs Number of tabs in the window. | 
| 436  * @return {string} The text to use. | 356  * @return {string} The text to use. | 
| 437  */ | 357  */ | 
| 438 function formatTabsText(numTabs) { | 358 function formatTabsText(numTabs) { | 
| 439   if (numTabs == 1) | 359   if (numTabs == 1) | 
| 440     return localStrings.getString('closedwindowsingle'); | 360     return localStrings.getString('closedwindowsingle'); | 
| 441   return localStrings.getStringF('closedwindowmultiple', numTabs); | 361   return localStrings.getStringF('closedwindowmultiple', numTabs); | 
| 442 } | 362 } | 
| 443 | 363 | 
| 444 /** |  | 
| 445  * We need both most visited and the shown sections to be considered loaded. |  | 
| 446  * @return {boolean} |  | 
| 447  */ |  | 
| 448 function onDataLoaded() { |  | 
| 449   if (gotMostVisited) { |  | 
| 450     mostVisited.layout(); |  | 
| 451     loading = false; |  | 
| 452     // Remove class name in a timeout so that changes done in this JS thread are |  | 
| 453     // not animated. |  | 
| 454     window.setTimeout(function() { |  | 
| 455       ensureSmallGridCorrect(); |  | 
| 456       removeClass(document.body, 'loading'); |  | 
| 457     }, 1); |  | 
| 458   } |  | 
| 459 } |  | 
| 460 |  | 
| 461 // Theme related | 364 // Theme related | 
| 462 | 365 | 
| 463 function themeChanged() { | 366 function themeChanged() { | 
| 464   $('themecss').href = 'chrome://theme/css/newtab.css?' + Date.now(); | 367   $('themecss').href = 'chrome://theme/css/newtab.css?' + Date.now(); | 
| 465   updateAttribution(); | 368   updateAttribution(); | 
| 466 } | 369 } | 
| 467 | 370 | 
| 468 function updateAttribution() { | 371 function updateAttribution() { | 
| 469   $('attribution-img').src = 'chrome://theme/theme_ntp_attribution?' + | 372   $('attribution-img').src = 'chrome://theme/theme_ntp_attribution?' + | 
| 470       Date.now(); | 373       Date.now(); | 
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 528 | 431 | 
| 529 var notificationTimeout; | 432 var notificationTimeout; | 
| 530 | 433 | 
| 531 function showNotification(text, actionText, opt_f, opt_delay) { | 434 function showNotification(text, actionText, opt_f, opt_delay) { | 
| 532   var notificationElement = $('notification'); | 435   var notificationElement = $('notification'); | 
| 533   var f = opt_f || function() {}; | 436   var f = opt_f || function() {}; | 
| 534   var delay = opt_delay || 10000; | 437   var delay = opt_delay || 10000; | 
| 535 | 438 | 
| 536   function show() { | 439   function show() { | 
| 537     window.clearTimeout(notificationTimeout); | 440     window.clearTimeout(notificationTimeout); | 
| 538     addClass(notificationElement, 'show'); | 441     notificationElement.classList.add('show'); | 
| 539     addClass(document.body, 'notification-shown'); | 442     document.body.classList.add('notification-shown'); | 
| 540   } | 443   } | 
| 541 | 444 | 
| 542   function delayedHide() { | 445   function delayedHide() { | 
| 543     notificationTimeout = window.setTimeout(hideNotification, delay); | 446     notificationTimeout = window.setTimeout(hideNotification, delay); | 
| 544   } | 447   } | 
| 545 | 448 | 
| 546   function doAction() { | 449   function doAction() { | 
| 547     f(); | 450     f(); | 
| 548     hideNotification(); | 451     hideNotification(); | 
| 549   } | 452   } | 
| 550 | 453 | 
| 551   // Remove any possible first-run trails. | 454   // Remove any possible first-run trails. | 
| 552   removeClass(notification, 'first-run'); | 455   notification.classList.remove('first-run'); | 
| 553 | 456 | 
| 554   var actionLink = notificationElement.querySelector('.link-color'); | 457   var actionLink = notificationElement.querySelector('.link-color'); | 
| 555   notificationElement.firstElementChild.textContent = text; | 458   notificationElement.firstElementChild.textContent = text; | 
| 556   actionLink.textContent = actionText; | 459   actionLink.textContent = actionText; | 
| 557 | 460 | 
| 558   actionLink.onclick = doAction; | 461   actionLink.onclick = doAction; | 
| 559   actionLink.onkeydown = handleIfEnterKey(doAction); | 462   actionLink.onkeydown = handleIfEnterKey(doAction); | 
| 560   notificationElement.onmouseover = show; | 463   notificationElement.onmouseover = show; | 
| 561   notificationElement.onmouseout = delayedHide; | 464   notificationElement.onmouseout = delayedHide; | 
| 562   actionLink.onfocus = show; | 465   actionLink.onfocus = show; | 
| 563   actionLink.onblur = delayedHide; | 466   actionLink.onblur = delayedHide; | 
| 564   // Enable tabbing to the link now that it is shown. | 467   // Enable tabbing to the link now that it is shown. | 
| 565   actionLink.tabIndex = 0; | 468   actionLink.tabIndex = 0; | 
| 566 | 469 | 
| 567   show(); | 470   show(); | 
| 568   delayedHide(); | 471   delayedHide(); | 
| 569 } | 472 } | 
| 570 | 473 | 
| 571 /** | 474 /** | 
| 572  * Hides the notifier. | 475  * Hides the notifier. | 
| 573  */ | 476  */ | 
| 574 function hideNotification() { | 477 function hideNotification() { | 
| 575   var notificationElement = $('notification'); | 478   var notificationElement = $('notification'); | 
| 576   removeClass(notificationElement, 'show'); | 479   notificationElement.classList.remove('show'); | 
| 577   removeClass(document.body, 'notification-shown'); | 480   document.body.classList.remove('notification-shown'); | 
| 578   var actionLink = notificationElement.querySelector('.link-color'); | 481   var actionLink = notificationElement.querySelector('.link-color'); | 
| 579   // Prevent tabbing to the hidden link. | 482   // Prevent tabbing to the hidden link. | 
| 580   actionLink.tabIndex = -1; | 483   actionLink.tabIndex = -1; | 
| 581   // Setting tabIndex to -1 only prevents future tabbing to it. If, however, the | 484   // Setting tabIndex to -1 only prevents future tabbing to it. If, however, the | 
| 582   // user switches window or a tab and then moves back to this tab the element | 485   // user switches window or a tab and then moves back to this tab the element | 
| 583   // may gain focus. We therefore make sure that we blur the element so that the | 486   // may gain focus. We therefore make sure that we blur the element so that the | 
| 584   // element focus is not restored when coming back to this window. | 487   // element focus is not restored when coming back to this window. | 
| 585   actionLink.blur(); | 488   actionLink.blur(); | 
| 586 } | 489 } | 
| 587 | 490 | 
| 588 function showFirstRunNotification() { | 491 function showFirstRunNotification() { | 
| 589   showNotification(localStrings.getString('firstrunnotification'), | 492   showNotification(localStrings.getString('firstrunnotification'), | 
| 590                    localStrings.getString('closefirstrunnotification'), | 493                    localStrings.getString('closefirstrunnotification'), | 
| 591                    null, 30000); | 494                    null, 30000); | 
| 592   var notificationElement = $('notification'); | 495   var notificationElement = $('notification'); | 
| 593   addClass(notification, 'first-run'); | 496   notification.classList.add('first-run'); | 
| 594 } | 497 } | 
| 595 | 498 | 
| 596 /** | 499 /** | 
| 597  * This handles the option menu. | 500  * This handles the option menu. | 
| 598  * @param {Element} button The button element. | 501  * @param {Element} button The button element. | 
| 599  * @param {Element} menu The menu element. | 502  * @param {Element} menu The menu element. | 
| 600  * @constructor | 503  * @constructor | 
| 601  */ | 504  */ | 
| 602 function OptionMenu(button, menu) { | 505 function OptionMenu(button, menu) { | 
| 603   this.button = button; | 506   this.button = button; | 
| 604   this.menu = menu; | 507   this.menu = menu; | 
| 605   this.button.onmousedown = bind(this.handleMouseDown, this); | 508   this.button.onmousedown = bind(this.handleMouseDown, this); | 
| 606   this.button.onkeydown = bind(this.handleKeyDown, this); | 509   this.button.onkeydown = bind(this.handleKeyDown, this); | 
| 607   this.boundHideMenu_ = bind(this.hide, this); | 510   this.boundHideMenu_ = bind(this.hide, this); | 
| 608   this.boundMaybeHide_ = bind(this.maybeHide_, this); | 511   this.boundMaybeHide_ = bind(this.maybeHide_, this); | 
| 609   this.menu.onmouseover = bind(this.handleMouseOver, this); | 512   this.menu.onmouseover = bind(this.handleMouseOver, this); | 
| 610   this.menu.onmouseout = bind(this.handleMouseOut, this); | 513   this.menu.onmouseout = bind(this.handleMouseOut, this); | 
| 611   this.menu.onmouseup = bind(this.handleMouseUp, this); | 514   this.menu.onmouseup = bind(this.handleMouseUp, this); | 
| 612 } | 515 } | 
| 613 | 516 | 
| 614 OptionMenu.prototype = { | 517 OptionMenu.prototype = { | 
| 615   show: function() { | 518   show: function() { | 
| 616     updateOptionMenu(); | 519     updateOptionMenu(); | 
| 617     this.positionMenu_(); | 520     this.positionMenu_(); | 
| 618     this.menu.style.display = 'block'; | 521     this.menu.style.display = 'block'; | 
| 619     addClass(this.button, 'open'); | 522     this.button.classList.add('open'); | 
| 620     this.button.focus(); | 523     this.button.focus(); | 
| 621 | 524 | 
| 622     // Listen to document and window events so that we hide the menu when the | 525     // Listen to document and window events so that we hide the menu when the | 
| 623     // user clicks outside the menu or tabs away or the whole window is blurred. | 526     // user clicks outside the menu or tabs away or the whole window is blurred. | 
| 624     document.addEventListener('focus', this.boundMaybeHide_, true); | 527     document.addEventListener('focus', this.boundMaybeHide_, true); | 
| 625     document.addEventListener('mousedown', this.boundMaybeHide_, true); | 528     document.addEventListener('mousedown', this.boundMaybeHide_, true); | 
| 626   }, | 529   }, | 
| 627 | 530 | 
| 628   positionMenu_: function() { | 531   positionMenu_: function() { | 
| 629     this.menu.style.top = this.button.getBoundingClientRect().bottom + 'px'; | 532     this.menu.style.top = this.button.getBoundingClientRect().bottom + 'px'; | 
| 630   }, | 533   }, | 
| 631 | 534 | 
| 632   hide: function() { | 535   hide: function() { | 
| 633     this.menu.style.display = 'none'; | 536     this.menu.style.display = 'none'; | 
| 634     removeClass(this.button, 'open'); | 537     this.button.classList.remove('open'); | 
| 635     this.setSelectedIndex(-1); | 538     this.setSelectedIndex(-1); | 
| 636 | 539 | 
| 637     document.removeEventListener('focus', this.boundMaybeHide_, true); | 540     document.removeEventListener('focus', this.boundMaybeHide_, true); | 
| 638     document.removeEventListener('mousedown', this.boundMaybeHide_, true); | 541     document.removeEventListener('mousedown', this.boundMaybeHide_, true); | 
| 639   }, | 542   }, | 
| 640 | 543 | 
| 641   isShown: function() { | 544   isShown: function() { | 
| 642     return this.menu.style.display == 'block'; | 545     return this.menu.style.display == 'block'; | 
| 643   }, | 546   }, | 
| 644 | 547 | 
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 960       span.textContent = tab.title; | 863       span.textContent = tab.title; | 
| 961       tooltip.appendChild(span); | 864       tooltip.appendChild(span); | 
| 962     }); | 865     }); | 
| 963   } | 866   } | 
| 964 }; | 867 }; | 
| 965 | 868 | 
| 966 var windowTooltip = new WindowTooltip($('window-tooltip')); | 869 var windowTooltip = new WindowTooltip($('window-tooltip')); | 
| 967 | 870 | 
| 968 window.addEventListener('load', bind(logEvent, global, 'Tab.NewTabOnload', | 871 window.addEventListener('load', bind(logEvent, global, 'Tab.NewTabOnload', | 
| 969                                      true)); | 872                                      true)); | 
| 970 window.addEventListener('load', onDataLoaded); |  | 
| 971 | 873 | 
| 972 window.addEventListener('resize', handleWindowResize); | 874 window.addEventListener('resize', handleWindowResize); | 
| 973 document.addEventListener('DOMContentLoaded', | 875 document.addEventListener('DOMContentLoaded', | 
| 974     bind(logEvent, global, 'Tab.NewTabDOMContentLoaded', true)); | 876     bind(logEvent, global, 'Tab.NewTabDOMContentLoaded', true)); | 
| 975 | 877 | 
| 976 // Whether or not we should send the initial 'GetSyncMessage' to the backend | 878 // Whether or not we should send the initial 'GetSyncMessage' to the backend | 
| 977 // depends on the value of the attribue 'syncispresent' which the backend sets | 879 // depends on the value of the attribue 'syncispresent' which the backend sets | 
| 978 // to indicate if there is code in the backend which is capable of processing | 880 // to indicate if there is code in the backend which is capable of processing | 
| 979 // this message. This attribute is loaded by the JSTemplate and therefore we | 881 // this message. This attribute is loaded by the JSTemplate and therefore we | 
| 980 // must make sure we check the attribute after the DOM is loaded. | 882 // must make sure we check the attribute after the DOM is loaded. | 
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1014 window.addEventListener('keydown', function(e) { | 916 window.addEventListener('keydown', function(e) { | 
| 1015   if (e.keyIdentifier == 'Alt' || e.keyIdentifier == 'Meta') { | 917   if (e.keyIdentifier == 'Alt' || e.keyIdentifier == 'Meta') { | 
| 1016     hideAllMenus(); | 918     hideAllMenus(); | 
| 1017   } | 919   } | 
| 1018 }, true); | 920 }, true); | 
| 1019 | 921 | 
| 1020 // Tooltip for elements that have text that overflows. | 922 // Tooltip for elements that have text that overflows. | 
| 1021 document.addEventListener('mouseover', function(e) { | 923 document.addEventListener('mouseover', function(e) { | 
| 1022   // We don't want to do this while we are dragging because it makes things very | 924   // We don't want to do this while we are dragging because it makes things very | 
| 1023   // janky | 925   // janky | 
| 1024   if (dnd.dragItem) { | 926   if (mostVisited.isDragging()) { | 
| 1025     return; | 927     return; | 
| 1026   } | 928   } | 
| 1027 | 929 | 
| 1028   var el = findAncestor(e.target, function(el) { | 930   var el = findAncestor(e.target, function(el) { | 
| 1029     return el.xtitle; | 931     return el.xtitle; | 
| 1030   }); | 932   }); | 
| 1031   if (el && el.xtitle != el.title) { | 933   if (el && el.xtitle != el.title) { | 
| 1032     if (el.scrollWidth > el.clientWidth) { | 934     if (el.scrollWidth > el.clientWidth) { | 
| 1033       el.title = el.xtitle; | 935       el.title = el.xtitle; | 
| 1034     } else { | 936     } else { | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
| 1056   while (el.hasChildNodes()) { | 958   while (el.hasChildNodes()) { | 
| 1057     span.appendChild(el.firstChild); | 959     span.appendChild(el.firstChild); | 
| 1058   } | 960   } | 
| 1059   el.appendChild(span); | 961   el.appendChild(span); | 
| 1060 } | 962 } | 
| 1061 | 963 | 
| 1062 updateAttribution(); | 964 updateAttribution(); | 
| 1063 | 965 | 
| 1064 // Closes the promo line when close button is clicked. | 966 // Closes the promo line when close button is clicked. | 
| 1065 $('promo-close').onclick = function (e) { | 967 $('promo-close').onclick = function (e) { | 
| 1066   addClass($('promo-line'), 'hidden'); | 968   $('promo-line').classList.add('hidden'); | 
| 1067   chrome.send('stopPromoLineMessage'); | 969   chrome.send('stopPromoLineMessage'); | 
| 1068   e.preventDefault(); | 970   e.preventDefault(); | 
| 1069 }; | 971 }; | 
| 1070 | 972 | 
| 1071 // Set bookmark sync button to start bookmark sync process on click; also set | 973 // Set bookmark sync button to start bookmark sync process on click; also set | 
| 1072 // link underline colors correctly. | 974 // link underline colors correctly. | 
| 1073 function setUpPromoMessage() { | 975 function setUpPromoMessage() { | 
| 1074   var syncButton = document.querySelector('#promo-message button'); | 976   var syncButton = document.querySelector('#promo-message button'); | 
| 1075   syncButton.className = 'sync-button link'; | 977   syncButton.className = 'sync-button link'; | 
| 1076   syncButton.onclick = syncSectionLinkClicked; | 978   syncButton.onclick = syncSectionLinkClicked; | 
| 1077   fixLinkUnderlines($('promo-message')); | 979   fixLinkUnderlines($('promo-message')); | 
| 1078 } | 980 } | 
|  | 981 | 
|  | 982 var mostVisited = new MostVisited($('most-visited'), | 
|  | 983                                   useSmallGrid(), | 
|  | 984                                   shownSections & Section.THUMB); | 
|  | 985 | 
|  | 986 function mostVisitedPages(data, firstRun) { | 
|  | 987   logEvent('received most visited pages'); | 
|  | 988 | 
|  | 989   mostVisited.data = data; | 
|  | 990   mostVisited.layout(); | 
|  | 991 | 
|  | 992   loading = false; | 
|  | 993 | 
|  | 994   // Remove class name in a timeout so that changes done in this JS thread are | 
|  | 995   // not animated. | 
|  | 996   window.setTimeout(function() { | 
|  | 997     mostVisited.ensureSmallGridCorrect(); | 
|  | 998     document.body.classList.remove('loading'); | 
|  | 999   }, 1); | 
|  | 1000 | 
|  | 1001   // Only show the first run notification if first run. | 
|  | 1002   if (firstRun) { | 
|  | 1003     showFirstRunNotification(); | 
|  | 1004   } | 
|  | 1005 } | 
|  | 1006 | 
|  | 1007 | 
| OLD | NEW | 
|---|