home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / mozil06.zip / bin / chrome / messenger.jar / content / messenger / msgHdrViewOverlay.js < prev    next >
Text File  |  2001-02-14  |  32KB  |  852 lines

  1. /* -*- Mode: C++; 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.  
  21. /* This is where functions related to displaying the headers for a selected message in the
  22.    message pane live. */
  23.  
  24. ////////////////////////////////////////////////////////////////////////////////////
  25. // Warning: if you go to modify any of these JS routines please get a code review from either
  26. // hangas@netscape.com or mscott@netscape.com. It's critical that the code in here for displaying
  27. // the message headers for a selected message remain as fast as possible. In particular, 
  28. // right now, we only introduce one reflow per message. i.e. if you click on a message in the thread
  29. // pane, we batch up all the changes for displaying the header pane (to, cc, attachements button, etc.) 
  30. // and we make a single pass to display them. It's critical that we maintain this one reflow per message
  31. // view in the message header pane. 
  32. //
  33. ////////////////////////////////////////////////////////////////////////////////////
  34.  
  35. var msgHeaderParserContractID           = "@mozilla.org/messenger/headerparser;1";
  36. var abAddressCollectorContractID     = "@mozilla.org/addressbook/services/addressCollecter;1";
  37.  
  38. var msgPaneData;
  39. var currentHeaderData = {};
  40. // gGeneratedViewAllHeaderInfo --> we clear this every time we start to display a new message.
  41. // the view all header popup will set it when we first generate a view of all the headers. this is 
  42. // just so it won't try to regenerate all the information every time the user clicks on the popup.
  43. var gGeneratedViewAllHeaderInfo = false; 
  44. var gViewAllHeaders = false;
  45. var gNumAddressesToShow = 3;
  46. var gShowUserAgent = false;
  47.  
  48. // attachments array
  49. var attachmentUrlArray = new Array();
  50. var attachmentDisplayNameArray = new Array();
  51. var attachmentMessageUriArray = new Array();
  52.  
  53. var msgHeaderParser = Components.classes[msgHeaderParserContractID].getService(Components.interfaces.nsIMsgHeaderParser);
  54. var abAddressCollector = Components.classes[abAddressCollectorContractID].getService(Components.interfaces.nsIAbAddressCollecter);
  55.  
  56. // All these variables are introduced to keep track of insertion and deletion of the toggle button either
  57. // as the first node in the list of emails or the last node.
  58. var numOfEmailsInEnumerator;
  59. var numOfEmailsInToField = 0;
  60. var numOfEmailsInCcField = 0;
  61. var numOfEmailsInFromField = 0;
  62.  
  63. // var used to determine whether to show the toggle button at the
  64. // beginning or at the end of a list of emails in to/cc fields.
  65. var gNumOfEmailsToShowToggleButtonInFront = 15;
  66.  
  67. function OnLoadMsgHeaderPane()
  68. {
  69.    // build a document object for the header pane so we can cache fetches for elements
  70.   // in a local variable
  71.   // if you add more document elements with ids to msgHeaderPane.xul, you should add 
  72.   // to this object...
  73.   msgPaneData = new Object;
  74.  
  75.   // HACK...force our XBL bindings file to be load before we try to create our first xbl widget....
  76.   // otherwise we have problems.
  77.  
  78.   document.loadBindingDocument('chrome://messenger/content/mailWidgets.xml');
  79.  
  80.   if (msgPaneData)
  81.   {
  82.     // First group of headers
  83.     msgPaneData.SubjectBox = document.getElementById("SubjectBox");
  84.     msgPaneData.SubjectValue = document.getElementById("SubjectValue");
  85.     msgPaneData.FromBox   =   document.getElementById("FromBox");
  86.     msgPaneData.FromValue = document.getElementById("FromValue");
  87.     msgPaneData.ReplyToBox   =   document.getElementById("ReplyToBox");
  88.     msgPaneData.ReplyToValue = document.getElementById("ReplyToValue");
  89.  
  90.     msgPaneData.DateBox = document.getElementById("DateBox");
  91.     msgPaneData.DateValue = document.getElementById("DateValue");
  92.  
  93.     // Attachment related elements
  94.     msgPaneData.AttachmentPopup = document.getElementById("attachmentPopup");
  95.     msgPaneData.AttachmentButton = document.getElementById("attachmentButton");
  96.  
  97.     // Second toolbar 
  98.     msgPaneData.ToBox = document.getElementById("ToBox");
  99.     
  100.     // ToValueShort is the div which shows a shortened number of addresses
  101.     // on the to line...ToValueLong is a div which shows all of the
  102.     // addresses on the to line. The same rule applies for ccValueShort/Long
  103.     msgPaneData.ToValueShort = document.getElementById("ToValueShort");
  104.     msgPaneData.ToValueLong = document.getElementById("ToValueLong");
  105.     msgPaneData.ToValueToggleIcon = document.getElementById("ToValueToggleIcon");
  106.  
  107.     msgPaneData.CcBox = document.getElementById("CcBox");
  108.     msgPaneData.CcValueShort = document.getElementById("CcValueShort");
  109.     msgPaneData.CcValueLong = document.getElementById("CcValueLong");
  110.     msgPaneData.CcValueToggleIcon = document.getElementById("CcValueToggleIcon");
  111.  
  112.     msgPaneData.NewsgroupBox = document.getElementById("NewsgroupBox");
  113.     msgPaneData.NewsgroupValue = document.getElementById("NewsgroupValue");
  114.     msgPaneData.FollowupToBox = document.getElementById("FollowupToBox");
  115.     msgPaneData.FollowupToValue = document.getElementById("FollowupToValue");
  116.  
  117.     msgPaneData.UserAgentBox = document.getElementById("UserAgentBox");
  118.     msgPaneData.UserAgentToolbar = document.getElementById("headerPart3");
  119.     msgPaneData.UserAgentValue = document.getElementById("UserAgentValue");
  120.  
  121.     msgPaneData.ViewAllHeadersToolbar = document.getElementById("viewAllHeadersToolbar");
  122.     msgPaneData.ViewAllHeadersBox = document.getElementById("viewAllHeadersBox");
  123.   }
  124.   
  125.   // load any preferences that at are global with regards to 
  126.   // displaying a message...
  127.   gNumAddressesToShow = pref.GetIntPref("mailnews.max_header_display_length");
  128.   gShowUserAgent = pref.GetBoolPref("mailnews.headers.showUserAgent");
  129. }
  130.  
  131. // The messageHeaderSink is the class that gets notified of a message's headers as we display the message
  132. // through our mime converter. 
  133.  
  134. var messageHeaderSink = {
  135.     onStartHeaders: function()
  136.     {
  137.       // every time we start to redisplay a message, check the view all headers pref....
  138.       var showAllHeadersPref = pref.GetIntPref("mail.show_headers");
  139.       if (showAllHeadersPref == 2)
  140.         gViewAllHeaders = true;
  141.       else
  142.         gViewAllHeaders = false;
  143.  
  144.       ClearCurrentHeaders();
  145.       gGeneratedViewAllHeaderInfo = false;
  146.       ClearAttachmentMenu();
  147.     },
  148.  
  149.     onEndHeaders: function() 
  150.     {
  151.       // WARNING: This is the ONLY routine inside of the message Header Sink that should 
  152.       // trigger a reflow!
  153.       
  154.       if (this.NotifyClearAddresses != undefined)
  155.         NotifyClearAddresses();
  156.  
  157.       // (1) clear out the email fields for to, from, cc....
  158.       ClearEmailField(msgPaneData.FromValue);
  159.       ClearEmailField(msgPaneData.ReplyToValue);
  160.  
  161.       // When calling the ClearEmailFieldWithButton, pass in the name of the header too.
  162.       ClearEmailFieldWithButton(msgPaneData.ToValueShort, "to");
  163.       ClearEmailFieldWithButton(msgPaneData.CcValueShort, "cc");
  164.       ClearEmailFieldWithButton(msgPaneData.ToValueLong, "to");
  165.       ClearEmailFieldWithButton(msgPaneData.CcValueLong, "cc");
  166.  
  167.       // be sure to re-hide the toggle button, we'll re-enable it later if we need it...
  168.       msgPaneData.ToValueToggleIcon.setAttribute('collapsed', 'true');
  169.       msgPaneData.CcValueToggleIcon.setAttribute('collapsed', 'true');
  170.       //hdrViewSetVisible(msgPaneData.ToValueToggleIcon, false);
  171.       //hdrViewSetVisible(msgPaneData.CcValueToggleIcon, false);
  172.       
  173.       ShowMessageHeaderPane();
  174.       UpdateMessageHeaders();
  175.     },
  176.  
  177.     handleHeader: function(headerName, headerValue) 
  178.     {
  179.       // WARNING: if you are modifying this function, make sure you do not do *ANY*
  180.       // dom manipulations which would trigger a reflow. This method gets called 
  181.       // for every rfc822 header in the message being displayed. If you introduce a reflow
  182.       // you'll be introducing a reflow for every time we are told about a header. And msgs have
  183.       // a lot of headers. Don't do it =)....Move your code into OnEndHeaders which is only called
  184.       // once per message view.
  185.  
  186.       // for consistancy sake, let's force all header names to be lower case so
  187.       // we don't have to worry about looking for: Cc and CC, etc.
  188.       var lowerCaseHeaderName = headerName.toLowerCase();
  189.       var foo = new Object;
  190.       foo.headerValue = headerValue;
  191.       foo.headerName = headerName;
  192.       currentHeaderData[lowerCaseHeaderName] = foo;
  193.       if (lowerCaseHeaderName == "from")
  194.       {
  195.              var  collectIncoming = pref.GetBoolPref("mail.collect_email_address_incoming");
  196.         if (collectIncoming && headerValue && abAddressCollector)
  197.           abAddressCollector.collectUnicodeAddress(headerValue);  
  198.       }
  199.  
  200.     },
  201.  
  202.     handleAttachment: function(contentType, url, displayName, uri, notDownloaded) 
  203.     {
  204.         // be sure to escape the display name before we insert it into the
  205.         // method
  206.       var commandString = "OpenAttachURL('" + contentType + "', '" + url + "', '" + escape(displayName) + "', '" + uri + "')";
  207.       var screenDisplayName = displayName;
  208.  
  209.       if (notDownloaded)
  210.       {
  211.         screenDisplayName += " " + Bundle.GetStringFromName("notDownloaded");
  212.       }
  213.  
  214.       AddAttachmentToMenu(screenDisplayName, commandString);
  215.  
  216.       var count = attachmentUrlArray.length;
  217.       // dump ("** attachment count**" + count + "\n");
  218.       if (count < 0) count = 0;
  219.       attachmentUrlArray[count] = url;
  220.       attachmentDisplayNameArray[count] = escape(displayName);
  221.       attachmentMessageUriArray[count] = uri;
  222.     },
  223.     
  224.     onEndAllAttachments: function()
  225.     {
  226.         AddSaveAllAttachmentsMenu();
  227.     }
  228. };
  229.  
  230. function AddNodeToAddressBook (emailAddressNode)
  231. {
  232.   if (emailAddressNode)
  233.   {
  234.     var primaryEmail = emailAddressNode.getAttribute("emailAddress");
  235.     var displayName = emailAddressNode.getAttribute("displayName");
  236.       window.openDialog("chrome://messenger/content/addressbook/abNewCardDialog.xul",
  237.                       "",
  238.                       "chrome,titlebar,resizeable=no", 
  239.             {primaryEmail:primaryEmail, displayName:displayName });
  240.   }
  241. }
  242.  
  243. // SendMailToNode takes the email address title button, extracts
  244. // the email address we stored in there and opens a compose window
  245. // with that address
  246. function SendMailToNode(emailAddressNode)
  247. {
  248.   if (emailAddressNode)
  249.   {
  250.      var emailAddress = emailAddressNode.getAttribute("emailAddress");
  251.      if (emailAddress)
  252.         messenger.OpenURL("mailto:" + emailAddress );
  253.   }
  254. }
  255.  
  256. function OpenAttachURL(contentType, url, displayName, messageUri)
  257. {
  258.     var args = {dspname: displayName, opval: 0};
  259.  
  260.   window.openDialog("chrome://messenger/content/openSaveAttachment.xul",
  261.                     "openSaveAttachment", "chrome,modal", args);
  262.   if (args.opval == 1)
  263.       messenger.openAttachment(contentType, url, displayName, messageUri);
  264.   else if (args.opval == 2)
  265.       messenger.saveAttachment(url, displayName, messageUri);
  266. }
  267.  
  268. function AddAttachmentToMenu(name, oncommand) 
  269.   var popup = document.getElementById("attachmentPopup"); 
  270.   if (popup)
  271.   { 
  272.     var item = document.createElement('menuitem'); 
  273.     if ( item ) 
  274.     { 
  275.       popup.appendChild(item);
  276.       item.setAttribute('value', name); 
  277.       item.setAttribute('oncommand', oncommand); 
  278.     } 
  279.  
  280.     var button = document.getElementById("attachmentButton");
  281.     if (button)
  282.     {
  283.        button.setAttribute("value", popup.childNodes.length);
  284.     }
  285.   } 
  286.  
  287.   var attachBox = document.getElementById("attachmentBox");
  288.   if (attachBox)
  289.     attachBox.removeAttribute("collapsed");
  290.  
  291. function SaveAllAttachments()
  292. {
  293.     try 
  294.     {
  295.         messenger.saveAllAttachments(attachmentUrlArray.length,
  296.                                      attachmentUrlArray,
  297.                                      attachmentDisplayNameArray,
  298.                                      attachmentMessageUriArray);
  299.     }
  300.     catch (ex)
  301.     {
  302.         dump ("** failed to save all attachments ** \n");
  303.     }
  304. }
  305.  
  306. function AddSaveAllAttachmentsMenu()
  307. {
  308.     var popup = document.getElementById("attachmentPopup");
  309.     if (popup && popup.childNodes.length > 1)
  310.     {
  311.         var separator = document.createElement('menuseparator');
  312.         var item = document.createElement('menuitem');
  313.         if (separator && item)
  314.         {
  315.             popup.appendChild(separator);
  316.             popup.appendChild(item);
  317.             item.setAttribute('value', "Save All...");
  318.             item.setAttribute('oncommand', "SaveAllAttachments()");
  319.         }
  320.     }
  321. }
  322.  
  323.  
  324. function ClearAttachmentMenu() 
  325.   var popup = document.getElementById("attachmentPopup"); 
  326.   if ( popup ) 
  327.   { 
  328.      while ( popup.childNodes.length ) 
  329.        popup.removeChild(popup.childNodes[0]); 
  330.   } 
  331.  
  332.   var attachBox = document.getElementById("attachmentBox");
  333.   if (attachBox)
  334.     attachBox.setAttribute("collapsed", "true");
  335.  
  336.   // reset attachments name array
  337.   attachmentUrlArray.length = 0;
  338.   attachmentDisplayNameArray.length = 0;
  339.   attachmentMessageUriArray.length = 0;
  340. }
  341.  
  342. // Assumes that all the child nodes of the parent div need removed..leaving
  343. // an empty parent div...This is used to clear the To/From/cc lines where
  344. // we had to insert email addresses one at a time into their parent divs...
  345. function ClearEmailFieldWithButton(parentDiv, headerName)
  346. {
  347.   if (parentDiv)
  348.   {
  349.     // the toggle button could be the very first child (if there are many email addresses)
  350.     // or it could be the last child in the child nodes..
  351.     // we should never remove the toggle button...
  352.  
  353.     // We use the delIndex variable to keep track of whether the toggle button is the:
  354.     // first child -- in which case it is set to 1 and first element is never deleted
  355.     // last child -- in which case it is set to 0 and the last element is never deleted.
  356.     var delIndex = 1;
  357.  
  358.     // Depending on the headerName and the numOfEmails inserted into that header,
  359.     // decide what the delIndex should be.
  360.     if (headerName == "to") {
  361.         if (numOfEmailsInToField < gNumOfEmailsToShowToggleButtonInFront)
  362.             delIndex = 0;
  363.     }
  364.     else if (headerName == "cc") {
  365.         if (numOfEmailsInCcField < gNumOfEmailsToShowToggleButtonInFront)
  366.             delIndex = 0;
  367.     }
  368.     else {
  369.         if (numOfEmailsInFromField < gNumOfEmailsToShowToggleButtonInFront)
  370.             delIndex = 0;
  371.     }
  372.  
  373.     while (parentDiv.childNodes.length > 1)
  374.       parentDiv.removeChild(parentDiv.childNodes[delIndex]);
  375.   }
  376. }
  377.  
  378. // Clear Email Field takes the passed in div and removes all the child nodes!
  379. // if your div has a button in it (like To/cc use ClearEmailfieldWithButton
  380. function ClearEmailField(parentDiv)
  381. {
  382.   if (parentDiv)
  383.   {
  384.     while (parentDiv.childNodes.length > 0)
  385.       parentDiv.removeChild(parentDiv.childNodes[0]);
  386.   }
  387. }
  388.  
  389. function OutputNewsgroups(boxNode, textNode, currentHeaderData, headerName)
  390. {
  391.   if (currentHeaderData[headerName])
  392.   {    
  393.     var headerValue = currentHeaderData[headerName].headerValue;
  394.     headerValue = headerValue.replace(/,/g,", ");
  395.  
  396.     hdrViewSetNodeWithBox(boxNode, textNode, headerValue);
  397.   }
  398.   else
  399.     hdrViewSetNodeWithBox(boxNode, textNode, "");
  400. }
  401.  
  402.  
  403. // OutputEmailAddresses --> knows how to take a comma separated list of email addresses,
  404. // extracts them one by one, linkifying each email address into a mailto url. 
  405. // Then we add the link'ified email address to the parentDiv passed in.
  406. // 
  407. // defaultParentDiv --> the div to add the link-ified email addresses into. 
  408. // emailAddresses --> comma separated list of the addresses for this header field
  409. // includeShortLongToggle --> true if you want to include the ability to toggle between short/long
  410. // address views for this header field. If true, then pass in a another div which is the div the long
  411. // view will be added too...
  412.  
  413. function OutputEmailAddresses(parentBox, defaultParentDiv, emailAddresses, includeShortLongToggle, optionalLongDiv, optionalToggleButton, currentHeaderName)
  414. {
  415.   // if we don't have any addresses for this field, hide the parent box!
  416.     if ( !emailAddresses )
  417.     {
  418.         hdrViewSetVisible(parentBox, false);
  419.         return;
  420.     }
  421.   if (msgHeaderParser)
  422.   {
  423.     // Count the number of email addresses being inserted into each header
  424.     // The headers could be "to", "cc", "from"
  425.     var myEnum = msgHeaderParser.ParseHeadersWithEnumerator(emailAddresses);
  426.     myEnum = myEnum.QueryInterface(Components.interfaces.nsISimpleEnumerator);
  427.  
  428.     numOfEmailsInEnumerator = 0;
  429.     while (myEnum.hasMoreElements())
  430.     {
  431.         myEnum.getNext();
  432.         numOfEmailsInEnumerator++;
  433.     }
  434.  
  435.     // Depending on the headerName and the variable that keeps track of the
  436.     // numOfEmails inserted into that header,
  437.     if (currentHeaderName == "to")
  438.         numOfEmailsInToField = numOfEmailsInEnumerator;
  439.     else if (currentHeaderName == "cc")
  440.         numOfEmailsInCcField = numOfEmailsInEnumerator;
  441.     else if (currentHeaderName == "from") 
  442.         numOfEmailsInFromField = numOfEmailsInEnumerator;
  443.  
  444.     var enumerator = msgHeaderParser.ParseHeadersWithEnumerator(emailAddresses);
  445.     enumerator = enumerator.QueryInterface(Components.interfaces.nsISimpleEnumerator);
  446.     var numAddressesParsed = 0;
  447.     if (enumerator)
  448.     {
  449.       var emailAddress = {};
  450.       var name = {};
  451.  
  452.       while (enumerator.hasMoreElements())
  453.       {
  454.         var headerResult = enumerator.getNext();
  455.         headerResult = enumerator.QueryInterface(Components.interfaces.nsIMsgHeaderParserResult);
  456.         
  457.         // get the email and name fields
  458.         var addrValue = {};
  459.         var nameValue = {};
  460.         var fullAddress = headerResult.getAddressAndName(addrValue, nameValue);
  461.         emailAddress = addrValue.value;
  462.         name = nameValue.value;
  463.  
  464.         // if we want to include short/long toggle views and we have a long view, always add it.
  465.         // if we aren't including a short/long view OR if we are and we haven't parsed enough
  466.         // addresses to reach the cutoff valve yet then add it to the default (short) div.
  467.         if (includeShortLongToggle && optionalLongDiv)
  468.         {
  469.           InsertEmailAddressUnderEnclosingBox(parentBox, optionalLongDiv, true, emailAddress, fullAddress, name);
  470.         }
  471.         if (!includeShortLongToggle || (numAddressesParsed < gNumAddressesToShow))
  472.         {
  473.           InsertEmailAddressUnderEnclosingBox(parentBox, defaultParentDiv, includeShortLongToggle, emailAddress, fullAddress, name);
  474.         }
  475.         
  476.         numAddressesParsed++;
  477.       } 
  478.     } // if enumerator
  479.  
  480.     if (includeShortLongToggle && (numAddressesParsed > gNumAddressesToShow) && optionalToggleButton)
  481.     {
  482.       optionalToggleButton.removeAttribute('collapsed');
  483.     }
  484.   } // if msgheader parser
  485. }
  486.  
  487. /* InsertEmailAddressUnderEnclosingBox --> right now all email addresses are borderless titled buttons
  488.    with formatting to make them look like html anchors. When you click on the button,
  489.    you are prompted with a popup asking you what you want to do with the email address
  490.  
  491.    parentBox --> the enclosing box for all the email addresses for this header. This is needed
  492.                  to control visibility of the header.
  493.    parentDiv --> the DIV the email addresses need to be inserted into.
  494.    includesToggleButton --> true if the parentDiv includes a toggle button we want contnet inserted BEFORE
  495.                             false if the parentDiv does not contain a toggle button. This is required in order
  496.                             to properly detect if we should be inserting addresses before this node....
  497. */
  498.    
  499. function InsertEmailAddressUnderEnclosingBox(parentBox, parentDiv, includesToggleButton, emailAddress, fullAddress, displayName) 
  500. {
  501.   if ( parentBox ) 
  502.   { 
  503.     var item = document.createElement("mail-emailaddress");
  504.     var itemInDocument;
  505.     if ( item && parentDiv) 
  506.     { 
  507.       if (parentDiv.childNodes.length)
  508.       {
  509.         var child = parentDiv.childNodes[parentDiv.childNodes.length - 1]; 
  510.         if (parentDiv.childNodes.length > 1 || (!includesToggleButton && parentDiv.childNodes.length >= 1) )
  511.         {
  512.           var textNode = document.createElement("text");
  513.           textNode.setAttribute("value", ", ");
  514.           textNode.setAttribute("class", "emailSeparator");
  515.           if (includesToggleButton && numOfEmailsInEnumerator < gNumOfEmailsToShowToggleButtonInFront)
  516.             parentDiv.insertBefore(textNode, child);
  517.           else
  518.             parentDiv.appendChild(textNode);
  519.         }
  520.         if (includesToggleButton && numOfEmailsInEnumerator < gNumOfEmailsToShowToggleButtonInFront)
  521.           itemInDocument = parentDiv.insertBefore(item, child);
  522.         else
  523.           itemInDocument = parentDiv.appendChild(item);
  524.       }
  525.       else
  526.       {
  527.         itemInDocument = parentDiv.appendChild(item);
  528.       }
  529.  
  530.       itemInDocument.setAttribute("value", fullAddress);    
  531.       itemInDocument.setTextAttribute("emailAddress", emailAddress);
  532.       itemInDocument.setTextAttribute("fullAddress", fullAddress);  
  533.       itemInDocument.setTextAttribute("displayName", displayName);  
  534.       
  535.       if (this.AddExtraAddressProcessing != undefined)
  536.         AddExtraAddressProcessing(emailAddress, itemInDocument);
  537.  
  538.       hdrViewSetVisible(parentBox, true);
  539.     } 
  540.   } 
  541. }
  542.  
  543.  
  544. function UpdateMessageHeaders()
  545. {
  546.   if (gViewAllHeaders)
  547.   {
  548.     fillBoxWithAllHeaders(msgPaneData.ViewAllHeadersBox, false);
  549.     return;
  550.   }
  551.  
  552.   if (currentHeaderData["subject"])
  553.      hdrViewSetNodeWithBox(msgPaneData.SubjectBox, msgPaneData.SubjectValue, currentHeaderData["subject"].headerValue);
  554.   else
  555.      hdrViewSetNodeWithBox(msgPaneData.SubjectBox, msgPaneData.SubjectValue, "");
  556.  
  557.   if (currentHeaderData["from"])
  558.     OutputEmailAddresses(msgPaneData.FromBox, msgPaneData.FromValue, currentHeaderData["from"].headerValue, false, "", "", "from"); 
  559.   else
  560.     OutputEmailAddresses(msgPaneData.FromBox, msgPaneData.FromValue, "", false, "", "", ""); 
  561.  
  562.   if (currentHeaderData["date"])
  563.     hdrViewSetNodeWithBox(msgPaneData.DateBox, msgPaneData.DateValue, currentHeaderData["date"].headerValue); 
  564.   else
  565.     hdrViewSetNodeWithBox(msgPaneData.DateBox, msgPaneData.DateValue, ""); 
  566.   
  567.   if (currentHeaderData["to"])
  568.     OutputEmailAddresses(msgPaneData.ToBox, msgPaneData.ToValueShort, currentHeaderData["to"].headerValue, true, msgPaneData.ToValueLong, msgPaneData.ToValueToggleIcon, "to");
  569.   else
  570.     OutputEmailAddresses(msgPaneData.ToBox, msgPaneData.ToValueShort, "", true, msgPaneData.ToValueLong, msgPaneData.ToValueToggleIcon, "");
  571.  
  572.   if (currentHeaderData["cc"])
  573.     OutputEmailAddresses(msgPaneData.CcBox, msgPaneData.CcValueShort, currentHeaderData["cc"].headerValue, true, msgPaneData.CcValueLong, msgPaneData.CcValueToggleIcon, "cc");
  574.   else
  575.     OutputEmailAddresses(msgPaneData.CcBox, msgPaneData.CcValueShort, "", true, msgPaneData.CcValueLong, msgPaneData.CcValueToggleIcon, "");
  576.   
  577.   if (currentHeaderData["newsgroups"])
  578.     OutputNewsgroups(msgPaneData.NewsgroupBox, msgPaneData.NewsgroupValue, currentHeaderData, "newsgroups");
  579.   else
  580.     hdrViewSetNodeWithBox(msgPaneData.NewsgroupBox, msgPaneData.NewsgroupValue, ""); 
  581.  
  582.   if (currentHeaderData["followup-to"])
  583.     OutputNewsgroups(msgPaneData.FollowupToBox, msgPaneData.FollowupToValue, currentHeaderData, "followup-to");
  584.   else
  585.     hdrViewSetNodeWithBox(msgPaneData.FollowupToBox, msgPaneData.NewsgroupValue, ""); 
  586.  
  587.   if (gShowUserAgent)
  588.   { 
  589.     if (currentHeaderData["user-agent"])
  590.     {
  591.       hdrViewSetNodeWithBox(msgPaneData.UserAgentBox, msgPaneData.UserAgentValue, currentHeaderData["user-agent"].headerValue);
  592.       if (msgPaneData.UserAgentToolbar)
  593.         msgPaneData.UserAgentToolbar.removeAttribute("collapsed");
  594.     }
  595.     else
  596.     {
  597.       hdrViewSetNodeWithBox(msgPaneData.UserAgentBox, msgPaneData.UserAgentValue, "");
  598.       if (msgPaneData.UserAgentToolbar)
  599.         msgPaneData.UserAgentToolbar.setAttribute("collapsed", "true"); 
  600.     }
  601.  
  602.   }
  603.   
  604.   if (this.FinishEmailProcessing != undefined)
  605.     FinishEmailProcessing();
  606. }
  607.  
  608. function ClearCurrentHeaders()
  609. {
  610.   currentHeaderData = {};
  611. }
  612.  
  613. function ShowMessageHeaderPane()
  614.   if (gViewAllHeaders)
  615.   {
  616.     HideMessageHeaderPane();
  617.     msgPaneData.ViewAllHeadersToolbar.removeAttribute("collapsed");
  618.     msgPaneData.ViewAllHeadersBox.removeAttribute("collapsed");
  619.   }
  620.   else
  621.   {
  622.     msgPaneData.ViewAllHeadersToolbar.setAttribute("collapsed", "true");
  623.     msgPaneData.ViewAllHeadersBox.setAttribute("collapsed", "true");
  624.  
  625.     /* workaround for 39655 */
  626.     var messagePaneBox = document.getElementById("messagepanebox");
  627.     if (messagePaneBox && gFolderJustSwitched)
  628.       messagePaneBox.setAttribute("collapsed", "true");
  629.           
  630.     var node = document.getElementById("headerPart1");
  631.     if (node)
  632.       node.removeAttribute("collapsed");
  633.     node = document.getElementById("headerPart2");
  634.     if (node)
  635.       node.removeAttribute("collapsed");
  636.  
  637.     /* more workaround for 39655 */
  638.     if (messagePaneBox && gFolderJustSwitched) {
  639.       messagePaneBox.setAttribute("collapsed", "false");
  640.       gFolderJustSwitched = false;
  641.     }
  642.  
  643. /*
  644.     node = document.getElementById("headerPart3");
  645.     if (node)
  646.       node.removeAttribute("collapsed");
  647. */
  648.   }
  649. }
  650.  
  651. function HideMessageHeaderPane()
  652. {
  653.   msgPaneData.ViewAllHeadersToolbar.setAttribute("collapsed", "true");
  654.   msgPaneData.ViewAllHeadersBox.setAttribute("collapsed", "true");
  655.  
  656.   var node = document.getElementById("headerPart1");
  657.   if (node)
  658.     node.setAttribute("collapsed", "true");
  659.   node = document.getElementById("headerPart2");
  660.   if (node)
  661.     node.setAttribute("collapsed", "true");
  662.   node = document.getElementById("headerPart3");
  663.   if (msgPaneData.UserAgentToolbar)
  664.     msgPaneData.UserAgentToolbar.setAttribute("collapsed", "true");
  665.  
  666. }
  667.  
  668. // ToggleLongShortAddresses is used to toggle between showing
  669. // all of the addresses on a given header line vs. only the first 'n'
  670. // where 'n' is a user controlled preference. By toggling on the more/less
  671. // images in the header window, we'll hide / show the appropriate div for that header.
  672.  
  673. function ToggleLongShortAddresses(shortDivID, longDivID)
  674. {
  675.   var shortNode = document.getElementById(shortDivID);
  676.   var longNode = document.getElementById(longDivID);
  677.   var nodeToReset;
  678.  
  679.   // test to see which if short is already hidden...
  680.   if (shortNode.getAttribute("collapsed") == "true")
  681.   {
  682.      
  683.      hdrViewSetVisible(longNode, false);
  684.      hdrViewSetVisible(shortNode, true);
  685.      nodeToReset = shortNode;
  686.   }
  687.   else
  688.   {
  689.      hdrViewSetVisible(shortNode, false);
  690.      hdrViewSetVisible(longNode, true);
  691.      nodeToReset = longNode;
  692.   }
  693.    
  694.    // HACK ALERT: this is required because of a bug in boxes when you add content
  695.    // to a box which is collapsed, when you then uncollapse that box, the content isn't 
  696.    // displayed. So I'm forcing us to reset the value for each node...
  697.    var endPos = nodeToReset.childNodes.length;
  698.    var index = 0;
  699.    var tempValue;
  700.    while (index < endPos - 1)
  701.    {
  702.      tempValue = nodeToReset.childNodes[index].getAttribute("value");
  703.      nodeToReset.childNodes[index].setAttribute("value", "");
  704.      nodeToReset.childNodes[index].setAttribute("value", tempValue);
  705.      index++;
  706.    }
  707. }
  708.  
  709. // given a box, iterate through all of the headers and add them to 
  710. // the enclosing box. 
  711. function fillBoxWithAllHeaders(containerBox, boxPartOfPopup)
  712. {
  713.   // clear out the old popup date if there is any...
  714.   while ( containerBox.childNodes.length ) 
  715.     containerBox.removeChild(containerBox.childNodes[0]); 
  716.  
  717.   for (header in currentHeaderData)
  718.   {
  719.     var innerBox = document.createElement('box');
  720.     innerBox.setAttribute("class", "headerBox");
  721.     innerBox.setAttribute("orient", "horizontal");
  722.     if (boxPartOfPopup)
  723.         innerBox.setAttribute("autostretch", "never");
  724.  
  725.     // for each header, create a header value and header name then assign those values...
  726.     var headerValueBox = document.createElement('hbox');
  727.     headerValueBox.setAttribute("class", "headerValueBox");
  728.  
  729.       var newHeaderTitle  = document.createElement('text');
  730.     newHeaderTitle.setAttribute("class", "headerdisplayname");
  731.       newHeaderTitle.setAttribute("value", currentHeaderData[header].headerName + ':');
  732.     headerValueBox.appendChild(newHeaderTitle);
  733.  
  734.       innerBox.appendChild(headerValueBox);
  735.  
  736.     var newHeaderValue = document.createElement('html');
  737.     // make sure we are properly resized...
  738. //    if (boxPartOfPopup)
  739. //        newHeaderValue.setAttribute("width", window.innerWidth*.65);
  740.     newHeaderValue.setAttribute("class", "headerValue");
  741.     if (!boxPartOfPopup)
  742.       newHeaderValue.setAttribute("flex", "1");
  743.     innerBox.appendChild(newHeaderValue);
  744.     containerBox.appendChild(innerBox);
  745.     ProcessHeaderValue(innerBox, newHeaderValue, currentHeaderData[header], boxPartOfPopup);
  746.   }
  747. }
  748.  
  749. // the on create handler for the view all headers popup...
  750. function fillAllHeadersPopup(node)
  751. {
  752.   // don't bother re-filling the popup if we've already done it for the
  753.   // currently displayed message....
  754.   if (gGeneratedViewAllHeaderInfo == true)
  755.     return true; 
  756.  
  757.   var containerBox = document.getElementById('allHeadersPopupContainer');
  758.  
  759.   containerBox.setAttribute("class", "header-part1");
  760.   containerBox.setAttribute("align", "vertical");
  761.   containerBox.setAttribute("flex", "1");
  762.  
  763.   fillBoxWithAllHeaders(containerBox, true);
  764.   gGeneratedViewAllHeaderInfo = true; // don't try to regenerate this information for the currently displayed message
  765.   return true;
  766. }
  767.  
  768. // containingBox --> the box containing the header
  769. // containerNode --> the div or box that we want to insert this specific header into
  770. // header --> an entry from currentHeaderData contains .headerName and .headerValue
  771. // boxPartOfPopup --> true if the box is part of a popup (certain functions are disabled in this scenario)
  772. function ProcessHeaderValue(containingBox, containerNode, header, boxPartOfPopup)
  773. {
  774.     // in the simplest case, we'll just create a text node for the header
  775.     // and append it to the container Node. for certain headers, we might want to do 
  776.     // extra processing....
  777.     
  778.     var headerName = header.headerName;
  779.     headerName = headerName.toLowerCase();
  780.     if (!boxPartOfPopup && (headerName == "cc" || headerName == "from" || headerName == "to"))
  781.     {
  782.       OutputEmailAddresses(containingBox, containerNode, header.headerValue, false, "", "", headerName)
  783.       return;
  784.     }
  785.     
  786.     var headerValue = header.headerValue;
  787.     headerValue = headerValue.replace(/\n|\r/g,"");
  788.     var textNode = document.createTextNode(headerValue);
  789.     if (headerName == "subject")
  790.     {
  791.         containerNode.setAttribute("class", "subjectvalue headerValue");
  792.     }
  793.  
  794.     containerNode.appendChild(textNode);
  795. }
  796.  
  797. ///////////////////////////////////////////////////////////////
  798. // The following are just small helper functions..
  799. ///////////////////////////////////////////////////////////////
  800.  
  801. function hdrViewSetNodeWithButton(boxNode, buttonNode, text)
  802. {
  803.   if (text)
  804.   {
  805.     buttonNode.setAttribute("value", text);
  806.     hdrViewSetVisible(boxNode, true);
  807.   }
  808.     else
  809.     {
  810.         hdrViewSetVisible(boxNode, false);
  811.         return false;
  812.     }
  813.  
  814. function hdrViewSetNodeWithBox(boxNode, textNode, text)
  815. {
  816.     if ( text )
  817.         return hdrViewSetNode(boxNode, textNode, text );
  818.     else
  819.     {
  820.         hdrViewSetVisible(boxNode, false);
  821.         return false;
  822.     }
  823. }
  824.  
  825. function hdrViewSetNode(boxNode, textNode, text)
  826. {
  827.     textNode.childNodes[0].nodeValue = text;
  828.     var visible;
  829.     
  830.     if ( text )
  831.         visible = true;
  832.     else
  833.         visible = false;
  834.     
  835.     hdrViewSetVisible(boxNode, visible);
  836.     return visible;
  837. }
  838.  
  839. function hdrViewSetVisible(boxNode, visible)
  840. {
  841.     if ( visible )
  842.         boxNode.removeAttribute("collapsed");
  843.     else
  844.         boxNode.setAttribute("collapsed", "true");
  845. }
  846.  
  847.