/** KLRUwidget.js
 * A device that takes up a portion of a non-Kimbia Web page, and offers a user
 * interface to Kimbia features. I.e., a form can have graphical representations 
 * as one or more widgets. This widget can present a form in multiple pages or
 * sections.
 * @requires widgetFramework.js,   aka KimbiaWidgetFramework
 * @requires anywhereFramework.js, aka the object "_Kimbia".
 */

var kwf = KimbiaWidgetFramework;

/** _KimbiaWidget Makes an object to use the Kimbia framework.
 * @constructor
 */
function _KimbiaWidget() {
	this.campaign = null;
	this.event = null;
	this.showDescriptions = true;
	this.payment = null;
	this.lastPriceResponse = null;
	this.lastPaymentResponse = null;
	this.mailingAddress = null;
	this.signup = null;
	this.signupType = "event";
	this.useAdditionalDonation = false;
	this.profile = null;
	this.newDiscount = "";
	this.metaData = new Array();
	this.regTypeIdOther = null;
}


/**	Prepares the widget for first use. 
 */
_KimbiaWidget.prototype.initialize = function() {
	this.campaign = Kimbia.getCampaign();
	this.payment = Kimbia.newPayment();
	this.payment.creditCard.monthExpires = 1;
	this.payment.creditCard.yearExpires = 2008;
	this.profile = Kimbia.getProfile();
	KimbiaWidget.setShowStyles(false);
	KimbiaWidget.setWidth(170);
	var cssDeclarations = "div#kimbiaDiv select.k_select{width:149px;}div#kimbiaDiv div.contactInfo div.k_radioButtons label{width:5em;float:left; text-indent:6px;margin: 6px 0 0 20px;padding:0px;}div#kimbiaDiv div.contactInfo input.k_text#kMoneyId{float:none;width:82px;clear:right;} div#kimbiaDiv label { font-size:1em; } div#kimbiaDiv select.k_select { font-size: 1em; } div#kimbiaDiv div.k_radioButtons label{text-indent:6px;}div#kimbiaDiv div.k_radioButtons input#kimbtn0{margin-left:20px;margin-top:6px} div#kimbiaDiv select.k_select option {font-size: 1em} div#kimbiaDiv ul.k_messages li.k_message { font-size:1em; margin:0px; padding:0px }div#kimbiaDiv div.contactInfo div.k_radioButtons{width:150px} div#kimbiaDiv div.divKtext {margin-bottom:0px !important;margin-bottom:4px}";
	kwf.addStyleTagToHead(cssDeclarations, "fixK");

	KimbiaWidget.addStyleElementToHead("http://www.klru.org/support/memberdrive/klru_sidebar.css");
};

/** Sets the signupType (is this a fundraiser or event?) 
 * @param eventId
 **/
_KimbiaWidget.prototype.loadEvent = function() {
	this.event = this.campaign.getEvent(this.saveEventId);
	if (this.event == null) {
		this.event = this.campaign.getFundraiser(this.saveEventId);
		this.signupType = "fundraiser";
	} else {
		this.signupType = "event";
	}
};

/** Loads the form needed by the signupType. No longer determines signupType
 * @see loadEvent
 */
_KimbiaWidget.prototype.loadForm = function() {
	if (this.signupType == "event") {
		this.reg = Kimbia.newRegistration(this.event);
		this.signup = this.reg;
		this.cart.addRegistration(this.reg);
		this.signup.registrationTypeId = "" + this.event.getDefaultRegistrationTypeId();
		this.signup.donationAmount = 0;
	} else {
		this.donation = Kimbia.newDonation(this.event);
		this.signup = this.donation;
		this.cart.addDonation(this.donation);
		this.donation.donationAmount = 0;
		if (this.event.getHasSuggestedAmounts()) {
			this.donation.suggestedAmountId = this.event.getDefaultSuggestedAmountId();
		}
	}
	this.signup.person = Kimbia.newPerson();
}

_KimbiaWidget.prototype.setAnswer = function(questionId, answer) {
	question = this.profile.getQuestion(questionId);
	if (question != null) {
		for (questionPos in this.profile.getQuestions()) {
			if(! this.profile.getQuestions().hasOwnProperty(questionPos)) { continue; }
			var question = this.profile.getQuestion(questionPos);
			if (this.signup.person.answers[questionId] == null) {
				this.signup.person.answers[questionId] = Kimbia.newAnswer(question);
			}
			realAnswer = this.signup.person.answers[questionId];
		}
	}
	if (question == null) {
		var question = this.getQuestionById(questionId);
		var realAnswer = this.getAnswerForQuestion(question);
	}
	if (realAnswer != null) {
		realAnswer.answer = answer;
	}
}

_KimbiaWidget.prototype.setShowDescriptions = function(showDescriptions) {
	this.showDescriptions = showDescriptions;
}

_KimbiaWidget.prototype.setBaseStylesheet = function(url) {
	KimbiaWidgetFramework.styleElementHref = url;
}

_KimbiaWidget.prototype.setDiv = function(divId) {
	KimbiaWidgetFramework.setDiv(divId);
}

_KimbiaWidget.prototype.setShowStyles = function(showStyles) {
	KimbiaWidgetFramework.setShowStyles(showStyles);
}

_KimbiaWidget.prototype.setShowHTMLtitle = function(showHTMLtitle) {
	KimbiaWidgetFramework.setShowHTMLtitle(showHTMLtitle);
}

_KimbiaWidget.prototype.setHeight = function(height) {
	KimbiaWidgetFramework.setHeight(height);
}

_KimbiaWidget.prototype.setWidth = function(width) {
	KimbiaWidgetFramework.setWidth(width);
}
_KimbiaWidget.prototype.addStyleElementToHead = function(styleUrl){
	KimbiaWidgetFramework.addStyleElementToHead(styleUrl);
}

/** Sets labelWrapLength, the variable that determines which CSS rule to apply to determine desired wrapping behavior.
 * @param {Object} labelWrapLength 
 */
_KimbiaWidget.prototype.setLabelWrapLength = function(labelWrapLength) {
	KimbiaWidgetFramework.setLabelWrapLength(labelWrapLength);
}

		

