зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1539651 - Convert places-popup-base and places-popup-arrow bindings to Custom Elements r=mak
Differential Revision: https://phabricator.services.mozilla.com/D33821 --HG-- rename : browser/components/places/content/menu.xml => browser/components/places/content/places-menupopup.js extra : moz-landing-system : lando
This commit is contained in:
Родитель
791788aef7
Коммит
002fc892ce
|
@ -235,6 +235,7 @@
|
|||
<menupopup id="goPopup"
|
||||
#ifndef XP_MACOSX
|
||||
placespopup="true"
|
||||
is="places-popup"
|
||||
#endif
|
||||
oncommand="this.parentNode._placesView._onCommand(event);"
|
||||
onclick="checkForMiddleClick(this, event);"
|
||||
|
@ -264,6 +265,7 @@
|
|||
<menupopup id="historyUndoPopup"
|
||||
#ifndef XP_MACOSX
|
||||
placespopup="true"
|
||||
is="places-popup"
|
||||
#endif
|
||||
onpopupshowing="document.getElementById('history-menu')._placesView.populateUndoSubmenu();"/>
|
||||
</menu>
|
||||
|
@ -272,6 +274,7 @@
|
|||
<menupopup id="historyUndoWindowPopup"
|
||||
#ifndef XP_MACOSX
|
||||
placespopup="true"
|
||||
is="places-popup"
|
||||
#endif
|
||||
onpopupshowing="document.getElementById('history-menu')._placesView.populateUndoWindowSubmenu();"/>
|
||||
</menu>
|
||||
|
@ -287,6 +290,7 @@
|
|||
<menupopup id="bookmarksMenuPopup"
|
||||
#ifndef XP_MACOSX
|
||||
placespopup="true"
|
||||
is="places-popup"
|
||||
#endif
|
||||
context="placesContext"
|
||||
openInTabs="children"
|
||||
|
@ -315,6 +319,7 @@
|
|||
<menupopup id="bookmarksToolbarFolderPopup"
|
||||
#ifndef XP_MACOSX
|
||||
placespopup="true"
|
||||
is="places-popup"
|
||||
#endif
|
||||
context="placesContext"
|
||||
onpopupshowing="if (!this.parentNode._placesView)
|
||||
|
@ -326,6 +331,7 @@
|
|||
<menupopup id="otherBookmarksFolderPopup"
|
||||
#ifndef XP_MACOSX
|
||||
placespopup="true"
|
||||
is="places-popup"
|
||||
#endif
|
||||
context="placesContext"
|
||||
onpopupshowing="if (!this.parentNode._placesView)
|
||||
|
@ -338,6 +344,7 @@
|
|||
<menupopup id="mobileBookmarksFolderPopup"
|
||||
#ifndef XP_MACOSX
|
||||
placespopup="true"
|
||||
is="places-popup"
|
||||
#endif
|
||||
context="placesContext"
|
||||
onpopupshowing="if (!this.parentNode._placesView)
|
||||
|
|
|
@ -979,7 +979,7 @@ toolbarpaletteitem[place="palette"] > #downloads-button[indicator] > .toolbarbut
|
|||
/* Give this menupopup an arrow panel styling */
|
||||
#BMB_bookmarksPopup {
|
||||
-moz-appearance: none;
|
||||
-moz-binding: url("chrome://browser/content/places/menu.xml#places-popup-arrow");
|
||||
-moz-binding: none;
|
||||
background: transparent;
|
||||
border: none;
|
||||
/* The popup inherits -moz-image-region from the button, must reset it */
|
||||
|
|
|
@ -100,6 +100,7 @@
|
|||
Services.scriptloader.loadSubScript("chrome://browser/content/tabbrowser.js", this);
|
||||
Services.scriptloader.loadSubScript("chrome://browser/content/tabbrowser-tab.js", this);
|
||||
Services.scriptloader.loadSubScript("chrome://browser/content/tabbrowser-tabs.js", this);
|
||||
Services.scriptloader.loadSubScript("chrome://browser/content/places/places-menupopup.js", this);
|
||||
Services.scriptloader.loadSubScript("chrome://browser/content/search/autocomplete-popup.js", this);
|
||||
Services.scriptloader.loadSubScript("chrome://browser/content/search/searchbar.js", this);
|
||||
|
||||
|
@ -1203,6 +1204,7 @@
|
|||
onpopupshowing="document.getElementById('PlacesToolbar')
|
||||
._placesView._onChevronPopupShowing(event);">
|
||||
<menupopup id="PlacesChevronPopup"
|
||||
is="places-popup"
|
||||
placespopup="true"
|
||||
tooltip="bhTooltip" popupsinherittooltip="true"
|
||||
context="placesContext"/>
|
||||
|
@ -1251,6 +1253,7 @@
|
|||
ondrop="PlacesMenuDNDHandler.onDrop(event);"
|
||||
oncommand="BookmarkingUI.onCommand(event);">
|
||||
<menupopup id="BMB_bookmarksPopup"
|
||||
is="places-popup-arrow"
|
||||
class="cui-widget-panel cui-widget-panelview cui-widget-panelWithFooter PanelUI-subView"
|
||||
placespopup="true"
|
||||
context="placesContext"
|
||||
|
@ -1279,6 +1282,7 @@
|
|||
label="&personalbarCmd.label;"
|
||||
container="true">
|
||||
<menupopup id="BMB_bookmarksToolbarPopup"
|
||||
is="places-popup"
|
||||
placespopup="true"
|
||||
context="placesContext"
|
||||
onpopupshowing="if (!this.parentNode._placesView)
|
||||
|
@ -1298,6 +1302,7 @@
|
|||
label="&bookmarksMenuButton.other.label;"
|
||||
container="true">
|
||||
<menupopup id="BMB_unsortedBookmarksPopup"
|
||||
is="places-popup"
|
||||
placespopup="true"
|
||||
context="placesContext"
|
||||
onpopupshowing="if (!this.parentNode._placesView)
|
||||
|
@ -1310,6 +1315,7 @@
|
|||
hidden="true"
|
||||
container="true">
|
||||
<menupopup id="BMB_mobileBookmarksPopup"
|
||||
is="places-popup"
|
||||
placespopup="true"
|
||||
context="placesContext"
|
||||
onpopupshowing="if (!this.parentNode._placesView)
|
||||
|
|
|
@ -395,7 +395,9 @@ PlacesViewBase.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
let popup = document.createXULElement("menupopup");
|
||||
let popup = document.createXULElement("menupopup", {
|
||||
is: "places-popup",
|
||||
});
|
||||
popup._placesNode = PlacesUtils.asContainer(aPlacesNode);
|
||||
|
||||
if (!this._nativeView) {
|
||||
|
@ -1062,7 +1064,9 @@ PlacesToolbar.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
let popup = document.createXULElement("menupopup");
|
||||
let popup = document.createXULElement("menupopup", {
|
||||
is: "places-popup",
|
||||
});
|
||||
popup.setAttribute("placespopup", "true");
|
||||
button.appendChild(popup);
|
||||
popup._placesNode = PlacesUtils.asContainer(aChild);
|
||||
|
|
|
@ -1,622 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!-- import-globals-from controller.js -->
|
||||
|
||||
<bindings id="placesMenuBindings"
|
||||
xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<binding id="places-popup-base"
|
||||
extends="chrome://global/content/bindings/popup.xml#popup">
|
||||
<content>
|
||||
<xul:hbox flex="1">
|
||||
<xul:vbox class="menupopup-drop-indicator-bar" hidden="true">
|
||||
<xul:image class="menupopup-drop-indicator" mousethrough="always"/>
|
||||
</xul:vbox>
|
||||
<xul:arrowscrollbox class="popup-internal-box" flex="1" orient="vertical"
|
||||
smoothscroll="false">
|
||||
<children/>
|
||||
</xul:arrowscrollbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
|
||||
<field name="AppConstants" readonly="true">
|
||||
(ChromeUtils.import("resource://gre/modules/AppConstants.jsm", {})).AppConstants;
|
||||
</field>
|
||||
|
||||
<field name="_indicatorBar">
|
||||
document.getAnonymousElementByAttribute(this, "class",
|
||||
"menupopup-drop-indicator-bar");
|
||||
</field>
|
||||
|
||||
<field name="_scrollBox">
|
||||
document.getAnonymousElementByAttribute(this, "class",
|
||||
"popup-internal-box");
|
||||
</field>
|
||||
|
||||
<!-- This is the view that manage the popup -->
|
||||
<field name="_rootView">PlacesUIUtils.getViewForNode(this);</field>
|
||||
|
||||
<!-- Check if we should hide the drop indicator for the target -->
|
||||
<method name="_hideDropIndicator">
|
||||
<parameter name="aEvent"/>
|
||||
<body><![CDATA[
|
||||
let target = aEvent.target;
|
||||
|
||||
// Don't draw the drop indicator outside of markers or if current
|
||||
// node is not a Places node.
|
||||
let betweenMarkers =
|
||||
(this._startMarker.compareDocumentPosition(target) & Node.DOCUMENT_POSITION_FOLLOWING) &&
|
||||
(this._endMarker.compareDocumentPosition(target) & Node.DOCUMENT_POSITION_PRECEDING);
|
||||
|
||||
// Hide the dropmarker if current node is not a Places node.
|
||||
return !(target && target._placesNode && betweenMarkers);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- This function returns information about where to drop when
|
||||
dragging over this popup insertion point -->
|
||||
<method name="_getDropPoint">
|
||||
<parameter name="aEvent"/>
|
||||
<body><![CDATA[
|
||||
// Can't drop if the menu isn't a folder
|
||||
let resultNode = this._placesNode;
|
||||
|
||||
if (!PlacesUtils.nodeIsFolder(resultNode) ||
|
||||
this._rootView.controller.disallowInsertion(resultNode)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var dropPoint = { ip: null, folderElt: null };
|
||||
|
||||
// The element we are dragging over
|
||||
let elt = aEvent.target;
|
||||
if (elt.localName == "menupopup")
|
||||
elt = elt.parentNode;
|
||||
|
||||
let eventY = aEvent.clientY;
|
||||
let {y: eltY, height: eltHeight} = elt.getBoundingClientRect();
|
||||
|
||||
if (!elt._placesNode) {
|
||||
// If we are dragging over a non places node drop at the end.
|
||||
dropPoint.ip = new PlacesInsertionPoint({
|
||||
parentId: PlacesUtils.getConcreteItemId(resultNode),
|
||||
parentGuid: PlacesUtils.getConcreteItemGuid(resultNode),
|
||||
});
|
||||
// We can set folderElt if we are dropping over a static menu that
|
||||
// has an internal placespopup.
|
||||
let isMenu = elt.localName == "menu" ||
|
||||
(elt.localName == "toolbarbutton" &&
|
||||
elt.getAttribute("type") == "menu");
|
||||
if (isMenu && elt.lastElementChild &&
|
||||
elt.lastElementChild.hasAttribute("placespopup"))
|
||||
dropPoint.folderElt = elt;
|
||||
return dropPoint;
|
||||
}
|
||||
|
||||
let tagName = PlacesUtils.nodeIsTagQuery(elt._placesNode) ?
|
||||
elt._placesNode.title : null;
|
||||
if ((PlacesUtils.nodeIsFolder(elt._placesNode) &&
|
||||
!PlacesUIUtils.isFolderReadOnly(elt._placesNode)) ||
|
||||
PlacesUtils.nodeIsTagQuery(elt._placesNode)) {
|
||||
// This is a folder or a tag container.
|
||||
if (eventY - eltY < eltHeight * 0.20) {
|
||||
// If mouse is in the top part of the element, drop above folder.
|
||||
dropPoint.ip = new PlacesInsertionPoint({
|
||||
parentId: PlacesUtils.getConcreteItemId(resultNode),
|
||||
parentGuid: PlacesUtils.getConcreteItemGuid(resultNode),
|
||||
orientation: Ci.nsITreeView.DROP_BEFORE,
|
||||
tagName,
|
||||
dropNearNode: elt._placesNode,
|
||||
});
|
||||
return dropPoint;
|
||||
} else if (eventY - eltY < eltHeight * 0.80) {
|
||||
// If mouse is in the middle of the element, drop inside folder.
|
||||
dropPoint.ip = new PlacesInsertionPoint({
|
||||
parentId: PlacesUtils.getConcreteItemId(elt._placesNode),
|
||||
parentGuid: PlacesUtils.getConcreteItemGuid(elt._placesNode),
|
||||
tagName,
|
||||
});
|
||||
dropPoint.folderElt = elt;
|
||||
return dropPoint;
|
||||
}
|
||||
} else if (eventY - eltY <= eltHeight / 2) {
|
||||
// This is a non-folder node or a readonly folder.
|
||||
// If the mouse is above the middle, drop above this item.
|
||||
dropPoint.ip = new PlacesInsertionPoint({
|
||||
parentId: PlacesUtils.getConcreteItemId(resultNode),
|
||||
parentGuid: PlacesUtils.getConcreteItemGuid(resultNode),
|
||||
orientation: Ci.nsITreeView.DROP_BEFORE,
|
||||
tagName,
|
||||
dropNearNode: elt._placesNode,
|
||||
});
|
||||
return dropPoint;
|
||||
}
|
||||
|
||||
// Drop below the item.
|
||||
dropPoint.ip = new PlacesInsertionPoint({
|
||||
parentId: PlacesUtils.getConcreteItemId(resultNode),
|
||||
parentGuid: PlacesUtils.getConcreteItemGuid(resultNode),
|
||||
orientation: Ci.nsITreeView.DROP_AFTER,
|
||||
tagName,
|
||||
dropNearNode: elt._placesNode,
|
||||
});
|
||||
return dropPoint;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<!-- Sub-menus should be opened when the mouse drags over them, and closed
|
||||
when the mouse drags off. The overFolder object manages opening and
|
||||
closing of folders when the mouse hovers. -->
|
||||
<field name="_overFolder"><![CDATA[({
|
||||
_self: this,
|
||||
_folder: {elt: null,
|
||||
openTimer: null,
|
||||
hoverTime: 350,
|
||||
closeTimer: null},
|
||||
_closeMenuTimer: null,
|
||||
|
||||
get elt() {
|
||||
return this._folder.elt;
|
||||
},
|
||||
set elt(val) {
|
||||
return this._folder.elt = val;
|
||||
},
|
||||
|
||||
get openTimer() {
|
||||
return this._folder.openTimer;
|
||||
},
|
||||
set openTimer(val) {
|
||||
return this._folder.openTimer = val;
|
||||
},
|
||||
|
||||
get hoverTime() {
|
||||
return this._folder.hoverTime;
|
||||
},
|
||||
set hoverTime(val) {
|
||||
return this._folder.hoverTime = val;
|
||||
},
|
||||
|
||||
get closeTimer() {
|
||||
return this._folder.closeTimer;
|
||||
},
|
||||
set closeTimer(val) {
|
||||
return this._folder.closeTimer = val;
|
||||
},
|
||||
|
||||
get closeMenuTimer() {
|
||||
return this._closeMenuTimer;
|
||||
},
|
||||
set closeMenuTimer(val) {
|
||||
return this._closeMenuTimer = val;
|
||||
},
|
||||
|
||||
setTimer: function OF__setTimer(aTime) {
|
||||
var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
timer.initWithCallback(this, aTime, timer.TYPE_ONE_SHOT);
|
||||
return timer;
|
||||
},
|
||||
|
||||
notify: function OF__notify(aTimer) {
|
||||
// Function to process all timer notifications.
|
||||
|
||||
if (aTimer == this._folder.openTimer) {
|
||||
// Timer to open a submenu that's being dragged over.
|
||||
this._folder.elt.lastElementChild.setAttribute("autoopened", "true");
|
||||
this._folder.elt.lastElementChild.openPopup();
|
||||
this._folder.openTimer = null;
|
||||
} else if (aTimer == this._folder.closeTimer) {
|
||||
// Timer to close a submenu that's been dragged off of.
|
||||
// Only close the submenu if the mouse isn't being dragged over any
|
||||
// of its child menus.
|
||||
var draggingOverChild = PlacesControllerDragHelper
|
||||
.draggingOverChildNode(this._folder.elt);
|
||||
if (draggingOverChild)
|
||||
this._folder.elt = null;
|
||||
this.clear();
|
||||
|
||||
// Close any parent folders which aren't being dragged over.
|
||||
// (This is necessary because of the above code that keeps a folder
|
||||
// open while its children are being dragged over.)
|
||||
if (!draggingOverChild)
|
||||
this.closeParentMenus();
|
||||
} else if (aTimer == this.closeMenuTimer) {
|
||||
// Timer to close this menu after the drag exit.
|
||||
var popup = this._self;
|
||||
// if we are no more dragging we can leave the menu open to allow
|
||||
// for better D&D bookmark organization
|
||||
if (PlacesControllerDragHelper.getSession() &&
|
||||
!PlacesControllerDragHelper.draggingOverChildNode(popup.parentNode)) {
|
||||
popup.hidePopup();
|
||||
// Close any parent menus that aren't being dragged over;
|
||||
// otherwise they'll stay open because they couldn't close
|
||||
// while this menu was being dragged over.
|
||||
this.closeParentMenus();
|
||||
}
|
||||
this._closeMenuTimer = null;
|
||||
}
|
||||
},
|
||||
|
||||
// Helper function to close all parent menus of this menu,
|
||||
// as long as none of the parent's children are currently being
|
||||
// dragged over.
|
||||
closeParentMenus: function OF__closeParentMenus() {
|
||||
var popup = this._self;
|
||||
var parent = popup.parentNode;
|
||||
while (parent) {
|
||||
if (parent.localName == "menupopup" && parent._placesNode) {
|
||||
if (PlacesControllerDragHelper.draggingOverChildNode(parent.parentNode))
|
||||
break;
|
||||
parent.hidePopup();
|
||||
}
|
||||
parent = parent.parentNode;
|
||||
}
|
||||
},
|
||||
|
||||
// The mouse is no longer dragging over the stored menubutton.
|
||||
// Close the menubutton, clear out drag styles, and clear all
|
||||
// timers for opening/closing it.
|
||||
clear: function OF__clear() {
|
||||
if (this._folder.elt && this._folder.elt.lastElementChild) {
|
||||
if (!this._folder.elt.lastElementChild.hasAttribute("dragover"))
|
||||
this._folder.elt.lastElementChild.hidePopup();
|
||||
// remove menuactive style
|
||||
this._folder.elt.removeAttribute("_moz-menuactive");
|
||||
this._folder.elt = null;
|
||||
}
|
||||
if (this._folder.openTimer) {
|
||||
this._folder.openTimer.cancel();
|
||||
this._folder.openTimer = null;
|
||||
}
|
||||
if (this._folder.closeTimer) {
|
||||
this._folder.closeTimer.cancel();
|
||||
this._folder.closeTimer = null;
|
||||
}
|
||||
},
|
||||
})]]></field>
|
||||
|
||||
<method name="_cleanupDragDetails">
|
||||
<body><![CDATA[
|
||||
// Called on dragend and drop.
|
||||
PlacesControllerDragHelper.currentDropTarget = null;
|
||||
this._rootView._draggedElt = null;
|
||||
this.removeAttribute("dragover");
|
||||
this.removeAttribute("dragstart");
|
||||
this._indicatorBar.hidden = true;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="DOMMenuItemActive"><![CDATA[
|
||||
let elt = event.target;
|
||||
if (elt.parentNode != this)
|
||||
return;
|
||||
|
||||
if (this.AppConstants.platform === "macosx") {
|
||||
// XXX: The following check is a temporary hack until bug 420033 is
|
||||
// resolved.
|
||||
let parentElt = elt.parent;
|
||||
while (parentElt) {
|
||||
if (parentElt.id == "bookmarksMenuPopup" ||
|
||||
parentElt.id == "goPopup")
|
||||
return;
|
||||
|
||||
parentElt = parentElt.parentNode;
|
||||
}
|
||||
}
|
||||
|
||||
if (window.XULBrowserWindow) {
|
||||
let placesNode = elt._placesNode;
|
||||
|
||||
var linkURI;
|
||||
if (placesNode && PlacesUtils.nodeIsURI(placesNode))
|
||||
linkURI = placesNode.uri;
|
||||
else if (elt.hasAttribute("targetURI"))
|
||||
linkURI = elt.getAttribute("targetURI");
|
||||
|
||||
if (linkURI)
|
||||
window.XULBrowserWindow.setOverLink(linkURI, null);
|
||||
}
|
||||
]]></handler>
|
||||
|
||||
<handler event="DOMMenuItemInactive"><![CDATA[
|
||||
let elt = event.target;
|
||||
if (elt.parentNode != this)
|
||||
return;
|
||||
|
||||
if (window.XULBrowserWindow)
|
||||
window.XULBrowserWindow.setOverLink("", null);
|
||||
]]></handler>
|
||||
|
||||
<handler event="dragstart"><![CDATA[
|
||||
let elt = event.target;
|
||||
if (!elt._placesNode)
|
||||
return;
|
||||
|
||||
let draggedElt = elt._placesNode;
|
||||
|
||||
// Force a copy action if parent node is a query or we are dragging a
|
||||
// not-removable node.
|
||||
if (!this._rootView.controller.canMoveNode(draggedElt))
|
||||
event.dataTransfer.effectAllowed = "copyLink";
|
||||
|
||||
// Activate the view and cache the dragged element.
|
||||
this._rootView._draggedElt = draggedElt;
|
||||
this._rootView.controller.setDataTransfer(event);
|
||||
this.setAttribute("dragstart", "true");
|
||||
event.stopPropagation();
|
||||
]]></handler>
|
||||
|
||||
<handler event="drop"><![CDATA[
|
||||
PlacesControllerDragHelper.currentDropTarget = event.target;
|
||||
|
||||
let dropPoint = this._getDropPoint(event);
|
||||
if (dropPoint && dropPoint.ip) {
|
||||
PlacesControllerDragHelper.onDrop(dropPoint.ip, event.dataTransfer)
|
||||
.catch(Cu.reportError);
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
this._cleanupDragDetails();
|
||||
event.stopPropagation();
|
||||
]]></handler>
|
||||
|
||||
<handler event="dragover"><![CDATA[
|
||||
PlacesControllerDragHelper.currentDropTarget = event.target;
|
||||
let dt = event.dataTransfer;
|
||||
|
||||
let dropPoint = this._getDropPoint(event);
|
||||
if (!dropPoint || !dropPoint.ip ||
|
||||
!PlacesControllerDragHelper.canDrop(dropPoint.ip, dt)) {
|
||||
this._indicatorBar.hidden = true;
|
||||
event.stopPropagation();
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark this popup as being dragged over.
|
||||
this.setAttribute("dragover", "true");
|
||||
|
||||
if (dropPoint.folderElt) {
|
||||
// We are dragging over a folder.
|
||||
// _overFolder should take the care of opening it on a timer.
|
||||
if (this._overFolder.elt &&
|
||||
this._overFolder.elt != dropPoint.folderElt) {
|
||||
// We are dragging over a new folder, let's clear old values
|
||||
this._overFolder.clear();
|
||||
}
|
||||
if (!this._overFolder.elt) {
|
||||
this._overFolder.elt = dropPoint.folderElt;
|
||||
// Create the timer to open this folder.
|
||||
this._overFolder.openTimer = this._overFolder
|
||||
.setTimer(this._overFolder.hoverTime);
|
||||
}
|
||||
// Since we are dropping into a folder set the corresponding style.
|
||||
dropPoint.folderElt.setAttribute("_moz-menuactive", true);
|
||||
} else {
|
||||
// We are not dragging over a folder.
|
||||
// Clear out old _overFolder information.
|
||||
this._overFolder.clear();
|
||||
}
|
||||
|
||||
// Autoscroll the popup strip if we drag over the scroll buttons.
|
||||
let anonid = event.originalTarget.getAttribute("anonid");
|
||||
let scrollDir = 0;
|
||||
if (anonid == "scrollbutton-up") {
|
||||
scrollDir = -1;
|
||||
} else if (anonid == "scrollbutton-down") {
|
||||
scrollDir = 1;
|
||||
}
|
||||
if (scrollDir != 0) {
|
||||
this._scrollBox.scrollByIndex(scrollDir, true);
|
||||
}
|
||||
|
||||
// Check if we should hide the drop indicator for this target.
|
||||
if (dropPoint.folderElt || this._hideDropIndicator(event)) {
|
||||
this._indicatorBar.hidden = true;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return;
|
||||
}
|
||||
|
||||
// We should display the drop indicator relative to the arrowscrollbox.
|
||||
let scrollRect = this._scrollBox.getBoundingClientRect();
|
||||
let newMarginTop = 0;
|
||||
if (scrollDir == 0) {
|
||||
let elt = this.firstElementChild;
|
||||
while (elt && event.screenY > elt.screenY +
|
||||
elt.getBoundingClientRect().height / 2)
|
||||
elt = elt.nextElementSibling;
|
||||
newMarginTop = elt ? elt.screenY - this._scrollBox.screenY :
|
||||
scrollRect.height;
|
||||
} else if (scrollDir == 1) {
|
||||
newMarginTop = scrollRect.height;
|
||||
}
|
||||
|
||||
// Set the new marginTop based on arrowscrollbox.
|
||||
newMarginTop += scrollRect.y - this._scrollBox.getBoundingClientRect().y;
|
||||
this._indicatorBar.firstElementChild.style.marginTop = newMarginTop + "px";
|
||||
this._indicatorBar.hidden = false;
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
]]></handler>
|
||||
|
||||
<handler event="dragexit"><![CDATA[
|
||||
PlacesControllerDragHelper.currentDropTarget = null;
|
||||
this.removeAttribute("dragover");
|
||||
|
||||
// If we have not moved to a valid new target clear the drop indicator
|
||||
// this happens when moving out of the popup.
|
||||
let target = event.relatedTarget;
|
||||
if (!target || !this.contains(target))
|
||||
this._indicatorBar.hidden = true;
|
||||
|
||||
// Close any folder being hovered over
|
||||
if (this._overFolder.elt) {
|
||||
this._overFolder.closeTimer = this._overFolder
|
||||
.setTimer(this._overFolder.hoverTime);
|
||||
}
|
||||
|
||||
// The autoopened attribute is set when this folder was automatically
|
||||
// opened after the user dragged over it. If this attribute is set,
|
||||
// auto-close the folder on drag exit.
|
||||
// We should also try to close this popup if the drag has started
|
||||
// from here, the timer will check if we are dragging over a child.
|
||||
if (this.hasAttribute("autoopened") ||
|
||||
this.hasAttribute("dragstart")) {
|
||||
this._overFolder.closeMenuTimer = this._overFolder
|
||||
.setTimer(this._overFolder.hoverTime);
|
||||
}
|
||||
|
||||
event.stopPropagation();
|
||||
]]></handler>
|
||||
|
||||
<handler event="dragend"><![CDATA[
|
||||
this._cleanupDragDetails();
|
||||
]]></handler>
|
||||
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
<!-- Most of this is copied from the arrowpanel binding in popup.xml -->
|
||||
<binding id="places-popup-arrow"
|
||||
extends="chrome://browser/content/places/menu.xml#places-popup-base">
|
||||
<content flip="both" side="top" position="bottomcenter topright">
|
||||
<xul:vbox anonid="container" class="panel-arrowcontainer" flex="1"
|
||||
xbl:inherits="side,panelopen">
|
||||
<xul:box anonid="arrowbox" class="panel-arrowbox">
|
||||
<xul:image anonid="arrow" class="panel-arrow" xbl:inherits="side"/>
|
||||
</xul:box>
|
||||
<xul:box class="panel-arrowcontent" xbl:inherits="side,align,dir,orient,pack" flex="1">
|
||||
<xul:vbox class="menupopup-drop-indicator-bar" hidden="true">
|
||||
<xul:image class="menupopup-drop-indicator" mousethrough="always"/>
|
||||
</xul:vbox>
|
||||
<xul:arrowscrollbox class="popup-internal-box" flex="1" orient="vertical"
|
||||
smoothscroll="false">
|
||||
<children/>
|
||||
</xul:arrowscrollbox>
|
||||
</xul:box>
|
||||
</xul:vbox>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<constructor><![CDATA[
|
||||
this.style.pointerEvents = "none";
|
||||
]]></constructor>
|
||||
<method name="adjustArrowPosition">
|
||||
<body><![CDATA[
|
||||
var arrow = document.getAnonymousElementByAttribute(this, "anonid", "arrow");
|
||||
|
||||
var anchor = this.anchorNode;
|
||||
if (!anchor) {
|
||||
arrow.hidden = true;
|
||||
return;
|
||||
}
|
||||
|
||||
var container = document.getAnonymousElementByAttribute(this, "anonid", "container");
|
||||
var arrowbox = document.getAnonymousElementByAttribute(this, "anonid", "arrowbox");
|
||||
|
||||
var position = this.alignmentPosition;
|
||||
var offset = this.alignmentOffset;
|
||||
|
||||
this.setAttribute("arrowposition", position);
|
||||
|
||||
// if this panel has a "sliding" arrow, we may have previously set margins...
|
||||
arrowbox.style.removeProperty("transform");
|
||||
if (position.indexOf("start_") == 0 || position.indexOf("end_") == 0) {
|
||||
container.orient = "horizontal";
|
||||
arrowbox.orient = "vertical";
|
||||
if (position.indexOf("_after") > 0) {
|
||||
arrowbox.pack = "end";
|
||||
} else {
|
||||
arrowbox.pack = "start";
|
||||
}
|
||||
arrowbox.style.transform = "translate(0, " + -offset + "px)";
|
||||
|
||||
// The assigned side stays the same regardless of direction.
|
||||
let isRTL = this.matches(":-moz-locale-dir(rtl)");
|
||||
|
||||
if (position.indexOf("start_") == 0) {
|
||||
container.dir = "reverse";
|
||||
this.setAttribute("side", isRTL ? "left" : "right");
|
||||
} else {
|
||||
container.dir = "";
|
||||
this.setAttribute("side", isRTL ? "right" : "left");
|
||||
}
|
||||
} else if (position.indexOf("before_") == 0 || position.indexOf("after_") == 0) {
|
||||
container.orient = "";
|
||||
arrowbox.orient = "";
|
||||
if (position.indexOf("_end") > 0) {
|
||||
arrowbox.pack = "end";
|
||||
} else {
|
||||
arrowbox.pack = "start";
|
||||
}
|
||||
arrowbox.style.transform = "translate(" + -offset + "px, 0)";
|
||||
|
||||
if (position.indexOf("before_") == 0) {
|
||||
container.dir = "reverse";
|
||||
this.setAttribute("side", "bottom");
|
||||
} else {
|
||||
container.dir = "";
|
||||
this.setAttribute("side", "top");
|
||||
}
|
||||
}
|
||||
|
||||
arrow.hidden = false;
|
||||
]]></body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="popupshowing" phase="target"><![CDATA[
|
||||
this.adjustArrowPosition();
|
||||
this.setAttribute("animate", "open");
|
||||
]]></handler>
|
||||
<handler event="popupshown" phase="target"><![CDATA[
|
||||
this.setAttribute("panelopen", "true");
|
||||
let disablePointerEvents;
|
||||
if (!this.hasAttribute("disablepointereventsfortransition")) {
|
||||
let container = document.getAnonymousElementByAttribute(this, "anonid", "container");
|
||||
let cs = getComputedStyle(container);
|
||||
let transitionProp = cs.transitionProperty;
|
||||
let transitionTime = parseFloat(cs.transitionDuration);
|
||||
disablePointerEvents = (transitionProp.includes("transform") ||
|
||||
transitionProp == "all") &&
|
||||
transitionTime > 0;
|
||||
this.setAttribute("disablepointereventsfortransition", disablePointerEvents);
|
||||
} else {
|
||||
disablePointerEvents = this.getAttribute("disablepointereventsfortransition") == "true";
|
||||
}
|
||||
if (!disablePointerEvents) {
|
||||
this.style.removeProperty("pointer-events");
|
||||
}
|
||||
]]></handler>
|
||||
<handler event="transitionend"><![CDATA[
|
||||
if (event.originalTarget.getAttribute("anonid") == "container" &&
|
||||
(event.propertyName == "transform" || event.propertyName == "-moz-window-transform")) {
|
||||
this.style.removeProperty("pointer-events");
|
||||
}
|
||||
]]></handler>
|
||||
<handler event="popuphiding" phase="target"><![CDATA[
|
||||
this.setAttribute("animate", "cancel");
|
||||
]]></handler>
|
||||
<handler event="popuphidden" phase="target"><![CDATA[
|
||||
this.removeAttribute("panelopen");
|
||||
if (this.getAttribute("disablepointereventsfortransition") == "true") {
|
||||
this.style.pointerEvents = "none";
|
||||
}
|
||||
this.removeAttribute("animate");
|
||||
]]></handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
</bindings>
|
|
@ -0,0 +1,872 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
/* eslint-env mozilla/browser-window */
|
||||
/* import-globals-from controller.js */
|
||||
|
||||
// This is loaded into all XUL windows. Wrap in a block to prevent
|
||||
// leaking to window scope.
|
||||
{
|
||||
const { AppConstants } = ChromeUtils.import(
|
||||
"resource://gre/modules/AppConstants.jsm"
|
||||
);
|
||||
|
||||
class MozPlacesPopup extends MozElements.MozMenuPopup {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const event_names = [
|
||||
"DOMMenuItemActive",
|
||||
"DOMMenuItemInactive",
|
||||
"dragstart",
|
||||
"drop",
|
||||
"dragover",
|
||||
"dragexit",
|
||||
"dragend",
|
||||
];
|
||||
for (let event_name of event_names) {
|
||||
this.addEventListener(event_name, ev => this[`on_${event_name}`](ev));
|
||||
}
|
||||
|
||||
this.attachShadow({ mode: "open" });
|
||||
}
|
||||
|
||||
get commonStyles() {
|
||||
let s = "";
|
||||
if (this.closest("#BMB_bookmarksPopup")) {
|
||||
s = `
|
||||
/* Remove padding on xul:arrowscrollbox to avoid extra padding on footer */
|
||||
arrowscrollbox.popup-internal-box {
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
.panel-arrowcontainer > .panel-arrowcontent > .popup-internal-box > .scrollbutton-up,
|
||||
.panel-arrowcontainer > .panel-arrowcontent > .popup-internal-box > .scrollbutton-down {
|
||||
-moz-appearance: none;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
switch (AppConstants.platform) {
|
||||
case "macosx":
|
||||
return `${s}
|
||||
.menupopup-drop-indicator-bar {
|
||||
position: relative;
|
||||
/* these two margins must together compensate the indicator's height */
|
||||
margin-top: -1px;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
.menupopup-drop-indicator {
|
||||
list-style-image: none;
|
||||
height: 2px;
|
||||
margin-inline-end: -4em;
|
||||
background-color: Highlight;
|
||||
}
|
||||
`;
|
||||
case "linux":
|
||||
return `${s}
|
||||
.menupopup-drop-indicator-bar {
|
||||
position: relative;
|
||||
/* these two margins must together compensate the indicator's height */
|
||||
margin-top: -1px;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
.menupopup-drop-indicator {
|
||||
list-style-image: none;
|
||||
height: 2px;
|
||||
margin-inline-end: -4em;
|
||||
background-color: Highlight;
|
||||
}
|
||||
`;
|
||||
case "win":
|
||||
return `${s}
|
||||
.menupopup-drop-indicator-bar {
|
||||
position: relative;
|
||||
/* these two margins must together compensate the indicator's height */
|
||||
margin-top: -1px;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
.menupopup-drop-indicator {
|
||||
list-style-image: none;
|
||||
height: 2px;
|
||||
margin-inline-end: -4em;
|
||||
background-color: Highlight;
|
||||
}
|
||||
`;
|
||||
default:
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
get styles() {
|
||||
if (!this.closest("#BMB_bookmarksPopup")) {
|
||||
return "";
|
||||
}
|
||||
|
||||
let s = `
|
||||
/* Popups with only one item don't have a footer */
|
||||
:host([singleitempopup=true]) > hbox > .popup-internal-box > .arrowscrollbox-scrollbox,
|
||||
/* These popups never have a footer */
|
||||
:host(#BMB_bookmarksToolbarPopup) > hbox > .popup-internal-box > .arrowscrollbox-scrollbox,
|
||||
:host(#BMB_unsortedBookmarksPopup) > hbox > .popup-internal-box > .arrowscrollbox-scrollbox,
|
||||
:host(#BMB_mobileBookmarksPopup) > hbox > .popup-internal-box > .arrowscrollbox-scrollbox {
|
||||
/* And so they need some bottom padding: */
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
`;
|
||||
switch (AppConstants.platform) {
|
||||
case "linux":
|
||||
case "win":
|
||||
return `${s}
|
||||
/* Add some space at the top because there are no headers: */
|
||||
:host > hbox > .popup-internal-box > .arrowscrollbox-scrollbox {
|
||||
padding-top: 4px;
|
||||
}
|
||||
`;
|
||||
default:
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
get markup() {
|
||||
return `
|
||||
<html:link rel="stylesheet" href="chrome://global/content/widgets.css" />
|
||||
<html:style>${this.commonStyles}${this.styles}</html:style>
|
||||
<hbox flex="1" part="innerbox">
|
||||
<vbox class="menupopup-drop-indicator-bar" hidden="true">
|
||||
<image class="menupopup-drop-indicator" mousethrough="always"></image>
|
||||
</vbox>
|
||||
<arrowscrollbox class="popup-internal-box" flex="1" orient="vertical"
|
||||
smoothscroll="false">
|
||||
<html:slot></html:slot>
|
||||
</arrowscrollbox>
|
||||
</hbox>
|
||||
`;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
if (this.delayConnectedCallback()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.shadowRoot.textContent = "";
|
||||
this.shadowRoot.appendChild(
|
||||
MozXULElement.parseXULToFragment(this.markup)
|
||||
);
|
||||
|
||||
this._indicatorBar = this.shadowRoot.querySelector(
|
||||
".menupopup-drop-indicator-bar"
|
||||
);
|
||||
this._scrollBox = this.shadowRoot.querySelector(".popup-internal-box");
|
||||
|
||||
/**
|
||||
* Sub-menus should be opened when the mouse drags over them, and closed
|
||||
* when the mouse drags off. The overFolder object manages opening and
|
||||
* closing of folders when the mouse hovers.
|
||||
*/
|
||||
this._overFolder = {
|
||||
_self: this,
|
||||
_folder: {
|
||||
elt: null,
|
||||
openTimer: null,
|
||||
hoverTime: 350,
|
||||
closeTimer: null,
|
||||
},
|
||||
_closeMenuTimer: null,
|
||||
|
||||
get elt() {
|
||||
return this._folder.elt;
|
||||
},
|
||||
set elt(val) {
|
||||
return (this._folder.elt = val);
|
||||
},
|
||||
|
||||
get openTimer() {
|
||||
return this._folder.openTimer;
|
||||
},
|
||||
set openTimer(val) {
|
||||
return (this._folder.openTimer = val);
|
||||
},
|
||||
|
||||
get hoverTime() {
|
||||
return this._folder.hoverTime;
|
||||
},
|
||||
set hoverTime(val) {
|
||||
return (this._folder.hoverTime = val);
|
||||
},
|
||||
|
||||
get closeTimer() {
|
||||
return this._folder.closeTimer;
|
||||
},
|
||||
set closeTimer(val) {
|
||||
return (this._folder.closeTimer = val);
|
||||
},
|
||||
|
||||
get closeMenuTimer() {
|
||||
return this._closeMenuTimer;
|
||||
},
|
||||
set closeMenuTimer(val) {
|
||||
return (this._closeMenuTimer = val);
|
||||
},
|
||||
|
||||
setTimer: function OF__setTimer(aTime) {
|
||||
var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
timer.initWithCallback(this, aTime, timer.TYPE_ONE_SHOT);
|
||||
return timer;
|
||||
},
|
||||
|
||||
notify: function OF__notify(aTimer) {
|
||||
// Function to process all timer notifications.
|
||||
|
||||
if (aTimer == this._folder.openTimer) {
|
||||
// Timer to open a submenu that's being dragged over.
|
||||
this._folder.elt.lastElementChild.setAttribute(
|
||||
"autoopened",
|
||||
"true"
|
||||
);
|
||||
this._folder.elt.lastElementChild.openPopup();
|
||||
this._folder.openTimer = null;
|
||||
} else if (aTimer == this._folder.closeTimer) {
|
||||
// Timer to close a submenu that's been dragged off of.
|
||||
// Only close the submenu if the mouse isn't being dragged over any
|
||||
// of its child menus.
|
||||
var draggingOverChild = PlacesControllerDragHelper.draggingOverChildNode(
|
||||
this._folder.elt
|
||||
);
|
||||
if (draggingOverChild) {
|
||||
this._folder.elt = null;
|
||||
}
|
||||
this.clear();
|
||||
|
||||
// Close any parent folders which aren't being dragged over.
|
||||
// (This is necessary because of the above code that keeps a folder
|
||||
// open while its children are being dragged over.)
|
||||
if (!draggingOverChild) {
|
||||
this.closeParentMenus();
|
||||
}
|
||||
} else if (aTimer == this.closeMenuTimer) {
|
||||
// Timer to close this menu after the drag exit.
|
||||
var popup = this._self;
|
||||
// if we are no more dragging we can leave the menu open to allow
|
||||
// for better D&D bookmark organization
|
||||
if (
|
||||
PlacesControllerDragHelper.getSession() &&
|
||||
!PlacesControllerDragHelper.draggingOverChildNode(
|
||||
popup.parentNode
|
||||
)
|
||||
) {
|
||||
popup.hidePopup();
|
||||
// Close any parent menus that aren't being dragged over;
|
||||
// otherwise they'll stay open because they couldn't close
|
||||
// while this menu was being dragged over.
|
||||
this.closeParentMenus();
|
||||
}
|
||||
this._closeMenuTimer = null;
|
||||
}
|
||||
},
|
||||
|
||||
// Helper function to close all parent menus of this menu,
|
||||
// as long as none of the parent's children are currently being
|
||||
// dragged over.
|
||||
closeParentMenus: function OF__closeParentMenus() {
|
||||
var popup = this._self;
|
||||
var parent = popup.parentNode;
|
||||
while (parent) {
|
||||
if (parent.localName == "menupopup" && parent._placesNode) {
|
||||
if (
|
||||
PlacesControllerDragHelper.draggingOverChildNode(
|
||||
parent.parentNode
|
||||
)
|
||||
) {
|
||||
break;
|
||||
}
|
||||
parent.hidePopup();
|
||||
}
|
||||
parent = parent.parentNode;
|
||||
}
|
||||
},
|
||||
|
||||
// The mouse is no longer dragging over the stored menubutton.
|
||||
// Close the menubutton, clear out drag styles, and clear all
|
||||
// timers for opening/closing it.
|
||||
clear: function OF__clear() {
|
||||
if (this._folder.elt && this._folder.elt.lastElementChild) {
|
||||
if (!this._folder.elt.lastElementChild.hasAttribute("dragover")) {
|
||||
this._folder.elt.lastElementChild.hidePopup();
|
||||
}
|
||||
// remove menuactive style
|
||||
this._folder.elt.removeAttribute("_moz-menuactive");
|
||||
this._folder.elt = null;
|
||||
}
|
||||
if (this._folder.openTimer) {
|
||||
this._folder.openTimer.cancel();
|
||||
this._folder.openTimer = null;
|
||||
}
|
||||
if (this._folder.closeTimer) {
|
||||
this._folder.closeTimer.cancel();
|
||||
this._folder.closeTimer = null;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the view that manages the popup.
|
||||
*/
|
||||
get _rootView() {
|
||||
if (!this.__rootView) {
|
||||
this.__rootView = PlacesUIUtils.getViewForNode(this);
|
||||
}
|
||||
return this.__rootView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we should hide the drop indicator for the target
|
||||
*/
|
||||
_hideDropIndicator(aEvent) {
|
||||
let target = aEvent.target;
|
||||
|
||||
// Don't draw the drop indicator outside of markers or if current
|
||||
// node is not a Places node.
|
||||
let betweenMarkers =
|
||||
this._startMarker.compareDocumentPosition(target) &
|
||||
Node.DOCUMENT_POSITION_FOLLOWING &&
|
||||
this._endMarker.compareDocumentPosition(target) &
|
||||
Node.DOCUMENT_POSITION_PRECEDING;
|
||||
|
||||
// Hide the dropmarker if current node is not a Places node.
|
||||
return !(target && target._placesNode && betweenMarkers);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns information about where to drop when
|
||||
* dragging over this popup insertion point
|
||||
*/
|
||||
_getDropPoint(aEvent) {
|
||||
// Can't drop if the menu isn't a folder
|
||||
let resultNode = this._placesNode;
|
||||
|
||||
if (
|
||||
!PlacesUtils.nodeIsFolder(resultNode) ||
|
||||
this._rootView.controller.disallowInsertion(resultNode)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var dropPoint = { ip: null, folderElt: null };
|
||||
|
||||
// The element we are dragging over
|
||||
let elt = aEvent.target;
|
||||
if (elt.localName == "menupopup") {
|
||||
elt = elt.parentNode;
|
||||
}
|
||||
|
||||
let eventY = aEvent.clientY;
|
||||
let { y: eltY, height: eltHeight } = elt.getBoundingClientRect();
|
||||
|
||||
if (!elt._placesNode) {
|
||||
// If we are dragging over a non places node drop at the end.
|
||||
dropPoint.ip = new PlacesInsertionPoint({
|
||||
parentId: PlacesUtils.getConcreteItemId(resultNode),
|
||||
parentGuid: PlacesUtils.getConcreteItemGuid(resultNode),
|
||||
});
|
||||
// We can set folderElt if we are dropping over a static menu that
|
||||
// has an internal placespopup.
|
||||
let isMenu =
|
||||
elt.localName == "menu" ||
|
||||
(elt.localName == "toolbarbutton" &&
|
||||
elt.getAttribute("type") == "menu");
|
||||
if (
|
||||
isMenu &&
|
||||
elt.lastElementChild &&
|
||||
elt.lastElementChild.hasAttribute("placespopup")
|
||||
) {
|
||||
dropPoint.folderElt = elt;
|
||||
}
|
||||
return dropPoint;
|
||||
}
|
||||
|
||||
let tagName = PlacesUtils.nodeIsTagQuery(elt._placesNode)
|
||||
? elt._placesNode.title
|
||||
: null;
|
||||
if (
|
||||
(PlacesUtils.nodeIsFolder(elt._placesNode) &&
|
||||
!PlacesUIUtils.isFolderReadOnly(elt._placesNode)) ||
|
||||
PlacesUtils.nodeIsTagQuery(elt._placesNode)
|
||||
) {
|
||||
// This is a folder or a tag container.
|
||||
if (eventY - eltY < eltHeight * 0.2) {
|
||||
// If mouse is in the top part of the element, drop above folder.
|
||||
dropPoint.ip = new PlacesInsertionPoint({
|
||||
parentId: PlacesUtils.getConcreteItemId(resultNode),
|
||||
parentGuid: PlacesUtils.getConcreteItemGuid(resultNode),
|
||||
orientation: Ci.nsITreeView.DROP_BEFORE,
|
||||
tagName,
|
||||
dropNearNode: elt._placesNode,
|
||||
});
|
||||
return dropPoint;
|
||||
} else if (eventY - eltY < eltHeight * 0.8) {
|
||||
// If mouse is in the middle of the element, drop inside folder.
|
||||
dropPoint.ip = new PlacesInsertionPoint({
|
||||
parentId: PlacesUtils.getConcreteItemId(elt._placesNode),
|
||||
parentGuid: PlacesUtils.getConcreteItemGuid(elt._placesNode),
|
||||
tagName,
|
||||
});
|
||||
dropPoint.folderElt = elt;
|
||||
return dropPoint;
|
||||
}
|
||||
} else if (eventY - eltY <= eltHeight / 2) {
|
||||
// This is a non-folder node or a readonly folder.
|
||||
// If the mouse is above the middle, drop above this item.
|
||||
dropPoint.ip = new PlacesInsertionPoint({
|
||||
parentId: PlacesUtils.getConcreteItemId(resultNode),
|
||||
parentGuid: PlacesUtils.getConcreteItemGuid(resultNode),
|
||||
orientation: Ci.nsITreeView.DROP_BEFORE,
|
||||
tagName,
|
||||
dropNearNode: elt._placesNode,
|
||||
});
|
||||
return dropPoint;
|
||||
}
|
||||
|
||||
// Drop below the item.
|
||||
dropPoint.ip = new PlacesInsertionPoint({
|
||||
parentId: PlacesUtils.getConcreteItemId(resultNode),
|
||||
parentGuid: PlacesUtils.getConcreteItemGuid(resultNode),
|
||||
orientation: Ci.nsITreeView.DROP_AFTER,
|
||||
tagName,
|
||||
dropNearNode: elt._placesNode,
|
||||
});
|
||||
return dropPoint;
|
||||
}
|
||||
|
||||
_cleanupDragDetails() {
|
||||
// Called on dragend and drop.
|
||||
PlacesControllerDragHelper.currentDropTarget = null;
|
||||
this._rootView._draggedElt = null;
|
||||
this.removeAttribute("dragover");
|
||||
this.removeAttribute("dragstart");
|
||||
this._indicatorBar.hidden = true;
|
||||
}
|
||||
|
||||
on_DOMMenuItemActive(event) {
|
||||
let elt = event.target;
|
||||
if (elt.parentNode != this) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (AppConstants.platform === "macosx") {
|
||||
// XXX: The following check is a temporary hack until bug 420033 is
|
||||
// resolved.
|
||||
let parentElt = elt.parent;
|
||||
while (parentElt) {
|
||||
if (
|
||||
parentElt.id == "bookmarksMenuPopup" ||
|
||||
parentElt.id == "goPopup"
|
||||
) {
|
||||
return;
|
||||
}
|
||||
parentElt = parentElt.parentNode;
|
||||
}
|
||||
}
|
||||
|
||||
if (window.XULBrowserWindow) {
|
||||
let placesNode = elt._placesNode;
|
||||
|
||||
var linkURI;
|
||||
if (placesNode && PlacesUtils.nodeIsURI(placesNode)) {
|
||||
linkURI = placesNode.uri;
|
||||
} else if (elt.hasAttribute("targetURI")) {
|
||||
linkURI = elt.getAttribute("targetURI");
|
||||
}
|
||||
|
||||
if (linkURI) {
|
||||
window.XULBrowserWindow.setOverLink(linkURI, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
on_DOMMenuItemInactive(event) {
|
||||
let elt = event.target;
|
||||
if (elt.parentNode != this) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (window.XULBrowserWindow) {
|
||||
window.XULBrowserWindow.setOverLink("", null);
|
||||
}
|
||||
}
|
||||
|
||||
on_dragstart(event) {
|
||||
let elt = event.target;
|
||||
if (!elt._placesNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
let draggedElt = elt._placesNode;
|
||||
|
||||
// Force a copy action if parent node is a query or we are dragging a
|
||||
// not-removable node.
|
||||
if (!this._rootView.controller.canMoveNode(draggedElt)) {
|
||||
event.dataTransfer.effectAllowed = "copyLink";
|
||||
}
|
||||
|
||||
// Activate the view and cache the dragged element.
|
||||
this._rootView._draggedElt = draggedElt;
|
||||
this._rootView.controller.setDataTransfer(event);
|
||||
this.setAttribute("dragstart", "true");
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
on_drop(event) {
|
||||
PlacesControllerDragHelper.currentDropTarget = event.target;
|
||||
|
||||
let dropPoint = this._getDropPoint(event);
|
||||
if (dropPoint && dropPoint.ip) {
|
||||
PlacesControllerDragHelper.onDrop(
|
||||
dropPoint.ip,
|
||||
event.dataTransfer
|
||||
).catch(Cu.reportError);
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
this._cleanupDragDetails();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
on_dragover(event) {
|
||||
PlacesControllerDragHelper.currentDropTarget = event.target;
|
||||
let dt = event.dataTransfer;
|
||||
|
||||
let dropPoint = this._getDropPoint(event);
|
||||
if (
|
||||
!dropPoint ||
|
||||
!dropPoint.ip ||
|
||||
!PlacesControllerDragHelper.canDrop(dropPoint.ip, dt)
|
||||
) {
|
||||
this._indicatorBar.hidden = true;
|
||||
event.stopPropagation();
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark this popup as being dragged over.
|
||||
this.setAttribute("dragover", "true");
|
||||
|
||||
if (dropPoint.folderElt) {
|
||||
// We are dragging over a folder.
|
||||
// _overFolder should take the care of opening it on a timer.
|
||||
if (
|
||||
this._overFolder.elt &&
|
||||
this._overFolder.elt != dropPoint.folderElt
|
||||
) {
|
||||
// We are dragging over a new folder, let's clear old values
|
||||
this._overFolder.clear();
|
||||
}
|
||||
if (!this._overFolder.elt) {
|
||||
this._overFolder.elt = dropPoint.folderElt;
|
||||
// Create the timer to open this folder.
|
||||
this._overFolder.openTimer = this._overFolder.setTimer(
|
||||
this._overFolder.hoverTime
|
||||
);
|
||||
}
|
||||
// Since we are dropping into a folder set the corresponding style.
|
||||
dropPoint.folderElt.setAttribute("_moz-menuactive", true);
|
||||
} else {
|
||||
// We are not dragging over a folder.
|
||||
// Clear out old _overFolder information.
|
||||
this._overFolder.clear();
|
||||
}
|
||||
|
||||
// Autoscroll the popup strip if we drag over the scroll buttons.
|
||||
let anonid = event.originalTarget.getAttribute("anonid");
|
||||
let scrollDir = 0;
|
||||
if (anonid == "scrollbutton-up") {
|
||||
scrollDir = -1;
|
||||
} else if (anonid == "scrollbutton-down") {
|
||||
scrollDir = 1;
|
||||
}
|
||||
if (scrollDir != 0) {
|
||||
this._scrollBox.scrollByIndex(scrollDir, true);
|
||||
}
|
||||
|
||||
// Check if we should hide the drop indicator for this target.
|
||||
if (dropPoint.folderElt || this._hideDropIndicator(event)) {
|
||||
this._indicatorBar.hidden = true;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return;
|
||||
}
|
||||
|
||||
// We should display the drop indicator relative to the arrowscrollbox.
|
||||
let scrollRect = this._scrollBox.getBoundingClientRect();
|
||||
let newMarginTop = 0;
|
||||
if (scrollDir == 0) {
|
||||
let elt = this.firstElementChild;
|
||||
while (
|
||||
elt &&
|
||||
event.screenY > elt.screenY + elt.getBoundingClientRect().height / 2
|
||||
) {
|
||||
elt = elt.nextElementSibling;
|
||||
}
|
||||
newMarginTop = elt
|
||||
? elt.screenY - this._scrollBox.screenY
|
||||
: scrollRect.height;
|
||||
} else if (scrollDir == 1) {
|
||||
newMarginTop = scrollRect.height;
|
||||
}
|
||||
|
||||
// Set the new marginTop based on arrowscrollbox.
|
||||
newMarginTop += scrollRect.y - this._scrollBox.getBoundingClientRect().y;
|
||||
this._indicatorBar.firstElementChild.style.marginTop =
|
||||
newMarginTop + "px";
|
||||
this._indicatorBar.hidden = false;
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
on_dragexit(event) {
|
||||
PlacesControllerDragHelper.currentDropTarget = null;
|
||||
this.removeAttribute("dragover");
|
||||
|
||||
// If we have not moved to a valid new target clear the drop indicator
|
||||
// this happens when moving out of the popup.
|
||||
let target = event.relatedTarget;
|
||||
if (!target || !this.contains(target)) {
|
||||
this._indicatorBar.hidden = true;
|
||||
}
|
||||
|
||||
// Close any folder being hovered over
|
||||
if (this._overFolder.elt) {
|
||||
this._overFolder.closeTimer = this._overFolder.setTimer(
|
||||
this._overFolder.hoverTime
|
||||
);
|
||||
}
|
||||
|
||||
// The autoopened attribute is set when this folder was automatically
|
||||
// opened after the user dragged over it. If this attribute is set,
|
||||
// auto-close the folder on drag exit.
|
||||
// We should also try to close this popup if the drag has started
|
||||
// from here, the timer will check if we are dragging over a child.
|
||||
if (this.hasAttribute("autoopened") || this.hasAttribute("dragstart")) {
|
||||
this._overFolder.closeMenuTimer = this._overFolder.setTimer(
|
||||
this._overFolder.hoverTime
|
||||
);
|
||||
}
|
||||
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
on_dragend(event) {
|
||||
this._cleanupDragDetails();
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("places-popup", MozPlacesPopup, {
|
||||
extends: "menupopup",
|
||||
});
|
||||
|
||||
class MozPlacesPopupArrow extends MozPlacesPopup {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const event_names = [
|
||||
"popupshowing",
|
||||
"popupshown",
|
||||
"transitionend",
|
||||
"popuphiding",
|
||||
"popuphidden",
|
||||
"dragexit",
|
||||
"dragend",
|
||||
];
|
||||
for (let event_name of event_names) {
|
||||
this.addEventListener(event_name, ev => this[`on_${event_name}`](ev));
|
||||
}
|
||||
}
|
||||
|
||||
static get inheritedAttributes() {
|
||||
return {
|
||||
".panel-arrowcontainer": "side,panelopen",
|
||||
".panel-arrow": "side",
|
||||
".panel-arrowcontent": "side,align,dir,orient,pack",
|
||||
};
|
||||
}
|
||||
|
||||
get markup() {
|
||||
return `
|
||||
<html:link rel="stylesheet" href="chrome://global/content/widgets.css" />
|
||||
<html:style>${this.commonStyles}</html:style>
|
||||
<vbox class="panel-arrowcontainer" flex="1">
|
||||
<box class="panel-arrowbox">
|
||||
<image class="panel-arrow"></image>
|
||||
</box>
|
||||
<box class="panel-arrowcontent" part="arrowcontent" flex="1">
|
||||
<vbox class="menupopup-drop-indicator-bar" hidden="true">
|
||||
<image class="menupopup-drop-indicator" mousethrough="always"></image>
|
||||
</vbox>
|
||||
<arrowscrollbox class="popup-internal-box" flex="1"
|
||||
orient="vertical" smoothscroll="false"
|
||||
part="popupbox">
|
||||
<html:slot></html:slot>
|
||||
</arrowscrollbox>
|
||||
</box>
|
||||
</vbox>
|
||||
`;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
if (this.delayConnectedCallback()) {
|
||||
return;
|
||||
}
|
||||
|
||||
super.connectedCallback();
|
||||
this.initializeAttributeInheritance();
|
||||
|
||||
this.setAttribute("flip", "both");
|
||||
this.setAttribute("side", "top");
|
||||
this.setAttribute("position", "bottomcenter topright");
|
||||
this.style.pointerEvents = "none";
|
||||
}
|
||||
|
||||
get container() {
|
||||
return this.shadowRoot.querySelector(".panel-arrowcontainer");
|
||||
}
|
||||
get arrowbox() {
|
||||
return this.shadowRoot.querySelector(".panel-arrowbox");
|
||||
}
|
||||
get arrow() {
|
||||
return this.shadowRoot.querySelector(".panel-arrow");
|
||||
}
|
||||
|
||||
adjustArrowPosition() {
|
||||
let arrow = this.arrow;
|
||||
|
||||
let anchor = this.anchorNode;
|
||||
if (!anchor) {
|
||||
arrow.hidden = true;
|
||||
return;
|
||||
}
|
||||
|
||||
let container = this.container;
|
||||
let arrowbox = this.arrowbox;
|
||||
|
||||
var position = this.alignmentPosition;
|
||||
var offset = this.alignmentOffset;
|
||||
|
||||
this.setAttribute("arrowposition", position);
|
||||
|
||||
// if this panel has a "sliding" arrow, we may have previously set margins...
|
||||
arrowbox.style.removeProperty("transform");
|
||||
if (position.indexOf("start_") == 0 || position.indexOf("end_") == 0) {
|
||||
container.orient = "horizontal";
|
||||
arrowbox.orient = "vertical";
|
||||
if (position.indexOf("_after") > 0) {
|
||||
arrowbox.pack = "end";
|
||||
} else {
|
||||
arrowbox.pack = "start";
|
||||
}
|
||||
arrowbox.style.transform = "translate(0, " + -offset + "px)";
|
||||
|
||||
// The assigned side stays the same regardless of direction.
|
||||
let isRTL = this.matches(":-moz-locale-dir(rtl)");
|
||||
|
||||
if (position.indexOf("start_") == 0) {
|
||||
container.dir = "reverse";
|
||||
this.setAttribute("side", isRTL ? "left" : "right");
|
||||
} else {
|
||||
container.dir = "";
|
||||
this.setAttribute("side", isRTL ? "right" : "left");
|
||||
}
|
||||
} else if (
|
||||
position.indexOf("before_") == 0 ||
|
||||
position.indexOf("after_") == 0
|
||||
) {
|
||||
container.orient = "";
|
||||
arrowbox.orient = "";
|
||||
if (position.indexOf("_end") > 0) {
|
||||
arrowbox.pack = "end";
|
||||
} else {
|
||||
arrowbox.pack = "start";
|
||||
}
|
||||
arrowbox.style.transform = "translate(" + -offset + "px, 0)";
|
||||
|
||||
if (position.indexOf("before_") == 0) {
|
||||
container.dir = "reverse";
|
||||
this.setAttribute("side", "bottom");
|
||||
} else {
|
||||
container.dir = "";
|
||||
this.setAttribute("side", "top");
|
||||
}
|
||||
}
|
||||
|
||||
arrow.hidden = false;
|
||||
}
|
||||
|
||||
on_popupshowing(event) {
|
||||
if (event.target == this) {
|
||||
this.adjustArrowPosition();
|
||||
this.setAttribute("animate", "open");
|
||||
}
|
||||
}
|
||||
|
||||
on_popupshown(event) {
|
||||
if (event.target != this) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setAttribute("panelopen", "true");
|
||||
let disablePointerEvents;
|
||||
if (!this.hasAttribute("disablepointereventsfortransition")) {
|
||||
let cs = getComputedStyle(this.container);
|
||||
let transitionProp = cs.transitionProperty;
|
||||
let transitionTime = parseFloat(cs.transitionDuration);
|
||||
disablePointerEvents =
|
||||
(transitionProp.includes("transform") || transitionProp == "all") &&
|
||||
transitionTime > 0;
|
||||
this.setAttribute(
|
||||
"disablepointereventsfortransition",
|
||||
disablePointerEvents
|
||||
);
|
||||
} else {
|
||||
disablePointerEvents =
|
||||
this.getAttribute("disablepointereventsfortransition") == "true";
|
||||
}
|
||||
if (!disablePointerEvents) {
|
||||
this.style.removeProperty("pointer-events");
|
||||
}
|
||||
}
|
||||
|
||||
on_transitionend(event) {
|
||||
if (
|
||||
event.originalTarget.classList.contains("panel-arrowcontainer") &&
|
||||
(event.propertyName == "transform" ||
|
||||
event.propertyName == "-moz-window-transform")
|
||||
) {
|
||||
this.style.removeProperty("pointer-events");
|
||||
}
|
||||
}
|
||||
|
||||
on_popuphiding(event) {
|
||||
if (event.target == this) {
|
||||
this.setAttribute("animate", "cancel");
|
||||
}
|
||||
}
|
||||
|
||||
on_popuphidden(event) {
|
||||
if (event.target == this) {
|
||||
this.removeAttribute("panelopen");
|
||||
if (this.getAttribute("disablepointereventsfortransition") == "true") {
|
||||
this.style.pointerEvents = "none";
|
||||
}
|
||||
this.removeAttribute("animate");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("places-popup-arrow", MozPlacesPopupArrow, {
|
||||
extends: "menupopup",
|
||||
});
|
||||
}
|
|
@ -20,7 +20,7 @@ tree[is="places-tree"] > treechildren::-moz-tree-cell {
|
|||
}
|
||||
|
||||
menupopup[placespopup="true"] {
|
||||
-moz-binding: url("chrome://browser/content/places/menu.xml#places-popup-base");
|
||||
-moz-binding: none;
|
||||
}
|
||||
|
||||
/* Apply crisp rendering for favicons at exactly 2dppx resolution */
|
||||
|
|
|
@ -11,7 +11,7 @@ browser.jar:
|
|||
content/browser/places/places.css (content/places.css)
|
||||
* content/browser/places/bookmarkProperties.xul (content/bookmarkProperties.xul)
|
||||
content/browser/places/bookmarkProperties.js (content/bookmarkProperties.js)
|
||||
content/browser/places/menu.xml (content/menu.xml)
|
||||
content/browser/places/places-menupopup.js (content/places-menupopup.js)
|
||||
content/browser/places/places-tree.js (content/places-tree.js)
|
||||
content/browser/places/controller.js (content/controller.js)
|
||||
content/browser/places/treeView.js (content/treeView.js)
|
||||
|
|
|
@ -104,21 +104,6 @@ menuitem.bookmark-item {
|
|||
color: HighlightText !important;
|
||||
}
|
||||
|
||||
/* rules for menupopup drop indicators */
|
||||
.menupopup-drop-indicator-bar {
|
||||
position: relative;
|
||||
/* these two margins must together compensate the indicator's height */
|
||||
margin-top: -1px;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
.menupopup-drop-indicator {
|
||||
list-style-image: none;
|
||||
height: 2px;
|
||||
margin-inline-end: -4em;
|
||||
background-color: Highlight;
|
||||
}
|
||||
|
||||
/* Bookmarks toolbar */
|
||||
#PlacesToolbarDropIndicator {
|
||||
list-style-image: url(chrome://browser/skin/places/toolbarDropMarker.png);
|
||||
|
|
|
@ -13,11 +13,6 @@
|
|||
padding-top: 1px;
|
||||
}
|
||||
|
||||
/* Add some space at the top because there are no headers: */
|
||||
#BMB_bookmarksPopup menupopup > hbox > .popup-internal-box > .arrowscrollbox-scrollbox {
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
menuitem.subviewbutton {
|
||||
-moz-appearance: none !important;
|
||||
}
|
||||
|
|
|
@ -651,21 +651,6 @@
|
|||
color: HighlightText !important;
|
||||
}
|
||||
|
||||
/* rules for menupopup drop indicators */
|
||||
.menupopup-drop-indicator-bar {
|
||||
position: relative;
|
||||
/* these two margins must together compensate the indicator's height */
|
||||
margin-top: -1px;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
.menupopup-drop-indicator {
|
||||
list-style-image: none;
|
||||
height: 2px;
|
||||
margin-inline-end: -4em;
|
||||
background-color: Highlight;
|
||||
}
|
||||
|
||||
%include ../shared/notification-icons.inc.css
|
||||
|
||||
/* Translation */
|
||||
|
|
|
@ -44,7 +44,7 @@ panelmultiview .toolbaritem-combined-buttons > spacer.before-label {
|
|||
background: transparent;
|
||||
}
|
||||
|
||||
#BMB_bookmarksPopup menupopup[placespopup=true] > hbox:-moz-lwtheme {
|
||||
#BMB_bookmarksPopup menupopup[placespopup=true]:-moz-lwtheme::part(innerbox) {
|
||||
background: var(--arrowpanel-background);
|
||||
border-radius: var(--arrowpanel-border-radius);
|
||||
box-shadow: 0 0 0 1px var(--arrowpanel-border-color);
|
||||
|
@ -53,6 +53,7 @@ panelmultiview .toolbaritem-combined-buttons > spacer.before-label {
|
|||
margin: 1px;
|
||||
}
|
||||
|
||||
|
||||
/* Override OSX-specific toolkit styles for the bookmarks panel */
|
||||
menu.subviewbutton > .menu-right {
|
||||
margin-inline-end: -4px;
|
||||
|
|
|
@ -233,7 +233,7 @@ panelview {
|
|||
max-width: @standaloneSubviewWidth@;
|
||||
}
|
||||
|
||||
#BMB_bookmarksPopup > .panel-arrowcontainer > .panel-arrowcontent > .popup-internal-box {
|
||||
#BMB_bookmarksPopup::part(popupbox) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
@ -339,7 +339,8 @@ panelview:not([mainview]) .toolbarbutton-text,
|
|||
display: -moz-box;
|
||||
}
|
||||
|
||||
.cui-widget-panel {
|
||||
.cui-widget-panel,
|
||||
.cui-widget-panel::part(arrowcontent) {
|
||||
--arrowpanel-padding: 4px 0;
|
||||
}
|
||||
|
||||
|
@ -361,6 +362,7 @@ panelview:not([mainview]) .toolbarbutton-text,
|
|||
min-width: calc(@menuPanelWidth@ + 32px);
|
||||
}
|
||||
|
||||
.cui-widget-panel.cui-widget-panelWithFooter::part(arrowcontent),
|
||||
.cui-widget-panel.cui-widget-panelWithFooter > .panel-arrowcontainer > .panel-arrowcontent {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
@ -1286,33 +1288,11 @@ menuitem.panel-subview-footer@menuStateActive@,
|
|||
margin-inline-end: 3px;
|
||||
}
|
||||
|
||||
#BMB_bookmarksPopup .panel-arrowcontainer > .panel-arrowcontent > .popup-internal-box > .scrollbutton-up,
|
||||
#BMB_bookmarksPopup .panel-arrowcontainer > .panel-arrowcontent > .popup-internal-box > .scrollbutton-down {
|
||||
-moz-appearance: none;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Remove padding on xul:arrowscrollbox to avoid extra padding on footer */
|
||||
#BMB_bookmarksPopup arrowscrollbox {
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
#BMB_bookmarksPopup menupopup > .bookmarks-actions-menuseparator {
|
||||
/* Hide bottom separator as the styled footer includes a top border serving the same purpose */
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Popups with only one item don't have a footer */
|
||||
#BMB_bookmarksPopup menupopup[placespopup=true][singleitempopup=true] > hbox > .popup-internal-box > .arrowscrollbox-scrollbox,
|
||||
/* These popups never have a footer */
|
||||
#BMB_bookmarksToolbarPopup > hbox > .popup-internal-box > .arrowscrollbox-scrollbox,
|
||||
#BMB_unsortedBookmarksPopup > hbox > .popup-internal-box > .arrowscrollbox-scrollbox,
|
||||
#BMB_mobileBookmarksPopup > hbox > .popup-internal-box > .arrowscrollbox-scrollbox {
|
||||
/* And so they need some bottom padding: */
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
/* Disabled (empty) item is always alone and never has an icon, so fix its left padding */
|
||||
#BMB_bookmarksPopup menupopup[emptyplacesresult] .bookmark-item.subviewbutton {
|
||||
padding-left: 6px;
|
||||
|
|
|
@ -704,21 +704,6 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
|
|||
color: HighlightText !important;
|
||||
}
|
||||
|
||||
/* rules for menupopup drop indicators */
|
||||
.menupopup-drop-indicator-bar {
|
||||
position: relative;
|
||||
/* these two margins must together compensate the indicator's height */
|
||||
margin-top: -1px;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
.menupopup-drop-indicator {
|
||||
list-style-image: none;
|
||||
height: 2px;
|
||||
margin-inline-end: -4em;
|
||||
background-color: Highlight;
|
||||
}
|
||||
|
||||
%include ../shared/notification-icons.inc.css
|
||||
%include ../shared/addon-notification.inc.css
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
padding-inline-start: 3px;
|
||||
}
|
||||
|
||||
#BMB_bookmarksPopup menupopup[placespopup=true] > hbox {
|
||||
/* emulating chrome://browser/content/places/menu.xml#places-popup-arrow but without the arrow */
|
||||
#BMB_bookmarksPopup menupopup[placespopup=true]::part(innerbox) {
|
||||
/* emulating MozPlacesPopupArrow but without the arrow */
|
||||
box-shadow: 0 0 4px rgba(0,0,0,0.2);
|
||||
background: var(--arrowpanel-background);
|
||||
color: var(--arrowpanel-color);
|
||||
|
@ -26,16 +26,11 @@
|
|||
|
||||
/* Add border-radius on Windows 7 */
|
||||
@media (-moz-os-version: windows-win7) {
|
||||
#BMB_bookmarksPopup menupopup[placespopup=true] > hbox {
|
||||
#BMB_bookmarksPopup menupopup[placespopup=true]::part(innerbox) {
|
||||
border-radius: 3.5px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add some space at the top because there are no headers: */
|
||||
#BMB_bookmarksPopup menupopup[placespopup=true] > hbox > .popup-internal-box > .arrowscrollbox-scrollbox {
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
/* bookmark panel separator */
|
||||
#BMB_bookmarksPopup menuseparator {
|
||||
padding-top: 0;
|
||||
|
|
|
@ -49,6 +49,8 @@ const MAPPINGS = {
|
|||
"viewSourceUtils.js":
|
||||
"toolkit/components/viewsource/content/viewSourceUtils.js",
|
||||
"places-tree.js": "browser/components/places/content/places-tree.js",
|
||||
"places-menupopup.js":
|
||||
"browser/components/places/content/places-menupopup.js",
|
||||
};
|
||||
|
||||
const globalScriptsRegExp = /^\s*Services.scriptloader.loadSubScript\(\"(.*?)\", this\);$/;
|
||||
|
|
Загрузка…
Ссылка в новой задаче