/*
 * Javascript Functions for The Villanovan.  Requires prototype.js ver 1.6
 */
var policy = null;
var spinner = null;
var checkTextTimer = null;
var wordCount = 0;
var classifiedIssueCount = 0;
var customMinimum = 3;
var columnsMinimum = 1;
var columnsMaximum = 5;
var inchesMinimum = 1;
var inchesMaximum = 12.5;
var discount = 0.05;
var standardIssues = new Array({ date: new Date('08/28/2008'), description: "" }, 
                           { date: new Date('09/04/2008'), description: "" },
                           { date: new Date('09/11/2008'), description: "" },
                           { date: new Date('09/18/2008'), description: "" },
                           { date: new Date('09/25/2008'), description: "" },
                           { date: new Date('10/02/2008'), description: "" },
                           { date: new Date('10/23/2008'), description: "" },
                           { date: new Date('10/30/2008'), description: "" },
                           { date: new Date('11/06/2008'), description: "" },
                           { date: new Date('11/13/2008'), description: "" },
                           { date: new Date('11/20/2008'), description: "" },
                           { date: new Date('12/04/2008'), description: "" },
                           { date: new Date('12/11/2008'), description: "" },
                           { date: new Date('01/15/2009'), description: "" },
                           { date: new Date('01/22/2009'), description: "" },
                           { date: new Date('01/29/2009'), description: "" },
                           { date: new Date('02/05/2009'), description: "" },
                           { date: new Date('02/12/2009'), description: "" },
                           { date: new Date('02/19/2009'), description: "" },
                           { date: new Date('03/12/2009'), description: "" },
                           { date: new Date('03/19/2009'), description: "" },
                           { date: new Date('03/26/2009'), description: "" },
                           { date: new Date('04/02/2009'), description: "" },
                           { date: new Date('04/16/2009'), description: "" },
                           { date: new Date('04/23/2009'), description: "" },
                           { date: new Date('04/30/2009'), description: "" }
                 );
var specialIssues = new Array({ date: new Date('08/20/2008'), description: "Freshman Orientation Issue" },
                              { date: new Date('10/31/2008'), description: "Basketball Preview" }  
                 );
var cushion = (5 * 24 + 7) * 60 * 60 * 1000;
var prices = new Array('business_bw_predefined', 'business_bw_custom',
                       'business_color_predefined', 'business_color_custom',
                       'business_special', 'classified');
prices['business_bw_predefined'] = new Array('standardC2', 'standardC3', 'standardHP', 'standardFP');
prices['business_bw_predefined']['standardC2'] = new Array('1', '3', '6', '9', '13');
prices['business_bw_predefined']['standardC2']['1'] = 160;
prices['business_bw_predefined']['standardC2']['3'] = 480;
prices['business_bw_predefined']['standardC2']['6'] = 870;
prices['business_bw_predefined']['standardC2']['9'] = 1215;
prices['business_bw_predefined']['standardC2']['13'] = 1690;
prices['business_bw_predefined']['standardC3'] = new Array('1', '3', '6', '9', '13');
prices['business_bw_predefined']['standardC3']['1'] = 240;
prices['business_bw_predefined']['standardC3']['3'] = 720;
prices['business_bw_predefined']['standardC3']['6'] = 1290;
prices['business_bw_predefined']['standardC3']['9'] = 1845;
prices['business_bw_predefined']['standardC3']['13'] = 2535;
prices['business_bw_predefined']['standardHP'] = new Array('1', '3', '6', '9', '13');
prices['business_bw_predefined']['standardHP']['1'] = 330;
prices['business_bw_predefined']['standardHP']['3'] = 990;
prices['business_bw_predefined']['standardHP']['6'] = 1770;
prices['business_bw_predefined']['standardHP']['9'] = 2520;
prices['business_bw_predefined']['standardHP']['13'] = 3380;
prices['business_bw_predefined']['standardFP'] = new Array('1', '3', '6', '9', '13');
prices['business_bw_predefined']['standardFP']['1'] = 595;
prices['business_bw_predefined']['standardFP']['3'] = 1785;
prices['business_bw_predefined']['standardFP']['6'] = 3210;
prices['business_bw_predefined']['standardFP']['9'] = 4545;
prices['business_bw_predefined']['standardFP']['13'] = 6175;
prices['business_color_predefined'] = new Array('standardC2', 'standardC3', 'standardHP', 'standardFP');
prices['business_color_predefined']['standardC2'] = new Array('1', '3', '6', '9', '13');
prices['business_color_predefined']['standardC2']['1'] = 195;
prices['business_color_predefined']['standardC2']['3'] = 585;
prices['business_color_predefined']['standardC2']['6'] = 1050;
prices['business_color_predefined']['standardC2']['9'] = 1485;
prices['business_color_predefined']['standardC2']['13'] = 2015;
prices['business_color_predefined']['standardC3'] = new Array('1', '3', '6', '9', '13');
prices['business_color_predefined']['standardC3']['1'] = 295;
prices['business_color_predefined']['standardC3']['3'] = 885;
prices['business_color_predefined']['standardC3']['6'] = 1590;
prices['business_color_predefined']['standardC3']['9'] = 2250;
prices['business_color_predefined']['standardC3']['13'] = 3055;
prices['business_color_predefined']['standardHP'] = new Array('1', '3', '6', '9', '13');
prices['business_color_predefined']['standardHP']['1'] = 405;
prices['business_color_predefined']['standardHP']['3'] = 1215;
prices['business_color_predefined']['standardHP']['6'] = 2190;
prices['business_color_predefined']['standardHP']['9'] = 3105;
prices['business_color_predefined']['standardHP']['13'] = 4225;
prices['business_color_predefined']['standardFP'] = new Array('1', '3', '6', '9', '13');
prices['business_color_predefined']['standardFP']['1'] = 735;
prices['business_color_predefined']['standardFP']['3'] = 2205;
prices['business_color_predefined']['standardFP']['6'] = 3960;
prices['business_color_predefined']['standardFP']['9'] = 5625;
prices['business_color_predefined']['standardFP']['13'] = 7670;
prices['business_bw_custom'] = 13;
prices['business_color_custom'] = 15;
prices['business_special'] = new Array('specialQP', 'specialHP', 'specialFP');
prices['business_special']['specialQP'] = 210;
prices['business_special']['specialHP'] = prices['business_color_predefined']['standardHP']['1'];
prices['business_special']['specialFP'] = prices['business_color_predefined']['standardFP']['1'];
prices['business_special_handling'] = new Array('alteration','design');
prices['business_special_handling']['alteration'] = 25;
prices['business_special_handling']['design'] = 50;
prices['classified'] = new Array('initial', 'threshold', 'increment');
prices['classified']['initial'] = 15;
prices['classified']['threshold'] = 20;
prices['classified']['increment'] = 0.5;