/** Applies arbitrary name-value pairs that describe the widget **/
_KimbiaWidget.prototype.addMetaData = function(key, value) {
	metaData = new _Kimbia_metaData();
	metaData.key = key;
	metaData.value = value;
	if (this.cart == null) {
		this.metaData.push(metaData);
	} else {
		this.cart.addMetaData(key, value);
	}
}

/** Persists metadata from the widget into the cart. **/
_KimbiaWidget.prototype.saveMetaData = function() {
	this.cart.metaData = this.metaData;
}

/** isCurrentlyOpen tests whether the even or fundraiser is available for input.
 *  if not, it prints messages.
 */
 _KimbiaWidget.prototype.isCurrentlyOpen = function() {
	if (this.event.getEventClosedMessage() != null) {
		KimbiaWidgetFramework.append("<p class='k_message'>"+this.event.getEventClosedMessage()+"</p>");
		KimbiaWidgetFramework.flush();
		return false;
	}
	return true;
}

/** Runs the form based on very few parameters.
 * @param {Object} campaignId
 * @param {Object} eventId
 */
_KimbiaWidget.prototype.runForm = function(campaignId, eventId) {
	this.saveEventId = eventId;	
	Kimbia.initialize(campaignId, "KimbiaWidget.runFormCallback", eventId);
}

/** Function called after initialize() */
_KimbiaWidget.prototype.runFormCallback = function() {
	this.initialize();
	this.loadEvent();
	this.cart = Kimbia.newCart();
	if(this.isCurrentlyOpen()){
		this.loadForm();
		this.showProfilePage();
	}
	KimbiaWidgetFramework.widgetHasLoadedAtLeastOnce = true;
}

/** Page 1 - Profile
 * hardcoded invocation of a page or section.
 * @param registrantNumber - 0-based position of first person in collection, optional, defaults to 0.
 **/
_KimbiaWidget.prototype.showProfilePage = function() {	
	KimbiaWidgetFramework.clearDiv();
	KimbiaWidgetFramework.showMessages("Please complete: ");
	
	if (this.showDescriptions) {
		KimbiaWidgetFramework.append("<div id='eventDescription'>" + KimbiaWidgetFramework.unescapeHTML(this.event.getDescription()) + "</div>");
	}
	KimbiaWidgetFramework.append("<div class='formBlock clearfix contactInfo' id='k_donationLevels'>");
	KimbiaWidgetFramework.append("<form name='k_profile' id='k_profile'>"); // Never gets submitted as a form
/*  no events -- see KLRUwidget.js code if events are needed */
	if (this.signupType == "fundraiser") {	//Adds fundraiser-specific questions, subheads, and money inputs.
		if (this.event.getHasSuggestedAmounts()) {
			KimbiaWidgetFramework.append("<div class='k_radioButtons'>");
			if (this.signup.suggestedAmountId != 0) {
				this.signup.donationAmount = "";
			}
			for (suggestedAmountId in this.event.getSuggestedAmounts()) {
				if(! this.event.getSuggestedAmounts().hasOwnProperty(suggestedAmountId)) { continue; }
				suggestedAmount = this.event.getSuggestedAmount(suggestedAmountId);
				labelField = suggestedAmount.getName();
				if (suggestedAmount.getAmount() != "") {
					labelField += " " + suggestedAmount.getAmount();
				}
				KimbiaWidgetFramework.addRadioButton(labelField, "suggestedAmounts", suggestedAmount.getId(), "KimbiaWidget.signup.suggestedAmountId");
			}
			if (this.event.getAllowDonorAmount()) { // generates a pair of controls: free-text gift amount input and radio button.
				KimbiaWidgetFramework.append(this.addRadioButton("Other", "suggestedAmounts", "0", "KimbiaWidget.signup.suggestedAmountId",false,"","white-space:nowrap;margin:0px;display:block;clear:both"));
				KimbiaWidgetFramework.addMoneyInput("", "KimbiaWidget.signup.donationAmount","kMoneyId");
				KimbiaWidgetFramework.append("</label>");
			}
		} else { // adds a single input for a donation of fixed amount.
			KimbiaWidgetFramework.addMoneyInput("Donation", "KimbiaWidget.signup.donationAmount");
		}
		KimbiaWidgetFramework.append("</div>");
	}
	for (questionId in this.profile.getQuestions()) {
		if(! this.profile.getQuestions().hasOwnProperty(questionId)) { continue; }
		var pQuestion = this.profile.getQuestion(questionId);
		if (this.signup.person.answers[questionId] == null) { //adds the answer to the collection the question IF missing.
			this.signup.person.answers[questionId] = Kimbia.newAnswer(pQuestion);
		}
		// adds the question / answer pair to the framework object.
		this.addQuestion("KimbiaWidget.profile.getQuestion(" + questionId + ")", "KimbiaWidget.signup.person.answers[" + questionId + "]", false);
	}

	KimbiaWidgetFramework.append("<span class='disclaimer'>&nbsp;&nbsp;* Indicates required input</span>");
	KimbiaWidgetFramework.append("<br class='clr'/>");
	KimbiaWidgetFramework.append("<label></label><a href='javascript:KimbiaWidget.profilePageContinue()' class='k_button forward' title='Donate Now'>&nbsp;</a>");	
	KimbiaWidgetFramework.append("</form>");
	
	KimbiaWidgetFramework.append("</div>");
	KimbiaWidgetFramework.flush();
/*	for (element in document.forms['k_profile'].elements){
		if(element.blur)element.blur();
	}
	*/
}

_KimbiaWidget.prototype.addRadioButton = function(labelField, groupId, value, field, showBreak, description, styleDeclarations) {
	if(typeof(description)== 'undefined'){description="";}
	var s = "<label for='kimbtn" + value + "' style='"+ styleDeclarations + "' >"
		+ "<input type='radio' name='radio" + groupId + "' value='" + value 
		+ "' class='k_radioCB' onclick='" + field + " = \"" + value + "\";' ";
	if (eval(field) == value) {
		s += " checked='checked'";
	}
	s += " id='kimbtn" + value + "'";
	if(labelField == "Other") {
		s += " onfocus='this.click();document.getElementById(\"kMoneyId\").focus();'"
		s += "/>"+ labelField +" "+ description;
	} else {
		s += "/>"+ labelField +" "+ description + "</label>";
	}
	if (showBreak) {
		s += "<br class='clr'/>";
	}
	return s;
}

