Reland Bug 449260 Replace rdf-driven addressbook popup menus with xbl based one with added protection against recursion. r=philor,sr=Neil
authorMark Banner <bugzilla@standard8.plus.com>
Thu, 14 Aug 2008 13:14:48 +0100
changeset 97 bbb70f28e335b301cef033dbc62b715c7c224ee7
parent 96 458c052c75cbef2edd85ba59d1291133139ed702
child 98 840d841a0a860eef3dc6728e9f0727611dff5432
push idunknown
push userunknown
push dateunknown
reviewersphilor, Neil
bugs449260
Reland Bug 449260 Replace rdf-driven addressbook popup menus with xbl based one with added protection against recursion. r=philor,sr=Neil
mail/base/content/ABSearchDialog.js
mail/base/content/ABSearchDialog.xul
mail/base/content/messenger.css
mail/components/addrbook/content/abCardOverlay.js
mail/components/addrbook/content/abCommon.js
mail/components/addrbook/content/abContactsPanel.js
mail/components/addrbook/content/abContactsPanel.xul
mail/components/addrbook/content/abEditListDialog.xul
mail/components/addrbook/content/abMailListDialog.xul
mail/components/addrbook/jar.mn
mailnews/addrbook/resources/content/abCardOverlay.js
mailnews/addrbook/resources/content/abCommon.js
mailnews/addrbook/resources/content/abMailListDialog.xul
mailnews/addrbook/resources/content/abNewCardDialog.xul
mailnews/addrbook/resources/content/abSelectAddressesDialog.js
mailnews/addrbook/resources/content/abSelectAddressesDialog.xul
mailnews/addrbook/resources/content/addrbookWidgets.xml
mailnews/addrbook/resources/content/addressbook-panel.js
mailnews/addrbook/resources/content/addressbook-panel.xul
mailnews/base/resources/content/messenger.css
mailnews/base/search/resources/content/ABSearchDialog.js
mailnews/base/search/resources/content/ABSearchDialog.xul
mailnews/jar.mn
--- a/mail/base/content/ABSearchDialog.js
+++ b/mail/base/content/ABSearchDialog.js
@@ -91,16 +91,19 @@ function searchOnLoad()
                               .getService(Components.interfaces.nsIPrefService);
   var prefBranch = prefService.getBranch(null).QueryInterface(Components.interfaces.nsIPrefBranch2);
   gSearchPhoneticName =
         prefBranch.getComplexValue("mail.addr_book.show_phonetic_fields", 
                                    Components.interfaces.nsIPrefLocalizedString).data;
 
   if (window.arguments && window.arguments[0])
     SelectDirectory(window.arguments[0].directory);
+  else
+    SelectDirectory(document.getElementById("abPopup-menupopup")
+                            .firstChild.value);
 
   // initialize globals, see abCommon.js, InitCommonJS()
   abList = document.getElementById("abPopup");
 
   onMore(null);
 }
 
 function searchOnUnload()
@@ -362,16 +365,8 @@ function UpdateCardView()
 
   gComposeButton.removeAttribute("disabled");
 
   if (numSelected == 1) 
     gPropertiesButton.removeAttribute("disabled");
   else
     gPropertiesButton.setAttribute("disabled","true");
 }
-
-function onChooseDirectory(event) 
-{
-    var directoryURI = event.id;
-    if (directoryURI) {
-        SelectDirectory(directoryURI);
-    }
-}
--- a/mail/base/content/ABSearchDialog.xul
+++ b/mail/base/content/ABSearchDialog.xul
@@ -48,17 +48,16 @@
 /abResultsPaneOverlay.dtd">
 %abResultsPaneOverlayDTD;
 <!ENTITY % SearchDialogDTD SYSTEM "chrome://messenger/locale/SearchDialog.dtd">
 %SearchDialogDTD;
 ]>
 
 <window id="searchAddressBookWindow"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        xmlns:nc="http://home.netscape.com/NC-rdf#"
         onload="searchOnLoad();"
         onunload="searchOnUnload();"
         onclose="onSearchStop();"
         windowtype="mailnews:absearch"
         title="&abSearchDialogTitle.label;"
         style="width: 52em; height: 34em;"
         persist="screenX screenY width height sizemode">
 
@@ -83,31 +82,18 @@
   </keyset>
 
   <dummy class="usesMailWidgets"/>
     
     <vbox id="searchTerms" flex="3" persist="height">
       <vbox>
         <hbox align="center">
           <label value="&abSearchHeading.label;" accesskey="&abSearchHeading.accesskey;" control="abPopup"/>
-          <menulist id="abPopup">
-            <menupopup id="abPopup-menupopup" ref="moz-abdirectory://"
-                       datasources="rdf:addressdirectory"
-                       sortActive="true"
-                       sortDirection="ascending"
-                       sortResource="http://home.netscape.com/NC-rdf#DirTreeNameSort"
-                       oncommand="onChooseDirectory(event.target);">
-              <template>
-                <rule nc:IsMailList="false">
-                  <menuitem uri="..."
-                            label="rdf:http://home.netscape.com/NC-rdf#DirName"
-                            value="rdf:http://home.netscape.com/NC-rdf#DirUri"/>
-                </rule>
-              </template>
-            </menupopup>
+          <menulist id="abPopup" oncommand="SelectDirectory(this.value);">
+            <menupopup id="abPopup-menupopup" class="addrbooksPopup"/>
           </menulist>
           <spacer flex="10"/>
           <button id="search-button" oncommand="onSearchButton(event);" default="true"/>
         </hbox>
         <hbox align="center">
           <spacer flex="1"/>
           <button label="&resetButton.label;" oncommand="onAbSearchReset(event);" accesskey="&resetButton.accesskey;"/>
         </hbox>
--- a/mail/base/content/messenger.css
+++ b/mail/base/content/messenger.css
@@ -257,8 +257,12 @@ tabmail
 
 .tabs-alltabs-popup {
   -moz-binding: url("chrome://messenger/content/tabmail.xml#tabmail-alltabs-popup");
 }
 
 menupopup[type="folder"] {
   -moz-binding: url("chrome://messenger/content/folderWidgets.xml#folder-menupopup");
 }