/*
 * Extends the String class with a trim function
 */
String.prototype.trim = function() {
	return this.replace(/^\s*/,"").replace(/\s*$/,"");
}

/*
 * Creates a popupWindow of the given width and height at center
 * stage.
 */
function popupWindow(url, popupName, width, height) {
  var left = parseInt((screen.availWidth/2) - (width/2));
  var top = parseInt((screen.availHeight/2) - (height/2));
  var windowFeatures = "width=" + width + ",height=" + height + 
        ",status=no,resizable,left=" + left + ",top=" + top + 
        ",screenX=" + left + ",screenY=" + top;
  return open(url, popupName, windowFeatures);
}

/*
 * Clears all radio buttons/checkboxes for a given group on a given
 * form.
 */
function clearButtonGroup(thisForm, buttonType, buttonGroup) {
	$(thisForm).getInputs(buttonType, buttonGroup).find(
	  function(input) {
		  input.checked = false;
	  }
  );
}

/*
 * Gets the element selected by the radio button group or
 * null is no button is selected.
 */
function getRadioGroupSelection(thisForm, radioGroup) {
  var checked = $(thisForm).getInputs('radio', radioGroup).find(
    function(input) {
    	return input.checked;
    }
  );
  return (checked) ? checked : null;
}

/*
 * Counts the number of checkboxes selected is the given checkbox
 * group.
 */
function getCheckboxSelectionCount(thisForm, checkboxGroup) {
	var count = 0;
	var checked = $(thisForm).getInputs('checkbox', checkboxGroup).find(
    function(input) {
    	if(input.checked) {
    		count++;
    	};
    }
  );
  return count;
}

/*
 * Returns a number rounded to 2 decimal places.
 */
function formatPrice(amount) {
	return (Math.round(100*amount)/100).toFixed(2);
}

/*
 * Returns a number to which the form discount is applied.
 */
function discountPrice(amount) {
	return formatPrice(amount * (1-discount));
}

/*
 * Returns true if the number of issues indicated conforms to allowed
 * package size.
 */
function isBusinessPackage(issueCount) {
	return(issueCount == 1
	 || issueCount == 3
	 || issueCount == 6
	 || issueCount == 9
	 || issueCount == 13)
}

/*
 * On page load, for the form page only. The form inputs are reset.  The
 * location of the spinner, which provides a processing animated gif is
 * provided but hidden.  Checkboxes for all the available ad run dates for
 * both standard and special issues and for business and classified ad are
 * created.  All the business and classified ad details are hidden.  Prices
 * for special issues and for special handling are added because they aren't
 * dynamic (i.e. they don't change with user inputs) although they are
 * hidden.  Listeners are established for all the static inputs on the form.
 */