/* Makes text inputs with auto-hide over-labels. Thanks to alistapart.com */
_KimbiaWidget.prototype.getTextInput = function(labelField, field, id, extraAttributes) {
	if (eval(field) == null) { // if the object referenced by the string is null
		eval(field + " = ''"); // set it to blank
	}
	if(typeof(console)!=='undefined')console.log(id);
	var s = "";
	s += '<div class="divKtext" id="div' + id +'">'; 
	s += this.getLabel(labelField, id, field);
	s += "<input type='text' class='k_text' id='k_" + id + "' name='" + id +"' title='"+labelField
	+"' value='" + kwf.removeQuotes(field) 
	+ "' onblur='" + field + "=this.value;if(this.value===\"\"){KimbiaWidget.hideLabel(this.id, false);}' " +
	" onfocus='KimbiaWidget.hideLabel(this.id, true);' "
	+extraAttributes+" /></div>";
	return s;
}

_KimbiaWidget.prototype.getLabel = function(labelField, id, field) {
	if (KimbiaWidgetFramework.isEmpty(labelField)) {
		return "";
	}
	var cls = "overlabel";
	if (eval(field) == ''){
		cls='overlabel-apply';
	}
	return '<label class="'+cls+'" for="k_' +id+'" '
	+'onclick="var id,field;id = this.getAttribute(\'for\');if (id&&(field=document.getElementById(id))){field.focus();}" '
	+'>'+labelField+'</label>';
}
_KimbiaWidget.prototype.addCreditCardInput = function(labelField, id, field) {
	if (eval(field) == null) {
		eval(field + " = ''");
	}
	kwf.append('<div class="divKtext" id="div' + id +'">');
	kwf.append(this.getLabel(labelField, id, field));
	kwf.append("<input type='text' class='k_text' name='creditCard' value='" + kwf.removeQuotes(field)+"'" 
	  + " onblur='if(this.value===\"\"){KimbiaWidget.hideLabel(this.id, false);}else{" 
	  + field + "=KimbiaWidgetFramework.formatCreditCardNumber(this.value);this.value = " 
	  + field + ";}' "
	  +" onfocus='KimbiaWidget.hideLabel(this.id, true);' id='k_" +id+ "' />"
	  +"</div>");
}



_KimbiaWidget.prototype.hideLabel = function(field_id, hide) {
  var field_for;
  var labels = document.getElementsByTagName('label');
  for (var i = 0; i < labels.length; i++) {
    field_for = labels[i].htmlFor || labels[i].getAttribute('for');
    if (field_for == field_id) {
      labels[i].style.textIndent = (hide) ? '-1000px' : '0px';
      return true;
    }
  }
};


/** Returns Postal Address inputs as an HTML String. **/
_KimbiaWidget.prototype.getMailingAddress = function(field, showBreak, id) {
	var s = "";
	s += this.getTextInput("Street Address*",        field + ".street1", id +"-street1");
	s += "<br class='clr'/>";
	s += this.getTextInput("Street Address (cont.)", field + ".street2", id +"-street2");
	s += "<br class='clr'/>";
	s += this.getTextInput("City*",                  field + ".city", id + "-city");
	s += "<br class='clr'/>";
	s += this.getStateInput(field, showBreak, id + "-state");
	s += "<br class='clr'/>";
	s += this.getTextInput("Zip/Post Code*",         field + ".zip", id+"-zip");
	return s;
}

_KimbiaWidget.prototype.getStateInput = function(field, showBreak, id) {
	var s = "";
	var	l = "State*";
	var state = eval(field + ".state");
	field = field + ".state";
	s += "<select onblur='" + field + " = this[this.selectedIndex].value' class='k_select'"
	  +" id='k_" + id + "' name='" + id +"' title='"+l
	  +"'>";
	    s += '<option value="" class="defaultOption" selected="selected">&nbsp;&nbsp;State*</option>';
        s += kwf.getOption(state, 'AL', 'Alabama'); 
        s += kwf.getOption(state, 'AK', 'Alaska'); 
        s += kwf.getOption(state, 'AS', 'American Samoa'); 
        s += kwf.getOption(state, 'AZ', 'Arizona'); 
        s += kwf.getOption(state, 'AR', 'Arkansas'); 
        s += kwf.getOption(state, 'CA', 'California'); 
        s += kwf.getOption(state, 'CO', 'Colorado'); 
        s += kwf.getOption(state, 'CT', 'Connecticut'); 
        s += kwf.getOption(state, 'DE', 'Delaware'); 
        s += kwf.getOption(state, 'DC', 'District of Columbia'); 
        s += kwf.getOption(state, 'FL', 'Florida'); 
        s += kwf.getOption(state, 'GA', 'Georgia'); 
        s += kwf.getOption(state, 'GU', 'Guam'); 
        s += kwf.getOption(state, 'HI', 'Hawaii'); 
        s += kwf.getOption(state, 'ID', 'Idaho'); 
        s += kwf.getOption(state, 'IL', 'Illinois'); 
        s += kwf.getOption(state, 'IN', 'Indiana'); 
        s += kwf.getOption(state, 'IA', 'Iowa'); 
        s += kwf.getOption(state, 'KS', 'Kansas'); 
        s += kwf.getOption(state, 'KY', 'Kentucky'); 
        s += kwf.getOption(state, 'LA', 'Louisiana'); 
        s += kwf.getOption(state, 'ME', 'Maine'); 
        s += kwf.getOption(state, 'MH', 'Marshall Islands'); 
        s += kwf.getOption(state, 'MD', 'Maryland'); 
        s += kwf.getOption(state, 'MA', 'Massachusetts'); 
        s += kwf.getOption(state, 'MI', 'Michigan'); 
        s += kwf.getOption(state, 'MN', 'Minnesota'); 
        s += kwf.getOption(state, 'MS', 'Mississippi'); 
        s += kwf.getOption(state, 'MO', 'Missouri'); 
        s += kwf.getOption(state, 'MT', 'Montana'); 
        s += kwf.getOption(state, 'NE', 'Nebraska'); 
        s += kwf.getOption(state, 'NV', 'Nevada'); 
        s += kwf.getOption(state, 'NH', 'New Hampshire'); 
        s += kwf.getOption(state, 'NJ', 'New Jersey'); 
        s += kwf.getOption(state, 'NM', 'New Mexico'); 
        s += kwf.getOption(state, 'NY', 'New York'); 
        s += kwf.getOption(state, 'NC', 'North Carolina'); 
        s += kwf.getOption(state, 'ND', 'North Dakota'); 
        s += kwf.getOption(state, 'OH', 'Ohio'); 
        s += kwf.getOption(state, 'OK', 'Oklahoma'); 
        s += kwf.getOption(state, 'OR', 'Oregon'); 
        s += kwf.getOption(state, 'PW', 'Palau'); 
        s += kwf.getOption(state, 'PA', 'Pennsylvania'); 
        s += kwf.getOption(state, 'PR', 'Puerto Rico'); 
        s += kwf.getOption(state, 'RI', 'Rhode Island'); 
        s += kwf.getOption(state, 'SC', 'South Carolina'); 
        s += kwf.getOption(state, 'SD', 'South Dakota'); 
        s += kwf.getOption(state, 'TN', 'Tennessee'); 
        s += kwf.getOption(state, 'TX', 'Texas'); 
        s += kwf.getOption(state, 'UT', 'Utah'); 
        s += kwf.getOption(state, 'VT', 'Vermont'); 
        s += kwf.getOption(state, 'VI', 'Virgin Islands'); 
        s += kwf.getOption(state, 'VA', 'Virginia'); 
        s += kwf.getOption(state, 'WA', 'Washington'); 
        s += kwf.getOption(state, 'WV', 'West Virginia'); 
        s += kwf.getOption(state, 'WI', 'Wisconsin'); 
        s += kwf.getOption(state, 'WY', 'Wyoming');
	s += "</select>";
	return s;	
}