+
+.addrbooksPopup {
+  -moz-binding: url("chrome://messenger/content/addressbook/addrbookWidgets.xml#addrbooks-menupopup");
+}
--- a/mail/components/addrbook/content/abCardOverlay.js
+++ b/mail/components/addrbook/content/abCardOverlay.js
@@ -371,17 +371,17 @@ function NewCardOKButton()
 
     gOkCallback(gEditCard.card.translateTo("vcard"));
     return true;  // close the window
   }
 
   var popup = document.getElementById('abPopup');
   if ( popup )
   {
-    var uri = popup.getAttribute('value');
+    var uri = popup.value;
 
     // FIX ME - hack to avoid crashing if no ab selected because of blank option bug from template
     // should be able to just remove this if we are not seeing blank lines in the ab popup
     if ( !uri )
       return false;  // don't close window
     // -----
 
     if (gEditCard.card)
--- a/mail/components/addrbook/content/abCommon.js
+++ b/mail/components/addrbook/content/abCommon.js
@@ -85,17 +85,17 @@ var DirPaneController =
         // only handles single selection
         // so we forward select all to the results pane
         // but if there is no gAbView
         // don't bother sending to the results pane
         return (gAbView != null);
       case "cmd_delete":
       case "button_delete":
         var selectedDir = GetSelectedDirectory();
-        if (command == "cmd_delete")
+        if (command == "cmd_delete" && selectedDir)
           goSetMenuValue(command, GetDirectoryFromURI(selectedDir).isMailList ?
                                   "valueList" : "valueAddressBook");
 
         if (selectedDir &&
 	    (selectedDir != kPersonalAddressbookURI) &&
 	    (selectedDir != kCollectedAddressbookURI)) {
           // If the directory is a mailing list, and it is read-only, return
           // false.
@@ -605,17 +605,17 @@ function DirPaneHasFocus()
 {
   // returns true if diectory pane has the focus. Returns false, otherwise.
   return (top.document.commandDispatcher.focusedElement == dirTree)
 }
 
 function GetSelectedDirectory()
 {
   if (abList)
-    return abList.selectedItem.id;
+    return abList.value;
   else {
     if (dirTree.currentIndex < 0)
       return null;
     var selected = dirTree.builderView.getResourceAtIndex(dirTree.currentIndex)
     return selected.Value;
   }
 }
 
--- a/mail/components/addrbook/content/abContactsPanel.js
+++ b/mail/components/addrbook/content/abContactsPanel.js
@@ -69,72 +69,22 @@ function addSelectedAddresses(recipientT
   {
     // turn each card into a properly formatted address 
     var address = GenerateAddressFromCard(cards[i]);
     if (address != "")
       parent.AddRecipient(recipientType, address);     
   }
 }
 
-var gAddressBookPanelAbListener = {
-  onItemAdded: function(parentDir, item) {
-    // will not be called
-  },
-  onItemRemoved: function(parentDir, item) {
-    // will only be called when an addressbook is deleted
-    try {
-      var directory = item.QueryInterface(Components.interfaces.nsIAbDirectory);
-      // check if the item being removed is the directory
-      // that we are showing in the addressbook sidebar
-      // if so, select the person addressbook (it can't be removed)
-      var abPopup = document.getElementById('addressbookList');
-      if (directory.URI == abPopup.value) {
-          abPopup.value = kPersonalAddressbookURI;
-          LoadPreviouslySelectedAB();
-      } 
-    }
-    catch (ex) {
-    }
-  },
-  onItemPropertyChanged: function(item, property, oldValue, newValue) {
-    try {
-      var directory = item.QueryInterface(Components.interfaces.nsIAbDirectory);
-      // check if the item being changed is the directory
-      // that we are showing in the addressbook sidebar
-      if (directory == GetAbView().directory) {
-          LoadPreviouslySelectedAB();
-      }
-    }
-    catch (ex) {
-    }
-  }
-};
-
-
-// XXX todo
-// can we combine some common code?  see OnLoadNewMailList()
-// set popup with address book names
-function LoadPreviouslySelectedAB()
-{
-  var abPopup = document.getElementById('addressbookList');
-  var value = abPopup.value || kPersonalAddressbookURI;
-  abPopup.selectedItem = null;
-  abPopup.value = value;
-  ChangeDirectoryByURI(abPopup.selectedItem.id);
-}
-
 function AddressBookMenuListChange()
 {
   if (gSearchInput.value && !gSearchInput.showingSearchCriteria) 
     onEnterInSearchBar();
   else 
-  {
-    var abPopup = document.getElementById('addressbookList');
-    ChangeDirectoryByURI(abPopup.selectedItem.id);
-  }
+    ChangeDirectoryByURI(document.getElementById('addressbookList').value);
 }
 
 function AbPanelOnComposerClose()
 {
   CloseAbView();
   onClearSearch();
 }
 
@@ -144,52 +94,49 @@ function AbPanelOnComposerReOpen()
 }
 
 function AbPanelLoad() 
 {
   InitCommonJS();
 
   document.title = parent.document.getElementById("sidebar-title").value;
 
-  LoadPreviouslySelectedAB();
+  var abPopup = document.getElementById('addressbookList');
 
-  // Add a listener, so we can switch directories if the current directory is
-  // deleted, and change the name if the selected directory's name is modified.
-  // This listener only cares when a directory is removed or modified.
-  Components.classes["@mozilla.org/abmanager;1"]
-            .getService(Components.interfaces.nsIAbManager)
-            .addAddressBookListener(gAddressBookPanelAbListener,
-                                    nsIAbListener.directoryRemoved |
-                                    nsIAbListener.itemChanged);
+  // Reselect the persisted address book if possible, if not just select the
+  // first in the list.
+  var temp = abPopup.value;
+  abPopup.selectedItem = null;
+  abPopup.value = temp;
+  if (!abPopup.selectedItem)
+    abPopup.selectedIndex = 0;
+
+  ChangeDirectoryByURI(abPopup.value);
 
   parent.addEventListener("compose-window-close", AbPanelOnComposerClose, true);
   parent.addEventListener("compose-window-reopen", AbPanelOnComposerReOpen, true);
   gSearchInput = document.getElementById("searchInput");
 }
 
 function AbPanelUnload()
 {
-  Components.classes["@mozilla.org/abmanager;1"]
-            .getService(Components.interfaces.nsIAbManager)
-            .removeAddressBookListener(gAddressBookPanelAbListener);
-
   parent.removeEventListener("compose-window-close", AbPanelOnComposerClose, true);
   parent.removeEventListener("compose-window-reopen", AbPanelOnComposerReOpen, true);
 
   CloseAbView();
 }
 
 function AbPanelNewCard() 
 {
-  goNewCardDialog(abList.selectedItem.getAttribute('id'));
+  goNewCardDialog(abList.value);
 }
 
 function AbPanelNewList() 
 {
-  goNewListDialog(abList.selectedItem.getAttribute('id'));
+  goNewListDialog(abList.value);
 }
 
 function ResultsPaneSelectionChanged() 
 {
   // do nothing for ab panel
 }
 
 function OnClickedCard() 
--- a/mail/components/addrbook/content/abContactsPanel.xul
+++ b/mail/components/addrbook/content/abContactsPanel.xul
@@ -52,18 +52,16 @@
 <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
 %globalDTD;
 ]>
 
 <page id="abContactsPanel"
       xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
       onload="AbPanelLoad();"
       onunload="AbPanelUnload();"