function startup() {
	if($("vuForms")) {
	 $("vuForms").reset();
	 spinner = $("statusIndicator");
   spinner.style.visibility = "hidden";
	 displayRunDates("standard", calculateRemainingIssues("standard"), displayStandardIssueCount);
	 displayRunDates("special", calculateRemainingIssues("special"), calculateBusinessCost);
	 displayRunDates("classified", calculateRemainingIssues("standard"), calculateClassifiedCost);
	 hideBusiness();
	 hideClassified();
	 displaySpecialIssuePrices();
	 displaySpecialHandlingPrices();
	 Event.observe('business', 'click', showBusiness, false);
	 Event.observe('classified', 'click', showClassified, false);
	 Event.observe('standard', 'click', showStandard, false);
	 Event.observe('special', 'click', showSpecial, false);
	 Event.observe('predefined', 'click', showPredefined, false);
	 Event.observe('custom', 'click', showCustom, false);
	 Event.observe('bw', 'click', displayBusinessPrices, false);
	 Event.observe('color', 'click', displayBusinessPrices, false);
	 Event.observe('standardC2', 'click', calculateBusinessCost, false);
	 Event.observe('standardC3', 'click', calculateBusinessCost, false);
	 Event.observe('standardHP', 'click', calculateBusinessCost, false);
	 Event.observe('standardFP', 'click', calculateBusinessCost, false);
	 Event.observe('specialQP', 'click', calculateBusinessCost, false);
	 Event.observe('specialHP', 'click', calculateBusinessCost, false);
	 Event.observe('specialFP', 'click', calculateBusinessCost, false);
	 Event.observe('columns', 'click', limitInches, false);
	 Event.observe('inches', 'click', limitColumns, false);
	 Event.observe('alteration', 'click', calculateBusinessCost, false);
	 Event.observe('design', 'click', calculateBusinessCost, false);
	 Event.observe('adContent', 'keyup', calculateClassifiedCost, false);
	 Event.observe('adContent', 'blur', calculateClassifiedCost, false);
	 Event.observe('adContent', 'change', calculateClassifiedCost, false);
	}
}

/*
 * Displays the initial fieldset for the business ad flow and hides/clears
 * classified ad info.
 */
function showBusiness() {
	hideClassified();
	$("businessAd").style.display = "block";
}

function hideBusiness() {
	$("businessAd").style.display = "none";
	clearButtonGroup("vuForms", "radio", "issueType");
	hideStandard();
	hideSpecial();
}

/*
 * Displays the fieldset for the classified ad details and the purchase
 * button and hides/clears business info.  Opening the classified fieldset
 * starts a 0.5 sec interval timers that calls the handler to calculate
 * the classified ad cost.  This is done to get arould the possibility of
 * a user providing classified ad content in the form of a cut and paste
 * operation (a right mouse click).  The interval timer is turned off
 * whenever the user chooses the business ad flow.
 */
function showClassified() {
	hideBusiness();
	$("classifiedAd").style.display = "block";
	showPurchase();
	checkTextTimer = setInterval("calculateClassifiedCost();", 500);
}

function hideClassified() {
	$("classifiedAd").style.display = "none";
	clearButtonGroup("vuForms", "checkbox", "classifiedRunDates");
	$("adContent").value = "";
	hidePurchase();
	clearInterval(checkTextTimer);
}

/*
 * Displays the fieldset for the standard issue business ad details and
 * hides/clears the special issue business ad info.
 */
function showStandard() {
	hideSpecial();
	$("standardIssue").style.display = "block";
}

function hideStandard() {
	$("standardIssue").style.display = "none";
	clearButtonGroup("vuForms", "radio", "bwcolor");
	clearButtonGroup("vuForms", "radio", "issues");
	clearButtonGroup("vuForms", "radio", "layout");
	clearButtonGroup("vuForms", "checkbox", "standardRunDates");
	hidePredefined();
	hideCustom();
}

/*
 * Displays the fieldsets for the special issue business ad details, the
 * special handling details and the purchase button and hides/clears the
 * standard issue business ad info. 
 */
function showSpecial() {
	hideStandard();
	$("specialIssue").style.display = "block";
	showSpecialHandling();
	showPurchase();
}

function hideSpecial() {
	$("specialIssue").style.display = "none";
	hideSpecialHandling();
	hidePurchase();
	clearButtonGroup("vuForms", "radio", "specialSize");
	clearButtonGroup("vuForms", "checkbox", "specialRunDates");
}

/*
 * Displays the fieldsets for the standard issue business ad predefined
 * layouts, the special handling details and the purhcase button and
 * hides/clears the standard issue business ad custom layout info.
 */