/** Validation routine that sets requirements for leaving the current section. */
_KimbiaWidget.prototype.isProfileComplete = function() {
	if (this.profile == null || this.signup == null || this.signup.person == null) {
		return false;
	}
	profileComplete = true;
	for (questionId in this.profile.getQuestions()) {
		if(! this.profile.getQuestions().hasOwnProperty(questionId)) { continue; }
		var question = this.profile.getQuestion(questionId);
		if (! question.getRequired()) {
			continue;
		}
		answer = this.signup.person.answers[questionId];
		if (answer==null || !KimbiaWidgetFramework.questionAnswered(question, answer, "KimbiaWidget.signup.person.answers[" + questionId + "]")) {
			profileComplete = false;
			KimbiaWidgetFramework.messages.push(question.getLabel());
			continue;
		}
	}		
	return profileComplete;
}

/** Determines whether the user is allowed to proceed to the next page, based on validation.
 * Adds validation of user-specified amount, where possible.
 * Triggers appropriate NEXT page, if conditions are met.
 */
_KimbiaWidget.prototype.profilePageContinue = function() {
	
	if (! this.isProfileComplete()) {
		this.showProfilePage();
		return;
	}
	
	if (this.signupType == "fundraiser") {
		if ((this.donation.suggestedAmountId == null || this.donation.suggestedAmountId == 0) 
		&& this.event.getDonorAmountMinimum() != null 
		&& ((this.event.getDonorAmountMinimum() * 1) > KimbiaWidgetFramework.getMoneyAsDouble(this.signup.donationAmount))) {
			KimbiaWidgetFramework.messages.push("Please enter a donation of at least " + KimbiaWidgetFramework.formatMoney(this.event.getDonorAmountMinimum()));
			this.showProfilePage();
			return;
		}
	}

	if (this.event.getHasQuestions()) {
		this.showQuestionPage();
	} else {
		this.showPaymentPage();
	}
}

/**
 * Page 2 - Questions
 * hardcoded invocation of a page or section.
 * Tests whether this widget needs registration questions, and gets them.
 **/
_KimbiaWidget.prototype.getQuestions = function() {
	if (this.signupType == "fundraiser") {
		return this.event.getQuestions();
	}
	if (! this.event.getHasRegistrationTypes()) {
		return this.event.getQuestions();
	}
	regType = this.event.getRegistrationType(this.signup.registrationTypeId);
	return regType.getQuestions();
}

/** Loops through answers in this widget's signup, and attempts to match one to the
 * supplied question.
 * @param {Object} question
 */
_KimbiaWidget.prototype.getAnswerForQuestion = function(question) {
	for (answerId in this.signup.answers) {
		if(! this.signup.answers.hasOwnProperty(answerId)) { continue; }
		answer = this.signup.answers[answerId];
		if (answer.questionId == question.id) {
			return answer;
		}
	}
	answer = Kimbia.newAnswer(question);
	this.signup.answers.push(answer);
	return answer;
}

_KimbiaWidget.prototype.getAnswerStringForQuestion = function(question) {
	answer = this.getAnswerForQuestion(question); // just for the side-effect of creating it if its not there
	for (answerId in this.signup.answers) {
		if(! this.signup.answers.hasOwnProperty(answerId)) { continue; }
		answer = this.signup.answers[answerId];
		if (answer.questionId == question.id) {
			return "KimbiaWidget.signup.answers[" + answerId + "]";
		}
	}
	return null; // should never happen
}

