bug 168504: de-XBLify the bookmarks toolbar
bug 172328, 172291: various DND problems
bug 192028: add context menus to the bookmark menu and the bookmarks toolbar.
This commit is contained in:
chanial%noos.fr 2003-02-23 21:49:19 +00:00
Родитель 60dd13df9e
Коммит 8a0a589d17
5 изменённых файлов: 1026 добавлений и 472 удалений

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

@ -23,12 +23,6 @@ window[chromehidden~="toolbar"] #navigator-throbber[busy="true"] {
-moz-binding: url("chrome://browser/content/search.xml#searchbar");
}
bookmarks-toolbar {
-moz-binding: url("chrome://browser/content/bookmarks/bookmarksToolbar.xml#bookmarks-toolbar");
min-width: 0px;
width:0px;
}
/* ::::: print preview toolbar ::::: */
toolbar[printpreview="true"] {

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

@ -406,9 +406,13 @@ function delayedStartup()
// now load bookmarks after a delay
BMSVC.ReadBookmarks();
var bt = document.getElementById("bookmarks-toolbar");
if (bt && "toolbar" in bt)
bt.toolbar.builder.rebuild();
var bt = document.getElementById("bookmarks-ptf");
if (bt) {
bt.builder.rebuild();
bt.database.AddObserver(BookmarksToolbarRDFObserver);
}
window.addEventListener("resize", BookmarksToolbar.resizeFunc, false);
controllers.appendController(BookmarksMenuController);
// called when we go into full screen, even if it is
// initiated by a web page script
@ -1395,38 +1399,6 @@ function updateToolbarStates(toolbarMenuElt)
}
}
// Fill in tooltips for personal toolbar
function FillInPTTooltip(tipElement)
{
var title = tipElement.label;
var url = tipElement.statusText;
if (!title && !url) {
// bail out early if there is nothing to show
return false;
}
var tooltipTitle = document.getElementById("ptTitleText");
var tooltipUrl = document.getElementById("ptUrlText");
if (title && title != url) {
tooltipTitle.removeAttribute("hidden");
tooltipTitle.setAttribute("value", title);
} else {
tooltipTitle.setAttribute("hidden", "true");
}
if (url) {
tooltipUrl.removeAttribute("hidden");
tooltipUrl.setAttribute("value", url);
} else {
tooltipUrl.setAttribute("hidden", "true");
}
return true; // show tooltip
}
function BrowserFullScreen()
{
window.fullScreen = !window.fullScreen;
@ -2014,387 +1986,6 @@ function OpenSearch(tabName, searchStr, newWindowFlag)
}
}
var personalToolbarDNDObserver = {
////////////////////
// Public methods //
////////////////////
onDragStart: function (aEvent, aXferData, aDragAction)
{
var target = aEvent.originalTarget;
// Prevent dragging from an invalid region
if (!this.canDrop(aEvent))
return;
// Prevent dragging out of menupopups on non Win32 platforms.
// a) on Mac drag from menus is generally regarded as being satanic
// b) on Linux, this causes an X-server crash, (bug 151336)
// c) on Windows, there is no hang or crash associated with this, so we'll leave
// the functionality there.
if (navigator.platform != "Win32" && target.localName != "toolbarbutton")
return;
// bail if dragging from the empty area of the bookmarks toolbar
if (target.localName == "hbox")
return
// a drag start is fired when leaving an open toolbarbutton(type=menu)
// (see bug 143031)
if (this.isContainer(target) &&
target.getAttribute("group") != "true") {
if (this.isPlatformNotSupported)
return;
if (!aEvent.shiftKey && !aEvent.altKey && !aEvent.ctrlKey)
return;
// menus open on mouse down
target.firstChild.hidePopup();
}
var bt = document.getElementById("bookmarks-toolbar");
var selection = bt.getBTSelection(target);
aXferData.data = BookmarksUtils.getXferDataFromSelection(selection);
},
onDragOver: function(aEvent, aFlavour, aDragSession)
{
var bt = document.getElementById("bookmarks-toolbar");
var orientation = bt.getBTOrientation(aEvent)
if (aDragSession.canDrop)
this.onDragSetFeedBack(aEvent.originalTarget, orientation);
if (orientation != this.mCurrentDropPosition) {
// emulating onDragExit and onDragEnter events since the drop region
// has changed on the target.
this.onDragExit(aEvent, aDragSession);
this.onDragEnter(aEvent, aDragSession);
}
if (this.isPlatformNotSupported)
return;
if (this.isTimerSupported)
return;
this.onDragOverCheckTimers();
},
onDragEnter: function (aEvent, aDragSession)
{
var target = aEvent.originalTarget;
var bt = document.getElementById("bookmarks-toolbar");
var orientation = bt.getBTOrientation(aEvent);
if (target.localName == "menupopup" || target.localName == "hbox")
target = target.parentNode;
if (aDragSession.canDrop) {
this.onDragSetFeedBack(target, orientation);
this.onDragEnterSetTimer(target, aDragSession);
}
this.mCurrentDragOverTarget = target;
this.mCurrentDropPosition = orientation;
},
onDragExit: function (aEvent, aDragSession)
{
var target = aEvent.originalTarget;
if (target.localName == "menupopup" || target.localName == "hbox")
target = target.parentNode;
this.onDragRemoveFeedBack(target);
this.onDragExitSetTimer(target, aDragSession);
this.mCurrentDragOverTarget = null;
this.mCurrentDropPosition = null;
},
onDrop: function (aEvent, aXferData, aDragSession)
{
var target = aEvent.originalTarget;
this.onDragRemoveFeedBack(target);
var bt = document.getElementById("bookmarks-toolbar");
var selection = BookmarksUtils.getSelectionFromXferData(aDragSession);
// if the personal toolbar does not exist, recreate it
if (target == "bookmarks-toolbar") {
//BookmarksUtils.recreatePersonalToolbarFolder(transactionSet);
//target = { parent: "NC:PersonalToolbarFolder", index: 1 };
} else {
var orientation = bt.getBTOrientation(aEvent);
var selTarget = bt.getBTTarget(target, orientation);
}
const kDSIID = Components.interfaces.nsIDragService;
const kCopyAction = kDSIID.DRAGDROP_ACTION_COPY + kDSIID.DRAGDROP_ACTION_LINK;
// hide the 'open in tab' menuseparator because bookmarks
// can be inserted after it if they are dropped after the last bookmark
// a more comprehensive fix would be in the menupopup template builder
var menuTarget = (target.localName == "toolbarbutton" ||
target.localName == "menu") &&
orientation == BookmarksUtils.DROP_ON?
target.lastChild:target.parentNode;
if (menuTarget.hasChildNodes() &&
menuTarget.lastChild.id == "openintabs-menuitem") {
menuTarget.removeChild(menuTarget.lastChild.previousSibling);
}
if (aDragSession.dragAction & kCopyAction)
BookmarksUtils.insertSelection("drag", selection, selTarget, true);
else
BookmarksUtils.moveSelection("drag", selection, selTarget);
// show again the menuseparator
if (menuTarget.hasChildNodes() &&
menuTarget.lastChild.id == "openintabs-menuitem") {
var element = document.createElementNS(XUL_NS, "menuseparator");
menuTarget.insertBefore(element, menuTarget.lastChild);
}
},
canDrop: function (aEvent, aDragSession)
{
var target = aEvent.originalTarget;
var bt = document.getElementById("bookmarks-toolbar");
return bt.isBTBookmark(target.id) &&
target.id != "NC:SystemBookmarksStaticRoot" &&
target.id.substring(0,5) != "find:" ||
target.id == "bookmarks-menu" ||
target.getAttribute("class") == "chevron" ||
target.localName == "hbox";
},
canHandleMultipleItems: true,
getSupportedFlavours: function ()
{
var flavourSet = new FlavourSet();
flavourSet.appendFlavour("moz/rdfitem");
flavourSet.appendFlavour("text/x-moz-url");
flavourSet.appendFlavour("application/x-moz-file", "nsIFile");
flavourSet.appendFlavour("text/unicode");
return flavourSet;
},
////////////////////////////////////
// Private methods and properties //
////////////////////////////////////
springLoadedMenuDelay: 350, // milliseconds
isPlatformNotSupported: navigator.platform.indexOf("Mac") != -1, // see bug 136524
isTimerSupported: navigator.platform.indexOf("Win") == -1,
mCurrentDragOverTarget: null,
mCurrentDropPosition: null,
loadTimer : null,
closeTimer : null,
loadTarget : null,
closeTarget: null,
_observers : null,
get mObservers ()
{
if (!this._observers) {
var bt = document.getElementById("bookmarks-toolbar");
this._observers = [
document.getAnonymousElementByAttribute(bt , "anonid", "bookmarks-ptf"),
document.getElementById("bookmarks-menu").parentNode,
document.getAnonymousElementByAttribute(bt , "class", "chevron").parentNode
]
}
return this._observers;
},
getObserverForNode: function (aNode)
{
if (!aNode)
return null;
var node = aNode;
var observer;
do {
for (var i=0; i < this.mObservers.length; i++) {
observer = this.mObservers[i];
if (observer == node)
return observer;
}
node = node.parentNode;
} while (node != document)
return null;
},
onDragCloseMenu: function (aNode)
{
var children = aNode.childNodes;
for (var i = 0; i < children.length; i++) {
if (this.isContainer(children[i]) &&
children[i].getAttribute("open") == "true") {
this.onDragCloseMenu(children[i].lastChild);
if (children[i] != this.mCurrentDragOverTarget || this.mCurrentDropPosition != BookmarksUtils.DROP_ON)
children[i].lastChild.hidePopup();
}
}
},
onDragCloseTarget: function ()
{
var currentObserver = this.getObserverForNode(this.mCurrentDragOverTarget);
// close all the menus not hovered by the mouse
for (var i=0; i < this.mObservers.length; i++) {
if (currentObserver != this.mObservers[i])
this.onDragCloseMenu(this.mObservers[i]);
else
this.onDragCloseMenu(this.mCurrentDragOverTarget.parentNode);
}
},
onDragLoadTarget: function (aTarget)
{
if (!this.mCurrentDragOverTarget)
return;
// Load the current menu
if (this.mCurrentDropPosition == BookmarksUtils.DROP_ON &&
this.isContainer(aTarget) &&
aTarget.getAttribute("group") != "true")
aTarget.lastChild.showPopup(aTarget);
},
onDragOverCheckTimers: function ()
{
var now = new Date().getTime();
if (this.closeTimer && now-this.springLoadedMenuDelay>this.closeTimer) {
this.onDragCloseTarget();
this.closeTimer = null;
}
if (this.loadTimer && (now-this.springLoadedMenuDelay>this.loadTimer)) {
this.onDragLoadTarget(this.loadTarget);
this.loadTimer = null;
}
},
onDragEnterSetTimer: function (aTarget, aDragSession)
{
if (this.isPlatformNotSupported)
return;
if (this.isTimerSupported) {
var targetToBeLoaded = aTarget;
clearTimeout(this.loadTimer);
if (aTarget == aDragSession.sourceNode)
return;
//XXX Hack: see bug 139645
var thisHack = this;
this.loadTimer=setTimeout(function () {thisHack.onDragLoadTarget(targetToBeLoaded)}, this.springLoadedMenuDelay);
} else {
var now = new Date().getTime();
this.loadTimer = now;
this.loadTarget = aTarget;
}
},
onDragExitSetTimer: function (aTarget, aDragSession)
{
if (this.isPlatformNotSupported)
return;
var thisHack = this;
if (this.isTimerSupported) {
clearTimeout(this.closeTimer)
this.closeTimer=setTimeout(function () {thisHack.onDragCloseTarget()}, this.springLoadedMenuDelay);
} else {
var now = new Date().getTime();
this.closeTimer = now;
this.closeTarget = aTarget;
this.loadTimer = null;
// If user isn't rearranging within the menu, close it
// To do so, we exploit a Mac bug: timeout set during
// drag and drop on Windows and Mac are fired only after that the drop is released.
// timeouts will pile up, we may have a better approach but for the moment, this one
// correctly close the menus after a drop/cancel outside the personal toolbar.
// The if statement in the function has been introduced to deal with rare but reproducible
// missing Exit events.
if (aDragSession.sourceNode.localName != "menuitem" && aDragSession.sourceNode.localName != "menu")
setTimeout(function () { if (thisHack.mCurrentDragOverTarget) {thisHack.onDragRemoveFeedBack(thisHack.mCurrentDragOverTarget); thisHack.mCurrentDragOverTarget=null} thisHack.loadTimer=null; thisHack.onDragCloseTarget() }, 0);
}
},
onDragSetFeedBack: function (aTarget, aOrientation)
{
switch (aTarget.localName) {
case "toolbarseparator":
case "toolbarbutton":
switch (aOrientation) {
case BookmarksUtils.DROP_BEFORE:
aTarget.setAttribute("dragover-left", "true");
break;
case BookmarksUtils.DROP_AFTER:
aTarget.setAttribute("dragover-right", "true");
break;
case BookmarksUtils.DROP_ON:
aTarget.setAttribute("dragover-top" , "true");
aTarget.setAttribute("dragover-bottom", "true");
aTarget.setAttribute("dragover-left" , "true");
aTarget.setAttribute("dragover-right" , "true");
break;
}
break;
case "menuseparator":
case "menu":
case "menuitem":
switch (aOrientation) {
case BookmarksUtils.DROP_BEFORE:
aTarget.setAttribute("dragover-top", "true");
break;
case BookmarksUtils.DROP_AFTER:
aTarget.setAttribute("dragover-bottom", "true");
break;
case BookmarksUtils.DROP_ON:
break;
}
break;
case "hbox" :
// hit between the last visible bookmark and the chevron
var bt = document.getElementById("bookmarks-toolbar");
var newTarget = bt.getLastVisibleBookmark();
if (newTarget)
newTarget.setAttribute("dragover-right", "true");
break;
case "stack" :
case "menupopup": break;
default: dump("No feedback for: "+aTarget.localName+"\n");
}
},
onDragRemoveFeedBack: function (aTarget)
{
var newTarget;
var bt;
if (aTarget.localName == "hbox") {
// hit when dropping in the bt or between the last visible bookmark
// and the chevron
bt = document.getElementById("bookmarks-toolbar");
newTarget = bt.getLastVisibleBookmark();
if (newTarget)
newTarget.removeAttribute("dragover-right");
} else if (aTarget.localName == "stack") {
bt = document.getElementById("bookmarks-toolbar");
newTarget = bt.getLastVisibleBookmark();
newTarget.removeAttribute("dragover-right");
} else {
aTarget.removeAttribute("dragover-left");
aTarget.removeAttribute("dragover-right");
aTarget.removeAttribute("dragover-top");
aTarget.removeAttribute("dragover-bottom");
}
},
onDropSetFeedBack: function (aTarget)
{
//XXX Not yet...
},
isContainer: function (aTarget)
{
return aTarget.localName == "menu" ||
aTarget.localName == "toolbarbutton" &&
aTarget.getAttribute("type") == "menu";
}
}
function FillHistoryMenu(aParent, aMenu)
{
// Remove old entries if any

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

@ -20,6 +20,10 @@
# Rights Reserved.
#
# Contributor(s):
# Blake Ross <blaker@netscape.com>
# David Hyatt <hyatt@apple.com>
# Joe Hewitt <hewitt@netscape.com>
# Pierre Chanial <chanial@noos.fr>
# Dean Tessman <dean_tessman@hotmail.com>
<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
@ -54,6 +58,7 @@
<script type="application/x-javascript" src="chrome://global/content/findUtils.js"/>
<script type="application/x-javascript" src="chrome://browser/content/utilityOverlay.js"/>
<script type="application/x-javascript" src="chrome://browser/content/bookmarks/bookmarks.js"/>
<script type="application/x-javascript" src="chrome://browser/content/bookmarks/bookmarksMenu.js"/>
<script type="application/x-javascript" src="chrome://global/content/viewZoomOverlay.js"/>
<script type="application/x-javascript" src="chrome://browser/content/contentAreaUtils.js"/>
<script type="application/x-javascript" src="chrome://browser/content/browser.js"/>
@ -464,6 +469,82 @@
</treecols>
</tree>
<!-- bookmarks context menu -->
<popupset>
<menupopup id="bookmarks-context-menu"
onpopupshowing="BookmarksMenu.createContextMenu(event);"
onpopuphidden ="BookmarksMenu.destroyContextMenu(event);"/>
</popupset>
<template id='bookmarks-template' xmlns:nc="http://home.netscape.com/NC-rdf#">
<rule parent="hbox" rdf:type="http://home.netscape.com/NC-rdf#BookmarkSeparator">
<toolbarseparator uri="rdf:*"
rdf:type="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type"/>
</rule>
<!-- yes, the type attribute is necessary otherwise all leaves are
treated as containers for some reason -->
<rule parent="hbox" iscontainer="true" isempty="true"
rdf:type="http://home.netscape.com/NC-rdf#Folder">
<toolbarbutton type="menu" editable="true" class="bookmark-item"
rdf:type="http://home.netscape.com/NC-rdf#Folder"
uri="rdf:*" label="rdf:http://home.netscape.com/NC-rdf#Name">
<menupopup>
<menuitem label="&emptyItem.label;" disabled="true"/>
</menupopup>
</toolbarbutton>
</rule>
<rule parent="hbox" iscontainer="true">
<toolbarbutton type="menu" class="bookmark-item" uri="rdf:*" editable="true"
rdf:type="http://home.netscape.com/NC-rdf#Folder"
label="rdf:http://home.netscape.com/NC-rdf#Name">
<menupopup contextmenu="bookmarks-context-menu"/>
</toolbarbutton>
</rule>
<rule parent="hbox">
<toolbarbutton class="bookmark-item" uri="rdf:*" editable="true"
status="rdf:http://home.netscape.com/WEB-rdf#status"
rdf:type="http://home.netscape.com/NC-rdf#Bookmark"
image="rdf:http://home.netscape.com/NC-rdf#Icon"
statustext="rdf:http://home.netscape.com/NC-rdf#URL"
tooltip="btTooltip"
label="rdf:http://home.netscape.com/NC-rdf#Name"/>
</rule>
<rule iscontainer="true" isempty="true"
rdf:type="http://home.netscape.com/NC-rdf#Folder">
<menupopup>
<menu class="menu-iconic bookmark-item" uri="rdf:*"
type="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
label="rdf:http://home.netscape.com/NC-rdf#Name">
<menupopup>
<menuitem label="&emptyItem.label;" disabled="true"/>
</menupopup>
</menu>
</menupopup>
</rule>
<rule iscontainer="true">
<menupopup>
<menu class="menu-iconic bookmark-item" uri="rdf:*"
label="rdf:http://home.netscape.com/NC-rdf#Name"
type="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type">
<menupopup contextmenu="bookmarks-context-menu"/>
</menu>
</menupopup>
</rule>
<rule rdf:type="http://home.netscape.com/NC-rdf#BookmarkSeparator">
<menupopup>
<menuseparator uri="rdf:*" />
</menupopup>
</rule>
<rule>
<menupopup>
<menuitem class="menuitem-iconic bookmark-item" uri="rdf:*"
label="rdf:http://home.netscape.com/NC-rdf#Name"
image="rdf:http://home.netscape.com/NC-rdf#Icon"
status="rdf:http://home.netscape.com/WEB-rdf#status"/>
</menupopup>
</rule>
</template>
<toolbox id="navigator-toolbox" class="toolbox-top" mode="icons" iconsize="small">
<!-- Menu -->
<toolbar type="menubar" id="toolbar-menubar" class="chromeclass-menubar" customizable="true"
@ -678,55 +759,20 @@
</menupopup>
</menu>
<menu id="bookmarks-menu" label="&bookmarksMenu.label;" accesskey="&bookmarksMenu.accesskey;"
datasources="rdf:bookmarks rdf:files rdf:localsearch rdf:internetsearch"
<menu id="bookmarks-menu" label="&bookmarksMenu.label;" accesskey="&bookmarksMenu.accesskey;"
datasources="rdf:bookmarks rdf:files rdf:localsearch"
ref="NC:BookmarksRoot" flags="dont-test-empty"
onpopupshowing="document.getElementById('bookmarks-toolbar').showOpenInTabsMenuItem(event.originalTarget)"
onpopuphidden="document.getElementById('bookmarks-toolbar').hideOpenInTabsMenuItem(event.originalTarget)"
template='bookmarks-template'
onpopupshowing="BookmarksMenu.showOpenInTabsMenuItem(event.target)"
onpopuphidden="BookmarksMenu.hideOpenInTabsMenuItem(event.target)"
oncommand="BookmarksUtils.loadBookmarkBrowser(event, event.originalTarget, this.database)"
onclick="BookmarksUtils.loadBookmarkBrowserMiddleClick(event, this.database)"
ondraggesture="nsDragAndDrop.startDrag(event, personalToolbarDNDObserver)"
ondragdrop="nsDragAndDrop.drop(event, personalToolbarDNDObserver); event.preventBubble()"
ondragenter="nsDragAndDrop.dragEnter(event, personalToolbarDNDObserver); event.preventBubble()"
ondragexit="nsDragAndDrop.dragExit(event, personalToolbarDNDObserver); event.preventBubble()"
ondragover="nsDragAndDrop.dragOver(event, personalToolbarDNDObserver); event.preventBubble()">
<template xmlns:nc="http://home.netscape.com/NC-rdf#">
<rule iscontainer="true" isempty="true"
rdf:type="http://home.netscape.com/NC-rdf#Folder">
<menupopup>
<menu class="menu-iconic bookmark-item" uri="rdf:*"
type="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
label="rdf:http://home.netscape.com/NC-rdf#Name">
<menupopup>
<menuitem label="&emptyItem.label;" disabled="true"/>
</menupopup>
</menu>
</menupopup>
</rule>
<rule iscontainer="true">
<menupopup>
<menu class="menu-iconic bookmark-item" uri="rdf:*"
label="rdf:http://home.netscape.com/NC-rdf#Name"
type="rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#type">
<menupopup />
</menu>
</menupopup>
</rule>
<rule rdf:type="http://home.netscape.com/NC-rdf#BookmarkSeparator">
<menupopup>
<menuseparator uri="rdf:*" />
</menupopup>
</rule>
<rule>
<menupopup>
<menuitem class="menuitem-iconic bookmark-item" uri="rdf:*"
label="rdf:http://home.netscape.com/NC-rdf#Name"
image="rdf:http://home.netscape.com/NC-rdf#Icon"
status="rdf:http://home.netscape.com/WEB-rdf#status"/>
</menupopup>
</rule>
</template>
<menupopup>
ondraggesture="nsDragAndDrop.startDrag(event, BookmarksMenuDNDObserver)"
ondragdrop="nsDragAndDrop.drop(event, BookmarksMenuDNDObserver); event.preventBubble()"
ondragenter="nsDragAndDrop.dragEnter(event, BookmarksMenuDNDObserver); event.preventBubble()"
ondragexit="nsDragAndDrop.dragExit(event, BookmarksMenuDNDObserver); event.preventBubble()"
ondragover="nsDragAndDrop.dragOver(event, BookmarksMenuDNDObserver); event.preventBubble()">
<menupopup contextmenu='bookmarks-context-menu'>
<menuitem key="addBookmarkAsKb"
label="&addCurPageAsCmd.label;"
accesskey="&addCurPageAsCmd.accesskey;"
@ -869,8 +915,53 @@
tooltiptext="&throbber.tooltip;"/>
</toolbaritem>
<toolbaritem id="personal-bookmarks" title="&bookmarksItem.title;" flex="1">
<bookmarks-toolbar id="bookmarks-toolbar" flex="1"/>
<toolbaritem id="bookmarks-toolbar" title="&bookmarksItem.title;" flex="1">
<stack id="bookmarks-stack" flex="1" style="min-width:0px; width:0px;">
<hbox id="bookmarks-ptf" class="bookmarks-toolbar-items" contextmenu="bookmarks-context-menu"
flex="1" style="min-width:0px; width:0px;margin-left: 3px;"
datasources="rdf:bookmarks rdf:files rdf:localsearch"
template="bookmarks-template"
ref="NC:PersonalToolbarFolder" flags="dont-test-empty"
rdf:type="http://home.netscape.com/NC-rdf#Folder"
onpopupshowing="BookmarksMenu.showOpenInTabsMenuItem(event.originalTarget)"
onpopuphidden="BookmarksMenu.hideOpenInTabsMenuItem(event.originalTarget)"
oncommand="BookmarksUtils.loadBookmarkBrowser(event, event.originalTarget, this.database)"
onclick="BookmarksUtils.loadBookmarkBrowserMiddleClick(event, this.database)"
ondraggesture="nsDragAndDrop.startDrag(event, BookmarksMenuDNDObserver)"
ondragdrop="nsDragAndDrop.drop(event, BookmarksMenuDNDObserver); event.preventBubble()"
ondragenter="nsDragAndDrop.dragEnter(event, BookmarksMenuDNDObserver); event.preventBubble()"
ondragexit="nsDragAndDrop.dragExit(event, BookmarksMenuDNDObserver); event.preventBubble()"
ondragover="nsDragAndDrop.dragOver(event, BookmarksMenuDNDObserver); event.preventBubble()">
<tooltip id="btTooltip" noautohide="true"
onpopupshowing="return BookmarksToolbar.fillInBTTooltip(document.tooltipNode)">
<vbox id="btTooltipTextBox" flex="1">
<label id="btTitleText" />
<label id="btUrlText" />
</vbox>
</tooltip>
</hbox>
<hbox class="bookmarks-toolbar-overflow-items" mousethrough="always">
<hbox mousethrough="always" id="overflow-padder"/>
<toolbarbutton id="bookmarks-chevron" type="menu" class="chevron"
mousethrough="never" collapsed="true"
datasources="rdf:bookmarks rdf:files rdf:localsearch"
template="bookmarks-template"
ref="NC:PersonalToolbarFolder" flags="dont-test-empty"
onpopupshowing="BookmarksMenu.showOpenInTabsMenuItem(event.originalTarget)"
onpopuphidden="BookmarksMenu.hideOpenInTabsMenuItem(event.originalTarget)"
oncommand="BookmarksUtils.loadBookmarkBrowser(event, event.originalTarget, this.database)"
onclick="BookmarksUtils.loadBookmarkBrowserMiddleClick(event, this.database)"
ondraggesture="nsDragAndDrop.startDrag(event, BookmarksMenuDNDObserver)"
ondragdrop="nsDragAndDrop.drop(event, BookmarksMenuDNDObserver); event.preventBubble()"
ondragenter="nsDragAndDrop.dragEnter(event, BookmarksMenuDNDObserver); event.preventBubble()"
ondragexit="nsDragAndDrop.dragExit(event, BookmarksMenuDNDObserver); event.preventBubble()"
ondragover="nsDragAndDrop.dragOver(event, BookmarksMenuDNDObserver); event.preventBubble()">
<menupopup contextmenu="bookmarks-context-menu"/>
</toolbarbutton>
</hbox>
<toolbarbutton class="bookmark-item bookmarks-toolbar-customize" mousethrough="never"
label="Bookmarks Toolbar Items"/>
</stack>
</toolbaritem>
<toolbarbutton id="downloads-button" class="toolbarbutton-1"
@ -918,7 +1009,7 @@
<toolbarset id="customToolbars" context="toolbar-context-menu"/>
<toolbar id="PersonalToolbar" class="chromeclass-directories" iconsize="small"
customizable="true" defaultset="personal-bookmarks" mode="icons"
customizable="true" defaultset="bookmarks-toolbar" mode="icons"
toolbarname="&personalbarCmd.label;" accesskey="&personalbarCmd.accesskey;"/>
</toolbox>

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

@ -0,0 +1,878 @@
# -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
# ***** BEGIN LICENSE BLOCK *****
# Version: NPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Netscape Public License
# Version 1.1 (the "License"); you may not use this file except in
# compliance with the License. You may obtain a copy of the License at
# http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is
# Pierre Chanial <chanial@noos.fr>
# Portions created by the Initial Developer are Copyright (C) 1998
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# David Hyatt <hyatt@apple.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the NPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the NPL, the GPL or the LGPL.
var BookmarksMenu = {
_selection:null,
_target:null,
_orientation:null,
/////////////////////////////////////////////////////////////////////////////
// shows the 'Open in Tabs' menu item if validOpenInTabsMenuItem is true -->
showOpenInTabsMenuItem: function (aTarget)
{
if (!this.validOpenInTabsMenuItem(aTarget) ||
aTarget.lastChild.id == "openintabs-menuitem")
return;
var element = document.createElementNS(XUL_NS, "menuseparator");
aTarget.appendChild(element);
element = document.createElementNS(XUL_NS, "menuitem");
element.setAttribute("id", "openintabs-menuitem")
element.setAttribute("label", BookmarksUtils.getLocaleString("cmd_bm_openfolder"));
//element.setAttribute("class", "groupmark-item menuitem-iconic bookmark-item");
element.setAttribute("accesskey", BookmarksUtils.getLocaleString("cmd_bm_openfolder_accesskey"));
element.setAttribute("oncommand", "BookmarksUtils.loadBookmarkBrowser(event, this.parentNode.parentNode, this.database); event.preventBubble();");
aTarget.appendChild(element);
},
/////////////////////////////////////////////////////////////////////////////
// hides the 'Open in Tabs' on popuphidden so that we won't duplicate it -->
hideOpenInTabsMenuItem: function (aTarget)
{
if (!aTarget.hasChildNodes())
return;
if (aTarget.lastChild.id == "openintabs-menuitem") {
aTarget.removeChild(aTarget.lastChild);
aTarget.removeChild(aTarget.lastChild);
}
},
/////////////////////////////////////////////////////////////////////////////
// returns false if...
// - the parent is the bookmark menu or the chevron
// - the menupopup contains ony one bookmark
validOpenInTabsMenuItem: function (aTarget)
{
var rParent = RDF.GetResource(aTarget.parentNode.id)
var type = BookmarksUtils.resolveType(rParent);
if (type != "Folder" && type != "FolderGroup" &&
type != "PersonalToolbarFolder")
return false;
var count = 0;
if (!aTarget.hasChildNodes())
return false;
var curr = aTarget.firstChild;
do {
type = BookmarksUtils.resolveType(curr.id);
if (type == "Bookmark" && ++count == 2)
return true;
curr = curr.nextSibling;
} while (curr);
return false;
},
//////////////////////////////////////////////////////////////////////////
// Fill a context menu popup with menuitems appropriate for the current
// selection.
createContextMenu: function (aEvent)
{
var target = document.popupNode;
target.focus() // buttons in the pt have -moz-user-focus: ignore -->
this._selection = this.getBTSelection(target);
this._orientation = this.getBTOrientation(aEvent, target);
this._target = this.getBTTarget(target, this._orientation);
BookmarksCommand.createContextMenu(aEvent, this._selection);
this.onCommandUpdate();
aEvent.target.addEventListener("mousemove", BookmarksMenuController.onMouseMove, false)
},
/////////////////////////////////////////////////////////////////////////
// Clean up after closing the context menu popup
destroyContextMenu: function (aEvent)
{
if (content)
content.focus()
BookmarksMenuDNDObserver.onDragRemoveFeedBack(document.popupNode); // needed on cancel
aEvent.target.removeEventListener("mousemove", BookmarksMenuController.onMouseMove, false)
},
/////////////////////////////////////////////////////////////////////////////
// returns the formatted selection from aNode
getBTSelection: function (aNode)
{
var item;
switch (aNode.id) {
case "bookmarks-ptf":
item = "NC:PersonalToolbarFolder";
break;
case "bookmarks-menu":
item = "NC:BookmarksRoot";
break;
default:
item = aNode.id;
}
if (!this.isBTBookmark(item))
return {length:0};
var parent = this.getBTContainer(aNode);
var isExpanded = aNode.hasAttribute("open") && aNode.open;
var selection = {};
selection.item = [RDF.GetResource(item)];
selection.parent = [RDF.GetResource(parent)];
selection.isExpanded = [isExpanded];
selection.length = selection.item.length;
BookmarksUtils.checkSelection(selection);
return selection;
},
/////////////////////////////////////////////////////////////////////////
// returns the insertion target from aNode
getBTTarget: function (aNode, aOrientation)
{
dump("aNode.id:"+aNode.id+", localName:"+aNode.localName+"\n");
var item, parent, index;
switch (aNode.id) {
case "bookmarks-ptf":
parent = "NC:PersonalToolbarFolder";
item = this.getLastVisibleBookmark();
break;
case "bookmarks-menu":
parent = "NC:BookmarksRoot";
break;
default:
if (aNode.id == "bookmarks-chevron") {
parent = "NC:PersonalToolbarFolder";
break;
}
if (aOrientation == BookmarksUtils.DROP_ON)
parent = aNode.id
else {
parent = this.getBTContainer(aNode);
item = aNode;
}
}
parent = RDF.GetResource(parent);
if (aOrientation == BookmarksUtils.DROP_ON)
return BookmarksUtils.getTargetFromFolder(parent);
item = RDF.GetResource(item.id);
RDFC.Init(BMDS, parent);
index = RDFC.IndexOf(item);
if (aOrientation == BookmarksUtils.DROP_AFTER)
++index;
return { parent: parent, index: index };
},
/////////////////////////////////////////////////////////////////////////
// returns the parent resource of a node in the personal toolbar.
// this is determined by inspecting the source element and walking up the
// DOM tree to find the appropriate containing node.
getBTContainer: function (aNode)
{
var parent;
var item = aNode.id;
if (!this.isBTBookmark(item))
return "NC:BookmarksRoot"
parent = aNode.parentNode.parentNode;
parent = parent.id;
switch (parent) {
case "bookmarks-chevron":
case "bookmarks-stack":
case "bookmarks-toolbar":
return "NC:PersonalToolbarFolder";
case "bookmarks-menu":
return "NC:BookmarksRoot";
default:
return parent;
}
},
///////////////////////////////////////////////////////////////////////////
// returns true if the node is a bookmark, a folder or a bookmark separator
isBTBookmark: function (aURI)
{
if (!aURI)
return false;
var type = BookmarksUtils.resolveType(aURI);
return (type == "BookmarkSeparator" ||
type == "Bookmark" ||
type == "Folder" ||
type == "FolderGroup" ||
type == "PersonalToolbarFolder")
},
/////////////////////////////////////////////////////////////////////////
// returns true if the node is a container. -->
isBTContainer: function (aTarget)
{
return aTarget.localName == "menu" || (aTarget.localName == "toolbarbutton" &&
(aTarget.getAttribute("container") == "true" || aTarget.getAttribute("group") == "true"));
},
/////////////////////////////////////////////////////////////////////////
// returns BookmarksUtils.DROP_BEFORE, DROP_ON or DROP_AFTER accordingly
// to the event coordinates. Skin authors could break us, we'll cross that
// bridge when they turn us 90degrees. -->
getBTOrientation: function (aEvent, aTarget)
{
var target
if (!aTarget)
target = aEvent.target;
else
target = aTarget;
if (target.localName == "menu" &&
target.parentNode.localName != "menupopup" ||
target.id == "bookmarks-chevron")
return BookmarksUtils.DROP_ON;
if (target.id == "bookmarks-ptf") {
return target.childNodes.length>4?
BookmarksUtils.DROP_AFTER:BookmarksUtils.DROP_ON;
}
var overButtonBoxObject = target.boxObject.QueryInterface(Components.interfaces.nsIBoxObject);
var overParentBoxObject = target.parentNode.boxObject.QueryInterface(Components.interfaces.nsIBoxObject);
var size, border;
var coordValue, clientCoordValue;
switch (target.localName) {
case "toolbarseparator":
case "toolbarbutton":
size = overButtonBoxObject.width;
coordValue = overButtonBoxObject.x;
clientCoordValue = aEvent.clientX;
break;
case "menuseparator":
case "menu":
case "menuitem":
size = overButtonBoxObject.height;
coordValue = overButtonBoxObject.y-overParentBoxObject.y;
clientCoordValue = aEvent.clientY;
break;
default: return BookmarksUtils.DROP_ON;
}
if (this.isBTContainer(target))
if (target.localName == "toolbarbutton") {
// the DROP_BEFORE area excludes the label
var iconNode = document.getAnonymousElementByAttribute(target, "class", "toolbarbutton-icon");
border = parseInt(document.defaultView.getComputedStyle(target,"").getPropertyValue("padding-left")) +
parseInt(document.defaultView.getComputedStyle(iconNode ,"").getPropertyValue("width"));
border = Math.min(size/5,Math.max(border,4));
} else
border = size/5;
else
border = size/2;
// in the first region?
if (clientCoordValue-coordValue < border)
return BookmarksUtils.DROP_BEFORE;
// in the last region?
if (clientCoordValue-coordValue >= size-border)
return BookmarksUtils.DROP_AFTER;
// must be in the middle somewhere
return BookmarksUtils.DROP_ON;
},
/////////////////////////////////////////////////////////////////////////
// expand the folder targeted by the context menu.
expandBTFolder: function ()
{
var target = document.popupNode.lastChild;
if (document.popupNode.open)
target.hidePopup();
else
target.showPopup(document.popupNode);
},
onCommandUpdate: function ()
{
var selection = this._selection;
var target = this._target;
BookmarksController.onCommandUpdate(selection, target);
if (document.popupNode.id == "NC:PersonalToolbarFolder") {
// disabling 'copy' on the empty area of the personal toolbar
var commandNode = document.getElementById("cmd_bm_copy");
commandNode.setAttribute("disabled", "true");
}
}
}
var BookmarksMenuController = {
supportsCommand: BookmarksController.supportsCommand,
isCommandEnabled: function (aCommand)
{
// warning: this is not the function called in BookmarksController.onCommandUpdate
var selection = BookmarksMenu._selection;
var target = BookmarksMenu._target;
if (selection)
return BookmarksController.isCommandEnabled(aCommand, selection, target);
return false;
},
doCommand: function (aCommand)
{
BookmarksMenuDNDObserver.onDragRemoveFeedBack(document.popupNode);
var selection = BookmarksMenu._selection;
var target = BookmarksMenu._target;
switch (aCommand) {
case "cmd_bm_expandfolder":
BookmarksMenu.expandBTFolder();
break;
default:
BookmarksController.doCommand(aCommand, selection, target);
}
},
onMouseMove: function (aEvent)
{
var command = aEvent.target.getAttribute("command");
var isDisabled = aEvent.target.getAttribute("disabled")
if (isDisabled != "true" && (command == "cmd_bm_newfolder" || command == "cmd_bm_paste")) {
BookmarksMenuDNDObserver.onDragSetFeedBack(document.popupNode, BookmarksMenu._orientation);
} else {
BookmarksMenuDNDObserver.onDragRemoveFeedBack(document.popupNode);
}
}
}
var BookmarksMenuDNDObserver = {
////////////////////
// Public methods //
////////////////////
onDragStart: function (aEvent, aXferData, aDragAction)
{
var target = aEvent.target;
// Prevent dragging from an invalid region
if (!this.canDrop(aEvent))
return;
// Prevent dragging out of menupopups on non Win32 platforms.
// a) on Mac drag from menus is generally regarded as being satanic
// b) on Linux, this causes an X-server crash, (bug 151336)
// c) on Windows, there is no hang or crash associated with this, so we'll leave
// the functionality there.
if (navigator.platform != "Win32" && target.localName != "toolbarbutton")
return;
// bail if dragging from the empty area of the bookmarks toolbar
if (target.id == "bookmarks-ptf")
return
// a drag start is fired when leaving an open toolbarbutton(type=menu)
// (see bug 143031)
if (this.isContainer(target) &&
target.getAttribute("group") != "true") {
if (this.isPlatformNotSupported)
return;
if (!aEvent.shiftKey && !aEvent.altKey && !aEvent.ctrlKey)
return;
// menus open on mouse down
target.firstChild.hidePopup();
}
var selection = BookmarksMenu.getBTSelection(target);
aXferData.data = BookmarksUtils.getXferDataFromSelection(selection);
},
onDragOver: function(aEvent, aFlavour, aDragSession)
{
var orientation = BookmarksMenu.getBTOrientation(aEvent)
if (aDragSession.canDrop)
this.onDragSetFeedBack(aEvent.target, orientation);
if (orientation != this.mCurrentDropPosition) {
// emulating onDragExit and onDragEnter events since the drop region
// has changed on the target.
this.onDragExit(aEvent, aDragSession);
this.onDragEnter(aEvent, aDragSession);
}
if (this.isPlatformNotSupported)
return;
if (this.isTimerSupported)
return;
this.onDragOverCheckTimers();
},
onDragEnter: function (aEvent, aDragSession)
{
var target = aEvent.target;
var orientation = BookmarksMenu.getBTOrientation(aEvent);
if (target.localName == "menupopup" || target.id == "bookmarks-ptf")
target = target.parentNode;
if (aDragSession.canDrop) {
this.onDragSetFeedBack(target, orientation);
this.onDragEnterSetTimer(target, aDragSession);
}
this.mCurrentDragOverTarget = target;
this.mCurrentDropPosition = orientation;
},
onDragExit: function (aEvent, aDragSession)
{
var target = aEvent.target;
if (target.localName == "menupopup" || target.id == "bookmarks-ptf")
target = target.parentNode;
this.onDragRemoveFeedBack(target);
this.onDragExitSetTimer(target, aDragSession);
this.mCurrentDragOverTarget = null;
this.mCurrentDropPosition = null;
},
onDrop: function (aEvent, aXferData, aDragSession)
{
var target = aEvent.target;
this.onDragRemoveFeedBack(target);
var selection = BookmarksUtils.getSelectionFromXferData(aDragSession);
// if the personal toolbar does not exist, recreate it
if (target == "bookmarks-toolbar") {
//BookmarksUtils.recreatePersonalToolbarFolder(transactionSet);
//target = { parent: "NC:PersonalToolbarFolder", index: 1 };
} else {
var orientation = BookmarksMenu.getBTOrientation(aEvent);
var selTarget = BookmarksMenu.getBTTarget(target, orientation);
}
const kDSIID = Components.interfaces.nsIDragService;
const kCopyAction = kDSIID.DRAGDROP_ACTION_COPY + kDSIID.DRAGDROP_ACTION_LINK;
// hide the 'open in tab' menuseparator because bookmarks
// can be inserted after it if they are dropped after the last bookmark
// a more comprehensive fix would be in the menupopup template builder
var menuTarget = (target.localName == "toolbarbutton" ||
target.localName == "menu") &&
orientation == BookmarksUtils.DROP_ON?
target.lastChild:target.parentNode;
if (menuTarget.hasChildNodes() &&
menuTarget.lastChild.id == "openintabs-menuitem") {
menuTarget.removeChild(menuTarget.lastChild.previousSibling);
}
if (aDragSession.dragAction & kCopyAction)
BookmarksUtils.insertSelection("drag", selection, selTarget, true);
else
BookmarksUtils.moveSelection("drag", selection, selTarget);
// show again the menuseparator
if (menuTarget.hasChildNodes() &&
menuTarget.lastChild.id == "openintabs-menuitem") {
var element = document.createElementNS(XUL_NS, "menuseparator");
menuTarget.insertBefore(element, menuTarget.lastChild);
}
},
canDrop: function (aEvent, aDragSession)
{
var target = aEvent.target;
return BookmarksMenu.isBTBookmark(target.id) &&
target.id != "NC:SystemBookmarksStaticRoot" &&
target.id.substring(0,5) != "find:" ||
target.id == "bookmarks-menu" ||
target.id == "bookmarks-chevron" ||
target.id == "bookmarks-ptf";
},
canHandleMultipleItems: true,
getSupportedFlavours: function ()
{
var flavourSet = new FlavourSet();
flavourSet.appendFlavour("moz/rdfitem");
flavourSet.appendFlavour("text/x-moz-url");
flavourSet.appendFlavour("application/x-moz-file", "nsIFile");
flavourSet.appendFlavour("text/unicode");
return flavourSet;
},
////////////////////////////////////
// Private methods and properties //
////////////////////////////////////
springLoadedMenuDelay: 350, // milliseconds
isPlatformNotSupported: navigator.platform.indexOf("Mac") != -1, // see bug 136524
isTimerSupported: navigator.platform.indexOf("Win") == -1,
mCurrentDragOverTarget: null,
mCurrentDropPosition: null,
loadTimer : null,
closeTimer : null,
loadTarget : null,
closeTarget: null,
_observers : null,
get mObservers ()
{
if (!this._observers) {
this._observers = [
document.getElementById("bookmarks-ptf"),
document.getElementById("bookmarks-menu").parentNode,
document.getElementById("bookmarks-chevron").parentNode
]
}
return this._observers;
},
getObserverForNode: function (aNode)
{
if (!aNode)
return null;
var node = aNode;
var observer;
do {
for (var i=0; i < this.mObservers.length; i++) {
observer = this.mObservers[i];
if (observer == node)
return observer;
}
node = node.parentNode;
} while (node != document)
return null;
},
onDragCloseMenu: function (aNode)
{
var children = aNode.childNodes;
for (var i = 0; i < children.length; i++) {
if (this.isContainer(children[i]) &&
children[i].getAttribute("open") == "true") {
this.onDragCloseMenu(children[i].lastChild);
if (children[i] != this.mCurrentDragOverTarget || this.mCurrentDropPosition != BookmarksUtils.DROP_ON)
children[i].lastChild.hidePopup();
}
}
},
onDragCloseTarget: function ()
{
var currentObserver = this.getObserverForNode(this.mCurrentDragOverTarget);
// close all the menus not hovered by the mouse
for (var i=0; i < this.mObservers.length; i++) {
if (currentObserver != this.mObservers[i])
this.onDragCloseMenu(this.mObservers[i]);
else
this.onDragCloseMenu(this.mCurrentDragOverTarget.parentNode);
}
},
onDragLoadTarget: function (aTarget)
{
if (!this.mCurrentDragOverTarget)
return;
// Load the current menu
if (this.mCurrentDropPosition == BookmarksUtils.DROP_ON &&
this.isContainer(aTarget) &&
aTarget.getAttribute("group") != "true")
aTarget.lastChild.showPopup(aTarget);
},
onDragOverCheckTimers: function ()
{
var now = new Date().getTime();
if (this.closeTimer && now-this.springLoadedMenuDelay>this.closeTimer) {
this.onDragCloseTarget();
this.closeTimer = null;
}
if (this.loadTimer && (now-this.springLoadedMenuDelay>this.loadTimer)) {
this.onDragLoadTarget(this.loadTarget);
this.loadTimer = null;
}
},
onDragEnterSetTimer: function (aTarget, aDragSession)
{
if (this.isPlatformNotSupported)
return;
if (this.isTimerSupported) {
var targetToBeLoaded = aTarget;
clearTimeout(this.loadTimer);
if (aTarget == aDragSession.sourceNode)
return;
//XXX Hack: see bug 139645
var thisHack = this;
this.loadTimer=setTimeout(function () {thisHack.onDragLoadTarget(targetToBeLoaded)}, this.springLoadedMenuDelay);
} else {
var now = new Date().getTime();
this.loadTimer = now;
this.loadTarget = aTarget;
}
},
onDragExitSetTimer: function (aTarget, aDragSession)
{
if (this.isPlatformNotSupported)
return;
var thisHack = this;
if (this.isTimerSupported) {
clearTimeout(this.closeTimer)
this.closeTimer=setTimeout(function () {thisHack.onDragCloseTarget()}, this.springLoadedMenuDelay);
} else {
var now = new Date().getTime();
this.closeTimer = now;
this.closeTarget = aTarget;
this.loadTimer = null;
// If user isn't rearranging within the menu, close it
// To do so, we exploit a Mac bug: timeout set during
// drag and drop on Windows and Mac are fired only after that the drop is released.
// timeouts will pile up, we may have a better approach but for the moment, this one
// correctly close the menus after a drop/cancel outside the personal toolbar.
// The if statement in the function has been introduced to deal with rare but reproducible
// missing Exit events.
if (aDragSession.sourceNode.localName != "menuitem" && aDragSession.sourceNode.localName != "menu")
setTimeout(function () { if (thisHack.mCurrentDragOverTarget) {thisHack.onDragRemoveFeedBack(thisHack.mCurrentDragOverTarget); thisHack.mCurrentDragOverTarget=null} thisHack.loadTimer=null; thisHack.onDragCloseTarget() }, 0);
}
},
onDragSetFeedBack: function (aTarget, aOrientation)
{
switch (aTarget.localName) {
case "toolbarseparator":
case "toolbarbutton":
switch (aOrientation) {
case BookmarksUtils.DROP_BEFORE:
aTarget.setAttribute("dragover-left", "true");
break;
case BookmarksUtils.DROP_AFTER:
aTarget.setAttribute("dragover-right", "true");
break;
case BookmarksUtils.DROP_ON:
aTarget.setAttribute("dragover-top" , "true");
aTarget.setAttribute("dragover-bottom", "true");
aTarget.setAttribute("dragover-left" , "true");
aTarget.setAttribute("dragover-right" , "true");
break;
}
break;
case "menuseparator":
case "menu":
case "menuitem":
switch (aOrientation) {
case BookmarksUtils.DROP_BEFORE:
aTarget.setAttribute("dragover-top", "true");
break;
case BookmarksUtils.DROP_AFTER:
aTarget.setAttribute("dragover-bottom", "true");
break;
case BookmarksUtils.DROP_ON:
break;
}
break;
case "hbox" :
// hit between the last visible bookmark and the chevron
var newTarget = BookmarksToolbar.getLastVisibleBookmark();
if (newTarget)
newTarget.setAttribute("dragover-right", "true");
break;
case "stack" :
case "menupopup": break;
default: dump("No feedback for: "+aTarget.localName+"\n");
}
},
onDragRemoveFeedBack: function (aTarget)
{
var newTarget;
var bt;
if (aTarget.id == "bookmarks-ptf") {
// hit when dropping in the bt or between the last visible bookmark
// and the chevron
newTarget = BookmarksToolbar.getLastVisibleBookmark();
if (newTarget)
newTarget.removeAttribute("dragover-right");
} else if (aTarget.id == "bookmarks-stack") {
newTarget = BookmarksToolbar.getLastVisibleBookmark();
newTarget.removeAttribute("dragover-right");
} else {
aTarget.removeAttribute("dragover-left");
aTarget.removeAttribute("dragover-right");
aTarget.removeAttribute("dragover-top");
aTarget.removeAttribute("dragover-bottom");
}
},
onDropSetFeedBack: function (aTarget)
{
//XXX Not yet...
},
isContainer: function (aTarget)
{
return aTarget.localName == "menu" ||
aTarget.localName == "toolbarbutton" &&
aTarget.getAttribute("type") == "menu";
}
}
var BookmarksToolbar =
{
/////////////////////////////////////////////////////////////////////////////
// returns the node of the last visible bookmark on the toolbar -->
getLastVisibleBookmark: function ()
{
var buttons = document.getElementById("bookmarks-ptf");
var button = buttons.childNodes[3].nextSibling;
if (!button)
return null; // empty bookmarks toolbar
do {
if (button.collapsed)
return button.previousSibling;
button = button.nextSibling;
} while (button)
return buttons.lastChild;
},
updateOverflowMenu: function (aMenuPopup)
{
var hbox = document.getElementById("bookmarks-ptf");
for (var i = 4; i < hbox.childNodes.length; i++) {
var button = hbox.childNodes[i];
var menu = aMenuPopup.childNodes[i-4];
if (menu.collapsed == button.collapsed)
menu.collapsed = !menu.collapsed;
}
},
resizeFunc: function(event)
{
var buttons = document.getElementById("bookmarks-ptf");
if (!buttons)
return;
var chevron = document.getElementById("bookmarks-chevron");
var width = window.innerWidth;
chevron.collapsed = true;
var overflowed = false;
for (var i=4; i<buttons.childNodes.length; i++) {
var button = buttons.childNodes[i];
button.collapsed = overflowed;
if (button.boxObject.x + button.boxObject.width > width) {
overflowed = true;
// This button doesn't fit. Show it in the menu. Hide it in the toolbar.
if (!button.collapsed)
button.collapsed = true;
if (chevron.collapsed) {
chevron.collapsed = false;
var overflowPadder = document.getElementById("overflow-padder");
overflowPadder.width = width - chevron.boxObject.width - buttons.boxObject.x;
}
}
}
},
// Fill in tooltips for personal toolbar
fillInBTTooltip: function (tipElement)
{
var title = tipElement.label;
var url = tipElement.statusText;
if (!title && !url) {
// bail out early if there is nothing to show
return false;
}
var tooltipTitle = document.getElementById("btTitleText");
var tooltipUrl = document.getElementById("btUrlText");
if (title && title != url) {
tooltipTitle.removeAttribute("hidden");
tooltipTitle.setAttribute("value", title);
} else {
tooltipTitle.setAttribute("hidden", "true");
}
if (url) {
tooltipUrl.removeAttribute("hidden");
tooltipUrl.setAttribute("value", url);
} else {
tooltipUrl.setAttribute("hidden", "true");
}
return true; // show tooltip
}
}
// Implement nsIRDFObserver so we can update our overflow state when items get
// added/removed from the toolbar
var BookmarksToolbarRDFObserver =
{
onAssert: function (aDataSource, aSource, aProperty, aTarget)
{
this.setOverflowTimeout(aSource, aProperty);
},
onUnassert: function (aDataSource, aSource, aProperty, aTarget)
{
this.setOverflowTimeout(aSource, aProperty);
},
onChange: function (aDataSource, aSource, aProperty, aOldTarget, aNewTarget) {},
onMove: function (aDataSource, aOldSource, aNewSource, aProperty, aTarget) {},
beginUpdateBatch: function (aDataSource) {},
endUpdateBatch: function (aDataSource) {},
_overflowTimerInEffect: false,
setOverflowTimeout: function (aSource, aProperty)
{
if (this._overflowTimerInEffect)
return;
if (aSource.Value != "NC:PersonalToolbarFolder" || aProperty.Value == NC_NS+"LastModifiedDate")
return;
this._overflowTimerInEffect = true;
setTimeout("function(){BookmarksToolbar.resizeFunc(null);BookmarksToolbarRDFObserver._overflowTimerInEffect=false;}", 0);
}
}
/*
constructor
{
var hbox = (document.getAnonymousNodes(this))[0].firstChild;
var theToolbar = this;
this.resizeFunc = resizeFunc;
window.addEventListener("resize", resizeFunc, false);
hbox.database.AddObserver(this);
}
destructor
{
var hbox = (document.getAnonymousNodes(this))[0].firstChild;
this.toolbar.controllers.removeController(this.commandController);
hbox.database.RemoveObserver(this);
}
<property name="toolbar">
<getter><![CDATA[
return document.getAnonymousElementByAttribute(this, "anonid", "bookmarks-ptf");
]]></getter>
</property>
<field name="resizeFunc">null</field>
*/

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

@ -20,8 +20,8 @@
browser.jar:
content/browser/bookmarks/bookmarks.css (content/bookmarks.css)
* content/browser/bookmarks/bookmarks.js (content/bookmarks.js)
* content/browser/bookmarks/bookmarksMenu.js (content/bookmarksMenu.js)
* content/browser/bookmarks/bookmarksTree.xml (content/bookmarksTree.xml)
* content/browser/bookmarks/bookmarksToolbar.xml (content/bookmarksToolbar.xml)
content/browser/bookmarks/addBookmark.xul (content/addBookmark.xul)
content/browser/bookmarks/addBookmark.js (content/addBookmark.js)
* content/browser/bookmarks/addBookmark2.xul (content/addBookmark2.xul)