function showPredefined() {
	hideCustom();
	$("predefinedLayout").style.display = "block";
	showSpecialHandling();
	showPurchase();
  displayBusinessPrices();
}

function hidePredefined() {
	$("predefinedLayout").style.display = "none";
	hideSpecialHandling();
	hidePurchase();
	clearButtonGroup("vuForms", "radio", "standardSize");
}

/*
 * Displays the fieldsets for the standard issue business ad custom
 * layout, the special handling details and the purchase button and
 * hides/clears the standard issue business ad predefined layout info.
 */
function showCustom() {
  hidePredefined();
	$("customLayout").style.display = "block";
	showSpecialHandling();
	showPurchase();
	limitColumns();
	limitInches();
	displayBusinessPrices();
}

function hideCustom() {
	$("customLayout").style.display = "none";
	hidePurchase();
	$("columns").value = 0;
	$("inches").value = 0;
	hideSpecialHandling();
}

/*
 * Display the special handling fieldset - applys to business ads only.
 */
function showSpecialHandling() {
	$("specialHandling").style.display = "block";
}

function hideSpecialHandling() {
	clearButtonGroup("vuForms", "checkbox", "alteration");
	clearButtonGroup("vuForms", "checkbox", "design");
	$("specialHandling").style.display = "none";
}

/*
 * Displays the total cost and the purchase button.
 */
function showPurchase() {
	$("purchase").style.display = "block";
}

function hidePurchase() {
	$("purchase").style.display = "none";
	clearCost();
}

/*
 * Called during the page load only and is used to extract and return only
 * those issue dates for which the deadline to submit ads has not
 * passed (i.e. 5 pm Monday prior to the Thursday publication date).
 */
function calculateRemainingIssues(issueType) {
	var deadline = null;
	var remainingIssues = new Array();
	var issueDates = (issueType == "special") ? specialIssues : standardIssues;
	$A(issueDates).each(
    function(issueDate) {
		  deadline = issueDate["date"] - cushion;
		  if(new Date() <= deadline) {
			  remainingIssues.push(issueDate);
		 }
    }
  );
	return remainingIssues;
}

/*
 * Collects the remaining run dates for the type of display (business-standard
 * issue, business-special issue, classified-standard issue) and displays
 * them with checkboxes in a 2 column format.  Each checkbox is assigned
 * an onclick handler defined by the callback parameter.
 */
function displayRunDates(type, remainingIssues, callback) {
	var side = null;
	var template = new Template("<div>" +
	    "<input type='checkbox' class='checkbox' name='#{type}RunDates' id='#{type}RunDate#{i}' value='#{remainingRunDate}'/>" +
	    "<label for='#{type}RunDate#{i}'>" +
	    "<span class='date_note'>#{remainingRunDate} #{description}</span>" +
	    "</label>" +
	    "</div>");
	side = $$("#" + type + "RunDates .form_entry_left")[0];
	side.innerHTML = "";
	for(var i = 0; i < Math.round(remainingIssues.length/2); i++) {
	  displayRunDate(side, template, type, i, remainingIssues[i], callback);
	}
	side = $$("#" + type + "RunDates .form_entry_right")[0];
	side.innerHTML = "";
  for(var i = Math.round(remainingIssues.length/2); i < remainingIssues.length; i++) {
	  displayRunDate(side, template, type, i, remainingIssues[i], callback);
	}
}

function displayRunDate(side, template, type, i, issue, callback) {
	remainingRunDate = (issue["date"].getMonth() + 1) + "/" + issue["date"].getDate() + "/" + issue["date"].getFullYear();
	var runDate = template.evaluate({type: type, i: i, remainingRunDate: remainingRunDate, description:issue["description"]});
	new Insertion.Bottom(side, runDate);
	Event.observe(type + 'RunDate' + i, 'click', callback, false);
}

/*
 * Displays the number of business standard issues selected by the user
 * and provides a warning if the count doesn't conform to an allowed
 * package size.  Business prices are re-displayed according to the new
 * issue count or not displayed in the case of a non-conforming issue
 * count.
 */
function displayStandardIssueCount() {
  var issueCount = getCheckboxSelectionCount("vuForms", "standardRunDates");
	$("standardIssueCount").innerHTML = issueCount + " <span id='issueNote' class='form_note'></span>";
	$("standardIssues").value = issueCount;
	if(!isBusinessPackage(issueCount)) {
		Element.addClassName($("standardIssueCount"), 'bad_package');
		$('issueNote').innerHTML = "(Only packages of 3, 6, 9, or 13 issues allowed!)"
	}
	else {
		Element.removeClassName($("standardIssueCount"), 'bad_package');
	}
	if(issueCount == 1) {
		$('issueNote').innerHTML = "(Allowed for time-sensitive ads only!)"
	}
	displayBusinessPrices();
}