_KimbiaWidget.prototype.showQuestionPage = function(registrantNumber) {
	if(KimbiaWidgetFramework.isEmpty(registrantNumber)){
		registrantNumber = -1;
	}
	KimbiaWidgetFramework.clearDiv();
	KimbiaWidgetFramework.showMessages("Please complete: ");
	
	KimbiaWidgetFramework.append("<form>");
	var fullName = this.getDefaultName(this.signup.person); // current registrant's name
	var profileHeadline = "Questions for "+fullName+"<span class='required'> (* required)</span>";
	KimbiaWidgetFramework.append("<span class='k_headline'>" + profileHeadline + "</span>");
    for (var qId in this.getQuestions()) {
        if(! this.getQuestions().hasOwnProperty(qId)) { continue; }
	    var qPageQ = this.getQuestions()[qId];
        
		var labelField = qPageQ.getLabel();
		this.addQuestion("KimbiaWidget.getQuestions()[" + qId + "]", this.getAnswerStringForQuestion(qPageQ),true);		
	}

	KimbiaWidgetFramework.append("<br class='clr'/>");
	KimbiaWidgetFramework.append("<label></label><a href='javascript:KimbiaWidget.showProfilePage()' class='k_button back'>Back</a>");
	if(this.event.getAllowMultipleSignups()){
		KimbiaWidgetFramework.append("<a href='javascript:KimbiaWidget.questionPageContinue(\"addAnother\")' class='k_button forward'>Add Another Registrant</a>");
	}
	KimbiaWidgetFramework.append("<a href='javascript:KimbiaWidget.questionPageContinue()' class='k_button forward'>Continue</a>");
	KimbiaWidgetFramework.append("<br class='clr'/>");
	KimbiaWidgetFramework.append("</form>");
	KimbiaWidgetFramework.flush();
}

/** Checks that required questions are answered, adds to error message collection when they are not,
 * and returns results found.
 * @return questionsComplete - boolean - whether the required questions are answered.
 */
_KimbiaWidget.prototype.areQuestionsComplete = function() {	
	questionsComplete = true;
	for (questionId in this.getQuestions()) {
		if(! this.getQuestions().hasOwnProperty(questionId)) {continue;}// Skips "toJSONArrray", or any other non-question object in array.
		var question = this.getQuestions()[questionId];
		if (! question.getRequired()) {
			continue;
		}
		if (this.getAnswerForQuestion(question) == null) {
			questionsComplete = false;
			KimbiaWidgetFramework.messages.push(question.getLabel());
			continue;
		}
		answer = this.getAnswerForQuestion(question);
		if (! KimbiaWidgetFramework.questionAnswered(question, answer, this.getAnswerStringForQuestion(question))) {
			questionsComplete = false;
			KimbiaWidgetFramework.messages.push(question.getLabel());
			continue;
		}
	}		
	return questionsComplete;
}

/** Checks if required questions are answered, and if so, and triggers display of payment page.
 * @param doNext the callback 
 */
_KimbiaWidget.prototype.questionPageContinue = function(doNext) {
	if (! this.areQuestionsComplete()) {
		this.showQuestionPage();
		return;
	}
	switch(doNext){
		case 'addAnother':
			this.loadForm();
			this.showProfilePage();
			break;
		default:
			this.showPaymentPage();
			break;
	}
	
}


/** Page 3 - Payment
 * hardcoded invocation of a page or section.
 **/
_KimbiaWidget.prototype.showPaymentPage = function() {
	if (! KimbiaWidgetFramework.isEmpty(this.newDiscount)) {
		this.cart.addDiscountCode(this.newDiscount);
		this.newDiscount = "";
	}
	this.priceCart();
}
/** Wrapper for Kimbia pricing routine */
_KimbiaWidget.prototype.priceCart = function() {
	if (this.signupType == "fundraiser") {
		if (this.signup.suggestedAmountId != null && this.signup.suggestedAmountId != 0) {
			this.signup.donationAmount = this.event.getSuggestedAmount(this.signup.suggestedAmountId).getAmount();
		}
	}
	Kimbia.priceCart(this.cart, "KimbiaWidget.priceCartCallback");
}

/** Function to handle response from Kimbia pricing call. Responds with one of the
 * following:
 *   error message page
 *   payment data page
 *   question page
 * @param {Object} response
 */
_KimbiaWidget.prototype.priceCartCallback = function(response) {
	this.lastPriceResponse = response;
	this.payment.amount = this.lastPriceResponse.discountedPrice;
    var i = 0;
	while (true) {
        msg = response.messages[i];
        if (msg == null) {
            break;
        }
        KimbiaWidgetFramework.messages.push(msg);
        ++i;
	}
	if (response.success) {
		this.showPaymentPageData();
	} else {
		this.showQuestionPage();
	}
}



