Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

HTML Settings

Here you can Sed posuere consectetur est at lobortis. Donec ullamcorper nulla non metus auctor fringilla. Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.

            
              <!-- NAV BAR SECTION -->
<nav class="navbar navbar-default">
  <div class="container">
    <div class="navbar-header">
      <a class="navbar-brand" href="#">Email Templates</a>
    </div>
			<ul class="nav navbar-nav navbar-right">
				<li>
					<select class="form-control" name="" id="templateSelect">
						<option value="totalLoss">Total Loss Offer</option>					
					</select>
				</li>
			</ul>
  </div><!-- /.container -->
</nav>

<div class='container'>
	<div class='row'>
		
		<div id="errDiv" class="alert alert-danger .alert-dismissible" role="alert">
			<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
  		<span class="sr-only">Error:</span>
		</div>
	
		<!-- EMAIL INPUTS SECTION -->
		<div class='col-sm-5' id='userInput'>
			<div class='thumbnail'>
				<div class='caption'>
					<form id='emailForm'>
						<!-- To email -->
						<div class="form-group row">
							<label for='toEmail' class="col-sm-3 col-form-label">To Email:</label>
							<div class="col-sm-9">
								<input type="email" class="form-control" name="toEmail" id="toEmail" placeholder="SendTo@example.com" autofocus required>
								<span class="tooltip-text">Insert the recipient's email address here</span>
							</div>
						</div>
						<!-- To name -->
						<div class="form-group row">
							<label for='toName' class="col-sm-3 col-form-label">To Name:</label>
							<div class="col-sm-9">
								<input type="text" class="form-control" name="toName" id="toName" placeholder="Optional Recipient Name">
								<span class="tooltip-text">Optionally Insert the recipient's name here</span>
							</div>
						</div>
						<!-- CC email -->				
						<div class="form-group row">
							<label for="ccEmail" class="col-sm-3 col-form-label">CC Email:</label>
							<div class="col-sm-9">
								<input type="email" class="form-control" name="ccEmail" id="ccEmail" placeholder="Optional CC Email">
								<span class="tooltip-text">Optionally add an email address to CC here</span>
							</div>
						</div>
						<!-- Main ref -->				
						<div class="form-group row">
							<label for="aRef" class="col-sm-3 col-form-label">Main ref:</label>
							<div class="col-sm-9">
								<input type="text" class="form-control DPA" name="aRef" id="aRef" placeholder="Insert Our Reference" required>
								<span class="tooltip-text">Insert the reference for this claim here</span>
							</div>
						</div>
						<!-- other ref -->				
						<div class="form-group row">
							<label for="oRef" class="col-sm-3 col-form-label">Your ref:</label>
							<div class="col-sm-9">
								<input type="text" class="form-control DPA" name="oRef" id="oRef" placeholder="Insert Other Reference">
								<span class="tooltip-text">Insert any broker or third&nbsp;party references here</span>
							</div>
						</div>
						<!-- DOA -->		
						<div class="form-group row">
							<label for="doa" class="col-sm-3 col-form-label">DOA:</label>
							<div class="col-sm-9">
								<input type="text" class="form-control DPA" name="doa" id="doa" placeholder='DD/MM/YYYY'>
								<span class="tooltip-text">Insert the date&nbsp;of&nbsp;accident</span>
							</div>
						</div>
						<!-- Our INSD Clinet -->				
						<div class="form-group row">
							<label for="insd" class="col-sm-3 col-form-label">INSD:</label>
							<div class="col-sm-9">
								<input type="text" class="form-control DPA" name="insd" id="insd" placeholder="Optional INSD Name">
								<span class="tooltip-text">Optionally insert the insured client's name here</span>
							</div>
						</div>
						<!-- VAT status -->		
						<div class="form-group row">
							<label for="vat" class="col-sm-3 col-form-label">VAT Status:</label>
							<div class="col-sm-9">
								<select class="form-control" name="vat" id="vat">
									<option value="">VAT status unknown</option>
									<option value="yes">Yes - Taxable</option>
									<option value="no">No - Non Taxable</option>
								</select>
								<span class="tooltip-text">Select the INSD VAT status if known</span>
							</div>
						</div>
						<!-- VRN -->		
						<div class="form-group row">
							<label for="phVrn" class="col-sm-3 col-form-label">INSD's VRN:</label>
							<div class="col-sm-9">
								<input type="text" class="form-control" name="phVrn" id="phVrn" placeholder="INSD's VRN" required>
								<span class="tooltip-text">Insert the registration of the vehicle being total lossed</span>
							</div>
						</div>
						<!-- Excess -->		
						<div class="form-group row">
							<label for="excess" class="col-sm-3 col-form-label">Excess:</label>
							<div class="col-sm-9">
								<input type="number" class="form-control totalLoss" name="excess" id="excess" placeholder='Client Excess' min="0" step="1" required>
								<span class="tooltip-text">Insert the client's excess</span>
							</div>
						</div>
						<!-- PAV -->		
						<div class="form-group row">
							<label for="pav" class="col-sm-3 col-form-label">PAV:</label>
							<div class="col-sm-9">
								<input type="number" class="form-control totalLoss" name="pav" id="pav" placeholder='Pre-accident Value' min="0" step="1" required>
								<span class="tooltip-text">Insert the pre-accident value of the vehicle</span>
							</div>
						</div>
						
						<!-- Additional Costs section -->

						<div id="addCostBtnDiv" class="form-group row">
							<label class="col-sm-3 col-form-label">Other Costs:</label>
							<button id="addCostBtn" class="btn btn-success">Add Cost</button>
						</div>
						
						<!-- Salvage CAT -->		
						<div class="form-group row">
							<label for="salCat" class="col-sm-3 col-form-label">Salvage CAT:</label>
							<div class="col-sm-9">
								<select class="form-control totalLoss" name="salCat" id="salCat">
									<option value="">Vehicle CAT unavailable</option>
									<option value="A">A - Scrap</option>
									<option value="B">B - Breaker</option>
									<option value="C">C - repairable TL</option>
									<option value="D">D - contsructive TL</option>
									<option value="T">Stolen Vehicle</option>
								</select>
								<span class="tooltip-text">Select the vehicle's salvage category if known</span>
							</div>
						</div>
						<!-- Customer Retention? -->		
						<div class="form-group row">
							<label for="custRetain" class="col-sm-3 col-form-label">Retain?</label>
							<div class="col-sm-9">
								<select class="form-control totalLoss" name="custRetain" id="custRetain">
									<option value="">No - Customer didn't request</option>
									<option value="retain">Yes - Customer to retain</option>
								</select>
								<span class="tooltip-text">If the customer has explicitly asked to retain the salvage, select here to add salvage costs to email body</span>
							</div>
						</div>
						<!-- Salvage cost -->		
						<div class="form-group row" id="salValDiv">
							<label for="salCostType salCostInput" class="col-sm-3 col-xs-12 col-form-label">Salvage Cost:</label>
							<div class="col-md-3 col-sm-4 col-xs-5">
								<select class="form-control totalLoss" name="salCostType" id="salCostType">
									<option value="cost">£</option>
									<option value="percent">%</option>
								</select>
								<span class="tooltip-text">Select whether salvage given as cost or percent</span>
							</div>
							<div class="col-md-6 col-sm-5 col-xs-7">
								<input type="number" class="form-control totalLoss" name="salCostInput" id="salCostInput">
								<span class="tooltip-text">Insert salvage cost here</span>
							</div>
						</div>
						
 						<!-- XXX -->
						<!-- Template for new inputs

						<div class="form-group row">
							<label for="XXX" class="col-sm-3 col-form-label">XXX: </label>
							<div class="col-sm-9">
								<input type="text" class="form-control" name="XXX" id="XXX" placeholder='XXX'>
							</div>
						</div> 

						-->
						
						<!-- Extra text -->	
						<div class="form-group row">
							<label for="extraText" class="col-sm-3 col-form-label">Extra Text:</label>
							<div class="col-sm-9">
								<textarea class="form-control" name="extraText" id="extraText"></textarea>
								<span class="tooltip-text">You can add any additional information to the email using this input</span>
							</div>
						</div>
						
						<!-- confirm okay to copy to clipboard -->
						<div class="row">
							<div class="col-xs-12" id="confText">
								<hr>
								<p>
									<strong>***PLEASE READ***</strong>
									<br>								
									This app will copy the body of the generated email to clipboard and open a new message in your email client containing the recipient's email addess and the subject line.<br/>You can then use <strong>CTRL</strong> + <strong>V</strong> to paste in the email body.
								</p>
								<p>
									<input type="checkbox" id="userConfCheck">
									Tick this box to proceed - <em>your choice will be saved.</em>
								</p>
							</div>
						</div> 
						
					</form>
				</div> <!-- /caption -->
			</div> <!-- /thumbnail -->
		</div> <!-- /userInput -->
		

		
		<!-- EMAIL EXAMPLE SECTION -->
		<div class='col-sm-7' id='exampleEmail'>
			<div class='thumbnail'>
				<div class='caption'>
					
					<div class='col-xs-2'>
						<div class="form-group row">
							<div>
								<button class='btn btn-default' id='sendBtn'>
									Create<br>
									Email<br>
									<span class="glyphicon glyphicon-send" aria-hidden="true"></span>
								</button>
							</div>
						</div>
					</div>
					
					<!-- group to & cc examples -->
					<div class='col-xs-10 '>
						<!-- to example -->
						<div class="input-group form-group">
							<span class="input-group-addon">To:</span>
							<div class="form-control" id="toEmailExamp" aria-describedby="basic-addon1" readonly> XXX </div>
						</div>
						
						<!-- CC example -->
						<div class="input-group form-group">
							<span class='input-group-addon'>CC:</span>
							<div class="form-control" id="ccEmailExamp" readonly> XXX </div>
						</div>
					</div> <!-- end group to & cc examples -->
					
						<!-- Subject example -->
						<div class="form-group row">
							<label for="subExamp" class="col-sm-2 col-form-label">Subject:</label>
							<div class="col-sm-10">
								<div class="form-control" id="subExamp" readonly>
									XXX
								</div> 
							</div>
						</div>

						<!-- Body example -->
						<div class="form-group">
							<div id='bodyExamp' class='form-control' readonly>
								*** Please enable javascript ***
							</div>
						</div>
					
				</div><!-- /caption -->
			</div><!-- end thumbnail -->
		</div> <!-- /exampleEmail-->
		
	</div> <!-- /row (both columms) -->
