summaryrefslogtreecommitdiffstats
path: root/chrome/browser/resources
diff options
context:
space:
mode:
authoraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-31 06:00:59 +0000
committeraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-31 06:00:59 +0000
commite8450483095b2b40ae8f78f33d2d2487ee1d1aa6 (patch)
tree23f1c42e290ce35dfd9c06bfb55d81b0b1f353aa /chrome/browser/resources
parent91ffbb3a177fb38b831b2a1fdec21de376f5403e (diff)
downloadchromium_src-e8450483095b2b40ae8f78f33d2d2487ee1d1aa6.zip
chromium_src-e8450483095b2b40ae8f78f33d2d2487ee1d1aa6.tar.gz
chromium_src-e8450483095b2b40ae8f78f33d2d2487ee1d1aa6.tar.bz2
Add an accordian effect to NTP.
BUG=53248 Review URL: http://codereview.chromium.org/3250002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@57966 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/resources')
-rw-r--r--chrome/browser/resources/new_new_tab.css128
-rw-r--r--chrome/browser/resources/new_new_tab.html43
-rw-r--r--chrome/browser/resources/new_new_tab.js198
-rw-r--r--chrome/browser/resources/new_tab_theme.css50
-rw-r--r--chrome/browser/resources/ntp/apps.js2
-rw-r--r--chrome/browser/resources/ntp/most_visited.css2
6 files changed, 304 insertions, 119 deletions
diff --git a/chrome/browser/resources/new_new_tab.css b/chrome/browser/resources/new_new_tab.css
index 5f27622..ef82016 100644
--- a/chrome/browser/resources/new_new_tab.css
+++ b/chrome/browser/resources/new_new_tab.css
@@ -20,8 +20,6 @@ html[mode=app-launcher] {
-webkit-transition: width .15s;
margin: 0 auto;
min-height: 100%;
- padding:10px 0 20px;
- position: relative;
width: 920px;
}
@@ -217,38 +215,11 @@ html[dir=rtl] .item {
pointer-events: none;
}
-#option-button {
- -webkit-appearance: none;
- background-color: transparent;
- width: 19px;
- height: 17px;
- position: absolute;
- right: 0;
- left: auto;
- top: 20px;
- border: 0;
- padding: 0;
- vertical-align: top;
- -webkit-margin-start: 10px;
- /* Do not show focus outline */
- outline: none;
- background-image: url(chrome://theme/IDR_NEWTAB_OPTION);
-}
-
-#option-button:hover,
-#option-button:focus {
- background-image: url(chrome://theme/IDR_NEWTAB_OPTION_H);
-}
-
-#option-button:active,
-#option-button.open {
- background-image: url(chrome://theme/IDR_NEWTAB_OPTION_P);
-}
-
#option-menu {
right: 0;
left: auto;
min-width: 175px;
+ z-index: 3;
}
html[dir=rtl] #option-button,
@@ -322,6 +293,7 @@ html[dir=rtl] #option-menu > [command=hide]:before {
.section > * {
font-size: 12px;
+ width: 920px;
}
.section.disabled {
@@ -329,49 +301,104 @@ html[dir=rtl] #option-menu > [command=hide]:before {
}
.section > div {
- margin-bottom: 15px;
+ padding-bottom: 20px;
}
#apps-section-content {
/* This one is special because the app buttons already have a lot of empty
space around them. */
- margin-bottom: 5px;
+ margin-top: -5px;
+ padding-bottom: 5px;
}
.section > h2 {
- background-position: 0 center;
- background-repeat: no-repeat;
- -webkit-background-size: 100% 26px;
display: block;
font-family: Helvetica, Arial, sans-serif;
font-size: 16px;
font-weight: normal;
- margin:10px 0;
- -webkit-margin-collapse: separate;
+ margin: 0;
+ padding: 15px 0;
+ position: fixed;
+ z-index: 2;
+}
+
+.section:not(.hidden) > h2 {
+ background-position: 0 0, 0 100%;
+ background-repeat: no-repeat;
+ background-size: 100% 39px, 100% 10px;
+}
+
+.section:not(.hidden) + .section > h2 {
+ background-position: 0 0, 0 100%;
+ background-repeat: no-repeat;
+ background-size: 100% 10px, 100% 39px;
}
.section:not([noexpand]) > h2 {
cursor: pointer;
}
-.section > h2 > img {
- margin-left:-13px;
- padding-right:4px;
+/* The first one is special because we want a little extra space at the top of
+the layout. */
+.section:first-child > h2 {
+ padding-top: 20px;
+ background-size: 100% 44px, 100% 10px;
+}
+
+.section > h2 > .disclosure {
+ margin-left: -13px;
+ padding-right: 4px;
}
-.section:not(.hidden) > h2 > img {
+.section:not(.hidden) > h2 > .disclosure {
-webkit-transform:rotate(90deg);
}
+.section > h2 > .back {
+ position: absolute;
+ bottom: 5px;
+ left: 0;
+ width: 100%;
+ height: 19px;
+ background-repeat: no-repeat;
+ z-index: 1;
+}
+
.section > h2 > span {
- padding-right: 4px;
+ padding-right: 5px;
+ position: relative;
+ z-index: 2;
+}
+
+.section > h2 > .settings {
+ position: absolute;
+ top: 18px;
+ right: 0;
+ width: 11px;
+ height: 11px;
+ /* TODO(aa): Need a better image. This one is semi-transparent. Also, I think
+ a gear would be better. */
+ background-image: url(chrome://theme/IDR_BALLOON_WRENCH);
+ background-position: center center;
+ background-repeat: no-repeat;
+ background-size: 100%;
+ border-style: solid;
+ border-width: 0 5px 0 6px;
+ z-index: 2;
+}
+
+.section.hidden > h2 > .settings {
+ display: none;
+}
+
+.section > .maxiview {
+ position: absolute;
}
.section > .miniview {
display: none;
- /* Because the items have 10px horizontal margins. */
- margin-left:-10px;
- margin-right:-10px;
+ position: fixed;
+ z-index: 2;
}
.section.hidden > * {
@@ -402,11 +429,20 @@ html[dir=rtl] #option-menu > [command=hide]:before {
margin: 0 10px;
}
+.miniview > span:first-child {
+ margin-left: 0;
+}
+
+.miniview > span:last-child {
+ margin-right: 0;
+}
+
/* small */
@media (max-width: 940px) {
- #main {
+ #main,
+ .section > * {
width: 692px;
}
diff --git a/chrome/browser/resources/new_new_tab.html b/chrome/browser/resources/new_new_tab.html
index cf93d2d..f14d019 100644
--- a/chrome/browser/resources/new_new_tab.html
+++ b/chrome/browser/resources/new_new_tab.html
@@ -90,13 +90,6 @@ function isRtl() {
return templateData['textdirection'] == 'rtl';
}
-// This will get overridden in new_new_tab.js
-function updateSimpleSection(id, section) {
- // All sections start off shown.
- if (!(shownSections & section))
- document.getElementById(id).className += ' hidden';
-}
-
// Parse any name value pairs passed through the URL hash.
var hashParams = (function() {
var result = {};
@@ -127,9 +120,6 @@ if ('mode' in hashParams) {
<div id="main">
<menu id="option-menu">
- <div command="hide" section="THUMB" i18n-content="mostvisited"></div>
- <div command="hide" section="RECENT" i18n-content="recentlyclosed"></div>
- <hr>
<div command="clear-all-blacklisted"
i18n-content="restorethumbnails"></div>
</menu>
@@ -141,16 +131,17 @@ if ('mode' in hashParams) {
<div class="sections">
<div class="section" section="APPS" id="apps-section">
- <h2><img src="ntp/ntp_disclosure_triangle.png"
- ><span i18n-content="apps"></span></h2>
- <div id="apps-section-content"></div>
+ <h2><img class="disclosure" img src="ntp/ntp_disclosure_triangle.png"
+ ><span i18n-content="apps"></span><div class="back"></div></h2>
+ <div class="maxiview" id="apps-section-content"></div>
<div class="miniview"></div>
</div>
<div id="most-visited-section" class="section" section="THUMB">
- <h2><img src="ntp/ntp_disclosure_triangle.png"
- ><span i18n-content="mostvisited"></span></h2>
- <div id="most-visited"></div>
+ <h2><img class="disclosure" src="ntp/ntp_disclosure_triangle.png"
+ ><span i18n-content="mostvisited"></span
+ ><div class="settings"></div><div class="back"></div></h2>
+ <div class="maxiview" id="most-visited"></div>
<div class="miniview"></div>
</div>
@@ -158,10 +149,12 @@ if ('mode' in hashParams) {
silly without any. -->
<div id="recently-closed" class="section hidden disabled" section="RECENT"
noexpand="true">
- <h2><span i18n-content="recentlyclosed"></span></h2>
+ <h2><span i18n-content="recentlyclosed"></span
+ ><div class="back"></div></h2>
<div class="miniview"></div>
</div>
+ <!-- TODO(aa): Remove this -- we don't use it anymore. -->
<div id="debug" class="section disabled" section="DEBUG">
<h2><span>Debug</span></h2>
<div id="apps-launch-control">
@@ -178,13 +171,6 @@ if ('mode' in hashParams) {
</div>
</div>
- <script>
- updateSimpleSection('apps-section', Section.APPS);
- updateSimpleSection('most-visited-section', Section.THUMB);
- updateSimpleSection('recently-closed', Section.RECENT);
- updateSimpleSection('debug', Section.DEBUG);
- </script>
-
<div id="sync-status">
<h2></h2>
<span></span>
@@ -212,4 +198,13 @@ i18nTemplate.process(document, templateData);
<script src="ntp/most_visited.js"></script>
<script src="new_new_tab.js"></script>
<script src="ntp/apps.js"></script>
+
+<script>
+ updateSimpleSection('apps-section', Section.APPS);
+ updateSimpleSection('most-visited-section', Section.THUMB);
+ updateSimpleSection('recently-closed', Section.RECENT);
+ updateSimpleSection('debug', Section.DEBUG);
+
+ layoutSections();
+</script>
</html>
diff --git a/chrome/browser/resources/new_new_tab.js b/chrome/browser/resources/new_new_tab.js
index 2255005..f780837 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
+// 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.
+ 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;
diff --git a/chrome/browser/resources/new_tab_theme.css b/chrome/browser/resources/new_tab_theme.css
index 40225de..790516a 100644
--- a/chrome/browser/resources/new_tab_theme.css
+++ b/chrome/browser/resources/new_tab_theme.css
@@ -3,7 +3,6 @@ html {
background-color: $2; /* COLOR_NTP_BACKGROUND */
background-position: $3;
background-repeat: $5;
- overflow: hidden;
}
html[bookmarkbarattached='true'] {
@@ -66,11 +65,6 @@ body {
background-color: $$1; /* COLOR_NTP_SECTION */
}
-#option-button {
- background-color: $7; /* color_header_gradient_light */
- -webkit-mask-image: url(chrome://theme/IDR_NEWTAB_MENU_MASK);
-}
-
.miniview {
color: $8; /* COLOR_NTP_TEXT */
}
@@ -106,24 +100,58 @@ body {
}
.section > h2 {
+ background-color: $2; /* COLOR_NTP_BACKGROUND */
+ color: $$8; /* COLOR_NTP_SECTION_HEADER_TEXT */
+}
+
+.section:not(.hidden) > h2 {
+ background-color: transparent;
+ background-image:
+ -webkit-gradient(linear, 0% 0%, 0% 100%, from($2), to($2)),
+ -webkit-gradient(linear, 0% 0%, 0% 100%, from($2), to($$$1));
color: $$9;
- background-image: url(chrome://theme/IDR_NEWTAB_SECTION_HEADER_BACKGROUND_A);
}
-.section.hidden > h2 {
- color: $$8; /* COLOR_NTP_SECTION_HEADER_TEXT */
- background-image: url(chrome://theme/IDR_NEWTAB_SECTION_HEADER_BACKGROUND);
+.section:not(.hidden) + .section > h2 {
+ background-color: transparent;
+ background-image:
+ -webkit-gradient(linear, 0% 0%, 0% 100%, from($$$1), to($2)),
+ -webkit-gradient(linear, 0% 0%, 0% 100%, from($2), to($2));
}
.section.hidden:not([noexpand]) > h2:hover {
color: $$9;
- background-image: url(chrome://theme/IDR_NEWTAB_SECTION_HEADER_BACKGROUND_H);
}
.section > h2 > span {
background: $2; /* COLOR_NTP_BACKGROUND */
}
+.section > h2 > .back {
+ background-image:
+ -webkit-gradient(radial, 50% -1753, 1750, 50% -1753, 1770,
+ from($$$2), to($$$1));
+ border-top: 1px solid $$$2; /* COLOR_NTP_SECTION_HEADER_RULE */
+}
+
+.section.hidden > h2 > .back {
+ background: none;
+ border-color-top: $$$3; /* COLOR_NTP_SECTION_HEADER_RULE_LIGHT */
+}
+
+.section.hidden:hover > h2 > .back {
+ border-color-top: $$$2; /* COLOR_NTP_SECTION_HEADER_RULE */
+}
+
+.section > h2 > .settings {
+ background-color: $2; /* COLOR_NTP_BACKGROUND */
+ border-color: $2; /* COLOR_NTP_BACKGROUND */
+}
+
+.section > .miniview {
+ background: $2; /* COLOR_NTP_BACKGROUND */
+}
+
#apps-section .app a {
color: $8; /* COLOR_NTP_TEXT */
}
diff --git a/chrome/browser/resources/ntp/apps.js b/chrome/browser/resources/ntp/apps.js
index 61712e4..5735b61 100644
--- a/chrome/browser/resources/ntp/apps.js
+++ b/chrome/browser/resources/ntp/apps.js
@@ -19,6 +19,8 @@ function getAppsCallback(data) {
data.apps.slice(0, MAX_MINIVIEW_ITEMS).forEach(function(app) {
appsMiniview.appendChild(apps.createMiniviewElement(app));
});
+
+ layoutSections();
}
var apps = {
diff --git a/chrome/browser/resources/ntp/most_visited.css b/chrome/browser/resources/ntp/most_visited.css
index 25366b8..0bb6735 100644
--- a/chrome/browser/resources/ntp/most_visited.css
+++ b/chrome/browser/resources/ntp/most_visited.css
@@ -4,7 +4,7 @@
position: relative;
padding: 0;
height: 366px;
- margin-top: -10px;
+ margin-top: 0;
-webkit-user-select: none;
}