308396 - UE improvements for tabbed browsing in response to usability studies conducted. In particular, add close buttons to tabs, improve the reselection behavior of new tabs opened especially in single window mode, simplify the preferences available for tabs, and improve the visual appearance of keyboard-focused tabs. r=mconnor.

This commit is contained in:
beng%bengoodger.com 2006-01-20 23:04:26 +00:00
Родитель 1dbb1a4bf2
Коммит 2edbfa7ff0
15 изменённых файлов: 532 добавлений и 138 удалений

Просмотреть файл

@ -244,6 +244,15 @@ pref("browser.tabs.loadFolderAndReplace", true);
pref("browser.tabs.opentabfor.middleclick", true);
pref("browser.tabs.loadDivertedInBackground", false);
pref("browser.tabs.loadBookmarksInBackground", false);
pref("browser.tabs.tabClipWidth", 140);
pref("browser.tabs.disableBackgroundClose", false);
// When tabs opened by links in other tabs via a combination of
// browser.link.open_newwindow being set to 3 and target="_blank" etc are
// closed:
// true return to the tab that opened this tab (its owner)
// false return to the adjacent tab (old default)
pref("browser.tabs.selectOwnerOnClose", true);
// Default bookmark sorting
pref("browser.bookmarks.sort.direction", "descending");

Просмотреть файл

@ -1431,13 +1431,8 @@ function BrowserHomeClick(aEvent)
case "tabshifted":
case "tab":
urls = homePage.split("|");
var firstTabAdded = gBrowser.addTab(urls[0]);
for (var i = 1; i < urls.length; ++i)
gBrowser.addTab(urls[i]);
if ((where == "tab") ^ getBoolPref("browser.tabs.loadBookmarksInBackground", false)) {
gBrowser.selectedTab = firstTabAdded;
content.focus();
}
var loadInBackground = getBoolPref("browser.tabs.loadBookmarksInBackground", false);
gBrowser.loadTabs(urls, loadInBackground);
break;
case "window":
OpenBrowserWindow();
@ -1455,16 +1450,12 @@ function loadOneOrMoreURIs(aURIString)
return;
}
#endif
var urls = aURIString.split("|");
loadURI(urls[0]);
for (var i = 1; i < urls.length; ++i) {
// addTab throws for certain malformed URIs
// catch this so we don't hork startup.
try {
gBrowser.addTab(urls[i]);
} catch (ex) {
// do nothing
}
// This function throws for certain malformed URIs, so use exception handling
// so that we don't disrupt startup
try {
gBrowser.loadTabs(aURIString.split("|"), false, true);
}
catch (e) {
}
}
@ -1667,7 +1658,7 @@ function openLocationCallback()
function BrowserOpenTab()
{
gBrowser.selectedTab = gBrowser.addTab('about:blank');
gBrowser.loadOneTab("about:blank", null, null, null, false);
if (gURLBar)
setTimeout(function() { gURLBar.focus(); }, 0);
}
@ -1690,7 +1681,7 @@ function delayedOpenWindow(chrome, flags, href, postData)
the URI kicked off before becoming the active content area. */
function delayedOpenTab(aUrl, aReferrer, aCharset, aPostData)
{
setTimeout(function(aTabElt) { gBrowser.selectedTab = aTabElt; }, 0, gBrowser.addTab(aUrl, aReferrer, aCharset, aPostData));
gBrowser.loadOneTab(aUrl, aReferrer, aCharset, aPostData, false);
}
function BrowserOpenFileWindow()
@ -1777,8 +1768,7 @@ function BrowserLoadURL(aTriggeringEvent, aPostData)
aTriggeringEvent.altKey) {
handleURLBarRevert();
content.focus();
var t = gBrowser.addTab(url, null, null, aPostData); // open link in new tab
gBrowser.selectedTab = t;
gBrowser.loadOneTab(url, null, null, aPostData, false);
gURLBar.value = url;
aTriggeringEvent.preventDefault();
aTriggeringEvent.preventBubble();
@ -1801,8 +1791,8 @@ function SearchLoadURL(aURL, aInNewTab)
if (gBrowser.localName == "tabbrowser" && aInNewTab) {
content.focus();
var t = gBrowser.addTab(aURL, null); // open link in new tab
gBrowser.selectedTab = t;
// Modal action, remember last viewed tab
gBrowser.loadOneTab(aURL, null, null, null, false);
if (gURLBar)
gURLBar.value = aURL;
}
@ -3703,9 +3693,8 @@ nsBrowserAccess.prototype =
newWindow = openDialog(getBrowserURL(), "_blank", "all,dialog=no", url);
break;
case nsCI.nsIBrowserDOMWindow.OPEN_NEWTAB :
var newTab = gBrowser.addTab("about:blank");
if (!gPrefService.getBoolPref("browser.tabs.loadDivertedInBackground"))
gBrowser.selectedTab = newTab;
var loadInBackground = gPrefService.getBoolPref("browser.tabs.loadDivertedInBackground");
var newTab = gBrowser.loadOneTab("about:blank", null, null, null, loadInBackground);
newWindow = gBrowser.getBrowserForTab(newTab).docShell
.QueryInterface(nsCI.nsIInterfaceRequestor)
.getInterface(nsCI.nsIDOMWindow);

Просмотреть файл

@ -229,15 +229,8 @@ function openUILinkIn( url, where )
break;
case "tabshifted":
case "tab":
var tab = browser.addTab(url);
// We check the pref here, rather than in whereToOpenLink, because an "open link in tab"
// context menu item could call openUILinkwhere directly.
if ((where == "tab") ^ getBoolPref("browser.tabs.loadBookmarksInBackground", false)) {
browser.selectedTab = tab;
w.content.focus();
}
var loadInBackground = getBoolPref("browser.tabs.loadBookmarksInBackground", false);
browser.loadOneTab(url, null, null, null, loadInBackground);
break;
}
}

