Adds menuitem for Open In Tabs.

Reorganizes code so that command/click handlers for toolbar/menu bindings can be attached by overlays.
r=ben@mozilla.org bug=327034


git-svn-id: svn://10.0.0.236/trunk@191751 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
annie.sullivan%gmail.com 2006-03-04 01:12:05 +00:00
parent 829b0ed044
commit c53df84f97
8 changed files with 189 additions and 64 deletions

View File

@ -439,13 +439,18 @@
#else
<menu id="bookmarksMenu"
label="&bookmarksMenu.label;" accesskey="&bookmarksMenu.accesskey;">
<menupopup id="bookmarksMenuPopup" type="places" context="placesContext">
<menupopup id="bookmarksMenuPopup"
type="places"
context="placesContext"
openInTabs="children"
oncommand="BookmarksMenu.onCommand(event);"
onclick="BookmarksMenu.onClick(event);">
<menuitem label="&addCurPageAsCmd.label;"
command="Browser:AddBookmarkAs" key="addBookmarkAsKb"/>
<!-- XXXben - this should move to the end of the list -->
<menuseparator builder="start"/>
<menuseparator builder="end"/>
<menuitem label="&manBookmarksCmd.label;"
command="Browser:ShowBookmarks" key="manBookmarkKb"/>
<menuseparator builder="start"/>
</menupopup>
</menu>
#endif

View File

@ -6974,5 +6974,87 @@ var HistoryMenu = {
},
};
/*
* Functions for the Bookmarks Menu
*/
var BookmarksMenu = {
/*
* Handler for when an item in the bookmarks menu is clicked.
* If the click is a middle-click, opens the item in a new tab
* and closes the menu. (Left-clicks are handled by the command handler)
* @param event DOMEvent for the click
*/
onClick: function BM_onClick(event) {
if (event.button == 1) {
PlacesController.mouseLoadURI(event);
// Menus selected with middle click must be closed manually.
var node = event.target;
while (node &&
(node.localName == "menu" ||
node.localName == "menupopup")) {
if (node.localName == "menupopup")
node.hidePopup();
node = node.parentNode;
}
}
},
/*
* Handler for command event for an item in the bookmarks menu.
* Opens the item.
* @param event DOMEvent for the command
*/
onCommand: function BM_onCommand(event) {
PlacesController.mouseLoadURI(event);
}
};
/*
* Functions for the Bookmarks Toolbar
*/
var BookmarksToolbar = {
/*
* Handler for click event for an item in the bookmarks toolbar.
* Menus and submenus from the folder buttons bubble up to this handler.
* Only handle middle-click; left-click is handled in the onCommand function.
* When items are middle-clicked, open them in tabs.
* If the click came through a menu, close the menu.
* @param event DOMEvent for the click
*/
onClick: function BT_onClick(event) {
// Only handle middle-clicks.
if (event.button != 1)
return;
PlacesController.openLinksInTabs();
// If this event bubbled up from a menu or menuitem,
// close the menus.
if (event.target.localName == "menu" ||
event.target.localName == "menuitem") {
var node = event.target;
while (node &&
(node.localName == "menu" ||
node.localName == "menupopup")) {
if (node.localName == "menupopup")
node.hidePopup();
node = node.parentNode;
}
}
},
/*
* Handler for command event for an item in the bookmarks toolbar.
* Menus and submenus from the folder buttons bubble up to this handler.
* Opens the item.
* @param event DOMEvent for the command
*/
onCommand: function BM_onCommand(event) {
PlacesController.mouseLoadURI(event);
}
};
#endif

View File

@ -273,7 +273,10 @@
<toolbarbutton id="bookmarksBarShowPlaces"
oncommand="PlacesBrowserShim.showHistory()"/>
<toolbaritem flex="1" id="personal-bookmarks" title="&bookmarksItem.title;">
<hbox id="bookmarksBarContent" flex="1" context="placesContext"/>
<hbox id="bookmarksBarContent" flex="1"
context="placesContext"
onclick="BookmarksToolbar.onClick(event);"
oncommand="BookmarksToolbar.onCommand(event);"/>
</toolbaritem>
<toolbarbutton id="places-bookmark"
label="&location.status.not_bookmarked;"