</div> <!-- /container all -->

<textarea id="copyPlaceholder"></textarea>
            
          
!
            
              /* ============== */
/* 		VARIABLES 	*/
/* ============== */

$tooltip-bg: rgba( 0, 0, 0, 0.7 );

/* ============== */
/* 			CODE 	  	*/
/* ============== */

body{
	background: #649173;  /* fallback for old browsers */
	background: -webkit-linear-gradient(to right, #DBD5A4, #649173);  /* Chrome 10-25, Safari 5.1-6 */
	background: linear-gradient(to right, #DBD5A4, #649173); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
}
#addCostBtn{
	margin: 5px 15px;
}
div{
	min-height:35px;
}

textarea{
	resize: none;
	overflow: scrollbar;
}

h4 {
	font-weight: bold;
}

.navbar-default{
	border: none;
	/* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#ffffff+0,f3f3f3+50,ededed+51,ffffff+100;White+Gloss+%232 */
	background: rgb(255,255,255); /* Old browsers */
	background: -moz-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(243,243,243,1) 50%, rgba(237,237,237,1) 51%, rgba(255,255,255,1) 100%); /* FF3.6-15 */
	background: -webkit-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(243,243,243,1) 50%,rgba(237,237,237,1) 51%,rgba(255,255,255,1) 100%); /* Chrome10-25,Safari5.1-6 */
	background: linear-gradient(to bottom, rgba(255,255,255,1) 0%,rgba(243,243,243,1) 50%,rgba(237,237,237,1) 51%,rgba(255,255,255,1) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
	filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#ffffff',GradientType=0 ); /* IE6-9 */
}

