diff --git a/mozilla/mail/components/compose/content/abCommon.js b/mozilla/mail/components/compose/content/abCommon.js new file mode 100644 index 00000000000..cd84cced9f9 --- /dev/null +++ b/mozilla/mail/components/compose/content/abCommon.js @@ -0,0 +1,1003 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Addressbook. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corp. + * Portions created by the Initial Developer are Copyright (C) 1999-2001 + * the Initial Developer. All Rights Reserved. + * + * Original Author: + * Paul Hangas + * + * Contributor(s): + * Seth Spitzer + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +var gResultsTree = 0; +var dirTree = 0; +var abList = 0; +var gAbView = null; +var gSearchInput; +var gSearchTimer = null; +var gQueryURIFormat = null; + +var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService); +var gPrefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch); +var gHeaderParser = Components.classes["@mozilla.org/messenger/headerparser;1"].getService(Components.interfaces.nsIMsgHeaderParser); + +const kDefaultSortColumn = "GeneratedName"; +const kDefaultAscending = "ascending"; +const kDefaultDescending = "descending"; +const kPersonalAddressbookURI = "moz-abmdbdirectory://abook.mab"; +const kCollectedAddressbookURI = "moz-abmdbdirectory://history.mab"; + +// Controller object for Results Pane +var ResultsPaneController = +{ + supportsCommand: function(command) + { + switch (command) { + case "cmd_selectAll": + case "cmd_delete": + case "button_delete": + case "button_edit": + return true; + default: + return false; + } + }, + + isCommandEnabled: function(command) + { + switch (command) { + case "cmd_selectAll": + return true; + + case "cmd_delete": + case "button_delete": + var numSelected; + var enabled = false; + if (gAbView && gAbView.selection) { + if (gAbView.directory) + enabled = gAbView.directory.operations & gAbView.directory.opWrite; + numSelected = gAbView.selection.count; + } + else + numSelected = 0; + + // fix me, don't update on isCommandEnabled + if (command == "cmd_delete") { + if (numSelected < 2) + goSetMenuValue(command, "valueCard"); + else + goSetMenuValue(command, "valueCards"); + } + return (enabled && (numSelected > 0)); + case "button_edit": + return (GetSelectedCardIndex() != -1); + default: + return false; + } + }, + + doCommand: function(command) + { + switch (command) { + case "cmd_selectAll": + if (gAbView) + gAbView.selectAll(); + break; + case "cmd_delete": + case "button_delete": + AbDelete(); + break; + case "button_edit": + AbEditSelectedCard(); + break; + } + }, + + onEvent: function(event) + { + // on blur events set the menu item texts back to the normal values + if (event == "blur") + goSetMenuValue("cmd_delete", "valueDefault"); + } +}; + + +// Controller object for Dir Pane +var DirPaneController = +{ + supportsCommand: function(command) + { + switch (command) { + case "cmd_selectAll": + case "cmd_delete": + case "button_delete": + case "button_edit": + return true; + default: + return false; + } + }, + + isCommandEnabled: function(command) + { + switch (command) { + case "cmd_selectAll": + return true; + case "cmd_delete": + case "button_delete": + if (command == "cmd_delete") + goSetMenuValue(command, "valueAddressBook"); + if (dirTree && dirTree.currentIndex >= 0) + return true; + else + return false; + case "button_edit": + var selectedDir = GetSelectedDirectory(); + if (selectedDir) { + var directory = GetDirectoryFromURI(selectedDir); + if ((directory.isMailList) || + (!(directory.operations & directory.opWrite))) + return true; + } + return false; + default: + return false; + } + }, + + doCommand: function(command) + { + switch (command) { + case "cmd_selectAll": + if (dirTree) + dirTree.treeBoxObject.selection.selectAll(); + break; + + case "cmd_delete": + case "button_delete": + if (dirTree) + AbDeleteDirectory(); + break; + case "button_edit": + AbEditSelectedDirectory(); + break; + } + }, + + onEvent: function(event) + { + // on blur events set the menu item texts back to the normal values + if (event == "blur") + goSetMenuValue("cmd_delete", "valueDefault"); + } +}; + +function AbEditSelectedDirectory() +{ + if (dirTree.treeBoxObject.selection.count == 1) { + var mailingListUri = GetSelectedDirectory(); + var directory = GetDirectoryFromURI(mailingListUri); + if (directory.isMailList) { + var dirUri = GetParentDirectoryFromMailingListURI(mailingListUri); + goEditListDialog(dirUri, null, mailingListUri, UpdateCardView); + } + else if (!(directory.operations & directory.opWrite)) + { + var ldapUrlPrefix = "moz-abldapdirectory://"; + if ((mailingListUri.indexOf(ldapUrlPrefix, 0)) == 0) + { + var args = { selectedDirectory: directory.dirName, + selectedDirectoryString: null}; + args.selectedDirectoryString = mailingListUri.substr(ldapUrlPrefix.length, mailingListUri.length); + window.openDialog("chrome://messenger/content/addressbook/pref-directory-add.xul", + "editDirectory", "chrome,modal=yes,resizable=no,centerscreen", args); + } + } + } +} + +function GetParentRow(aTree, aRow) +{ + var row = aRow; + var level = aTree.view.getLevel(row); + var parentLevel = level; + while (parentLevel >= level) { + row--; + if (row == -1) + return row; + parentLevel = aTree.view.getLevel(row); + } + return row; +} + +function InitCommonJS() +{ + dirTree = document.getElementById("dirTree"); + //abList = document.getElementById("addressbookList"); + gResultsTree = document.getElementById("abResultsTree"); +} + +// builds prior to 12-08-2001 did not use an tree for +// the results pane. so for any existing profiles will +// get all columns, whereas new profile only get a select few +// because we hide them by default in localStore.rdf +// to work around this, we hide the non-default columns once. +// there is more than one results pane (addressbook, select addresses, +// addressbook sidebar channel, etc) so we'll pass in the +// the pref so that we'll migrate each of them once. +function UpgradeAddressBookResultsPaneUI(prefName) +{ + var resultsPaneUIVersion; + + try { + resultsPaneUIVersion = gPrefs.getIntPref(prefName); + if (resultsPaneUIVersion == 1) { + // hide all columns with hiddenbydefault="true" + var elements = document.getElementsByAttribute("hiddenbydefault","true"); + for (var i=0; i 0); +} + +// XXX todo +// could this be moved into utilityOverlay.js? +function goToggleSplitter( id, elementID ) +{ + var splitter = document.getElementById( id ); + var element = document.getElementById( elementID ); + if ( splitter ) + { + var attribValue = splitter.getAttribute("state") ; + + if ( attribValue == "collapsed" ) + { + splitter.setAttribute("state", "open" ); + if ( element ) + element.setAttribute("checked","true") + } + else + { + splitter.setAttribute("state", "collapsed"); + if ( element ) + element.setAttribute("checked","false") + } + document.persist(id, 'state'); + document.persist(elementID, 'checked'); + } +} + +// Generate a list of cards from the selected mailing list +// and get a comma separated list of card addresses. If the +// item selected in the directory pane is not a mailing list, +// an empty string is returned. +function GetSelectedAddressesFromDirTree() +{ + var addresses = ""; + + if (dirTree.currentIndex >= 0) { + var selected = dirTree.contentView.getItemAtIndex(dirTree.currentIndex); + var mailingListUri = selected.id; + var directory = GetDirectoryFromURI(mailingListUri); + if (directory.isMailList) { + var listCardsCount = directory.addressLists.Count(); + var cards = new Array(listCardsCount); + for ( var i = 0; i < listCardsCount; i++ ) { + var card = directory.addressLists.GetElementAt(i); + card = card.QueryInterface(Components.interfaces.nsIAbCard); + cards[i] = card; + } + addresses = GetAddressesForCards(cards); + } + } + return addresses; +} + +function GetSelectedAddresses() +{ + var selectedCards = GetSelectedAbCards(); + return GetAddressesForCards(selectedCards); +} + +// Generate a comma seperate list of addresses from a given +// set of cards. +function GetAddressesForCards(cards) +{ + var addresses = ""; + + if (!cards) + return addresses; + + var count = cards.length; + if (count > 0) + addresses += GenerateAddressFromCard(cards[0]); + + for (var i = 1; i < count; i++) { + var generatedAddress = GenerateAddressFromCard(cards[i]); + + if (generatedAddress) + addresses += ", " + generatedAddress; + } + return addresses; +} + +function GetNumSelectedCards() +{ + try { + var treeSelection = gAbView.selection; + return treeSelection.count; + } + catch (ex) { + } + + // if something went wrong, return 0 for the count. + return 0; +} + +// XXX todo +// an optimization might be to make this return +// the selected ranges, which would be faster +// when the user does large selections, but for now, let's keep it simple. +function GetSelectedRows() +{ + var selectedRows = ""; + + if (!gAbView) + return selectedRows; + + var i,j; + var rangeCount = gAbView.selection.getRangeCount(); + var current = 0; + + for (i=0; i < rangeCount; i++) { + var start = new Object; + var end = new Object; + gAbView.selection.getRangeAt(i,start,end); + for (j=start.value;j<=end.value;j++) { + if (selectedRows) + selectedRows += ","; + selectedRows += j; + } + } + return selectedRows; +} + +function GetSelectedAbCards() +{ + var abView = gAbView; + + // if sidebar is open, and addressbook panel is open and focused, + // then use the ab view from sidebar (gCurFrame is from sidebarOverlay.js) + const abPanelUrl = "chrome://messenger/content/addressbook/addressbook-panel.xul"; + if (document.getElementById("sidebar-box")) { + if (gCurFrame && + gCurFrame.getAttribute("src") == abPanelUrl && + document.commandDispatcher.focusedWindow == gCurFrame.contentDocument.defaultView) + { + abView = gCurFrame.contentDocument.defaultView.gAbView; + } + } + + if (!abView) + return null; + + var cards = new Array(abView.selection.count); + var i,j; + var count = abView.selection.getRangeCount(); + + var current = 0; + + for (i=0; i < count; i++) { + var start = new Object; + var end = new Object; + abView.selection.getRangeAt(i,start,end); + for (j=start.value;j<=end.value;j++) { + cards[current] = abView.getCardFromRow(j); + current++; + } + } + return cards; +} + +function SelectFirstAddressBook() +{ + ChangeDirectoryByURI(kPersonalAddressbookURI); +} + +function SelectFirstCard() +{ + if (gAbView && gAbView.selection) { + gAbView.selection.select(0); + } +} + +function DirPaneClick(event) +{ + // we only care about left button events + if (event.button != 0) + return; + + var searchInput = document.getElementById("searchInput"); + // if there is a searchInput element, and it's not blank + // then we need to act like the user cleared the + // search text + if (searchInput && searchInput.value) { + searchInput.value = ""; + onEnterInSearchBar(); + } +} + +function DirPaneDoubleClick() +{ + if (dirTree && dirTree.treeBoxObject.selection && dirTree.treeBoxObject.selection.count == 1) + AbEditSelectedDirectory(); +} + +function DirPaneSelectionChange() +{ + if (dirTree && dirTree.treeBoxObject.selection && dirTree.treeBoxObject.selection.count == 1) + ChangeDirectoryByURI(GetSelectedDirectory()); +} + +function GetAbResultsBoxObject() +{ + return GetAbResultsTree().treeBoxObject; +} + +var gAbResultsTree = null; + +function GetAbResultsTree() +{ + if (gAbResultsTree) + return gAbResultsTree; + + gAbResultsTree = document.getElementById('abResultsTree'); + return gAbResultsTree; +} + +function CloseAbView() +{ + var boxObject = GetAbResultsBoxObject(); + boxObject.view = null; + + if (gAbView) { + gAbView.close(); + gAbView = null; + } +} + +function SetAbView(uri, sortColumn, sortDirection) +{ + CloseAbView(); + + if (!sortColumn) + sortColumn = kDefaultSortColumn; + + if (!sortDirection) + sortDirection = kDefaultAscending; + + gAbView = Components.classes["@mozilla.org/addressbook/abview;1"].createInstance(Components.interfaces.nsIAbView); + + var actualSortColumn = gAbView.init(uri, GetAbViewListener(), sortColumn, sortDirection); + var boxObject = GetAbResultsBoxObject(); + boxObject.view = gAbView.QueryInterface(Components.interfaces.nsITreeView); + return actualSortColumn; +} + +function GetAbView() +{ + return gAbView; +} + +function GetAbViewURI() +{ + if (gAbView) + return gAbView.URI; + else + return null; +} + +function ChangeDirectoryByURI(uri) +{ + if (!uri) + uri = kPersonalAddressbookURI; + + if (gAbView && gAbView.URI == uri) + return; + + var dataNode = document.getElementById(uri); + var sortColumn = dataNode ? dataNode.getAttribute("sortColumn") : kDefaultSortColumn; + var sortDirection = dataNode ? dataNode.getAttribute("sortDirection") : kDefaultAscending; + + var actualSortColumn = SetAbView(uri, sortColumn, sortDirection); + + UpdateSortIndicators(actualSortColumn, sortDirection); + + // only select the first card if there is a first card + if (gAbView && gAbView.getCardFromRow(0)) { + SelectFirstCard(); + } + else { + // the selection changes if we were switching directories. + ResultsPaneSelectionChanged() + } + return; +} + +function AbSortAscending() +{ + var sortColumn = kDefaultSortColumn; + + if (gAbView) { + var node = document.getElementById(gAbView.URI); + sortColumn = node.getAttribute("sortColumn"); + } + + SortAndUpdateIndicators(sortColumn, kDefaultAscending); +} + +function AbSortDescending() +{ + var sortColumn = kDefaultSortColumn; + + if (gAbView) { + var node = document.getElementById(gAbView.URI); + sortColumn = node.getAttribute("sortColumn"); + } + + SortAndUpdateIndicators(sortColumn, kDefaultDescending); +} + +function SortResultPane(sortColumn) +{ + var sortDirection = kDefaultAscending; + + if (gAbView) { + sortDirection = gAbView.sortDirection; + } + + SortAndUpdateIndicators(sortColumn, sortDirection); +} + +function SortAndUpdateIndicators(sortColumn, sortDirection) +{ + // XXX todo remove once #116341 is fixed + if (!sortColumn) + return; + + UpdateSortIndicators(sortColumn, sortDirection); + + if (gAbView) + gAbView.sortBy(sortColumn, sortDirection); + + SaveSortSetting(sortColumn, sortDirection); +} + +function SaveSortSetting(column, direction) +{ + if (dirTree && gAbView) { + var node = document.getElementById(gAbView.URI); + if (node) { + node.setAttribute("sortColumn", column); + node.setAttribute("sortDirection", direction); + } + } +} + +function UpdateSortIndicators(colID, sortDirection) +{ + var sortedColumn; + // set the sort indicator on the column we are sorted by + if (colID) { + sortedColumn = document.getElementById(colID); + if (sortedColumn) { + sortedColumn.setAttribute("sortDirection",sortDirection); + } + } + + // remove the sort indicator from all the columns + // except the one we are sorted by + var currCol = GetAbResultsTree().firstChild.firstChild; + while (currCol) { + if (currCol != sortedColumn && currCol.localName == "treecol") + currCol.removeAttribute("sortDirection"); + currCol = currCol.nextSibling; + } +} + +function GetAbResultsTree() +{ + if (!gAbResultsTree) + gAbResultsTree = document.getElementById('abResultsTree'); + return gAbResultsTree; +} + + +function InvalidateResultsPane() +{ + var tree = GetAbResultsTree(); + if (tree) { + tree.treeBoxObject.invalidate(); + } +} + +function AbNewList(abListItem) +{ + var selectedAB = GetSelectedAddressBookDirID(abListItem); + + goNewListDialog(selectedAB); +} + +function GetSelectedAddressBookDirID(abListItem) +{ + /*var selectedAB = 0; + var abDirEntries = document.getElementById(abListItem); + + if (abDirEntries && abDirEntries.localName == "tree" && abDirEntries.currentIndex >= 0) { + var selected = abDirEntries.contentView.getItemAtIndex(abDirEntries.currentIndex); + selectedAB = selected.id; + } + + if (!selectedAB && abDirEntries && abDirEntries.localName == "menulist" && abDirEntries.selectedItem) + selectedAB = abDirEntries.selectedItem.getAttribute("id"); + + return selectedAB;*/ + + //var addressbookList = document.getElementById("addressbookList"); + + //return addressbookList.selectedItem.id; + + return kPersonalAddressbookURI; +} + +function goNewListDialog(selectedAB) +{ + window.openDialog("chrome://messenger/content/addressbook/abMailListDialog.xul", + "", + "chrome,resizable=no,titlebar,modal,centerscreen", + {selectedAB:selectedAB}); +} + +function goEditListDialog(abURI, abCard, listURI, okCallback) +{ + window.openDialog("chrome://messenger/content/addressbook/abEditListDialog.xul", + "", + "chrome,resizable=no,titlebar,modal,centerscreen", + {abURI:abURI, abCard:abCard, listURI:listURI, okCallback:okCallback}); +} + +function goNewCardDialog(selectedAB) +{ + window.openDialog("chrome://messenger/content/addressbook/abNewCardDialog.xul", + "", + "chrome,resizable=no,titlebar,modal,centerscreen", + {selectedAB:selectedAB}); +} + +function goEditCardDialog(abURI, card, okCallback) +{ + window.openDialog("chrome://messenger/content/addressbook/abEditCardDialog.xul", + "", + "chrome,resizable=no,modal,titlebar,centerscreen", + {abURI:abURI, card:card, okCallback:okCallback}); +} + + +function setSortByMenuItemCheckState(id, value) +{ + var menuitem = document.getElementById(id); + if (menuitem) { + menuitem.setAttribute("checked", value); + } +} + +function InitViewSortByMenu() +{ + var sortColumn = kDefaultSortColumn; + var sortDirection = kDefaultAscending; + + if (gAbView) { + sortColumn = gAbView.sortColumn; + sortDirection = gAbView.sortDirection; + } + + // this approach is necessary to support generic columns that get overlayed. + var elements = document.getElementsByAttribute("name","sortas"); + for (var i=0; i