Chromium Code Reviews| 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 // To avoid creating tons of unnecessary nodes. We assume we cannot fit more | 5 // To avoid creating tons of unnecessary nodes. We assume we cannot fit more |
| 6 // than this many items in the miniview. | 6 // than this many items in the miniview. |
| 7 var MAX_MINIVIEW_ITEMS = 15; | 7 var MAX_MINIVIEW_ITEMS = 15; |
| 8 | 8 |
| 9 // Extra spacing at the top of the layout. | 9 // Extra spacing at the top of the layout. |
| 10 var LAYOUT_SPACING_TOP = 5; | 10 var LAYOUT_SPACING_TOP = 25; |
| 11 | 11 |
| 12 var loading = true; | 12 var loading = true; |
| 13 | 13 |
| 14 function updateSimpleSection(id, section) { | 14 function updateSimpleSection(id, section) { |
| 15 if (shownSections & section) | 15 var elm = $(id); |
| 16 var maxiview = getSectionMaxiview(elm); | |
| 17 if (shownSections & section) { | |
| 16 $(id).classList.remove('hidden'); | 18 $(id).classList.remove('hidden'); |
| 17 else | 19 if (maxiview) |
| 20 maxiview.classList.remove('hidden'); | |
| 21 } else { | |
| 18 $(id).classList.add('hidden'); | 22 $(id).classList.add('hidden'); |
| 23 if (maxiview) | |
| 24 maxiview.classList.add('hidden'); | |
| 25 } | |
| 19 } | 26 } |
| 20 | 27 |
| 21 function recentlyClosedTabs(data) { | 28 function recentlyClosedTabs(data) { |
| 22 logEvent('received recently closed tabs'); | 29 logEvent('received recently closed tabs'); |
| 23 // We need to store the recent items so we can update the layout on a resize. | 30 // We need to store the recent items so we can update the layout on a resize. |
| 24 recentItems = data; | 31 recentItems = data; |
| 25 renderRecentlyClosed(); | 32 renderRecentlyClosed(); |
| 26 layoutSections(); | 33 layoutSections(); |
| 27 } | 34 } |
| 28 | 35 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 94 | 101 |
| 95 layoutSections(); | 102 layoutSections(); |
| 96 } | 103 } |
| 97 | 104 |
| 98 // Stores some information about each section necessary to layout. A new | 105 // Stores some information about each section necessary to layout. A new |
| 99 // instance is constructed for each section on each layout. | 106 // instance is constructed for each section on each layout. |
| 100 function SectionLayoutInfo(section) { | 107 function SectionLayoutInfo(section) { |
| 101 this.section = section; | 108 this.section = section; |
| 102 this.header = section.getElementsByTagName('h2')[0]; | 109 this.header = section.getElementsByTagName('h2')[0]; |
| 103 this.miniview = section.getElementsByClassName('miniview')[0]; | 110 this.miniview = section.getElementsByClassName('miniview')[0]; |
| 104 this.maxiview = section.getElementsByClassName('maxiview')[0]; | 111 this.maxiview = getSectionMaxiview(section); |
| 105 this.expanded = !section.classList.contains('hidden'); | 112 this.expanded = this.maxiview && !section.classList.contains('hidden'); |
| 106 this.fixedHeight = this.header.offsetHeight; | 113 this.fixedHeight = this.section.offsetHeight; |
| 107 this.scrollingHeight = 0; | 114 this.scrollingHeight = 0; |
| 108 | 115 |
| 109 if (this.expanded) { | 116 if (this.expanded) |
| 110 this.scrollingHeight = this.maxiview.offsetHeight; | 117 this.scrollingHeight = this.maxiview.offsetHeight; |
| 111 } else if (this.miniview) { | |
| 112 this.fixedHeight += this.miniview.offsetHeight; | |
| 113 } | |
| 114 } | 118 } |
| 115 | 119 |
| 116 // Get all sections to be layed out. | 120 // Get all sections to be layed out. |
| 117 SectionLayoutInfo.getAll = function() { | 121 SectionLayoutInfo.getAll = function() { |
| 118 var sections = document.querySelectorAll('.section:not(.disabled)'); | 122 var sections = document.querySelectorAll('.section:not(.disabled)'); |
| 119 var result = []; | 123 var result = []; |
| 120 for (var i = 0, section; section = sections[i]; i++) { | 124 for (var i = 0, section; section = sections[i]; i++) { |
| 121 result.push(new SectionLayoutInfo(section)); | 125 result.push(new SectionLayoutInfo(section)); |
| 122 } | 126 } |
| 123 return result; | 127 return result; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 202 'px'; | 206 'px'; |
| 203 } else { | 207 } else { |
| 204 expandedSectionHeight = expandedSection.scrollingHeight; | 208 expandedSectionHeight = expandedSection.scrollingHeight; |
| 205 document.body.style.height = ''; | 209 document.body.style.height = ''; |
| 206 } | 210 } |
| 207 } | 211 } |
| 208 | 212 |
| 209 // Now position all the elements. | 213 // Now position all the elements. |
| 210 var y = LAYOUT_SPACING_TOP; | 214 var y = LAYOUT_SPACING_TOP; |
| 211 for (i = 0, section; section = sections[i]; i++) { | 215 for (i = 0, section; section = sections[i]; i++) { |
| 212 section.header.style.top = y + 'px'; | 216 section.section.style.top = y + 'px'; |
| 213 y += section.header.offsetHeight; | 217 y += section.fixedHeight; |
| 214 | |
| 215 if (section.miniview) { | |
| 216 section.miniview.style.top = y + 'px'; | |
| 217 if (section != expandedSection) { | |
| 218 y += section.miniview.offsetHeight; | |
| 219 } | |
| 220 } | |
| 221 | 218 |
| 222 if (section.maxiview) { | 219 if (section.maxiview) { |
| 223 section.maxiview.style.top = y + 'px'; | 220 section.maxiview.style.top = y + 'px'; |
| 224 if (section == expandedSection) { | 221 |
| 225 y += expandedSectionHeight; | 222 if (section == expandedSection) |
| 226 } | 223 updateMask(section.maxiview, expandedSectionHeight); |
| 227 } | 224 } |
| 225 | |
| 226 if (section == expandedSection) | |
| 227 y += expandedSectionHeight; | |
| 228 } | 228 } |
| 229 } | 229 } |
| 230 | 230 |
| 231 function updateMask(maxiview, visibleHeightPx) { | |
| 232 // We want to end up with 10px gradients at the top and bottom of | |
| 233 // visibleHeight, but webkit-mask only supports expression in terms of | |
| 234 // percentages. | |
| 235 | |
| 236 // We might not have enough room to do 10px gradients on each side. To get the | |
| 237 // right effect, we don't want to make the gradients smaller, but make them | |
| 238 // appear to mush into each other. | |
| 239 var gradientHeightPx = Math.min(10, Math.floor(visibleHeightPx / 2)); | |
| 240 var gradientDestination = "rgba(0,0,0," + (gradientHeightPx / 10) + ")"; | |
|
arv (Not doing code reviews)
2010/09/03 00:24:22
s/"/'/
| |
| 241 | |
| 242 var bottomSpacing = 15; | |
| 243 var first = parseFloat(maxiview.style.top) / window.innerHeight; | |
| 244 var second = first + gradientHeightPx / window.innerHeight; | |
| 245 var fourth = first + (visibleHeightPx - bottomSpacing) / window.innerHeight; | |
| 246 var third = fourth - gradientHeightPx / window.innerHeight; | |
| 247 | |
| 248 var gradientArguments = [ | |
| 249 "linear", | |
| 250 "0 0", | |
| 251 "0 100%", | |
| 252 "from(transparent)", | |
| 253 getColorStopString(first, "transparent"), | |
| 254 getColorStopString(second, gradientDestination), | |
| 255 getColorStopString(third, gradientDestination), | |
| 256 getColorStopString(fourth, "transparent"), | |
| 257 "to(transparent)" | |
| 258 ]; | |
| 259 | |
| 260 var gradient = '-webkit-gradient(' + gradientArguments.join(', ') + ')'; | |
| 261 console.log(gradient); | |
|
arv (Not doing code reviews)
2010/09/03 00:24:22
can you remove this log?
| |
| 262 maxiview.style.WebkitMaskImage = gradient; | |
| 263 } | |
| 264 | |
| 265 function getColorStopString(height, color) { | |
| 266 return "color-stop(" + height + ", " + color + ")"; | |
| 267 } | |
| 268 | |
| 231 window.addEventListener('resize', handleWindowResize); | 269 window.addEventListener('resize', handleWindowResize); |
| 232 | 270 |
| 233 var sectionToElementMap; | 271 var sectionToElementMap; |
| 234 function getSectionElement(section) { | 272 function getSectionElement(section) { |
| 235 if (!sectionToElementMap) { | 273 if (!sectionToElementMap) { |
| 236 sectionToElementMap = {}; | 274 sectionToElementMap = {}; |
| 237 for (var key in Section) { | 275 for (var key in Section) { |
| 238 sectionToElementMap[Section[key]] = | 276 sectionToElementMap[Section[key]] = |
| 239 document.querySelector('.section[section=' + key + ']'); | 277 document.querySelector('.section[section=' + key + ']'); |
| 240 } | 278 } |
| 241 } | 279 } |
| 242 return sectionToElementMap[section]; | 280 return sectionToElementMap[section]; |
| 243 } | 281 } |
| 244 | 282 |
| 283 function getSectionMaxiview(section) { | |
| 284 return $(section.id + '-maxiview'); | |
| 285 } | |
| 286 | |
| 245 function showSection(section) { | 287 function showSection(section) { |
| 246 if (!(section & shownSections)) { | 288 if (!(section & shownSections)) { |
| 247 shownSections |= section; | 289 shownSections |= section; |
| 248 var el = getSectionElement(section); | 290 var el = getSectionElement(section); |
| 249 if (el) | 291 if (el) { |
| 250 el.classList.remove('hidden'); | 292 el.classList.remove('hidden'); |
| 251 | 293 |
| 294 var maxiview = getSectionMaxiview(el); | |
| 295 if (maxiview) | |
| 296 maxiview.classList.remove('hidden'); | |
| 297 } | |
| 298 | |
| 252 switch (section) { | 299 switch (section) { |
| 253 case Section.THUMB: | 300 case Section.THUMB: |
| 254 mostVisited.visible = true; | 301 mostVisited.visible = true; |
| 255 mostVisited.layout(); | 302 mostVisited.layout(); |
| 256 break; | 303 break; |
| 257 } | 304 } |
| 258 } | 305 } |
| 259 } | 306 } |
| 260 | 307 |
| 261 function hideSection(section) { | 308 function hideSection(section) { |
| 262 if (section & shownSections) { | 309 if (section & shownSections) { |
| 263 shownSections &= ~section; | 310 shownSections &= ~section; |
| 264 | 311 |
| 265 switch (section) { | 312 switch (section) { |
| 266 case Section.THUMB: | 313 case Section.THUMB: |
| 267 mostVisited.visible = false; | 314 mostVisited.visible = false; |
| 268 mostVisited.layout(); | 315 mostVisited.layout(); |
| 269 break; | 316 break; |
| 270 } | 317 } |
| 271 | 318 |
| 272 var el = getSectionElement(section); | 319 var el = getSectionElement(section); |
| 273 if (el) | 320 if (el) { |
| 274 el.classList.add('hidden'); | 321 el.classList.add('hidden'); |
| 322 | |
| 323 var maxiview = getSectionMaxiview(el); | |
| 324 if (maxiview) | |
| 325 maxiview.classList.add('hidden'); | |
| 326 } | |
| 275 } | 327 } |
| 276 } | 328 } |
| 277 | 329 |
| 278 /** | 330 /** |
| 279 * Callback when the shown sections changes in another NTP. | 331 * Callback when the shown sections changes in another NTP. |
| 280 * @param {number} newShownSections Bitmask of the shown sections. | 332 * @param {number} newShownSections Bitmask of the shown sections. |
| 281 */ | 333 */ |
| 282 function setShownSections(newShownSections) { | 334 function setShownSections(newShownSections) { |
| 283 for (var key in Section) { | 335 for (var key in Section) { |
| 284 if (newShownSections & Section[key]) | 336 if (newShownSections & Section[key]) |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 333 * linkisvisible is true). | 385 * linkisvisible is true). |
| 334 * linkurlisset: true if an URL should be set as the href for the link and false | 386 * linkurlisset: true if an URL should be set as the href for the link and false |
| 335 * otherwise. If this field is false, then clicking on the link | 387 * otherwise. If this field is false, then clicking on the link |
| 336 * will result in sending a message to the backend (see | 388 * will result in sending a message to the backend (see |
| 337 * 'SyncLinkClicked'). | 389 * 'SyncLinkClicked'). |
| 338 * linkurl: the URL to use as the element's href (only used if linkurlisset is | 390 * linkurl: the URL to use as the element's href (only used if linkurlisset is |
| 339 * true). | 391 * true). |
| 340 */ | 392 */ |
| 341 function syncMessageChanged(newMessage) { | 393 function syncMessageChanged(newMessage) { |
| 342 var syncStatusElement = $('sync-status'); | 394 var syncStatusElement = $('sync-status'); |
| 343 var style = syncStatusElement.style; | |
| 344 | 395 |
| 345 // Hide the section if the message is emtpy. | 396 // Hide the section if the message is emtpy. |
| 346 if (!newMessage['syncsectionisvisible']) { | 397 if (!newMessage['syncsectionisvisible']) { |
| 347 style.display = 'none'; | 398 syncStatusElement.classList.add('disabled'); |
| 348 return; | 399 return; |
| 349 } | 400 } |
| 350 style.display = 'block'; | 401 |
| 402 syncStatusElement.classList.remove('disabled'); | |
| 403 | |
| 404 var content = syncStatusElement.children[0]; | |
| 351 | 405 |
| 352 // Set the sync section background color based on the state. | 406 // Set the sync section background color based on the state. |
| 353 if (newMessage.msgtype == 'error') { | 407 if (newMessage.msgtype == 'error') { |
| 354 style.backgroundColor = 'tomato'; | 408 content.style.backgroundColor = 'tomato'; |
| 355 } else { | 409 } else { |
| 356 style.backgroundColor = ''; | 410 content.style.backgroundColor = ''; |
| 357 } | 411 } |
| 358 | 412 |
| 359 // Set the text for the header and sync message. | 413 // Set the text for the header and sync message. |
| 360 var titleElement = syncStatusElement.firstElementChild; | 414 var titleElement = content.firstElementChild; |
| 361 titleElement.textContent = newMessage.title; | 415 titleElement.textContent = newMessage.title; |
| 362 var messageElement = titleElement.nextElementSibling; | 416 var messageElement = titleElement.nextElementSibling; |
| 363 messageElement.textContent = newMessage.msg; | 417 messageElement.textContent = newMessage.msg; |
| 364 | 418 |
| 365 // Remove what comes after the message | 419 // Remove what comes after the message |
| 366 while (messageElement.nextSibling) { | 420 while (messageElement.nextSibling) { |
| 367 syncStatusElement.removeChild(messageElement.nextSibling); | 421 content.removeChild(messageElement.nextSibling); |
| 368 } | 422 } |
| 369 | 423 |
| 370 if (newMessage.linkisvisible) { | 424 if (newMessage.linkisvisible) { |
| 371 var el; | 425 var el; |
| 372 if (newMessage.linkurlisset) { | 426 if (newMessage.linkurlisset) { |
| 373 // Use a link | 427 // Use a link |
| 374 el = document.createElement('a'); | 428 el = document.createElement('a'); |
| 375 el.href = newMessage.linkurl; | 429 el.href = newMessage.linkurl; |
| 376 } else { | 430 } else { |
| 377 el = document.createElement('button'); | 431 el = document.createElement('button'); |
| 378 el.className = 'link'; | 432 el.className = 'link'; |
| 379 el.addEventListener('click', syncSectionLinkClicked); | 433 el.addEventListener('click', syncSectionLinkClicked); |
| 380 } | 434 } |
| 381 el.textContent = newMessage.linktext; | 435 el.textContent = newMessage.linktext; |
| 382 syncStatusElement.appendChild(el); | 436 content.appendChild(el); |
| 383 fixLinkUnderline(el); | 437 fixLinkUnderline(el); |
| 384 } | 438 } |
| 439 | |
| 440 layoutSections(); | |
| 385 } | 441 } |
| 386 | 442 |
| 387 /** | 443 /** |
| 388 * Invoked when the link in the sync status section is clicked. | 444 * Invoked when the link in the sync status section is clicked. |
| 389 */ | 445 */ |
| 390 function syncSectionLinkClicked(e) { | 446 function syncSectionLinkClicked(e) { |
| 391 chrome.send('SyncLinkClicked'); | 447 chrome.send('SyncLinkClicked'); |
| 392 e.preventDefault(); | 448 e.preventDefault(); |
| 393 } | 449 } |
| 394 | 450 |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 713 var command = item.getAttribute('command'); | 769 var command = item.getAttribute('command'); |
| 714 if (command in this.commands) { | 770 if (command in this.commands) { |
| 715 this.commands[command].call(this, item); | 771 this.commands[command].call(this, item); |
| 716 } | 772 } |
| 717 | 773 |
| 718 this.hide(); | 774 this.hide(); |
| 719 } | 775 } |
| 720 }; | 776 }; |
| 721 | 777 |
| 722 var optionMenu = new OptionMenu( | 778 var optionMenu = new OptionMenu( |
| 723 document.querySelector('#most-visited-section h2 .settings-wrapper'), | 779 document.querySelector('#most-visited h2 .settings-wrapper'), |
| 724 $('option-menu')); | 780 $('option-menu')); |
| 725 optionMenu.commands = { | 781 optionMenu.commands = { |
| 726 'clear-all-blacklisted' : function() { | 782 'clear-all-blacklisted' : function() { |
| 727 mostVisited.clearAllBlacklisted(); | 783 mostVisited.clearAllBlacklisted(); |
| 728 chrome.send('getMostVisited'); | 784 chrome.send('getMostVisited'); |
| 729 } | 785 } |
| 730 }; | 786 }; |
| 731 | 787 |
| 732 $('main').addEventListener('click', function(e) { | 788 $('main').addEventListener('click', function(e) { |
| 733 var p = e.target; | 789 var p = e.target; |
| 734 while (p && p.tagName != 'H2') { | 790 while (p && p.tagName != 'H2') { |
| 735 p = p.parentNode; | 791 p = p.parentNode; |
| 736 } | 792 } |
| 737 | 793 |
| 738 if (!p) { | 794 if (!p) { |
| 739 return; | 795 return; |
| 740 } | 796 } |
| 741 | 797 |
| 742 p = p.parentNode; | 798 p = p.parentNode; |
| 743 if (p.hasAttribute('noexpand')) { | 799 if (!getSectionMaxiview(p)) { |
| 744 return; | 800 return; |
| 745 } | 801 } |
| 746 | 802 |
| 747 var section = p.getAttribute('section'); | 803 var section = p.getAttribute('section'); |
| 748 if (section) { | 804 if (section) { |
| 749 if (shownSections & Section[section]) { | 805 if (shownSections & Section[section]) { |
| 750 hideSection(Section[section]); | 806 hideSection(Section[section]); |
| 751 } else { | 807 } else { |
| 752 for (var p in Section) { | 808 for (var p in Section) { |
| 753 if (p == section) | 809 if (p == section) |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 996 span.className = 'link-color'; | 1052 span.className = 'link-color'; |
| 997 while (el.hasChildNodes()) { | 1053 while (el.hasChildNodes()) { |
| 998 span.appendChild(el.firstChild); | 1054 span.appendChild(el.firstChild); |
| 999 } | 1055 } |
| 1000 el.appendChild(span); | 1056 el.appendChild(span); |
| 1001 } | 1057 } |
| 1002 | 1058 |
| 1003 updateAttribution(); | 1059 updateAttribution(); |
| 1004 | 1060 |
| 1005 var mostVisited = new MostVisited( | 1061 var mostVisited = new MostVisited( |
| 1006 $('most-visited'), | 1062 $('most-visited-maxiview'), |
| 1007 document.querySelector('#most-visited-section .miniview'), | 1063 document.querySelector('#most-visited .miniview'), |
| 1008 useSmallGrid(), | 1064 useSmallGrid(), |
| 1009 shownSections & Section.THUMB); | 1065 shownSections & Section.THUMB); |
| 1010 | 1066 |
| 1011 function mostVisitedPages(data, firstRun) { | 1067 function mostVisitedPages(data, firstRun) { |
| 1012 logEvent('received most visited pages'); | 1068 logEvent('received most visited pages'); |
| 1013 | 1069 |
| 1014 mostVisited.data = data; | 1070 mostVisited.data = data; |
| 1015 mostVisited.layout(); | 1071 mostVisited.layout(); |
| 1016 layoutSections(); | 1072 layoutSections(); |
| 1017 | 1073 |
| 1018 loading = false; | 1074 loading = false; |
| 1019 | 1075 |
| 1020 // Remove class name in a timeout so that changes done in this JS thread are | 1076 // Remove class name in a timeout so that changes done in this JS thread are |
| 1021 // not animated. | 1077 // not animated. |
| 1022 window.setTimeout(function() { | 1078 window.setTimeout(function() { |
| 1023 mostVisited.ensureSmallGridCorrect(); | 1079 mostVisited.ensureSmallGridCorrect(); |
| 1024 document.body.classList.remove('loading'); | 1080 document.body.classList.remove('loading'); |
| 1025 }, 1); | 1081 }, 1); |
| 1026 | 1082 |
| 1027 // Only show the first run notification if first run. | 1083 // Only show the first run notification if first run. |
| 1028 if (firstRun) { | 1084 if (firstRun) { |
| 1029 showFirstRunNotification(); | 1085 showFirstRunNotification(); |
| 1030 } | 1086 } |
| 1031 } | 1087 } |
| OLD | NEW |