/*
 * Creates and displays an inches droplist which is set so as to
 * deny to the user, the option of choosing a combination of columns
 * and inches that would amount to less than 3 column-inches.  A listener
 * is additionally set on the droplist so that a selection here will
 * call a handler to limit the column droplist selections appropriately.
 * Finally the business cost is recalculated in the event that enough
 * information has been given to calculate the cost.
 */
function limitInches() {
	var inchesLimit = inchesMinimum;
	var columns = $("columns").value;
	var inches = $("inches").value;
	
	if(columns && columns > 0) {
	  inchesLimit = Math.max(Math.round(2.0*customMinimum/columns)/2, inchesMinimum);
	}
	
	$("inchesDropList").innerHTML = "<select name='inches' id='inches'>" +
			                            "</select>" +
			                            "<span id='priceCustomTotal' class='price_note'>" +
			                            "</span>";
	var element = $("inches");
	var	inchOption = "<option value='0' selected='selected'>Choose one...</option>";
	new Insertion.Bottom(element, inchOption);
  for(var i = inchesLimit; i <= inchesMaximum ; i += 0.5) {
		inchOption = "<option value='" + i + "'>" + i + "</option>";
		new Insertion.Bottom(element, inchOption);
	}
	if(inches && inches > 0) {
		$("inches").value = inches;
	}
	else {
		$("vuForms").inches.selectedIndex = 0;
	}
	Event.observe('inches', 'click', limitColumns, false);
	calculateBusinessCost();
}

/*
 * Creates and displays an columns droplist which is set so as to
 * deny to the user, the option of choosing a combination of columns
 * and inches that would amount to less than 3 column-inches.  A listener
 * is additionally set on the droplist so that a selection here will
 * call a handler to limit the inch droplist selections appropriately.
 * Finally the business cost is recalculated in the event that enough
 * information has been given to calculate the cost.
 */
function limitColumns() {
	var columnsLimit = columnsMinimum;
	var columns = $("columns").value;
	var inches = $("inches").value;
	if(inches && inches > 0) {
	 columnsLimit = Math.max(Math.round(customMinimum/inches), columnsMinimum);
	}
	$("columnsDropList").innerHTML = "<select name='columns' id='columns'>" +
			                             "</select>" +
			                             "<span id='priceCustomUnit' class='price_note'>" +
			                             "</span>";
	var element = $("columns");
	var columnOption = "<option value='0'>Choose one...</option>";
	new Insertion.Bottom(element, columnOption);
  for(var i = columnsLimit; i <= columnsMaximum ; i++) {
	 columnOption = "<option value='" + i + "'>" + i + "</option>";
	 new Insertion.Bottom(element, columnOption);
	}
	if(columns && columns > 0) {
		$("columns").value = columns;
	}
	else {
		$("vuForms").columns.selectedIndex = 0;
	}
	Event.observe('columns', 'click', limitInches, false);
	displayBusinessPrices();
}

/*
 * Display of business prices is determined by selections for
 * bw/color, run dates, layout type and whether the number of
 * issues selected reflect an allowed business package.  Business
 * cost is re-calculated in the event that enough information
 * already exists upon which to base the cost.
 */
function displayBusinessPrices() {
	var bwcolor = getRadioGroupSelection("vuForms", "bwcolor");
	var issueCount = $F("standardIssues");
	var layout = getRadioGroupSelection("vuForms", "layout");
	if(bwcolor != null && isBusinessPackage(issueCount)) {
	  if(layout != null && $F(layout) == "predefined") {
		  displayPredefinedPrices($F(bwcolor), issueCount);
	  }
	  else if(layout != null && $F(layout) == "custom") {
		  displayCustomPrices($F(bwcolor));
	  }
	  calculateBusinessCost();
	}
	else {
		clearPredefinedPrices();
    clearCustomPrices();
		clearCost();
	} 
}

function displayPredefinedPrices(bwcolor, issues) {
  $("standardPriceC2").innerHTML = "(<span class='originalPrice'>$" + prices['business_' + bwcolor + '_predefined']['standardC2'][issues] + "</span> $" + discountPrice(prices['business_' + bwcolor + '_predefined']['standardC2'][issues]) + ")";
	$("standardPriceC3").innerHTML = "(<span class='originalPrice'>$" + prices['business_' + bwcolor + '_predefined']['standardC3'][issues] + "</span> $" + discountPrice(prices['business_' + bwcolor + '_predefined']['standardC3'][issues]) + ")";
	$("standardPriceHP").innerHTML = "(<span class='originalPrice'>$" + prices['business_' + bwcolor + '_predefined']['standardHP'][issues] + "</span> $" + discountPrice(prices['business_' + bwcolor + '_predefined']['standardHP'][issues]) + ")";
	$("standardPriceFP").innerHTML = "(<span class='originalPrice'>$" + prices['business_' + bwcolor + '_predefined']['standardFP'][issues] + "</span> $" + discountPrice(prices['business_' + bwcolor + '_predefined']['standardFP'][issues]) + ")";
}