/** Displays tally of items in cart, offers input for discount codes and payment types. */
_KimbiaWidget.prototype.showPaymentPageData = function() {

	KimbiaWidgetFramework.clearDiv();
	KimbiaWidgetFramework.showMessages("Please attend to the following: ");
	KimbiaWidgetFramework.append("<div class='formBlock clearfix pay'>");
	KimbiaWidgetFramework.append("<form name='pay'>");


	var isEventWithRegistrations =(this.signupType == "event" 
		&& typeof(KimbiaWidget.cart.registrations[0])!='undefined'
		&& KimbiaWidget.cart.registrations[0].answers.length > 0);
	KimbiaWidgetFramework.append("<span class='k_headline'>Payment Details</span>");
	if (KimbiaWidgetFramework.isEmpty(this.payment.creditCard.name)) {
		if(isEventWithRegistrations){		
			this.payment.creditCard.name = this.getDefaultName(KimbiaWidget.cart.registrations[0].person);
		}else{
			this.payment.creditCard.name = this.getDefaultName();
		}
	}
	if (KimbiaWidgetFramework.isEmptyAddress(this.payment.creditCard.address)) {
		this.payment.creditCard.address = Kimbia.newAddress();
		this.payment.creditCard.address.country = 'US';
		var a = null;
		if(isEventWithRegistrations){
			a = this.getDefaultMailingAddress(KimbiaWidget.cart.registrations[0].person);
		}else{
			a = this.getDefaultMailingAddress();
		}	
		if (a != null) {
			this.payment.creditCard.address.street1 = a.street1;
			this.payment.creditCard.address.street2 = a.street2;
			this.payment.creditCard.address.city = a.city;
			this.payment.creditCard.address.state = a.state;
			this.payment.creditCard.address.zip = a.zip;
			this.payment.creditCard.address.country = a.country;
		}
	}
	
	KimbiaWidgetFramework.append(this.getMailingAddress("KimbiaWidget.payment.creditCard.address",true,"KimbiaWidget.payment.creditCard.address"));
	
	this.addCreditCardInput("Credit Card Number*", "ccnum", "KimbiaWidget.payment.creditCard.accountNumber");
	kwf.append("<br class='clr'/>");
	var ccverif = this.getTextInput("Verification Code*", "KimbiaWidget.payment.creditCard.verification",'ccverif', ' maxlength="4" ');
	KimbiaWidgetFramework.append(ccverif);
	

	var s = "<label class='defaultOption'>&nbsp;&nbsp;Expiration Date*</label>" +
			"<select onblur='KimbiaWidget.payment.creditCard.monthExpires = this[this.selectedIndex].value' class='k_select'>" +
			"<option value='1'" + (this.payment.creditCard.monthExpires ==  1 ? " selected='selected'" : "") + ">01 - January</option>" + 
			"<option value='2'" + (this.payment.creditCard.monthExpires ==  2 ? " selected='selected'" : "") + ">02 - February</option>" + 
			"<option value='3'" + (this.payment.creditCard.monthExpires ==  3 ? " selected='selected'" : "") + ">03 - March</option>" + 
			"<option value='4'" + (this.payment.creditCard.monthExpires ==  4 ? " selected='selected'" : "") + ">04 - April</option>" + 
			"<option value='5'" + (this.payment.creditCard.monthExpires ==  5 ? " selected='selected'" : "") + ">05 - May</option>" + 
			"<option value='6'" + (this.payment.creditCard.monthExpires ==  6 ? " selected='selected'" : "") + ">06 - June</option>" + 
			"<option value='7'" + (this.payment.creditCard.monthExpires ==  7 ? " selected='selected'" : "") + ">07 - July</option>" + 
			"<option value='8'" + (this.payment.creditCard.monthExpires ==  8 ? " selected='selected'" : "") + ">08 - August</option>" + 
			"<option value='9'" + (this.payment.creditCard.monthExpires ==  9 ? " selected='selected'" : "") + ">09 - September</option>" + 
			"<option value='10'" + (this.payment.creditCard.monthExpires == 10 ? " selected='selected'" : "") + ">10 - October</option>" + 
			"<option value='11'" + (this.payment.creditCard.monthExpires == 11 ? " selected='selected'" : "") + ">11 - November</option>" + 
			"<option value='12'" + (this.payment.creditCard.monthExpires == 12 ? " selected='selected'" : "") + ">12 - December</option>" + 
			"</select>";
	KimbiaWidgetFramework.append(s);
	s = 	"<select onblur='KimbiaWidget.payment.creditCard.yearExpires = this[this.selectedIndex].value' class='k_select'>" +
			"<option value='2008'" + (this.payment.creditCard.yearExpires == 2008 ? " selected" : "") + ">2008</option>" + 
			"<option value='2009'" + (this.payment.creditCard.yearExpires == 2009 ? " selected" : "") + ">2009</option>" + 
			"<option value='2010'" + (this.payment.creditCard.yearExpires == 2010 ? " selected" : "") + ">2010</option>" + 
			"<option value='2011'" + (this.payment.creditCard.yearExpires == 2011 ? " selected" : "") + ">2011</option>" + 
			"<option value='2012'" + (this.payment.creditCard.yearExpires == 2012 ? " selected" : "") + ">2012</option>" + 
			"<option value='2013'" + (this.payment.creditCard.yearExpires == 2013 ? " selected" : "") + ">2013</option>" + 
			"<option value='2014'" + (this.payment.creditCard.yearExpires == 2014 ? " selected" : "") + ">2014</option>" + 
			"<option value='2015'" + (this.payment.creditCard.yearExpires == 2015 ? " selected" : "") + ">2015</option>" + 
			"<option value='2016'" + (this.payment.creditCard.yearExpires == 2016 ? " selected" : "") + ">2016</option>" + 
			"<option value='2017'" + (this.payment.creditCard.yearExpires == 2017 ? " selected" : "") + ">2017</option>" + 
			"</select><br class='clr'/>";
	KimbiaWidgetFramework.append(s);
	
	this.payment.amount = this.lastPriceResponse.discountedPrice;
	
	
	KimbiaWidgetFramework.append("<a id='k_checkout_back_link' href='javascript:KimbiaWidget.paymentPageBack();' class='k_button back'>Back</a>");
	KimbiaWidgetFramework.append("<a id='k_checkout_forward_link' href='javascript:this.disabled=true;KimbiaWidget.showConfirmationPage()' class='k_button forward'>I'm Finished</a>");
	KimbiaWidgetFramework.append("<br class='clr'/>");
	KimbiaWidgetFramework.append("<span class='disclaimer'>&nbsp;&nbsp;* Indicates required input</span>");
	KimbiaWidgetFramework.append("<br class='clr'/>");
	KimbiaWidgetFramework.append("</form>");
	KimbiaWidgetFramework.append("</div>");
	KimbiaWidgetFramework.flush();
}

/** Link href to the "prior" page (either a questions page or a profile page). **/
_KimbiaWidget.prototype.paymentPageBack = function() {
	if (this.event.getHasQuestions()) {
		this.showQuestionPage();
	} else {
		this.showProfilePage();
	}
}



// Utility methods
_KimbiaWidget.prototype.getDefaultMailingAddress = function(person) {
	if (person == null) {
		person = this.signup.person;
	}
	for (questionId in this.profile.getQuestions()) {
		if(! this.profile.getQuestions().hasOwnProperty(questionId)) { continue; }
		question = this.profile.getQuestion(questionId);
		if (question.getResponseFormat() == "defaultMailingAddress") {
			return person.answers[questionId].answer;
		}
	}
	return null;
}