.form-control{
	height: auto;
	overflow-wrap: break-word;
}

.input-group-addon{
	min-width: 50px;
}

.navbar-brand{
	font-size: 200%;
	margin: 0px;
	margin-top: 8px;
}

.error{
	background-color: rgb(235, 204, 209);
	border-color: rgb(235, 204, 209);
}

.thumbnail{
	box-shadow: 3px 3px 10px rgba( 0, 0, 0, 0.5 );
	box-shadow: 6px 6px 10px rgba( 0, 0, 0, 0.2 );
}

#errDiv{
	display: none;
}

#send{
	padding: 0;
	height:85px;
	width:90%;
}

#templateSelect{
	margin: 15px;
	width: 200px
}

#salValDiv{
	display: none;
}

#confText{
	text-align: center
}

#userConfCheck{
	position: relative;
	top: 2px;
	margin-right: 3px;
}

#copyPlaceholder{
	position: relative;
	left: -9999px;
}

/* Tool tip styles */

.form-control{
	& + .tooltip-text{
		visibility: hidden;
		opacity: 0;
		width: 90%; // rough fall back for calc
		width: calc(100% - 30px);
		background-color: $tooltip-bg;
		color: #fff;
		text-align: center;
		padding: 5px;
		margin-right: 20px;
		border-radius: 6px;
		// Position the tooltip text
		position: absolute;
		bottom: 100%;
		margin-bottom: 5px;
		z-index: 2;
		transition: opacity 1s;
		// add arrow after tooltip
		&::after {
			content: " ";
			position: absolute;
			top: 100%;
			left: 50%;
			border-width: 5px;
			border-style: solid;
			border-color: $tooltip-bg transparent transparent transparent ;
		}
	}
	// on focus show tip
	&:focus + .tooltip-text {
		animation: fadeTip 10s ease;
	}
}