-      xmlns:nc="http://home.netscape.com/NC-rdf#"
-      xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
       selectedaddresses="true">
 
   <stringbundleset id="stringbundleset">
     <stringbundle id="bundle_addressBook" src="chrome://messenger/locale/addressbook/addressBook.properties"/>
   </stringbundleset>
 
   <script type="application/x-javascript" src="chrome://messenger/content/addressbook/addressbook.js"/>
   <script type="application/x-javascript" src="chrome://global/content/nsDragAndDrop.js"/>
@@ -83,30 +81,17 @@
 
   <vbox id="results_box" flex="1">
     <separator class="thin"/>
     <label value="&addressbookPicker.label;" accesskey="&addressbookPicker.accesskey;" control="addressbookList"/>
     <hbox id="panel-bar" class="toolbar" align="center">
       <menulist id="addressbookList"
                 oncommand="AddressBookMenuListChange();" flex="1"
                 persist="value">
-        <menupopup id="addressbookList-menupopup"
-                   datasources="rdf:addressdirectory"
-                   ref="moz-abdirectory://"
-                   sortActive="true"
-                   sortDirection="ascending"
-                   sortResource="http://home.netscape.com/NC-rdf#DirTreeNameSort">
-          <template>
-            <rule nc:IsMailList="false">
-              <menuitem uri="..."
-                    label="rdf:http://home.netscape.com/NC-rdf#DirName"
-                    value="rdf:http://home.netscape.com/NC-rdf#DirUri"/>
-            </rule>
-          </template>
-        </menupopup>
+        <menupopup id="addressbookList-menupopup" class="addrbooksPopup"/>
       </menulist>
     </hbox>
 
     <separator class="thin"/>
 
     <vbox>
       <label value="&searchInput.label;" accesskey="&searchInput.accesskey;" control="searchInput"/>
       <textbox id="searchInput" flex="1" type="timed" timeout="800"
--- a/mail/components/addrbook/content/abEditListDialog.xul
+++ b/mail/components/addrbook/content/abEditListDialog.xul
@@ -37,17 +37,16 @@
 #
 # ***** END LICENSE BLOCK *****
 
 <?xml-stylesheet href="chrome://messenger/skin/addressbook/cardDialog.css" type="text/css"?>
 
 <!DOCTYPE dialog SYSTEM "chrome://messenger/locale/addressbook/abMailListDialog.dtd">
 
 <dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         id="ablistWindow"
         title="&mailListWindow.title;"
         onload="OnLoadEditList();"
         ondialogaccept="return EditListOKButton();"
         ondragover="DragOverAddressListTree(event);"
         ondragdrop="DropOnAddressListTree(event);">
 
   <stringbundleset id="stringbundleset">
--- a/mail/components/addrbook/content/abMailListDialog.xul
+++ b/mail/components/addrbook/content/abMailListDialog.xul
@@ -37,18 +37,16 @@
 #
 # ***** END LICENSE BLOCK *****
 
 <?xml-stylesheet href="chrome://messenger/skin/addressbook/cardDialog.css" type="text/css"?>
 
 <!DOCTYPE dialog SYSTEM "chrome://messenger/locale/addressbook/abMailListDialog.dtd">
 
 <dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        xmlns:nc="http://home.netscape.com/NC-rdf#"
-        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         id="ablistWindow"
         title="&mailListWindow.title;"
         ondialogaccept="return MailListOKButton();"
         onload="OnLoadNewMailList();"
         ondragover="DragOverAddressListTree(event);"
         ondragdrop="DropOnAddressListTree(event);">
 
   <stringbundleset id="stringbundleset">
@@ -58,31 +56,18 @@
   <!-- move needed functions into a single js file -->
   <script type="application/x-javascript" src="chrome://messenger/content/messengercompose/addressingWidgetOverlay.js"/>
   <script type="application/x-javascript" src="chrome://messenger/content/addressbook/abCommon.js"/>
   <script type="application/x-javascript" src="chrome://messenger/content/addressbook/abMailListDialog.js"/>
 
   <hbox align="center">
     <label control="abPopup" value="&addToAddressBook.label;" accesskey="&addToAddressBook.accesskey;"/>
     <menulist id="abPopup">
