This is a follow-up question to original [Prorated Refund Calculator](http://codereview.stackexchange.com/questions/91743/prorated-refund-calculator). Here is the summary of the changes I made since last, thanks to the good answers and some study of my own. 

- Did away with bleeding-edge ECMAScript 6 code that was causing compatibility issues with some browsers.
- Added more input validation.
- Added a utility function to format dates to MM/DD/YYYY format.
- Input values are now obtained using `getElementById` instead of getting them from a numbered list.
- Output is appended into the existing page, rather than updating placeholder HTML tags.
- Documentation throughout.
- Output is more comprehensive and user-friendly. 

Is there anything else that I could improve before I share this with my colleagues?

<!-- begin snippet: js hide: false -->

<!-- language: lang-html -->

 <!DOCTYPE html>
 <html>
 <head>
 <title>Prorated Refund Calculator</title>
 <style>
 body {
 font-family: Calibri, Arial, sans-serif;
 font-size: 1.0em;
 }
 h1 {
 font-size: 1.2em;
 }
 </style>
 </head>
 <body>
 <h1>Prorated Refund Calculator</h1>
 <p>Input into the following fields and press Calculate.</p>
 <p style="color: red;">Enter date format as MM/DD/YYYY</p>
 <form>
 <label>Product Purchase Date: <input type="text" id="productPurchaseDate" /> </label><br/>
 <label>Contract Purchase Date: <input type="text" id="contractPurchaseDate" /> </label><br/>
 <label>Purchase Price: <input type="text" id="purchasePrice" /> </label><br/>
 <label>Term (in years): <input type="text" id="termInYears" value="10" /> </label><br/>
 <label>Cancel Date: <input type="text" id="cancelDate" /> </label><br/>
 <label>Amount paid in claims: <input type="text" id="amtPaidInClaims" value="0" /> </label><br/>
 <label>Grace period (in days): <input type="text" id="gracePeriodInDays" value="60" /></label><br/>
 </form>
 <br/>
 <button onclick="calculateProratedRefund()">Calculate</button>
 
 <script type="text/javascript">
 
 /**
 * Main function called by HTML form.
 * Validates input values, then performs calculations 
 * and adds the result into the HTML document to display to the user.
 */
 function calculateProratedRefund() {
 "use strict";
 
 var productPurchaseDate = new Date(document.getElementById("productPurchaseDate").value);
 var contractPurchaseDate = new Date(document.getElementById("contractPurchaseDate").value);
 var purchasePrice = parseFloat(document.getElementById("purchasePrice").value).toFixed(2);
 var termInYears = parseInt(document.getElementById("termInYears").value, 10);
 var cancelDate = new Date(document.getElementById("cancelDate").value);
 var amtPaidInClaims = parseFloat(document.getElementById("amtPaidInClaims").value).toFixed(2);
 var gracePeriodInDays = parseInt(document.getElementById("gracePeriodInDays").value, 10);
 
 /**
 * Underwriting policies specify that a Year of coverage is exactly 365 Days, regardless of Leap Years.
 * Hence the following calculations:
 */
 var totalDays = (termInYears * 365);
 var expirationDate = new Date(productPurchaseDate);
 expirationDate.setDate(productPurchaseDate.getDate() + (totalDays));
 
 /**
 * Confirm that all dates are valid Date values and that they follow business rules before proceeding to calculations.
 */
 if ( termInYears < 0 ) {
 window.alert("Term in years must be greater than zero.")
 }
 else if ( !isValidDate(productPurchaseDate) ) {
 window.alert("Invalid ProductPurchase Date.");
 } 
 else if ( !isValidDate(contractPurchaseDate) ) {
 window.alert("Invalid Contract Purchase Date.");
 } 
 else if ( !isValidDate(cancelDate) ) {
 window.alert("Invalid Cancel Date.");
 }
 else if ( cancelDate < productPurchaseDate || cancelDate < contractPurchaseDate ) {
 window.alert("Cancel date cannot be prior to Product or Contract purchase date.");
 }
 else if ( cancelDate > expirationDate ) {
 window.alert("Cancel date cannot be past Expiration date.");
 }
 
 /**
 * Confirm that all numbers are valid numbers for calculations. 
 */
 else if ( isNaN(purchasePrice) || isNaN(termInYears) || isNaN(amtPaidInClaims) || isNaN(gracePeriodInDays) ) {
 window.alert("Invalid Number Entry. Please check your entries and try again.");
 }
 
 /**
 * If all the input values are valid, we proceed to calculations.
 */
 else {
 
 /**
 * All terms are calculated in Days, hence the following conversion from JavaScript's millisecond precision to Days.
 * (ms * secs * mins * hours) = 1 Day
 */
 var msPerDay = (1000 * 60 * 60 * 24); 
 var daysElapsed = Math.floor(( Date.parse(cancelDate) - Date.parse(contractPurchaseDate) ) / msPerDay);
 
 /**
 * Policy holder is entitled to a full refund within the grace period.
 */
 var termUsed = 0.0;
 if ( daysElapsed <= gracePeriodInDays ) {
 termUsed = 0.0;
 } 
 else {
 termUsed = (daysElapsed / totalDays);
 }
 var termLeft = 1.0 - termUsed;
 
 /**
 * Finally we calculate the refund amount
 */
 var proratedRefund = (purchasePrice * termLeft).toFixed(2);
 var finalRefund = (proratedRefund - amtPaidInClaims).toFixed(2);
 if ( finalRefund < 0.0 ) {
 finalRefund = 0.0;
 }
 
 /**
 * Output calculation results to HTML document.
 */
 var outputPar = document.createElement("p");
 
 outputPar.appendChild(document.createTextNode("Product Purchase date: " + formatDate(productPurchaseDate)));
 outputPar.appendChild(document.createElement("br"));
 outputPar.appendChild(document.createTextNode("Contract Purchase date: " + formatDate(contractPurchaseDate)));
 outputPar.appendChild(document.createElement("br"));
 outputPar.appendChild(document.createTextNode("Total days: " + totalDays + " (" + termInYears + " years)"));
 outputPar.appendChild(document.createElement("br"));
 outputPar.appendChild(document.createTextNode("Expiration date: " + formatDate(expirationDate)));
 outputPar.appendChild(document.createElement("br"));
 outputPar.appendChild(document.createTextNode("Cancel date: " + formatDate(cancelDate)));
 outputPar.appendChild(document.createElement("br"));
 outputPar.appendChild(document.createTextNode("Grace period: " + gracePeriodInDays + " days"));
 outputPar.appendChild(document.createElement("br"));
 outputPar.appendChild(document.createTextNode("Days elapsed: " + daysElapsed + " (" + parseFloat(daysElapsed / 365).toFixed(2) + " years)"));
 outputPar.appendChild(document.createElement("br"));
 outputPar.appendChild(document.createTextNode("Refund percent: " + (termLeft * 100).toFixed(2) + " %"));
 outputPar.appendChild(document.createElement("br"));
 outputPar.appendChild(document.createTextNode("Purchase price: $ " + purchasePrice));
 outputPar.appendChild(document.createElement("br"));
 outputPar.appendChild(document.createTextNode("Prorated refund: $ " + proratedRefund));
 outputPar.appendChild(document.createElement("br"));
 outputPar.appendChild(document.createTextNode("Paid in claims: $ " + amtPaidInClaims));
 outputPar.appendChild(document.createElement("br"));
 outputPar.appendChild(document.createTextNode("Final refund: $ " + finalRefund));
 outputPar.appendChild(document.createElement("br"));
 
 document.body.appendChild(outputPar);
 }
 }
 
 /**
 * Utility function to make sure an input is a correct Date format
 * @param date Date - A date or date-time value.
 * @returns boolean - Whether the input date is a valid date.
 */
 function isValidDate(date) {
 "use strict";
 if ( Object.prototype.toString.call(date) !== "[object Date]" ) {
 return false;
 } 
 else if ( isNaN(date.getTime()) ) {
 return false;
 } 
 else {
 return true;
 }
 }
 
 /**
 * Utility function to convert a Date to MM/DD/YYYY formatted String.
 * @param date Date - A date or date-time value.
 * @returns String - A String formatted to MM/DD/YYYY date if date is valid, otherwise a String with error message.
 */
 function formatDate(date) {
 "use strict";
 var inputDate = new Date(date);
 if ( isValidDate(inputDate) ) {
 var year = inputDate.getFullYear();
 var month = (1 + inputDate.getMonth()).toString(); // months are 0-indexed hence the 1 + getMonth()
 var day = inputDate.getDate().toString();
 return(month + '/' + day + '/' + year);
 } 
 else {
 return("Invalid date: " + inputDate);
 }
 }
 
 </script>
 
 </body>
 </html>

<!-- end snippet -->

Sample input:

> Product Purchase date: 6/1/2013 <br>
> Contract Purchase date: 1/15/2014<br>
> Purchase Price: 699 <br>
> Term (in years): 10 <br>
> Cancel date: 07/13/2015 <br>
> Paid in claims: 147 <br>
> Grace period: 60<br>

Resulting output:

<pre><blockquote>Product Purchase date: 6/1/2013
Contract Purchase date: 1/15/2014
Total days: 3650 (10 years)
Expiration date: 5/30/2023
Cancel date: 7/13/2015
Grace period: 60 days
Days elapsed: 543 (1.49 years)
Refund percent: 85.12 %
Purchase price: $ 699.00
Prorated refund: $ 595.01
Paid in claims: $ 147.00
Final refund: $ 448.01</blockquote></pre>