function clearPredefinedPrices() {
	$("standardPriceC2").innerHTML = "";
	$("standardPriceC3").innerHTML = "";
	$("standardPriceHP").innerHTML = "";
	$("standardPriceFP").innerHTML = "";
}

function displayCustomPrices(bwcolor) {
	$("priceCustomUnit").innerHTML = " (<span class='originalPrice'>$" + prices['business_' + bwcolor + '_custom'] + "</span> $" + discountPrice(prices['business_' + bwcolor + '_custom']) + " /column-inch/issue)";
}

function clearCustomPrices() {
	$("priceCustomUnit").innerHTML = "";
}

/*
 * Called only once at startup because the user's selections
 * have no impact on amounts or visibility.
 */
function displaySpecialIssuePrices() {
	$("specialPriceQP").innerHTML = "(<span class='originalPrice'>$" + prices['business_special']['specialQP'] + "</span> $" + discountPrice(prices['business_special']['specialQP']) + ")";
	$("specialPriceHP").innerHTML = "(<span class='originalPrice'>$" + prices['business_special']['specialHP'] + "</span> $" + discountPrice(prices['business_special']['specialHP']) + ")";
	$("specialPriceFP").innerHTML = "(<span class='originalPrice'>$" + prices['business_special']['specialFP'] + "</span> $" + discountPrice(prices['business_special']['specialFP']) + ")";
}

/*
 * Called only once at startup because the user's selections
 * have no impact on amounts or visibility.
 */
function displaySpecialHandlingPrices() {
	$("alterationPrice").innerHTML = "<span class='originalPrice'>$" + prices['business_special_handling']['alteration'] + "</span> $" + discountPrice(prices['business_special_handling']['alteration']);
	$("designPrice").innerHTML = "<span class='originalPrice'>$" + prices['business_special_handling']['design'] + "</span> $" + discountPrice(prices['business_special_handling']['design']);
}

/*
 * Called whether a button click has the potential to alter the business
 * cost.  The ad type must be business.  For standard issues, the bw/color,
 * run date and layout selections must be made and the number of run dates
 * selected must conform to an allowed business package.  Special handling
 * costs are added in once the predefined, custom, or special costs are
 * determined.  If the cost is non-zero, it is display alongside the submit
 * button.
 */
function calculateBusinessCost() {
	var cost = 0;
	var adType = getRadioGroupSelection("vuForms", "adType");
	if(adType != null  && $F(adType) == "business") {
		var issueType = getRadioGroupSelection("vuForms", "issueType");
		if(issueType != null && $F(issueType) == "standard") {
	    var bwcolor = getRadioGroupSelection("vuForms", "bwcolor");
	    var issueCount = $F("standardIssues");
	    var layout = getRadioGroupSelection("vuForms", "layout");
	    if(bwcolor != null && isBusinessPackage(issueCount)) {
	      if(layout != null && $F(layout) == "predefined") {
          cost = calculatePredefinedCost($F(bwcolor), issueCount);
	      }
	      else if(layout != null && $F(layout) == "custom") {
	        cost = calculateCustomCost($F(bwcolor), issueCount);
	      }
	      cost += calculateSpecialHandlingCost();
	    }
		}
		else if(issueType != null && $F(issueType) == "special") {
			cost = calculateSpecialIssueCost() + calculateSpecialHandlingCost();
		}
	}
	if(cost > 0) {
		displayCost("business", cost);
	}
}

/*
 * The predefined cost is determined based upon bw/color, issue count
 * and size selections.  If no size is provided, a cost of 0 is returned.
 */
function calculatePredefinedCost(bwcolor, issueCount) {
  var cost = 0;
  var size = getRadioGroupSelection("vuForms", "standardSize");
  if(size != null) {
    cost = new Number(prices['business_' + bwcolor + '_predefined'][$(size).id][issueCount]);
  }
  return cost;
}

/*
 * The custom cost is determined based upon bw/color, issue count
 * and the size of the ad in column-inches.  If either of the column
 * or inch values is 0, a cost of 0 is returned.
 */
function calculateCustomCost(bwcolor, issueCount) {
	var cost = 0;
  var columns = $F("columns");
	var inches = $F("inches");
	if(columns && columns > 0 && inches && inches > 0) {
	  cost = new Number(prices['business_' + bwcolor + '_custom']) * columns * inches * issueCount;
		$("priceCustomTotal").innerHTML = " ($" + (cost * (1-discount)) + " total)";
	}
	return cost;
}

