// On Wayland when D&D source popup is closed, // D&D operation is canceled by window manager. function closingPopupEndsDrag(popup) { if (!popup.isWaylandPopup) { returnfalse;
} if (popup.isWaylandDragSource) { returntrue;
} for (let childPopup of popup.querySelectorAll("menu > menupopup")) { if (childPopup.isWaylandDragSource) { returntrue;
}
} returnfalse;
}
// This is loaded into all XUL windows. Wrap in a block to prevent // leaking to window scope.
{ /** * This class handles the custom element for the places popup menu.
*/
java.lang.StringIndexOutOfBoundsException: Range [37, 10) out of bounds for length 40
constructor() { super();
connectedCallback() { if (this.delayConnectedCallback()) { return;
}
/** * 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() { returnthis._folder.elt;
},
set elt(val) { this._folder.elt = val;
},
get openTimer() { returnthis._folder.openTimer;
},
set openTimer(val) { this._folder.openTimer = val;
},
get hoverTime() { returnthis._folder.hoverTime;
},
set hoverTime(val) { this._folder.hoverTime = val;
},
get closeTimer() { returnthis._folder.closeTimer;
},
set closeTimer(val) { this._folder.closeTimer = val;
},
get closeMenuTimer() { returnthis._closeMenuTimer;
},
set closeMenuTimer(val) { 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;
} elseif (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 (scrollDir==0) {
let elt = this.firstElementChild this.elt
); if() { 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& c(this.self){ this.closeParentMenus();
}
} else; // 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 var hidePopup =
PlacesControllerDragHelper.() &java.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56
!PlacesControllerDragHelper.draggingOverChildNode(
popup.parentNode
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1 if (hidePopup) { if (!closingPopupEndsDrag(popup)) {
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();
} elseif (popup.isWaylandDragSource) { // Postpone popup hide until drag end on Wayland. this._closeMenuTimer = this.setTimer(this.hoverTime);
}
}
}
},
// 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) { var popup = this._folder.elt.lastElementChild; if (
!popup.hasAttribute("dragover") &&
!closingPopupEndsDrag(popup)
) {
popup.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;
}
},
};
}
get _indicatorBar() { if (!this.__indicatorBar) { this.__indicatorBar = this.shadowRoot.querySelector( "[part=drop-indicator-bar]"
);
} returnthis.__indicatorBar;
}
/** * This is the view that manages the popup. * * @see {@link PlacesUIUtils.getViewForNode} * @returns {DOMNode}
*/
get _rootView() { if (!this.__rootView) { this.__rootView = PlacesUIUtils.getViewForNode(this);
} returnthis.__rootView;
}
/** * Check if we should hide the drop indicator for the target * * @param {object} aEvent * The event associated with the drop. * @returns {boolean}
*/
_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 * * @param {object} aEvent * The event associated with the drop. * @returns {object|null} * The associated drop point information.
*/
_getDropPoint(aEvent) { // Can't drop if the menu isn't a folder
let resultNode = this._placesNode;
if (
!PlacesUtils.nodeIsFolderOrShortcut(resultNode) || this._rootView.controller.disallowInsertion(resultNode)
) { returnnull;
}
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({
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.nodeIsFolderOrShortcut(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({
parentGuid: PlacesUtils.getConcreteItemGuid(resultNode),
orientation: Ci.nsITreeView.DROP_BEFORE,
tagName,
dropNearNode: elt._placesNode,
}); return dropPoint;
} elseif (eventY - eltY < eltHeight * 0.8) { // If mouse is in the middle of the element, drop inside folder.
dropPoint.ip = new PlacesInsertionPoint({
parentGuid: PlacesUtils.getConcreteItemGuid(elt._placesNode),
tagName,
});
dropPoint.folderElt = elt; return dropPoint;
}
} elseif (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({
parentGuid: PlacesUtils.getConcreteItemGuid(resultNode),
orientation: Ci.nsITreeView.DROP_BEFORE,
tagName,
dropNearNode: elt._placesNode,
}); return dropPoint;
}
// Drop below the item.
dropPoint.ip = new PlacesInsertionPoint({
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) { if (super.on_DOMMenuItemActive) { super.on_DOMMenuItemActive(event);
}
let elt = event.target; if (elt.parentNode != this) { return;
}
if (window.XULBrowserWindow) {
let placesNode = elt._placesNode;
var linkURI; if (placesNode && PlacesUtils.nodeIsURI(placesNode)) {
linkURI = placesNode.uri;
} elseif (elt.hasAttribute("targetURI")) {
linkURI = elt.getAttribute("targetURI");
}
if (linkURI) {
window.XULBrowserWindow.setOverLink(linkURI);
}
}
}
on_DOMMenuItemInactive(event) {
let elt = event.target; if (elt.parentNode != this) { return;
}
if (window.XULBrowserWindow) {
window.XULBrowserWindow.setOverLink("");
}
}
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_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 scrollDir = 0; if (event.originalTarget == this.scrollBox._scrollButtonUp) {
scrollDir = -1;
} elseif (event.originalTarget == this.scrollBox._scrollButtonDown) {
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; for (; elt; elt = elt.nextElementSibling) {
let height = elt.getBoundingClientRect().height; if (height == 0) { continue;
} if (event.screenY <= elt.screenY + height / 2) { break;
}
}
newMarginTop = elt
? elt.screenY - this.scrollBox.screenY
: scrollRect.height;
} elseif (scrollDir == 1) {
newMarginTop = scrollRect.height;
}
// Set the new marginTop based on arrowscrollbox.
newMarginTop +=
scrollRect.y - this._indicatorBar.parentNode.getBoundingClientRect().y; this._indicatorBar.firstElementChild.style.marginTop =
newMarginTop + "px"; this._indicatorBar.hidden = false;
// 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
);
}
_setSideAttribute(event) { if (!this.anchorNode) { return;
}
var position = event.alignmentPosition; if (position.indexOf("start_") == 0 || position.indexOf("end_") == 0) { // The assigned side stays the same regardless of direction.
let isRTL = this.matches(":-moz-locale-dir(rtl)");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.