/** Concatenates first and last name, with a space between. **/
_KimbiaWidget.prototype.getDefaultName = function(person) {
	if (person == null) {
		person = this.signup.person;
	}
	var familyName = "";
	var givenName = "";
	for (questionId in this.profile.getQuestions()) {
		if(! this.profile.getQuestions().hasOwnProperty(questionId)) { continue; }
		question = this.profile.getQuestion(questionId);
		if (question.getResponseFormat() == "familyName") {
		familyName = person.answers[questionId].answer;
		}
		if (question.getResponseFormat() == "givenName") {
			givenName = person.answers[questionId].answer;
		}
	}
		return KimbiaWidgetFramework.trimString(givenName + " " + familyName);
}
/** If first or last name are blank, returns blank. else Returns first and last name, with a space between. **/
_KimbiaWidget.prototype.getCompleteName = function(person) {
	if (person == null) {
		person = this.signup.person;
	}
	var familyName = "";
	var givenName = "";
	for (questionId in this.profile.getQuestions()) {
		if(! this.profile.getQuestions().hasOwnProperty(questionId)) { continue; }
		question = this.profile.getQuestion(questionId);
		if (question.getResponseFormat() == "familyName") {
			familyName = person.answers[questionId].answer;
			if(KimbiaWidgetFramework.isEmpty(familyName)){return "";}
		}
		if (question.getResponseFormat() == "givenName") {
			givenName = person.answers[questionId].answer;
			if(KimbiaWidgetFramework.isEmpty(givenName)){return "";}
		}
	}
	return KimbiaWidgetFramework.trimString(givenName + " " + familyName);
}
/** Validates payment input, and then either displays a page of transaction details for review, OR
 * applies the payment.
 */
_KimbiaWidget.prototype.showConfirmationPage = function() {
	// Disables the page navigation so that we can't be called twice in a row.
	KimbiaWidgetFramework.disableLinkById('k_checkout_back_link');
	KimbiaWidgetFramework.disableLinkById('k_checkout_forward_link');
	
	var doPayment = true;
	
	if (KimbiaWidgetFramework.isEmpty(this.payment.creditCard.name)) {
		doPayment = false;
	}
	
	if (KimbiaWidgetFramework.isEmpty(this.payment.creditCard.address.street1)) {
		KimbiaWidgetFramework.messages.push("\"Street Address\" is required.");
		doPayment = false;
	}
	
	if (KimbiaWidgetFramework.isEmpty(this.payment.creditCard.address.city)) {
		KimbiaWidgetFramework.messages.push("\"City\" is required.");
		doPayment = false;
	}
	
	if (KimbiaWidgetFramework.isEmpty(this.payment.creditCard.address.state)) {
		KimbiaWidgetFramework.messages.push("\"State/Province\" is required.");
		doPayment = false;
	}
	
	if (KimbiaWidgetFramework.isEmpty(this.payment.creditCard.address.zip)) {
		KimbiaWidgetFramework.messages.push("\"Zip/Postal Code\" is required.");
		doPayment = false;
	}

	if (! KimbiaWidgetFramework.isCreditCardNumber(this.payment.creditCard.accountNumber)) {
		KimbiaWidgetFramework.messages.push("A valid credit card number is required");
		doPayment = false;
	}

	if (KimbiaWidgetFramework.isEmpty(this.payment.creditCard.verification)) {
		KimbiaWidgetFramework.messages.push("\"Verification Code\" is required.");
		doPayment = false;
	} else if (this.payment.creditCard.verification.length < 3 || this.payment.creditCard.verification.length > 4) {
		KimbiaWidgetFramework.messages.push("Your verification code must be 3 or 4 numbers long");
		doPayment = false;
	}

	if (!doPayment) {
		this.showPaymentPage();
		return;
	}
	
	this.applyPayment();
}
/**
 * Displays a page reviewing the transaction that just occurred.
 */
_KimbiaWidget.prototype.showConfirmationPageData = function() {
	this.setDiv("kimbiaInnerDiv");
	KimbiaWidgetFramework.clearDiv();
	KimbiaWidgetFramework.append("<a id='k_errMarker'></a>");
	KimbiaWidgetFramework.showMessages();
	KimbiaWidgetFramework.append("<div id='k_summary'>");
	KimbiaWidgetFramework.append("<span class='k_headline'>Transaction Summary</span>");
	// KLRU requires different success text in widget, versus email.
	var customSignupText = "<p>Thank you for your gift to KLRU. Through your support, KLRU is able to serve Central Texas with the quality television programming and Beyond TV activities that contribute to the region's celebrated quality of life. </p>"
		+"<p>We are committed to providing the best in television programming and community service.  Supporters like you are indispensable partners in that effort.  Thank you for investing in KLRU. </p>"
		+"<p>You will receive a confirmation email for this gift.</p>";
	KimbiaWidgetFramework.append(customSignupText);

	KimbiaWidgetFramework.append("<div id='k_transaction'>Transaction Code: " + this.lastPaymentResponse.transactionCode + "</div><br class='clr'/>");
	KimbiaWidgetFramework.append("<p>You were charged a total of " + this.lastPriceResponse.discountedPrice + " and we've emailed you a receipt.</p>");

	KimbiaWidgetFramework.append("</div>");
	KimbiaWidgetFramework.flush();
}
/** Wrapper for Kimbia.applyPayment() **/
_KimbiaWidget.prototype.applyPayment = function() {
	Kimbia.applyPayment(this.cart, this.payment, "KimbiaWidget.applyPaymentCallback");
}
/** Callback function to handle reponse from payment **/
_KimbiaWidget.prototype.applyPaymentCallback = function(response) {
	this.lastPaymentResponse = response;
    var i = 0;
	while (true) {
        msg = response.messages[i];
        if (msg == null) {
            break;
        }
        KimbiaWidgetFramework.messages.push(msg);
        ++i;
	}
	if (response.success) {
		this.showConfirmationPageData();
	} else {
		this.showPaymentPage();
	}
}