-      <menupopup id="abPopup-menupopup" 
-                 ref="moz-abdirectory://" 
-                 datasources="rdf:addressdirectory"
-                 sortActive="true"
-                 sortDirection="ascending"
-                 sortResource="http://home.netscape.com/NC-rdf#DirTreeNameSort">
-        <template>
-        <rule nc:IsWriteable="false"/>
-        <rule nc:SupportsMailingLists="true">
-          <menuitem uri="..."
-                    label="rdf:http://home.netscape.com/NC-rdf#DirName"
-                    value="rdf:http://home.netscape.com/NC-rdf#DirUri"/>
-        </rule>
-        </template>
-      </menupopup>
+      <menupopup id="abPopup-menupopup" class="addrbooksPopup" writeable="true"
+                 supportsmaillists="true"/>
     </menulist>
   </hbox>
 
   <spacer style="height:1em"/>
 
   <vbox id="editlist">
     <hbox>
       <spacer flex="1"/>
--- a/mail/components/addrbook/jar.mn
+++ b/mail/components/addrbook/jar.mn
@@ -3,16 +3,17 @@ messenger.jar:
 *   content/messenger/addressbook/addressbook.js                (content/addressbook.js)
 *   content/messenger/addressbook/addressbook.xul               (content/addressbook.xul)
 *   content/messenger/addressbook/abCommon.js                   (content/abCommon.js)
 *   content/messenger/addressbook/abCardOverlay.js              (content/abCardOverlay.js)
 *   content/messenger/addressbook/abEditListDialog.xul          (content/abEditListDialog.xul)
 *   content/messenger/addressbook/abMailListDialog.xul          (content/abMailListDialog.xul)
 *   content/messenger/addressbook/abContactsPanel.xul           (content/abContactsPanel.xul)
 *   content/messenger/addressbook/abContactsPanel.js            (content/abContactsPanel.js)
+    content/messenger/addressbook/addrbookWidgets.xml           (/mailnews/addrbook/resources/content/addrbookWidgets.xml)
     content/messenger/addressbook/pref-directory.js             (/mailnews/addrbook/prefs/resources/content/pref-directory.js)
     content/messenger/addressbook/pref-directory-add.js         (/mailnews/addrbook/prefs/resources/content/pref-directory-add.js)
     content/messenger/addressbook/pref-directory-add.xul        (/mailnews/addrbook/prefs/resources/content/pref-directory-add.xul)
     content/messenger/addressbook/pref-editdirectories.js       (/mailnews/addrbook/prefs/resources/content/pref-editdirectories.js)
     content/messenger/addressbook/pref-editdirectories.xul      (/mailnews/addrbook/prefs/resources/content/pref-editdirectories.xul)
     content/messenger/addressbook/abAddressBookNameDialog.js    (/mailnews/addrbook/resources/content/abAddressBookNameDialog.js)
     content/messenger/addressbook/abAddressBookNameDialog.xul   (/mailnews/addrbook/resources/content/abAddressBookNameDialog.xul)
     content/messenger/addressbook/abNewCardDialog.xul           (/mailnews/addrbook/resources/content/abNewCardDialog.xul)
--- a/mailnews/addrbook/resources/content/abCardOverlay.js
+++ b/mailnews/addrbook/resources/content/abCardOverlay.js
@@ -370,17 +370,17 @@ function NewCardOKButton()
 
     gOkCallback(gEditCard.card.translateTo("vcard"));
     return true;  // close the window
   }
 
   var popup = document.getElementById('abPopup');
   if ( popup )
   {
-    var uri = popup.getAttribute('value');
+    var uri = popup.value;
 
     // FIX ME - hack to avoid crashing if no ab selected because of blank option bug from template
     // should be able to just remove this if we are not seeing blank lines in the ab popup
     if ( !uri )
       return false;  // don't close window
     // -----
 
     if (gEditCard.card)
--- a/mailnews/addrbook/resources/content/abCommon.js
+++ b/mailnews/addrbook/resources/content/abCommon.js
@@ -617,17 +617,17 @@ function DirPaneHasFocus()
 {
   // returns true if diectory pane has the focus. Returns false, otherwise.
   return (top.document.commandDispatcher.focusedElement == dirTree)
 }
 
 function GetSelectedDirectory()
 {
   if (abList)
-    return abList.selectedItem.id;
+    return abList.value;
   else {
     if (dirTree.currentIndex < 0)
       return null;
     var selected = dirTree.builderView.getResourceAtIndex(dirTree.currentIndex)
     return selected.Value;
   }
 }
 
--- a/mailnews/addrbook/resources/content/abMailListDialog.xul
+++ b/mailnews/addrbook/resources/content/abMailListDialog.xul
@@ -38,45 +38,30 @@
 
 <?xml-stylesheet href="chrome://messenger/skin/dialogs.css" type="text/css"?>
 
 <?xul-overlay href="chrome://messenger/content/addressbook/abListOverlay.xul"?>
 
 <!DOCTYPE dialog SYSTEM "chrome://messenger/locale/addressbook/abMailListDialog.dtd">
 
 <dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-    xmlns:nc="http://home.netscape.com/NC-rdf#"
-    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
     id="ablistWindow"
     title="&mailListWindow.title;"
     ondialogaccept="return MailListOKButton();"
     onload="OnLoadNewMailList()"
     ondragover="DragOverAddressListTree(event);"
     ondragdrop="DropOnAddressListTree(event);">
 
   <stringbundleset id="stringbundleset"/>
 
   <hbox align="center" valign="center">
     <label control="abPopup" value="&addToAddressBook.label;" accesskey="&addToAddressBook.accesskey;"/>
     <menulist id="abPopup">
-      <menupopup id="abPopup-menupopup" 
-                 ref="moz-abdirectory://" 
-                 datasources="rdf:addressdirectory"
-                 sortActive="true"
-                 sortDirection="ascending"
-                 sortResource="http://home.netscape.com/NC-rdf#DirTreeNameSort">
-        <template> 
-        <rule nc:IsWriteable="false"/>
-        <rule nc:SupportsMailingLists="true">
-          <menuitem uri="..."
-                    label="rdf:http://home.netscape.com/NC-rdf#DirName"
-                    value="rdf:http://home.netscape.com/NC-rdf#DirUri"/>
-        </rule>
-        </template> 
-      </menupopup>
+      <menupopup id="abPopup-menupopup" class="addrbooksPopup" writeable="true"
+                 supportsmaillists="true"/>
     </menulist>
   </hbox>
 
   <spacer style="height:1em"/>
 
   <vbox id="editlist"/>
 
 </dialog>
--- a/mailnews/addrbook/resources/content/abNewCardDialog.xul
+++ b/mailnews/addrbook/resources/content/abNewCardDialog.xul
@@ -38,44 +38,28 @@
 
 <?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
 
 <?xul-overlay href="chrome://messenger/content/addressbook/abCardOverlay.xul"?>
 
 <!DOCTYPE dialog SYSTEM "chrome://messenger/locale/addressbook/abNewCardDialog.dtd">
 
 <dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-    xmlns:nc="http://home.netscape.com/NC-rdf#"
-    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
     id="abcardWindow"
     onload="OnLoadNewCard()"
     ondialogaccept="return NewCardOKButton();">
 
   <stringbundleset id="stringbundleset"/>
 
   <hbox align="center">
 
     <label id="abPopupLabel" control="abPopup" value="&chooseAddressBook.label;" accesskey="&chooseAddressBook.accesskey;"/>
 
     <menulist id="abPopup">
-      <menupopup id="abPopup-menupopup" 
-                 ref="moz-abdirectory://" 
-                 datasources="rdf:addressdirectory"
-                 sortActive="true"
-                 sortDirection="ascending"
-                 sortResource="http://home.netscape.com/NC-rdf#DirTreeNameSort">
-        <template> 
-        <rule nc:IsWriteable="false"/>
-        <rule nc:IsMailList="false">
-        <menuitem uri="..."
-            label="rdf:http://home.netscape.com/NC-rdf#DirName"
-            value="rdf:http://home.netscape.com/NC-rdf#DirUri"/>
-        </rule>
-        </template> 
-      </menupopup>
+      <menupopup id="abPopup-menupopup" class="addrbooksPopup" writeable="true"/>
     </menulist>
 
   </hbox>
 
   <spacer style="height:1em"/>
 
   <vbox id="editcard"/>
 
--- a/mailnews/addrbook/resources/content/abSelectAddressesDialog.js
+++ b/mailnews/addrbook/resources/content/abSelectAddressesDialog.js
@@ -111,17 +111,25 @@ function OnLoadSelectAddress()
     AddAddressFromComposeWindow(toAddress, prefixTo);
     AddAddressFromComposeWindow(ccAddress, prefixCc);
     AddAddressFromComposeWindow(bccAddress, prefixBcc);
   }
 
   gSearchInput = document.getElementById("searchInput");
   SearchInputChanged();
 
