| 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 |