home *** CD-ROM | disk | FTP | other *** search
/ ftp.tcs3.com / ftp.tcs3.com.tar / ftp.tcs3.com / DRIVERS / Audio / Office2010 / Office.en-us / OfficeLR.cab / EADOCUMENTAPPROVAL_REVIEW.XSN_1033 / script.js < prev    next >
Text File  |  2009-07-06  |  20KB  |  613 lines

  1. /*
  2.  * This file contains functions for data validation and form-level events.
  3.  * Because the functions are referenced in the form definition (.xsf) file, 
  4.  * it is recommended that you do not modify the name of the function,
  5.  * or the name and number of arguments.
  6.  *
  7. */
  8.  
  9. // The following line is created by Microsoft InfoPath to define the prefixes
  10. // for all the known namespaces in the main XML data file.
  11. // Any modification to the form files made outside of Microsoft InfoPath
  12. // will not be automatically updated.
  13. //<namespacesDefinition>
  14. XDocument.DOM.setProperty("SelectionNamespaces", ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:o12="http://schemas.microsoft.com/office/2004/7/core" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w12="http://schemas.microsoft.com/office/word/2004/6/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:sl="http://schemas.microsoft.com/schemaLibrary/2003/core" xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD" xmlns:xd="http://schemas.microsoft.com/office/infopath/2003"');
  15. //</namespacesDefinition>
  16.  
  17. var hostApplication;
  18.  
  19. //=======
  20. // The following function handler is created by Microsoft InfoPath.
  21. // Do not modify the name of the function, or the name and number of arguments.
  22. //=======
  23. function CTRL78_5::OnClick(eventObj)
  24. {
  25.     // On Approve button clicked
  26.  
  27.     // Validate signatures
  28.     if (IsInvalidated())
  29.     {
  30.         var fIsInvalidated = XDocument.DOM.selectSingleNode("/my:myFields/my:IsInvalidated");
  31.         fIsInvalidated.text = "true";
  32.     }
  33.  
  34.     // Validate participants
  35.     // Arbitrary approval does not need to validate the next approver
  36.     // NOTE: nodeIsArbitrary.text can be empty string by calculation logic in manifest.xsf.
  37.     //           It is because we also have to inspect ows_IsArbitrary node in ItemMetadata for claimed/released task.
  38.     var nodeIsArbitrary = XDocument.DOM.selectSingleNode("/my:myFields/my:IsArbitrary");
  39.     if (nodeIsArbitrary.text == "false" || nodeIsArbitrary.text == "")
  40.     {
  41.         if (!ValidateNextParticipant())
  42.             return;
  43.     }
  44.  
  45.     var TaskStatus = XDocument.DOM.selectSingleNode("/my:myFields/my:TaskStatus");
  46.     TaskStatus.text = "#";
  47.  
  48.     // Get the current approver's signature image URL
  49.     // CTasks.Init() will properly initialize this value when delegated approval
  50.     var strImageUrl = XDocument.DOM.selectSingleNode("/my:myFields/my:MySignatureURL").text;
  51.  
  52.     if (SignAndUpdateWorkflowInfo(strImageUrl))
  53.     {
  54.         RemoveFileAttachment();
  55.  
  56.         XDocument.Submit();
  57.         XDocument.CloseDocument();
  58.     }
  59.     else
  60.         TaskStatus.text = "";
  61. }
  62.  
  63. //=======
  64. // The following function handler is created by Microsoft InfoPath.
  65. // Do not modify the name of the function, or the name and number of arguments.
  66. //=======
  67. function CTRL79_5::OnClick(eventObj)
  68. {
  69.     // On Reject button clicked
  70.  
  71.     var nodeRejectedImageUrl;
  72.     
  73.     // Validate signatures
  74.     if (IsInvalidated())
  75.     {
  76.         var fIsInvalidated = XDocument.DOM.selectSingleNode("/my:myFields/my:IsInvalidated");
  77.         fIsInvalidated.text = "true";
  78.     }
  79.  
  80.     var TaskStatus = XDocument.DOM.selectSingleNode("/my:myFields/my:TaskStatus");
  81.     TaskStatus.text = "@";
  82.  
  83.     var siteUrl = XDocument.GetDOM("Context").selectSingleNode("Context/@siteUrl").value;
  84.  
  85.     // Get "Rejected" image url
  86.     XDocument.GetDOM("ItemMetadata").setProperty("SelectionNamespaces", 'xmlns:z="#RowsetSchema"');
  87.     nodeRejectedImageUrl = XDocument.GetDOM("ItemMetadata").selectSingleNode("//z:row/@ows_RejectedImageURL");
  88.  
  89.     if (SignAndUpdateWorkflowInfo(nodeRejectedImageUrl.text))
  90.     {
  91.         RemoveFileAttachment();
  92.  
  93.         XDocument.Submit();
  94.         XDocument.CloseDocument();
  95.     }
  96.     else
  97.         TaskStatus.text = "";
  98. }
  99.  
  100. //=======
  101. // The following function handler is created by Microsoft InfoPath.
  102. // Do not modify the name of the function, or the name and number of arguments.
  103. //=======
  104. function CTRL85_5::OnClick(eventObj)
  105. {
  106.     // On Hold button clicked
  107.  
  108.     // Validate signatures
  109.     if (IsInvalidated())
  110.     {
  111.         var fIsInvalidated = XDocument.DOM.selectSingleNode("/my:myFields/my:IsInvalidated");
  112.         fIsInvalidated.text = "true";
  113.     }
  114.  
  115.     var IsHold = XDocument.DOM.selectSingleNode("/my:myFields/my:IsHold");
  116.     IsHold.text = "true";
  117.  
  118.     RemoveFileAttachment();
  119.  
  120.     XDocument.Submit();
  121.     XDocument.CloseDocument();
  122. }
  123.  
  124. //=======
  125. // The following function handler is created by Microsoft InfoPath.
  126. // Do not modify the name of the function, or the name and number of arguments.
  127. //=======
  128. function XDocument::OnSubmitRequest(eventObj)
  129. {
  130.     XDocument.DataAdapters("Submit").Submit();
  131.  
  132.     // If the submit operation is successful, set
  133.     // eventObj.ReturnStatus = true;
  134.     eventObj.ReturnStatus = true;
  135. }
  136.  
  137. //=======
  138. // The following function handler is created by Microsoft InfoPath.
  139. // Do not modify the name of the function, or the name and number of arguments.
  140. //=======
  141. function XDocument::OnLoad(eventObj)
  142. {
  143.     hostApplication = XDocument.Host;
  144. }
  145.  
  146. //=======
  147. // Signs document and updates workflow information after signing
  148. //=======
  149. function SignAndUpdateWorkflowInfo(strImageUrl)
  150. {
  151.     // Message string localizable
  152.     var L_SIGNATURE_ALREADY_SIGNED_TXT = "You cannot sign this document because it is already signed for you.\n\nYou can proceed after removing the signature or you can ask the administrator for information.";
  153.     var L_ARBITRARY_APPROVAL_POSTFIX_TXT = "(A)";
  154.     var L_DELEGATED_APPROVAL_POSTFIX_TXT = "(D)";
  155.     var L_ARBITRARYDELEGATED_APPROVAL_POSTFIX_TXT = "(A/D)";
  156.  
  157.     var result = false;
  158.     var msoSignatureSubsetSignatureLines = 2;
  159.     var mySignatureID;
  160.     var strCurrentSigner;
  161.     var strCurrentSignerTitle;
  162.     var fIsDelegated;
  163.     var fIsArbitrary;
  164.     var fIsGroupTask;
  165.  
  166.     if (hostApplication == null)
  167.         return result;
  168.  
  169.     // Check if it is a delegated approval
  170.     XDocument.GetDOM("ItemMetadata").setProperty("SelectionNamespaces", 'xmlns:z="#RowsetSchema"');
  171.     var nodeIsDelegated = XDocument.GetDOM("ItemMetadata").selectSingleNode("//z:row/@ows_IsDelegated");
  172.     if (nodeIsDelegated.text == "true")
  173.         fIsDelegated = true;
  174.     else
  175.         fIsDelegated = false;
  176.  
  177.     // Get SignatureID of the current approver from XML DOM node
  178.     var nodeCurrentSignatureID = XDocument.GetDOM("ItemMetadata").selectSingleNode("//z:row/@ows_CurrentSignatureID");
  179.     mySignatureID = nodeCurrentSignatureID.text;
  180.  
  181.     // Check if it is an arbitrary approval
  182.     var nodeIsArbitrary = XDocument.DOM.selectSingleNode("/my:myFields/my:IsArbitrary");
  183.     if (nodeIsArbitrary != null)
  184.     {
  185.         if (nodeIsArbitrary.text == "true")
  186.             fIsArbitrary = true;
  187.         else
  188.             fIsArbitrary = false;
  189.     }
  190.  
  191.     // Check if it is a group task
  192.     XDocument.GetDOM("ItemMetadata").setProperty("SelectionNamespaces", 'xmlns:z="#RowsetSchema"');
  193.     var nodeIsGroupTask = XDocument.GetDOM("ItemMetadata").selectSingleNode("//z:row/@ows_TaskGroup");
  194.     if (nodeIsGroupTask != null)
  195.         fIsGroupTask = true;
  196.     else
  197.         fIsGroupTask = false;
  198.  
  199.     // Get the current approver's name and title  (CTasks::Init() will properly initialize these fields)
  200.     strCurrentSigner = XDocument.DOM.selectSingleNode("/my:myFields/my:CurrentSigner").text;
  201.     strCurrentSignerTitle = XDocument.DOM.selectSingleNode("/my:myFields/my:CurrentSignerTitle").text;
  202.  
  203.     // Get email address of the current approver from XML DOM node
  204.     var myEmail = XDocument.DOM.selectSingleNode("/my:myFields/my:AssigneeEmail").text;
  205.  
  206.     // Get signature set from host application's document
  207.     var Signatures = XDocument.Host.Signatures;
  208.  
  209.     // Find my signature in host application's document
  210.     Signatures.Subset = msoSignatureSubsetSignatureLines;
  211.     var cSignatures = Signatures.Count;
  212.  
  213.     for (i = 1; i <= cSignatures; i++)
  214.     {
  215.         var aSignature = Signatures(i);
  216.  
  217.         var canSetup = aSignature.CanSetup;
  218.         if (canSetup == false)
  219.             continue;
  220.         
  221.         var pSignatureSetup = aSignature.Setup;
  222.         
  223.         var strSuggestedSignerEmail = pSignatureSetup.SuggestedSignerEmail;
  224.         var strSignatureID = pSignatureSetup.Id;
  225.  
  226.         if (strSignatureID == mySignatureID)
  227.         {
  228.             var fIsSigned = aSignature.IsSigned;
  229.             if (fIsSigned)
  230.             {
  231.                 XDocument.UI.Alert(L_SIGNATURE_ALREADY_SIGNED_TXT);
  232.                 result = false;
  233.                 break;
  234.             }
  235.             else
  236.             {
  237.                 // Check if this is delegation or arbitrary approval
  238.                 if (fIsDelegated && fIsArbitrary)
  239.                     strCurrentSignerTitle = strCurrentSignerTitle + L_ARBITRARYDELEGATED_APPROVAL_POSTFIX_TXT;
  240.                 else if (fIsArbitrary)
  241.                     strCurrentSignerTitle = strCurrentSignerTitle + L_ARBITRARY_APPROVAL_POSTFIX_TXT;
  242.                 else if (fIsDelegated)
  243.                     strCurrentSignerTitle = strCurrentSignerTitle + L_DELEGATED_APPROVAL_POSTFIX_TXT;
  244.                 else
  245.                     strCurrentSignerTitle = strCurrentSignerTitle;
  246.                 
  247.                 var nodeCanSubmit = XDocument.DOM.selectSingleNode("/my:myFields/my:CanSubmit");
  248.  
  249.                 try
  250.                 {
  251.                     // Show signing ceremony dialog
  252.                     aSignature.Sign(strImageUrl, strCurrentSigner, strCurrentSignerTitle, myEmail);
  253.                 }
  254.                 catch (e)
  255.                 {
  256.                     // Disable submit UI
  257.                     nodeCanSubmit.text = "false";
  258.                 }
  259.  
  260.                 // NOTE: While signing, we may detect there is a newer version of a currenlty opened document.
  261.                 //           In this case, aSignautre is not null but has invalid COM object pointer.
  262.                 //           Invalidated object 'aSignature' causes an exception when its 'IsSigned' property is accessed.
  263.                 //           We catch that exception for detecting 'document reload'.
  264.                 if (aSignature == null)
  265.                 {
  266.                     // Disable submit UI
  267.                     nodeCanSubmit.text = "false";
  268.                 }
  269.                 else
  270.                 {
  271.                     // aSignature is not NULL
  272.                     
  273.                     try
  274.                     {
  275.                         fIsSigned = aSignature.IsSigned;
  276.                     }
  277.                     catch (e)
  278.                     {
  279.                         // aSignature is not NULL but invalid object.
  280.                         // This happens when a newer version of document is just reloaded.
  281.                         XDocument.CloseDocument();
  282.                     }
  283.                 }
  284.  
  285.                 // Check if user click "Cancel" button
  286.                 if (fIsSigned == false)
  287.                     break;
  288.             }
  289.             
  290.             var pSignatureInfo = aSignature.Details;
  291.  
  292.             // Update my comment in Reviewers info
  293.             var myComment = pSignatureInfo.SignatureComment;
  294.             var Reviewers = XDocument.DOM.selectSingleNode("/my:myFields/my:Reviewers");
  295.             var Persons = Reviewers.selectNodes("/my:myFields/my:Reviewers/my:Person");
  296.             var Person;
  297.             while (Person = Persons.nextNode())
  298.             {
  299.                 var nodeSignatureID = Person.selectSingleNode("my:SignatureID");
  300.                 
  301.                 if (mySignatureID == nodeSignatureID.text)
  302.                 {
  303.                     var nodeComment = Person.selectSingleNode("my:Comment");
  304.                     nodeComment.text = myComment;
  305.                     break;
  306.                 }
  307.             }
  308.  
  309.             // Successfully signed and comment is applied to xml node
  310.             result = true;
  311.             break;
  312.         }
  313.     }
  314.  
  315.     return result;
  316. }
  317.  
  318. //=======
  319. // Returns true if any signature in a host document is invalidated
  320. //=======
  321. function IsInvalidated()
  322. {
  323.     // Message string localizable
  324.     var L_INVALIDATED_SIGNATURE_FOUND_ERR = "The original setting of signatures has been deliberately modified.\n\nWorkflow will be canceled.";
  325.  
  326.     var hasInvalidSignature = false;
  327.     var msoSignatureSubsetSignatureLines = 2;
  328.  
  329.     var Signatures = XDocument.Host.Signatures;
  330.  
  331.     Signatures.Subset = msoSignatureSubsetSignatureLines;
  332.     var cSignatures = Signatures.Count;
  333.  
  334.     // 1. Search for signature whose "IsValid" status is set (ex. document is modified)
  335.     for (i = 1; i <= cSignatures; i++)
  336.     {
  337.         var aSignature = Signatures(i);
  338.  
  339.         var canSetup = aSignature.CanSetup;
  340.         if (canSetup == false)
  341.             continue;
  342.  
  343.         var fIsSigned = aSignature.IsSigned;
  344.         if (!fIsSigned)
  345.             continue;
  346.  
  347.         var pSignatureInfo = aSignature.Details;
  348.         if (pSignatureInfo.IsValid == false)
  349.         {
  350.             hasInvalidSignature = true;
  351.             break;
  352.         }
  353.     }
  354.  
  355.     // 2. Check each SignatureID in Reviewers exists in the document's signature set to see if any signature has been deleted.
  356.     if (!hasInvalidSignature)
  357.     {
  358.         var Reviewers = XDocument.DOM.selectSingleNode("/my:myFields/my:Reviewers");
  359.         var Persons = Reviewers.selectNodes("/my:myFields/my:Reviewers/my:Person");
  360.         var Person;
  361.  
  362.         while (Person = Persons.nextNode())
  363.         {
  364.             var nodeGUID = Person.selectSingleNode("my:SignatureID");
  365.             var fFound = false;
  366.  
  367.             for (i = 1; i <= cSignatures; i++)
  368.             {
  369.                 var aSignature = Signatures(i);
  370.                 var pSignatureSetup = aSignature.Setup;
  371.                 var strSignatureID = pSignatureSetup.Id;
  372.                 
  373.                 if (nodeGUID.text == strSignatureID)
  374.                 {
  375.                     fFound = true;
  376.                     break;
  377.                 }
  378.             }
  379.  
  380.             if (fFound == false)
  381.                 {
  382.                     hasInvalidSignature = true;
  383.                     break;
  384.                 }            
  385.         }
  386.     }
  387.  
  388.     if (hasInvalidSignature)
  389.         XDocument.UI.Alert(L_INVALIDATED_SIGNATURE_FOUND_ERR);
  390.  
  391.     return hasInvalidSignature;
  392. }
  393.  
  394. //=======
  395. // Returns true if the next approver is resolved person or if a user allows unresolved participant in the next approval step
  396. //=======
  397. function ValidateNextParticipant(mySignatureID)
  398. {
  399.     // NOTE: No optimization for comprehensive code (hgkim)
  400.  
  401.     // Consts for message box
  402.     var xdYesNo = 4;
  403.     var xdYes = 6;
  404.     var xdNo = 7;
  405.  
  406.     // Message string localizable
  407.     var L_NEXT_APPROVER_UNRESOLVED_TXT = "Next approver not resolved\n\nPlease assign a person to the next approver.";
  408.     var L_NEXTNEXT_APPROVER_MISSING_TXT = "Failed to find an approver\n\nSome of approvers information might be corrupted.";
  409.     var L_IS_NEXTSTEP_GROUPTASK_TXT = "The next approver is not resolved.\nYou may leave the next approver unresolved if this is for the group task.\n\nIs this a group task?";
  410.     var L_PARALLELSTEP_INCLUDE_GROUP_TXT = "The next parallel approval step includes unresolved approval role.\n\nIs this unresolved approval role '%s' for a group task?";
  411.     
  412.     // Get Reviewers data.
  413.     var Reviewers = XDocument.DOM.selectSingleNode("/my:myFields/my:Reviewers");
  414.     var Persons = Reviewers.selectNodes("/my:myFields/my:Reviewers/my:Person");
  415.     var Person;
  416.     
  417.     // Get SignatureID of the current approver from XML DOM node.
  418.     XDocument.GetDOM("ItemMetadata").setProperty("SelectionNamespaces", 'xmlns:z="#RowsetSchema"');
  419.     var mySignatureID = XDocument.GetDOM("ItemMetadata").selectSingleNode("//z:row/@ows_CurrentSignatureID").text;
  420.  
  421.     var fFoundMe = false;
  422.     var strNextApprover_Email = "";
  423.     var strNextApprover_ApprovalType = "";
  424.     var strNextApprover_Order = "";
  425.  
  426.     // Person node for next approver after me
  427.     var nodeNextApprover;
  428.     var strMyOrder = "";
  429.     var strMyApprovalType;
  430.  
  431.     // Find the next approver.
  432.     while (Person = Persons.nextNode())
  433.     {
  434.         var nodeSignatureID = Person.selectSingleNode("my:SignatureID");
  435.         
  436.         // If fFoundMe is true, the current Person node is pointing to the next approver
  437.         if (fFoundMe)
  438.         {
  439.             // Get the order of the next approver.
  440.             var nodeOrder = Person.selectSingleNode("my:Order");
  441.             strNextApprover_Order = nodeOrder.text;
  442.  
  443.             // Find a person who has bigger order than me. (I may be in parallel step)
  444.             if (strMyOrder == strNextApprover_Order)
  445.                 continue;
  446.  
  447.             nodeNextApprover = Person;
  448.  
  449.             // Get the email address of the next approver.
  450.             var nodeEmail = Person.selectSingleNode("my:EmailAddress");
  451.             strNextApprover_Email = nodeEmail.text;
  452.             
  453.             // Get the approval type of the next approver.
  454.             var nodeApprovalType = Person.selectSingleNode("my:ApprovalType");
  455.             strNextApprover_ApprovalType = nodeApprovalType.text;
  456.             
  457.             break;
  458.         }
  459.  
  460.         if (mySignatureID == nodeSignatureID.text)
  461.         {
  462.             var nodeMyOrder = Person.selectSingleNode("my:Order");
  463.             var nodeMyApprovalType = Person.selectSingleNode("my:ApprovalType");
  464.             strMyOrder = nodeMyOrder.text
  465.             strMyApprovalType = nodeMyApprovalType.text;
  466.             fFoundMe = true;
  467.         }
  468.     }
  469.  
  470.     // No more approver after me.
  471.     if (nodeNextApprover == null)
  472.         return true;
  473.  
  474.     // We don't check next approval step if I'm parallel approver.
  475.     if (IsParallelApprovalType(strMyApprovalType))
  476.         return true;
  477.  
  478.     // Check if the next approval step is parallel.
  479.     if (IsParallelApprovalType(strNextApprover_ApprovalType))
  480.     {
  481.         // If the very next approver is parallel branch, there should not be any unresolved participant in that branch.    
  482.         Persons = Reviewers.selectNodes("/my:myFields/my:Reviewers/my:Person");
  483.         while (Person = Persons.nextNode())
  484.         {
  485.             var nodeApprovalType = Person.selectSingleNode("my:ApprovalType");
  486.             var strApprovalType = nodeApprovalType.text;
  487.  
  488.             // if (parallel approver) ...
  489.             if (IsParallelApprovalType(strApprovalType))
  490.             {
  491.                 var strEmail = Person.selectSingleNode("my:EmailAddress").text;
  492.                 if (strEmail == "")
  493.                 {
  494.                     var strDisplayName = Person.selectSingleNode("my:DisplayName").text;
  495.                     var strMessage = L_PARALLELSTEP_INCLUDE_GROUP_TXT.replace("%s", strDisplayName);
  496.                     var result = XDocument.UI.Confirm(strMessage, xdYesNo);
  497.  
  498.                     if (result == xdNo)
  499.                     {
  500.                         // Do not proceed with workflow. User will resolve the next approver.
  501.                         XDocument.UI.Alert(L_NEXT_APPROVER_UNRESOLVED_TXT);
  502.                         return false;
  503.                     }
  504.                 }
  505.             }
  506.         }
  507.  
  508.         // If the very next approver is a parallel approval step, the approver after that parallel approval step should be resolved, too.
  509.         var nodeNextToParallel;
  510.         var strNextToParallel_Order = "" + (parseInt(strNextApprover_Order) + 1);
  511.         Persons = Reviewers.selectNodes("/my:myFields/my:Reviewers/my:Person");
  512.         while (Person = Persons.nextNode())
  513.         {
  514.             var nodeOrder = Person.selectSingleNode("my:Order");
  515.             if (nodeOrder.text == strNextToParallel_Order)
  516.             {
  517.                 nodeNextToParallel = Person;
  518.                 break;
  519.             }
  520.         }
  521.         
  522.         if (nodeNextToParallel != null)
  523.         {
  524.             var strEmailOfNextToParallel = nodeNextToParallel.selectSingleNode("my:EmailAddress").text;
  525.  
  526.             if (strEmailOfNextToParallel == "")
  527.             {
  528.                 var result = XDocument.UI.Confirm(L_IS_NEXTSTEP_GROUPTASK_TXT, xdYesNo);
  529.  
  530.                 if (result == xdNo)
  531.                 {
  532.                     // Do not proceed with workflow. User will resolve the next approver after parallel approval step.
  533.                     XDocument.UI.Alert(L_NEXT_APPROVER_UNRESOLVED_TXT);
  534.                     return false;
  535.                 }
  536.                 else
  537.                 {
  538.                     // Proceed with workflow. 'nodeNextToParallel' is for group task.
  539.                     return true;
  540.                 }
  541.             }
  542.             else
  543.             {
  544.                 // Good. Approver after the parallel approval step is resolved.
  545.                 return true;
  546.             }
  547.         }
  548.         else
  549.         {
  550.             // Reviewers info might be corrupted.
  551.             XDocument.UI.Alert(L_NEXTNEXT_APPROVER_MISSING_TXT);
  552.             return false;
  553.         }
  554.  
  555.     }
  556.     else
  557.     {
  558.         // See if the last approver's email address is empty.
  559.         if (strNextApprover_Email == "")
  560.         {
  561.             var result = XDocument.UI.Confirm(L_IS_NEXTSTEP_GROUPTASK_TXT, xdYesNo);
  562.  
  563.             if (result == xdNo)
  564.             {
  565.                 // Do not proceed with workflow. User will resolve the next approver.
  566.                 XDocument.UI.Alert(L_NEXT_APPROVER_UNRESOLVED_TXT);
  567.                 return false;
  568.             }
  569.             else
  570.             {
  571.                 // We may proceed with workflow. This is really for the 'group task'.
  572.                 return true;
  573.             }
  574.         }
  575.         else
  576.         {
  577.             // Good. Next approver is resolved.
  578.             return true;
  579.         }
  580.     }
  581. }
  582.  
  583. //=======
  584. // Returns true if given string is "Coapproval" or "Cooperative"
  585. //=======
  586. function IsParallelApprovalType(approvalType)
  587. {
  588.     if ((approvalType == "Coapproval") || (approvalType == "Cooperative"))
  589.         return true;
  590.     else
  591.         return false;
  592. }
  593.  
  594. //=======
  595. // Removes all the children nodes of my:EawfAttachments
  596. //=======
  597. function RemoveFileAttachment()
  598. {
  599.     var nodeEawfAttachments = XDocument.DOM.selectSingleNode("/my:myFields/my:EawfAttachments");
  600.     var nodesEawfAttachment = nodeEawfAttachments.selectNodes("/my:myFields/my:EawfAttachments/my:EawfAttachment");
  601.     var nodeEawfAttachment;
  602.  
  603.     // Remove all the children nodes of my:EawfAttachments
  604.     if (nodesEawfAttachment != null)
  605.     {
  606.         while (nodeEawfAttachment = nodesEawfAttachment.nextNode())
  607.         {
  608.             var nodeAttachedFile = nodeEawfAttachment.selectSingleNode("my:AttachedFile");
  609.             nodeEawfAttachments.removeChild(nodeEawfAttachment);
  610.         }
  611.     }
  612. }
  613.