-  SelectFirstAddressBookMenulist();
+  // Reselect the persisted address book if possible, if not just select the
+  // first in the list.
+  var temp = abPopup.value;
+  abPopup.selectedItem = null;
+  abPopup.value = temp;
+  if (!abPopup.selectedItem)
+    abPopup.selectedIndex = 0;
+
+  ChangeDirectoryByURI(abList.value);
 
   DialogBucketPaneSelectionChanged();
   
   var workPhoneCol = document.getElementById("WorkPhone");
   workPhoneCol.setAttribute("hidden", "true");
   
   var companyCol = document.getElementById("Company");
   companyCol.setAttribute("hidden", "true");
@@ -392,40 +400,34 @@ function onEnterInSearchBar()
   if (!selectedNode)
     return;
 
   if (!gQueryURIFormat) {
     gQueryURIFormat = gPrefs.getComplexValue("mail.addr_book.quicksearchquery.format", 
                                               Components.interfaces.nsIPrefLocalizedString).data;
   }
   
-  var searchURI = selectedNode.getAttribute("id");
+  var searchURI = selectedNode.value;
 
   if (gSearchInput.value != "") {
     searchURI += gQueryURIFormat.replace(/@V/g, encodeURIComponent(gSearchInput.value));
   }
 
   SetAbView(searchURI);
   
   SelectFirstCard();
 }
 
