|
|
|
@ -1,4 +1,4 @@
|
|
|
|
|
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ |
|
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
|
|
|
/* vim: set ts=2 et sw=2 tw=80: */ |
|
|
|
|
/* 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, |
|
|
|
@ -47,7 +47,8 @@ const DownloadsButton = {
|
|
|
|
|
* Returns a reference to the downloads button position placeholder, or null |
|
|
|
|
* if not available because it has been removed from the toolbars. |
|
|
|
|
*/ |
|
|
|
|
get _placeholder() { |
|
|
|
|
get _placeholder() |
|
|
|
|
{ |
|
|
|
|
return document.getElementById("downloads-button"); |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
@ -55,10 +56,12 @@ const DownloadsButton = {
|
|
|
|
|
* This function is called asynchronously just after window initialization. |
|
|
|
|
* |
|
|
|
|
* NOTE: This function should limit the input/output it performs to improve |
|
|
|
|
* startup time. |
|
|
|
|
* startup time, and in particular should not cause the Download Manager |
|
|
|
|
* service to start. |
|
|
|
|
*/ |
|
|
|
|
initializeIndicator() { |
|
|
|
|
DownloadsIndicatorView.ensureInitialized(); |
|
|
|
|
initializeIndicator: function DB_initializeIndicator() |
|
|
|
|
{ |
|
|
|
|
this._update(); |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -74,19 +77,65 @@ const DownloadsButton = {
|
|
|
|
|
* placeholder is an ordinary button defined in the browser window that can be |
|
|
|
|
* moved freely between the toolbars and the customization palette. |
|
|
|
|
*/ |
|
|
|
|
customizeStart() { |
|
|
|
|
// Prevent the indicator from being displayed as a temporary anchor
|
|
|
|
|
customizeStart: function DB_customizeStart() |
|
|
|
|
{ |
|
|
|
|
// Hide the indicator and prevent it to be displayed as a temporary anchor
|
|
|
|
|
// during customization, even if requested using the getAnchor method.
|
|
|
|
|
this._customizing = true; |
|
|
|
|
this._anchorRequested = false; |
|
|
|
|
|
|
|
|
|
let indicator = DownloadsIndicatorView.indicator; |
|
|
|
|
if (indicator) { |
|
|
|
|
indicator.collapsed = true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let placeholder = this._placeholder; |
|
|
|
|
if (placeholder) { |
|
|
|
|
placeholder.collapsed = false; |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* This function is called when toolbar customization ends. |
|
|
|
|
*/ |
|
|
|
|
customizeDone() { |
|
|
|
|
customizeDone: function DB_customizeDone() |
|
|
|
|
{ |
|
|
|
|
this._customizing = false; |
|
|
|
|
DownloadsIndicatorView.afterCustomize(); |
|
|
|
|
this._update(); |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* This function is called during initialization or when toolbar customization |
|
|
|
|
* ends. It determines if we should enable or disable the object that keeps |
|
|
|
|
* the indicator updated, and ensures that the placeholder is hidden unless it |
|
|
|
|
* has been moved to the customization palette. |
|
|
|
|
* |
|
|
|
|
* NOTE: This function is also called on startup, thus it should limit the |
|
|
|
|
* input/output it performs, and in particular should not cause the |
|
|
|
|
* Download Manager service to start. |
|
|
|
|
*/ |
|
|
|
|
_update: function DB_update() { |
|
|
|
|
this._updatePositionInternal(); |
|
|
|
|
|
|
|
|
|
if (!DownloadsCommon.useToolkitUI) { |
|
|
|
|
DownloadsIndicatorView.ensureInitialized(); |
|
|
|
|
} else { |
|
|
|
|
DownloadsIndicatorView.ensureTerminated(); |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Determines the position where the indicator should appear, and moves its |
|
|
|
|
* associated element to the new position. This does not happen if the |
|
|
|
|
* indicator is currently being used as the anchor for the panel, to ensure |
|
|
|
|
* that the panel doesn't flicker because we move the DOM element to which |
|
|
|
|
* it's anchored. |
|
|
|
|
*/ |
|
|
|
|
updatePosition: function DB_updatePosition() |
|
|
|
|
{ |
|
|
|
|
if (!this._anchorRequested) { |
|
|
|
|
this._updatePositionInternal(); |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -95,22 +144,37 @@ const DownloadsButton = {
|
|
|
|
|
* |
|
|
|
|
* @return Anchor element, or null if the indicator is not visible. |
|
|
|
|
*/ |
|
|
|
|
_getAnchorInternal() { |
|
|
|
|
_updatePositionInternal: function DB_updatePositionInternal() |
|
|
|
|
{ |
|
|
|
|
let indicator = DownloadsIndicatorView.indicator; |
|
|
|
|
if (!indicator) { |
|
|
|
|
// Exit now if the indicator overlay isn't loaded yet, or if the button
|
|
|
|
|
// is not in the document.
|
|
|
|
|
// Exit now if the indicator overlay isn't loaded yet.
|
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let placeholder = this._placeholder; |
|
|
|
|
if (!placeholder) { |
|
|
|
|
// The placeholder has been removed from the browser window.
|
|
|
|
|
indicator.collapsed = true; |
|
|
|
|
// Move the indicator to a safe position on the toolbar, since otherwise
|
|
|
|
|
// it may break the merge of adjacent items, like back/forward + urlbar.
|
|
|
|
|
indicator.parentNode.appendChild(indicator); |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Position the indicator where the placeholder is located. We should
|
|
|
|
|
// update the position even if the placeholder is located on an invisible
|
|
|
|
|
// toolbar, because the toolbar may be displayed later.
|
|
|
|
|
placeholder.parentNode.insertBefore(indicator, placeholder); |
|
|
|
|
placeholder.collapsed = true; |
|
|
|
|
indicator.collapsed = false; |
|
|
|
|
|
|
|
|
|
indicator.open = this._anchorRequested; |
|
|
|
|
|
|
|
|
|
let widget = CustomizableUI.getWidget("downloads-button") |
|
|
|
|
.forWindow(window); |
|
|
|
|
// Determine if the indicator is located on an invisible toolbar.
|
|
|
|
|
if (!isElementVisible(indicator.parentNode) && !widget.overflowed) { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
// Determine if the placeholder is located on an invisible toolbar.
|
|
|
|
|
if (!isElementVisible(placeholder.parentNode)) { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return DownloadsIndicatorView.indicatorAnchor; |
|
|
|
|
}, |
|
|
|
@ -123,15 +187,18 @@ const DownloadsButton = {
|
|
|
|
|
* Called once the indicator overlay has loaded. Gets a boolean |
|
|
|
|
* argument representing the indicator visibility. |
|
|
|
|
*/ |
|
|
|
|
checkIsVisible(aCallback) { |
|
|
|
|
DownloadsOverlayLoader.ensureOverlayLoaded(this.kIndicatorOverlay, () => { |
|
|
|
|
checkIsVisible: function DB_checkIsVisible(aCallback) |
|
|
|
|
{ |
|
|
|
|
function DB_CEV_callback() { |
|
|
|
|
if (!this._placeholder) { |
|
|
|
|
aCallback(false); |
|
|
|
|
} else { |
|
|
|
|
let element = DownloadsIndicatorView.indicator || this._placeholder; |
|
|
|
|
aCallback(isElementVisible(element.parentNode)); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
DownloadsOverlayLoader.ensureOverlayLoaded(this.kIndicatorOverlay, |
|
|
|
|
DB_CEV_callback.bind(this)); |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -148,33 +215,40 @@ const DownloadsButton = {
|
|
|
|
|
* panel should be anchored, or null if an anchor is not available (for |
|
|
|
|
* example because both the tab bar and the navigation bar are hidden). |
|
|
|
|
*/ |
|
|
|
|
getAnchor(aCallback) { |
|
|
|
|
getAnchor: function DB_getAnchor(aCallback) |
|
|
|
|
{ |
|
|
|
|
// Do not allow anchoring the panel to the element while customizing.
|
|
|
|
|
if (this._customizing) { |
|
|
|
|
aCallback(null); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
DownloadsOverlayLoader.ensureOverlayLoaded(this.kIndicatorOverlay, () => { |
|
|
|
|
function DB_GA_callback() { |
|
|
|
|
this._anchorRequested = true; |
|
|
|
|
aCallback(this._getAnchorInternal()); |
|
|
|
|
}); |
|
|
|
|
aCallback(this._updatePositionInternal()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
DownloadsOverlayLoader.ensureOverlayLoaded(this.kIndicatorOverlay, |
|
|
|
|
DB_GA_callback.bind(this)); |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Allows the temporary anchor to be hidden. |
|
|
|
|
*/ |
|
|
|
|
releaseAnchor() { |
|
|
|
|
releaseAnchor: function DB_releaseAnchor() |
|
|
|
|
{ |
|
|
|
|
this._anchorRequested = false; |
|
|
|
|
this._getAnchorInternal(); |
|
|
|
|
this._updatePositionInternal(); |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
get _tabsToolbar() { |
|
|
|
|
get _tabsToolbar() |
|
|
|
|
{ |
|
|
|
|
delete this._tabsToolbar; |
|
|
|
|
return this._tabsToolbar = document.getElementById("TabsToolbar"); |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
get _navBar() { |
|
|
|
|
get _navBar() |
|
|
|
|
{ |
|
|
|
|
delete this._navBar; |
|
|
|
|
return this._navBar = document.getElementById("nav-bar"); |
|
|
|
|
} |
|
|
|
@ -204,7 +278,8 @@ const DownloadsIndicatorView = {
|
|
|
|
|
/** |
|
|
|
|
* Prepares the downloads indicator to be displayed. |
|
|
|
|
*/ |
|
|
|
|
ensureInitialized() { |
|
|
|
|
ensureInitialized: function DIV_ensureInitialized() |
|
|
|
|
{ |
|
|
|
|
if (this._initialized) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -217,7 +292,8 @@ const DownloadsIndicatorView = {
|
|
|
|
|
/** |
|
|
|
|
* Frees the internal resources related to the indicator. |
|
|
|
|
*/ |
|
|
|
|
ensureTerminated() { |
|
|
|
|
ensureTerminated: function DIV_ensureTerminated() |
|
|
|
|
{ |
|
|
|
|
if (!this._initialized) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -238,35 +314,28 @@ const DownloadsIndicatorView = {
|
|
|
|
|
* Ensures that the user interface elements required to display the indicator |
|
|
|
|
* are loaded, then invokes the given callback. |
|
|
|
|
*/ |
|
|
|
|
_ensureOperational(aCallback) { |
|
|
|
|
_ensureOperational: function DIV_ensureOperational(aCallback) |
|
|
|
|
{ |
|
|
|
|
if (this._operational) { |
|
|
|
|
if (aCallback) { |
|
|
|
|
aCallback(); |
|
|
|
|
} |
|
|
|
|
aCallback(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// If we don't have a _placeholder, there's no chance that the overlay
|
|
|
|
|
// will load correctly: bail (and don't set _operational to true!)
|
|
|
|
|
if (!DownloadsButton._placeholder) { |
|
|
|
|
return; |
|
|
|
|
function DIV_EO_callback() { |
|
|
|
|
this._operational = true; |
|
|
|
|
|
|
|
|
|
// If the view is initialized, we need to update the elements now that
|
|
|
|
|
// they are finally available in the document.
|
|
|
|
|
if (this._initialized) { |
|
|
|
|
DownloadsCommon.getIndicatorData(window).refreshView(this); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
aCallback(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
DownloadsOverlayLoader.ensureOverlayLoaded( |
|
|
|
|
DownloadsButton.kIndicatorOverlay, |
|
|
|
|
() => { |
|
|
|
|
this._operational = true; |
|
|
|
|
|
|
|
|
|
// If the view is initialized, we need to update the elements now that
|
|
|
|
|
// they are finally available in the document.
|
|
|
|
|
if (this._initialized) { |
|
|
|
|
DownloadsCommon.getIndicatorData(window).refreshView(this); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (aCallback) { |
|
|
|
|
aCallback(); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
DownloadsButton.kIndicatorOverlay, |
|
|
|
|
DIV_EO_callback.bind(this)); |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
@ -277,18 +346,6 @@ const DownloadsIndicatorView = {
|
|
|
|
|
*/ |
|
|
|
|
_notificationTimeout: null, |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Check if the panel containing aNode is open. |
|
|
|
|
* @param aNode |
|
|
|
|
* the node whose panel we're interested in. |
|
|
|
|
*/ |
|
|
|
|
_isAncestorPanelOpen(aNode) { |
|
|
|
|
while (aNode && aNode.localName != "panel") { |
|
|
|
|
aNode = aNode.parentNode; |
|
|
|
|
} |
|
|
|
|
return aNode && aNode.state == "open"; |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* If the status indicator is visible in its assigned position, shows for a |
|
|
|
|
* brief time a visual notification of a relevant event, like a new download. |
|
|
|
@ -296,7 +353,8 @@ const DownloadsIndicatorView = {
|
|
|
|
|
* @param aType |
|
|
|
|
* Set to "start" for new downloads, "finish" for completed downloads. |
|
|
|
|
*/ |
|
|
|
|
showEventNotification(aType) { |
|
|
|
|
showEventNotification: function DIV_showEventNotification(aType) |
|
|
|
|
{ |
|
|
|
|
if (!this._initialized) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -310,51 +368,22 @@ const DownloadsIndicatorView = {
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let anchor = DownloadsButton._placeholder; |
|
|
|
|
let widgetGroup = CustomizableUI.getWidget("downloads-button"); |
|
|
|
|
let widget = widgetGroup.forWindow(window); |
|
|
|
|
if (widget.overflowed || widgetGroup.areaType == CustomizableUI.TYPE_MENU_PANEL) { |
|
|
|
|
if (anchor && this._isAncestorPanelOpen(anchor)) { |
|
|
|
|
// If the containing panel is open, don't do anything, because the
|
|
|
|
|
// notification would appear under the open panel. See
|
|
|
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=984023
|
|
|
|
|
return; |
|
|
|
|
function DIV_SEN_callback() { |
|
|
|
|
if (this._notificationTimeout) { |
|
|
|
|
clearTimeout(this._notificationTimeout); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Otherwise, try to use the anchor of the panel:
|
|
|
|
|
anchor = widget.anchor; |
|
|
|
|
} |
|
|
|
|
if (!anchor || !isElementVisible(anchor.parentNode)) { |
|
|
|
|
// Our container isn't visible, so can't show the animation:
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
// Now that the overlay is loaded, place the indicator in its final
|
|
|
|
|
// position.
|
|
|
|
|
DownloadsButton.updatePosition(); |
|
|
|
|
|
|
|
|
|
if (this._notificationTimeout) { |
|
|
|
|
clearTimeout(this._notificationTimeout); |
|
|
|
|
let indicator = this.indicator; |
|
|
|
|
indicator.setAttribute("notification", aType); |
|
|
|
|
this._notificationTimeout = setTimeout( |
|
|
|
|
function () indicator.removeAttribute("notification"), 1000); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// The notification element is positioned to show in the same location as
|
|
|
|
|
// the downloads button. It's not in the downloads button itself in order to
|
|
|
|
|
// be able to anchor the notification elsewhere if required, and to ensure
|
|
|
|
|
// the notification isn't clipped by overflow properties of the anchor's
|
|
|
|
|
// container.
|
|
|
|
|
let notifier = this.notifier; |
|
|
|
|
if (notifier.style.transform == '') { |
|
|
|
|
let anchorRect = anchor.getBoundingClientRect(); |
|
|
|
|
let notifierRect = notifier.getBoundingClientRect(); |
|
|
|
|
let topDiff = anchorRect.top - notifierRect.top; |
|
|
|
|
let leftDiff = anchorRect.left - notifierRect.left; |
|
|
|
|
let heightDiff = anchorRect.height - notifierRect.height; |
|
|
|
|
let widthDiff = anchorRect.width - notifierRect.width; |
|
|
|
|
let translateX = (leftDiff + .5 * widthDiff) + "px"; |
|
|
|
|
let translateY = (topDiff + .5 * heightDiff) + "px"; |
|
|
|
|
notifier.style.transform = "translate(" + translateX + ", " + translateY + ")"; |
|
|
|
|
} |
|
|
|
|
notifier.setAttribute("notification", aType); |
|
|
|
|
this._notificationTimeout = setTimeout(() => { |
|
|
|
|
notifier.removeAttribute("notification"); |
|
|
|
|
notifier.style.transform = ''; |
|
|
|
|
}, 1000); |
|
|
|
|
this._ensureOperational(DIV_SEN_callback.bind(this)); |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
@ -364,18 +393,23 @@ const DownloadsIndicatorView = {
|
|
|
|
|
* Indicates whether the indicator should be shown because there are some |
|
|
|
|
* downloads to be displayed. |
|
|
|
|
*/ |
|
|
|
|
set hasDownloads(aValue) { |
|
|
|
|
if (this._hasDownloads != aValue || (!this._operational && aValue)) { |
|
|
|
|
set hasDownloads(aValue) |
|
|
|
|
{ |
|
|
|
|
if (this._hasDownloads != aValue) { |
|
|
|
|
this._hasDownloads = aValue; |
|
|
|
|
|
|
|
|
|
// If there is at least one download, ensure that the view elements are
|
|
|
|
|
// loaded before determining the position of the downloads button.
|
|
|
|
|
if (aValue) { |
|
|
|
|
this._ensureOperational(); |
|
|
|
|
this._ensureOperational(function() DownloadsButton.updatePosition()); |
|
|
|
|
} else { |
|
|
|
|
DownloadsButton.updatePosition(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return aValue; |
|
|
|
|
}, |
|
|
|
|
get hasDownloads() { |
|
|
|
|
get hasDownloads() |
|
|
|
|
{ |
|
|
|
|
return this._hasDownloads; |
|
|
|
|
}, |
|
|
|
|
_hasDownloads: false, |
|
|
|
@ -384,7 +418,8 @@ const DownloadsIndicatorView = {
|
|
|
|
|
* Status text displayed in the indicator. If this is set to an empty value, |
|
|
|
|
* then the small downloads icon is displayed instead of the text. |
|
|
|
|
*/ |
|
|
|
|
set counter(aValue) { |
|
|
|
|
set counter(aValue) |
|
|
|
|
{ |
|
|
|
|
if (!this._operational) { |
|
|
|
|
return this._counter; |
|
|
|
|
} |
|
|
|
@ -408,7 +443,8 @@ const DownloadsIndicatorView = {
|
|
|
|
|
* progress bar is hidden if the current progress is unknown and no status |
|
|
|
|
* text is set in the "counter" property. |
|
|
|
|
*/ |
|
|
|
|
set percentComplete(aValue) { |
|
|
|
|
set percentComplete(aValue) |
|
|
|
|
{ |
|
|
|
|
if (!this._operational) { |
|
|
|
|
return this._percentComplete; |
|
|
|
|
} |
|
|
|
@ -432,7 +468,8 @@ const DownloadsIndicatorView = {
|
|
|
|
|
* Setting this property forces a paused progress bar to be displayed, even if |
|
|
|
|
* the current progress information is unavailable. |
|
|
|
|
*/ |
|
|
|
|
set paused(aValue) { |
|
|
|
|
set paused(aValue) |
|
|
|
|
{ |
|
|
|
|
if (!this._operational) { |
|
|
|
|
return this._paused; |
|
|
|
|
} |
|
|
|
@ -452,7 +489,8 @@ const DownloadsIndicatorView = {
|
|
|
|
|
/** |
|
|
|
|
* Set when the indicator should draw user attention to itself. |
|
|
|
|
*/ |
|
|
|
|
set attention(aValue) { |
|
|
|
|
set attention(aValue) |
|
|
|
|
{ |
|
|
|
|
if (!this._operational) { |
|
|
|
|
return this._attention; |
|
|
|
|
} |
|
|
|
@ -472,16 +510,18 @@ const DownloadsIndicatorView = {
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//// User interface event functions
|
|
|
|
|
|
|
|
|
|
onWindowUnload() { |
|
|
|
|
onWindowUnload: function DIV_onWindowUnload() |
|
|
|
|
{ |
|
|
|
|
// This function is registered as an event listener, we can't use "this".
|
|
|
|
|
DownloadsIndicatorView.ensureTerminated(); |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
onCommand(aEvent) { |
|
|
|
|
// If the downloads button is in the menu panel, open the Library
|
|
|
|
|
let widgetGroup = CustomizableUI.getWidget("downloads-button"); |
|
|
|
|
if (widgetGroup.areaType == CustomizableUI.TYPE_MENU_PANEL) { |
|
|
|
|
DownloadsPanel.showDownloadsHistory(); |
|
|
|
|
onCommand: function DIV_onCommand(aEvent) |
|
|
|
|
{ |
|
|
|
|
if (DownloadsCommon.useToolkitUI) { |
|
|
|
|
// The panel won't suppress attention for us, we need to clear now.
|
|
|
|
|
DownloadsCommon.getIndicatorData(window).attention = false; |
|
|
|
|
BrowserDownloadsUI(); |
|
|
|
|
} else { |
|
|
|
|
DownloadsPanel.showPanel(); |
|
|
|
|
} |
|
|
|
@ -489,11 +529,13 @@ const DownloadsIndicatorView = {
|
|
|
|
|
aEvent.stopPropagation(); |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
onDragOver(aEvent) { |
|
|
|
|
onDragOver: function DIV_onDragOver(aEvent) |
|
|
|
|
{ |
|
|
|
|
browserDragAndDrop.dragOver(aEvent); |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
onDrop(aEvent) { |
|
|
|
|
onDrop: function DIV_onDrop(aEvent) |
|
|
|
|
{ |
|
|
|
|
let dt = aEvent.dataTransfer; |
|
|
|
|
// If dragged item is from our source, do not try to
|
|
|
|
|
// redownload already downloaded file.
|
|
|
|
@ -513,66 +555,40 @@ const DownloadsIndicatorView = {
|
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
_indicator: null, |
|
|
|
|
__indicatorCounter: null, |
|
|
|
|
__indicatorProgress: null, |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Returns a reference to the main indicator element, or null if the element |
|
|
|
|
* is not present in the browser window yet. |
|
|
|
|
*/ |
|
|
|
|
get indicator() { |
|
|
|
|
if (this._indicator) { |
|
|
|
|
return this._indicator; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let indicator = document.getElementById("downloads-button"); |
|
|
|
|
if (!indicator || indicator.getAttribute("indicator") != "true") { |
|
|
|
|
get indicator() |
|
|
|
|
{ |
|
|
|
|
let indicator = document.getElementById("downloads-indicator"); |
|
|
|
|
if (!indicator) { |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return this._indicator = indicator; |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
get indicatorAnchor() { |
|
|
|
|
let widget = CustomizableUI.getWidget("downloads-button") |
|
|
|
|
.forWindow(window); |
|
|
|
|
if (widget.overflowed) { |
|
|
|
|
return widget.anchor; |
|
|
|
|
} |
|
|
|
|
return document.getElementById("downloads-indicator-anchor"); |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
get _indicatorCounter() { |
|
|
|
|
return this.__indicatorCounter || |
|
|
|
|
(this.__indicatorCounter = document.getElementById("downloads-indicator-counter")); |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
get _indicatorProgress() { |
|
|
|
|
return this.__indicatorProgress || |
|
|
|
|
(this.__indicatorProgress = document.getElementById("downloads-indicator-progress")); |
|
|
|
|
// Once the element is loaded, it will never be unloaded.
|
|
|
|
|
delete this.indicator; |
|
|
|
|
return this.indicator = indicator; |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
get notifier() { |
|
|
|
|
return this._notifier || |
|
|
|
|
(this._notifier = document.getElementById("downloads-notification-anchor")); |
|
|
|
|
get indicatorAnchor() |
|
|
|
|
{ |
|
|
|
|
delete this.indicatorAnchor; |
|
|
|
|
return this.indicatorAnchor = |
|
|
|
|
document.getElementById("downloads-indicator-anchor"); |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
_onCustomizedAway() { |
|
|
|
|
this._indicator = null; |
|
|
|
|
this.__indicatorCounter = null; |
|
|
|
|
this.__indicatorProgress = null; |
|
|
|
|
get _indicatorCounter() |
|
|
|
|
{ |
|
|
|
|
delete this._indicatorCounter; |
|
|
|
|
return this._indicatorCounter = |
|
|
|
|
document.getElementById("downloads-indicator-counter"); |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
afterCustomize() { |
|
|
|
|
// If the cached indicator is not the one currently in the document,
|
|
|
|
|
// invalidate our references
|
|
|
|
|
if (this._indicator != document.getElementById("downloads-button")) { |
|
|
|
|
this._onCustomizedAway(); |
|
|
|
|
this._operational = false; |
|
|
|
|
this.ensureTerminated(); |
|
|
|
|
this.ensureInitialized(); |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
get _indicatorProgress() |
|
|
|
|
{ |
|
|
|
|
delete this._indicatorProgress; |
|
|
|
|
return this._indicatorProgress = |
|
|
|
|
document.getElementById("downloads-indicator-progress"); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|