View File

@ -1,5 +1,5 @@
<commandset id="placesCommands"
commandupdater="true" events="focus,select,mousedown,click"
commandupdater="true" events="focus,select,mousedown,click,keypress"
oncommandupdate="PlacesController.onCommandUpdate()">
<command id="placesCmd_find" label="&cmd.find.label;" accesskey="&cmd.find.accesskey;"
oncommand="PlacesSearchBox.focus();"/>
@ -45,8 +45,13 @@
<commandset type="link">
</commandset>
<commandset type="container" readonly="true">
<!-- The open:tabs command gets enabled/disabled based on the current
selection, and is used in the context menu for a node.
The open:tabsEnabled is always enabled, and is shown in bookmarks menus. -->
<command id="placesCmd_open:tabs" label="&cmd.open_tabs.label;" accesskey="&cmd.open_tabs.accesskey;"
oncommand="PlacesController.openLinksInTabs();"/>
<command id="placesCmd_open:tabsEnabled" label="&cmd.open_tabs.label;" accesskey="&cmd.open_tabs.accesskey;"
oncommand="PlacesController.openLinksInTabs();"/>
<command id="placesCmd_groupby:site"
label="&cmd.groupby_site.label;" accesskey="&cmd.groupby_site.accesskey;"
oncommand="PlacesController.groupBySite();"/>

View File