@keyframes fadeTip{
	0% {
		visibility: hidden;
		opacity: 0;
	}
	10%{
		visibility: visible;
		opacity: 1;
	}
	90%{
		visibility: visible;
		opacity: 1;
	}
	100%{
		visibility: hidden;
		opacity: 0;
	}
}
            
          
!
            
              // Run JS in IIFE to prevent var clash
(function(){
/*==================*/
/*		Variables	*/
/*==================*/

var template = "totalLoss",
	// subject
	DPA	= document.querySelectorAll(".DPA"),
	// TL inputs
	allTL = document.querySelectorAll(".totalLoss"),
	// text vars
	taxable = "This value does not include VAT which we would not pay due to your VAT registered status.",
	salvageText = {
		// salvage cat descriptions
		A : "Please note that as a CAT A Total loss, your vehicle has no economically salvageable parts and has value only for scrap metal.",
		B : "Please note that as a CAT B Total loss, your vehicle should not be repaired. The vehicle should be broken down for spares and the main structure of the vehicle will be destroyed.",
		C : "Please note that as a CAT C Total loss, The cost of repairs exceeded the pre-accident value of the vehicle.",
		D : "Please note that as a CAT D Total loss, The repair costs are less than the pre-accident value of the vehicle and for economic reasons it has been decided to deal with the vehicle as a Constructive Total Loss.",
		T : "Please note that as a stolen vehicle, we will be transferred ownership of the vehicle after settlement is complete. In the event of the vehicle ever being recovered after settlement, you will no longer be the legal owner of the vehicle.",
		// text if PH wants to retain
		retainStd : '<p>Since you have decided to retain ownership of your vehicle, we will need to deduct the salvage value of the vehicle. This is the value of the vehicle if it was sold in its current condition which we have valued at £<span id="salCostExamp">0</span>. <br/> Therefore if your decide to keep the vehicle, after salvage and excess deductions we will pay you £<span id="salPayoutExamp">0</span>.</p>',
		retainDestroy : '<p>We must inform customers that the salvage category placed on the vehicle describes the vehicle as scrap and can result in the vehicle remains being classed as hazardous waste - the remains should be disposed of in line with legislative requirements. DVLA will not reissue a V5 for your vehicle and it is the customers responsibility to ensure that they comply with all the necessary legislation and documentation which can include removing allowable salvageable parts and ensuring that the Bodyshell is crushed and a Certificate of Destruction V860 is produced. All costs associated with the above procedures will be borne by the customer and will be their personal responsibility.</p>',
		retainRepair : '<p>Please be aware that you will be responsible for any repair work necessary to make the vehicle roadworthy again.</p>',
		collect: ' ensuring we are aware of the vehicle\'s location for collection by our salvage agent Copart',
};

/*==================*/
/**		FUNCTIONS			*/
/*==================*/

function addEvent( id, event, func ){
	// get element by Id or element
	var element = document.getElementById(id) || id;
	// check and anssign appropriate event handler
	if( element.attachEvent ){
		return element.attachEvent( 'on' + event, func );
	} else {
		return element.addEventListener( event, func, false );
	}
}

function removeEvent( id, event, func ){
	// get element by Id or element
	var element = document.getElementById(id) || id;
	// check and anssign appropriate event handler
	if( element.attachEvent ){
		return element.detachEvent( 'on' + event, func );
	} else {
		return element.removeEventListener( event, func, false );
	}
}
	
String.prototype.roundInput = function(){
	// set to zero if negative
	if( this < 0 ){
		 return 0;
	} else {
		// otherwise force 2 nums after decimal points if needed
		return this > ~~this ? parseFloat(this).toFixed(2): ~~this;
	}
}

String.prototype.capName = function(){
	// seperate name words into an array
	var nameArr = this.split(" "),
		capStr = "";
	// iterate through array
	for(var i = 0; i < nameArr.length; i++){
		var str = nameArr[i];
		capStr += " " + str.charAt(0).toUpperCase() + str.slice(1);
	}
	return capStr;
}

function checkId( source ){
	// round number input
	source.value = source.type === "number" ? source.value.roundInput() : source.value ;
	// identify special cases by ID
	switch ( source.id ){
		case "vat":
			return source.value !== "no" ? taxable : "";
		case "phVrn":
			source.value = source.value.toUpperCase();
			return source.value || "XXX";
		case "toName":
			source.value = source.value.capName();
			return source.value ? source.value : "";
		default:
			return source.value;
	}
}

function assignValue( target, source ){
	// uppercase for VRN
	var sourceVal = checkId( source );
	// check if input
	if( target.value ){
		target.value = sourceVal;
	} else {
		target.textContent = sourceVal;
	}
}

function updateSelf(){
	var target = document.getElementById( this.id + "Examp" ),
		targetClass = document.getElementsByClassName( this.id + "Examp" ),
		targetName = document.getElementsByClassName( this.name + "Examp" ) ;
	// check that getElementById returns an item
	if ( target ){
		// assign value to one field
		assignValue( target , this );
	// otherwise search by class instead using id or name
	} else if ( targetClass.length || targetName.length ) {
		target = targetClass.length ? targetClass : targetName;
		// assign values via loop instead
		for( var i = 0; i < target.length; i++ ){
			assignValue( target[i] , this );
		}
	}
}
	
function newElement(type, bootstrapClass, id){
	var newContain = document.createElement(type);
	// add class to div and return
	newContain.className = bootstrapClass;
	newContain.id = id;
	return newContain;
}

function createInput(type, placeholder, classes){
	var newInput = document.createElement("input");
	// set default values for arguments
	type = type || "text",
	placeholder = placeholder || "insert " + type,
	// set attributes
	newInput.type = type;
	newInput.placeholder = placeholder;
	newInput.className = classes;
	return newInput;
}

// ADD COST FUNCTION
function addCost(evt){
	var rowDiv = newElement("div", "form-group row"),
		targetDiv = document.getElementById("otherCosts"),
		nameInputContain = newElement("div", "col-xs-6"),
		amountInputContain = newElement("div", "col-xs-6"),
		amountInputGrp = newElement("div", "input-group"),
		nameInput = createInput("text", 
								"Name - Additional Cost", 
								"form-control otherCostsName"),
		amountInput = createInput("number", 
								  "Amount - Additional Cost", 
								  "form-control otherCostsAmount"),
		deleteBtnSpan = newElement("span", "input-group-btn"),
		deleteBtn = newElement("button", "btn btn-danger");
	// prevent form submit
	evt.preventDefault();
	// create targetDiv if not yet present
	if(!targetDiv){
		var addCostBtnDiv = document.getElementById("addCostBtnDiv");
		// create element for div
		targetDiv = newElement("div", null, "otherCosts");
		addCostBtnDiv.insertAdjacentElement("afterend", targetDiv);
	}
	// add number attr to input
	amountInput.min = 0;
	amountInput.step = 1;
	// add event listeners to inputs
	addEvent( nameInput, "change", updateOtherCosts );
	addEvent( amountInput, "change", updateOtherCosts );
	addEvent( deleteBtn, "click", deleteCost );
	// Assemble button
	deleteBtn.textContent = "X";
	deleteBtnSpan.appendChild(deleteBtn);
	// assemble amount input group
	amountInputGrp.appendChild(amountInput);
	amountInputGrp.appendChild(deleteBtnSpan);
	// add inputs to containers
	nameInputContain.appendChild(nameInput);
	amountInputContain.appendChild(amountInputGrp);
	// add containers to NewDiv
	rowDiv.appendChild(nameInputContain);
	rowDiv.appendChild(amountInputContain);
	// append to additional costs section
	targetDiv.appendChild(rowDiv);
}

function deleteCost(evt){
	var deleteBtn = this,
		// target container for both inputs 4 lvls up
		targetDiv = deleteBtn.parentNode.parentNode.parentNode.parentNode,
		otherCostsContainer = document.getElementById("otherCosts"),
		otherCostsArr = document.getElementsByClassName("otherCostsName");
	// prevent submit
	evt.preventDefault();
	// disconnect event listener
	removeEvent( deleteBtn, "click", deleteCost );
	// check if last cost element
	if( otherCostsArr.length <= 1 ){
		// remove entire container
		otherCostsContainer.remove();
	} else {
		// remove cost element
		targetDiv.remove();
	}
	updateOtherCosts();
	updateTlSect();
}

// CREATE GREETING FUNTION
function greet() {
	var t = new Date(),
		h = t.getHours(),
		msg = "";
	//Decide whether Morning or afternoon and assign to var
	if (h < 12) {
		msg = "Good morning";
	} else {
		msg = "Good afternoon";
	}
	return msg += '<span id="toNameExamp"></span>,';
}

// UPDATE SUBJECT FUNCTION
function createSubject() {
	// create array for subject - text container and counter
	var subjectArr = document.getElementsByClassName('DPA'),
		subjectText = "Offer our services",
		limit = 3;
	// loop through subjectArr
	for(var i = 0; i < subjectArr.length; i++){
		// create var for current loop item
		var itemVal = subjectArr[i].value;
		// check that current element does not push past limit
		if( itemVal && limit > 0){
			var containingDiv = subjectArr[i].parentElement,
				labelText = containingDiv.previousElementSibling.innerText;
			// add label & value to subjectText
			subjectText += " - ";
			subjectText += labelText;
			subjectText += " " +  itemVal;
			limit--;
		}
	}
	return subjectText;
} // end createSubject func

function updateSubject(){
	var subjectText = createSubject();
	document.getElementById("subExamp").textContent = subjectText;
}

// UPDATE BODY FUNCTION
function selectTemplate() {
	// Create text holder var
	var bodyText = "<p>" + greet() + "</p>";
	
	bodyText += '<p>After conducting my own research and conferring with our engineer, we have decided that a pre-accident value of £<span id="pavExamp">0</span> would be an acceptable valuation for your vehicle <span id="phVrnExamp">ABC123</span>. <span id="otherCostsExamp"></span> <span id="vatExamp">' + taxable + '</span> <br/>After the deduction of your £<span id="excessExamp">0</span> excess, we would pay you a total of £<span id="payoutExamp">0</span> for your vehicle, after which ownership of the vehicle will be transferred to ourselves.</p>' +
		'<span id="catExamp"></span>' +
		'<span id="retainExamp"></span>' +
		'<p>If you accept our offer, please confirm your payment details for settlement<span id="collectExamp">' + salvageText.collect + '</span>.</p>' +
		'<p>We will be able to make swifter payment upon acceptance of any offer if you can provide your bank details comprising of sort-code, account number & account name.</p>' +
		'<p id="extraTextExamp"><p>';

	return bodyText;
} // end selectTemplate()
	
function matchOtherCosts(){
	var matches = [],
		otherCostsName = document.getElementsByClassName("otherCostsName"),
		otherCostsAmount = document.getElementsByClassName("otherCostsAmount");
	for( var i = 0; i < otherCostsName.length; i++ ){
		// round number input and update 
		otherCostsAmount[i].value = otherCostsAmount[i].value.roundInput() ;
		// check that both matching inputs have values
		if( otherCostsName[i].value && 
			//convert to number to prevent "0" as string reading as true
			parseFloat( otherCostsAmount[i].value )
		  ){
			// add values to assoc array
			matches.push({
				name: otherCostsName[i].value,
				/* convert amount value to a Number ensures they
				can be added together without coercion to String */
				cost: otherCostsAmount[i].value,
			});
		}
	}
	return matches;
}

// UPDATE OTHER COSTS FUNCTION
function updateOtherCosts(){
	var otherCostsExamp = document.getElementById("otherCostsExamp"),
		matches = matchOtherCosts(),
		payout = calcPayout(),
		msg = "We will also cover the cost of ";	
	// add values to string for display
	for( var i = 0; i < matches.length ; i++ ){
		msg += matches[i].name + " at £" + matches[i].cost;
		// add approbriate connector 
		switch ( matches.length - i ){
			case 1:
				msg += "."; break;
			case 2:
				msg += " and "; break;
			default:
				msg += ", "; break;
		}
	}
	// display message in placeholder
	otherCostsExamp.textContent = matches.length > 0 ? msg : null;
	updateTlSect();
}

function updateTlSect(){
			// Needed inputs 
	var salCat = document.getElementById("salCat"),
		custRetain = document.getElementById("custRetain"),
		// retaining if customer requests and salvage cat has appropriate value
		retaining = custRetain.value && ( salCat.value && salCat.value !== "T" ),
		// set up cost vars
		salDesc = salCat.value ? "<p>" + salvageText[salCat.value] + "</p>" : "",
		salCost = 0,
		payout = 0,
		salPayout = 0;
	
	// calculate costs
	payout = calcPayout();
	salCost = calcSalCost();
	salPayout = payout - salCost;
	// round costs to 2 decimal places
	payout = payout > Math.floor(payout) ? payout.toFixed(2): payout;
	salCost = salCost > Math.floor(salCost) ? salCost.toFixed(2): salCost;
	salPayout = salPayout > Math.floor(salPayout) ? salPayout.toFixed(2): salPayout;
	// check if retain - adjust accordingly
	salDisplay( salCat, salCost, salPayout, retaining );
	// set example fileds to new value
	document.getElementById("payoutExamp").innerText = payout || "0";
	document.getElementById("catExamp").innerHTML = salDesc || "";
}

function calcPayout(){
	var pavVal = document.getElementById("pav").value,
		xsVal = document.getElementById("excess").value,
		matches = matchOtherCosts(),
		otherCostsTotal = 0;
	// calc other costs total
	for( var i = 0; i < matches.length; i++){
		otherCostsTotal += parseFloat(matches[i].cost);
	}
	// return sum
	return (pavVal - xsVal + otherCostsTotal);
}

function calcSalCost(){
	// set variables
	var pavVal = document.getElementById("pav").value,
		salCostType = document.getElementById("salCostType").value,
		salCostVal = document.getElementById("salCostInput").value;
	// calculate sal cost based on input
	switch (salCostType){
		case "percent":
			return (salCostVal / 100) * pavVal;
		case "cost":
			// retun as a number
			return parseFloat(salCostVal);
		default:
			return 0;
	}
}

function salDisplay( salCat, salCost, salPayout, retaining ){
	var salValDiv = document.getElementById("salValDiv"),
		retainExamp = document.getElementById("retainExamp"),
		colEx = document.getElementById("collectExamp"),
		retainState = "retain" + ( salCat.value === "C" || salCat.value === "D" ? "Repair" : "Destroy" );
		// if retaining set display to block
		displayProp = retaining ? "block" : "none" ;
	// hide/show salvage percentage input if necessary
	salValDiv.style.display = displayProp;
	// adjust example text as needed
	if( retaining ){
		// adjust text for retaining
		retainExamp.innerHTML = salvageText.retainStd + salvageText[retainState];
		colEx.innerText = "";
		// set example values
		document.getElementById("salCostExamp").innerText = salCost || "0";
		document.getElementById("salPayoutExamp").innerText = salPayout || "0";
	} else {
		// adjust costs for not retaining
		retainExamp.innerHTML = "";
		colEx.innerText = salCat !== "T" ? salvageText.collect : "";
	}
}

// CREATE EMAIL FUNCTION
function createEmail(){
	if( !validateInputs() || !userConfirm() ){
		return;
	}
	var checkbox = document.getElementById("userConfCheck");
	localStorage.userConfirm = checkbox.checked = true;
	// gather inputs for sending mail
	var toEmail = document.getElementById('toEmail').value,
			ccEmail = document.getElementById('ccEmail').value,
			subject = document.getElementById('subExamp').innerText;
	// copy email body to clipboard using one of two methods
	copyBody();
	// copyToClipboard("bodyExamp");
	
	//construct mailto link
	var message = "mailto: " + toEmail +
								"?cc= " + ccEmail +
								"&subject=" + subject ;
	// execute mailto link
	window.location.href = message; 
}

function copyBody(){
	var placeholder = document.getElementById("copyPlaceholder"),
		body = document.getElementById("bodyExamp");
	// set placeholder value to body and select contents
	placeholder.value = body.innerText;
	placeholder.select();
	// copy and delete contents of placeholder
	document.execCommand("cut");
}

function userConfirm(){
	// create text var for confirm message
	var confText = "***PLEASE READ*** \nThis will copy the body of the generated email to clipboard and open a new message in your email client containing the recipient's email address and the subject line.\nYou can then use CTRL + V to paste in the email body.\nDo you wish to proceed?",
		checkbox = document.getElementById("userConfCheck");
	// check whether checkbox is ticked
	if(checkbox.checked){
		return true;
	}
	//check user wants to copy to clipboard
	return confirm(confText);
}

function validateInputs(){
	try{
		//*  ***IN PROGRESS ERROR CHECKING***
		// create err container array
		var err = [],
			//inputs = document.querySelectorAll("input:not(#userConfCheck):not(.otherCostsName):not(.otherCostsAmount), select:not(#templateSelect)"),
			inputs = document.querySelectorAll("input, select"),
			excess = document.getElementById("excess"),
			pav = document.getElementById("pav"),
			payoutExamp = document.getElementById("payoutExamp"),
			custRetain = document.getElementById("custRetain"),
			salCat = document.getElementById("salCat"),
			salCostType = document.getElementById("salCostType"),
			salCostInput = document.getElementById("salCostInput"),
			// if salPayout is undefined set to payout Examp for err checking purposes
			salPayoutExamp = document.getElementById("salPayoutExamp") || payoutExamp;
		// iterate through inputs
		for(var i = 0; i < inputs.length; i++){
			// create label var for current input
			var containingDiv = inputs[i].parentElement,
				//labelText = containingDiv.previousElementSibling.innerText.slice(0, -1) ,
				prevDiv = containingDiv.previousElementSibling,
				labelText = prevDiv ? prevDiv.textContent.slice(0, -1) : "",
				isEmail = inputs[i].type === "email";
			// check if required & blank
			if( !inputs[i].value && inputs[i].required ){
				errorColor( inputs[i], true );
				err.push("<strong>" + labelText + "</strong> field cannot be empty");
				// check if type is email
			} else if ( inputs[i].value && isEmail) {
				// check if there is err with email & set color based o result
				var emailError = !isEmailValid( inputs[i].value );
				errorColor( inputs[i], emailError );
				// push err message if necessary
				if(emailError){ 
					err.push("Value of <strong>" + labelText + "</strong> is not a valid email");
				}
				// check for valid percentage if vehicle type set to custom
			} else {
				// if not captured by other statements set to standard color
				errorColor( inputs[i], false );
			}
		}
		// check for retain w/ no CAT
		if( custRetain.value && !salCat.value ){
			errorColor( salCat, true );
			err.push("Customer cannot retain the vehicle without a <strong>salvage CAT</strong>");
		}
		// check for valid percentage if vehicle type set to custom
		if( salCostType.value === "percent" && (salCostInput.value < 0 || salCostInput.value > 100) ){
			errorColor( salCostInput, true );
			err.push("<strong>Salvage percentage</strong> should be between 0 and 100");
		}
		// check for negative offers
		if ( payoutExamp.innerText <= 0 || salPayoutExamp.innerText < 0 ) {
			errorColor( excess, true );
			errorColor( pav, true );
			errorColor( salCostType, true );
			errorColor( salCostInput, true );
			err.push("we cannot offer a <strong>negative value!</strong>");
		}	
		// throw err array
		throw err;
	} catch(err){
		// find errDiv on page 
		var errDiv = document.getElementById("errDiv");
		// if there are items in err array
		if(err.length){
			var ul = document.createElement("ul"),
					h3 = document.createElement("h4");
			h3.innerHTML = '<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>' + 
				'<span class="sr-only">Error:</span> ' +
				'Please correct the following errors';
			// reset errDiv and create ul
			errDiv.innerHTML = "";
			errDiv.style.display = "block";
			errDiv.appendChild(h3);
			errDiv.appendChild(ul);
			// loop through err items and list them
			for(var x = 0; x< err.length; x++){
				var li = document.createElement("li");
				ul.appendChild(li);
				li.innerHTML = err[x];
			}
			//redirect to show errors
			window.location.href = "#errDiv";
			return false;
		} else {
			// if no items in err array 
			// remove errDiv from page
			errDiv.style.display = "none";
			return true;
		}
	}
}

function errorColor( target, error ){
	error ? target.classList.add("error") : target.classList.remove("error");
}

function isEmailValid( email ){
	var regEx = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
	return regEx.test(email);
}

/*==================*/
/*		ACTUAL CODE		*/
/*==================*/

// update body text
document.getElementById("bodyExamp").innerHTML = selectTemplate();

/*	EVENT LISTENERS	*/
// add cost function
addEvent( "addCostBtn", "click", addCost );
// update to email preview on type
addEvent( "toEmail", "change", updateSelf );
// update toName
addEvent( "toName", "change", updateSelf );
// update cc email preview on type
addEvent( "ccEmail", "change", updateSelf );
//update vat
addEvent( "vat", "change", updateSelf );
// update ph Vrn
addEvent( "phVrn", "change", updateSelf );
// update Excess
addEvent( "excess", "change", updateSelf );
// update PAV
addEvent( "pav", "change", updateSelf );
// update extra text
addEvent( "extraText", "input", updateSelf );

// Create template on click
addEvent( "sendBtn", "click", createEmail );
	
// update subject when a subject field is altered
[].forEach.call(DPA, function(input){
	debugger
	addEvent(input, "change", updateSubject)
});

// update TL section on update
for(var x = 0; x < allTL.length; x++){
	allTL[x].onchange = updateTlSect;
};

// remember state of checkbox locally
if(window.localStorage){
	var checkbox = document.getElementById("userConfCheck");
	checkbox.checked = localStorage.userConfirm;	
	// change storage on click
	checkbox.onchange = function(){
		if (checkbox.checked){
			localStorage.userConfirm = checkbox.checked;
		} else {
			localStorage.removeItem("userConfirm");
		}
	};
};
	
// end IIFE
})()
            
          
!
999px
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.

Console