home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 January / 01_02.iso / software / netscape62win / mail.xpi / bin / chrome / messenger.jar / content / messenger / msgMail3PaneWindow.js < prev    next >
Text File  |  2001-10-03  |  34KB  |  1,115 lines

  1. /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2.  * The contents of this file are subject to the Netscape Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/NPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is Mozilla Communicator client code, released
  13.  * March 31, 1998.
  14.  * 
  15.  * The Initial Developer of the Original Code is Netscape
  16.  * Communications Corporation. Portions created by Netscape are
  17.  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
  18.  * Rights Reserved.
  19.  *
  20.  * Contributor(s):
  21.  *   Jan Varga (varga@utcru.sk)
  22.  *   Hσkan Waara (hwaara@chello.se)
  23.  */
  24.  
  25. /* This is where functions related to the 3 pane window are kept */
  26.  
  27. var showPerformance = false;
  28.  
  29. var gFolderOutliner; 
  30. var gMessagePane;
  31. var gMessagePaneFrame;
  32. var gThreadOutliner;
  33.  
  34. var gThreadAndMessagePaneSplitter = null;
  35. var gUnreadCount = null;
  36. var gTotalCount = null;
  37.  
  38. var gCurrentLoadingFolderURI;
  39. var gCurrentFolderToReroot;
  40. var gCurrentLoadingFolderSortType = 0;
  41. var gCurrentLoadingFolderSortOrder = 0;
  42. var gCurrentLoadingFolderViewType = 0;
  43. var gCurrentLoadingFolderViewFlags = 0;
  44.  
  45. var gCurrentDisplayedMessage = null;
  46. var gNextMessageAfterDelete = null;
  47. var gNextMessageAfterLoad = null;
  48. var gNextMessageViewIndexAfterDelete = -2;
  49. var gCurrentlyDisplayedMessage=-1;
  50.  
  51. var gActiveThreadPaneSortColumn = "";
  52.  
  53. var gStartFolderUri = null;
  54.  
  55. //If we've loaded a message, set to true.  Helps us keep the start page around.
  56. var gHaveLoadedMessage;
  57.  
  58. var gDisplayStartupPage = false;
  59.  
  60. // the folderListener object
  61. var folderListener = {
  62.     OnItemAdded: function(parentItem, item, view) {},
  63.  
  64.     OnItemRemoved: function(parentItem, item, view){},
  65.  
  66.     OnItemPropertyChanged: function(item, property, oldValue, newValue) {},
  67.  
  68.     OnItemIntPropertyChanged: function(item, property, oldValue, newValue)
  69.     {
  70.         var currentLoadedFolder = GetThreadPaneFolder();
  71.         if (!currentLoadedFolder) return;
  72.  
  73.         var currentURI = currentLoadedFolder.URI;
  74.  
  75.         //if we don't have a folder loaded, don't bother.
  76.         if(currentURI)
  77.         {
  78.             if(property.GetUnicode() == "TotalMessages" || property.GetUnicode() == "TotalUnreadMessages")
  79.             {
  80.                 var folder = item.QueryInterface(Components.interfaces.nsIMsgFolder);
  81.                 if(folder)
  82.                 {
  83.                     var folderResource = folder.QueryInterface(Components.interfaces.nsIRDFResource);
  84.                     if(folderResource)
  85.                     {
  86.                         var folderURI = folderResource.Value;
  87.                         if(currentURI == folderURI)
  88.                         {
  89.                             UpdateStatusMessageCounts(folder);
  90.                         }
  91.                     }
  92.                 }
  93.             }      
  94.         }
  95.     },
  96.  
  97.     OnItemBoolPropertyChanged: function(item, property, oldValue, newValue) {},
  98.  
  99.     OnItemUnicharPropertyChanged: function(item, property, oldValue, newValue){},
  100.     OnItemPropertyFlagChanged: function(item, property, oldFlag, newFlag) {},
  101.  
  102.     OnItemEvent: function(folder, event) {
  103.         var eventType = event.GetUnicode();
  104.  
  105.         if (eventType == "FolderLoaded") {
  106.         if(folder)
  107.         {
  108.             var resource = folder.QueryInterface(Components.interfaces.nsIRDFResource);
  109.             if(resource)
  110.             {
  111.                 var uri = resource.Value;
  112.                 if(uri == gCurrentFolderToReroot)
  113.                 {
  114.                     gCurrentFolderToReroot="";
  115.                     var msgFolder = folder.QueryInterface(Components.interfaces.nsIMsgFolder);
  116.                     if(msgFolder)
  117.                     {
  118.                         msgFolder.endFolderLoading();
  119.                         RerootFolder(uri, msgFolder, gCurrentLoadingFolderViewType, gCurrentLoadingFolderViewFlags, gCurrentLoadingFolderSortType, gCurrentLoadingFolderSortOrder);
  120.                         gIsEditableMsgFolder = IsSpecialFolder(msgFolder, MSG_FOLDER_FLAG_DRAFTS);
  121.  
  122.                         gCurrentLoadingFolderSortType = 0;
  123.                         gCurrentLoadingFolderSortOrder = 0;
  124.             gCurrentLoadingFolderViewType = 0;
  125.             gCurrentLoadingFolderViewFlags = 0;
  126.  
  127.             SetFocusThreadPane();
  128.             var scrolled = false;
  129.             if (gNextMessageAfterLoad) 
  130.             {
  131.               var type = gNextMessageAfterLoad;
  132.               gNextMessageAfterLoad = null;
  133.  
  134.               // scroll to and select the proper message
  135.               scrolled = ScrollToMessage(type, true, true /* selectMessage */);
  136.             }
  137.                     }
  138.                 }
  139.                 if(uri == gCurrentLoadingFolderURI)
  140.                 {
  141.                   gCurrentLoadingFolderURI = "";
  142.                   //Now let's select the first new message if there is one
  143.                   var beforeScrollToNew;
  144.                   if(showPerformance) {
  145.                     beforeScrollToNew = new Date();
  146.                   }
  147.                   if (!scrolled) {
  148.                     // if we didn't just scroll, scroll to the first new message
  149.                     // don't select it though
  150.                     scrolled = ScrollToMessage(nsMsgNavigationType.firstNew, true, false /* selectMessage */);
  151.                     
  152.                     // if we failed to find a new message, scroll to the top
  153.                     if (!scrolled) {
  154.                       EnsureRowInThreadOutlinerIsVisible(0);
  155.                     }
  156.                   }
  157.  
  158.                   if(showPerformance) {
  159.                       var afterScrollToNew = new Date();
  160.                       var timeToScroll = (afterScrollToNew.getTime() - beforeScrollToNew.getTime())/1000;
  161.  
  162.                       var afterFolderLoadTime = new Date();
  163.                       var timeToLoad = (afterFolderLoadTime.getTime() - gBeforeFolderLoadTime.getTime())/1000;
  164.                       dump("Time to load " + uri + " is " +  timeToLoad + " seconds\n");
  165.                         dump("of which scrolling to new is " + timeToScroll + " seconds\n");
  166.                   }
  167.                     SetBusyCursor(window, false);
  168.                 }
  169.             }
  170.  
  171.         }
  172.         } else if (eventType == "DeleteOrMoveMsgCompleted") {
  173.             HandleDeleteOrMoveMsgCompleted(folder);
  174.         }     
  175.           else if (eventType == "DeleteOrMoveMsgFailed") {
  176.                         HandleDeleteOrMoveMsgFailed(folder);
  177.         }
  178.           else if (eventType == "CompactCompleted") {
  179.                         HandleCompactCompleted(folder);
  180.         }
  181.     }
  182. }
  183.  
  184. var folderObserver = {
  185.     canDropOn: function(index)
  186.     {
  187.         return CanDropOnFolderOutliner(index);
  188.     },
  189.  
  190.     canDropBeforeAfter: function(index, before)
  191.     {
  192.         return CanDropBeforeAfterFolderOutliner(index, before);
  193.     },
  194.  
  195.     onDrop: function(row, orientation)
  196.     {
  197.         DropOnFolderOutliner(row, orientation);
  198.     },
  199.  
  200.     onToggleOpenState: function()
  201.     {
  202.     },
  203.  
  204.     onCycleHeader: function(colID, elt)
  205.     {
  206.     },
  207.  
  208.     onCycleCell: function(row, colID)
  209.     {
  210.     },
  211.  
  212.     onSelectionChanged: function()
  213.     {
  214.     },
  215.  
  216.     isEditable: function(row, colID)
  217.     {
  218.         return false;
  219.     },
  220.  
  221.     onSetCellText: function(row, colID, value)
  222.     {
  223.     },
  224.  
  225.     onPerformAction: function(action)
  226.     {
  227.     },
  228.  
  229.     onPerformActionOnRow: function(action, row)
  230.     {
  231.     },
  232.  
  233.     onPerformActionOnCell: function(action, row, colID)
  234.     {
  235.     }
  236. }
  237.  
  238. function HandleDeleteOrMoveMsgFailed(folder)
  239. {
  240.   if(IsCurrentLoadedFolder(folder)) {
  241.     if(gNextMessageAfterDelete) {
  242.       gNextMessageAfterDelete = null;
  243.       gNextMessageViewIndexAfterDelete = -2;
  244.     }
  245.   }
  246.  
  247.   // fix me???
  248.   // ThreadPaneSelectionChange(true);
  249. }
  250.  
  251. function HandleDeleteOrMoveMsgCompleted(folder)
  252. {
  253.   if (gNextMessageViewIndexAfterDelete != -2) 
  254.   {
  255.     if (IsCurrentLoadedFolder(folder)) 
  256.     {
  257.       var outlinerView = gDBView.QueryInterface(Components.interfaces.nsIOutlinerView);
  258.       var outlinerSelection = outlinerView.selection;
  259.       if (gNextMessageViewIndexAfterDelete != -1) 
  260.       {
  261.         viewSize = outlinerView.rowCount;
  262.         if (gNextMessageViewIndexAfterDelete >= viewSize) 
  263.         {
  264.           if (viewSize > 0)
  265.             gNextMessageViewIndexAfterDelete = viewSize - 1;
  266.           else
  267.             gNextMessageViewIndexAfterDelete = -1;
  268.         }
  269.       }
  270.  
  271.       // if we are about to set the selection with a new element then DON'T clear
  272.       // the selection then add the next message to select. This just generates
  273.       // an extra round of command updating notifications that we are trying to
  274.       // optimize away.
  275.       if (gNextMessageViewIndexAfterDelete != -1) 
  276.       {
  277.         outlinerSelection.select(gNextMessageViewIndexAfterDelete);
  278.         // since gNextMessageViewIndexAfterDelete probably has the same value
  279.         // as the last index we had selected, the outliner isn't generating a new
  280.         // selectionChanged notification for the outliner view. So we aren't loading the 
  281.         // next message. to fix this, force the selection changed update.
  282.         if (outlinerView)
  283.           outlinerView.selectionChanged();
  284.         EnsureRowInThreadOutlinerIsVisible(gNextMessageViewIndexAfterDelete); 
  285.       }
  286.       else 
  287.       {
  288.         outlinerSelection.clearSelection(); /* clear selection in either case  */
  289.         setTitleFromFolder(folder,null);
  290.         ClearMessagePane();
  291.       }
  292.     }
  293.       gNextMessageViewIndexAfterDelete = -2;  
  294.      //default value after delete/move/copy is over
  295.   }
  296. }
  297.  
  298. function HandleCompactCompleted (folder)
  299. {
  300.   if(folder)
  301.   {
  302.     var resource = folder.QueryInterface(Components.interfaces.nsIRDFResource);
  303.     if(resource)
  304.     {
  305.       var uri = resource.Value;
  306.       var msgFolder = msgWindow.openFolder;
  307.       if (msgFolder && uri == msgFolder.URI)
  308.       {
  309.         var msgdb = msgFolder.getMsgDatabase(msgWindow);
  310.         if (msgdb)
  311.         {
  312.           var dbFolderInfo = msgdb.dBFolderInfo;
  313.           sortType = dbFolderInfo.sortType;
  314.           sortOrder = dbFolderInfo.sortOrder;
  315.           viewFlags = dbFolderInfo.viewFlags;
  316.           viewType = dbFolderInfo.viewType;
  317.         }
  318.         RerootFolder(uri, msgFolder, viewType, viewFlags, sortType, sortOrder);
  319.         SetFocusThreadPane();
  320.         if (gCurrentlyDisplayedMessage != -1)
  321.         {
  322.           var outlinerView = gDBView.QueryInterface(Components.interfaces.nsIOutlinerView);
  323.           var outlinerSelection = outlinerView.selection;
  324.           outlinerSelection.select(gCurrentlyDisplayedMessage);
  325.           if (outlinerView)
  326.             outlinerView.selectionChanged();
  327.           EnsureRowInThreadOutlinerIsVisible(gCurrentlyDisplayedMessage);
  328.         }
  329.         gCurrentlyDisplayedMessage = -1; //reset
  330.       }
  331.     }
  332.   }
  333. }
  334.  
  335. function IsCurrentLoadedFolder(folder)
  336. {
  337.     var msgfolder = folder.QueryInterface(Components.interfaces.nsIMsgFolder);
  338.     if(msgfolder)
  339.     {
  340.         var folderResource = msgfolder.QueryInterface(Components.interfaces.nsIRDFResource);
  341.         if(folderResource)
  342.         {
  343.             var folderURI = folderResource.Value;
  344.             var currentLoadedFolder = GetThreadPaneFolder();
  345.             var currentURI = currentLoadedFolder.URI;
  346.             return(currentURI == folderURI);
  347.         }
  348.     }
  349.  
  350.     return false;
  351. }
  352.  
  353. /* Functions related to startup */
  354. function OnLoadMessenger()
  355. {
  356.   showPerformance = pref.GetBoolPref('mail.showMessengerPerformance');
  357.   var beforeLoadMessenger;
  358.   if(showPerformance) {
  359.       beforeLoadMessenger = new Date();
  360.   }
  361.  
  362.   AddMailOfflineObserver();
  363.   CreateMailWindowGlobals();
  364.   Create3PaneGlobals();
  365.   verifyAccounts();
  366.     
  367.   HideAccountCentral();
  368.   loadStartPage();
  369.   InitMsgWindow();
  370.  
  371.   messenger.SetWindow(window, msgWindow);
  372.  
  373.   InitializeDataSources();
  374.   InitPanes();
  375.  
  376.   accountManager.SetSpecialFoldersForIdentities();
  377.  
  378.   AddToSession();
  379.   //need to add to session before trying to load start folder otherwise listeners aren't
  380.   //set up correctly.
  381.   if ("arguments" in window && window.arguments[0])
  382.   {
  383.     gStartFolderUri = window.arguments[0];
  384.   }
  385.   else
  386.   {
  387.     gStartFolderUri = null;
  388.   }
  389.  
  390.   setTimeout("loadStartFolder(gStartFolderUri);", 0);
  391.  
  392.   // FIX ME - later we will be able to use onload from the overlay
  393.   OnLoadMsgHeaderPane();
  394.  
  395.     var id = null;
  396.     var headerchoice = null;
  397.  
  398.     try {
  399.         headerchoice = pref.GetIntPref("mail.show_headers");
  400.     }
  401.     catch (ex) {
  402.         dump("failed to get the header pref\n");
  403.     }
  404.  
  405.     switch (headerchoice) {
  406.         case 2:    
  407.             id = "viewallheaders";
  408.             break;
  409.         case 0:
  410.             id = "viewbriefheaders";
  411.             break;
  412.         case 1:    
  413.             id = "viewnormalheaders";
  414.             break;
  415.         default:
  416.             id = "viewnormalheaders";
  417.             break;
  418.     }
  419.  
  420.     var menuitem = document.getElementById(id);
  421.  
  422.     try {
  423.         // not working right yet.  see bug #??????
  424.         // menuitem.setAttribute("checked", "true"); 
  425.     }
  426.     catch (ex) {
  427.         dump("failed to set the view headers menu item\n");
  428.     }
  429.  
  430.     gHaveLoadedMessage = false;
  431.  
  432.     //Set focus to the Thread Pane the first time the window is opened.
  433.     SetFocusThreadPane();
  434.  
  435.     if(showPerformance) {
  436.       var afterLoadMessenger = new Date();
  437.       var timeToLoad = (afterLoadMessenger.getTime() - beforeLoadMessenger.getTime())/1000;
  438.       dump("Time in OnLoadMessger is " +  timeToLoad + " seconds\n");
  439.     }
  440.  
  441.   // hack for #100952, remove when #73953 gets fixed
  442.   var getMsgButton = document.getElementById("button-getmsg");
  443.   getMsgButton.setAttribute("ref", "msgaccounts:/");
  444. }
  445.  
  446. function OnUnloadMessenger()
  447. {
  448.   OnMailWindowUnload();
  449. }
  450.  
  451. function Create3PaneGlobals()
  452. {
  453. }
  454.  
  455. // because the "open" state persists, we'll call
  456. // PerformExpand() for all servers that are open at startup.            
  457. function PerformExpandForAllOpenServers()
  458. {
  459.     var folderOutliner = GetFolderOutliner();
  460.     var view = folderOutliner.outlinerBoxObject.view;
  461.     for (var i = 0; i < view.rowCount; i++)
  462.     {
  463.         if (view.isContainer(i))
  464.         {
  465.             var folderResource = GetFolderResource(folderOutliner, i);
  466.             var msgFolder = folderResource.QueryInterface(Components.interfaces.nsIMsgFolder);
  467.             var isServer = GetFolderAttribute(folderOutliner, folderResource, "IsServer"); 
  468.             if (isServer == "true")
  469.             {
  470.                 if (view.isContainerOpen(i))
  471.                 {
  472.                     var server = msgFolder.server;
  473.                     // Don't do this for imap servers. See bug #41943
  474.                     if (server.type != "imap")
  475.                         server.performExpand(msgWindow);
  476.                 }
  477.             }
  478.         }
  479.     }
  480. }
  481.  
  482. function loadStartFolder(initialUri)
  483. {
  484.     var folderOutliner = GetFolderOutliner();
  485.     var defaultServer = null;
  486.     var startFolderResource = null;
  487.     var isLoginAtStartUpEnabled = false;
  488.     var enabledNewMailCheckOnce = false;
  489.     var mailCheckOncePref = "mail.startup.enabledMailCheckOnce";
  490.  
  491.     //First get default account
  492.     try
  493.     {
  494.         if(initialUri)
  495.             startFolderResource = RDF.GetResource(initialUri);
  496.         else
  497.         {
  498.             var defaultAccount = accountManager.defaultAccount;
  499.  
  500.             defaultServer = defaultAccount.incomingServer;
  501.             var rootFolder = defaultServer.RootFolder;
  502.             var rootMsgFolder = rootFolder.QueryInterface(Components.interfaces.nsIMsgFolder);
  503.  
  504.             startFolderResource = rootMsgFolder.QueryInterface(Components.interfaces.nsIRDFResource);
  505.  
  506.             enabledNewMailCheckOnce = pref.GetBoolPref(mailCheckOncePref);
  507.  
  508.             // Enable checknew mail once by turning checkmail pref 'on' to bring 
  509.             // all users to one plane. This allows all users to go to Inbox. User can 
  510.             // always go to server settings panel and turn off "Check for new mail at startup"
  511.             if (!enabledNewMailCheckOnce)
  512.             {
  513.                 pref.SetBoolPref(mailCheckOncePref, true);
  514.                 defaultServer.loginAtStartUp = true;
  515.             }
  516.  
  517.             // Get the user pref to see if the login at startup is enabled for default account
  518.             isLoginAtStartUpEnabled = defaultServer.loginAtStartUp;
  519.  
  520.             // Get Inbox only if when we have to login 
  521.             if (isLoginAtStartUpEnabled) 
  522.             {
  523.                 //now find Inbox
  524.                 var outNumFolders = new Object();
  525.                 var inboxFolder = rootMsgFolder.getFoldersWithFlag(0x1000, 1, outNumFolders); 
  526.                 if (!inboxFolder) return;
  527.  
  528.                 startFolderResource = inboxFolder.QueryInterface(Components.interfaces.nsIRDFResource);
  529.             }
  530.             else
  531.             {
  532.                 // set the startFolderResource to the server, so we select it
  533.                 // so we'll get account central
  534.                 startFolderResource = RDF.GetResource(defaultServer.serverURI);
  535.             }
  536.         }
  537.  
  538.         var startFolder = startFolderResource.QueryInterface(Components.interfaces.nsIFolder);
  539.         SelectFolder(startFolder.URI);
  540.                 
  541.         // only do this on startup, when we pass in null
  542.         if (!initialUri && isLoginAtStartUpEnabled)
  543.         {
  544.             // Perform biff on the server to check for new mail, except for imap
  545.             if (defaultServer.type != "imap")
  546.             {
  547.                var localFolder = inboxFolder.QueryInterface(Components.interfaces.nsIMsgLocalMailFolder);
  548.                if (localFolder)
  549.                { 
  550.                    if (!localFolder.parsingInbox)
  551.                        defaultServer.PerformBiff();
  552.                    else
  553.                        localFolder.checkForNewMessagesAfterParsing = true;
  554.                }              
  555.                else  //it can be only nntp
  556.                    defaultServer.PerformBiff();
  557.             }
  558.         } 
  559.  
  560.         // because the "open" state persists, we'll call
  561.         // PerformExpand() for all servers that are open at startup.
  562.         PerformExpandForAllOpenServers();
  563.     }
  564.     catch(ex)
  565.     {
  566.         dump(ex);
  567.         dump('Exception in LoadStartFolder caused by no default account.  We know about this\n');
  568.     }
  569.  
  570.     if (!initialUri) 
  571.     {
  572.         MsgGetMessagesForAllServers(defaultServer);
  573.     }
  574. }
  575.  
  576. function TriggerGetMessages(server)
  577. {
  578.     // downloadMessagesAtStartup for a given server type indicates whether 
  579.     // or not there is a need to Trigger GetMessages action
  580.     if (server.downloadMessagesAtStartup)
  581.         MsgGetMessage();
  582. }
  583.  
  584. function AddToSession()
  585. {
  586.     try {
  587.         var mailSession = Components.classes[mailSessionContractID].getService(Components.interfaces.nsIMsgMailSession);
  588.         
  589.         mailSession.AddFolderListener(folderListener);
  590.     } catch (ex) {
  591.         dump("Error adding to session\n");
  592.     }
  593. }
  594.  
  595. function InitPanes()
  596. {
  597.     OnLoadFolderPane();
  598.     SetupCommandUpdateHandlers();
  599. }
  600.  
  601. function InitializeDataSources()
  602. {
  603.     //Setup common mailwindow stuff.
  604.     AddDataSources();
  605.  
  606.     //To threadpane move context menu
  607.     SetupMoveCopyMenus('threadPaneContext-moveMenu', accountManagerDataSource, folderDataSource);
  608.  
  609.     //To threadpane copy content menu
  610.     SetupMoveCopyMenus('threadPaneContext-copyMenu', accountManagerDataSource, folderDataSource);
  611. }
  612.  
  613. function OnFolderUnreadColAttrModified(event)
  614. {
  615.     if (event.attrName == "hidden")
  616.     {
  617.         var folderNameCell = document.getElementById("folderNameCell");
  618.         if (event.newValue == "true")
  619.         {
  620.             folderNameCell.setAttribute("label", "?folderTreeName");
  621.         }
  622.         else if (event.attrChange == Components.interfaces.nsIDOMMutationEvent.REMOVAL)
  623.         {
  624.             folderNameCell.setAttribute("label", "?folderTreeSimpleName");
  625.         }
  626.     }
  627. }
  628.  
  629. // builds prior to 8-14-2001 did not have the unread and total columns
  630. // in the folder pane.  so if a user ran an old build, and then
  631. // upgraded, they get the new columns, and this causes problems
  632. // because it looks like all the folder names are gone (see bug #96979)
  633. // to work around this, we hide those columns once, using the 
  634. // "mail.ui.folderpane.version" pref.
  635. function UpgradeFolderPaneUI()
  636. {
  637.   var folderPaneUIVersion = pref.GetIntPref("mail.ui.folderpane.version");
  638.  
  639.   if (folderPaneUIVersion == 1) {
  640.     var folderUnreadCol = document.getElementById("folderUnreadCol");
  641.     folderUnreadCol.setAttribute("hidden", "true");
  642.     var folderTotalCol = document.getElementById("folderTotalCol");
  643.     folderTotalCol.setAttribute("hidden", "true");
  644.     pref.SetIntPref("mail.ui.folderpane.version", 2);
  645.   }
  646. }
  647.  
  648. function OnLoadFolderPane()
  649. {
  650.     UpgradeFolderPaneUI();
  651.  
  652.     var folderUnreadCol = document.getElementById("folderUnreadCol");
  653.     var hidden = folderUnreadCol.getAttribute("hidden");
  654.     if (!hidden)
  655.     {
  656.         var folderNameCell = document.getElementById("folderNameCell");
  657.         folderNameCell.setAttribute("label", "?folderTreeSimpleName");
  658.     }
  659.     folderUnreadCol.addEventListener("DOMAttrModified", OnFolderUnreadColAttrModified, false);
  660.  
  661.     SortFolderPane("folderNameCol");
  662.  
  663.     //Add folderDataSource and accountManagerDataSource to folderPane
  664.     accountManagerDataSource = accountManagerDataSource.QueryInterface(Components.interfaces.nsIRDFDataSource);
  665.     folderDataSource = folderDataSource.QueryInterface(Components.interfaces.nsIRDFDataSource);
  666.     var database = GetFolderDatasource();
  667.  
  668.     database.AddDataSource(accountManagerDataSource);
  669.     database.AddDataSource(folderDataSource);
  670.     var folderOutliner = GetFolderOutliner();
  671.     folderOutliner.outlinerBoxObject.outlinerBody.setAttribute("ref", "msgaccounts:/");
  672.     // hack for #98418, remove when #73953 gets fixed
  673.     // (when that gets fixed, the plan is to set the ref and datasources
  674.     // in the .xul
  675.     //
  676.     // setting the ref attribute on the outliner causes us to rebuild it
  677.     folderOutliner.outlinerBoxObject.outlinerBody.setAttribute("ref", "msgaccounts:/");
  678.  
  679.     var folderOutlinerBuilder = folderOutliner.outlinerBoxObject.outlinerBody.builder.QueryInterface(Components.interfaces.nsIXULOutlinerBuilder);
  680.     folderOutlinerBuilder.addObserver(folderObserver);
  681.     folderOutliner.addEventListener("click",FolderPaneOnClick,true);
  682. }
  683.  
  684. function GetFolderDatasource()
  685. {
  686.     var folderOutliner = GetFolderOutliner();
  687.     return folderOutliner.outlinerBoxObject.outlinerBody.database;
  688. }
  689.  
  690. /* Functions for accessing particular parts of the window*/
  691. function GetFolderOutliner()
  692. {
  693.     if (! gFolderOutliner)
  694.         gFolderOutliner = document.getElementById("folderOutliner");
  695.     return gFolderOutliner;
  696. }
  697.  
  698. function GetMessagePane()
  699. {
  700.     if (gMessagePane) return gMessagePane;
  701.     gMessagePane = document.getElementById("messagepanebox");
  702.     return gMessagePane;
  703. }
  704.  
  705. function GetMessagePaneFrame()
  706. {
  707.     if (gMessagePaneFrame) return gMessagePaneFrame;
  708.     gMessagePaneFrame = top.frames['messagepane'];
  709.     return gMessagePaneFrame;
  710. }
  711.  
  712. function FindInSidebar(currentWindow, id)
  713. {
  714.     var item = currentWindow.document.getElementById(id);
  715.     if(item)
  716.         return item;
  717.  
  718.     for(var i = 0; i < currentWindow.frames.length; i++)
  719.     {
  720.         var frameItem = FindInSidebar(currentWindow.frames[i], id);
  721.         if(frameItem)
  722.             return frameItem;
  723.     }
  724.  
  725.     return null;
  726. }
  727.  
  728. function GetThreadAndMessagePaneSplitter()
  729. {
  730.     if(gThreadAndMessagePaneSplitter) return gThreadAndMessagePaneSplitter;
  731.     var splitter = document.getElementById('threadpane-splitter');
  732.     gThreadAndMessagePaneSplitter = splitter;
  733.     return splitter;
  734. }
  735.  
  736. function GetUnreadCountElement()
  737. {
  738.     if(gUnreadCount) return gUnreadCount;
  739.     var unreadCount = document.getElementById('unreadMessageCount');
  740.     gUnreadCount = unreadCount;
  741.     return unreadCount;
  742. }
  743. function GetTotalCountElement()
  744. {
  745.     if(gTotalCount) return gTotalCount;
  746.     var totalCount = document.getElementById('totalMessageCount');
  747.     gTotalCount = totalCount;
  748.     return totalCount;
  749. }
  750.  
  751. function IsThreadAndMessagePaneSplitterCollapsed()
  752. {
  753.   var messagePane = GetMessagePane();
  754.   try {
  755.     return (messagePane.getAttribute("collapsed") == "true");
  756.     }
  757.   catch (ex) {
  758.         return false;
  759.   }
  760. }
  761.  
  762. function FindMessenger()
  763. {
  764.   return messenger;
  765. }
  766.  
  767. function ClearThreadPaneSelection()
  768. {
  769.   try {
  770.     if (gDBView) {
  771.       var outlinerView = gDBView.QueryInterface(Components.interfaces.nsIOutlinerView);
  772.       var outlinerSelection = outlinerView.selection;
  773.       if (outlinerSelection) 
  774.         outlinerSelection.clearSelection(); 
  775.     }
  776.   }
  777.   catch (ex) {
  778.     dump("ClearThreadPaneSelection: ex = " + ex + "\n");
  779.   }
  780. }
  781.  
  782. function ClearMessagePane()
  783. {
  784.     if(gHaveLoadedMessage)
  785.     {    
  786.     gHaveLoadedMessage = false;
  787.         gCurrentDisplayedMessage = null;
  788.         if (window.frames["messagepane"].location != "about:blank")
  789.             window.frames["messagepane"].location = "about:blank";
  790.         // hide the message header view AND the message pane...
  791.         HideMessageHeaderPane();
  792.     }
  793. }
  794.  
  795.  
  796. function GetSelectedFolderIndex()
  797. {
  798.     var folderOutliner = GetFolderOutliner();
  799.     var startIndex = {};
  800.     var endIndex = {};
  801.     folderOutliner.outlinerBoxObject.selection.getRangeAt(0, startIndex, endIndex);
  802.     return startIndex.value;
  803. }
  804.  
  805. function FolderPaneOnClick(event)
  806. {
  807.     // we only care about button 0 (left click) events
  808.     if (event.button != 0)
  809.         return;
  810.  
  811.     var folderOutliner = GetFolderOutliner();
  812.     var row = {};
  813.     var col = {};
  814.     var elt = {};
  815.     folderOutliner.outlinerBoxObject.getCellAt(event.clientX, event.clientY, row, col, elt);
  816.  
  817.     if (elt.value == "twisty")
  818.     {
  819.         var folderResource = GetFolderResource(folderOutliner, row.value);
  820.         var msgFolder = folderResource.QueryInterface(Components.interfaces.nsIMsgFolder);
  821.  
  822.         if (!(folderOutliner.outlinerBoxObject.view.isContainerOpen(row.value)))
  823.         {
  824.             var isServer = GetFolderAttribute(folderOutliner, folderResource, "IsServer");
  825.             if (isServer == "true")
  826.             {
  827.                 var server = msgFolder.server;
  828.                 server.performExpand(msgWindow);
  829.             }
  830.             else
  831.             {
  832.                 var serverType = GetFolderAttribute(folderOutliner, folderResource, "ServerType");
  833.                 if (serverType == "imap")
  834.                 {
  835.                     var imapFolder = folderResource.QueryInterface(Components.interfaces.nsIMsgImapMailFolder);
  836.                     imapFolder.performExpand(msgWindow);
  837.                 }
  838.             }
  839.         }
  840.     }
  841.     else if ((event.originalTarget.localName == "outlinercol") ||
  842.              (event.originalTarget.localName == "slider") ||
  843.              (event.originalTarget.localName == "scrollbarbutton")) {
  844.       // clicking on the name column in the folder pane should not sort
  845.       event.preventBubble();
  846.     }
  847.     else if (event.detail == 2) {
  848.       FolderPaneDoubleClick(row.value, event);
  849.     }
  850. }
  851.  
  852. function FolderPaneDoubleClick(folderIndex, event)
  853. {
  854.     var folderOutliner = GetFolderOutliner();
  855.     var folderResource = GetFolderResource(folderOutliner, folderIndex);
  856.     var msgFolder = folderResource.QueryInterface(Components.interfaces.nsIMsgFolder);
  857.     var isServer = GetFolderAttribute(folderOutliner, folderResource, "IsServer");
  858.  
  859.     if (isServer == "true")
  860.     {
  861.       if (!(folderOutliner.outlinerBoxObject.view.isContainerOpen(folderIndex)))
  862.       {
  863.         var server = msgFolder.server;
  864.         server.performExpand(msgWindow);
  865.       }
  866.     }
  867.     else 
  868.     {
  869.       // Open a new msg window only if we are double clicking on 
  870.       // folders or newsgroups.
  871.       MsgOpenNewWindowForFolder(folderResource.Value);
  872.  
  873.       // double clicking should not toggle the open / close state of the
  874.       // folder.  this will happen if we don't prevent the event from
  875.       // bubbling to the default handler in outliner.xml
  876.       event.preventBubble();
  877.     }
  878. }
  879.  
  880. function ChangeSelection(outliner, newIndex)
  881. {
  882.     if(newIndex >= 0)
  883.     {
  884.         outliner.outlinerBoxObject.selection.select(newIndex);
  885.         outliner.outlinerBoxObject.ensureRowIsVisible(newIndex);
  886.     }
  887. }
  888.  
  889. function SetActiveThreadPaneSortColumn(column)
  890. {
  891.     gActiveThreadPaneSortColumn = column;
  892. }
  893.  
  894. function GetActiveThreadPaneSortColumn()
  895. {
  896.     return gActiveThreadPaneSortColumn;
  897. }
  898.  
  899. function ClearActiveThreadPaneSortColumn()
  900. {
  901.     var activeColumn = document.getElementById(gActiveThreadPaneSortColumn);
  902.     if(activeColumn)
  903.     {
  904.         activeColumn.removeAttribute("sortActive");
  905.         activeColumn = "";
  906.     }
  907.  
  908. }
  909.  
  910. function GetSelectedFolders()
  911. {
  912.     var folderArray = [];
  913.     var k = 0;
  914.     var folderOutliner = GetFolderOutliner();
  915.     var rangeCount = folderOutliner.outlinerBoxObject.selection.getRangeCount();
  916.  
  917.     for(var i = 0; i < rangeCount; i++)
  918.     {
  919.         var startIndex = {};
  920.         var endIndex = {};
  921.         folderOutliner.outlinerBoxObject.selection.getRangeAt(i, startIndex, endIndex);
  922.         for (var j = startIndex.value; j <= endIndex.value; j++)
  923.         {
  924.             var folderResource = GetFolderResource(folderOutliner, j);
  925.             folderArray[k++] = folderResource.Value;
  926.         }
  927.     }
  928.  
  929.     return folderArray;
  930. }
  931.  
  932. function GetSelectedMsgFolders()
  933. {
  934.     var folderArray = [];
  935.     var k = 0;
  936.     var folderOutliner = GetFolderOutliner();
  937.     var rangeCount = folderOutliner.outlinerBoxObject.selection.getRangeCount();
  938.  
  939.     for(var i = 0; i < rangeCount; i++)
  940.     {
  941.         var startIndex = {};
  942.         var endIndex = {};
  943.         folderOutliner.outlinerBoxObject.selection.getRangeAt(i, startIndex, endIndex);
  944.         for (var j = startIndex.value; j <= endIndex.value; j++)
  945.         {
  946.             var msgFolder = GetFolderResource(folderOutliner, j).QueryInterface(Components.interfaces.nsIMsgFolder);
  947.             if(msgFolder)
  948.                 folderArray[k++] = msgFolder;
  949.         }
  950.     }
  951.  
  952.     return folderArray;
  953. }
  954.  
  955. function GetFirstSelectedMessage()
  956. {
  957.     try {
  958.         return gDBView.URIForFirstSelectedMessage;
  959.     }
  960.     catch (ex) {
  961.         return null;
  962.     }
  963. }
  964.  
  965. function GetSelectedIndices(dbView)
  966. {
  967.   try {
  968.     var indicesArray = {}; 
  969.     var length = {};
  970.     dbView.getIndicesForSelection(indicesArray,length);
  971.     return indicesArray.value;
  972.   }
  973.   catch (ex) {
  974.     dump("ex = " + ex + "\n");
  975.     return null;
  976.   }
  977. }
  978.  
  979. function GetSelectedMessages()
  980. {
  981.   try {
  982.     var messageArray = {}; 
  983.     var length = {};
  984.     gDBView.getURIsForSelection(messageArray,length);
  985.     return messageArray.value;
  986.   }
  987.   catch (ex) {
  988.     dump("ex = " + ex + "\n");
  989.     return null;
  990.   }
  991. }
  992.  
  993. function GetLoadedMsgFolder()
  994. {
  995.     if (!gDBView) return null;
  996.     return gDBView.msgFolder;
  997. }
  998.  
  999. function GetLoadedMessage()
  1000. {
  1001.     try {
  1002.         return gDBView.URIForFirstSelectedMessage;
  1003.     }
  1004.     catch (ex) {
  1005.         return null;
  1006.     }
  1007. }
  1008.  
  1009. //Clear everything related to the current message. called after load start page.
  1010. function ClearMessageSelection()
  1011. {
  1012.     ClearThreadPaneSelection();
  1013. }
  1014.  
  1015. function GetCompositeDataSource(command)
  1016. {
  1017.     if (command == "GetNewMessages" || command == "NewFolder" || command == "MarkAllMessagesRead")
  1018.         return GetFolderDatasource();
  1019.  
  1020.     return null;
  1021. }
  1022.  
  1023. function SetNextMessageAfterDelete()
  1024. {
  1025.     gNextMessageViewIndexAfterDelete = gDBView.msgToSelectAfterDelete;
  1026. }
  1027.  
  1028. function EnsureAllAncestorsAreExpanded(outliner, resource)
  1029. {
  1030.     // get the parent of the desired folder, and then try to get
  1031.     // the index of the parent in the outliner
  1032.     var folder = resource.QueryInterface(Components.interfaces.nsIFolder);
  1033.     
  1034.     // if this is a server, there are no ancestors, so stop.
  1035.     var msgFolder = folder.QueryInterface(Components.interfaces.nsIMsgFolder);
  1036.     if (msgFolder.isServer)
  1037.       return;
  1038.  
  1039.     var parentFolderResource = RDF.GetResource(folder.parent.URI);
  1040.     var folderIndex = GetFolderIndex(outliner, parentFolderResource);
  1041.  
  1042.     if (folderIndex == -1) {
  1043.       // if we couldn't find the parent, recurse
  1044.       EnsureAllAncestorsAreExpanded(outliner, parentFolderResource);
  1045.       // ok, now we should be able to find the parent
  1046.       folderIndex = GetFolderIndex(outliner, parentFolderResource);
  1047.     }
  1048.  
  1049.     // if the parent isn't open, open it
  1050.     if (!(outliner.outlinerBoxObject.view.isContainerOpen(folderIndex)))
  1051.       outliner.outlinerBoxObject.view.toggleOpenState(folderIndex);
  1052. }
  1053.  
  1054. function SelectFolder(folderUri)
  1055. {
  1056.     var folderOutliner = GetFolderOutliner();
  1057.     var folderResource = RDF.GetResource(folderUri);
  1058.  
  1059.     // before we can select a folder, we need to make sure it is "visible"
  1060.     // in the outliner.  to do that, we need to ensure that all its
  1061.     // ancestors are expanded
  1062.     EnsureAllAncestorsAreExpanded(folderOutliner, folderResource);
  1063.     var folderIndex = GetFolderIndex(folderOutliner, folderResource);
  1064.     ChangeSelection(folderOutliner, folderIndex);
  1065. }
  1066.  
  1067. function SelectMessage(messageUri)
  1068. {
  1069.   // this isn't going to work anymore
  1070.   dump("XXX fix this or remove SelectMessage()\n");
  1071. }
  1072.  
  1073. function ReloadMessage()
  1074. {
  1075.   gDBView.reloadMessage();
  1076. }
  1077.  
  1078. function SetBusyCursor(window, enable)
  1079. {
  1080.     if(enable)
  1081.         window.setCursor("wait");
  1082.     else
  1083.         window.setCursor("auto");
  1084.  
  1085.     var numFrames = window.frames.length;
  1086.     for(var i = 0; i < numFrames; i++)
  1087.         SetBusyCursor(window.frames[i], enable);
  1088. }
  1089.  
  1090. function GetDBView()
  1091. {
  1092.     return gDBView;
  1093. }
  1094.  
  1095. function GetFolderResource(outliner, index)
  1096. {
  1097.     var outlinerBuilder = outliner.outlinerBoxObject.outlinerBody.builder.QueryInterface(Components.interfaces.nsIXULOutlinerBuilder);
  1098.     return outlinerBuilder.getResourceAtIndex(index);
  1099. }
  1100.  
  1101. function GetFolderIndex(outliner, resource)
  1102. {
  1103.     var outlinerBuilder = outliner.outlinerBoxObject.outlinerBody.builder.QueryInterface(Components.interfaces.nsIXULOutlinerBuilder);
  1104.     return outlinerBuilder.getIndexOfResource(resource);
  1105. }
  1106.  
  1107. function GetFolderAttribute(outliner, source, attribute)
  1108. {
  1109.     var property = RDF.GetResource("http://home.netscape.com/NC-rdf#" + attribute);
  1110.     var target = outliner.outlinerBoxObject.outlinerBody.database.GetTarget(source, property, true);
  1111.     if (target)
  1112.         target = target.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
  1113.     return target;
  1114. }
  1115.