@ -632,6 +632,7 @@ var PlacesController = {
this.nodeIsFolder(this._activeView.selectedNode);
this._setEnabled("placesCmd_open:tabs",
singleFolderSelected || !hasSingleSelection);
this._setEnabled("placesCmd_open:tabsEnabled", true); // Always on
// Some views, like menupopups, destroy their result as they hide, but they
// are still the "last-active" view. Don't barf.
@ -799,6 +800,8 @@ var PlacesController = {
var node = this._activeView.selectedNode;
if (this._activeView.hasSingleSelection && this.nodeIsFolder(node)) {
asFolder(node);
var wasOpen = node.containerOpen;
node.containerOpen = true;
var cc = node.childCount;
for (var i = 0; i < cc; ++i) {
var childNode = node.getChild(i);
@ -806,6 +809,7 @@ var PlacesController = {
this._activeView.browserWindow.openNewTabWith(childNode.uri,
null, null);
}
node.containerOpen = wasOpen;
}
else {
var nodes = this._activeView.getSelectionNodes();
@ -1065,8 +1069,11 @@ var PlacesController = {
var parent = node.parent;
if (!parent || !this.nodeIsContainer(parent))
return -1;
var cc = asContainer(parent).childCount;
var wasOpen = parent.containerOpen;
parent.containerOpen = true;
var cc = parent.childCount;
for (var i = 0; i < cc && asContainer(parent).getChild(i) != node; ++i);
parent.containerOpen = wasOpen;
return i < cc ? i : -1;
},
@ -1195,6 +1202,8 @@ var PlacesController = {
// Get the folder's children
var kids = self.getFolderContents(folderId, false, false);
var wasOpen = kids.containerOpen;
kids.containerOpen = true;
var cc = kids.childCount;
for (var i = 0; i < cc; ++i) {
var node = kids.getChild(i);
@ -1206,6 +1215,7 @@ var PlacesController = {
index));
}
}
kids.containerOpen = wasOpen;
}
createTransactions(data.folderId, container, index);
return new PlacesAggregateTransaction("FolderCopy", transactions);
@ -1800,6 +1810,9 @@ PlacesRemoveFolderTransaction.prototype = {
*/
_saveFolderContents: function PRFT__saveFolderContents(id, parent) {
var contents = PlacesController.getFolderContents(id, false, false);
// Container open status doesn't need to be reset to what it was before
// because it's being deleted.
contents.containerOpen = true;
for (var i = contents.childCount - 1; i >= 0; --i) {
var child = contents.getChild(i);
var obj = null;

View File

@ -10,6 +10,9 @@
extends="chrome://global/content/bindings/popup.xml#popup">
<implementation>
<constructor><![CDATA[
var bundle = document.getElementById("placeBundle");
this._labelOpenInTabs = bundle.getString("menuOpenInTabs.label");
this._accesskeyOpenInTabs = bundle.getString("menuOpenInTabs.accesskey");
]]></constructor>
<destructor><![CDATA[
@ -97,14 +100,17 @@
this._endMarker = i;
continue;
}
if ((this._startMarker != -1) && (this._endMarker == -1))
if ((this._startMarker != -1) && (this._endMarker == -1))
items.push(item);
}
// If static items at the beginning were found, remove all items between
// them and the static content at the end.
for (var i = 0; i < items.length; ++i)
for (var i = 0; i < items.length; ++i) {
items[i].parentNode.removeChild(items[i]);
if (this._endMarker > 0)
--this._endMarker;
}
// If no static items were found at the beginning, remove all items before
// the static items at the end.
@ -112,6 +118,8 @@
var end = (this._endMarker == -1) ? this.childNodes.length - 1 : this._endMarker - 1;
for (var i = end; i >=0; i--) {
this.removeChild(this.childNodes[i]);
if (this._endMarker > 0)
--this._endMarker;
}
}
LOG("KIDS = " + this.childNodes.length);
@ -173,6 +181,8 @@
element.setAttribute("label", child.title);
var popup = document.createElementNS(XULNS, "menupopup");
popup.setAttribute("type", "places");
if (this.hasAttribute("openInTabs"))
popup.setAttribute("openInTabs", "all"); // Include menu option to open in tabs.
element.appendChild(popup);
#ifndef XP_MACOSX
// No context menus on menus on Mac
@ -220,6 +230,18 @@
}
}
// If this menu has the attribute set to open children in tabs,
// add the menuitems here to do that.
if ((cc > 0) && this.getAttribute("openInTabs") == "all") {
var separator = document.createElementNS(XULNS, "menuseparator");
this.appendChild(separator);
var openInTabs = document.createElementNS(XULNS, "menuitem");
openInTabs.setAttribute("label", this._labelOpenInTabs);
openInTabs.setAttribute("accesskey", this._accesskeyOpenInTabs);
openInTabs.setAttribute("command", "placesCmd_open:tabsEnabled");
this.appendChild(openInTabs);
}
// Reset the container to the same state it was in before the function was called.
this._resultNode.containerOpen = wasOpen;
]]></body>
@ -474,7 +496,7 @@
// get dropped in/above/below.
// Ignore static content at the top and bottom of the menu.
var start = (this._self._startMarker != -1) ? (this._self._startMarker + 1) : 0;
var end = (this._self._endMarker != -1) ? this.self._endMarker : this._self.childNodes.length;
var end = (this._self._endMarker != -1) ? this._self._endMarker : this._self.childNodes.length;
for (var i = start; i < end; i++) {
var xulNode = this._self.childNodes[i];
var nodeY = xulNode.boxObject.y - this._self.boxObject.y;
@ -604,6 +626,40 @@
})]]></field>
<!-- Checks whether and event should be acted on by this menu
(It should be if the event affects one of this menu's child
nodes) -->
<method name="eventValid">
<parameter name="event"/>
<body><![CDATA[
if ((event.target.localName != "menuitem" &&
event.target.localName != "menuseparator" &&
event.target.localName != "menu") ||
event.target.parentNode != this)
return false;
return true;
]]></body>
</method>
<!-- Sets the active view to this view, and sets the selection
to the node from this event. -->
<method name="setSelectionForEvent">
<parameter name="event"/>
<body><![CDATA[
// Set the selection to the node that was clicked on. If that
// node has a command but no data associated with it, it should
// act on the entire menu.
this._selection = event.target.node;
if (event.target.node == null && event.target.hasAttribute("command"))
this._selection = this._resultNode;
// Set the active view to this node.
PlacesController.activeView = this;
// When right clicking an item in a bookmarks menu the places commands
// need to be updated for the context menu to appear correctly.
document.commandDispatcher.updateCommands(event.type);
]]></body>
</method>
</implementation>
<handlers>
<handler event="popupshowing">
@ -623,54 +679,19 @@
this.removeAttribute("autoopened");
}
</handler>
<handler event="command"><![CDATA[
// Only menu and menuitems are valid nodes.
// Filter out events coming from sub-containers that have bubbled up.
if ((event.target.localName != "menuitem" &&
event.target.localName != "menuseparator" &&
event.target.localName != "menu") ||
event.target.parentNode != this)
return;
this._selection = event.target.node;
PlacesController.activeView = this;
PlacesController.mouseLoadURI(event);
]]></handler>
<handler event="click"><![CDATA[
// Left-click is handled by command handler.
if (event.button == 0)
return;
// Only menu and menuitems are valid nodes.
// Filter out events coming from sub-containers that have bubbled up.
if ((event.target.localName != "menuitem" &&
event.target.localName != "menuseparator" &&
event.target.localName != "menu") ||
event.target.parentNode != this)
return;
this._selection = event.target.node;
PlacesController.activeView = this;
// When right clicking an item in a bookmarks menu the places commands
// need to be updated for the context menu to appear correctly.
document.commandDispatcher.updateCommands("click");
// Only middle clicks should load the URI from this function
// (left clicks go through command event handler)
if (event.button != 1)
return;
PlacesController.mouseLoadURI(event);
// Menus selected with middle click must be closed manually.
if (event.button == 1) {
var node = this;
while (node &&
(node.localName == "menu" ||
node.localName == "menupopup")) {
if (node.localName == "menupopup")
node.hidePopup();
node = node.parentNode;
}
<!-- Set selected node/active view on mousedown/DOMMenuItemActive events
so that they're set up when command and click events fire. -->
<handler event="mousedown"><![CDATA[
if (this.eventValid(event)) {
this.setSelectionForEvent(event);
// Don't let the event bubble up to a parent toolbar.
event.preventBubble();
}
]]></handler>
<handler event="DOMMenuItemActive"><![CDATA[
if (this.eventValid(event))
this.setSelectionForEvent(event);
]]></handler>
<handler event="draggesture"><![CDATA[
if (event.target.localName == "menuitem")
// TODO--allow menu drag if shift (or alt??) key is down

View File

@ -120,6 +120,7 @@
button.setAttribute("container", "true");
var popup = document.createElementNS(XULNS, "menupopup");
popup.setAttribute("type", "places");
popup.setAttribute("openInTabs", "all"); // Include menu option to open in tabs.
// This is set here and not in the XBL constructor for the menu because
// it doesn't get initialized properly in the constructor.
#ifndef XP_MACOSX
@ -643,7 +644,7 @@
<handlers>
<handler event="mousedown"><![CDATA[
// When the user clicks down on a button, set it as the selection and
// tell the controller that we are the active view.
// tell the controller that we are the active view.
if (event.target.localName == "toolbarbutton" ||
event.target.localName == "toolbarseparator")
this._selection = event.target.node;
@ -652,14 +653,6 @@
PlacesController.activeView = this;
document.commandDispatcher.updateCommands("mousedown");
]]></handler>
<handler event="click"><![CDATA[
// Filter out events from non-toolbarbuttons
// Only left or middle clicks should load the URI
if (event.target.localName != "toolbarbutton" ||
event.button > 1)
return;
PlacesController.mouseLoadURI(event);
]]></handler>
<handler event="draggesture"><![CDATA[
if (event.target.localName == "toolbarbutton" &&
!event.target.hasAttribute("type"))

View File

@ -38,3 +38,6 @@ moreCriteria.label=+
locationStatusNotBookmarked=Star (Off)
locationStatusBookmarked=Star (On)
menuOpenInTabs.label=Open in Tabs
menuOpenInTabs.accesskey=o