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 |