/* reads question, display it and put the answer into signup.answer */
_KimbiaWidget.prototype.addQuestion = function(questionString, answerString, showBreak) {
	// Answer was created with Kimbia.newAnswer(question) - answerString is its setLocation
	var question2 = eval(questionString);
	var answer = eval(answerString);
	var mc = false;
	for (var choiceId in question2.getChoices()) {
		if(! question2.getChoices().hasOwnProperty(choiceId)) { continue; }
		mc = true; 
	}
	var labelString = question2.getLabel() + (question2.getRequired() ? "*" : "");
	if(showBreak && question2.type != "INSTRUCTIONS" && question2.getResponseFormat() != "defaultMailingAddress") {
		KimbiaWidgetFramework.addLabel(labelString);
		KimbiaWidgetFramework.append("<br class='clr'/>");
		labelString = "&nbsp;";
	}
	if (mc) {
		if (question2.type == "MCMR" || question2.getResponseFormat() == "radioButtons") {
			labelString = "";
		}
		KimbiaWidgetFramework.addLabel(labelString);
		if (question2.type == "MCMR") {
			KimbiaWidgetFramework.append("<div class='k_radioButtons'>");
			for (choiceId in question2.getChoices()) {
				if(! question2.getChoices().hasOwnProperty(choiceId)) { continue; }
				var choice = question2.getChoice(choiceId);
				var labelField = choice.getLabel() + (choice.getFee() != "" ? (" - " + choice.getFee()) : "");
				var fieldString = answerString + ".detail.MCMR" + choice.getId();
                f = eval(fieldString);
                if (f == null) {
	                eval(fieldString + " = false");
                }
                KimbiaWidgetFramework.fixMCMR(questionString, answerString);
                KimbiaWidgetFramework.addCheckbox(labelField, question2.getId(), choice.getId(), fieldString, "KimbiaWidgetFramework.fixMCMR(\"" + questionString + "\", \"" + answerString + "\")");
			}
			KimbiaWidgetFramework.append("</div>");
		} else if (question2.getResponseFormat() == "radioButtons") {
			// Radio Buttons
			if (answer.answer == null) {
				 answer.answer = "";
			}
			KimbiaWidgetFramework.append("<div class='k_radioButtons'>");
			var description = "";
			longestLabelTextLength = KimbiaWidgetFramework.getLongestLabelTextLength(question2);
			styleDeclarations = "";
			styleDeclarations +="clear:none;white-space:nowrap;display:block;\n width:"+Math.round(longestLabelTextLength *.5)+"em;\n/* no descriptions */";	
			for (choiceId in question2.getChoices()) {
				if(! question2.getChoices().hasOwnProperty(choiceId)) { continue; }
				choice = question2.getChoice(choiceId);
				labelField = choice.getLabel() + (choice.getFee() != "" ? (" - " + choice.getFee()) : "");
				field = answerString + ".answer";
				KimbiaWidgetFramework.addRadioButton(labelField, question2.getId(), choice.getId(), field, true, description, styleDeclarations);
			}
			if (! question2.getRequired()) {
				KimbiaWidgetFramework.addRadioButton("None of the above", question2.getId(), "", answerString + ".answer", true, description, styleDeclarations);
			}
			KimbiaWidgetFramework.append("</div>");
		} else if (question2.getResponseFormat() == "dropDownMenu") {
			// Drop down menu
			if (answer.answer == null) {
				 answer.answer = "";
			}
			var s = "<select onblur='" + answerString + ".answer = this[this.selectedIndex].value' class='k_select'>";
			s += "<option value=''" + (answer.answer == "" ? " selected" : "") + ">" +
				(question2.getRequired() ? "Please Select..." : "") +
				 "</option>";
			for (choiceId in question2.getChoices()) {
				if(! question2.getChoices().hasOwnProperty(choiceId)) { continue; }
				choice = question2.getChoice(choiceId);
				s += "<option value='" + choice.getId() + "'" + (answer.answer == choice.getId() ? " selected" : "") + ">" +
					choice.getLabel() + (choice.getFee() != "" ? (" - " + choice.getFee()) : "") +
					 "</option>";
			}
			s += "</select>";
			KimbiaWidgetFramework.append(s);
		}
	} else { // Not multiple choice
		if (question2.getResponseFormat() == "defaultMailingAddress") {
			if (answer.answer == null || answer.answer == "") {
				answer.answer = Kimbia.newAddress();
				answer.answer.country = 'US';
			}
			KimbiaWidgetFramework.append(this.getMailingAddress(answerString + ".answer", showBreak,questionId));
		} else if (question2.type == "INSTRUCTIONS") {
//			if (answer.answer == null) {
//				answer.answer = "";
//			}
//			KimbiaWidgetFramework.append("<span class='k_headline'>" + question2.getCaption() + "</span>");
			return;
		} else if (question2.type == "DATE") {
			if (answer.answer == null) {
				answer.answer = "";
			}
			KimbiaWidgetFramework.addDateInput(labelString, answerString + ".answer");
		} else if (question2.type == "ACKNOWLEDGMENT") {
			if (answer.answer == null) {
				answer.answer = false;
			}
			KimbiaWidgetFramework.addTextarea(labelString, question2.getCaption());
			var s = "<br class='clr'/><label>&nbsp;</label><span class='fieldCaption'><input type='checkbox' name='checkbox" + question2.getId() + "' value='true' class='k_radioCB' onclick='" + answerString + ".answer = this.checked;'";
			if (answer.answer == true) {
				s += " checked='checked'";
			}
			s += ">&nbsp;&nbsp;" + question2.getConfirmation() + "</input></span><br class='clr'/>";
			KimbiaWidgetFramework.append(s);
		} else if (question2.getResponseFormat() == "textArea") {
			if (answer.answer == null) {
				answer.answer = "";
			}
			KimbiaWidgetFramework.addTextareaInput(labelString, answerString + ".answer", false);
		} else {
			if (answer.answer == null) {
				answer.answer = "";
			}
			KimbiaWidgetFramework.append(this.getTextInput(labelString, answerString + ".answer",questionId));
		}
	}
	if (question2.type != "ACKNOWLEDGMENT") {
		KimbiaWidgetFramework.append("<br class='clr'/>");
	}
	if (question2.getCaption() != null && question2.getCaption() != '' && question2.type != "ACKNOWLEDGMENT" && question2.type != "INSTRUCTIONS")  {
		KimbiaWidgetFramework.append("<label>&nbsp;</label><span class='fieldCaption'>");
		KimbiaWidgetFramework.append(question2.getCaption());
		KimbiaWidgetFramework.append("</span><br class='clr'/>");
	}
}


/** Invokes the widget constructor, and makes the widget accessible to the external page. **/
KimbiaWidget = new _KimbiaWidget();