diff options
author | arv@chromium.org <arv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-06 18:34:06 +0000 |
---|---|---|
committer | arv@chromium.org <arv@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-06 18:34:06 +0000 |
commit | 02b18209b05fc5c465d4518b9d7a4df1135c1a95 (patch) | |
tree | 1f79efbfd51b38a30f5441962e86752ea76956ca | |
parent | 004f80b0ab3bc8467b4df5a15b3e2fe040569aee (diff) | |
download | chromium_src-02b18209b05fc5c465d4518b9d7a4df1135c1a95.zip chromium_src-02b18209b05fc5c465d4518b9d7a4df1135c1a95.tar.gz chromium_src-02b18209b05fc5c465d4518b9d7a4df1135c1a95.tar.bz2 |
NTP: Adds a context menu to the apps section
This uses the cr Menu system and replaces the old options menu with a cr Menu.
BUG=52446
TEST=Start chrome with enable-apps. Install some apps.
Right clicking on an app should show a context menu.
Clicking the wrench should show the same menu.
Review URL: http://codereview.chromium.org/3315005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@58648 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/dom_ui/ntp_resource_cache.cc | 6 | ||||
-rw-r--r-- | chrome/browser/resources/new_new_tab.css | 56 | ||||
-rw-r--r-- | chrome/browser/resources/new_new_tab.html | 44 | ||||
-rw-r--r-- | chrome/browser/resources/new_new_tab.js | 214 | ||||
-rw-r--r-- | chrome/browser/resources/new_tab_theme.css | 3 | ||||
-rw-r--r-- | chrome/browser/resources/ntp/apps.css | 77 | ||||
-rw-r--r-- | chrome/browser/resources/ntp/apps.js | 235 | ||||
-rw-r--r-- | chrome/browser/resources/ntp/most_visited.js | 21 | ||||
-rw-r--r-- | chrome/browser/resources/shared/css/menu.css | 4 | ||||
-rw-r--r-- | chrome/browser/resources/shared/js/cr/ui/command.js | 2 | ||||
-rw-r--r-- | chrome/browser/resources/shared/js/cr/ui/position_util.js | 11 |
11 files changed, 235 insertions, 438 deletions
diff --git a/chrome/browser/dom_ui/ntp_resource_cache.cc b/chrome/browser/dom_ui/ntp_resource_cache.cc index c2209bd..a3e5020 100644 --- a/chrome/browser/dom_ui/ntp_resource_cache.cc +++ b/chrome/browser/dom_ui/ntp_resource_cache.cc @@ -11,7 +11,6 @@ #include "app/l10n_util.h" #include "app/resource_bundle.h" #include "app/theme_provider.h" -#include "base/command_line.h" #include "base/file_util.h" #include "base/ref_counted_memory.h" #include "base/string16.h" @@ -304,11 +303,6 @@ void NTPResourceCache::CreateNewTabHTML() { Animation::ShouldRenderRichAnimation() ? "true" : "false"; localized_strings.SetString("anim", anim); - const CommandLine* command_line = CommandLine::ForCurrentProcess(); - bool has_3d = - command_line->HasSwitch(switches::kEnableAcceleratedCompositing); - localized_strings.SetString("has_3d", has_3d ? "true" : "false"); - // Pass the shown_sections pref early so that we can prevent flicker. const int shown_sections = ShownSectionsHandler::GetShownSections( profile_->GetPrefs()); diff --git a/chrome/browser/resources/new_new_tab.css b/chrome/browser/resources/new_new_tab.css index 68d7cd7..f43aaa8 100644 --- a/chrome/browser/resources/new_new_tab.css +++ b/chrome/browser/resources/new_new_tab.css @@ -129,7 +129,7 @@ html[anim=false] *, background: no-repeat 0% 50%; padding: 2px; padding-left: 18px; - background-size: 16px; + background-size: 16px 16px; background-color: hsla(213, 63%, 93%, 0); display: block; line-height: 20px; @@ -219,47 +219,6 @@ html[dir=rtl] .item { pointer-events: none; } -#option-menu { - right: 0; - left: auto; - min-width: 175px; - z-index: 3; -} - -html[dir=rtl] #option-button, -html[dir=rtl] #option-menu { - right: auto; - left: 0; -} - -#option-menu > * { - /* Work around rendering bug. */ - outline: 1px solid transparent; -} - -#option-menu > [command=show]:before, -#option-menu > [command=hide]:before { - -webkit-margin-start: -14px; - content: '\00a0'; /* non breaking space */ - display: inline-block; - background-position: 0 50%; - background-repeat: no-repeat; - width: 14px; -} - -html[dir=rtl] #option-menu > [command=show]:before, -html[dir=rtl] #option-menu > [command=hide]:before { - background-position-x: 100%; -} - -#option-menu > [command=hide]:before { - background-image: url('ntp/checkbox_black.png'); -} - -#option-menu > [selected][command=hide]:active:before { - background-image: url('ntp/checkbox_white.png'); -} - #attribution { position: fixed; right: 5px; @@ -367,17 +326,18 @@ html[dir=rtl] .section > h2 .settings-wrapper { } .section > h2 .settings { - position: absolute; - left: 5px; - top: 5px; - width: 11px; - height: 11px; /* TODO(aa): Need a better image. This one is semi-transparent. Also, I think a gear would be better. */ + background-color: transparent; background-image: url(chrome://theme/IDR_BALLOON_WRENCH); background-position: center center; background-repeat: no-repeat; - background-size: 100%; + border: 0; + height: 11px; + left: 5px; + position: absolute; + top: 5px; + width: 11px; } .section.hidden > h2 .settings-wrapper { diff --git a/chrome/browser/resources/new_new_tab.html b/chrome/browser/resources/new_new_tab.html index 2080c71..1a88c6d 100644 --- a/chrome/browser/resources/new_new_tab.html +++ b/chrome/browser/resources/new_new_tab.html @@ -4,8 +4,7 @@ bookmarkbarattached:bookmarkbarattached; hasattribution:hasattribution; anim:anim; - syncispresent:syncispresent; - has_3d:has_3d"> + syncispresent:syncispresent"> <head> <meta charset="utf-8"> <title i18n-content="title"></title> @@ -123,10 +122,6 @@ if ('mode' in hashParams) { </div> <div id="main"> - <menu id="option-menu"> - <div command="clear-all-blacklisted" - i18n-content="restorethumbnails"></div> - </menu> <div id="notification"> <span> </span> @@ -152,7 +147,9 @@ if ('mode' in hashParams) { <img class="disclosure" src="ntp/ntp_disclosure_triangle.png"> <div class="back"></div> <span i18n-content="mostvisited"></span> - <div class="settings-wrapper"><div class="settings"></div></div> + <div class="settings-wrapper"> + <button class="settings" menu="#option-menu"></button> + </div> </h2> <div class="miniview"></div> </div> @@ -179,6 +176,22 @@ if ('mode' in hashParams) { <div class="window-menu" id="window-tooltip"></div> +<command id="clear-all-blacklisted" i18n-values=".label:restorethumbnails"> +<command id="apps-launch-command"> +<command id="apps-options-command" i18n-values=".label:appoptions"> +<command id="apps-uninstall-command" i18n-values=".label:appuninstall"> + +<menu id="option-menu"> + <button command="#clear-all-blacklisted"></button> +</menu> + +<menu id="app-context-menu"> + <button class="default" command="#apps-launch-command"></button> + <hr> + <button command="#apps-options-command"></button> + <button command="#apps-uninstall-command"></button> +</menu> + </body> <script src="shared/js/i18n_template.js"></script> @@ -188,12 +201,29 @@ i18nTemplate.process(document, templateData); <script src="shared/js/local_strings.js"></script> <script src="shared/js/class_list.js"></script> <script src="shared/js/parse_html_subset.js"></script> + +<script src="shared/js/cr.js"></script> +<script src="shared/js/cr/ui.js"></script> +<script src="shared/js/cr/ui/command.js"></script> +<script src="shared/js/cr/ui/menu_item.js"></script> +<script src="shared/js/cr/ui/menu.js"></script> +<script src="shared/js/cr/ui/position_util.js"></script> +<script src="shared/js/cr/ui/menu_button.js"></script> +<script src="shared/js/cr/ui/context_menu_button.js"></script> +<script src="shared/js/cr/ui/context_menu_handler.js"></script> + <script src="ntp/util.js"></script> <script src="ntp/most_visited.js"></script> <script src="new_new_tab.js"></script> <script src="ntp/apps.js"></script> <script> +cr.ui.decorate('menu', cr.ui.Menu); +cr.ui.decorate('command', cr.ui.Command); +cr.ui.decorate('button[menu]', cr.ui.MenuButton); +</script> + +<script> updateSimpleSection('apps', Section.APPS); updateSimpleSection('most-visited', Section.THUMB); updateSimpleSection('recently-closed', Section.RECENT); diff --git a/chrome/browser/resources/new_new_tab.js b/chrome/browser/resources/new_new_tab.js index 6fbd6c7..79a459f 100644 --- a/chrome/browser/resources/new_new_tab.js +++ b/chrome/browser/resources/new_new_tab.js @@ -647,208 +647,13 @@ function showFirstRunNotification() { notification.classList.add('first-run'); } -/** - * This handles the option menu. - * @param {Element} button The button element. - * @param {Element} menu The menu element. - * @constructor - */ -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); - this.boundMaybeHide_ = bind(this.maybeHide_, this); - this.menu.onmouseover = bind(this.handleMouseOver, this); - this.menu.onmouseout = bind(this.handleMouseOut, this); - this.menu.onmouseup = bind(this.handleMouseUp, this); -} - -OptionMenu.prototype = { - show: function() { - this.positionMenu_(); - this.menu.style.display = 'block'; - this.button.classList.add('open'); - this.button.focus(); - - // Listen to document and window events so that we hide the menu when the - // user clicks outside the menu or tabs away or the whole window is blurred. - document.addEventListener('focus', this.boundMaybeHide_, true); - document.addEventListener('mousedown', this.boundMaybeHide_, true); - }, - - positionMenu_: function() { - var rect = this.button.getBoundingClientRect(); - this.menu.style.top = rect.bottom + 'px'; - if (document.documentElement.dir == 'rtl') - this.menu.style.left = rect.left + 'px'; - else - this.menu.style.right = (document.body.clientWidth - rect.right) + 'px' - }, - - hide: function() { - this.menu.style.display = 'none'; - this.button.classList.remove('open'); - this.setSelectedIndex(-1); - - document.removeEventListener('focus', this.boundMaybeHide_, true); - document.removeEventListener('mousedown', this.boundMaybeHide_, true); - }, - - isShown: function() { - return this.menu.style.display == 'block'; - }, - - /** - * Callback for document mousedown and focus. It checks if the user tried to - * navigate to a different element on the page and if so hides the menu. - * @param {Event} e The mouse or focus event. - * @private - */ - maybeHide_: function(e) { - if (!this.menu.contains(e.target) && !this.button.contains(e.target)) { - this.hide(); - } - }, - - handleMouseDown: function(e) { - if (this.isShown()) { - this.hide(); - } else { - this.show(); - } - }, - - handleClick: function(e) { - e.stopPropagation(); - }, - - handleMouseOver: function(e) { - var el = e.target; - if (!el.hasAttribute('command')) { - this.setSelectedIndex(-1); - } else { - var index = Array.prototype.indexOf.call(this.menu.children, el); - this.setSelectedIndex(index); - } - }, - - handleMouseOut: function(e) { - this.setSelectedIndex(-1); - }, - - handleMouseUp: function(e) { - var item = this.getSelectedItem(); - if (item) { - this.executeItem(item); - } - }, - - handleKeyDown: function(e) { - var item = this.getSelectedItem(); - - var self = this; - function selectNextVisible(m) { - var children = self.menu.children; - var len = children.length; - var i = self.selectedIndex_; - if (i == -1 && m == -1) { - // Edge case when we need to go the last item fisrt. - i = 0; - } - while (true) { - i = (i + m + len) % len; - item = children[i]; - if (item && item.hasAttribute('command') && - item.style.display != 'none') { - break; - } - } - if (item) { - self.setSelectedIndex(i); - } - } - - switch (e.keyIdentifier) { - case 'Down': - if (!this.isShown()) { - this.show(); - } - selectNextVisible(1); - e.preventDefault(); - break; - case 'Up': - if (!this.isShown()) { - this.show(); - } - selectNextVisible(-1); - e.preventDefault(); - break; - case 'Esc': - case 'U+001B': // Maybe this is remote desktop playing a prank? - this.hide(); - break; - case 'Enter': - case 'U+0020': // Space - if (this.isShown()) { - if (item) { - this.executeItem(item); - } else { - this.hide(); - } - } else { - this.show(); - } - e.preventDefault(); - break; - } - }, - - selectedIndex_: -1, - setSelectedIndex: function(i) { - if (i != this.selectedIndex_) { - var items = this.menu.children; - var oldItem = items[this.selectedIndex_]; - if (oldItem) { - oldItem.removeAttribute('selected'); - } - var newItem = items[i]; - if (newItem) { - newItem.setAttribute('selected', 'selected'); - } - this.selectedIndex_ = i; - } - }, - - getSelectedItem: function() { - return this.menu.children[this.selectedIndex_] || null; - }, - - executeItem: function(item) { - var command = item.getAttribute('command'); - if (command in this.commands) { - this.commands[command].call(this, item); - } - - this.hide(); - } -}; - -var optionMenu = new OptionMenu( - document.querySelector('#most-visited h2 .settings-wrapper'), - $('option-menu')); -optionMenu.commands = { - 'clear-all-blacklisted' : function() { - mostVisited.clearAllBlacklisted(); - chrome.send('getMostVisited'); - } -}; - $('main').addEventListener('click', function(e) { var p = e.target; while (p && p.tagName != 'H2') { + // In case the user clicks on a button we do not want to expand/collapse a + // section. + if (p.tagName == 'BUTTON') + return; p = p.parentNode; } @@ -1066,17 +871,6 @@ function callGetSyncMessageIfSyncIsPresent() { } } -function hideAllMenus() { - optionMenu.hide(); -} - -window.addEventListener('blur', hideAllMenus); -window.addEventListener('keydown', function(e) { - if (e.keyIdentifier == 'Alt' || e.keyIdentifier == 'Meta') { - hideAllMenus(); - } -}, true); - // Tooltip for elements that have text that overflows. document.addEventListener('mouseover', function(e) { // We don't want to do this while we are dragging because it makes things very diff --git a/chrome/browser/resources/new_tab_theme.css b/chrome/browser/resources/new_tab_theme.css index 237274e..e21eaef 100644 --- a/chrome/browser/resources/new_tab_theme.css +++ b/chrome/browser/resources/new_tab_theme.css @@ -134,8 +134,7 @@ body { color: $8; /* COLOR_NTP_TEXT */ } -.app:hover > .front > a, -.app > .back { +.app:hover > a { color: $$3; /* COLOR_NTP_SECTION_TEXT */ background-color: $$1; /* COLOR_NTP_SECTION */; } diff --git a/chrome/browser/resources/ntp/apps.css b/chrome/browser/resources/ntp/apps.css index 1527d9b..9c51f44 100644 --- a/chrome/browser/resources/ntp/apps.css +++ b/chrome/browser/resources/ntp/apps.css @@ -13,8 +13,6 @@ width: 124px; /* 920 / 7 - margin * 2 */ } -.app > .front, -.app > .back, .app a { border-radius: 10px; bottom: 0; @@ -24,12 +22,6 @@ top: 0; } -.app > .front, -.app > .back { - -webkit-backface-visibility: hidden; - -webkit-transition: -webkit-transform .15s; -} - .app a { -webkit-transition: background-color .5s; background: rgba(255, 255, 255, 0) /* transparent white */ @@ -45,8 +37,9 @@ white-space: nowrap; } -.app .flip { +.app .app-settings { background-color: transparent; + background-position: center center; border: 0; height: 14px; padding: 0; @@ -56,49 +49,24 @@ width: 14px; } -.app > .front > .flip { +.app > .app-settings { -webkit-transition: opacity .3s; -webkit-transition-delay: 0; background-image: url(chrome://theme/IDR_BALLOON_WRENCH); opacity: 0; } -.app > .front > .flip:hover { +.app > .app-settings:hover { -webkit-transition: none; background-image: url(chrome://theme/IDR_BALLOON_WRENCH_H); } -.app:hover > .front > .flip, -.app > .front > .flip:focus { +.app:hover > .app-settings, +.app > .app-settings:focus { -webkit-transition-delay: .5s; opacity: .9; } -.app > .back > .flip { - background-image: url(chrome://theme/IDR_BALLOON_CLOSE); - opacity: .9; -} - -.app > .back > .flip:hover { - background-image: url(chrome://theme/IDR_BALLOON_CLOSE_HOVER); -} - -.app > .back { - padding: 10px; -} - -.app > .back > h2 { - font-size: 100%; - margin: 10px 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.app > .back > button:not(.flip) { - width: 100%; -} - @-webkit-keyframes bounce { 0% { -webkit-transform: scale(0, 0); @@ -122,37 +90,10 @@ -webkit-transition: opacity .5s; } -a[app_id=web-store-entry] { +a[app-id=web-store-entry] { background-image: url("web_store_icon.png"); } -/* Make items on the wrong side non focusable by hiding them. */ -.app:not(.config) > .back button, -.app.config > .front button, -.app.config > .front a { - display: none; -} - -html[has_3d=true] .app.config > .front { - -webkit-transform: rotateY(180deg); -} - -html[has_3d=true] .app > .back { - -webkit-transform: rotateY(-180deg); -} - -html[has_3d=true] .app.config > .back { - -webkit-transform: rotateY(0deg); -} - -html[has_3d=false] .app.config > .front { - display: none; -} - -html[has_3d=false] .app > .back { - display: none; -} - -html[has_3d=false] .app.config > .back { - display: block; +menu > button.default { + font-weight: bold; } diff --git a/chrome/browser/resources/ntp/apps.js b/chrome/browser/resources/ntp/apps.js index 0099634..c946b4d 100644 --- a/chrome/browser/resources/ntp/apps.js +++ b/chrome/browser/resources/ntp/apps.js @@ -30,111 +30,164 @@ function getAppsCallback(data) { layoutSections(); } -var apps = { - /** - * @this {!HTMLAnchorElement} - */ - handleClick_: function() { +var apps = (function() { + + function createElement(app) { + var div = document.createElement('div'); + div.className = 'app'; + + var a = div.appendChild(document.createElement('a')); + a.setAttribute('app-id', app['id']); + a.xtitle = a.textContent = app['name']; + a.href = app['launch_url']; + + return div; + } + + function createContextMenu(app) { + var menu = new cr.ui.Menu; + var button = document.createElement(button); + } + + function launchApp(appId) { + var appsSection = $('apps'); + var expanded = !appsSection.classList.contains('hidden'); + var element = document.querySelector( + (expanded ? '.maxiview' : '.miniview') + ' a[app-id=' + appId + ']'); + // TODO(arv): Handle zoom? - var rect = this.getBoundingClientRect(); - var cs = getComputedStyle(this); + var rect = element.getBoundingClientRect(); + var cs = getComputedStyle(element); var size = cs.backgroundSize.split(/\s+/); // background-size has the // format '123px 456px'. + var width = parseInt(size[0], 10); var height = parseInt(size[1], 10); - // We are using background-position-x 50%. - var left = rect.left + ((rect.width - width) >> 1); // Integer divide by 2. - var top = rect.top + parseInt(cs.backgroundPositionY, 10); - chrome.send('launchApp', [this.getAttribute("app_id"), + var top, left; + if (expanded) { + // We are using background-position-x 50%. + top = rect.top + parseInt(cs.backgroundPositionY, 10); + left = rect.left + ((rect.width - width) >> 1); // Integer divide by 2. + + } else { + // We are using background-position-y 50%. + top = rect.top + ((rect.height - width) >> 1); // Integer divide by 2. + if (getComputedStyle(element).direction == 'rtl') + left = rect.left + rect.width - width; + else + left = rect.left; + } + + chrome.send('launchApp', [appId, String(left), String(top), String(width), String(height)]); + } + + /** + * @this {!HTMLAnchorElement} + */ + function handleClick(e) { + var appId = e.currentTarget.getAttribute('app-id'); + launchApp(appId); return false; - }, + } - createElement_: function(app) { - var div = document.createElement('div'); - div.className = 'app'; + var currentApp; - var front = div.appendChild(document.createElement('div')); - front.className = 'front'; + function addContextMenu(el, app) { + el.addEventListener('contextmenu', cr.ui.contextMenuHandler); + el.addEventListener('keydown', cr.ui.contextMenuHandler); + el.addEventListener('keyup', cr.ui.contextMenuHandler); - var a = front.appendChild(document.createElement('a')); - a.setAttribute('app_id', app['id']); - a.xtitle = a.textContent = app['name']; - a.href = app['launch_url']; + Object.defineProperty(el, 'contextMenu', { + get: function() { + currentApp = app; - return div; - }, - - createElement: function(app) { - var div = this.createElement_(app); - var front = div.firstChild; - var a = front.firstChild; - - a.onclick = apps.handleClick_; - a.style.backgroundImage = url(app['icon_big']); - if (hashParams['app-id'] == app['id']) { - div.setAttribute('new', 'new'); - // Delay changing the attribute a bit to let the page settle down a bit. - setTimeout(function() { - div.setAttribute('new', 'installed'); - }, 500); - } + $('apps-launch-command').label = app['name']; + $('apps-options-command').canExecuteChange(); - var settingsButton = front.appendChild(document.createElement('button')); - settingsButton.className = 'flip'; - settingsButton.title = localStrings.getString('appsettings'); - - var back = div.appendChild(document.createElement('div')); - back.className = 'back'; - - var header = back.appendChild(document.createElement('h2')); - header.textContent = app['name']; - - var optionsButton = back.appendChild(document.createElement('button')); - optionsButton.textContent = localStrings.getString('appoptions'); - optionsButton.disabled = !app['options_url']; - optionsButton.onclick = function() { - window.location = app['options_url']; - }; - - var uninstallButton = back.appendChild(document.createElement('button')); - uninstallButton.textContent = uninstallButton.xtitle = - localStrings.getString('appuninstall'); - uninstallButton.onclick = function() { - chrome.send('uninstallApp', [app['id']]); - }; - - var closeButton = back.appendChild(document.createElement('button')); - closeButton.title = localStrings.getString('close'); - closeButton.className = 'flip'; - closeButton.onclick = settingsButton.onclick = function() { - div.classList.toggle('config'); - }; + return $('app-context-menu'); + } + }); + } - return div; - }, + document.addEventListener('command', function(e) { + if (!currentApp) + return; + + switch (e.command.id) { + case 'apps-options-command': + window.location = currentApp['options_url']; + break; + case 'apps-launch-command': + launchApp(currentApp['id']); + break; + case 'apps-uninstall-command': + chrome.send('uninstallApp', [currentApp['id']]); + break; + } + }); - createMiniviewElement: function(app) { - var span = document.createElement('span'); - var a = span.appendChild(document.createElement('a')); + document.addEventListener('canExecute', function(e) { + switch (e.command.id) { + case 'apps-options-command': + e.canExecute = currentApp && currentApp['options_url']; + break; + case 'apps-launch-command': + case 'apps-uninstall-command': + e.canExecute = true; + break; + } + }); - a.setAttribute('app_id', app['id']); - a.textContent = app['name']; - a.href = app['launch_url']; - a.onclick = apps.handleClick_; - a.style.backgroundImage = url(app['icon_small']); - a.className = 'item'; - span.appendChild(a); - return span; - }, - - createWebStoreElement: function() { - return this.createElement_({ - 'id': 'web-store-entry', - 'name': localStrings.getString('web_store_title'), - 'launch_url': localStrings.getString('web_store_url') - }); - } -}; + return { + createElement: function(app) { + var div = createElement(app); + var a = div.firstChild; + + a.onclick = handleClick; + a.style.backgroundImage = url(app['icon_big']); + if (hashParams['app-id'] == app['id']) { + div.setAttribute('new', 'new'); + // Delay changing the attribute a bit to let the page settle down a bit. + setTimeout(function() { + div.setAttribute('new', 'installed'); + }, 500); + } + + var settingsButton = div.appendChild(new cr.ui.ContextMenuButton); + settingsButton.className = 'app-settings'; + settingsButton.title = localStrings.getString('appsettings'); + + addContextMenu(div, app); + + return div; + }, + + createMiniviewElement: function(app) { + var span = document.createElement('span'); + var a = span.appendChild(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'; + span.appendChild(a); + + addContextMenu(span, app); + + return span; + }, + + createWebStoreElement: function() { + return createElement({ + 'id': 'web-store-entry', + 'name': localStrings.getString('web_store_title'), + 'launch_url': localStrings.getString('web_store_url') + }); + } + }; +})(); diff --git a/chrome/browser/resources/ntp/most_visited.js b/chrome/browser/resources/ntp/most_visited.js index 7dac8a4..bff2c1f 100644 --- a/chrome/browser/resources/ntp/most_visited.js +++ b/chrome/browser/resources/ntp/most_visited.js @@ -56,6 +56,10 @@ var MostVisited = (function() { document.addEventListener('DOMContentLoaded', bind(this.ensureSmallGridCorrect, this)); + // Commands + document.addEventListener('command', bind(this.handleCommand_, this)); + document.addEventListener('canExecute', bind(this.handleCanExecute_, this)); + // DND el.addEventListener('dragstart', bind(this.handleDragStart_, this)); el.addEventListener('dragenter', bind(this.handleDragEnter_, this)); @@ -300,6 +304,23 @@ var MostVisited = (function() { return this.getMostVisitedLayoutRects_()[index]; }, + // Commands + + handleCommand_: function(e) { + var commandId = e.command.id; + switch (commandId) { + case 'clear-all-blacklisted': + this.clearAllBlacklisted(); + chrome.send('getMostVisited'); + break; + } + }, + + handleCanExecute_: function(e) { + if (e.command.id == 'clear-all-blacklisted') + e.canExecute = true; + }, + // DND currentOverItem_: null, diff --git a/chrome/browser/resources/shared/css/menu.css b/chrome/browser/resources/shared/css/menu.css index 9ee83e6..39ddafd 100644 --- a/chrome/browser/resources/shared/css/menu.css +++ b/chrome/browser/resources/shared/css/menu.css @@ -1,17 +1,17 @@ menu { display: none; - position: absolute; + position: fixed; border: 1px solid rgba(0, 0, 0, .50); -webkit-box-shadow: 0px 2px 4px rgba(0, 0, 0, .50); color: black; background: -webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#eee)); left: 0; white-space: nowrap; - z-index: 2; padding: 8px 0; margin: 0; cursor: default; border-radius: 3px; + z-index: 3; } menu > * { diff --git a/chrome/browser/resources/shared/js/cr/ui/command.js b/chrome/browser/resources/shared/js/cr/ui/command.js index 4df2275..4f4610d 100644 --- a/chrome/browser/resources/shared/js/cr/ui/command.js +++ b/chrome/browser/resources/shared/js/cr/ui/command.js @@ -282,7 +282,7 @@ cr.define('cr.ui', function() { return this.canExecute_; }, set canExecute(canExecute) { - this.canExecute_ = canExecute; + this.canExecute_ = !!canExecute; this.stopPropagation(); } }; diff --git a/chrome/browser/resources/shared/js/cr/ui/position_util.js b/chrome/browser/resources/shared/js/cr/ui/position_util.js index 85e86b2..380e9e1 100644 --- a/chrome/browser/resources/shared/js/cr/ui/position_util.js +++ b/chrome/browser/resources/shared/js/cr/ui/position_util.js @@ -57,10 +57,15 @@ cr.define('cr.ui', function() { */ function positionPopupAroundRect(anchorRect, popupElement, type) { var popupRect = popupElement.getBoundingClientRect(); - var popupContainer = popupElement.offsetParent; + var popupContainer; + var cs = popupElement.ownerDocument.defaultView. + getComputedStyle(popupElement); + if (cs.position == 'fixed') + popupContainer = popupElement.ownerDocument.body; + else + popupContainer = popupElement.offsetParent; var availRect = popupContainer.getBoundingClientRect(); - var rtl = popupElement.ownerDocument.defaultView. - getComputedStyle(popupElement).direction == 'rtl'; + var rtl = cs.direction == 'rtl'; // Flip BEFORE, AFTER based on RTL. if (rtl) { |