diff options
author | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-01 23:58:13 +0000 |
---|---|---|
committer | thakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-01 23:58:13 +0000 |
commit | 6d9f4e810c1ac13e46b0fdd1c2ca64d8a64488ba (patch) | |
tree | 50b3473b2f8b286e0b6c73ad308f8f2325c6aaec /chrome/browser/resources | |
parent | 73c4532bd7f5b84bc822a4acca5c5b8affef4129 (diff) | |
download | chromium_src-6d9f4e810c1ac13e46b0fdd1c2ca64d8a64488ba.zip chromium_src-6d9f4e810c1ac13e46b0fdd1c2ca64d8a64488ba.tar.gz chromium_src-6d9f4e810c1ac13e46b0fdd1c2ca64d8a64488ba.tar.bz2 |
Make it possible to hide "most visited" on nnnnnnntp
This implements http://folder/glen/chrome/spec/101_ntp/8_wish&sidebar mocks 2, 5, 6
It's a bit lame to use a bit in the "sections" bitmask to serialize the "should show?" information, but the damage here was done when someone decided to that "THUBMS bit missing" should mean "show a list instead" (instead of adding another bit for that).
BUG=55148
TEST=Hover "Most Visited" bar. Close button should appear. Clicking it should hide "Most Visited" area and add a button at the window edge. That button should have a menu that makes it possible to make the "Most Visited" area visible again. Also do this while multiple NTPs are open; the changes made in the front NTP should be synced to the background NTPs.
Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=61095
Review URL: http://codereview.chromium.org/3455007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@61259 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/resources')
-rw-r--r-- | chrome/browser/resources/new_new_tab.css | 66 | ||||
-rw-r--r-- | chrome/browser/resources/new_new_tab.html | 58 | ||||
-rw-r--r-- | chrome/browser/resources/new_new_tab.js | 149 | ||||
-rw-r--r-- | chrome/browser/resources/new_tab_theme.css | 6 | ||||
-rw-r--r-- | chrome/browser/resources/ntp/apps.js | 23 | ||||
-rw-r--r-- | chrome/browser/resources/ntp/most_visited.js | 17 |
6 files changed, 303 insertions, 16 deletions
diff --git a/chrome/browser/resources/new_new_tab.css b/chrome/browser/resources/new_new_tab.css index b3bfd35..9d72dff 100644 --- a/chrome/browser/resources/new_new_tab.css +++ b/chrome/browser/resources/new_new_tab.css @@ -279,7 +279,8 @@ html[anim=true][enable-section-animations=true] .section { -webkit-transition: top .15s; } -.section.disabled { +.section.disabled, +#closed-sections-bar .disabled { display: none !important; } @@ -313,7 +314,7 @@ html[anim=true] .section > h2 > .disclosure { } .section:not(.hidden) > h2 > .disclosure { - -webkit-transform:rotate(90deg); + -webkit-transform: rotate(90deg); } .section > h2 .back { @@ -331,6 +332,67 @@ html[anim=true] .section > h2 > .disclosure { z-index: 2; } +.section-close-button { + -webkit-appearance: none; + -webkit-transition: opacity .15s; + background-color: transparent; + background-image: url(chrome://theme/IDR_CLOSE_BAR); + background-position: center center; + background-repeat no-repeat; + border: 0; + height: 21px; + margin-top: -10px; + position: absolute; + right: -21px; + top: 50%; + width: 21px; + opacity: 0; + z-index: 3; +} + +html[dir=rtl] .section-close-button { + left: -21px; + right: auto; +} + +.section > h2:hover .section-close-button, +.section-close-button:hover { + opacity: 1; +} + +.section-close-button:hover { + background-image: url(chrome://theme/IDR_CLOSE_BAR_H); +} + +#closed-sections-bar { + position: fixed; + bottom: 5px; +} + +#closed-sections-bar > button { + -webkit-appearance: none; + background: none; + border: 0; + cursor: pointer; + font: inherit; + margin: 0; + margin-right: 1.5em; + padding: 0; + + /* Note: The font here should end up the same as .section > h2. A different + percentage is needed because the parent element here has a different size. */ + font-family: Helvetica, Arial, sans-serif; + font-size: 122%; + font-weight: normal; +} + +#closed-sections-bar > button > img { + -webkit-transform: rotate(90deg); + position: relative; + top: -2px; + margin-left: 1px; +} + .maxiview { padding: 5px 0 30px; position: absolute; diff --git a/chrome/browser/resources/new_new_tab.html b/chrome/browser/resources/new_new_tab.html index 369cec0..8700500 100644 --- a/chrome/browser/resources/new_new_tab.html +++ b/chrome/browser/resources/new_new_tab.html @@ -67,10 +67,16 @@ registerCallback('setShownSections'); * @enum {number} */ var Section = { - THUMB: 1, - APPS: 64 + THUMB: 1 << 0, + APPS: 1 << 6 }; +// These are used to hide sections and are part of the |shownSections| bitmask, +// but are not sections themselves. +var MINIMIZED_THUMB = 1 << (0 + 16); +var MINIMIZED_RECENT = 1 << (2 + 16); +var MINIMIZED_APPS = 1 << (6 + 16); + var shownSections = templateData['shown_sections']; // Until themes can clear the cache, force-reload the theme stylesheet. @@ -135,6 +141,7 @@ if ('mode' in hashParams) { <img class="disclosure" img src="ntp/ntp_disclosure_triangle.png"> <div class="back"></div> <span i18n-content="apps"></span> + <button class="section-close-button"></button> </h2> <div class="miniview"></div> </div> @@ -146,6 +153,7 @@ if ('mode' in hashParams) { <span i18n-content="mostvisited"></span> <button id="most-visited-settings" i18n-content="restorethumbnails"> </button> + <button class="section-close-button"></button> </h2> <div class="miniview"></div> </div> @@ -157,6 +165,7 @@ if ('mode' in hashParams) { <h2> <div class="back"></div> <span i18n-content="recentlyclosed"></span> + <button class="section-close-button"></button> </h2> <div class="miniview"></div> </div> @@ -168,6 +177,27 @@ if ('mode' in hashParams) { </div> </div> </div> + + <div id="closed-sections-bar"> + <!-- The default visibility of these buttons needs to be the opposite of the + default visibility of the corresponding sections. --> + <button id="apps-button" + menu="#apps-menu"> + <span i18n-content="apps"></span> + <img src="ntp/ntp_disclosure_triangle.png"> + </button> + <button id="most-visited-button" + class="disabled" + menu="#most-visited-menu"> + <span i18n-content="mostvisited"></span> + <img src="ntp/ntp_disclosure_triangle.png"> + </button> + <button id="recently-closed-button" + menu="#recently-closed-menu"> + <span i18n-content="recentlyclosed"></span> + <img src="ntp/ntp_disclosure_triangle.png"> + </button> + </div> </div> <!-- main --> <div class="window-menu" id="window-tooltip"></div> @@ -194,6 +224,11 @@ if ('mode' in hashParams) { <button command="#apps-uninstall-command"></button> </menu> +<!-- These are populated dynamically --> +<menu id="apps-menu"></menu> +<menu id="most-visited-menu"></menu> +<menu id="recently-closed-menu"></menu> + </body> <script src="shared/js/i18n_template.js"></script> @@ -226,8 +261,27 @@ cr.ui.decorate('button[menu]', cr.ui.MenuButton); </script> <script> + initializeSection('apps', MINIMIZED_APPS, Section.APPS); + initializeSection('most-visited', MINIMIZED_THUMB, Section.THUMB); + initializeSection('recently-closed', MINIMIZED_RECENT); + updateSimpleSection('apps', Section.APPS); updateSimpleSection('most-visited', Section.THUMB); + var appsInitiallyVisible = !(shownSections & MINIMIZED_APPS); + var mostVisitedInitiallyVisible = !(shownSections & MINIMIZED_THUMB); + var recentlyClosedInitiallyVisible = !(shownSections & MINIMIZED_RECENT); + // Apps and recently closed start as hidden in the HTML, most visited is + // initially visible. Adapt to the change received from the prefs by forcing + // all three sections to update. + shownSections &= ~MINIMIZED_THUMB; + shownSections |= MINIMIZED_APPS | MINIMIZED_RECENT; + setSectionVisible('apps', Section.APPS, appsInitiallyVisible, MINIMIZED_APPS); + setSectionVisible( + 'most-visited', Section.THUMB, + mostVisitedInitiallyVisible, MINIMIZED_THUMB); + setSectionVisible( + 'recently-closed', undefined, + recentlyClosedInitiallyVisible, MINIMIZED_RECENT); layoutSections(); </script> </html> diff --git a/chrome/browser/resources/new_new_tab.js b/chrome/browser/resources/new_new_tab.js index c201dda..b7e292a 100644 --- a/chrome/browser/resources/new_new_tab.js +++ b/chrome/browser/resources/new_new_tab.js @@ -9,6 +9,95 @@ var MAX_MINIVIEW_ITEMS = 15; // Extra spacing at the top of the layout. var LAYOUT_SPACING_TOP = 25; +function getSectionCloseButton(sectionId) { + return document.querySelector('#' + sectionId + ' .section-close-button'); +} + +function getSectionMenuButton(sectionId) { + return $(sectionId + '-button'); +} + +function getSectionMenuButtonTextId(sectionId) { + return sectionId.replace(/-/g, ''); +} + +function setSectionVisible(sectionId, section, visible, hideMask) { + if (visible && !(shownSections & hideMask) || + !visible && (shownSections & hideMask)) + return; + + if (visible) { + // Because sections are collapsed when they are minimized, it is not + // necessary to restore the maxiview here. It will happen if the section + // header is clicked. + var el = $(sectionId); + el.classList.remove('disabled'); + el = getSectionMenuButton(sectionId); + el.classList.add('disabled'); + shownSections &= ~hideMask; + } else { + if (section) { + hideSection(section); // To hide the maxiview. + } + var el = $(sectionId); + el.classList.add('disabled'); + el = getSectionMenuButton(sectionId); + el.classList.remove('disabled'); + shownSections |= hideMask; + } + layoutSections(); +} + +function clearClosedMenu(menu) { + menu.innerHTML = ''; +} + +function addClosedMenuEntryWithLink(menu, a) { + var span = document.createElement('span'); + a.className += ' item menuitem'; + span.appendChild(a); + menu.appendChild(span); +} + +function addClosedMenuEntry(menu, url, title, imageUrl) { + var a = document.createElement('a'); + a.href = url; + a.textContent = title; + a.style.backgroundImage = 'url(' + imageUrl + ')'; + addClosedMenuEntryWithLink(menu, a); +} + +function addClosedMenuFooter(menu, sectionId, mask, opt_section) { + menu.appendChild(document.createElement('hr')); + + var span = document.createElement('span'); + var a = span.appendChild(document.createElement('a')); + a.href = ''; + a.textContent = + localStrings.getString(getSectionMenuButtonTextId(sectionId)); + a.className = 'item'; + a.addEventListener( + 'click', + function(e) { + getSectionMenuButton(sectionId).hideMenu(); + e.preventDefault(); + setSectionVisible(sectionId, opt_section, true, mask); + shownSections &= ~mask; + saveShownSections(); + }); + menu.appendChild(span); +} + +function initializeSection(sectionId, mask, opt_section) { + var button = getSectionCloseButton(sectionId); + button.addEventListener( + 'click', + function() { + setSectionVisible(sectionId, opt_section, false, mask); + saveShownSections(); + }); +} + function updateSimpleSection(id, section) { var elm = $(id); var maxiview = getSectionMaxiview(elm); @@ -38,10 +127,14 @@ function renderRecentlyClosed() { var recentElement = $('recently-closed'); var parentEl = recentElement.lastElementChild; parentEl.textContent = ''; + var recentMenu = $('recently-closed-menu'); + clearClosedMenu(recentMenu); recentItems.forEach(function(item) { parentEl.appendChild(createRecentItem(item)); + addRecentMenuItem(recentMenu, item); }); + addClosedMenuFooter(recentMenu, 'recently-closed', MINIMIZED_RECENT); layoutRecentlyClosed(); } @@ -70,6 +163,26 @@ function createRecentItem(data) { return wrapperEl; } +function addRecentMenuItem(menu, data) { + var isWindow = data.type == 'window'; + var a = document.createElement('a'); + if (isWindow) { + a.textContent = formatTabsText(data.tabs.length); + a.className = 'window'; // To get the icon from the CSS .window rule. + a.href = ''; // To make underline show up. + } else { + a.href = data.url; + a.style.backgroundImage = 'url(chrome://favicon/' + data.url + ')'; + a.textContent = data.title; + } + function clickHandler(e) { + chrome.send('reopenTab', [String(data.sessionId)]); + e.preventDefault(); + } + a.addEventListener('click', clickHandler); + addClosedMenuEntryWithLink(menu, a); +} + function saveShownSections() { chrome.send('setShownSections', [String(shownSections)]); } @@ -202,6 +315,9 @@ function layoutSections() { for (; section = sections[i]; i++) { footerHeight += section.fixedHeight; } + // Leave room for bottom bar if it's visible. + footerHeight += $('closed-sections-bar').offsetHeight; + // 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 @@ -305,6 +421,7 @@ function getSectionMaxiview(section) { return $(section.id + '-maxiview'); } +// You usually want to call |showOnlySection()| instead of this. function showSection(section) { if (!(section & shownSections)) { shownSections |= section; @@ -328,6 +445,17 @@ function showSection(section) { } } +// Show this section and hide all other sections - at most one section can +// be open at one time. +function showOnlySection(section) { + for (var p in Section) { + if (p == section) + showSection(Section[p]); + else + hideSection(Section[p]); + } +} + function hideSection(section) { if (section & shownSections) { shownSections &= ~section; @@ -374,6 +502,15 @@ function setShownSections(newShownSections) { else hideSection(Section[key]); } + setSectionVisible( + 'apps', Section.APPS, + !(newShownSections & MINIMIZED_APPS), MINIMIZED_APPS); + setSectionVisible( + 'most-visited', Section.THUMB, + !(newShownSections & MINIMIZED_THUMB), MINIMIZED_THUMB); + setSectionVisible( + 'recently-closed', undefined, + !(newShownSections & MINIMIZED_RECENT), MINIMIZED_RECENT); layoutSections(); } @@ -386,7 +523,9 @@ function layoutRecentlyClosed() { updateMiniviewClipping(miniview); if (miniview.hasChildNodes()) { - recentElement.classList.remove('disabled'); + if (!(shownSections & MINIMIZED_RECENT)) { + recentElement.classList.remove('disabled'); + } } else { recentElement.classList.add('disabled'); } @@ -685,12 +824,7 @@ function toggleSectionVisibilityAndAnimate(section) { if (shownSections & Section[section]) { hideSection(Section[section]); } else { - for (var p in Section) { - if (p == section) - showSection(Section[p]); - else - hideSection(Section[p]); - } + showOnlySection(section); } layoutSections(); saveShownSections(); @@ -928,6 +1062,7 @@ updateAttribution(); var mostVisited = new MostVisited( $('most-visited-maxiview'), document.querySelector('#most-visited .miniview'), + $('most-visited-menu'), useSmallGrid(), shownSections & Section.THUMB); diff --git a/chrome/browser/resources/new_tab_theme.css b/chrome/browser/resources/new_tab_theme.css index 88e3fcc..7500a4f 100644 --- a/chrome/browser/resources/new_tab_theme.css +++ b/chrome/browser/resources/new_tab_theme.css @@ -102,7 +102,8 @@ body { color: $$5; /* COLOR_NTP_LINK_UNDERLINE */ } -.section > h2 { +.section > h2, +#closed-sections-bar > button { color: $$7; /* COLOR_NTP_SECTION_HEADER_TEXT */ } @@ -110,7 +111,8 @@ body { color: $$8; /* COLOR_NTP_SECTION_HEADER_TEXT_HOVER */ } -.section.hidden:not([noexpand]) > h2:hover { +.section.hidden:not([noexpand]) > h2:hover, +#closed-sections-bar > button:hover { color: $$8; /* COLOR_NTP_SECTION_HEADER_TEXT_HOVER */ } diff --git a/chrome/browser/resources/ntp/apps.js b/chrome/browser/resources/ntp/apps.js index 68a1be6..70018aa 100644 --- a/chrome/browser/resources/ntp/apps.js +++ b/chrome/browser/resources/ntp/apps.js @@ -10,6 +10,7 @@ function getAppsCallback(data) { appsSectionContent.textContent = ''; appsMiniview.textContent = ''; + clearClosedMenu(apps.menu); if (data.apps.length == 0) { appsSection.classList.add('disabled'); layoutSections(); @@ -22,10 +23,14 @@ function getAppsCallback(data) { data.apps.slice(0, MAX_MINIVIEW_ITEMS).forEach(function(app) { appsMiniview.appendChild(apps.createMiniviewElement(app)); + addClosedMenuEntryWithLink(apps.menu, apps.createClosedMenuElement(app)); }); - appsSection.classList.remove('disabled'); + if (!(shownSections & MINIMIZED_APPS)) { + appsSection.classList.remove('disabled'); + } } + addClosedMenuFooter(apps.menu, 'apps', MINIMIZED_APPS, Section.APPS); apps.loaded = true; maybeDoneLoading(); @@ -199,6 +204,8 @@ var apps = (function() { return { loaded: false, + menu: $('apps-menu'), + createElement: function(app) { var div = createElement(app); var a = div.firstChild; @@ -221,7 +228,8 @@ var apps = (function() { document.documentElement.setAttribute("install-animation-enabled", "false"); }); - if ($('apps').classList.contains('hidden')) + if ($('apps').classList.contains('hidden') && + !(shownSections & MINIMIZED_APPS)) toggleSectionVisibilityAndAnimate('APPS'); } @@ -251,6 +259,17 @@ var apps = (function() { return span; }, + createClosedMenuElement: function(app) { + var a = document.createElement('a'); + a.setAttribute('app-id', app['id']); + a.textContent = app['name']; + a.href = app['launch_url']; + a.onclick = handleClick; + a.style.backgroundImage = url(app['icon_small']); + a.className = 'item'; + return a; + }, + createWebStoreElement: function() { return createElement({ 'id': 'web-store-entry', diff --git a/chrome/browser/resources/ntp/most_visited.js b/chrome/browser/resources/ntp/most_visited.js index 98f3317..72557ac 100644 --- a/chrome/browser/resources/ntp/most_visited.js +++ b/chrome/browser/resources/ntp/most_visited.js @@ -41,9 +41,10 @@ var MostVisited = (function() { return Array.prototype.indexOf.call(nodes, el); } - function MostVisited(el, miniview, useSmallGrid, visible) { + function MostVisited(el, miniview, menu, useSmallGrid, visible) { this.element = el; this.miniview = miniview; + this.menu = menu; this.useSmallGrid_ = useSmallGrid; this.visible_ = visible; @@ -536,6 +537,7 @@ var MostVisited = (function() { this.data_ = data; this.updateMostVisited_(); this.updateMiniview_(); + this.updateMenu_(); }, updateMostVisited_: function() { @@ -609,6 +611,19 @@ var MostVisited = (function() { updateMiniviewClipping(this.miniview); }, + updateMenu_: function() { + clearClosedMenu(this.menu); + var data = this.data.slice(0, MAX_MINIVIEW_ITEMS); + for (var i = 0, item; item = data[i]; i++) { + if (!item.filler) { + addClosedMenuEntry( + this.menu, item.url, item.title, 'chrome://favicon/' + item.url); + } + } + addClosedMenuFooter( + this.menu, 'most-visited', MINIMIZED_THUMB, Section.THUMB); + }, + handleClick_: function(e) { var target = e.target; if (target.classList.contains('pin')) { |