-function SelectFirstAddressBookMenulist()
-{
-  ChangeDirectoryByURI(abList.selectedItem.id);
-  return;
-}
-
 function DirPaneSelectionChangeMenulist()
 {
   if (abList && abList.selectedItem) {
     if (gSearchInput.value && (gSearchInput.value != "")) 
       onEnterInSearchBar();
     else
-      ChangeDirectoryByURI(abList.selectedItem.id);
+      ChangeDirectoryByURI(abList.value);
   }
 }
 
 function GetPromptService()
 {
   try {
     return Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
                      .getService(Components.interfaces.nsIPromptService);
--- a/mailnews/addrbook/resources/content/abSelectAddressesDialog.xul
+++ b/mailnews/addrbook/resources/content/abSelectAddressesDialog.xul
@@ -48,19 +48,17 @@
 <!DOCTYPE window [
 <!ENTITY % abSelectAddressesDialogDTD SYSTEM "chrome://messenger/locale/addressbook/abSelectAddressesDialog.dtd" >
 %abSelectAddressesDialogDTD;
 <!ENTITY % abResultsPaneOverlayDTD SYSTEM "chrome://messenger/locale/addressbook/abResultsPaneOverlay.dtd" >
 %abResultsPaneOverlayDTD;
 ]>
 
 <window id="selectAddressesWindow"
-        xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        xmlns:nc="http://home.netscape.com/NC-rdf#"
         title="&selectAddressWindow.title;"
         class="dialog"
         style="width: 50em; height: 35em;"
         persist="width height screenX screenY"
         onload="OnLoadSelectAddress()"
         onunload="OnUnloadSelectAddress()">
 
   <stringbundle id="bundle_addressBook" src="chrome://messenger/locale/addressbook/addressBook.properties"/>
@@ -74,32 +72,18 @@
 
   <keyset id="dialogKeys"/>
 
   <vbox flex="1">
   
     <hbox id="topBox" align="center">
       <label value="&lookIn.label;" accesskey="&lookIn.accesskey;" control="addressbookList"/>
       <menulist id="addressbookList" 
-                ref="moz-abdirectory://" 
-                datasources="rdf:addressdirectory"
-                containment="http://home.netscape.com/NC-rdf#child"
-                sortActive="true"
-                sortDirection="ascending"
-                sortResource="http://home.netscape.com/NC-rdf#DirTreeNameSort"
                 oncommand="DirPaneSelectionChangeMenulist(); document.commandDispatcher.updateCommands('addrbook-select');">
-        <template>
-          <rule nc:IsMailList="false">
-            <menupopup>
-              <menuitem label="rdf:http://home.netscape.com/NC-rdf#DirName" uri="..."
-                        IsMailList="rdf:http://home.netscape.com/NC-rdf#IsMailList"
-                        IsRemote="rdf:http://home.netscape.com/NC-rdf#IsRemote"/>
-            </menupopup>
-          </rule>
-        </template>
+        <menupopup id="addressbookList-menupopup" class="addrbooksPopup"/>
       </menulist>  
       <label value="&for.label;" accesskey="&for.accesskey;" control="searchInput"/>
       <textbox id="searchInput" flex="1"
                type="timed" timeout="800"
                oninput="SearchInputChanged();"
                oncommand="onEnterInSearchBar();"/>  
       <button id="clear" label="&clearButton.label;" disabled="true" accesskey="&clearButton.accesskey;" oncommand="onAbClearSearch();"/>
     </hbox>
--- a/mailnews/addrbook/resources/content/addrbookWidgets.xml
+++ b/mailnews/addrbook/resources/content/addrbookWidgets.xml
@@ -68,17 +68,18 @@
         ]]>
       </destructor>
 
       <!-- nsIAbListener methods -->
       <method name="onItemAdded">
         <parameter name="aParentDir"/>
         <parameter name="aItem"/>
         <body><![CDATA[
-          if (aItem instanceof Components.interfaces.nsIAbDirectory) {
+          if (aItem instanceof Components.interfaces.nsIAbDirectory &&
+              !aItem.isMailList && !this._building) {
             // Save the currently selected item
             var selectedItem = this.parentNode.value;
             this.parentNode.value = null;
 
             // Re-use _teardown and _build so that we can use its sort function
             this._teardown();
             this._build();
 
@@ -88,17 +89,18 @@
           }
         ]]></body>
       </method>
 
       <method name="onItemRemoved">
         <parameter name="aParentDir"/>
         <parameter name="aItem"/>
         <body><![CDATA[
-          if (aItem instanceof Components.interfaces.nsIAbDirectory) {
+          if (aItem instanceof Components.interfaces.nsIAbDirectory &&
+              !aItem.isMailList && !this._building) {
             // Find the item in the list to remove
             var nodes = this.getElementsByAttribute("value", aItem.URI);
 
             // We should only ever have at most one node with the URI.
             if (nodes.length > 0)
               this.removeChild(nodes[0]);
 
             // Update the parent item
@@ -110,17 +112,18 @@
       </method>
 
       <method name="onItemPropertyChanged">
         <parameter name="aItem"/>
         <parameter name="aProperty"/>
         <parameter name="aOldValue"/>
         <parameter name="aNewValue"/>
         <body><![CDATA[
-          if (aItem instanceof Components.interfaces.nsIAbDirectory) {
+          if (aItem instanceof Components.interfaces.nsIAbDirectory &&
+              !aItem.isMailList && !this._building) {
             // Find the item in the list to rename.
             var nodes = this.getElementsByAttribute("value", aItem.URI);
 
             // We should only ever have at most one node with the URI.
             if (nodes.length > 0)
               nodes[0].label = aItem.dirName;
           }
         ]]></body>
@@ -132,16 +135,20 @@
           // Empty out anything in the list.
           while (this.hasChildNodes())
             this.removeChild(this.lastChild);
         ]]></body>
       </method>
 
       <method name="_build">
         <body><![CDATA[
+          // Protect against cyclic updates that can be caused by getting
+          // all the address books.
+          this._building = true;
+
           // Init the address book list.
           var addressBooks = Components.classes["@mozilla.org/abmanager;1"]
                                        .getService(Components.interfaces.nsIAbManager)
                                        .directories;
           var holdingArray = [];
 
           var remoteOnly = this.getAttribute("remoteonly");
           var localOnly = this.getAttribute("localonly");
@@ -199,13 +206,15 @@
 
           holdingArray.forEach(function (ab) {
             var item = document.createElement('menuitem');
             item.setAttribute("label", ab.dirName);
             item.setAttribute("value", ab.URI);
 
             menupopup.appendChild(item);
           });
+
+          this._building = false;
         ]]></body>
       </method>
     </implementation>
   </binding>
 </bindings>
--- a/mailnews/addrbook/resources/content/addressbook-panel.js
+++ b/mailnews/addrbook/resources/content/addressbook-panel.js
@@ -37,79 +37,33 @@
 var gMsgCompose = false;
 
 function GetAbViewListener()
 {
   // the ab panel doesn't care if the total changes, or if the selection changes
   return null;
 }
 
-var gAddressBookPanelAbListener = {
-  onItemAdded: function(parentDir, item) {
-    // will not be called
-  },
-  onItemRemoved: function(parentDir, item) {
-    // will only be called when an addressbook is deleted
-    try {
-      var directory = item.QueryInterface(Components.interfaces.nsIAbDirectory);
-      // check if the item being removed is the directory
-      // that we are showing in the addressbook sidebar
-      // if so, select the person addressbook (it can't be removed)
-      var abPopup = document.getElementById('addressbookList');
-      if (directory.URI == abPopup.value) {
-          abPopup.value = kPersonalAddressbookURI;
-          LoadPreviouslySelectedAB();
-      } 
-    }
-    catch (ex) {
-    }
-  },
-  onItemPropertyChanged: function(item, property, oldValue, newValue) {
-    try {
-      var directory = item.QueryInterface(Components.interfaces.nsIAbDirectory);
-      // check if the item being changed is the directory
-      // that we are showing in the addressbook sidebar
-      if (directory == GetAbView().directory) {
-          LoadPreviouslySelectedAB();
-      }
-    }
-    catch (ex) {
-    }
-  }
-};
-
-
-// XXX todo
-// can we combine some common code?  see OnLoadNewMailList()
-// set popup with address book names
-function LoadPreviouslySelectedAB()
-{
-  var abPopup = document.getElementById('addressbookList');
-  var value = abPopup.value || kPersonalAddressbookURI;
-  abPopup.selectedItem = null;
-  abPopup.value = value;
-  ChangeDirectoryByURI(abPopup.selectedItem.id);
-}
-
 function AbPanelLoad() 
 {
   InitCommonJS(); 
 
   UpgradeAddressBookResultsPaneUI("mailnews.ui.addressbook_panel_results.version");
 
-  LoadPreviouslySelectedAB();
+  var abPopup = document.getElementById('addressbookList');
 
-  // Add a listener, so we can switch directories if the current directory is
-  // deleted, and change the name if the selected directory's name is modified.
-  // This listener only cares when a directory is removed or modified.
-  Components.classes["@mozilla.org/abmanager;1"]
-            .getService(Components.interfaces.nsIAbManager)
-            .addAddressBookListener(gAddressBookPanelAbListener,
-                                    nsIAbListener.directoryRemoved |
-                                    nsIAbListener.itemChanged);
+  // Reselect the persisted address book if possible, if not just select the
+  // first in the list.
+  var temp = abPopup.value;
+  abPopup.selectedItem = null;
+  abPopup.value = temp;
+  if (!abPopup.selectedItem)
+    abPopup.selectedIndex = 0;
+
+  ChangeDirectoryByURI(abPopup.value);
 
   gSearchInput = document.getElementById("searchInput");
 
   // for the compose window we want to show To, Cc, Bcc and a separator
   // for all other windows we want to show Compose Mail To
   var popup = document.getElementById("composeMail");
   gMsgCompose = parent.document.documentElement.getAttribute("windowtype") == "msgcompose";
   for (var i = 0; i < 4; i++)
@@ -120,20 +74,16 @@ function AbPanelLoad()
     parent.addEventListener("compose-window-close", onAbClearSearch, true);
 }
 
 function AbPanelUnload()
 {
   if (gMsgCompose)
     parent.removeEventListener("compose-window-close", onAbClearSearch, true);
 
-  Components.classes["@mozilla.org/abmanager;1"]
-            .getService(Components.interfaces.nsIAbManager)
-            .removeAddressBookListener(gAddressBookPanelAbListener);
-
   CloseAbView();
 }
 
 function AbPanelAdd(addrtype)
 {
   var cards = GetSelectedAbCards();
   var count = cards.length;
 
@@ -146,22 +96,22 @@ function AbPanelAdd(addrtype)
       gPromptService.alert(window,
                            gAddressBookBundle.getString("emptyEmailAddCardTitle"),
                            gAddressBookBundle.getString("emptyEmailAddCard"));
   }
 }
 
 function AbPanelNewCard() 
 {
-  goNewCardDialog(abList.selectedItem.getAttribute('id'));
+  goNewCardDialog(abList.value);
 }
 
 function AbPanelNewList() 
 {
-  goNewListDialog(abList.selectedItem.getAttribute('id'));
+  goNewListDialog(abList.value);
 }
 
 function ResultsPaneSelectionChanged() 
 {
   // do nothing for ab panel
 }
 
 function OnClickedCard() 
--- a/mailnews/addrbook/resources/content/addressbook-panel.xul
+++ b/mailnews/addrbook/resources/content/addressbook-panel.xul
@@ -50,18 +50,16 @@
 <!ENTITY % abResultsPaneOverlayDTD SYSTEM "chrome://messenger/locale/addressbook/abResultsPaneOverlay.dtd" >
 %abResultsPaneOverlayDTD;
 ]>
 
 <page id="addressbook-panel"
       xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
       onload="AbPanelLoad();"
       onunload="AbPanelUnload();"
-      xmlns:nc="http://home.netscape.com/NC-rdf#"
-      xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
       title="&selectAddressWindow.title;"
       selectedaddresses="true">
 
   <stringbundleset id="stringbundleset">
     <stringbundle id="bundle_addressBook" src="chrome://messenger/locale/addressbook/addressBook.properties"/>
   </stringbundleset>
 
   <script type="application/x-javascript" src="chrome://global/content/globalOverlay.js"/>
@@ -90,30 +88,17 @@
     <menuitem label="&addrBookCardProperties.label;" accesskey="&addrBookCardProperties.accesskey;" oncommand="AbEditSelectedCard();"/>
   </popup>
   <vbox id="results_box" flex="1">
     <hbox id="panel-bar" class="toolbar" align="center">
 	  <label value="&lookIn.label;" control="addressbookList" id="lookInLabel"/>
       <menulist id="addressbookList" 
                 oncommand="DirPaneSelectionChangeMenulist();" flex="1"
                 persist="value">
-        <menupopup id="addressbookList-menupopup" 
-          datasources="rdf:addressdirectory" 
-                   ref="moz-abdirectory://"
-                   sortActive="true"
-                   sortDirection="ascending"
-                   sortResource="http://home.netscape.com/NC-rdf#DirTreeNameSort">
-          <template>
-            <rule nc:IsMailList="false">
-              <menuitem uri="..."
-                    label="rdf:http://home.netscape.com/NC-rdf#DirName"
-                    value="rdf:http://home.netscape.com/NC-rdf#DirUri"/>
-            </rule>
-          </template>
-        </menupopup>
+        <menupopup id="addressbookList-menupopup" class="addrbooksPopup"/>
       </menulist>
     </hbox>
 	<hbox align="center">
 	  <label value="&for.label;" id="forLabel" control="searchInput"/> 
 	  <textbox id="searchInput" flex="1"
                type="timed" timeout="800"
                aria-labelledby="lookInLabel addressbookList forLabel"
                oncommand="onEnterInSearchBar();"/>
--- a/mailnews/base/resources/content/messenger.css
+++ b/mailnews/base/resources/content/messenger.css
@@ -86,16 +86,20 @@ mail-headerfield {
 mail-tagfield {
   -moz-binding: url("chrome://messenger/content/mailWidgets.xml#mail-headerfield-tags");
 }
 
 menupopup[type="folder"] {
   -moz-binding: url("chrome://messenger/content/folderWidgets.xml#folder-menupopup");
 }
 
+.addrbooksPopup {
+  -moz-binding: url("chrome://messenger/content/addressbook/addrbookWidgets.xml#addrbooks-menupopup");
+}
+
 searchattribute {
   -moz-binding: url("chrome://messenger/content/mailWidgets.xml#searchattribute");
 }
 
 searchoperator {
   -moz-binding: url("chrome://messenger/content/mailWidgets.xml#searchoperator");
 }
 
--- a/mailnews/base/search/resources/content/ABSearchDialog.js
+++ b/mailnews/base/search/resources/content/ABSearchDialog.js
@@ -93,16 +93,19 @@ function searchOnLoad()
                               .getService(Components.interfaces.nsIPrefService);
   var prefBranch = prefService.getBranch(null).QueryInterface(Components.interfaces.nsIPrefBranch2);
   gSearchPhoneticName =
         prefBranch.getComplexValue("mail.addr_book.show_phonetic_fields", 
                                    Components.interfaces.nsIPrefLocalizedString).data;
 
   if (window.arguments && window.arguments[0])
     SelectDirectory(window.arguments[0].directory);
+  else
+    SelectDirectory(document.getElementById("abPopup-menupopup")
+                            .firstChild.value);
 
   // initialize globals, see abCommon.js, InitCommonJS()
   abList = document.getElementById("abPopup");
 
   onMore(null);
 }
 
 function searchOnUnload()
@@ -358,16 +361,8 @@ function UpdateCardView()
 
   gComposeButton.removeAttribute("disabled");
 
   if (numSelected == 1) 
     gPropertiesButton.removeAttribute("disabled");
   else
     gPropertiesButton.setAttribute("disabled","true");
 }
-
-function onChooseDirectory(event) 
-{
-    var directoryURI = event.id;
-    if (directoryURI) {
-        SelectDirectory(directoryURI);
-    }
-}
--- a/mailnews/base/search/resources/content/ABSearchDialog.xul
+++ b/mailnews/base/search/resources/content/ABSearchDialog.xul
@@ -84,31 +84,18 @@
   </keyset>
 
   <dummy class="usesMailWidgets"/>
     
     <vbox id="searchTerms" flex="3" persist="height">
       <vbox>
         <hbox align="center">
           <label value="&abSearchHeading.label;" accesskey="&abSearchHeading.accesskey;" control="abPopup"/>
-          <menulist id="abPopup">
-            <menupopup id="abPopup-menupopup" ref="moz-abdirectory://"
-                       datasources="rdf:addressdirectory"
-                       sortActive="true"
-                       sortDirection="ascending"
-                       sortResource="http://home.netscape.com/NC-rdf#DirTreeNameSort"
-                       oncommand="onChooseDirectory(event.target);">
-              <template>
-                <rule nc:IsMailList="false">
-                  <menuitem uri="..."
-                            label="rdf:http://home.netscape.com/NC-rdf#DirName"
-                            value="rdf:http://home.netscape.com/NC-rdf#DirUri"/>
-                </rule>
-              </template>
-            </menupopup>
+          <menulist id="abPopup" oncommand="SelectDirectory(this.value);">
+            <menupopup id="abPopup-menupopup" class="addrbooksPopup"/>
           </menulist>
           <spacer flex="10"/>
           <button id="search-button" oncommand="onSearchButton(event);" default="true"/>
         </hbox>
         <hbox align="center">
           <spacer flex="1"/>
           <button label="&resetButton.label;" oncommand="onAbSearchReset(event);" accesskey="&resetButton.accesskey;"/>
         </hbox>
--- a/mailnews/jar.mn
+++ b/mailnews/jar.mn
@@ -33,16 +33,17 @@ messenger.jar:
     content/messenger/addressbook/abCommon.js                                  (addrbook/resources/content/abCommon.js)
     content/messenger/addressbook/abDirTreeOverlay.xul                         (addrbook/resources/content/abDirTreeOverlay.xul)
     content/messenger/addressbook/abEditCardDialog.xul                         (addrbook/resources/content/abEditCardDialog.xul)
     content/messenger/addressbook/abNewCardDialog.xul                          (addrbook/resources/content/abNewCardDialog.xul)
     content/messenger/addressbook/abResultsPaneOverlay.xul                     (addrbook/resources/content/abResultsPaneOverlay.xul)
     content/messenger/addressbook/abResultsPane.js                             (addrbook/resources/content/abResultsPane.js)
     content/messenger/addressbook/abSelectAddressesDialog.js                   (addrbook/resources/content/abSelectAddressesDialog.js)
     content/messenger/addressbook/abSelectAddressesDialog.xul                  (addrbook/resources/content/abSelectAddressesDialog.xul)
+    content/messenger/addressbook/addrbookWidgets.xml                          (addrbook/resources/content/addrbookWidgets.xml)
     content/messenger/addressbook/addressbook.js                               (addrbook/resources/content/addressbook.js)
     content/messenger/addressbook/addressbook.xul                              (addrbook/resources/content/addressbook.xul)
     content/messenger/addressbook/abDragDrop.js                                (addrbook/resources/content/abDragDrop.js)
     content/messenger/addressbook/abMailListDialog.xul                         (addrbook/resources/content/abMailListDialog.xul)
     content/messenger/addressbook/abMailListDialog.js                          (addrbook/resources/content/abMailListDialog.js)
     content/messenger/addressbook/abListOverlay.xul                            (addrbook/resources/content/abListOverlay.xul)
     content/messenger/addressbook/abEditListDialog.xul                         (addrbook/resources/content/abEditListDialog.xul)
     content/messenger/addressbook/addressbook-panel.xul                        (addrbook/resources/content/addressbook-panel.xul)