Просмотреть файл

@ -726,8 +726,14 @@ var BookmarksCommand = {
var uri = target.QueryInterface(kRDFLITIID).Value;
if (index < tabCount)
tabPanels[index].loadURI(uri);
else
else {
// This is not a modal sub-action of a given tab/document within a window
// since opening a bookmarks group replaces all existing tabs in the window,
// closing extras. If this ever changes to be augmentative, this code will
// have to change to probably just use <tabbrowser>.loadTabs() which figures
// out whether or not owner should be set.
browser.addTab(uri);
}
++index;
}
}

Просмотреть файл

@ -37,37 +37,20 @@
# ***** END LICENSE BLOCK *****
var gTabsPane = {
_lastForceLinksMode: 3,
writeWindowLinksBehavior: function ()
{
var tabbedOpenForce = document.getElementById("tabbedOpenForce");
if (!tabbedOpenForce.checked)
return 2;
var tabbedWindowLinks = document.getElementById("tabbedWindowLinks");
this._lastForceLinksMode = parseInt(tabbedWindowLinks.value)
return this._lastForceLinksMode;
readLinkTarget: function() {
// Each open link preference has an integer value of the form:
// 0 - open links in the default window
// 1 - open links in the most recent window or tab
// 2 - open links in a new window
// 3 - open links in a new tab
var openExternal = document.getElementById("browser.link.open_external");
return openExternal.value != 2 ? 3 : 2;
},
readForceLinks: function ()
{
var preference = document.getElementById("browser.link.open_newwindow");
var tabbedWindowLinks = document.getElementById("tabbedWindowLinks");
tabbedWindowLinks.disabled = preference.value == 2;
return preference.value != 2;
},
readForceLinksMode: function ()
{
var preference = document.getElementById("browser.link.open_newwindow");
return preference.value != 2 ? preference.value : this._lastForceLinksMode;
},
updateWindowLinksBehavior: function ()
{
var preference = document.getElementById("app.update.autoInstallEnabled");
return undefined;
writeLinkTarget: function() {
var linkTargeting = document.getElementById("linkTargeting");
document.getElementById("browser.link.open_newwindow").value = linkTargeting.value;
return linkTargeting.value;
}
};

Просмотреть файл

@ -60,27 +60,16 @@
<script type="application/x-javascript" src="chrome://browser/content/preferences/tabs.js"/>
<groupbox align="start">
<caption label="&openExternalLinksIn.label;"/>
<radiogroup id="tabbedExternalLinks"
preference="browser.link.open_external">
<caption label="&linkTargeting.label;"/>
<radiogroup id="linkTargeting"
preference="browser.link.open_external"
onsyncfrompreference="return gTabsPane.readLinkTarget();"
onsynctopreference="return gTabsPane.writeLinkTarget();">
<radio label="&newWindow.label;" accesskey="&newWindow.accesskey;" value="2"/>
<radio label="&newTabInRecentWindow.label;" accesskey="&newTabInRecentWindow.accesskey;" value="3"/>
<radio label="&recentWindowOrTab.label;" accesskey="&recentWindowOrTab.accesskey;" value="1"/>
</radiogroup>
</groupbox>
<vbox align="start">
<checkbox id="tabbedOpenForce" label="&forceNewWindowLinks.label;"
accesskey="&forceNewWindowLinks.accesskey;"
preference="browser.link.open_newwindow"
onsynctopreference="return gTabsPane.writeWindowLinksBehavior();"
onsyncfrompreference="return gTabsPane.readForceLinks();"/>
<radiogroup id="tabbedWindowLinks" class="indent"
preference="browser.link.open_newwindow"
onsynctopreference="return gTabsPane.writeWindowLinksBehavior();"
onsyncfrompreference="return gTabsPane.readForceLinksMode();">
<radio label="&sameTabOrWindow.label;" accesskey="&sameTabOrWindow.accesskey;" value="1"/>
<radio label="&newTab.label;" accesskey="&newTab.accesskey;" value="3"/>
</radiogroup>
<checkbox id="hideTabBar" label="&hideTabBar.label;"
accesskey="&hideTabBar.accesskey;"
preference="browser.tabs.autoHide"/>

Просмотреть файл

@ -1,18 +1,10 @@
<!ENTITY tabsTab.label "Tabs">
<!ENTITY openExternalLinksIn.label "Open links from other applications in:">
<!ENTITY newWindow.label "a new window">
<!ENTITY linkTargeting.label "Open links that would open new windows in:">
<!ENTITY newWindow.label "new windows">
<!ENTITY newWindow.accesskey "w">
<!ENTITY newTabInRecentWindow.label "a new tab in the most recent window">
<!ENTITY newTabInRecentWindow.label "new tabs in the most recent window">
<!ENTITY newTabInRecentWindow.accesskey "t">
<!ENTITY recentWindowOrTab.label "the most recent tab/window">
<!ENTITY recentWindowOrTab.accesskey "r">
<!ENTITY forceNewWindowLinks.label "Force links that open new windows to open in:">
<!ENTITY forceNewWindowLinks.accesskey "F">
<!ENTITY sameTabOrWindow.label "the same tab/window as the link">
<!ENTITY sameTabOrWindow.accesskey "s">
<!ENTITY newTab.label "a new tab">
<!ENTITY newTab.accesskey "n">
<!ENTITY hideTabBar.label "Hide the tab bar when only one web site is open">
<!ENTITY hideTabBar.accesskey "d">
<!ENTITY loadInBackground.label "Select new tabs opened from links">

Просмотреть файл

@ -428,6 +428,13 @@
</implementation>
</binding>
<!--
XXXben - this looks like something added specifically for tabbrowser.
if it turns out no one uses this that can't easily be evangelized to
use their own roll-your-own binding, then we should get rid of this
to tighten up the toolkit api. This binding made obsolete in Firefox
by 308396.
-->
<binding id="tabs-closebutton"
extends="chrome://global/content/bindings/tabbox.xml#tabs">
<content>
@ -443,7 +450,8 @@
</xul:stack>
</content>
</binding>
<binding id="tabpanels"
extends="chrome://global/content/bindings/tabbox.xml#tab-base">
<implementation implements="nsIAccessibleProvider">
@ -541,20 +549,29 @@
return this.getAttribute("selected") == "true" ? true : false;
</getter>
<setter>
<![CDATA[
this.setAttribute("selected", val);
if (this.previousSibling) {
if (this.previousSibling && this.previousSibling.localName == "tab") {
if (val)
this.previousSibling.setAttribute("beforeselected", val);
else
this.previousSibling.removeAttribute("beforeselected");
this.removeAttribute("first-tab");
}
if (this.nextSibling) {
else
this.setAttribute("first-tab", "true");
if (this.nextSibling && this.nextSibling.localName == "tab") {
if (val)
this.nextSibling.setAttribute("afterselected", val);
else
this.nextSibling.removeAttribute("afterselected");
this.removeAttribute("last-tab");
}
else
this.setAttribute("last-tab", "true");
return val;
]]>
</setter>
</property>

Просмотреть файл

@ -43,6 +43,8 @@
<!DOCTYPE bindings [
<!ENTITY % tabBrowserDTD SYSTEM "chrome://global/locale/tabbrowser.dtd" >
%tabBrowserDTD;
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
%globalDTD;
]>
<bindings id="tabBrowserBindings"
@ -67,7 +69,7 @@
ondragover="nsDragAndDrop.dragOver(event, this.parentNode.parentNode); event.stopPropagation();"
ondragdrop="nsDragAndDrop.drop(event, this.parentNode.parentNode); event.stopPropagation();"
ondragexit="nsDragAndDrop.dragExit(event, this.parentNode.parentNode); event.stopPropagation();">
<xul:tooltip onpopupshowing="event.preventBubble(); if (document.tooltipNode.hasAttribute('label')) { this.setAttribute('label', document.tooltipNode.getAttribute('label')); return true; } return false;"/>
<xul:tooltip onpopupshowing="return this.parentNode.parentNode.parentNode.createTooltip(event);"/>
<xul:menupopup anonid="tabContextMenu" onpopupshowing="this.parentNode.parentNode.parentNode.updatePopupMenu(this);">
<xul:menuitem label="&newTab.label;" accesskey="&newTab.accesskey;"
xbl:inherits="oncommand=onnewtab"/>
@ -90,8 +92,7 @@
tabbrowser.removeTab(tabbrowser.mContextTab);"/>
</xul:menupopup>
<xul:tabs class="tabbrowser-tabs" closebutton="true" flex="1"
setfocus="false"
<xul:tabs class="tabbrowser-tabs" flex="1" setfocus="false"
onclick="this.parentNode.parentNode.parentNode.onTabClick(event);"
xbl:inherits="onnewtab"
ondblclick="this.parentNode.parentNode.parentNode.onTabBarDblClick(event);"
@ -1010,7 +1011,8 @@
<parameter name="aLoadInBackground"/>
<body>
<![CDATA[
var tab = this.addTab(aURI, aReferrerURI, aCharset, aPostData);
var owner = aLoadInBackground ? null : this.selectedTab;
var tab = this.addTab(aURI, aReferrerURI, aCharset, aPostData, owner);
var bgLoad = (typeof(aLoadInBackground) != "undefined") ? aLoadInBackground :
this.mPrefs.getBoolPref("browser.tabs.loadInBackground");
// Set newly selected tab after quick timeout, otherwise hideous focus problems
@ -1021,16 +1023,55 @@
}
setTimeout(selectNewForegroundTab, 0, getBrowser(), tab);
}
if (!bgLoad)
this.selectedTab = tab;
return tab;
]]>
</body>
</method>
<method name="loadTabs">
<parameter name="aURIs"/>
<parameter name="aLoadInBackground"/>
<parameter name="aReplace"/>
<body><![CDATA[
// The tab selected after this new tab is closed (i.e. the new tab's
// "owner") is the next adjacent tab (i.e. not the previously viewed tab)
// when several urls are opened here (i.e. closing the first should select
// the next of many URLs opened) or if the pref to have UI links opened in
// the background is set (i.e. the link is not being opened modally)
//
// i.e.
// Number of URLs Load UI Links in BG Focus Last Viewed?
// == 1 false YES
// == 1 true NO
// > 1 false/true NO
var owner = (aURIs.length > 1) || aLoadInBackground ? null : gBrowser.selectedTab;
var firstTabAdded = null;
if (aReplace)
this.loadURI(aURIs[0], null, null);
else
firstTabAdded = gBrowser.addTab(aURIs[0], null, null, null, owner);
for (var i = 1; i < aURIs.length; ++i)
gBrowser.addTab(aURIs[i]);
if (!aLoadInBackground) {
if (firstTabAdded) {
// .selectedTab setter focuses the content area
this.selectedTab = firstTabAdded;
}
else
window.content.focus();
}
]]></body>
</method>
<method name="addTab">
<parameter name="aURI"/>
<parameter name="aReferrerURI"/>
<parameter name="aCharset"/>
<parameter name="aPostData"/>
<parameter name="aOwner"/>
<body>
<![CDATA[
if (!this.mTabbedMode)
@ -1053,7 +1094,23 @@
t.setAttribute("flex", "100");
t.setAttribute("validate", "never");
t.setAttribute("onerror", "this.parentNode.parentNode.parentNode.parentNode.addToMissedIconCache(this.getAttribute('image')); this.removeAttribute('image');");
t.className = "tabbrowser-tab";
this.mTabContainer.appendChild(t);
// If this new tab is owned by another, assert that relationship
if (aOwner !== undefined && aOwner !== null) {
t.owner = aOwner;
var self = this;
function attrChanged(event) {
if (event.attrName == "selectedIndex" &&
event.prevValue != event.newValue)
self.resetOwner(parseInt(event.prevValue));
}
if (!this.mTabChangedListenerAdded) {
this.mTabBox.addEventListener("DOMAttrModified", attrChanged, false);
this.mTabChangedListenerAdded = true;
}
}
var b = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
"browser");
@ -1190,6 +1247,20 @@
]]>
</body>
</method>
<method name="resetOwner">
<parameter name="oldIndex"/>
<body>
<![CDATA[
// Reset the owner property, since we're leaving the modally opened
// tab for another.
if (oldIndex < this.mTabContainer.childNodes.length) {
var tab = this.mTabContainer.childNodes[oldIndex];
tab.owner = null;
}
]]>
</body>
</method>
<method name="removeTab">
<parameter name="aTab"/>
@ -1255,15 +1326,32 @@
newIndex = currentIndex-1;
else if (currentIndex < index)
newIndex = currentIndex;
else if (index == l - 1)
newIndex = index-1;
else
newIndex = index;
else {
if ("owner" in aTab && aTab.owner &&
this.mPrefs.getBoolPref("browser.tabs.selectOwnerOnClose")) {
for (i = 0; i < this.mTabContainer.childNodes.length; ++i) {
var tab = this.mTabContainer.childNodes[i];
if (tab == aTab.owner) {
newIndex = i;
break;
}
}
}
if (newIndex == -1)
newIndex = (index == l - 1) ? index - 1 : index;
}
var oldTab = aTab;
// clean up the before/afterselected attributes before removing the tab
oldTab.selected = false;
// Remove this tab as the owner of any other tabs, since it's going away.
for (i = 0; i < this.mTabContainer.childNodes.length; ++i) {
tab = this.mTabContainer.childNodes[i];
if (tab.owner == oldTab)
tab.owner = null;
}
// Because of the way XBL works (fields just set JS
// properties on the element) and the code we have in place
@ -1339,7 +1427,7 @@
]]>
</body>
</method>
<method name="addProgressListener">
<parameter name="aListener"/>
<parameter name="aMask"/>
@ -1456,7 +1544,8 @@
<parameter name="aDragAction"/>
<body>
<![CDATA[
if (aEvent.target.localName == "tab") {
if (aEvent.target.localName == "tab" &&
aEvent.originalTarget.localName != "toolbarbutton") {
aXferData.data = new TransferData();
var URI = this.getBrowserForTab(aEvent.target).currentURI;
@ -1548,7 +1637,7 @@
}
else {
// Load in an existing tab.
var tab = aEvent.originalTarget;
var tab = aEvent.target;
this.getBrowserForTab(tab).loadURI(getShortcutOrURI(url));
if (this.mCurrentTab != tab && !bgLoad)
@ -2045,6 +2134,27 @@
<property name="forceSyncURLBarUpdate"
onget="return this.mModalDialogShowing;"/>
<method name="createTooltip">
<parameter name="event"/>
<body>
<![CDATA[
event.preventBubble();
var tn = document.tooltipNode;
if (tn.localName != "tab")
return false; // Not a tab, so cancel the tooltip
if ("mOverCloseButton" in tn && tn.mOverCloseButton) {
event.target.setAttribute("label", tn.getAttribute("closetabtext"));
return true;
}
if (tn.hasAttribute("label")) {
event.target.setAttribute("label", tn.getAttribute("label"));
return true;
}
return false;
]]>
</body>
</method>
<constructor>
<![CDATA[
@ -2136,5 +2246,150 @@
</handler>
</handlers>
</binding>
<binding id="tabbrowser-tabs"
extends="chrome://global/content/bindings/tabbox.xml#tabs">
<content>
<xul:hbox flex="1" style="min-width: 1px;">
<children includes="tab"/>
<xul:spacer class="tabs-right" flex="1"/>
</xul:hbox>
</content>
<implementation implements="nsIObserver">
<constructor>
var pb2 =
Components.classes['@mozilla.org/preferences-service;1'].
getService(Components.interfaces.nsIPrefBranch2);
try {
this.mTabClipWidth = pb2.getIntPref("browser.tabs.tabClipWidth");
}
catch (e) {
}
this._updateDisableBackgroundClose();
pb2.addObserver("browser.tabs.disableBackgroundClose", this, false);
var self = this;
function onResize() {
self.adjustCloseButtons(1);
}
window.addEventListener("resize", onResize, false);
</constructor>
<destructor>
var pb2 =
Components.classes["@mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefBranch2);
pb2.removeObserver("browser.tabs.disableBackgroundClose", this);
</destructor>
<method name="_updateDisableBackgroundClose">
<body><![CDATA[
var prefs =
Components.classes['@mozilla.org/preferences-service;1'].
getService(Components.interfaces.nsIPrefBranch);
try {
if (prefs.getBoolPref("browser.tabs.disableBackgroundClose"))
this.setAttribute("disablebackgroundclose", "true");
else
this.removeAttribute("disablebackgroundclose");
}
catch (e) {
this.setAttribute("disablebackgroundclose", "true");
}
]]></body>
</method>
<method name="observe">
<parameter name="subject"/>
<parameter name="topic"/>
<parameter name="data"/>
<body><![CDATA[
if (topic == "nsPref:changed")
this._updateDisableBackgroundClose();
]]></body>
</method>
<field name="mTabClipWidth">140</field>
<method name="adjustCloseButtons">
<parameter name="aNumTabs"/>
<body><![CDATA[
// aNumTabs is the number of tabs that need to be present to cause
// the close button on the last visible tab to disappear when the
// pref for "always show the tab bar, even when only one tab is open"
// is set.
// When tabs are being removed from the tab strip, and the number of
// open tabs approaches 1 (i.e. when the number of open tabs is 2
// and one is removed), we need to set an attribute on the tabstrip
// that will cause the close button on the last item to be hidden.
// When tabs are being added to the tab strip - the number of open
// tabs is increasing (i.e. the number of open tabs is 1 and one is
// added) then we need to remove the attribute on the tab strip which
// will cause the close button to be shown on all tabs.
try {
if (this.childNodes.length == aNumTabs)
this.setAttribute("singlechild", "true");
else
this.removeAttribute("singlechild");
var width = this.firstChild.boxObject.width;
// 0 width is an invalid value and indicates an item without display,
// so ignore.
if (width > this.mTabClipWidth || width == 0)
this.removeAttribute("tiny");
else
this.setAttribute("tiny", "true");
}
catch (e) {
}
]]></body>
</method>
</implementation>
<handlers>
<handler event="DOMNodeInserted" action="this.adjustCloseButtons(1);"/>
<handler event="DOMNodeRemoved" action="this.adjustCloseButtons(2);"/>
</handlers>
</binding>
<binding id="tabbrowser-tab" display="xul:box"
extends="chrome://global/content/bindings/tabbox.xml#tab">
<content chromedir="&locale.dir;" mousethrough="always"
closetabtext="&closeTab.label;">
<xul:hbox class="tab-middle box-inherit" xbl:inherits="align,dir,pack,orient,selected" flex="1">
<xul:image class="tab-icon" xbl:inherits="validate,src=image"/>
<xul:label class="tab-text" xbl:inherits="value=label,accesskey,crop,disabled" flex="1"/>
</xul:hbox>
<xul:image anonid="close-button-placeholder" class="tab-close-button-placeholder"/>
<xul:toolbarbutton anonid="close-button" class="tab-close-button"/>
</content>
<implementation>
<field name="mOverCloseButton">false</field>
</implementation>
<handlers>
<handler event="mouseover">
var anonid = event.originalTarget.getAttribute("anonid");
if (anonid == "close-button")
this.mOverCloseButton = true;
</handler>
<handler event="mouseout">
var anonid = event.originalTarget.getAttribute("anonid");
if (anonid == "close-button")
this.mOverCloseButton = false;
</handler>
<handler event="command">
<![CDATA[
var anonid = event.originalTarget.getAttribute("anonid");
if (anonid == "close-button")
this.parentNode.parentNode.parentNode.parentNode.removeTab(this);
]]>
</handler>
<handler event="mousedown" button="0" phase="capturing">
<![CDATA[
if (this.mOverCloseButton)
event.stopPropagation();
]]>
</handler>
</handlers>
</binding>
</bindings>

Просмотреть файл

@ -595,6 +595,13 @@ tabs {
-moz-box-orient: horizontal;
}
/**
* XXXben - this looks like something added specifically for tabbrowser.
* if it turns out no one uses this that can't easily be evangelized to
* use their own roll-your-own binding, then we should get rid of this
* to tighten up the toolkit api. This binding made obsolete in Firefox
* by 308396.
*/
tabs[closebutton="true"] {
-moz-binding: url("chrome://global/content/bindings/tabbox.xml#tabs-closebutton");
}
@ -605,6 +612,41 @@ tab {
-moz-box-pack: center;
}
.tabbrowser-tabs {
-moz-binding: url("chrome://global/content/bindings/tabbrowser.xml#tabbrowser-tabs");
}
.tabbrowser-tabs > .tabbrowser-tab {
-moz-binding: url("chrome://global/content/bindings/tabbrowser.xml#tabbrowser-tab");
}
.tab-close-button {
display: -moz-box;
}
.tab-close-button-placeholder {
display: none;
}
.tabbrowser-tabs[disablebackgroundclose="true"] > .tabbrowser-tab:not([selected="true"]) > .tab-close-button {
display: none;
}
.tabbrowser-tabs[disablebackgroundclose="true"]:not([tiny="true"]):not([singlechild="true"]) > .tabbrowser-tab:not([selected="true"]) .tab-close-button-placeholder {
display: -moz-box;
}
.tabbrowser-tabs[tiny="true"] > .tabbrowser-tab > .tab-close-button,
.tabbrowser-tabs[tiny="true"] > .tabbrowser-tab .tab-close-button-placeholder,
.tabbrowser-tabs[singlechild="true"] > .tabbrowser-tab > .tab-close-button,
.tabbrowser-tabs[singlechild="true"] > .tabbrowser-tab .tab-close-button-placeholder {
display: none;
}
.tabbrowser-tabs[tiny="true"] > .tabbrowser-tab[selected="true"] > .tab-close-button {
display: -moz-box;
}
tabpanels {
-moz-binding: url("chrome://global/content/bindings/tabbox.xml#tabpanels");
display: -moz-deck;

Просмотреть файл

@ -34,12 +34,12 @@ tab:hover > .tab-image-middle > .tab-icon > .tab-extra-status {
}
.tab-icon {
padding-top: 1px;
padding-top: 1px;
}
.tab-text {
font: icon;
padding-top: 1px;
font: icon;
padding-top: 1px;
}
@ -49,7 +49,7 @@ tab[busy] > .tab-icon-image, tab[busy] > .tab-image-middle > .tab-icon > .tab-ic
}
tab {
-moz-binding: url("chrome://global/skin/globalBindings.xml#tab") !important;
-moz-binding: url("chrome://global/skin/globalBindings.xml#tabbrowser-tab") !important;
-moz-appearance: none;
color: #383838;
-moz-box-pack: center;
@ -109,7 +109,13 @@ tab:not([selected="true"]) > .tab-image-middle > .tab-icon > .tab-icon-image {
}
/* ::::: close button ::::: */
/**
* XXXben - this looks like something added specifically for tabbrowser.
* if it turns out no one uses this that can't easily be evangelized to
* use their own roll-your-own binding, then we should get rid of this
* to tighten up the toolkit api. This binding made obsolete in Firefox
* by 308396.
*/
.tabs-closebutton {
padding: 0px 4px 2px 0px;
margin: 0px;
@ -130,12 +136,11 @@ tab:not([selected="true"]) > .tab-image-middle > .tab-icon > .tab-icon-image {
-moz-box-orient: vertical !important;
}
.tabbrowser-tabs {
padding: 0px;
margin: 0px;
-moz-box-pack: center;
-moz-box-align: center;
background: url("chrome://global/skin/10pct_transparent_pixel.png") repeat;
padding: 0px;
margin: 0px;
-moz-box-pack: center;
-moz-box-align: center;
background: url("chrome://global/skin/10pct_transparent_pixel.png") repeat;
}
@ -182,3 +187,54 @@ tabbrowser > tabbox > tabpanels {
display: -moz-box;
}
/**
* In-tab close button
*/
.tab-close-button > .toolbarbutton-icon {
-moz-margin-end: 0px !important;
}
.tab-close-button {
list-style-image: url("chrome://global/skin/icons/closetab.png");
-moz-appearance: none;
-moz-margin-start: -5px;
-moz-padding-end: 3px;
margin-top: 2px;
border: none !important;
padding: 0px;
opacity: 0.7;
}
.tab-close-button:hover,
.tabbrowser-tab[selected="true"] > .tab-close-button:hover {
opacity: 1.0;
}
.tab-close-button:hover:active,
.tabbrowser-tab[selected="true"] > .tab-close-button:hover:active {
list-style-image: url("chrome://global/skin/icons/closetab-active.png");
opacity: 1.0;
}
.tabbrowser-tab[selected="true"] > .tab-close-button {
-moz-margin-start: -5px;
-moz-margin-end: -1px;
margin-top: 0px;
opacity: 1.0;
-moz-padding-end: 3px;
padding-top: 2px;
background-image: url("chrome://global/skin/activetab-middle.png");
background-repeat: no-repeat;
background-position: 5px 0px;
}
.tab-close-button-placeholder {
list-style-image: url("chrome://global/skin/icons/closetab.png");
opacity: 0.5;
-moz-margin-start: -5px;
-moz-padding-end: 3px;
margin-top: 2px;
border: none !important;
padding: 0px;
}

Просмотреть файл

@ -93,7 +93,7 @@ menulist > menupopup,
}
.tabbrowser-tabs {
-moz-binding: url("chrome://global/skin/globalBindings.xml#tabs-closebutton");
-moz-binding: url("chrome://global/skin/globalBindings.xml#tabbrowser-tabs");
}
/* ::::: root elements ::::: */

Просмотреть файл

@ -5,17 +5,18 @@
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="tab" extends="chrome://global/content/bindings/tabbox.xml#tab">
<binding id="tabbrowser-tab" extends="chrome://global/content/bindings/tabbrowser.xml#tabbrowser-tab">
<content>
<xul:hbox class="tab-image-left" xbl:inherits="selected"/>
<xul:hbox pack="center" align="center">
<xul:image anonid="close-button-placeholder" class="tab-close-button-placeholder"/>
</xul:hbox>
<xul:toolbarbutton anonid="close-button" class="tab-close-button"/>
<xul:hbox flex="1" class="tab-image-middle" align="center" xbl:inherits="selected">
<xul:stack class="tab-icon">
<xul:image xbl:inherits="validate,src=image" class="tab-icon-image"/>
<xul:image class="tab-extra-status"/>
</xul:stack>
<xul:image xbl:inherits="validate,src=image" class="tab-icon-image"/>
<xul:image class="tab-extra-status"/>
</xul:stack>
<xul:label flex="1" xbl:inherits="value=label,crop,accesskey" crop="right" class="tab-text"/>
</xul:hbox>
<xul:hbox class="tab-image-right" xbl:inherits="selected"/>
@ -37,8 +38,8 @@
</content>
</binding>
<binding id="tabs-closebutton"
extends="chrome://global/content/bindings/tabbox.xml#tabs">
<binding id="tabbrowser-tabs"
extends="chrome://global/content/bindings/tabbrowser.xml#tabbrowser-tabs">
<content>
<xul:stack flex="1" class="tabs-stack">
<xul:vbox>
@ -54,12 +55,6 @@
<children/>
<xul:spacer class="tabs-right" flex="1"/>
</xul:hbox>
<xul:stack>
<xul:spacer class="tabs-right"/>
<xul:hbox class="tabs-closebutton-box" align="center" pack="end">
<xul:toolbarbutton class="tabs-closebutton close-button" xbl:inherits="disabled=disableclose,oncommand=onclosetab"/>
</xul:hbox>
</xul:stack>
</xul:hbox>
<xul:spacer class="tabs-bottom-spacer"/>
</xul:vbox>

Просмотреть файл

@ -10,11 +10,11 @@ tabpanels {
}
.tabbrowser-tabs {
padding-top: 1px;
background: transparent url("chrome://global/skin/icons/tabstrip-bottom.png") repeat-x bottom center !important;
-moz-padding-start: 2px;
border-bottom: 2px solid;
-moz-border-bottom-colors: threedshadow threedlightshadow;
padding-top: 1px;
background: transparent url("chrome://global/skin/icons/tabstrip-bottom.png") repeat-x bottom center !important;
-moz-padding-start: 2px;
border-bottom: 2px solid;
-moz-border-bottom-colors: threedshadow threedlightshadow;
}
.tabs-left,
@ -40,6 +40,12 @@ tab[busy] > .tab-middle > .tab-icon {
tab[selected="true"] {
font-weight: bold;
margin-bottom: 0px;
-moz-padding-start: 3px;
}
.tabbrowser-tabs[tiny="true"] > .tabbrowser-tab[selected="true"],
.tabborwser-tabs[singlechild="true"] > .tabbrowser-tab[selected="true"] {
min-width: 50px; /* approximately favicon + close icon + slop for tab boundaries */
}
tab {
@ -91,3 +97,65 @@ browsermessage[type="bottom"] {
.messageButton {
margin: 0px 5px 0px 5px;
}
/**
* In-tab close button
*/
.tab-close-button > .toolbarbutton-icon {
-moz-margin-end: 0px !important;
}
.tab-close-button {
list-style-image: url("chrome://global/skin/icons/close.png");
-moz-appearance: none;
-moz-image-region: rect(0px, 64px, 16px, 48px);
-moz-margin-start: 2px;
margin-top: 2px;
border: none !important;
padding: 0px;
opacity: 0.7;
}
.tab-close-button:hover,
.tabbrowser-tab[selected="true"] > .tab-close-button:hover {
-moz-image-region: rect(0px, 32px, 16px, 16px);
opacity: 1.0;
}
.tab-close-button:hover:active,
.tabbrowser-tab[selected="true"] > .tab-close-button:hover:active {
-moz-image-region: rect(0px, 48px, 16px, 32px);
opacity: 1.0;
}
.tab-close-button-placeholder {
list-style-image: url("chrome://global/skin/icons/close.png");
-moz-image-region: rect(0px, 64px, 16px, 48px);
opacity: 0.7;
-moz-margin-start: 2px;
margin-top: 2px;
border: none !important;
padding: 0px;
}
.tabbrowser-tab[selected="true"] > .tab-close-button {
-moz-margin-start: 2px;
margin-top: 0px;
opacity: 1.0;
-moz-image-region: rect(0px, 16px, 16px, 0px);
}
/**
* Tabbrowser Tabs
*/
.tabbrowser-tab[selected="true"] {
-moz-padding-end: 4px;
padding-top: 4px;
padding-bottom: 1px;
}
.tabbrowser-tab[selected="true"] > .tab-middle {
padding-bottom: 1px;
-moz-padding-start: 1px;
margin-bottom: 1px;
}

Двоичные данные
toolkit/themes/winstripe/global/icons/close.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 1.8 KiB

После

Ширина:  |  Высота:  |  Размер: 2.1 KiB