Bug 1308776 - Add choosing of default addressbook from preferences dialog and a context menu. ui-r=Paenglab, r=mkmelin,jorgk,frgrahl a=jorgk
--- a/mail/components/addrbook/content/abCommon.js
+++ b/mail/components/addrbook/content/abCommon.js
@@ -40,16 +40,17 @@ var DirPaneController =
{
supportsCommand: function(command)
{
switch (command) {
case "cmd_selectAll":
case "cmd_delete":
case "button_delete":
case "cmd_properties":
+ case "cmd_abToggleStartupDir":
case "cmd_printcard":
case "cmd_printcardpreview":
case "cmd_newlist":
case "cmd_newCard":
return true;
default:
return false;
}
@@ -131,16 +132,18 @@ var DirPaneController =
goSetLabelAccesskeyTooltiptext("cmd_properties-button", null, null,
tooltipTextAttr);
goSetLabelAccesskeyTooltiptext("cmd_properties-contextMenu",
labelAttr, accKeyAttr);
goSetLabelAccesskeyTooltiptext("cmd_properties-menu",
labelAttr, accKeyAttr);
return (selectedDir != null);
}
+ case "cmd_abToggleStartupDir":
+ return !!getSelectedDirectoryURI();
case "cmd_newlist":
case "cmd_newCard":
return true;
default:
return false;
}
},
@@ -155,16 +158,19 @@ var DirPaneController =
case "cmd_delete":
case "button_delete":
if (gDirTree)
AbDeleteSelectedDirectory();
break;
case "cmd_properties":
AbEditSelectedDirectory();
break;
+ case "cmd_abToggleStartupDir":
+ abToggleSelectedDirStartup();
+ break;
case "cmd_newlist":
AbNewList();
break;
case "cmd_newCard":
AbNewCard();
break;
}
},
@@ -213,16 +219,51 @@ function AbEditSelectedDirectory()
} else {
window.openDialog(selectedDir.propertiesChromeURI,
"",
"chrome,modal,resizable=no,centerscreen",
{selectedDirectory: selectedDir});
}
}
+function updateDirTreeContext() {
+ let startupItem = document.getElementById("dirTreeContext-startupDir");
+ if (Services.prefs.getBoolPref("mail.addr_book.view.startupURIisDefault")) {
+ let startupURI = Services.prefs.getCharPref("mail.addr_book.view.startupURI");
+ let selectedDirURI = getSelectedDirectoryURI();
+ startupItem.setAttribute("checked", (startupURI == selectedDirURI));
+ } else {
+ startupItem.setAttribute("checked", "false");
+ }
+}
+
+function abToggleSelectedDirStartup()
+{
+ let selectedDirURI = getSelectedDirectoryURI();
+ if (!selectedDirURI)
+ return;
+
+ let isDefault = Services.prefs.getBoolPref("mail.addr_book.view.startupURIisDefault");
+ let startupURI = Services.prefs.getCharPref("mail.addr_book.view.startupURI");
+
+ if (isDefault && (startupURI == selectedDirURI)) {
+ // The current directory has been the default startup view directory;
+ // toggle that off now. So there's no default startup view directory any more.
+ Services.prefs.setBoolPref("mail.addr_book.view.startupURIisDefault", false);
+ } else {
+ // The current directory will now be the default view
+ // when starting up the main AB window.
+ Services.prefs.setCharPref("mail.addr_book.view.startupURI", selectedDirURI);
+ Services.prefs.setBoolPref("mail.addr_book.view.startupURIisDefault", true);
+ }
+
+ // Update the checkbox in the menuitem.
+ goUpdateCommand("cmd_abToggleStartupDir");
+}
+
function AbDeleteSelectedDirectory()
{
let selectedDirURI = getSelectedDirectoryURI();
if (!selectedDirURI)
return;
AbDeleteDirectory(selectedDirURI);
}
--- a/mail/components/addrbook/content/addressbook.js
+++ b/mail/components/addrbook/content/addressbook.js
@@ -287,16 +287,17 @@ function onOSXFileMenuInit()
.setAttribute("checked", AbOSXAddressBookExists());
}
function CommandUpdate_AddressBook()
{
goUpdateCommand('cmd_delete');
goUpdateCommand('button_delete');
goUpdateCommand('cmd_properties');
+ goUpdateCommand("cmd_abToggleStartupDir");
goUpdateCommand('cmd_newlist');
goUpdateCommand('cmd_newCard');
goUpdateCommand('cmd_chatWithCard');
}
function ResultsPaneSelectionChanged()
{
UpdateCardView();
--- a/mail/components/addrbook/content/addressbook.xul
+++ b/mail/components/addrbook/content/addressbook.xul
@@ -195,26 +195,32 @@
#ifdef XP_MACOSX
<!-- Mac Window keys -->
<key id="key_minimizeWindow" command="minimizeWindow" key="&minimizeWindow.key;" modifiers="accel"/>
#endif
</keyset>
<keyset id="baseMenuKeyset"/>
-<menupopup id="dirTreeContext">
+<menupopup id="dirTreeContext" onpopupshowing="updateDirTreeContext();">
<menuitem id="dirTreeContext-properties"
command="cmd_properties-contextMenu"/>
<menuseparator/>
<menuitem id="dirTreeContext-newcard" label="&newContactButton.label;"
accesskey="&newContactButton.accesskey;" command="cmd_newCard"/>
<menuitem id="dirTreeContext-newlist"
label="&newlistButton.label;"
accesskey="&newlistButton.accesskey;"
command="cmd_newlist"/>
+ <menuitem id="dirTreeContext-startupDir"
+ label="&showAsDefault.label;"
+ accesskey="&showAsDefault.accesskey;"
+ type="checkbox"
+ checked="false"
+ oncommand="goDoCommand('cmd_abToggleStartupDir');"/>
<menuseparator/>
<menuitem id="dirTreeContext-delete"
label="&deleteButton2.label;"
accesskey="&deleteButton2.accesskey;"
observes="button_delete"
oncommand="goDoCommand('button_delete');"/>
</menupopup>
--- a/mail/components/preferences/compose.js
+++ b/mail/components/preferences/compose.js
@@ -21,16 +21,18 @@ var gComposePane = {
this.populateFonts();
this.updateAutosave();
this.updateAttachmentCheck();
this.updateEmailCollection();
+ this.initAbDefaultStartupDir();
+
if (!(("arguments" in window) && window.arguments[1])) {
// If no tab was specified, select the last used tab.
let preference = document.getElementById("mail.preferences.compose.selectedTabIndex");
if (preference.value)
document.getElementById("composePrefs").selectedIndex = preference.value;
}
if (this._loadInContent) {
@@ -111,16 +113,50 @@ var gComposePane = {
if (this._loadInContent) {
gSubDialog.open("chrome://messenger/content/addressbook/pref-editdirectories.xul");
} else {
window.openDialog("chrome://messenger/content/addressbook/pref-editdirectories.xul",
"editDirectories", "chrome,modal=yes,resizable=no", null);
}
},
+ initAbDefaultStartupDir: function() {
+ if (!this.startupDirListener.inited)
+ this.startupDirListener.load();
+
+ let dirList = document.getElementById("defaultStartupDirList");
+ if (Services.prefs.getBoolPref("mail.addr_book.view.startupURIisDefault")) {
+ // Some directory is the default.
+ let startupURI = Services.prefs.getCharPref("mail.addr_book.view.startupURI");
+ let dirItem = dirList.menupopup.querySelector('[value="' + startupURI + '"]');
+ // It may happen that the stored URI is not in the list.
+ // In that case select the "none" value and let the AB code clear out
+ // the invalid value, unless the user selects something here.
+ if (dirItem)
+ dirList.selectedItem = dirItem;
+ else
+ dirList.value = "";
+ } else {
+ // Choose item meaning there is no default startup directory any more.
+ dirList.value = "";
+ }
+ },
+
+ setDefaultStartupDir: function(aDirURI) {
+ if (aDirURI) {
+ // Some AB directory was selected. Set prefs to make this directory
+ // the default view when starting up the main AB.
+ Services.prefs.setCharPref("mail.addr_book.view.startupURI", aDirURI);
+ Services.prefs.setBoolPref("mail.addr_book.view.startupURIisDefault", true);
+ } else {
+ // Set pref that there's no default startup view directory any more.
+ Services.prefs.setBoolPref("mail.addr_book.view.startupURIisDefault", false);
+ }
+ },
+
initLanguageMenu: function ()
{
var languageMenuList = document.getElementById("languageMenuList");
this.mSpellChecker = Components.classes['@mozilla.org/spellchecker/engine;1'].getService(Components.interfaces.mozISpellCheckingEngine);
var o1 = {};
var o2 = {};
// Get the list of dictionaries from
@@ -170,17 +206,17 @@ var gComposePane = {
localFonts[i] != "sans-serif" && localFonts[i] != "monospace")
fontsList.appendItem(localFonts[i], localFonts[i]);
}
}
catch(e) { }
// Choose the item after the list is completely generated.
var preference = document.getElementById(fontsList.getAttribute("preference"));
fontsList.value = preference.value;
- },
+ },
restoreHTMLDefaults: function()
{
// reset throws an exception if the pref value is already the default so
// work around that with some try/catch exception handling
try {
document.getElementById('msgcompose.font_face').reset();
} catch (ex) {}
@@ -191,10 +227,35 @@ var gComposePane = {
try {
document.getElementById('msgcompose.text_color').reset();
} catch (ex) {}
try {
document.getElementById('msgcompose.background_color').reset();
} catch (ex) {}
- }
+ },
+
+ startupDirListener: {
+ inited: false,
+ domain: "mail.addr_book.view.startupURI",
+ observe: function(subject, topic, prefName) {
+ if (topic != "nsPref:changed")
+ return;
+
+ // If the default startup directory prefs have changed,
+ // reinitialize the default startup dir picker to show the new value.
+ gComposePane.initAbDefaultStartupDir();
+ },
+ load: function() {
+ // Observe changes of our prefs.
+ Services.prefs.addObserver(this.domain, this, false);
+ // Unload the pref observer when preferences window is closed.
+ window.addEventListener("unload", this.unload, true);
+ this.inited = true;
+ },
+
+ unload: function(event) {
+ Services.prefs.removeObserver(gComposePane.startupDirListener.domain,
+ gComposePane.startupDirListener);
+ }
+ }
};
--- a/mail/components/preferences/compose.xul
+++ b/mail/components/preferences/compose.xul
@@ -214,16 +214,27 @@
oncommand="gComposePane.updateEmailCollection();"/>
<menulist id="localDirectoriesList" flex="1"
preference="mail.collect_addressbook"
aria-labelledby="emailCollectionOutgoing">
<menupopup id="abPopup-menupopup" class="addrbooksPopup"
localonly="true" writable="true"/>
</menulist>
</hbox>
+
+ <hbox align="center" pack="start">
+ <label value="&showAsDefault.label;" accesskey="&showAsDefault.accesskey;"/>
+ <menulist id="defaultStartupDirList" flex="1"
+ oncommand="gComposePane.setDefaultStartupDir(this.value);">
+ <menupopup class="addrbooksPopup"
+ none="&showAsDefaultLast.label;"
+ alladdressbooks="true"
+ mailinglists="true"/>
+ </menulist>
+ </hbox>
</tabpanel>
<tabpanel orient="vertical">
<hbox>
<checkbox id="spellCheckBeforeSend"
label="&spellCheck.label;"
preference="mail.SpellCheckBeforeSend"
accesskey="&spellCheck.accesskey;"/>
--- a/mail/locales/en-US/chrome/messenger/addressbook/abMainWindow.dtd
+++ b/mail/locales/en-US/chrome/messenger/addressbook/abMainWindow.dtd
@@ -135,16 +135,18 @@ because displayed names don't have the c
<!ENTITY preferencesCmdUnix.label "Preferences">
<!ENTITY preferencesCmdUnix.accesskey "n">
<!-- Address Book Toolbar and Context Menus -->
<!ENTITY newContactButton.label "New Contact">
<!ENTITY newContactButton.accesskey "C">
<!ENTITY newlistButton.label "New List">
<!ENTITY newlistButton.accesskey "L">
+<!ENTITY showAsDefault.label "Default startup directory">
+<!ENTITY showAsDefault.accesskey "S">
<!ENTITY editPropertiesButton.label "Edit">
<!ENTITY propertiesContext.label "Properties">
<!ENTITY propertiesContext.accesskey "i">
<!ENTITY abPropertiesContext.label "Properties">
<!ENTITY abPropertiesContext.accesskey "i">
<!ENTITY editContactContext.label "Edit Contact">
<!ENTITY editContactContext.accesskey "E">
<!ENTITY editMailingListContext.label "Edit List">
--- a/mail/locales/en-US/chrome/messenger/preferences/compose.dtd
+++ b/mail/locales/en-US/chrome/messenger/preferences/compose.dtd
@@ -49,16 +49,19 @@
<!ENTITY autocompleteText.label "When addressing messages, look for matching entries in:">
<!ENTITY addressingEnable.label "Local Address Books">
<!ENTITY addressingEnable.accesskey "L">
<!ENTITY directories.label "Directory Server:">
<!ENTITY directories.accesskey "D">
<!ENTITY directoriesNone.label "None">
<!ENTITY editDirectories.label "Edit Directories…">
<!ENTITY editDirectories.accesskey "E">
+<!ENTITY showAsDefault.label "Default startup directory in the address book window:">
+<!ENTITY showAsDefault.accesskey "S">
+<!ENTITY showAsDefaultLast.label "Last used directory">
<!ENTITY sendOptionsDescription.label "Configure text format behavior">
<!ENTITY sendOptions.label "Send Options…">
<!ENTITY sendOptions.accesskey "S">
<!ENTITY attachmentReminder.label "Check for missing attachments">
<!ENTITY attachmentReminder.accesskey "m">
<!ENTITY attachmentReminderOptions.label "Keywords…">
--- a/mail/themes/shared/mail/messenger.css
+++ b/mail/themes/shared/mail/messenger.css
@@ -77,8 +77,26 @@ notification[value="addon-install-failed
@keyframes highlight {
from { background-color: Highlight; }
to { background-color: transparent; }
}
#findbar-beforeReplaceSeparator {
height: 16px;
}
+
+/* ::::: Address Book menuitem icons ::::: */
+
+.abMenuItem[AddrBook="true"] {
+ list-style-image: url("chrome://messenger/skin/addressbook/icons/addrbook.png");
+}
+
+.abMenuItem[MailList="true"] {
+ list-style-image: url("chrome://messenger/skin/addressbook/icons/ablist.png");
+}
+
+.abMenuItem[AddrBook="true"][IsRemote="true"] {
+ list-style-image: url("chrome://messenger/skin/addressbook/icons/remote-addrbook.png");
+}
+
+.abMenuItem[AddrBook="true"][IsRemote="true"][IsSecure="true"] {
+ list-style-image: url("chrome://messenger/skin/addressbook/icons/secure-remote-addrbook.png");
+}
--- a/mailnews/addrbook/content/addrbookWidgets.xml
+++ b/mailnews/addrbook/content/addrbookWidgets.xml
@@ -13,134 +13,181 @@
<implementation implements="nsIAbListener">
<!-- A cache of nsIAbDirectory objects. -->
<field name="_directories">[]</field>
<!-- Represents the nsIAbDirectory attribute used as the value of the
parent menulist. Defaults to URI but can be e.g. dirPrefId -->
<field name="_value">this.getAttribute("value") || "URI"</field>
+ <field name="_stringBundle">null</field>
+
<constructor>
<![CDATA[
- Components.utils.import("resource:///modules/mailServices.js");
- // Init the address book cache.
- const nsIAbDirectory = Components.interfaces.nsIAbDirectory;
- let directories = MailServices.ab.directories;
- while (directories && directories.hasMoreElements()) {
- var ab = directories.getNext();
- if (ab instanceof nsIAbDirectory && this._matches(ab))
- this._directories.push(ab);
- }
-
- this._directories.sort(this._compare);
+ Components.utils.import("resource:///modules/mailServices.js", this);
+ Components.utils.import("resource:///modules/iteratorUtils.jsm", this);
+ Components.utils.import("resource:///modules/StringBundle.js", this);
+ this._stringBundle = new this
+ .StringBundle("chrome://messenger/locale/addressbook/addressBook.properties");
- // Now create menuitems for all displayed directories.
- var menulist = this.parentNode;
- var value = this._value;
- this._directories.forEach(function (ab) {
- menulist.appendItem(ab.dirName, ab[value]);
- });
- if (this.hasAttribute("none")) {
- // Create a dummy menuitem representing no selection.
- this._directories.unshift(null);
- menulist.insertItemAt(0, this.getAttribute("none"), "");
- }
-
- // Attempt to select the persisted or otherwise first directory.
- menulist.value = menulist.value;
- if (!menulist.selectedItem && this.hasChildNodes())
- menulist.selectedIndex = 0;
-
+ this._rebuild();
const nsIAbListener = Components.interfaces.nsIAbListener;
// Add a listener so we can update correctly if the list should change
- MailServices.ab.addAddressBookListener(this,
- nsIAbListener.itemAdded |
- nsIAbListener.directoryRemoved |
- nsIAbListener.itemChanged);
+ this.MailServices.ab
+ .addAddressBookListener(this,
+ nsIAbListener.itemAdded |
+ nsIAbListener.directoryItemRemoved |
+ nsIAbListener.directoryRemoved |
+ nsIAbListener.itemChanged);
]]>
</constructor>
<destructor>
<![CDATA[
- Components.utils.import("resource:///modules/mailServices.js");
- MailServices.ab.removeAddressBookListener(this);
+ this.MailServices.ab.removeAddressBookListener(this);
+
+ this._teardown();
+ ]]>
+ </destructor>
+
+ <method name="_rebuild">
+ <parameter name="aSelectValue"/>
+ <body><![CDATA[
+ // Init the address book cache.
+ this._directories.length = 0;
+ const nsIAbDirectory = Components.interfaces.nsIAbDirectory;
+ let directories = this.MailServices.ab.directories;
+ while (directories && directories.hasMoreElements()) {
+ let ab = directories.getNext();
+ if ((ab instanceof nsIAbDirectory) && this._matches(ab)) {
+ this._directories.push(ab);
+ if (this.getAttribute("mailinglists") == "true") {
+ // Also append contained mailinglists.
+ for (let list of this.fixIterator(ab.childNodes, Components.interfaces.nsIAbDirectory)) {
+ if (this._matches(list))
+ this._directories.push(list);
+ }
+ }
+ }
+ }
+
+ this._sort();
+
+ this._teardown();
+
+ // Now create menuitems for all displayed directories.
+ let menulist = this.parentNode;
+ let value = this._value;
+ for (let ab of this._directories) {
+ let listItem = menulist.appendItem(ab.dirName, ab[value]);
+ listItem.setAttribute("class", "menuitem-iconic abMenuItem");
+ // Style the items by type.
+ if (ab.isMailList)
+ listItem.setAttribute("MailList", "true");
+ else
+ listItem.setAttribute("AddrBook", "true");
+
+ if (ab.isRemote)
+ listItem.setAttribute("IsRemote", "true");
+ if (ab.isSecure)
+ listItem.setAttribute("IsSecure", "true");
+ }
+
+ if (this.hasAttribute("alladdressbooks")) {
+ // Insert a menuitem representing All addressbooks.
+ let allABLabel = this.getAttribute("alladdressbooks");
+ if (allABLabel == "true")
+ allABLabel = this._stringBundle.getString("allAddressBooks");
+ const allABURI = "moz-abdirectory://?";
+ this._directories.unshift(null);
+ let listItem = menulist.insertItemAt(0, allABLabel, allABURI);
+ listItem.setAttribute("class", "menuitem-iconic abMenuItem");
+ listItem.setAttribute("AddrBook", "true");
+ listItem.setAttribute("IsAllAB", "true");
+ }
+
+ if (this.hasAttribute("none")) {
+ // Create a dummy menuitem representing no selection.
+ this._directories.unshift(null);
+ let listItem = menulist.insertItemAt(0, this.getAttribute("none"), "");
+ listItem.setAttribute("class", "menuitem-iconic abMenuItem");
+ listItem.setAttribute("IsNone", "true");
+ }
+
+ // Attempt to select the persisted or otherwise first directory.
+ menulist.value = aSelectValue || this.parentNode.value;
+ if (!menulist.selectedItem && this.hasChildNodes())
+ menulist.selectedIndex = 0;
+ ]]></body>
+ </method>
+
+ <method name="_teardown">
+ <body><![CDATA[
// Empty out anything in the list.
+ // (Don't use menulist.removeAllItems() as it would remove
+ // the menupopup with our special attributes too.)
while (this.hasChildNodes())
this.lastChild.remove();
- ]]>
- </destructor>
+ ]]></body>
+ </method>
<!-- nsIAbListener methods -->
<method name="onItemAdded">
<parameter name="aParentDir"/>
<parameter name="aItem"/>
<body><![CDATA[
// Are we interested in this new directory?
if (aItem instanceof Components.interfaces.nsIAbDirectory &&
- !aItem.isMailList && this._matches(aItem)) {
- this._directories.push(aItem);
- this._directories.sort(this._compare);
- // Insert the new menuitem at the position to which it was sorted.
- this.parentNode.insertItemAt(this._directories.indexOf(aItem),
- aItem.dirName, aItem[this._value]);
+ this._matches(aItem)) {
+ this._rebuild();
}
]]></body>
</method>
<method name="onItemRemoved">
<parameter name="aParentDir"/>
<parameter name="aItem"/>
<body><![CDATA[
- if (aItem instanceof Components.interfaces.nsIAbDirectory &&
- !aItem.isMailList) {
- // Find the item in the list to remove
- // We can't use indexOf here because we need loose equality
+ if (aItem instanceof Components.interfaces.nsIAbDirectory) {
+ // Find the item in the list to remove.
+ // We can't use indexOf here because we need loose equality.
for (var index = this._directories.length; --index >= 0; )
if (this._directories[index] == aItem)
break;
- if (index != -1)
+ if (index != -1) {
+ this._directories.splice(index, 1);
// Are we removing the selected directory?
if (this.parentNode.selectedItem ==
- this.removeChild(this.childNodes[index]))
+ this.removeChild(this.childNodes[index])) {
// If so, try to select the first directory, if available.
if (this.hasChildNodes())
this.firstChild.doCommand();
else
this.parentNode.selectedItem = null;
+ }
+ }
}
]]></body>
</method>
<method name="onItemPropertyChanged">
<parameter name="aItem"/>
<parameter name="aProperty"/>
<parameter name="aOldValue"/>
<parameter name="aNewValue"/>
<body><![CDATA[
- if (aItem instanceof Components.interfaces.nsIAbDirectory &&
- !aItem.isMailList) {
+ if (aItem instanceof Components.interfaces.nsIAbDirectory) {
// Find the item in the list to rename.
- // We can't use indexOf here because we need loose equality
+ // We can't use indexOf here because we need loose equality.
for (var oldIndex = this._directories.length; --oldIndex >= 0; )
if (this._directories[oldIndex] == aItem)
break;
- if (oldIndex != -1) {
- // Cache the matching item so that we can use indexOf next time.
- aItem = this._directories[oldIndex];
- var child = this.childNodes[oldIndex];
- child.label = aItem.dirName;
- this._directories.sort(this._compare);
- // Reorder the menuitems if renaming changed the directory index.
- var newIndex = this._directories.indexOf(aItem);
- if (newIndex < oldIndex)
- this.insertBefore(child, this.childNodes[newIndex]);
- else if (newIndex > oldIndex)
- this.insertBefore(child, this.childNodes[newIndex].nextSibling);
- }
+ if (oldIndex != -1)
+ this._rebuild();
}
]]></body>
</method>
<!-- Private methods -->
<!-- Tests to see whether this directory should display in the list. -->
<method name="_matches">
<parameter name="ab"/>
@@ -153,16 +200,53 @@
if (this.getAttribute("supportsmaillists") == "true" &&
!ab.supportsMailingLists)
return false;
return this.getAttribute(ab.isRemote ? "localonly" : "remoteonly") != "true";
]]></body>
</method>
+ <!-- Sort all our directories. -->
+ <method name="_sort">
+ <body><![CDATA[
+ let lists = {};
+ let lastAB;
+ // If there are any mailing lists, pull them out of the array temporarily.
+ for (let d = 0; d < this._directories.length; d++) {
+ if (this._directories[d].isMailList) {
+ let [list] = this._directories.splice(d, 1);
+ if (!(lastAB in lists))
+ lists[lastAB] = [];
+ lists[lastAB].push(list);
+ d--;
+ } else {
+ lastAB = this._directories[d].URI;
+ }
+ }
+
+ this._directories.sort(this._compare);
+
+ // Push mailing lists back appending them after their respective
+ // containing addressbook.
+ for (let d = this._directories.length - 1; d >= 0; d--) {
+ let abURI = this._directories[d].URI;
+ if (abURI in lists) {
+ lists[abURI].sort(function(a,b) { return a.dirName.localeCompare(b.dirName); });
+ let listIndex = d;
+ for (let list of lists[abURI]) {
+ listIndex++;
+ this._directories.splice(listIndex, 0, list);
+ }
+ delete lists[abURI];
+ }
+ }
+ ]]></body>
+ </method>
+
<!-- Used to sort directories in order -->
<method name="_compare">
<parameter name="a"/>
<parameter name="b"/>
<body><![CDATA[
// Null at the very top.
if (!a)
return -1;