/*
 * The special issue cost is determined based upon issue count and the
 * size of the ad.  If either the issue count is 0 or the ad size is not
 * selected, a cost of 0 is returned.
 */
function calculateSpecialIssueCost() {
	var cost = 0;
	var issueCount = getCheckboxSelectionCount("vuForms", "specialRunDates"); 
  var size = getRadioGroupSelection("vuForms", "specialSize");
  if(size != null) {
    cost = new Number(prices['business_special'][$(size).id]) * new Number(issueCount);
  }
  return cost;
}

/*
 * The special handling cost is determined based upon whether either or
 * both of the special handling checkboxes is selected.  If neither is
 * selected, a cost of 0 is returned.
 */
function calculateSpecialHandlingCost() {
	var cost = 0;
	if($("alteration").checked) {
		cost += prices['business_special_handling']['alteration'];
	}
	if($("design").checked) {
		cost += prices['business_special_handling']['design'];
	}
	return cost;
}

/*
 * Displays the cost (discounted for business ad) alongside the purchase
 * button.  The hidden input is used to convey the data to the backend app.
 * If the cost is 0, the cost display is cleared.
 */
function displayCost(type, cost) {
	if(cost > 0) {
    actualCost = type=="business" ? discountPrice(cost) : formatPrice(cost);
    $("displayCost").innerHTML = "$" + actualCost
	  $("cost").value = actualCost;
	}
	else {
		clearCost();
	}
}

function clearCost() {
	$("priceCustomTotal").innerHTML = "";
	$("displayCost").innerHTML = "N/A";
	$("cost").value = 0;
}

/*
 * If the word count for the ad content or the issue count have changed
 * since since handler was last activated, the cost is re-evaluated based
 * upon word count and issue count.  If either is 0, so is the cost.
 */
function calculateClassifiedCost() {
	var cost = 0;
	var content = $F("adContent");
	var newWordCount = content.length > 0 ? Math.round(content.split(/\b/).length/2) : 0;
	var newClassifiedIssueCount = getCheckboxSelectionCount("vuForms", "classifiedRunDates");
	if(newWordCount != wordCount || newClassifiedIssueCount != classifiedIssueCount) {
		if(newWordCount > 0) {
		  cost = prices["classified"]["initial"];
		}
		var overage = newWordCount - prices["classified"]["threshold"];
		if(overage > 0) {
			cost += overage * prices["classified"]["increment"];
		}
		cost *= newClassifiedIssueCount;
		$("priceClassifiedTotal").innerHTML = "([$" + prices["classified"]["initial"] + " (first 20 words) + $" + prices["classified"]["increment"] + " x " + Math.max(overage, 0) + " (additional words)] x " + newClassifiedIssueCount + " issues = $" + cost + ")";
		displayCost("classified", cost);
	}
	wordCount = newWordCount;
	classifiedIssueCount = newClassifiedIssueCount;
}

/*
 * This form validation contains several conditional validations,
 * enclosed within switch statements.
 */
