Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2200)

Unified Diff: chrome/browser/resources/new_new_tab.js

Issue 3250002: Add an accordian effect to NTP. (Closed)
Patch Set: Fix menu positioning when there is a scrollbar. Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/new_new_tab.js
diff --git a/chrome/browser/resources/new_new_tab.js b/chrome/browser/resources/new_new_tab.js
index 2255005c901ac48b6d06fb30f5788373b54d7c78..f78083701f7ad74a8d0647f3c88afc1bf97c5a9c 100644
--- a/chrome/browser/resources/new_new_tab.js
+++ b/chrome/browser/resources/new_new_tab.js
@@ -20,6 +20,7 @@ function recentlyClosedTabs(data) {
// We need to store the recent items so we can update the layout on a resize.
recentItems = data;
renderRecentlyClosed();
+ layoutSections();
}
var recentItems = [];
@@ -87,6 +88,141 @@ function handleWindowResize() {
mostVisited.layout();
renderRecentlyClosed();
}
+
+ layoutSections();
+}
+
+// Stores some information about each section necessary to layout. A new
+// instance is constructed for each section on each layout.
+function SectionLayoutInfo(section) {
+ this.section = section;
+ this.header = section.getElementsByTagName('h2')[0];
+ this.miniview = section.getElementsByClassName('miniview')[0];
+ this.maxiview = section.getElementsByClassName('maxiview')[0];
+ this.expanded = !section.classList.contains('hidden');
+ this.fixedHeight = this.header.offsetHeight;
+ this.scrollingHeight = 0;
+
+ if (this.expanded) {
+ this.scrollingHeight = this.maxiview.offsetHeight;
+ } else if (this.miniview) {
+ this.fixedHeight += this.miniview.offsetHeight;
+ }
+}
+
+// Get all sections to be layed out.
+SectionLayoutInfo.getAll = function() {
+ var sections = document.querySelectorAll('.section:not(.disabled)');
+ var result = [];
+ for (var i = 0, section; section = sections[i]; i++) {
+ result.push(new SectionLayoutInfo(section));
+ }
+ return result;
+};
+
+// Layout the sections in a modified accordian. The header and miniview, if
arv (Not doing code reviews) 2010/08/31 21:13:59 accordion
+// visible are fixed within the viewport. If there is an expanded section, its
+// it scrolls.
+//
+// =============================
+// | collapsed section | <- Any collapsed sections are fixed position.
+// | and miniview |
+// |---------------------------|
+// | expanded section |
+// | | <- There can be one expanded section and it
+// | and maxiview | is absolutely positioned so that it can
+// | | scroll "underneath" the fixed elements.
+// | |
+// |---------------------------|
+// | another collapsed section |
+// |---------------------------|
+//
+// We want the main frame scrollbar to be the one that scrolls the expanded
+// region. To get this effect, we make the fixed elements position:fixed and the
+// scrollable element position:absolute. We also artificially increase the
+// height of the document so that it is possible to scroll down enough to
+// display the end of the document, even with any fixed elements at the bottom
+// of the viewport.
+//
+// There is a final twist: If the intrinsic height of the expanded section is
+// less than the available height (because the window is tall), any collapsed
+// sections sinch up and sit below the expanded section. This is so that we
+// don't have a bunch of dead whitespace in the case of expanded sections that
+// aren't very tall.
+function layoutSections() {
+ var sections = SectionLayoutInfo.getAll();
+ var expandedSection = null;
+ var headerHeight = 0;
+ var footerHeight = 0;
+
+ // Calculate the height of the fixed elements above the expanded section. Also
+ // take note of the expanded section, if there is one.
+ var i;
+ var section;
+ for (i = 0; section = sections[i]; i++) {
+ headerHeight += section.fixedHeight;
+ if (section.expanded) {
+ expandedSection = section;
+ i++;
+ break;
+ }
+ }
+
+ // Calculate the height of the fixed elements below the expanded section, if
+ // any.
+ for (; section = sections[i]; i++) {
+ footerHeight += section.fixedHeight;
+ }
+
+ // Determine the height to use for the expanded section. If there isn't enough
+ // space to show the expanded section completely, this will be the available
+ // height. Otherwise, we use the intrinsic height of the expanded section.
+ var expandedSectionHeight;
+ if (expandedSection) {
+ var flexHeight = window.innerHeight - headerHeight - footerHeight;
+ if (flexHeight < expandedSection.scrollingHeight) {
+ expandedSectionHeight = flexHeight;
+
+ // Also, artificially expand the height of the document so that we can see
+ // the entire expanded section.
+ //
+ // TODO(aa): Where does this come from? It is the difference between what
+ // we set document.body.style.height to and what
+ // document.body.scrollHeight measures afterward. I expect them to be the
+ // same if document.body has no margins.
arv (Not doing code reviews) 2010/08/31 21:13:59 I think we had a padding or margin on the body to
+ var fudge = 44;
+ document.body.style.height =
+ headerHeight +
+ expandedSection.scrollingHeight +
+ footerHeight +
+ fudge +
+ 'px';
+ } else {
+ expandedSectionHeight = expandedSection.scrollingHeight;
+ document.body.style.height = '';
+ }
+ }
+
+ // Now position all the elements.
+ var y = 0;
+ for (i = 0, section; section = sections[i]; i++) {
+ section.header.style.top = y + 'px';
+ y += section.header.offsetHeight;
+
+ if (section.miniview) {
+ section.miniview.style.top = y + 'px';
+ if (section != expandedSection) {
+ y += section.miniview.offsetHeight;
+ }
+ }
+
+ if (section.maxiview) {
+ section.maxiview.style.top = y + 'px';
+ if (section == expandedSection) {
+ y += expandedSectionHeight;
+ }
+ }
+ }
}
window.addEventListener('resize', handleWindowResize);
@@ -147,6 +283,7 @@ function setShownSections(newShownSections) {
else
hideSection(Section[key]);
}
+ layoutSections();
}
// Recently closed
@@ -303,20 +440,6 @@ function viewLog() {
console.log(lines.join('\n'));
}
-// Updates the visibility of the menu items.
-function updateOptionMenu() {
- var menuItems = $('option-menu').children;
- for (var i = 0; i < menuItems.length; i++) {
- var item = menuItems[i];
- var command = item.getAttribute('command');
- if (command == 'show' || command == 'hide') {
- var section = Section[item.getAttribute('section')];
- var visible = shownSections & section;
- item.setAttribute('command', visible ? 'hide' : 'show');
- }
- }
-}
-
// We apply the size class here so that we don't trigger layout animations
// onload.
@@ -416,6 +539,7 @@ function showFirstRunNotification() {
function OptionMenu(button, menu) {
this.button = button;
this.menu = menu;
+ this.button.onclick = bind(this.handleClick, this);
this.button.onmousedown = bind(this.handleMouseDown, this);
this.button.onkeydown = bind(this.handleKeyDown, this);
this.boundHideMenu_ = bind(this.hide, this);
@@ -427,7 +551,6 @@ function OptionMenu(button, menu) {
OptionMenu.prototype = {
show: function() {
- updateOptionMenu();
this.positionMenu_();
this.menu.style.display = 'block';
this.button.classList.add('open');
@@ -440,7 +563,9 @@ OptionMenu.prototype = {
},
positionMenu_: function() {
- this.menu.style.top = this.button.getBoundingClientRect().bottom + 'px';
+ var rect = this.button.getBoundingClientRect();
+ this.menu.style.top = rect.bottom + 'px';
+ this.menu.style.right = (document.body.clientWidth - rect.right) + 'px'
},
hide: function() {
@@ -476,6 +601,10 @@ OptionMenu.prototype = {
}
},
+ handleClick: function(e) {
+ e.stopPropagation();
+ },
+
handleMouseOver: function(e) {
var el = e.target;
if (!el.hasAttribute('command')) {
@@ -587,27 +716,15 @@ OptionMenu.prototype = {
}
};
-// TODO(aa): The 'clear-all-blacklisted' feature needs to move into a menu in
-// the most visited section.
-/*
-var optionMenu = new OptionMenu($('option-button'), $('option-menu'));
+var optionMenu = new OptionMenu(
+ document.querySelector('#most-visited-section h2 .settings'),
+ $('option-menu'));
optionMenu.commands = {
'clear-all-blacklisted' : function() {
mostVisited.clearAllBlacklisted();
chrome.send('getMostVisited');
- },
- 'show': function(item) {
- var section = Section[item.getAttribute('section')];
- showSection(section);
- saveShownSections();
- },
- 'hide': function(item) {
- var section = Section[item.getAttribute('section')];
- hideSection(section);
- saveShownSections();
}
};
-*/
$('main').addEventListener('click', function(e) {
var p = e.target;
@@ -626,10 +743,17 @@ $('main').addEventListener('click', function(e) {
var section = p.getAttribute('section');
if (section) {
- if (shownSections & Section[section])
+ if (shownSections & Section[section]) {
hideSection(Section[section]);
- else
- showSection(Section[section]);
+ } else {
+ for (var p in Section) {
+ if (p == section)
+ showSection(Section[p]);
+ else
+ hideSection(Section[p]);
+ }
+ }
+ layoutSections();
saveShownSections();
}
});
@@ -821,8 +945,7 @@ function callGetSyncMessageIfSyncIsPresent() {
}
function hideAllMenus() {
- // TODO(aa): See comment in definition of optionMenu.
- //optionMenu.hide();
+ optionMenu.hide();
}
window.addEventListener('blur', hideAllMenus);
@@ -878,7 +1001,7 @@ updateAttribution();
var mostVisited = new MostVisited(
$('most-visited'),
- $('most-visited-section').getElementsByClassName('miniview')[0],
+ document.querySelector('#most-visited-section .miniview'),
useSmallGrid(),
shownSections & Section.THUMB);
@@ -887,6 +1010,7 @@ function mostVisitedPages(data, firstRun) {
mostVisited.data = data;
mostVisited.layout();
+ layoutSections();
loading = false;

Powered by Google App Engine
This is Rietveld 408576698