summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorthakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-30 19:47:05 +0000
committerthakis@chromium.org <thakis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-30 19:47:05 +0000
commit23b7ec676e36ff858b11997bb70d262b315c5010 (patch)
tree1fbc01e663709fbc36dbfcf6190d695d3d72f0b7
parent9d5d932a17ca43eca60cd7755526daa58d7b4472 (diff)
downloadchromium_src-23b7ec676e36ff858b11997bb70d262b315c5010.zip
chromium_src-23b7ec676e36ff858b11997bb70d262b315c5010.tar.gz
chromium_src-23b7ec676e36ff858b11997bb70d262b315c5010.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. Review URL: http://codereview.chromium.org/3455007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@61095 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/dom_ui/shown_sections_handler.cc5
-rw-r--r--chrome/browser/dom_ui/shown_sections_handler.h12
-rw-r--r--chrome/browser/resources/new_new_tab.css61
-rw-r--r--chrome/browser/resources/new_new_tab.html58
-rw-r--r--chrome/browser/resources/new_new_tab.js149
-rw-r--r--chrome/browser/resources/ntp/apps.js20
-rw-r--r--chrome/browser/resources/ntp/most_visited.js17
7 files changed, 305 insertions, 17 deletions
diff --git a/chrome/browser/dom_ui/shown_sections_handler.cc b/chrome/browser/dom_ui/shown_sections_handler.cc
index e32511d..381ea32 100644
--- a/chrome/browser/dom_ui/shown_sections_handler.cc
+++ b/chrome/browser/dom_ui/shown_sections_handler.cc
@@ -21,10 +21,11 @@ namespace {
// Will cause an UMA notification if the mode of the new tab page
// was changed to hide/show the most visited thumbnails.
+// TODO(aa): Needs to be updated to match newest NTP - http://crbug.com/57440
void NotifySectionDisabled(int new_mode, int old_mode, Profile *profile) {
// If the oldmode HAD either thumbs or lists visible.
- bool old_had_it = old_mode & THUMB;
- bool new_has_it = new_mode & THUMB;
+ bool old_had_it = (old_mode & THUMB) && !(old_mode & MINIMIZED_THUMB);
+ bool new_has_it = (new_mode & THUMB) && !(new_mode & MINIMIZED_THUMB);
if (old_had_it && !new_has_it) {
UserMetrics::RecordAction(
diff --git a/chrome/browser/dom_ui/shown_sections_handler.h b/chrome/browser/dom_ui/shown_sections_handler.h
index a281346..be07735 100644
--- a/chrome/browser/dom_ui/shown_sections_handler.h
+++ b/chrome/browser/dom_ui/shown_sections_handler.h
@@ -18,8 +18,16 @@ class PrefService;
// Currently, only the THUMB and APPS sections can be toggled by the user. Other
// sections are shown automatically if they have data, and hidden otherwise.
enum Section {
- THUMB = 1,
- APPS = 64
+ // If one of these is set, the corresponding section shows large thumbnails,
+ // else it shows only a small overview list.
+ THUMB = 1 << 0,
+ APPS = 1 << 6,
+
+ // If one of these is set, then the corresponding section is shown minimized
+ // at the bottom of the NTP and no data is directly visible on the NTP.
+ MINIMIZED_THUMB = 1 << (0 + 16),
+ MINIMIZED_RECENT = 1 << (2 + 16),
+ MINIMIZED_APPS = 1 << (6 + 16),
};
class ShownSectionsHandler : public DOMMessageHandler,
diff --git a/chrome/browser/resources/new_new_tab.css b/chrome/browser/resources/new_new_tab.css
index b3bfd35..cb3c784 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,62 @@ 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;
+ font: inherit;
+ margin: 0;
+ margin-right: 10px;
+ padding: 0;
+
+ /* from .section > h2 */
+ font-family: Helvetica, Arial, sans-serif;
+ font-size: 133%;
+ font-weight: normal;
+}
+
+#closed-sections-bar > button > img {
+ -webkit-transform: rotate(90deg);
+}
+
.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 7290e32..6f15bb4 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 99cb712..39c7718 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) {
+ if (section) {
+ showOnlySection(section);
+ }
+ var el = $(sectionId);
+ el.classList.remove('disabled');
+ el = getSectionMenuButton(sectionId);
+ el.classList.add('disabled');
+ shownSections &= ~hideMask;
+ } else {
+ if (section) {
+ hideSection(section);
+ }
+ 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();
}
@@ -399,7 +536,9 @@ function layoutRecentlyClosed() {
});
if (parentEl.hasChildNodes()) {
- recentElement.classList.remove('disabled');
+ if (!(shownSections & MINIMIZED_RECENT)) {
+ recentElement.classList.remove('disabled');
+ }
} else {
recentElement.classList.add('disabled');
}
@@ -698,12 +837,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();
@@ -941,6 +1075,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/ntp/apps.js b/chrome/browser/resources/ntp/apps.js
index b128f05..4f577db 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');
setShownSections(Section.THUMB);
@@ -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;
@@ -251,6 +258,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')) {