--- a/mail/components/compose/content/MsgComposeCommands.js
+++ b/mail/components/compose/content/MsgComposeCommands.js
@@ -97,17 +97,17 @@ var gCurrentIdentity;
var defaultSaveOperation;
var gSendOperationInProgress;
var gSaveOperationInProgress;
var gCloseWindowAfterSave;
var gSavedSendNowKey;
var gSendFormat;
var gContextMenu;
-var gMsgAttachmentElement;
+var gAttachmentBucket;
var gMsgHeadersToolbarElement;
// TODO: Maybe the following two variables can be combined.
var gManualAttachmentReminder;
var gDisableAttachmentReminder;
var gComposeType;
var gLanguageObserver;
var gBodyFromArgs;
@@ -890,36 +890,36 @@ var defaultController = {
// Note: We cannot pass event along the call chain: Bug 461578 / 959494.
// eslint-disable-next-line no-restricted-globals
toggleAttachmentPane("toggle", event);
},
},
cmd_reorderAttachments: {
isEnabled() {
- if (attachmentsCount() == 0) {
+ if (!gAttachmentBucket.itemCount) {
let reorderAttachmentsPanel = document.getElementById(
"reorderAttachmentsPanel"
);
if (reorderAttachmentsPanel.state == "open") {
// When the panel is open and all attachments get deleted,
// we get notified here and want to close the panel.
reorderAttachmentsPanel.hidePopup();
}
}
- return attachmentsCount() > 1;
+ return gAttachmentBucket.itemCount > 1;
},
doCommand() {
showReorderAttachmentsPanel();
},
},
cmd_removeAllAttachments: {
isEnabled() {
- return !gWindowLocked && attachmentsCount() > 0;
+ return !gWindowLocked && gAttachmentBucket.itemCount;
},
doCommand() {
RemoveAllAttachments();
},
},
cmd_close: {
isEnabled() {
@@ -1178,136 +1178,138 @@ var defaultController = {
var attachmentBucketController = {
commands: {
cmd_selectAll: {
isEnabled() {
return true;
},
doCommand() {
- document.getElementById("attachmentBucket").selectAll();
+ gAttachmentBucket.selectAll();
},
},
cmd_delete: {
isEnabled() {
- let selectedCount = attachmentsSelectedCount();
let cmdDelete = document.getElementById("cmd_delete");
let textValue = getComposeBundle().getString("removeAttachmentMsgs");
- textValue = PluralForm.get(selectedCount, textValue);
+ textValue = PluralForm.get(gAttachmentBucket.selectedCount, textValue);
let accesskeyValue = cmdDelete.getAttribute(
"valueRemoveAttachmentAccessKey"
);
cmdDelete.setAttribute("label", textValue);
cmdDelete.setAttribute("accesskey", accesskeyValue);
- return selectedCount > 0;
+ return gAttachmentBucket.selectedCount;
},
doCommand() {
RemoveSelectedAttachment();
},
},
cmd_openAttachment: {
isEnabled() {
- return attachmentsSelectedCount() == 1;
+ return gAttachmentBucket.selectedCount == 1;
},
doCommand() {
OpenSelectedAttachment();
},
},
cmd_renameAttachment: {
isEnabled() {
- return attachmentsSelectedCount() == 1;
+ return gAttachmentBucket.selectedCount == 1;
},
doCommand() {
RenameSelectedAttachment();
},
},
cmd_moveAttachmentUp: {
isEnabled() {
return (
- attachmentsSelectedCount() > 0 && !attachmentsSelectionIsBlock("top")
+ gAttachmentBucket.selectedCount && !attachmentsSelectionIsBlock("top")
);
},
doCommand() {
moveSelectedAttachments("up");
},
},
cmd_moveAttachmentDown: {
isEnabled() {
return (
- attachmentsSelectedCount() > 0 &&
+ gAttachmentBucket.selectedCount &&
!attachmentsSelectionIsBlock("bottom")
);
},
doCommand() {
moveSelectedAttachments("down");
},
},
cmd_moveAttachmentBundleUp: {
isEnabled() {
- return attachmentsSelectedCount() > 1 && !attachmentsSelectionIsBlock();
+ return (
+ gAttachmentBucket.selectedCount > 1 && !attachmentsSelectionIsBlock()
+ );
},
doCommand() {
moveSelectedAttachments("bundleUp");
},
},
cmd_moveAttachmentBundleDown: {
isEnabled() {
- return attachmentsSelectedCount() > 1 && !attachmentsSelectionIsBlock();
+ return (
+ gAttachmentBucket.selectedCount > 1 && !attachmentsSelectionIsBlock()
+ );
},
doCommand() {
moveSelectedAttachments("bundleDown");
},
},
cmd_moveAttachmentTop: {
isEnabled() {
return (
- attachmentsSelectedCount() > 0 && !attachmentsSelectionIsBlock("top")
+ gAttachmentBucket.selectedCount && !attachmentsSelectionIsBlock("top")
);
},
doCommand() {
moveSelectedAttachments("top");
},
},
cmd_moveAttachmentBottom: {
isEnabled() {
return (
- attachmentsSelectedCount() > 0 &&
+ gAttachmentBucket.selectedCount &&
!attachmentsSelectionIsBlock("bottom")
);
},
doCommand() {
moveSelectedAttachments("bottom");
},
},
cmd_sortAttachmentsToggle: {
isEnabled() {
- let attachmentsSelCount = attachmentsSelectedCount();
let sortSelection;
let currSortOrder;
let isBlock;
let btnAscending;
let toggleCmd = document.getElementById("cmd_sortAttachmentsToggle");
let toggleBtn = document.getElementById("btn_sortAttachmentsToggle");
let sortDirection;
let btnLabelAttr;
if (
- attachmentsSelCount > 1 &&
- attachmentsSelCount < attachmentsCount()
+ gAttachmentBucket.selectedCount > 1 &&
+ gAttachmentBucket.selectedCount < gAttachmentBucket.itemCount
) {
// Sort selected attachments only, which needs at least 2 of them,
// but not all.
sortSelection = true;
currSortOrder = attachmentsSelectionGetSortOrder();
isBlock = attachmentsSelectionIsBlock();
// If current sorting is ascending AND it's a block; OR
// if current sorting is descending AND it's NOT a block yet:
@@ -1321,17 +1323,17 @@ var attachmentBucketController = {
if (btnAscending) {
sortDirection = "ascending";
btnLabelAttr = "label-selection-AZ";
} else {
sortDirection = "descending";
btnLabelAttr = "label-selection-ZA";
}
} else {
- // attachmentsSelectedCount() <= 1 or all attachments selected
+ // gAttachmentBucket.selectedCount <= 1 or all attachments are selected.
// Sort all attachments.
sortSelection = false;
currSortOrder = attachmentsGetSortOrder();
btnAscending = !(currSortOrder == "ascending");
// Set sortDirection for toggleCmd, and respective button face.
if (btnAscending) {
sortDirection = "ascending";
btnLabelAttr = "label-AZ";
@@ -1365,18 +1367,17 @@ var attachmentBucketController = {
cmd.hidden =
!Services.prefs.getBoolPref("mail.cloud_files.enabled") ||
cloudFileAccounts.configuredAccounts.length == 0 ||
Services.io.offline;
if (cmd.hidden) {
return false;
}
- let bucket = document.getElementById("attachmentBucket");
- for (let item of bucket.selectedItems) {
+ for (let item of gAttachmentBucket.selectedItems) {
if (item.uploading) {
return false;
}
if (item.cloudFileUpload && item.cloudFileUpload.repeat) {
return false;
}
}
return true;
@@ -1388,18 +1389,17 @@ var attachmentBucketController = {
},
cmd_convertAttachment: {
isEnabled() {
if (!Services.prefs.getBoolPref("mail.cloud_files.enabled")) {
return false;
}
- let bucket = document.getElementById("attachmentBucket");
- for (let item of bucket.selectedItems) {
+ for (let item of gAttachmentBucket.selectedItems) {
if (item.uploading) {
return false;
}
if (item.cloudFileUpload && item.cloudFileUpload.repeat) {
return false;
}
}
return true;
@@ -1416,18 +1416,17 @@ var attachmentBucketController = {
);
// If Filelink is disabled, hide this menuitem and bailout.
if (!Services.prefs.getBoolPref("mail.cloud_files.enabled")) {
cmd.hidden = true;
return false;
}
- let bucket = document.getElementById("attachmentBucket");
- for (let item of bucket.selectedItems) {
+ for (let item of gAttachmentBucket.selectedItems) {
if (item && item.uploading) {
cmd.hidden = false;
return true;
}
}
// Hide the command entirely if the selected attachments aren't cloud
// files.
@@ -1436,18 +1435,17 @@ var attachmentBucketController = {
cmd.hidden = true;
return false;
},
doCommand() {
let fileHandler = Services.io
.getProtocolHandler("file")
.QueryInterface(Ci.nsIFileProtocolHandler);
- let bucket = document.getElementById("attachmentBucket");
- for (let item of bucket.selectedItems) {
+ for (let item of gAttachmentBucket.selectedItems) {
if (item && item.uploading) {
let file = fileHandler.getFileFromURLSpec(item.attachment.url);
item.cloudFileAccount.cancelFileUpload(file);
}
}
},
},
},
@@ -1510,34 +1508,30 @@ function QuoteSelectedMessage() {
}
function GetSelectedMessages() {
let mailWindow = Services.wm.getMostRecentWindow("mail:3pane");
return mailWindow ? mailWindow.gFolderDisplay.selectedMessageUris : null;
}
function SetupCommandUpdateHandlers() {
- let attachmentBucket = document.getElementById("attachmentBucket");
-
top.controllers.appendController(defaultController);
- attachmentBucket.controllers.appendController(attachmentBucketController);
+ gAttachmentBucket.controllers.appendController(attachmentBucketController);
document
.getElementById("optionsMenuPopup")
.addEventListener("popupshowing", updateOptionItems, true);
}
function UnloadCommandUpdateHandlers() {
- let attachmentBucket = document.getElementById("attachmentBucket");
-
document
.getElementById("optionsMenuPopup")
.removeEventListener("popupshowing", updateOptionItems, true);
- attachmentBucket.controllers.removeController(attachmentBucketController);
+ gAttachmentBucket.controllers.removeController(attachmentBucketController);
top.controllers.removeController(defaultController);
}
function CommandUpdate_MsgCompose() {
var focusedWindow = top.document.commandDispatcher.focusedWindow;
// we're just setting focus to where it was before
if (focusedWindow == gLastWindowToHaveFocus) {
@@ -2074,40 +2068,40 @@ function addAttachCloudMenuItems(aParent
fileItem.setAttribute("class", "menuitem-iconic");
fileItem.setAttribute("image", "moz-icon://" + file.leafName);
aParentMenu.appendChild(fileItem);
}
}
}
function addConvertCloudMenuItems(aParentMenu, aAfterNodeId, aRadioGroup) {
- let attachment = document.getElementById("attachmentBucket").selectedItem;
let afterNode = document.getElementById(aAfterNodeId);
while (afterNode.nextElementSibling) {
afterNode.nextElementSibling.remove();
}
- if (!attachment.sendViaCloud) {
+ if (!gAttachmentBucket.selectedItem.sendViaCloud) {
let item = document.getElementById(
"convertCloudMenuItems_popup_convertAttachment"
);
item.setAttribute("checked", "true");
}
for (let account of cloudFileAccounts.configuredAccounts) {
let item = document.createXULElement("menuitem");
let iconURL = account.iconURL;
item.cloudFileAccount = account;
item.setAttribute("label", cloudFileAccounts.getDisplayName(account));
item.setAttribute("type", "radio");
item.setAttribute("name", aRadioGroup);
if (
- attachment.cloudFileAccount &&
- attachment.cloudFileAccount.accountKey == account.accountKey
+ gAttachmentBucket.selectedItem.cloudFileAccount &&
+ gAttachmentBucket.selectedItem.cloudFileAccount.accountKey ==
+ account.accountKey
) {
item.setAttribute("checked", "true");
} else if (iconURL) {
item.setAttribute("class", "menu-iconic");
item.setAttribute("image", iconURL);
}
aParentMenu.appendChild(item);
@@ -2117,18 +2111,17 @@ function addConvertCloudMenuItems(aParen
async function uploadCloudAttachment(attachment, file, cloudFileAccount) {
// Notify the UI that we're starting the upload process: disable send commands
// and show a "connecting" icon for the attachment.
attachment.sendViaCloud = true;
gNumUploadingAttachments++;
updateSendCommands(true);
let displayName = cloudFileAccounts.getDisplayName(cloudFileAccount);
- let bucket = document.getElementById("attachmentBucket");
- let attachmentItem = bucket.findItemForAttachment(attachment);
+ let attachmentItem = gAttachmentBucket.findItemForAttachment(attachment);
if (attachmentItem) {
let itemIcon = attachmentItem.querySelector(".attachmentcell-icon");
itemIcon.setAttribute("src", "chrome://global/skin/icons/loading.png");
attachmentItem.setAttribute(
"tooltiptext",
getComposeBundle().getFormattedString("cloudFileUploadingTooltip", [
displayName,
])
@@ -2444,31 +2437,32 @@ function convertListItemsToCloudAttachme
}
/**
* Convert the selected attachments to cloud attachments.
*
* @param aAccount the cloud account to upload the files to
*/
function convertSelectedToCloudAttachment(aAccount) {
- let bucket = document.getElementById("attachmentBucket");
- convertListItemsToCloudAttachment([...bucket.selectedItems], aAccount);
+ convertListItemsToCloudAttachment(
+ [...gAttachmentBucket.selectedItems],
+ aAccount
+ );
}
/**
* Convert an array of nsIMsgAttachments to cloud attachments.
*
* @param aAttachments an array of nsIMsgAttachments
* @param aAccount the cloud account to upload the files to
*/
function convertToCloudAttachment(aAttachments, aAccount) {
- let bucket = document.getElementById("attachmentBucket");
let items = [];
for (let attachment of aAttachments) {
- let item = bucket.findItemForAttachment(attachment);
+ let item = gAttachmentBucket.findItemForAttachment(attachment);
if (item) {
items.push(item);
}
}
convertListItemsToCloudAttachment(items, aAccount);
}
@@ -2518,30 +2512,28 @@ function convertListItemsToRegularAttach
delete item.attachment.contentLocation;
}
}
/**
* Convert the selected attachments to regular (non-cloud) attachments.
*/
function convertSelectedToRegularAttachment() {
- let bucket = document.getElementById("attachmentBucket");
- convertListItemsToRegularAttachment([...bucket.selectedItems]);
+ convertListItemsToRegularAttachment([...gAttachmentBucket.selectedItems]);
}
/**
* Convert an array of nsIMsgAttachments to regular (non-cloud) attachments.
*
* @param aAttachments an array of nsIMsgAttachments
*/
function convertToRegularAttachment(aAttachments) {
- let bucket = document.getElementById("attachmentBucket");
let items = [];
for (let attachment of aAttachments) {
- let item = bucket.findItemForAttachment(attachment);
+ let item = gAttachmentBucket.findItemForAttachment(attachment);
if (item) {
items.push(item);
}
}
convertListItemsToRegularAttachment(items);
}
@@ -2941,24 +2933,24 @@ function manageAttachmentNotification(aF
notification.messageDetails.querySelector("button").before(msg);
notification.messageDetails
.querySelector("button:last-child")
.appendChild(remindLaterMenuPopup);
}
/**
- * Returns whether the attachment notification should be suppressed regardless of
- * the state of keywords.
+ * Returns whether the attachment notification should be suppressed regardless
+ * of the state of keywords.
*/
function attachmentNotificationSupressed() {
return (
gDisableAttachmentReminder ||
gManualAttachmentReminder ||
- AttachmentElementHasItems()
+ gAttachmentBucket.getRowCount()
);
}
var attachmentWorker = new Worker("resource:///modules/AttachmentChecker.jsm");
// The array of currently found keywords. Or null if keyword detection wasn't
// run yet so we don't know.
attachmentWorker.lastMessage = null;
@@ -3003,19 +2995,18 @@ attachmentWorker.onmessage = function(ev
* @param aShowPane {string} "show": show the attachment pane
* "hide": hide the attachment pane
* omitted: just update without changing pane visibility
* @param aContentChanged {Boolean} optional value to assign to gContentChanged;
* defaults to true.
*/
function AttachmentsChanged(aShowPane, aContentChanged = true) {
gAttachmentsSize = 0;
- let bucket = document.getElementById("attachmentBucket");
- for (let item of bucket.itemChildren) {
- bucket.invalidateItem(item);
+ for (let item of gAttachmentBucket.itemChildren) {
+ gAttachmentBucket.invalidateItem(item);
gAttachmentsSize += item.attachment.size;
}
gContentChanged = aContentChanged;
updateAttachmentPane(aShowPane);
attachmentBucketMarkEmptyBucket();
manageAttachmentNotification(true);
updateAttachmentItems();
@@ -3961,16 +3952,22 @@ function ComposeLoad() {
"mail.compose.other.header",
""
);
AddMessageComposeOfflineQuitObserver();
BondOpenPGP.init();
+ // Setup the attachment bucket.
+ gAttachmentBucket = document.getElementById("attachmentBucket");
+ let viewMode = Services.prefs.getIntPref("mailnews.attachments.display.view");
+ let views = ["small", "large", "tile"];
+ gAttachmentBucket.view = views[viewMode];
+
try {
SetupCommandUpdateHandlers();
// This will do migration, or create a new account if we need to.
// We also want to open the account wizard if no identities are found
let state = verifyAccounts(WizCallback, true);
if (otherHeaders) {
let extraRecipientsPanel = document.getElementById(
@@ -4698,17 +4695,17 @@ async function CompleteGenericSendMessag
msgType == Ci.nsIMsgCompDeliverMode.Later ||
msgType == Ci.nsIMsgCompDeliverMode.Background
) {
window.dispatchEvent(new CustomEvent("aftersend"));
let maxSize =
Services.prefs.getIntPref("mail.compose.big_attachments.threshold_kb") *
1024;
- let items = [...document.getElementById("attachmentBucket").itemChildren];
+ let items = [...gAttachmentBucket.itemChildren];
// When any big attachment is not sent via filelink, increment
// `tb.filelink.ignored`.
if (
items.some(
item => item.attachment.size >= maxSize && !item.attachment.sendViaCloud
)
) {
@@ -5795,17 +5792,17 @@ function SetLastAttachDirectory(attached
parent
);
} catch (ex) {
dump("error: SetLastAttachDirectory failed: " + ex + "\n");
}
}
function AttachFile() {
- if (attachmentsCount() > 0) {
+ if (gAttachmentBucket.itemCount) {
// If there are existing attachments already, restore attachment pane before
// showing the file picker so that user can see them while adding more.
toggleAttachmentPane("show");
}
// Get file using nsIFilePicker and convert to URL
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
fp.init(
@@ -5863,17 +5860,16 @@ function FileToAttachment(file) {
* @param {nsIMsgAttachment[]} aAttachments - Objects to add as attachments.
* @param {function} [aCallback] - An optional callback function called after
* adding each attachment. Takes one argument: the newly-added
* <attachmentitem> node.
* @param {Boolean} [aContentChanged=true] - Optional value to assign gContentChanged
* after adding attachments.
*/
function AddAttachments(aAttachments, aCallback, aContentChanged = true) {
- let bucket = document.getElementById("attachmentBucket");
let addedAttachments = Cc["@mozilla.org/array;1"].createInstance(
Ci.nsIMutableArray
);
let items = [];
for (let attachment of fixIterator(aAttachments, Ci.nsIMsgAttachment)) {
if (
!(attachment && attachment.url) ||
@@ -5895,17 +5891,17 @@ function AddAttachments(aAttachments, aC
) {
attachment.name = getComposeBundle().getString(
"messageAttachmentSafeName"
);
} else if (/^file:|^mailbox:|^imap:|^s?news:/i.test(attachment.name)) {
attachment.name = getComposeBundle().getString("partAttachmentSafeName");
}
- let item = bucket.appendItem(attachment);
+ let item = gAttachmentBucket.appendItem(attachment);
addedAttachments.appendElement(attachment);
if (attachment.size != -1) {
gAttachmentsSize += attachment.size;
}
try {
item.setAttribute("tooltiptext", decodeURI(attachment.url));
@@ -5934,99 +5930,81 @@ function AddAttachments(aAttachments, aC
}
if (addedAttachments.length > 0) {
// If no attachment item has had focus yet (currentIndex == -1, or undefined
// on some platforms according to spec), make sure there's at least one item
// set as currentItem which will be focused when listbox gets focus, because
// currently we don't indicate focus on the listbox itself when there are
// attachments, assuming that one of them has focus.
- if (!(bucket.currentIndex >= 0)) {
- bucket.currentIndex = bucket.getIndexOfItem(items[0]);
+ if (!(gAttachmentBucket.currentIndex >= 0)) {
+ gAttachmentBucket.currentIndex = gAttachmentBucket.getIndexOfItem(
+ items[0]
+ );
}
AttachmentsChanged("show", aContentChanged);
dispatchAttachmentBucketEvent("attachments-added", addedAttachments);
- } else if (attachmentsCount() > 0) {
+ } else if (gAttachmentBucket.itemCount) {
// We didn't succeed to add attachments (e.g. duplicate files),
// but user was trying to; so we must at least react by ensuring the pane
// is shown, which might be hidden by user with existing attachments.
toggleAttachmentPane("show");
}
return items;
}
/**
- * Get the number of all attachments of the message.
- *
- * @return the number of all attachment items in attachmentBucket;
- * 0 if attachmentBucket not found or no attachments in the list.
- */
-function attachmentsCount() {
- let bucketList = GetMsgAttachmentElement();
- return bucketList ? bucketList.itemCount : 0;
-}
-
-/**
- * Get the number of selected attachments.
- *
- * @return {number} the number of selected attachments, or 0 if there are
- * no attachments selected, no attachments, or no attachmentBucket
- */
-function attachmentsSelectedCount() {
- let bucketList = GetMsgAttachmentElement();
- return bucketList ? bucketList.selectedCount : 0;
-}
-
-/**
* Returns a sorted-by-index, "non-live" array of attachment list items.
*
* @param aAscending {boolean}: true (default): sort return array ascending
* false : sort return array descending
* @param aSelectedOnly {boolean}: true: return array of selected items only.
* false (default): return array of all items.
*
* @return {array} an array of (all | selected) listItem elements in
* attachmentBucket listbox, "non-live" and sorted by their index
* in the list; [] if there are (no | no selected) attachments.
*/
function attachmentsGetSortedArray(aAscending = true, aSelectedOnly = false) {
- let bucketList;
let listItems;
if (aSelectedOnly) {
// Selected attachments only.
- if (attachmentsSelectedCount() < 1) {
+ if (!gAttachmentBucket.selectedCount) {
return [];
}
- bucketList = document.getElementById("attachmentBucket");
- // bucketList.selectedItems is a "live" and "unordered" node list (items get
- // added in the order they were added to the selection). But we want a stable
- // ("non-live") array of selected items, sorted by their index in the list.
- listItems = [...bucketList.selectedItems];
+ // gAttachmentBucket.selectedItems is a "live" and "unordered" node list
+ // (items get added in the order they were added to the selection). But we
+ // want a stable ("non-live") array of selected items, sorted by their index
+ // in the list.
+ listItems = [...gAttachmentBucket.selectedItems];
} else {
// All attachments.
- if (attachmentsCount() < 1) {
+ if (!gAttachmentBucket.itemCount) {
return [];
}
- bucketList = document.getElementById("attachmentBucket");
- listItems = [...bucketList.itemChildren];
+ listItems = [...gAttachmentBucket.itemChildren];
}
if (aAscending) {
listItems.sort(
- (a, b) => bucketList.getIndexOfItem(a) - bucketList.getIndexOfItem(b)
+ (a, b) =>
+ gAttachmentBucket.getIndexOfItem(a) -
+ gAttachmentBucket.getIndexOfItem(b)
);
} else {
// descending
listItems.sort(
- (a, b) => bucketList.getIndexOfItem(b) - bucketList.getIndexOfItem(a)
+ (a, b) =>
+ gAttachmentBucket.getIndexOfItem(b) -
+ gAttachmentBucket.getIndexOfItem(a)
);
}
return listItems;
}
/**
* Returns a sorted-by-index, "non-live" array of selected attachment list items.
*
@@ -6052,38 +6030,39 @@ function attachmentsSelectionGetSortedAr
* (at the list edge if/as specified by 'aListPosition'),
* or only 1 item selected.
* false: The selected attachment items are NOT a coherent block
* (at the list edge if/as specified by 'aListPosition'),
* or no attachments selected, or no attachments,
* or no attachmentBucket.
*/
function attachmentsSelectionIsBlock(aListPosition) {
- let selectedCount = attachmentsSelectedCount();
- if (selectedCount < 1) {
+ if (!gAttachmentBucket.selectedCount) {
// No attachments selected, no attachments, or no attachmentBucket.
return false;
}
- let bucketList = document.getElementById("attachmentBucket");
let selItems = attachmentsSelectionGetSortedArray();
- let indexFirstSelAttachment = bucketList.getIndexOfItem(selItems[0]);
- let indexLastSelAttachment = bucketList.getIndexOfItem(
- selItems[selectedCount - 1]
+ let indexFirstSelAttachment = gAttachmentBucket.getIndexOfItem(selItems[0]);
+ let indexLastSelAttachment = gAttachmentBucket.getIndexOfItem(
+ selItems[gAttachmentBucket.selectedCount - 1]
);
let isBlock =
- indexFirstSelAttachment == indexLastSelAttachment + 1 - selectedCount;
+ indexFirstSelAttachment ==
+ indexLastSelAttachment + 1 - gAttachmentBucket.selectedCount;
switch (aListPosition) {
case "top":
// True if selection is a coherent block at the top of the list.
return indexFirstSelAttachment == 0 && isBlock;
case "bottom":
// True if selection is a coherent block at the bottom of the list.
- return indexLastSelAttachment == attachmentsCount() - 1 && isBlock;
+ return (
+ indexLastSelAttachment == gAttachmentBucket.itemCount - 1 && isBlock
+ );
default:
// True if selection is a coherent block.
return isBlock;
}
}
function AttachPage() {
let result = { value: "http://" };
@@ -6112,52 +6091,45 @@ function AttachPage() {
}
/**
* Check if the given fileURL already exists in the attachment bucket.
* @param fileURL the URL (as a String) of the file to check
* @return true if the fileURL is already attached
*/
function DuplicateFileAlreadyAttached(fileURL) {
- var bucket = document.getElementById("attachmentBucket");
- let rowCount = bucket.getRowCount();
- for (let i = 0; i < rowCount; i++) {
- let attachment = bucket.getItemAtIndex(i).attachment;
- if (attachment && attachment.url == fileURL) {
+ for (let item of gAttachmentBucket.itemChildren) {
+ if (item.attachment && item.attachment.url == fileURL) {
return true;
}
}
+
return false;
}
function Attachments2CompFields(compFields) {
- var bucket = document.getElementById("attachmentBucket");
-
- // First, we need to clear all attachment in the compose fields
+ // First, we need to clear all attachment in the compose fields.
compFields.removeAttachments();
- let rowCount = bucket.getRowCount();
- for (let i = 0; i < rowCount; i++) {
- let attachment = bucket.getItemAtIndex(i).attachment;
- if (attachment) {
- compFields.addAttachment(attachment);
+ for (let item of gAttachmentBucket.itemChildren) {
+ if (item.attachment) {
+ compFields.addAttachment(item.attachment);
}
}
}
function RemoveAllAttachments() {
// Ensure that attachment pane is shown before removing all attachments.
toggleAttachmentPane("show");
- let bucket = document.getElementById("attachmentBucket");
- if (bucket.itemCount == 0) {
+ if (!gAttachmentBucket.itemCount) {
return;
}
- RemoveAttachments(bucket.itemChildren);
+ RemoveAttachments(gAttachmentBucket.itemChildren);
}
/**
* Show or hide the attachment pane after updating its header bar information
* (number and total file size of attachments) and tooltip.
*
* @param aShowBucket {Boolean} true: show the attachment pane
* false (or omitted): hide the attachment pane
@@ -6170,18 +6142,17 @@ function UpdateAttachmentBucket(aShowBuc
* Update the header bar information (number and total file size of attachments)
* and tooltip of attachment pane, then (optionally) show or hide the pane.
*
* @param aShowPane {string} "show": show the attachment pane
* "hide": hide the attachment pane
* omitted: just update without changing pane visibility
*/
function updateAttachmentPane(aShowPane) {
- let bucket = GetMsgAttachmentElement();
- let count = bucket.itemCount;
+ let count = gAttachmentBucket.itemCount;
document.l10n.setAttributes(
document.getElementById("attachmentBucketCount"),
"attachment-bucket-count",
{ count }
);
document.getElementById("attachmentBucketSize").value =
@@ -6201,28 +6172,26 @@ function updateAttachmentPane(aShowPane)
return;
}
// Otherwise, show or hide the panel per aShowPane argument.
toggleAttachmentPane(aShowPane);
}
function RemoveSelectedAttachment() {
- let bucket = GetMsgAttachmentElement();
- if (bucket.selectedCount == 0) {
+ if (!gAttachmentBucket.selectedCount) {
return;
}
- RemoveAttachments(bucket.selectedItems);
+ RemoveAttachments(gAttachmentBucket.selectedItems);
}
function RemoveAttachments(items) {
- let bucket = document.getElementById("attachmentBucket");
// Remember the current focus index so we can try to restore it when done.
- let focusIndex = bucket.currentIndex;
+ let focusIndex = gAttachmentBucket.currentIndex;
let fileHandler = Services.io
.getProtocolHandler("file")
.QueryInterface(Ci.nsIFileProtocolHandler);
let removedAttachments = Cc["@mozilla.org/array;1"].createInstance(
Ci.nsIMutableArray
);
@@ -6256,42 +6225,42 @@ function RemoveAttachments(items) {
removedAttachments.appendElement(item.attachment);
// Let's release the attachment object held by the node else it won't go
// away until the window is destroyed
item.attachment = null;
item.remove();
}
// Try to restore original focus or somewhere close by.
- if (bucket.itemCount == 0) {
- bucket.currentIndex = -1;
- } else if (focusIndex < bucket.itemCount) {
- bucket.currentIndex = focusIndex;
+ if (gAttachmentBucket.itemCount == 0) {
+ gAttachmentBucket.currentIndex = -1;
+ } else if (focusIndex < gAttachmentBucket.itemCount) {
+ gAttachmentBucket.currentIndex = focusIndex;
} else {
- bucket.currentIndex = bucket.itemCount - 1;
+ gAttachmentBucket.currentIndex = gAttachmentBucket.itemCount - 1;
}
if (removedAttachments.length > 0) {
- // Bug workaround: Force update of selectedCount and selectedItem, both wrong
- // after item removal, to avoid confusion for listening command controllers.
- bucket.clearSelection();
+ // Bug 1661507 workaround: Force update of selectedCount and selectedItem,
+ // both wrong after item removal, to avoid confusion for listening command
+ // controllers.
+ gAttachmentBucket.clearSelection();
AttachmentsChanged();
dispatchAttachmentBucketEvent("attachments-removed", removedAttachments);
}
}
function RenameSelectedAttachment() {
- let bucket = document.getElementById("attachmentBucket");
- if (bucket.selectedItems.length != 1) {
+ if (gAttachmentBucket.selectedItems.length != 1) {
// Not one attachment selected.
return;
}
- let item = bucket.getSelectedItem(0);
+ let item = gAttachmentBucket.getSelectedItem(0);
let attachmentName = { value: item.attachment.name };
if (
Services.prompt.prompt(
window,
getComposeBundle().getString("renameAttachmentTitle"),
getComposeBundle().getString("renameAttachmentMessage"),
attachmentName,
null,
@@ -6332,34 +6301,33 @@ function RenameSelectedAttachment() {
* "bundleUp" : Move attachments together (upwards).
* "bundleDown": Move attachments together (downwards).
* "toggleSort": Sort attachments alphabetically (toggle).
*/
function moveSelectedAttachments(aDirection) {
// Command controllers will bail out if no or all attachments are selected,
// or if block selections can't be moved, or if other direction-specific
// adverse circumstances prevent the intended movement.
-
if (!aDirection) {
return;
}
- let bucket = document.getElementById("attachmentBucket");
-
- // Ensure focus on bucket when we're coming from 'Reorder Attachments' panel.
- bucket.focus();
-
- // Get a sorted and "non-live" array of bucket.selectedItems.
+ // Ensure focus on gAttachmentBucket when we're coming from
+ // 'Reorder Attachments' panel.
+ gAttachmentBucket.focus();
+
+ // Get a sorted and "non-live" array of gAttachmentBucket.selectedItems.
let selItems = attachmentsSelectionGetSortedArray();
- let visibleIndex = bucket.currentIndex; // In case of misspelled aDirection.
+ // In case of misspelled aDirection.
+ let visibleIndex = gAttachmentBucket.currentIndex;
// Keep track of the item we had focused originally. Deselect it though,
// since listbox gets confused if you move its focused item around.
- let focusItem = bucket.currentItem;
- bucket.currentItem = null;
+ let focusItem = gAttachmentBucket.currentItem;
+ gAttachmentBucket.currentItem = null;
let upwards;
let targetItem;
switch (aDirection) {
case "up":
case "down":
// Move selected attachments upwards/downwards.
upwards = aDirection == "up";
@@ -6385,45 +6353,45 @@ function moveSelectedAttachments(aDirect
// i.e. before previousElementSibling of block.
checkItem
: // Downwards: Insert block items *after* checkItem,
// i.e. *before* nextElementSibling.nextElementSibling of block,
// which works according to spec even if that's null.
checkItem.nextElementSibling;
// Move current blockItems.
for (let blockItem of blockItems) {
- bucket.insertBefore(blockItem, targetItem);
+ gAttachmentBucket.insertBefore(blockItem, targetItem);
}
}
// Else if checkItem doesn't exist, the block is already at the edge
// of the list, so we can't move it in the intended direction.
blockItems.length = 0; // Either way, we're done with the current block.
}
// Else if current selItem is NOT the end of the current block, proceed:
// Add next selItem to the block and see if that's the end of the block.
} // Next selItem.
// Ensure helpful visibility of moved items (scroll into view if needed):
// If first item of selection is now at the top, first list item.
// Else if last item of selection is now at the bottom, last list item.
// Otherwise, let's see where we are going by ensuring visibility of the
// nearest unselected sibling of selection according to direction of move.
- if (bucket.getIndexOfItem(selItems[0]) == 0) {
+ if (gAttachmentBucket.getIndexOfItem(selItems[0]) == 0) {
visibleIndex = 0;
} else if (
- bucket.getIndexOfItem(selItems[selItems.length - 1]) ==
- bucket.itemCount - 1
+ gAttachmentBucket.getIndexOfItem(selItems[selItems.length - 1]) ==
+ gAttachmentBucket.itemCount - 1
) {
- visibleIndex = bucket.itemCount - 1;
+ visibleIndex = gAttachmentBucket.itemCount - 1;
} else if (upwards) {
- visibleIndex = bucket.getIndexOfItem(
+ visibleIndex = gAttachmentBucket.getIndexOfItem(
selItems[0].previousElementSibling
);
} else {
- visibleIndex = bucket.getIndexOfItem(
+ visibleIndex = gAttachmentBucket.getIndexOfItem(
selItems[selItems.length - 1].nextElementSibling
);
}
break;
case "top":
case "bottom":
case "bundleUp":
@@ -6432,43 +6400,43 @@ function moveSelectedAttachments(aDirect
upwards = ["top", "bundleUp"].includes(aDirection);
// Downwards: Reverse order of selItems so we can use the same algorithm.
if (!upwards) {
selItems.reverse();
}
if (["top", "bottom"].includes(aDirection)) {
- let listEdgeItem = bucket.getItemAtIndex(
- upwards ? 0 : bucket.itemCount - 1
+ let listEdgeItem = gAttachmentBucket.getItemAtIndex(
+ upwards ? 0 : gAttachmentBucket.itemCount - 1
);
let selEdgeItem = selItems[0];
if (selEdgeItem != listEdgeItem) {
// Top/Bottom: Move the first/last selected item to the edge of the list
// so that we always have an initial anchor target block in the right
// place, so we can use the same algorithm for top/bottom and
// inner bundling.
targetItem = upwards
? // Upwards: Insert before first list item.
listEdgeItem
: // Downwards: Insert after last list item, i.e.
// *before* non-existing listEdgeItem.nextElementSibling,
// which is null. It works because it's a feature.
null;
- bucket.insertBefore(selEdgeItem, targetItem);
+ gAttachmentBucket.insertBefore(selEdgeItem, targetItem);
}
}
// We now have a selected block (at least one item) at the target position.
// Let's find the end (inner edge) of that block and move only the
// remaining selected items to avoid unnecessary moves.
targetItem = null;
for (let item of selItems) {
if (targetItem) {
// We know where to move it, so move it!
- bucket.insertBefore(item, targetItem);
+ gAttachmentBucket.insertBefore(item, targetItem);
if (!upwards) {
// Downwards: As selItems are reversed, and there's no insertAfter()
// method to insert *after* a stable target, we need to insert
// *before* the first item of the target block at target position,
// which is the current selItem which we've just moved onto the block.
targetItem = item;
}
} else {
@@ -6486,31 +6454,31 @@ function moveSelectedAttachments(aDirect
item;
}
// Else if nextItem is selected, it is still part of initial anchor
// target block, so just proceed to look for the edge of that block.
}
} // next selItem
// Ensure visibility of first/last selected item after the move.
- visibleIndex = bucket.getIndexOfItem(selItems[0]);
+ visibleIndex = gAttachmentBucket.getIndexOfItem(selItems[0]);
break;
case "toggleSort":
// Sort the selected attachments alphabetically after moving them together.
// The command updater of cmd_sortAttachmentsToggle toggles the sorting
// direction based on the current sorting and block status of the selection.
let toggleCmd = document.getElementById("cmd_sortAttachmentsToggle");
let sortDirection =
toggleCmd.getAttribute("sortdirection") || "ascending";
let sortItems;
let sortSelection;
- if (attachmentsSelectedCount() > 1) {
+ if (gAttachmentBucket.selectedCount > 1) {
// Sort selected attachments only.
sortSelection = true;
sortItems = selItems;
// Move selected attachments together before sorting as a block.
goDoCommand("cmd_moveAttachmentBundleUp");
// Find the end of the selected block to find our targetItem.
for (let item of selItems) {
@@ -6541,34 +6509,35 @@ function moveSelectedAttachments(aDirect
// "descending"
sortItems.sort((a, b) =>
b.attachment.name.localeCompare(a.attachment.name)
);
}
// Insert sortItems in new order before the nextElementSibling of the block.
for (let item of sortItems) {
- bucket.insertBefore(item, targetItem);
+ gAttachmentBucket.insertBefore(item, targetItem);
}
if (sortSelection) {
// After sorting selection: Ensure visibility of first selected item.
- visibleIndex = bucket.getIndexOfItem(selItems[0]);
+ visibleIndex = gAttachmentBucket.getIndexOfItem(selItems[0]);
} else {
// After sorting all items: Ensure visibility of selected item,
// otherwise first list item.
- visibleIndex = selItems.length == 1 ? bucket.selectedIndex : 0;
+ visibleIndex =
+ selItems.length == 1 ? gAttachmentBucket.selectedIndex : 0;
}
break;
} // end switch (aDirection)
// Restore original focus.
- bucket.currentItem = focusItem;
+ gAttachmentBucket.currentItem = focusItem;
// Ensure smart visibility of a relevant item according to direction.
- bucket.ensureIndexIsVisible(visibleIndex);
+ gAttachmentBucket.ensureIndexIsVisible(visibleIndex);
// Moving selected items around does not trigger auto-updating of our command
// handlers, so we must do it now as the position of selected items has changed.
updateReorderAttachmentsItems();
}
/* eslint-enable complexity */
/**
@@ -6576,48 +6545,47 @@ function moveSelectedAttachments(aDirect
* If aAction parameter is omitted, toggle current view state.
*
* @param {string} [aAction = "toggle"] - "show": show attachment pane
* "hide": hide attachment pane
* "toggle": toggle attachment pane
* @param {Event} [event] - The command event (cmd_toggleAttachmentPane)
*/
function toggleAttachmentPane(aAction = "toggle", event) {
- let bucket = GetMsgAttachmentElement();
let attachmentsBox = document.getElementById("attachments-box");
let attachmentBucketSizer = document.getElementById("attachmentbucket-sizer");
- let bucketHasFocus = document.activeElement == bucket;
+ let bucketHasFocus = document.activeElement == gAttachmentBucket;
if (aAction == "toggle") {
let shown = !attachmentsBox.collapsed;
if (shown && !bucketHasFocus && event && (event.altKey || event.ctrlKey)) {
// If attachment pane is shown but not focused, and we're here via
// key_toggleAttachmentPane, handle access key here: Focus bucket.
- bucket.focus();
- if (bucket.currentItem) {
- bucket.ensureElementIsVisible(bucket.currentItem);
+ gAttachmentBucket.focus();
+ if (gAttachmentBucket.currentItem) {
+ gAttachmentBucket.ensureElementIsVisible(gAttachmentBucket.currentItem);
}
return;
}
// Toggle attachment pane.
aAction = shown ? "hide" : "show";
}
switch (aAction) {
case "show": {
attachmentsBox.collapsed = false;
attachmentBucketSizer.collapsed = false;
attachmentBucketSizer.setAttribute("state", "");
if (!bucketHasFocus) {
- bucket.focus();
- }
- if (bucket.currentItem) {
- bucket.ensureElementIsVisible(bucket.currentItem);
+ gAttachmentBucket.focus();
+ }
+ if (gAttachmentBucket.currentItem) {
+ gAttachmentBucket.ensureElementIsVisible(gAttachmentBucket.currentItem);
}
break;
}
case "hide": {
if (bucketHasFocus) {
SetMsgBodyFrameFocus();
}
@@ -6652,17 +6620,17 @@ function showReorderAttachmentsPanel() {
);
// After the panel is shown, focus attachmentBucket so that keyboard
// operation for selecting and moving attachment items works; the panel
// helpfully presents the keyboard shortcuts for moving things around.
// Bucket focus is also required because the panel will only close with ESC
// or attachmentBucketOnBlur(), and that's because we're using noautohide as
// event.preventDefault() of onpopuphiding event fails when the panel
// is auto-hiding, but we don't want panel to hide when focus goes to bucket.
- document.getElementById("attachmentBucket").focus();
+ gAttachmentBucket.focus();
}
/**
* Returns a string representing the current sort order of selected attachment
* items by their names. We don't check if selected items form a coherent block
* or not; use attachmentsSelectionIsBlock() to check on that.
*
* @return {string} "ascending" : Sort order is ascending.
@@ -6688,24 +6656,24 @@ function attachmentsSelectionGetSortOrde
* "equivalent": The names of the items are equivalent.
* "" : There's no sort order, or no attachments,
* or no attachmentBucket; or (with aSelectedOnly),
* only 1 item selected, or no items selected.
*/
function attachmentsGetSortOrder(aSelectedOnly = false) {
let listItems;
if (aSelectedOnly) {
- if (attachmentsSelectedCount() <= 1) {
+ if (gAttachmentBucket.selectedCount <= 1) {
return "";
}
listItems = attachmentsSelectionGetSortedArray();
} else {
// aSelectedOnly == false
- if (attachmentsCount() < 1) {
+ if (!gAttachmentBucket.itemCount) {
return "";
}
listItems = attachmentsGetSortedArray();
}
// We're comparing each item to the next item, so exclude the last item.
let listItems1 = listItems.slice(0, -1);
@@ -6751,17 +6719,17 @@ function reorderAttachmentsPanelOnPopupS
// Let's add some pretty keyboard shortcuts to the buttons.
buttons.forEach(btn => {
if (btn.hasAttribute("key")) {
btn.setAttribute("prettykey", getPrettyKey(btn.getAttribute("key")));
}
});
// Focus attachment bucket to activate attachmentBucketController, which is
// required for updating the reorder commands.
- document.getElementById("attachmentBucket").focus();
+ gAttachmentBucket.focus();
// We're updating commands before showing the panel so that button states
// don't change after the panel is shown, and also because focus is still
// in attachment bucket right now, which is required for updating them.
updateReorderAttachmentsItems();
}
function attachmentHeaderContextOnPopupShowing() {
let initiallyShowItem = document.getElementById(
@@ -6797,42 +6765,40 @@ function attachmentBucketOnBlur() {
document.activeElement.id != "attachmentBucket" &&
reorderAttachmentsPanel.state != "showing"
) {
reorderAttachmentsPanel.hidePopup();
}
}
function attachmentBucketOnKeyPress(aEvent) {
- let bucket = GetMsgAttachmentElement();
-
// When ESC is pressed ...
if (aEvent.key == "Escape") {
let reorderAttachmentsPanel = document.getElementById(
"reorderAttachmentsPanel"
);
if (reorderAttachmentsPanel.state == "open") {
// First close reorderAttachmentsPanel if open.
reorderAttachmentsPanel.hidePopup();
- } else if (bucket.itemCount > 0) {
- if (bucket.selectedCount > 0) {
- // Then deselect selected items in full bucket if any.
- bucket.clearSelection();
+ } else if (gAttachmentBucket.itemCount) {
+ if (gAttachmentBucket.selectedCount) {
+ // Then deselect selected items in full gAttachmentBucket if any.
+ gAttachmentBucket.clearSelection();
} else {
- // Then unfocus full bucket to continue with msg body.
+ // Then unfocus full gAttachmentBucket to continue with msg body.
SetMsgBodyFrameFocus();
}
} else {
- // (bucket.itemCount == 0)
- // Otherwise close empty bucket.
+ // (gAttachmentBucket.itemCount == 0)
+ // Otherwise close empty gAttachmentBucket.
toggleAttachmentPane("hide");
}
}
- if (aEvent.key == "Enter" && bucket.itemCount == 0) {
+ if (aEvent.key == "Enter" && !gAttachmentBucket.itemCount) {
// Enter on empty bucket to add file attachments, convenience
// keyboard equivalent of single-click on bucket whitespace.
goDoCommand("cmd_attachFile");
}
}
function attachmentBucketOnClick(aEvent) {
// Handle click on attachment pane whitespace normally clear selection.
@@ -6847,25 +6813,23 @@ function attachmentBucketOnClick(aEvent)
}
function attachmentBucketOnSelect() {
attachmentBucketUpdateTooltips();
updateAttachmentItems();
}
function attachmentBucketUpdateTooltips() {
- let bucket = GetMsgAttachmentElement();
-
// Attachment pane whitespace tooltip
- if (attachmentsSelectedCount() > 0) {
- bucket.tooltipText = getComposeBundle().getString(
+ if (gAttachmentBucket.selectedCount) {
+ gAttachmentBucket.tooltipText = getComposeBundle().getString(
"attachmentBucketClearSelectionTooltip"
);
} else {
- bucket.tooltipText = getComposeBundle().getString(
+ gAttachmentBucket.tooltipText = getComposeBundle().getString(
"attachmentBucketAttachFilesTooltip"
);
}
}
function attachmentBucketHeaderOnClick(aEvent) {
if (aEvent.button == 0) {
// Left click
@@ -6880,35 +6844,28 @@ function attachmentBucketCloseButtonOnCo
function attachmentBucketSizerOnMouseUp() {
updateViewItems();
if (document.getElementById("attachments-box").collapsed) {
// If user collapsed the attachment pane, move focus to message body.
SetMsgBodyFrameFocus();
}
}
-function AttachmentElementHasItems() {
- var element = document.getElementById("attachmentBucket");
- return element ? element.getRowCount() > 0 : false;
-}
-
function attachmentBucketMarkEmptyBucket() {
- let attachmentBucket = GetMsgAttachmentElement();
let attachmentsBox = document.getElementById("attachments-box");
- if (attachmentBucket.itemCount > 0) {
+ if (gAttachmentBucket.itemCount) {
attachmentsBox.removeAttribute("empty");
} else {
attachmentsBox.setAttribute("empty", "true");
}
}
function OpenSelectedAttachment() {
- let bucket = document.getElementById("attachmentBucket");
- if (bucket.selectedItems.length == 1) {
- let attachmentUrl = bucket.getSelectedItem(0).attachment.url;
+ if (gAttachmentBucket.selectedItems.length == 1) {
+ let attachmentUrl = gAttachmentBucket.getSelectedItem(0).attachment.url;
let messagePrefix = /^mailbox-message:|^imap-message:|^news-message:/i;
if (messagePrefix.test(attachmentUrl)) {
// we must be dealing with a forwarded attachment, treat this special
let msgHdr = gMessenger
.messageServiceFromURI(attachmentUrl)
.messageURIToMsgHdr(attachmentUrl);
if (msgHdr) {
@@ -7392,40 +7349,38 @@ var envelopeDragObserver = {
* @param {Event} event - The drag-and-drop event being performed.
* @return {attachmentitem|string} - the adjusted drop target:
* - an attachmentitem node for inserting *before*
* - "none" if this isn't a valid insertion point
* - "afterLastItem" for appending at the bottom of the list.
*/
_adjustDropTarget(event) {
let target = event.target;
- let bucket = document.getElementById("attachmentBucket");
-
- if (target == bucket) {
+ if (target == gAttachmentBucket) {
// Dragging or dropping at top/bottom border of the listbox
if (
(event.screenY - target.screenY) /
target.getBoundingClientRect().height <
0.5
) {
- target = bucket.firstElementChild;
+ target = gAttachmentBucket.firstElementChild;
} else {
- target = bucket.lastElementChild;
+ target = gAttachmentBucket.lastElementChild;
}
// We'll check below if this is a valid target.
} else if (target.id == "attachmentBucketCount") {
// Dragging or dropping at top border of the listbox.
// Allow bottom half of attachment list header as extended drop target
// for top of list, because otherwise it would be too small.
if (
(event.screenY - target.screenY) /
target.getBoundingClientRect().height >=
0.5
) {
- target = bucket.firstElementChild;
+ target = gAttachmentBucket.firstElementChild;
// We'll check below if this is a valid target.
} else {
// Top half of attachment list header: sorry, can't drop here.
return "none";
}
}
// Target is an attachmentitem.
@@ -7468,27 +7423,25 @@ var envelopeDragObserver = {
}
return target;
}
return "none";
},
_showDropMarker(targetItem) {
- let bucket = document.getElementById("attachmentBucket");
-
- let oldDropMarkerItem = bucket.querySelector(
+ let oldDropMarkerItem = gAttachmentBucket.querySelector(
"richlistitem.attachmentItem[dropOn]"
);
if (oldDropMarkerItem) {
oldDropMarkerItem.removeAttribute("dropOn");
}
if (targetItem == "afterLastItem") {
- targetItem = bucket.lastElementChild;
+ targetItem = gAttachmentBucket.lastElementChild;
targetItem.setAttribute("dropOn", "bottom");
} else {
targetItem.setAttribute("dropOn", "top");
}
},
_hideDropMarker() {
let oldDropMarkerItem = document
@@ -7496,94 +7449,96 @@ var envelopeDragObserver = {
.querySelector("richlistitem.attachmentItem[dropOn]");
if (oldDropMarkerItem) {
oldDropMarkerItem.removeAttribute("dropOn");
}
},
// eslint-disable-next-line complexity
onDrop(event) {
- let bucket = document.getElementById("attachmentBucket");
let dragSession = Cc["@mozilla.org/widget/dragservice;1"]
.getService(Ci.nsIDragService)
.getCurrentSession();
let dragSourceNode = dragSession.sourceNode;
- if (dragSourceNode && dragSourceNode.parentNode == bucket) {
+ if (dragSourceNode && dragSourceNode.parentNode == gAttachmentBucket) {
// We dragged from the attachment pane onto itself, so instead of
// attaching a new object, we're just reordering them.
// Adjust the drop target according to mouse position on list (items).
let target = this._adjustDropTarget(event);
// Get a non-live, sorted list of selected attachment list items.
let selItems = attachmentsSelectionGetSortedArray();
// Keep track of the item we had focused originally. Deselect it though,
// since listbox gets confused if you move its focused item around.
- let focus = bucket.currentItem;
- bucket.currentItem = null;
+ let focus = gAttachmentBucket.currentItem;
+ gAttachmentBucket.currentItem = null;
// Moving possibly non-coherent multiple selections around correctly
// is much more complex than one might think...
if (
(target.matches && target.matches("richlistitem.attachmentItem")) ||
target == "afterLastItem"
) {
// Drop before targetItem in the list, or after last item.
let blockItems = [];
let targetItem;
for (let item of selItems) {
blockItems.push(item);
if (target == "afterLastItem") {
// Original target is the end of the list; append all items there.
- bucket.appendChild(item);
+ gAttachmentBucket.appendChild(item);
} else if (target == selItems[0]) {
// Original target is first item of first selected block.
if (blockItems.includes(target)) {
// Item is in first block: do nothing, find the end of the block.
let nextItem = item.nextElementSibling;
if (!nextItem || !nextItem.selected) {
// We've reached the end of the first block.
blockItems.length = 0;
targetItem = nextItem;
}
} else {
// Item is NOT in first block: insert before targetItem,
// i.e. after end of first block.
- bucket.insertBefore(item, targetItem);
+ gAttachmentBucket.insertBefore(item, targetItem);
}
} else if (target.selected) {
// Original target is not first item of first block,
// but first item of another block.
- if (bucket.getIndexOfItem(item) < bucket.getIndexOfItem(target)) {
+ if (
+ gAttachmentBucket.getIndexOfItem(item) <
+ gAttachmentBucket.getIndexOfItem(target)
+ ) {
// Insert all items from preceding blocks before original target.
- bucket.insertBefore(item, target);
+ gAttachmentBucket.insertBefore(item, target);
} else if (blockItems.includes(target)) {
// target is included in any selected block except first:
// do nothing for that block, find its end.
let nextItem = item.nextElementSibling;
if (!nextItem || !nextItem.selected) {
// end of block containing target
blockItems.length = 0;
targetItem = nextItem;
}
} else {
// Item from block after block containing target: insert before
// targetItem, i.e. after end of block containing target.
- bucket.insertBefore(item, targetItem);
+ gAttachmentBucket.insertBefore(item, targetItem);
}
} else {
// target != selItems [0]
// Original target is NOT first item of any block, and NOT selected:
// Insert all items before the original target.
- bucket.insertBefore(item, target);
+ gAttachmentBucket.insertBefore(item, target);
}
}
}
- bucket.currentItem = focus;
+ gAttachmentBucket.currentItem = focus;
this._hideDropMarker();
return;
}
let attachments = [];
let dt = event.dataTransfer;
let dataList = [];
for (let i = 0; i < dt.mozItemCount; i++) {
@@ -7686,29 +7641,28 @@ var envelopeDragObserver = {
}
}
// Add attachments if any.
if (attachments.length > 0) {
AddAttachments(attachments);
}
- bucket.focus();
+ gAttachmentBucket.focus();
event.stopPropagation();
},
onDragOver(event) {
let dragSession = Cc["@mozilla.org/widget/dragservice;1"]
.getService(Ci.nsIDragService)
.getCurrentSession();
- let bucket = document.getElementById("attachmentBucket");
let dragSourceNode = dragSession.sourceNode;
- if (dragSourceNode && dragSourceNode.parentNode == bucket) {
- // If we're dragging from the attachment bucket onto itself, we need to
- // show a drop marker.
+ if (dragSourceNode && dragSourceNode.parentNode == gAttachmentBucket) {
+ // If we're dragging from the attachment gAttachmentBucket onto itself,
+ // we need to show a drop marker.
let target = this._adjustDropTarget(event);
if (
(target.matches && target.matches("richlistitem.attachmentItem")) ||
target == "afterLastItem"
) {
// Adjusted target is an attachment list item; show dropmarker.
@@ -7799,21 +7753,16 @@ function SetMsgToRecipientElementFocus()
function SetMsgIdentityElementFocus() {
document.getElementById("msgIdentity").focus();
}
function SetMsgSubjectElementFocus() {
document.getElementById("msgSubject").focus();
}
-function SetMsgAttachmentElementFocus() {
- // Caveat: Callers must ensure that attachment pane is visible.
- GetMsgAttachmentElement().focus();
-}
-
/**
* Focus the people search input in contacts side bar.
*
* @return {Boolean} true if peopleSearchInput was found, false otherwise.
*/
function focusContactsSidebarSearchInput() {
// Caveat: Callers must ensure that contacts side bar is visible.
let peopleSearchInput = sidebarDocumentGetElementById(
@@ -7829,24 +7778,16 @@ function focusContactsSidebarSearchInput
function SetMsgBodyFrameFocus() {
// window.content.focus() fails to blur the currently focused element
document.commandDispatcher.advanceFocusIntoSubtree(
document.getElementById("appcontent")
);
}
-function GetMsgAttachmentElement() {
- if (!gMsgAttachmentElement) {
- gMsgAttachmentElement = document.getElementById("attachmentBucket");
- }
-
- return gMsgAttachmentElement;
-}
-
/**
* Get an element by ID in the current sidebar browser document.
*
* @param aId {string} the ID of the element to get
* @param aWindowId {string} the ID of a <window> in the sidebar <browser>;
* only return the element if the window exists.
* Assuming unique window ids and that there there can
* only ever be one <window> in a <browser>'s src.xhtml
@@ -7971,22 +7912,22 @@ function SwitchElementFocus(event) {
}
break;
case sidebarDocumentGetElementById("abContactsPanel"):
SetMsgBodyFrameFocus();
break;
case document.getElementById("content-frame"): // message body
// Focus attachment bucket if shown, otherwise message subject.
if (!document.getElementById("attachments-box").collapsed) {
- SetMsgAttachmentElementFocus();
+ gAttachmentBucket.focus();
} else {
SetMsgSubjectElementFocus();
}
break;
- case gMsgAttachmentElement:
+ case gAttachmentBucket:
SetMsgSubjectElementFocus();
break;
case document.getElementById("msgSubject"):
SetFocusOnPreviousAvailableElement(focusedElement);
break;
default:
SetMsgToRecipientElementFocus();
break;
@@ -8012,22 +7953,22 @@ function SwitchElementFocus(event) {
case document.getElementById("replyAddrInput"):
case document.getElementById("followupAddrInput"):
case document.getElementById("newsgroupsAddrInput"):
SetFocusOnNextAvailableElement(focusedElement);
break;
case document.getElementById("msgSubject"):
// Focus attachment bucket if shown, otherwise message body.
if (!document.getElementById("attachments-box").collapsed) {
- SetMsgAttachmentElementFocus();
+ gAttachmentBucket.focus();
} else {
SetMsgBodyFrameFocus();
}
break;
- case gMsgAttachmentElement:
+ case gAttachmentBucket:
SetMsgBodyFrameFocus();
break;
case document.getElementById("content-frame"): // message body
// Focus the search input of contacts side bar if that's available,
// otherwise focus "From" selector.
if (sidebar_is_hidden() || !focusContactsSidebarSearchInput()) {
SetMsgIdentityElementFocus();
}
@@ -8752,18 +8693,17 @@ function getMailToolbox() {
/**
* Helper function to dispatch a CustomEvent to the attachmentbucket.
*
* @param aEventType the name of the event to fire.
* @param aData any detail data to pass to the CustomEvent.
*/
function dispatchAttachmentBucketEvent(aEventType, aData) {
- let bucket = document.getElementById("attachmentBucket");
- bucket.dispatchEvent(
+ gAttachmentBucket.dispatchEvent(
new CustomEvent(aEventType, {
bubbles: true,
cancelable: true,
detail: aData,
})
);
}