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

  1. /*
  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.org code.
  13.  *
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation.  Portions created by Netscape are
  16.  * Copyright (C) 1998 Netscape Communications Corporation. All
  17.  * Rights Reserved.
  18.  *
  19.  * Contributor(s): 
  20.  */
  21.  
  22. top.MAX_RECIPIENTS = 0;
  23.  
  24. var inputElementType = "";
  25. var selectElementType = "";
  26. var selectElementIndexTable = null;
  27.  
  28. var test_addresses_sequence = false;
  29. if (prefs)
  30.     try {
  31.         test_addresses_sequence = prefs.GetBoolPref("mail.debug.test_addresses_sequence");
  32.     }
  33.     catch (ex) {}
  34.  
  35. function awInputElementName()
  36. {
  37.     if (inputElementType == "")
  38.         inputElementType = document.getElementById("msgRecipient#1").localName;
  39.     return inputElementType;
  40. }
  41.  
  42. function awSelectElementName()
  43. {
  44.     if (selectElementType == "")
  45.         selectElementType = document.getElementById("msgRecipientType#1").localName;
  46.     return selectElementType;
  47. }
  48.  
  49. function awGetSelectItemIndex(itemData)
  50. {
  51.     if (selectElementIndexTable == null)
  52.     {
  53.         selectElementIndexTable = new Object();
  54.         var selectElem = document.getElementById("msgRecipientType#1");
  55.         for (var i = 0; i < selectElem.childNodes[0].childNodes.length; i ++)
  56.     {
  57.             var aData = selectElem.childNodes[0].childNodes[i].getAttribute("data");
  58.             selectElementIndexTable[aData] = i;
  59.         }
  60.     }
  61.     return selectElementIndexTable[itemData];
  62. }
  63.  
  64. function Recipients2CompFields(msgCompFields)
  65. {
  66.     if (msgCompFields)
  67.     {
  68.         var i = 1;
  69.         var addrTo = "";
  70.         var addrCc = "";
  71.         var addrBcc = "";
  72.         var addrReply = "";
  73.         var addrNg = "";
  74.         var addrFollow = "";
  75.         var addrOther = "";
  76.         var to_Sep = "";
  77.         var cc_Sep = "";
  78.         var bcc_Sep = "";
  79.         var reply_Sep = "";
  80.         var ng_Sep = "";
  81.         var follow_Sep = "";
  82.  
  83.     var inputField;
  84.         while ((inputField = awGetInputElement(i)))
  85.         {
  86.             var fieldValue = inputField.value;
  87.             if (fieldValue == null)
  88.               fieldValue = inputField.getAttribute("value");
  89.  
  90.             if (fieldValue != "")
  91.             {
  92.                 switch (awGetPopupElement(i).selectedItem.getAttribute("data"))
  93.                 {
  94.                     case "addr_to"            : addrTo += to_Sep + fieldValue; to_Sep = ",";                    break;
  95.                     case "addr_cc"            : addrCc += cc_Sep + fieldValue; cc_Sep = ",";                    break;
  96.                     case "addr_bcc"            : addrBcc += bcc_Sep + fieldValue; bcc_Sep = ",";                break;
  97.                     case "addr_reply"        : addrReply += reply_Sep + fieldValue; reply_Sep = ",";            break;
  98.                     case "addr_newsgroups"    : addrNg += ng_Sep + fieldValue; ng_Sep = ",";                    break;
  99.                     case "addr_followup"    : addrFollow += follow_Sep + fieldValue; follow_Sep = ",";        break;
  100.                     case "addr_other"        : addrOther += other_header + ": " + fieldValue + "\n";         break;
  101.                 }
  102.             }
  103.             i ++;
  104.         }
  105.         msgCompFields.SetTo(addrTo);
  106.         msgCompFields.SetCc(addrCc);
  107.         msgCompFields.SetBcc(addrBcc);
  108.         msgCompFields.SetReplyTo(addrReply);
  109.         msgCompFields.SetNewsgroups(addrNg);
  110.         msgCompFields.SetFollowupTo(addrFollow);
  111.         msgCompFields.SetOtherRandomHeaders(addrOther);
  112.     }
  113.     else
  114.         dump("Message Compose Error: msgCompFields is null (ExtractRecipients)");
  115. }
  116.  
  117. function CompFields2Recipients(msgCompFields, msgType)
  118. {
  119.     if (msgCompFields)
  120.     {
  121.         var treeChildren = document.getElementById('addressWidgetBody');
  122.         var newTreeChildrenNode = treeChildren.cloneNode(false);
  123.         var templateNode = treeChildren.firstChild;
  124.         
  125.         top.MAX_RECIPIENTS = 0;
  126.  
  127.         awSetInputAndPopupFromArray(msgCompFields.SplitRecipients(msgCompFields.GetReplyTo(), false), "addr_reply", newTreeChildrenNode, templateNode);
  128.         awSetInputAndPopupFromArray(msgCompFields.SplitRecipients(msgCompFields.GetTo(), false), "addr_to", newTreeChildrenNode, templateNode);
  129.         awSetInputAndPopupFromArray(msgCompFields.SplitRecipients(msgCompFields.GetCc(), false), "addr_cc", newTreeChildrenNode, templateNode);
  130.         awSetInputAndPopupFromArray(msgCompFields.SplitRecipients(msgCompFields.GetBcc(), false), "addr_bcc", newTreeChildrenNode, templateNode);
  131.         awSetInputAndPopup(msgCompFields.GetOtherRandomHeaders(), "addr_other", newTreeChildrenNode, templateNode);
  132.         awSetInputAndPopup(msgCompFields.GetNewsgroups(), "addr_newsgroups", newTreeChildrenNode, templateNode);
  133.         awSetInputAndPopup(msgCompFields.GetFollowupTo(), "addr_followup", newTreeChildrenNode, templateNode);
  134.         
  135.         //If it's a new message, we need to add an extrat empty recipient.
  136.         var msgComposeType = Components.interfaces.nsIMsgCompType;
  137.         if (msgType == msgComposeType.New || top.MAX_RECIPIENTS == 0)
  138.             _awSetInputAndPopup("", "addr_to", newTreeChildrenNode, templateNode);
  139.         dump("replacing child in comp fields 2 recips \n");
  140.         var parent = treeChildren.parentNode;
  141.         parent.replaceChild(newTreeChildrenNode, treeChildren);
  142.         setTimeout("awFinishCopyNodes();", 0);
  143.     }
  144. }
  145.  
  146. function awSetInputAndPopupValue(inputElem, inputValue, popupElem, popupValue, rowNumber)
  147. {
  148.     // remove leading spaces
  149.     while (inputValue[0] == " " )
  150.         inputValue = inputValue.substring(1, inputValue.length);
  151.     
  152.   inputElem.setAttribute("value", inputValue);
  153.   inputElem.value = inputValue;
  154.  
  155.   popupElem.selectedItem = popupElem.childNodes[0].childNodes[awGetSelectItemIndex(popupValue)];
  156.   
  157.   if (rowNumber >= 0)
  158.   {
  159.     inputElem.setAttribute("id", "msgRecipient#" + rowNumber);
  160.       popupElem.setAttribute("id", "msgRecipientType#" + rowNumber);
  161.     }
  162.   
  163.   _awSetAutoComplete(popupElem, inputElem);
  164. }
  165.  
  166. function _awSetInputAndPopup(inputValue, popupValue, parentNode, templateNode)
  167. {
  168.     top.MAX_RECIPIENTS++;
  169.  
  170.     var newNode = templateNode.cloneNode(true);
  171.     parentNode.appendChild(newNode); // we need to insert the new node before we set the value of the select element!
  172.  
  173.     var input = newNode.getElementsByTagName(awInputElementName());
  174.     var select = newNode.getElementsByTagName(awSelectElementName());
  175.  
  176.     if (input && input.length == 1 && select && select.length == 1)
  177.       awSetInputAndPopupValue(input[0], inputValue, select[0], popupValue, top.MAX_RECIPIENTS)
  178. }
  179.  
  180. function awSetInputAndPopup(inputValue, popupValue, parentNode, templateNode)
  181. {
  182.     if ( inputValue && popupValue )
  183.     {
  184.         var addressArray = inputValue.split(",");
  185.         
  186.         for ( var index = 0; index < addressArray.length; index++ )
  187.             _awSetInputAndPopup(addressArray[index], popupValue, parentNode, templateNode);
  188.     }
  189. }
  190.  
  191. function awSetInputAndPopupFromArray(inputArray, popupValue, parentNode, templateNode)
  192. {
  193.     if ( inputArray && popupValue )
  194.     {
  195.         for ( var index = 0; index < inputArray.count; index++ )
  196.             _awSetInputAndPopup(inputArray.StringAt(index), popupValue, parentNode, templateNode);
  197.     }
  198. }
  199.  
  200. function awRemoveRecipients(msgCompFields, recipientType, recipientsList)
  201. {
  202.   if (!msgCompFields)
  203.     return;
  204.  
  205.   var recipientArray = msgCompFields.SplitRecipients(recipientsList, false);
  206.   if (! recipientArray)
  207.     return;
  208.   
  209.   for ( var index = 0; index < recipientArray.count; index++ )
  210.     for (var row = 1; row <= top.MAX_RECIPIENTS; row ++)
  211.     {
  212.       var popup = awGetPopupElement(row);
  213.       if (popup.selectedItem.getAttribute("data") == recipientType)
  214.       {
  215.         var input = awGetInputElement(row);
  216.         if (input.value == recipientArray.StringAt(index))
  217.         {
  218.           awSetInputAndPopupValue(input, "", popup, "addr_to", -1);
  219.           break;
  220.         }
  221.       }
  222.     } 
  223. }
  224.  
  225. function awAddRecipients(msgCompFields, recipientType, recipientsList)
  226. {
  227.   if (!msgCompFields)
  228.     return;
  229.  
  230.   var recipientArray = msgCompFields.SplitRecipients(recipientsList, false);
  231.   if (! recipientArray)
  232.     return;
  233.   
  234.   for ( var index = 0; index < recipientArray.count; index++ )
  235.   {
  236.     for (var row = 1; row <= top.MAX_RECIPIENTS; row ++)
  237.     {
  238.       if (awGetInputElement(row).value == "")
  239.         break;
  240.     }
  241.     if (row > top.MAX_RECIPIENTS)
  242.       awAppendNewRow(false);
  243.   
  244.     awSetInputAndPopupValue(awGetInputElement(row), recipientArray.StringAt(index), awGetPopupElement(row), recipientType, row);
  245.  
  246.     /* be sure we still have an empty row left at the end */
  247.     if (row == top.MAX_RECIPIENTS)
  248.     {
  249.       awAppendNewRow(true);
  250.       awSetInputAndPopupValue(awGetInputElement(top.MAX_RECIPIENTS), "", awGetPopupElement(top.MAX_RECIPIENTS), "addr_to", top.MAX_RECIPIENTS);
  251.     }
  252.   }
  253. }
  254.  
  255. function awTestRowSequence()
  256. {
  257.   /*
  258.     This function is for debug and testing purpose only, normal user should not run it!
  259.     
  260.     Everytime we insert or delete a row, we must be sure we didn't break the ID sequence of
  261.     the addressing widget rows. This function will run a quick test to see if the sequence still ok
  262.     
  263.     You need to define the pref mail.debug.test_addresses_sequence to true in order to activate it
  264.   */
  265.   
  266.     if (! test_addresses_sequence)
  267.       return true;
  268.  
  269.   /* debug code to verify the sequence still good */
  270.     var body = document.getElementById('addressWidgetBody');
  271.     var treeitems = body.getElementsByTagName('treeitem');
  272.     if (treeitems.length == top.MAX_RECIPIENTS )
  273.     {
  274.       for (var i = 1; i <= treeitems.length; i ++)
  275.       {
  276.             var item = treeitems[i - 1];
  277.       var inputID = item.getElementsByTagName(awInputElementName())[0].getAttribute("id").split("#")[1];
  278.       var popupID = item.getElementsByTagName(awSelectElementName())[0].getAttribute("id").split("#")[1];
  279.       if (inputID != i || popupID != i)
  280.       {
  281.           dump("#ERROR: sequence broken at row " + i + ", inputID=" + inputID + ", popupID=" + popupID + "\n");
  282.           break;
  283.         }
  284.         }
  285.     dump("---SEQUENCE OK---\n");
  286.     return true;        
  287.     }
  288.     else
  289.       dump("#ERROR: treeitems.length(" + treeitems.length + ") != top.MAX_RECIPIENTS(" + top.MAX_RECIPIENTS + ")\n");
  290.  
  291.     return false;
  292. }
  293.  
  294. function awCleanupRows()
  295. {
  296.   var maxRecipients = top.MAX_RECIPIENTS;
  297.   var rowID = 1;
  298.  
  299.   for (var row = 1; row <= maxRecipients; row ++)
  300.   {
  301.     var inputElem = awGetInputElement(row);
  302.     if (inputElem.value == "" && row < maxRecipients)
  303.       awRemoveRow(row);
  304.     else
  305.     {
  306.       inputElem.setAttribute("id", "msgRecipient#" + rowID);
  307.         awGetPopupElement(row).setAttribute("id", "msgRecipientType#" + rowID);
  308.       rowID ++;
  309.     }
  310.   }
  311.   
  312.   awTestRowSequence();
  313. }
  314.  
  315. function awDeleteRow(rowToDelete)
  316. {
  317.   /* When we delete a row, we must reset the id of others row in order to not break the sequence */
  318.   var maxRecipients = top.MAX_RECIPIENTS;
  319.   var rowID = rowToDelete;
  320.   
  321.   awRemoveRow(rowToDelete);
  322.  
  323.   for (var row = rowToDelete + 1; row <= maxRecipients; row ++)
  324.   {
  325.     awGetInputElement(row).setAttribute("id", "msgRecipient#" + rowID);
  326.       awGetPopupElement(row).setAttribute("id", "msgRecipientType#" + rowID);
  327.       rowID ++;
  328.   }
  329.  
  330.   awTestRowSequence();
  331. }
  332.  
  333. function awClickEmptySpace(targ, setFocus)
  334. {
  335.   if (targ.localName != 'treechildren')
  336.     return;
  337.  
  338.     dump("awClickEmptySpace\n");
  339.     var lastInput = awGetInputElement(top.MAX_RECIPIENTS);
  340.  
  341.     if ( lastInput && lastInput.value )
  342.         awAppendNewRow(setFocus);
  343.     else
  344.         if (setFocus)
  345.             awSetFocus(top.MAX_RECIPIENTS, lastInput);
  346. }
  347.  
  348. function awReturnHit(inputElement)
  349. {
  350.     var row = awGetRowByInputElement(inputElement);
  351.     
  352.     if ( inputElement.value )
  353.     {
  354.         var nextInput = awGetInputElement(row+1);
  355.         if ( !nextInput )
  356.             awAppendNewRow(true);
  357.         else
  358.             awSetFocus(row+1, nextInput);
  359.     }
  360. }
  361.  
  362. function awDeleteHit(inputElement)
  363. {
  364.   var row = awGetRowByInputElement(inputElement);
  365.   
  366.   /* 1. don't delete the row if it's the last one remaining, just reset it! */
  367.   if (top.MAX_RECIPIENTS <= 1)
  368.   {
  369.     inputElement.value = "";
  370.     return;
  371.   }
  372.  
  373.   /* 2. Set the focus to the previous field if possible */
  374.   if (row > 1)
  375.     awSetFocus(row - 1, awGetInputElement(row - 1))
  376.   else
  377.     awSetFocus(1, awGetInputElement(2))   /* We have to cheat a little bit because the focus will */
  378.                                           /* be set asynchronusly after we delete the current row, */
  379.                                           /* therefore the row number still the same! */
  380.                                                 
  381.   /* 3. Delete the row */
  382.   awDeleteRow(row);
  383. }
  384.  
  385. function awInputChanged(inputElement)
  386. {
  387.     dump("awInputChanged\n");
  388. //    AutoCompleteAddress(inputElement);
  389.  
  390.     //Do we need to add a new row?
  391.     var lastInput = awGetInputElement(top.MAX_RECIPIENTS);
  392.     if ( lastInput && lastInput.value && !top.doNotCreateANewRow)
  393.         awAppendNewRow(false);
  394.     top.doNotCreateANewRow = false;
  395. }
  396.  
  397. function awAppendNewRow(setFocus)
  398. {
  399.     var body = document.getElementById('addressWidgetBody');
  400.     var treeitem1 = awGetTreeItem(1);
  401.     
  402.     if ( body && treeitem1 )
  403.     {
  404.         var lastRecipientType = awGetPopupElement(top.MAX_RECIPIENTS).selectedItem.getAttribute("data");
  405.  
  406.         var newNode = awCopyNode(treeitem1, body, 0);
  407.         top.MAX_RECIPIENTS++;
  408.  
  409.         var input = newNode.getElementsByTagName(awInputElementName());
  410.         if ( input && input.length == 1 )
  411.         {
  412.                  input[0].setAttribute("value", "");
  413.             input[0].setAttribute("id", "msgRecipient#" + top.MAX_RECIPIENTS);
  414.  
  415.           // We always clone the first row.  The problem is that the first row
  416.           // could be focused.  When we clone that row, we end up with a cloned
  417.           // XUL textfield that has a focused attribute set.  Therefore we think
  418.           // we're focused and don't properly refocus.  The best solution to this
  419.           // would be to clone a template row that didn't really have any presentation,
  420.           // rather than using the real visible first row of the tree.
  421.           //
  422.           // For now we'll just put in a hack that ensures the focused attribute
  423.           // is never copied when the node is cloned.
  424.           if (input[0].getAttribute('focused') != '')
  425.             input[0].removeAttribute('focused');
  426.           }
  427.         var select = newNode.getElementsByTagName(awSelectElementName());
  428.         if ( select && select.length == 1 )
  429.         {
  430.             select[0].selectedItem = select[0].childNodes[0].childNodes[awGetSelectItemIndex(lastRecipientType)];
  431.             select[0].setAttribute("id", "msgRecipientType#" + top.MAX_RECIPIENTS);
  432.             if (input)
  433.             _awSetAutoComplete(select[0], input[0]);
  434.         }
  435.  
  436.         // focus on new input widget
  437.         if (setFocus && input[0] )
  438.             awSetFocus(top.MAX_RECIPIENTS, input[0]);
  439.     }
  440. }
  441.  
  442.  
  443. // functions for accessing the elements in the addressing widget
  444.  
  445. function awGetPopupElement(row)
  446. {
  447.     return document.getElementById("msgRecipientType#" + row);
  448. }
  449.  
  450. function awGetInputElement(row)
  451. {
  452.     return document.getElementById("msgRecipient#" + row);
  453. }
  454.  
  455. function awGetTreeRow(row)
  456. {
  457.     var body = document.getElementById('addressWidgetBody');
  458.     
  459.     if ( body && row > 0)
  460.     {
  461.         var treerows = body.getElementsByTagName('treerow');
  462.         if ( treerows && treerows.length >= row )
  463.             return treerows[row-1];
  464.     }
  465.     return 0;
  466. }
  467.  
  468. function awGetTreeItem(row)
  469. {
  470.     var body = document.getElementById('addressWidgetBody');
  471.     
  472.     if ( body && row > 0)
  473.     {
  474.         var treeitems = body.getElementsByTagName('treeitem');
  475.         if ( treeitems && treeitems.length >= row )
  476.             return treeitems[row-1];
  477.     }
  478.     return 0;
  479. }
  480.  
  481. function awGetRowByInputElement(inputElement)
  482. {
  483.     if ( inputElement )
  484.     {
  485.         var treerow;
  486.         var inputElementTreerow = inputElement.parentNode.parentNode;
  487.         
  488.         if ( inputElementTreerow )
  489.         {
  490.             for ( var row = 1;  (treerow = awGetTreeRow(row)); row++ )
  491.             {
  492.                 if ( treerow == inputElementTreerow )
  493.                     return row;
  494.             }
  495.         }
  496.     }
  497.     return 0;
  498. }
  499.  
  500.  
  501. // Copy Node - copy this node and insert ahead of the (before) node.  Append to end if before=0
  502. function awCopyNode(node, parentNode, beforeNode)
  503. {
  504.     var newNode = node.cloneNode(true);
  505.     
  506.     if ( beforeNode )
  507.         parentNode.insertBefore(newNode, beforeNode);
  508.     else
  509.         parentNode.appendChild(newNode);
  510.  
  511.     return newNode;
  512. }
  513.  
  514. // remove row
  515.  
  516. function awRemoveRow(row)
  517. {
  518.     var body = document.getElementById('addressWidgetBody');
  519.     
  520.     awRemoveNodeAndChildren(body, awGetTreeItem(row));
  521.  
  522.     top.MAX_RECIPIENTS --;
  523. }
  524.  
  525. function awRemoveNodeAndChildren(parent, nodeToRemove)
  526. {
  527.     // children of nodes
  528.     var childNode;
  529.     
  530.     while ( nodeToRemove.childNodes && nodeToRemove.childNodes.length )
  531.     {
  532.         childNode = nodeToRemove.childNodes[0];
  533.     
  534.         awRemoveNodeAndChildren(nodeToRemove, childNode);
  535.     }
  536.     
  537.     parent.removeChild(nodeToRemove);
  538.  
  539. }
  540.  
  541. function awSetFocus(row, inputElement)
  542. {
  543.     top.awRow = row;
  544.     top.awInputElement = inputElement;
  545.     top.awFocusRetry = 0;
  546.     setTimeout("_awSetFocus();", 0);
  547. }
  548.  
  549. function _awSetFocus()
  550. {
  551.     var tree = document.getElementById('addressingWidgetTree');
  552.     try
  553.     {
  554.         var theNewRow = awGetTreeRow(top.awRow);
  555.         //temporary patch for bug 26344
  556.         awFinishCopyNode(theNewRow);
  557.  
  558.     //Warning: firstVisibleRow is zero base but top.awRow is one base!
  559.     var firstVisibleRow = tree.getIndexOfFirstVisibleRow();
  560.     var numOfVisibleRows = tree.getNumberOfVisibleRows();
  561.   
  562.     //Do we need to scroll in order to see the selected row?
  563.     if (top.awRow <= firstVisibleRow)
  564.       tree.scrollToIndex(top.awRow - 1);
  565.     else
  566.       if (top.awRow - 1 >= (firstVisibleRow + numOfVisibleRows))
  567.         tree.scrollToIndex(top.awRow - numOfVisibleRows);
  568.  
  569.         top.awInputElement.focus();
  570.     }
  571.     catch(ex)
  572.     {
  573.         top.awFocusRetry ++;
  574.         if (top.awFocusRetry < 3)
  575.         {
  576.             dump("_awSetFocus failed, try it again...\n");
  577.             setTimeout("_awSetFocus();", 0);
  578.         }
  579.         else
  580.             dump("_awSetFocus failed, forget about it!\n");
  581.     }
  582. }
  583.  
  584.  
  585. //temporary patch for bug 26344 & 26528
  586. function awFinishCopyNode(node)
  587. {
  588.     msgCompose.ResetNodeEventHandlers(node);
  589.     return;
  590. }
  591.  
  592.  
  593. function awFinishCopyNodes()
  594. {
  595.   var treeChildren = document.getElementById('addressWidgetBody');
  596.   awFinishCopyNode(treeChildren);
  597. }
  598.  
  599. function awTabFromRecipient(element, event)
  600. {
  601.     //If we are le last element in the tree, we don't want to create a new row.
  602.     if (element == awGetInputElement(top.MAX_RECIPIENTS))
  603.         top.doNotCreateANewRow = true;
  604. }
  605.  
  606. function awGetNumberOfRecipients()
  607. {
  608.     return top.MAX_RECIPIENTS;
  609. }
  610.  
  611. function DragOverTree(event)
  612. {
  613.     var validFlavor = false;
  614.     var dragSession = null;
  615.     var retVal = true;
  616.  
  617.     var dragService = Components.classes["@mozilla.org/widget/dragservice;1"].getService();
  618.     if (dragService) 
  619.         dragService = dragService.QueryInterface(Components.interfaces.nsIDragService);
  620.     if (!dragService)    return(false);
  621.  
  622.     dragSession = dragService.getCurrentSession();
  623.     if (!dragSession)    return(false);
  624.  
  625.     if (dragSession.isDataFlavorSupported("text/nsabcard"))    validFlavor = true;
  626.     //XXX other flavors here...
  627.  
  628.     // touch the attribute on the rowgroup to trigger the repaint with the drop feedback.
  629.     if (validFlavor)
  630.     {
  631.         //XXX this is really slow and likes to refresh N times per second.
  632.         var rowGroup = event.target.parentNode.parentNode;
  633.         rowGroup.setAttribute ( "dd-triggerrepaint", 0 );
  634.         dragSession.canDrop = true;
  635.         // necessary??
  636.         retVal = false; // do not propagate message
  637.     }
  638.     return(retVal);
  639. }
  640.  
  641. function DropOnAddressingWidgetTree(event)
  642. {
  643.     dump("DropOnTree\n");
  644.     var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService();
  645.     if (rdf)   
  646.         rdf = rdf.QueryInterface(Components.interfaces.nsIRDFService);
  647.     if (!rdf) return(false);
  648.  
  649.     var dragService = Components.classes["@mozilla.org/widget/dragservice;1"].getService();
  650.     if (dragService) 
  651.         dragService = dragService.QueryInterface(Components.interfaces.nsIDragService);
  652.     if (!dragService)    return(false);
  653.     
  654.     var dragSession = dragService.getCurrentSession();
  655.     if ( !dragSession )    return(false);
  656.  
  657.     var trans = Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable);
  658.     if ( !trans ) return(false);
  659.     trans.addDataFlavor("text/nsabcard");
  660.  
  661.     for ( var i = 0; i < dragSession.numDropItems; ++i )
  662.     {
  663.         dragSession.getData ( trans, i );
  664.         dataObj = new Object();
  665.         bestFlavor = new Object();
  666.         len = new Object();
  667.         trans.getAnyTransferData ( bestFlavor, dataObj, len );
  668.         if ( dataObj )    dataObj = dataObj.value.QueryInterface(Components.interfaces.nsISupportsWString);
  669.         if ( !dataObj )    continue;
  670.  
  671.         // pull the URL out of the data object
  672.         var sourceID = dataObj.data.substring(0, len.value);
  673.         if (!sourceID)    continue;
  674.  
  675.         var cardResource = rdf.GetResource(sourceID);
  676.         var card = cardResource.QueryInterface(Components.interfaces.nsIAbCard);
  677.         var address = "\"" + card.name + "\" <" + card.primaryEmail + ">";
  678.         dump("    Address #" + i + " = " + address + "\n");
  679.  
  680.         DropRecipient(address); 
  681.         
  682.     }
  683.  
  684.     return(false);
  685. }
  686.  
  687. function DropRecipient(recipient) 
  688.     awClickEmptySpace(true);    //that will automatically set the focus on a new available row, and make sure is visible 
  689.     var lastInput = awGetInputElement(top.MAX_RECIPIENTS); 
  690.     lastInput.value = recipient; 
  691.     awAppendNewRow(true); 
  692. }
  693.  
  694. function _awSetAutoComplete(selectElem, inputElem)
  695. {
  696.     if (selectElem.data != 'addr_newsgroups' && selectElem.data != 'addr_followup')
  697.         inputElem.disableAutocomplete = false;
  698.     else
  699.     inputElem.disableAutocomplete = true;
  700. }
  701.  
  702. function awSetAutoComplete(rowNumber)
  703. {
  704.     var inputElem = awGetInputElement(rowNumber);
  705.     var selectElem = awGetPopupElement(rowNumber);
  706.     _awSetAutoComplete(selectElem, inputElem)
  707. }
  708.  
  709. function awRecipientKeyPress(event, element)
  710. {
  711.   switch(event.keyCode) {
  712.   case 13:
  713.     awReturnHit(element);
  714.     break;
  715.   case 9:
  716.     awTabFromRecipient(element, event);
  717.     break;
  718.   }
  719. }
  720.  
  721. function awRecipientKeyDown(event, element)
  722. {
  723.   switch(event.keyCode) {
  724.   case 46:
  725.   case 8:
  726.     if (!element.value)
  727.       awDeleteHit(element);
  728.     event.preventBubble();  //We need to stop the event else the tree will receive it and the function
  729.                             //awKeyDown will be executed!
  730.     break;
  731.   }
  732. }
  733.  
  734. function awKeyDown(event, treeElement)
  735. {
  736.   switch(event.keyCode) {
  737.   case 46:
  738.   case 8:
  739.     /* Warning, the treeElement.selectedItems will change everytime we delete a row */
  740.     var selItems = treeElement.selectedItems;
  741.     var length = treeElement.selectedItems.length;
  742.     for (var i = 1; i <= length; i++) {
  743.       var inputs = treeElement.selectedItems[0].getElementsByTagName(awInputElementName());
  744.       if (inputs && inputs.length == 1)
  745.         awDeleteHit(inputs[0]);
  746.     }
  747.     break;   
  748.   }
  749. }
  750.