function validateForm(thisForm) {
  var selected;
  var field;
  var pattern;

  // Contact Name Validation
  field = thisForm.contactName.value.trim();
  if(field.length == 0) {
    alert("Please provide a contact name.");
    thisForm.contactName.focus();
    return false;
  }
  pattern = /^[a-zA-Z\-\.\s']*$/;
  if(!field.match(pattern)) {
    alert("Please use only spaces, letters, dashes, apostrophes, or periods in the contact name.");
    thisForm.contactName.focus();
    return false;
  }
  // Email Address Validation
  field = thisForm.emailAddress.value.trim();
  if(field == "") {
    alert("Please provide your email address.");
    thisForm.emailAddress.focus();
    return false;
  }
  pattern = /^.*@[\w\-\.]+\.\w+$/;
  if(!field.match(pattern)) {
    alert("Please enter a valid email address.");
    thisForm.emailAddress.focus();
    return false;
  }
  // Phone Validation
  if(thisForm.phone.value.trim().length == 0) {
    alert("Please provde a contact phone number.");
    thisForm.phone.focus();
    return false;
  }
  // Street Address 1 Validation
  field = thisForm.street1.value.trim();
  if(field.length == 0) {
    alert("Please provide a street address.");
    thisForm.street1.focus();
    return false;
  }
  pattern = /^[\s\w\-\.#,]*$/;
  if(!field.match(pattern)) {
    alert("Please use only spaces, digits, letters, dashes, commas, periods, or hashes in the street address.");
    thisForm.street1.focus();
    return false;
  }
  // City Validation
  field = thisForm.city.value.trim();
  if(field.length == 0) {
    alert("Please provide a city.");
    thisForm.city.focus();
    return false;
  }
  pattern = /^[\s\w\-\.#]*$/;
  if(!field.match(pattern)) {
    alert("Please use only spaces, digits, letters, dashes, periods, or hashes in the city.");
    thisForm.city.focus();
    return false;
  }
  // State Validation
  if(thisForm.state.selectedIndex < 1) {
    alert("Please select one of the state options.");
    thisForm.state.focus();
    return false;
  }
  // Zip Validation
  field = thisForm.zip.value.trim();
  if(field.length == 0) {
    alert("Please provide a zip.");
    thisForm.zip.focus();
    return false;
  }
  pattern = /^\d{5}(-\d{4})?$/;
  if(!field.match(pattern)) {
    alert("Please indicate the zip in either the 5-digit (nnnnn) or the 9-digit (nnnnn-nnnn) format.");
    thisForm.zip.focus();
    return false;
  }

  // Ad Type Validation
  field = getRadioGroupSelection(thisForm, "adType");
  if(field == null) {
  	alert("Please select the ad type");
  	thisForm.business.focus();
  	return false;
  }
  
  var adType = field.value;
  switch(adType) {
  	case "business":
  	  // Issue Type Validation
  	  field = getRadioGroupSelection(thisForm, "issueType");
  	  if(field == null) {
  	    alert("Please select the issue type");
  	    thisForm.standard.focus();
  	    return false;
  	  }
  	
  	  var issueType = field.value;
  	  switch(issueType) {
  		  case "standard":
          // Color Validation
          field = getRadioGroupSelection(thisForm, "bwcolor");  
          if(field == null) {
  	        alert("Please select B/W or Color");
  	        thisForm.bw.focus();
  	        return false;
          }
          // Business Issue Count
          field = thisForm.standardIssues.value.trim();
          if(field.length == 0 || !isBusinessPackage(field)) {
          	alert("Please select 1, 3, 6, 9 or 13 issue dates on which the ad is to run");
        	  thisForm.standardRunDate0.focus();
        	  return false;
          }
          // Layout Validation
          field = getRadioGroupSelection(thisForm, "layout");  
          if(field == null) {
  	        alert("Please select an ad layout");
  	        thisForm.predefined.focus();
  	        return false;
          }
        
          var layout = field.value;
          switch(layout) {
            case "predefined":
    	        // Ad Size Validation
    	        field = getRadioGroupSelection(thisForm, "standardSize");
    	        if(field == null) {
        		    alert("Please select an ad size.");
        		    thisForm.c2.focus();
        		    return false;
      	      }
      	      break;
            case "custom":
      	      // Column Validation
      	      field = thisForm.columns.value.trim();
      	      if(field.length == 0 || field == "0" ) {
      	    	alert("Please select the number of columns the ad should span.");
      	    	thisForm.columns.focus();
      	    	return false;
      	    }
    	      // Height Validation
    	      field = thisForm.inches.value.trim();
    	      if(field.length == 0 || field == "0" ) {
    	      	alert("Please specify the column height in inches.");
    	      	thisForm.inches.focus();
    	      	return false;
    	      }
    	      break;
          default:
    	      alert("The layout selection is limited to predefined or custom.  Please choose either of those options.");
    	      thisForm.predefined.focus();
    	      return false;
        }
        break;
  		  case "special":
  		    // Special Issue Count Validation
  		    field = getCheckboxSelectionCount(thisForm, "specialRunDates");
  		    if(field == 0) {
    	      alert("Please select one or more issue dates on which the ad is to run");
    	      thisForm.specialRunDate0.focus();
    	      return false;
  		    }
        	// Ad Size Validation
    	    field = getRadioGroupSelection(thisForm, "specialSize");
    	    if(field == null) {
            alert("Please select an ad size.");
          	thisForm.special_qp.focus();
          	return false;
          }
          break
        default:
      	  alert("The issue type selection is limited to standard or special.  Please choose either of those options.");
          thisForm.predefined.focus();
          return false;
      }
      break;  
    case "classified":
      // Classified Issue Count Validation
      calculateClassifiedCost();
      if(classifiedIssueCount == 0) {
    	  alert("Please select one or more issue dates on which the ad is to run");
    	  thisForm.classifiedRunDate0.focus();
    	  return false;
      }
      // Ad Content Validation
      field = thisForm.adContent.value.trim();
      if(field.length == 0) {
        alert("Please specify the ad content.");
    	  thisForm.adContent.focus();
    	  return false;
      }
      break;
    default:
    	alert("The ad type selection is limited to business or classified.  Please choose either of those options.");
    	thisForm.business.focus();
    	return false;
  }
  
  policy = popupWindow("policy.htm?template=no", "Policies", 650, 525);
  return false;
}

function acceptPolicy() {
	policy.close();
  $("subcommand").disabled = true;
  spinner.style.visibility = "visible";
  $("vuForms").submit();
}

function declinePolicy() {
	policy.close();
}