/**
* SurveyGizmo Survey Javascript Library
* This is split into two classes, SGSurvey and Survey
*
* @author unknown - sometime
* @author Pete Fredricks - 04/28/2011
*
**/

////TURN FIREBUG CONSOLE ON!!
//window.loadFirebugConsole();

// wrap all code in closure 
(function($) {

//page initiator... gets run on ready
//throw in here anything you need run (event handlers etc)
function SG_init_page(context) {
	
	context = context || document;	
	
	//set up the save&continue
	var bar = $('#sg-snc-bar', context);
	
	if (bar.is(':visible')) {
		$('#sGizmoSaveButtonX', context).bind('click', __sgregIDs[0].object, __sgregIDs[0].object.save_n_continue);
		$('#sGizmoCancelButtonX', context).click(__sgregIDs[0].object.cancel_save_n_continue);
	}	

	var noRepeat = $('.sg-no-repeat', context);
	
	if (noRepeat.size() > 0)	{
		__sgregIDs[0].object.force_no_repeats(noRepeat);
	}
	
	// Matt Null -- attach events for pdf review export -- this probably needs moved
	// update pFred
	$('#pdf-review-export', context).click(function() {
		
		var html = ['<form action="http://', __sgregIDs[0].object.surveyObject.current_domain, '/s3/pdfexport.php" method="POST" id="pdf-export-form">',
						'<input type="hidden" name="review" value="'+$SG(this).attr('data')+'" />', 
						'<input type="hidden" value="'+$SG(this).attr('surveyname')+'" name="surveyname" />',
						'<input type="hidden" name="session" value="'+__sgregIDs[0].object.surveyObject.session+'" />',
					'</form>'];		
		
		var form = $(html.join(''));		
		
		$('body').append(form);
		
		form.submit();
	});
	
	//Matt Null
	//attach event for error trigger link
	$('#error-scroll-trigger').click(function(){
		__sgregIDs[0].object.go_first_error();
	});
}


/* This variable is global and contasin a list of registered survey handlers on the page */
var __sgregIDs = new Array();

// the cal will be initalized on page init.
var cal;

/**
* This is the basic contructor for the SGSurvey Library 
* @param SurveyObject surveydata - this is the survey data object supplied by the Survey class. 
* @param ajaxProxy surveydata - enabled is the server the survey is running on has an AJAX Proxy script.
**/
function SGSurvey(SurveyData,ajaxProxy) {
	this.libversion = 2.0;
	this.surveyObject = SurveyData;
	this.pageErrors = new Array();
	this.doLoop = new Array();
	this.ajaxProxy = ajaxProxy; 
	this.page_errors = {};
	this.timer_pulse = 200; 		//how often do the timed checks/animation run in milliseconds.
	this.pipeIndex = {};
	this.messages = this.surveyObject.messages; //the language specific messages
	this.language = this.surveyObject.language;
	this.count_uploaded_files = 1;
	this.registeredOptions = new Array();

	__sgregIDs.push({id: this.surveyObject.id, object: this});

	if(this.surveyObject.options && this.surveyObject.options.is_kiosk){
		this.runKioskMode();
	}
	
	var c = this;
	$('.sg-file-delete').click(function(){
		var data = {};
		data.success = {};
		data.success.file_name = $(this).attr('rel');
		var name = $(this).parents('.sg-question').attr("id").replace('-box','');
		c.deleteUploadedFile(data,name,this);
	});
}

SGSurvey.prototype.cancel_save_n_continue = function()
{
	$SG('#sg-snc-error').text('').fadeOut();
	$SG('#sg-snc-email').val('');
	$SG('#sg-snc-email2').val('');
	$SG('#sg-snc-box').slideUp();
}

SGSurvey.prototype.save_n_continue = function(e)
{
	$SG('#sg-snc-error').text('').fadeOut();
	var email1 = $SG('#sg-snc-email').val();
	var email2 = $SG('#sg-snc-email2').val();
	var slug = $SG('#sg-snc-slug').val();
	var sgsessionid = $SG('#sg_sessionid').val();
	//Same filter as we give in email validation 
	var filter = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
	if($SG.trim(email1)=='') //empty email
	{
		//e.data is the survey object.
		//access the messages array for the correct language string
	 	$SG('#sg-snc-error').text(e.data.messages.required).fadeIn();
	 	return;
	}
	else if(!filter.test(email1)) //validate email
	{
		$SG('#sg-snc-error').text(e.data.messages.save_n_continue_invalid).fadeIn();
	 	return;
	}
	else if($SG.trim(email1)!=$SG.trim(email2)) //emails don't match
	{
		//e.data is the survey object.
		$SG('#sg-snc-error').text(e.data.messages.save_n_continue_match).fadeIn();
		return;
	}
	
	//in preview mode, do not send, just notify
	if(e.data.surveyObject.ispreview == 'true')
	{
		$SG('#sg-snc-form').slideUp(function(){
			$SG('#sg-snc-thanks p').html('Normally, an email would have been sent to the address provided with a link to return to this survey. However, you are in preview mode so <b>no email has been sent</b>.');
		});
		$SG('#sg-snc-thanks').slideDown();
	}
	else {
		//got this far, send it
		var params = {
			sg_ajax_action: 'save_n_continue',
			email: email1,
			sg_sessionid: sgsessionid, 
			slug: slug
		}
		$SG.ajax({
			type: 'POST',
			url: '/s3/ajax_snc.php',
			data: params,
			success: function(data) {
				
				if (data && data.result=='ok') {			
					$SG('#sg-snc-form').slideUp();
					$SG('#sg-snc-thanks').slideDown();
				}
				else {
					$SG('#sg-snc-error').text("Please try again.  There was a problem sending your email.").fadeIn();
				}
			},
			error: function(data) {
				$SG('#sg-snc-error').text("Please try again.  There was a problem sending your email.").fadeIn();
			},
			dataType: "json"
		});
	}
}

SGSurvey.prototype.go_first_error = function()
{
	var el = $SG('div.sg-question-errorlist, div.sg-question-warninglist').filter(':first');
	
	$SG.scrollTo(el,800);
}

/**
 * Records the results of a poll through JS injection
 */
SGSurvey.prototype.Vote = function(domain) {
	
	// COOKIE CHECK....
	var date = new Date();
	date.setTime(date.getTime()+(1*24*60*60*1000));
	var expires = date.toGMTString();

	//this will tell me if cookies are enabled... if cookies are disabled... do not let them vote
	document.cookie = 'sg-check-'+this.surveyObject.id+'='+this.surveyObject.id+'; expires='+expires+'; path=/';
	test_cookie = SGCookie('sg-check-'+this.surveyObject.id);
	
	if (!test_cookie) {
		alert("You must have cookies enabled to take this poll.");
		return;
	}	
	
	var data = $("#sg_FormFor" + this.surveyObject.id).serialize();
	var url = ["http://", domain, "/s3/polljs/",  this.surveyObject.id,  "-",  this.surveyObject.key,  "?_vote=",  escape(data)].join('');
	
	$.ajax({
		url: url,
		dataType: 'jsonp'
	});

    $SG("#sg_FormFor" + this.surveyObject.id).addClass("voted");
}

/**
 * Shows the results of a poll
 */
SGSurvey.prototype.ShowResults = function (domain)
{
	var data = $SG("#sg_FormFor" + this.surveyObject.id).serialize();
	var url = ["http://", domain, "/s3/polljs/", this.surveyObject.id, "-", this.surveyObject.key, "?_showresults=", escape(data)].join('');
		
	$.ajax({
		url: url,
		dataType: 'jsonp'
	});
    
    $SG("#sg_FormFor" + this.surveyObject.id).addClass("voted");
}

/** little ditty for the 'none of the above' in checkboxes **/
SGSurvey.prototype.set_nota = function(id,inp)
{
	$SG(id).find('input:checkbox').not(this).each(function(){
			if(this.id!=inp.id)
			{
				if($SG('#'+inp.id).attr('checked'))
				{
					$SG(this).removeAttr('checked').attr('disabled','disabled').closest('li').addClass('sg-disabled');
				}
				else
				{
					$SG(this).removeAttr('disabled').closest('li').removeClass('sg-disabled');
				}
			}
		});
		
	SGAPI.survey.checkQuestionDependents();
}

/** 
* This function initializes the events for a survey page based on the currently loaded object
* this includes:  
*		Show/Hide
*		Accessibility Helpers
*		Validation
*		On-Page Merge Codes
*		Calculations, etc. 
**/
SGSurvey.prototype.InitPage = function (page_id, admin_view) {

	this.page_id = page_id;
	
	this.checkForwardOnly();
	
	currency_glyph_global = this.surveyObject.currency_glyph;
	
	var quest, 
		len = this.surveyObject.questions.length,
		types = [];
			
	var oArgs = {
		sgSurvey: this,
		surveyObject: this.surveyObject,
		pageId: this.page_id
	}

	// init sgapi survey class
	SGAPI.survey.init(oArgs);
	
	// Setup dynamic logic and handlers for each question type
	for (var q = 0; q < len; q++)	{
		
		quest = this.surveyObject.questions[q];
		
		if (!quest || quest.properties.disabled) {
			continue;
		}
		
		this.InitializeQuestion(quest,admin_view);	
	
		// NEW CHECK
		if (quest.properties.stars || quest.properties.stars_review) {
			types["stars"] = 1;
		}
		else if(quest.properties.thumbs){
			types['thumbs'] = 1;
		}
	}
	
	// question inits for new survey class
	if (types["stars"]) {
		SGAPI.survey.initStarRanking();
	}
	else if (types["thumbs"]) { //added this for thumbs -- Matt Null
		SGAPI.survey.initThumbsQuestion();
	}
	
	// set up display for show/hide triggers
	SGAPI.survey.checkQuestionDependents();
	
	if(typeof admin_view == 'undefined')
	{
		//setTimeout("sgTimer(" + this.surveyObject.id + ")" , this.timer_pulse);
		this.isEditor = false;
	}
	else
	{
		this.isEditor = true;
	}
	
	// Matt Null added this bc this was breaking in polls (the class was not being included)
	try{
		cal = Calendar.setup({
			fdow     : 0,
			onSelect   : function(cal) {cal.hide()}
		});
	}
	catch(e) {}
	
	this.InitValidationHooks();	
}


/** 
* 	Timer
* 	This function runs times events that check the stust of rules placed in the doLoop
**/
SGSurvey.prototype.Timer = function ()
{
	if(this.isEditor == true)return;
	/* Setup dynamic logic and handlers on the page */
	for(var q = 0; q < this.doLoop.length;q++)
	{
		this.doLoop[q].rule();
	}
}
/**
* add a timer rule to the current survey object in js
*
**/
SGSurvey.prototype.add_rule = function (r)
{
	this.doLoop.push(r);
}
/**ported from global functions in old survey render 
* adds an error for an element id (question)
*
*/
SGSurvey.prototype.add_error = function (elementid,id,message) //old function: sgjsAddError
{ 

    this.remove_error(elementid,id);
    if( typeof this.page_errors[elementid]  == 'undefined') this.page_errors[elementid] = [];
    this.page_errors[elementid].push([id,message]);
    if( typeof this.total_errors == 'undefined') this.total_errors = 0;
    this.total_errors++;      
}
/**ported from global functions in old survey render 
* removes an error for an element id (question)
*
*/
SGSurvey.prototype.remove_error = function (elementid,id)
{
    if( typeof this.page_errors[elementid]  == 'undefined') this.page_errors[elementid] = [];
    var newarray = Array();
    
    for(var i = 0; i < this.page_errors[elementid].length;i++)
    {
        if(this.page_errors[elementid][i][0] != id) newarray.push(this.page_errors[elementid][i]);
        else {this.total_errors--;}
    } 
	this.page_errors[elementid] = newarray;                
}
/**
* ported.  Counts the number of errors for an element id (question)
**/
SGSurvey.prototype.error_count = function (elementid) //sgjsErrorCount
{
	if( typeof this.page_errors[elementid]  == 'undefined') this.page_errors[elementid] = [];
	return this.page_errors[elementid].length;
}
/**ported from global functions in old survey render 
* updates the element error display
*
*/
// !update
SGSurvey.prototype.update_element_errors = function (element,msg) //sgjsUpdateElementErrors
{
	var current_id = element.id;
	var num = this.error_count(current_id);
	var msg = $SG('#'+$SG(element).attr('id')+'-message');
	if(msg.attr('id') !== $SG(element).attr('id')+'-message')
	{
		$SG(element).parent().append('<div id="'+$SG(element).attr('id')+'-message" class="sg-message" style="display:none;"></div>');
		msg = $SG('#'+$SG(element).attr('id')+'-message');
	}
	if(num > 0)
	{
	    arr = this.page_errors[current_id]?this.page_errors[current_id]:[];
	    msg.html('');
	    for(var i = 0; i < arr.length;i++)
	    {
	        if(arr[i][1] != "")
	        {
	        	$SG("<div></div>").text(arr[i][1]).appendTo(msg);
	        }
	    }         
	    if(msg != "" && typeof msg != "undefined")
	    {
	        msg.parent().removeClass('sg-validation-pass').addClass('sg-validation-fail');
	        msg.show();
	    }              
	}
	else
	{
	    if(msg != "" && typeof msg != "undefined")
	    {
	       	msg.html('').parent().removeClass('sg-validation-fail').addClass('sg-validation-pass');
	       	msg.hide();
	    }
	}
}

/**
* in_arr (works like to JQuery.inArray and Array.indexOf)
* proprietary - do not remove without replacing calls in this file and verifying that they work identically as Array.indexOf is **not** an exact replacement.
* @author unknown
* @param mixed - value to search for
* @param arr - array to search
* @return int  (-1 on failure, position in array on success)
**/
function in_arr(val,arr){
	for(i=0;i<arr.length;i++) if (val==arr[i]) return i;
	return -1;
}

/** 
 *
 * Forward Only Survey **/
SGSurvey.prototype.checkForwardOnly = function ()
{
  return;

	if(this.surveyObject.options.forward_only)
	{
		var cookievalue = SGCookie("path" + this.surveyObject.session);
		if(cookievalue == null)cookievalue = "S";
				
		var page_list = cookievalue.split(",");
		var lastpage = page_list.pop();
		
		if(lastpage != this.surveyObject.currentpage && in_arr(this.surveyObject.currentpage,page_list) >= 0)
		{
			$SG("#sgbody-" + this.surveyObject.id ).hide();
			document.location = $SG("#sg_FormFor"+this.surveyObject.id).get(0).action + ($SG("#sg_FormFor"+this.surveyObject.id).get(0).action.indexOf("?") > 0 ? "&" : "?") + "id=" +  this.surveyObject.id + "&sg_navigate=current_page";
			return;
		}

		if(lastpage != this.surveyObject.currentpage)page_list.push(lastpage);  
		page_list.push(this.surveyObject.currentpage);
		SGCookie("path" + this.surveyObject.session,page_list.join(","));		
	}
}

/**
 * Get the value of a cookie with the given name.
 *
 * @example SGCookie('the_cookie');
 * @desc Get the value of a cookie.
 *
 * @param String name The name of the cookie.
 * @return The value of the cookie.
 * @type String
 */
SGCookie = function(name, value, options) {

    if (typeof value != 'undefined') { // name and value given, set cookie
     
        options = options || {};
        if (value === null) {
            value = '';
            options.expires = -1;
        }
        var expires = '';
        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
            var date;
            if (typeof options.expires == 'number') {
                date = new Date();
                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
            } else {
                date = options.expires;
            }
            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
        } 
        // CAUTION: Needed to parenthesize options.path and options.domain
        // in the following expressions, otherwise they evaluate to undefined
        // in the packed version for some reason...
        var path = options.path ? '; path=' + (options.path) : '';
        var domain = options.domain ? '; domain=' + (options.domain) : '';
        var secure = options.secure ? '; secure' : '';
        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
   
    } else { // only name given, get cookie
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = $SG.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
};
 
/**
 * This function is responsible for returning the total of the continuous sum.
 * @author dehru -- modifications by Matt Null
 * @properties -- the question's properties
 * @return total
 * 
 */
SGSurvey.prototype.getContinuousSumTotal = function(el,properties) {
	properties  = properties || null;
	var onlyWholeNumbers = properties.only_whole_num || null;

	stotal=0;
	$SG(el).parents('.sg-type-continuous-sum').find('input.sg-input-text').each(function(i, element, onlyWholeNumbers){
					var basevalue = $SG.trim(this.value.replace(/[^\-\.\d]/g,''));
					if(onlyWholeNumbers)
						stotal += isNaN(parseInt(basevalue)) ? 0 : parseInt(basevalue);
					else
						stotal += isNaN(parseFloat(basevalue)) ? 0 : parseFloat(basevalue);
				});
	
	//@Matt Null added this so avoid very long decimal places          
	if(!onlyWholeNumbers)
		stotal = stotal.toFixed(2);
	
	//Matt Null append appropriate symbol to the total
	if(properties.force_currency == true){	
		stotal = '' + currency_glyph_global + stotal;
	}
	else if(properties.force_percent == true){
		stotal = stotal+'%';
	}
	
	return stotal;
}

/**
 * This function is responsible for the display changes based on the continuous sum.
 * @author dehru
 * @param domElement element
 * @param float stotal
 * @param questionObject question
 */
SGSurvey.prototype.displayContinuousSum = function(element, stotal, question) {
	element.html(stotal);
	var showError = false;
	if(stotal>question.properties.max_total && question.properties.max_total)
	{
		showError = true;
	}
	
    if(question.properties.must_be_max && stotal!=question.properties.max_total)
    {
    	showError = true;
    }
    
    if (showError) 
    	$SG(element).parent().addClass("sg_Counter_Error");
    else
    	$SG(element).parent().removeClass("sg_Counter_Error");
}


/**
 * Used as callback method to onBlur, also supporting method for other number formatters
 */
SGSurvey.prototype.formatNumber = function(target, properties, format) {
	var element = $SG(target);
	// sanitize input so we can process it
	if(element.val().match(/,\d{2}$/)) {
		var num = element.val().replace(/[^\-\,\d]/g,'').replace(/\,/, ':').replace(/\,/g, '').replace(/\:/, '.'); // Euro validation. convert comma to decimal for now.
	} else {
		var num = element.val().replace(/[^\-\.\d]/g,'').replace(/\./, ':').replace(/\./g, '').replace(/\:/, '.');
	}
	// what to do with waht we got
	if($SG.trim(element.val()) == '') {
		// don't let only spaces get through
		num = '';
		$SG(target).removeClass('sg-validation-error');
	} else if($SG.trim(num) == '' || isNaN(Number(num))) {
		// flag as error
		$SG(target).addClass('sg-validation-error');
		num = element.val();
	} else {
		// go go go
		var prepend = '';
		var append = '';
		var is_negative = false;
		
		// do we have a negative number
		if(num != Math.abs(num) && properties.only_positive_num !== true) {
			is_negative = true;
		}
		
		// strip off modifier (we'll add it later if needed)
		num = num.replace(/\-/g, '');
		
		// round for "whole numbers only" validation
		if(properties.only_whole_num) {
			num = Math.round(num);
		}
		
		// accessorize the values
		if(format == 'percent') {
			append = '%';
		}
		
		if(format == 'currency') {
			prepend = currency_glyph_global;
			if(!properties.only_whole_num) {
				num = Math.floor(num*100+0.50000000001);
				cents = num%100;
				num = Math.floor(num/100).toString();
				if(cents<10) {cents = "0" + cents;}
				
				for (var i = 0; i < Math.floor((num.length-(1+i))/3); i++) {
					num = num.substring(0,num.length-(4*i+3))+',' + num.substring(num.length-(4*i+3));
				}
				num = num + '.' + cents;
			}
		}
		$SG(target).removeClass('sg-validation-error');
		num = (is_negative ? '-' : '') + prepend + num + append;
	}
	return num;
}


/**
 * Used as callback method to onBlur
 */
SGSurvey.prototype.formatPercent = function(target, properties) {
	var num = this.formatNumber(target, properties, 'percent');
	return num;
}


/**
 * Used as callback method to onBlur
 */
SGSurvey.prototype.formatCurrency = function(target, properties) {
	var num = this.formatNumber(target, properties, 'currency');
	return num;
}

/** A Better way to hook validation functions to targets **/
SGSurvey.prototype.InitValidationHooks = function () {

	$SG(".sg-validation-date").each(function (name,item)
			{
				var calandericonid = (new String (item.id)).replace("-element","Trigger");
				cal.manageFields(calandericonid, item.id, "%m/%d/%Y");		
			});
	
	/**
	 * autocomplete uses jquery.autocomplete.js library
	 * @author dehru
	 */
	$SG(".sg-autocomplete").each(function (name,item)
	{
		/** find question **/
		var question = null;
		var surveyId = (new String(item.id)).split("-")[1];
		var surveyobj = SGAPI.surveyData[surveyId];
		var parent_sku = (new String(item.id)).split("-")[3];
		
		for(var qi in surveyobj.questions)
		{
			if(surveyobj.questions[qi].id==parent_sku)
			{
				var base = "#" + item.id;
				question = surveyobj.questions[qi];
			}
		}
		if(question == null)return true;
	
		if (question.properties.autocomplete.length > 0 && question.properties.autocomplete.substring(0,1) == '@')
		{
			//$SG(base).autocomplete("https://appv3.sgizmo.com/http/filesearch?file=" + question.properties.autocomplete.substring(1));
			$SG(base).autocomplete("/s3/ajax_proxy.php?call=filesearch&file=" + question.properties.autocomplete.substring(1));
			
		} else if (question.properties.autocomplete.length > 0 && question.properties.autocomplete.indexOf("\n") > 0) 
		{
			$SG(base).autocomplete(question.properties.autocomplete.split("\n"));
		}
		
		if(question.properties.force_autocomplete && question.properties.autocomplete.length > 0){
			$SG(this).blur(function(){
				var inlist = false;
				var list = '';
				if(question.properties.autocomplete.substring(0,1) == '@')
				{
					var this_value = this;
					$SG.ajax({
						url : "/s3/ajax_proxy.php?call=filesearch&file=" + question.properties.autocomplete.substring(1) + "&q=" + $SG(this_value).val(),
						success : function(res){
							list = res.split("\n");
							for(var i in list)
							{
								if($SG(this_value).val() == list[i].trim())
								{
									inlist = true;
									break;
								}
							}
							if(!inlist){
								$SG(this_value).val('');
							}
						}});
				}
				else
				{
					list = question.properties.autocomplete.split("\n");
					for(var i in list)
					{
						if($SG(this).val() == list[i].trim())
						{
							inlist = true;
							break;
						}
					}
					if(!inlist){
						$SG(this).val('');
					}
				}
			});
		}
	}); 
}

/**
* Uploads a file to the webserver via background iframe
*
*
**/
SGSurvey.prototype.UploadFile = function(name,cid,key,maxfiles,maxfilesize,extentions)
{
	var url = ''; 
	SO = this;
	maxfiles = maxfiles || null;
	if($SG('#'+name+'-element').val() != '')
	{
	
		//Start spinner
		$SG('#'+name+'-box .sg-file-feedback').fadeIn(function(){$SG(this).removeClass('sg-hide')}).addClass('sg-file-loader').html(SO.messages.uploading_file);
		
		if(this.surveyObject.ispreview == 'true')
		{
			url = '/projects/previewupload?input_name='+name+'&cid='+cid+'&key='+key+'&uuid='+this.surveyObject.session;
		}
		else
		{
			url = '/s3/file500/?input_name='+name+'&cid='+cid+'&key='+key+'&uuid='+this.surveyObject.session+'&maxfilesize='+maxfilesize+'&extentions='+extentions;
		}
		
		var can_add = false;
		$SG('.'+name).each(function()
		{
			if($SG(this).val()=='')
			{
				can_add = true;
				return false;
			}
		});
		
		if(can_add == true)
		{ 	
			//context
			var c = this;
			$SG.ajaxFileUpload(
			{
				url:url, 
				secureuri:false,
				fileElementId:name+'-element',
				dataType: 'json',
				success: function (data, status)
				{ 
					//stop spinner gif
					$SG('#'+name+'-box .sg-file-feedback').fadeOut().removeClass('sg-file-loader');
					
					if(data.error != undefined && data.error != '')
					{
						c.UploadShowAlert(name,data.error);
					}
					else if(data.success.file_name == '')
					{
						c.UploadShowAlert(name,SO.messages.upload_error);
					}
					else
					{
						//Add file name to hidden input
						$SG('.'+name).each(function()
						{
							if($SG(this).val()=='')
							{
								$SG(this).val(data.success.file_name.replace(/\'|"/g,""));
								return false;//Acts like a break
							}
						});
						//Add li for new file
						if($SG('#sg-file-desc-'+name+' ul').children('li').length < 2)
							$SG('#sg-file-desc-'+name).removeClass('sg-hide');
						
						var li_html = $SG('#sg-file-desc-'+name+' .sg-prototype-li').clone().removeClass('sg-prototype-li');
						$SG(li_html).html($SG(li_html).html().replace('{{filename}}',data.success.name));
						$SG(li_html).find('a').attr('rel',data.success.file_name);
						$SG('#sg-file-desc-'+name+' ul').append(li_html);
						$SG('#'+name+'-element').val('');

						var file_name = data.success.file_name;
						//Matt Null -- attach delete button event and do the delete
						$SG(li_html).find('.sg-file-delete').click(function(){
							c.deleteUploadedFile(data,name,this);
						});
					}
				},
				error: function (data, status, e)//General Upload Error
				{
					var response = $SG.parseJSON(data.responseText);
					
					if(status == 'error' && response.error == 'filetype'){
						c.UploadShowAlert(name,SO.messages.invalid_file_type);
					}
					else if(status == 'error' && response.error == 'filesize'){
						c.UploadShowAlert(name,SO.messages.invalid_file_size);
					}
					else{
						c.UploadShowAlert(name,SO.messages.upload_error);
					}
				}
			});
		}
		else//Max files reached
		{
			$SG('#'+name+'-element').val('');
			this.UploadShowAlert(name,SO.messages.no_more_files);
		}
	}
	else//No file specified
	{
		this.UploadShowAlert(name,SO.messages.no_file_specified);
	}
	/**MattNull this takes the maxfiles
	if(maxfiles != null){ 
		if(this.count_uploaded_files == parseInt(maxfiles)){
			$SG('#'+name+'-element').parent('div').css("display","none");
		} 
	}**/
	this.count_uploaded_files++;
}

//Matt Null -- deletes and uploaded file
SGSurvey.prototype.deleteUploadedFile = function(data,name,el){
	data = data || {};
	var filename = data.success.file_name,
		c = this;
	
	if(el.target){
		el = el.target;
	}
	else if(el.srcElement){
		el = el. srcElement;
	}
	else{
		el = el;
	}
	
	$SG.ajax({
		url: '/s3/delete_file.php',
		data : {file : filename,cid : c.surveyObject.customer_id, sid : c.surveyObject.id},
		type : 'POST',
		beforeSend : function(){
			c.UploadShowAlert(name, 'Deleting...');
		},
		success : function(){
			$SG(el).parent('li').remove(); 
			
			if($SG('#sg-file-desc-'+name).find('li').length == 1)
				$SG('#sg-file-desc-'+name).addClass('sg-hide');
				
			$SG('.'+name).each(function()
			{
				if($SG(this).val() == filename)
				{
					$SG(this).val('');
					return false;
				}
			});
		}
	});
}

SGSurvey.prototype.UploadShowAlert = function(name,msg)
{
	$SG('#'+name+'-box .sg-file-feedback').removeClass('sg-file-loader').fadeIn(function(){$SG(this).removeClass('sg-hide')}).addClass('sg-file-alert').html(msg);
	setTimeout(function(){$SG('#'+name+'-box .sg-file-feedback').fadeOut(2000).removeClass('sg-file-alert');},3000);
}

/** 
* Function:  InitializeQuestion 
* sets up the question with the appropriate click handlers etc.  This does a lot of setting up, so it's probably
* going to be one that gets checked/used a lot 
* @param Object question
**/
SGSurvey.prototype.InitializeQuestion = function (question, admin_view) { 
	var self = this;
	
	//skip over questions that do not exist.
	if(typeof question == 'undefined') {
		return false;
	}
	
	var base = "#sgE-" + this.surveyObject.id + "-" +  this.page_id +'-'+ question.id;
	
	// to fake a one-input vs. options... one input calls its id -element, many options have -sku
	// pFred- what??
	if (typeof question.options == 'undefined' && question.type!='MENU') {
		question.options = {0:{id:'element'}}; 
	}
	
	// hide all after? really this should be taken care of server-side, so nothing gets shown-hidden -- jarring
	if (question.properties.hide_all_after_until_value == true || question.properties.has_showhide_deps == true) {
		SGAPI.survey.initShowHideTriggers(question);		
	}

	/** hide after response **/
	if(question.properties.hide_after_response==true)
	{
		for(o in question.options)
		{
			var elem =  base +'-'+question.options[o].id;
			SO=this;
			$SG(elem).click(function(){
								$SG(this).closest('.sg-question').hide();
							});
		}
	}	
		
	/** title case **/
	if(question.properties.title_case)
	{
		for(o in question.options)
		{
			var elem =  base +'-'+question.options[o].id;
			var SO = this;
			$SG(elem).blur(function(event){
            		if(typeof event == "undefined"){event = window.event;}
	            		var target = sgGetEventTarget(event);
	            		var a = $SG(this).val().split(' ');
	            		var b=[];
	            		for(w in a){
	            		var iehack = a[w].split('');
	            			if(iehack.length && a[w]!=''){
	            				a[w] = iehack.join('');
		            			b[w] = a[w].replace(/^(\s*)(.)/,"$1"+iehack[0].toUpperCase());
		            			iehack.shift();
		            			if(iehack.length){
		            				b[w] = b[w].replace(/^(\s*)(.)(.*)/,"$1"+"$2"+iehack.join('').toLowerCase());
		            			}
	            			}else{ //accounts for \s+
	            				b[w]='';
	            			}
	            		}
	            		$SG(this).val(b.join(' '));
							}
						   );
	 	 }	
	}
	
	
	/** auto format numeric, percent, or currency **/
	if(question.properties.force_numeric || question.properties.force_percent || question.properties.force_currency)
	{
		var SO = this;
		for(o in question.options)
		{
			var elem =  base +'-'+question.options[o].id;
			$SG(elem).blur(function(event){
								if(typeof event == "undefined"){event = window.event;} 
								var target = sgGetEventTarget(event);
								if(question.properties.force_percent) {
									var num = SO.formatPercent(target, question.properties);
								} else if(question.properties.force_numeric) {
									var num = SO.formatNumber(target, question.properties);
								} else if(question.properties.force_currency) {
									var num = SO.formatCurrency(target, question.properties);
								}
								$SG(target).val(num);
							});
		}
	}

	/* input mask */
	if(question.properties.inputmask)
	{
		for(o in question.options)
		{
			var elem =  base +'-'+question.options[o].id;
			var mask = question.properties.inputmask.MASK;
			var mssg = '';
			if (question.properties.messages && question.properties.messages.inputmask)
				mssg = question.properties.messages.inputmask[this.language] || '';
			var SO = this;
			$SG(elem).blur(function(event){
								if(typeof event == "undefined"){event = window.event;}
								var target = sgGetEventTarget(event);
								if(target.value != "" && !target.value.match(new RegExp(mask)))
								{
									SO.add_error(target.id,"inputmask",mssg);
								} else {
									SO.remove_error(target.id,"inputmask");
								}
								SO.update_element_errors(target,$SG(base + "-msg"));
						});
		}
	}
	/* min number */// !min
	if(question.properties.min_number)
	{
		for(o in question.options)
		{
			var elem = base +'-'+question.options[o].id;
			var SO = this;
			var min_num = question.properties.min_number;
			if(question.properties.force_percent)
			{
				min_num = question.properties.min_number +'%';
			}
			
			if(question.properties.force_currency)
			{
				min_num = '' + currency_glyph_global + question.properties.min_number;
			}
			$SG(elem).blur(function(event){ 
				if(typeof event == "undefined") {event = window.event;}
				var target = sgGetEventTarget(event);
				if(parseFloat((target.value).replace(/,/g,'').replace(/\$/g,'').replace(/%/g,'')) < parseFloat(question.properties.min_number) && target.value != "")
				{
					var msg = SO.messages.min_number;
					if (msg.indexOf(":min") > -1) {msg = msg.replace(":min", min_num);}
					if (msg.indexOf(":value") > -1) {msg = msg.replace(":value", target.value);}
					SO.add_error(target.id,"minnumber",msg);
				}
				else
				{
					SO.remove_error(target.id,"minnumber");
				}
				SO.update_element_errors(target,$SG(base + "-msg"));
			});
		}
	}
	/* max number */// !max
	if(question.properties.max_number)
	{
		for(o in question.options)
		{
			var elem = base +'-'+question.options[o].id;
			var SO = this;
			var max_num = question.properties.max_number;
			if(question.properties.force_percent)
			{
				max_num = question.properties.max_number +'%';
			}
			
			if(question.properties.force_currency)
			{
				max_num = '' + currency_glyph_global + question.properties.max_number;
			}
			
			$SG(elem).blur(function(event) {
				if(typeof event == "undefined") {event = window.event;}
				var target = sgGetEventTarget(event);
				if(parseFloat((target.value).replace(/,/g,'').replace(/\$/g,'').replace(/%/g,'')) > parseFloat(question.properties.max_number) && target.value != "")
				{
					var msg = SO.messages.max_number;
					//uses messages array and expects to replace ":min" and ":value"
					if (msg.indexOf(":max") > -1) {msg = msg.replace(":max", max_num);}
					if (msg.indexOf(":value") > -1) {msg = msg.replace(":value", target.value);}

					SO.add_error(target.id,"maxnumber",msg);
				}
				else
				{
					SO.remove_error(target.id,"maxnumber");
				}
				SO.update_element_errors(target,$SG(base + "-msg"));
			});
		}
	}
	
	if(question.properties.xnumber && question.type == 'CHECKBOX')
	{
		$SG(base+'-box :checkbox').click(function()
		{
			//Matt Null -- if someone checks an NA checkbox... we need to disable everything else
			if($SG(this).hasClass('na') && $SG(this).is(':checked')){ 
				$SG(base+'-box :checkbox').not(this).each(function(){
					$SG(this).removeAttr('checked');
					$SG(this).attr('disabled','disabled');
				});
				return;
			}
			else{
				$SG(this).parent().siblings().children(base+'-box :checkbox').each(function(){
					this.removeAttribute("disabled");//Have to use javascript removeAttribute instead of jQuery removeAttr because of ****ing IE6
				});
			}
			
			if($SG(base+'-box :checked').length >= question.properties.xnumber)
			{
				$SG(base+'-box :checkbox').each(function(){	
					if(!$SG(this).attr('checked'))
						$SG(this).attr('disabled','disabled');
				});
			}
			else
			{
				$SG(base+'-box :checkbox').each(function(){
					this.removeAttribute("disabled");//Have to use javascript removeAttribute instead of jQuery removeAttr because of ****ing IE6
				});
			}
		});
	} 
	
	//##########################################
	
	/* date picker */
	if(question.properties.subtype=='DATE')
	{
		
	}

	/** image select **/
	if(question.type == 'IMAGE_SELECT' && question.properties.image_select_type)
	{
		tot_images = 0;
		for(var qo in question.options) tot_images++;
		var stype = question.properties.image_select_type
			,SO = this //needed for onclick since 'this' is different scope there
			,max_width_available = $SG('.sg-question-options').width() //needed for width calculations for each image's footprint
			;
		
		for(var o in question.options)
		{
			var question_box = base + '-box'
				,element = base + '-'+o //radio
				,image =  element+'-image' //elem
				,handle = element+'-handle .sg-image-box'
				,icon = element+'-icon'
				,image_width = $SG(image).width() //Math.floor($SG(image).outerWidth(true) / 1.5) //elem_width  //need to know if a min-width should be applied to the image-select box because IE is just that dumb
				;
			//make sure the state of the input is correct
			if($SG(element).is(':checked')) {
				$SG(handle).parent('.sg-imageselect-item').addClass('sg-image-selected');
				$SG(icon+' span').text('Selected');
				$SG(element).attr('checked','checked'); // why? Because we can.
			}
			// set appropriate image width to the max available if it is more than that
			if(image_width > max_width_available) {
				image_width = max_width_available;
			}
			// if we have no preconcieved inline styles, apply the computed image_width as a min-width
			if(!$SG(image).closest('.sg-imageselect-item').attr('style')) {
				$SG(image).closest('.sg-imageselect-item').css('min-width',image_width);
			}
			//click added to radio only b/c a click on the label will call the click on the button
			$SG(handle).click(function(event) {
						event.preventDefault(); 
						if(stype == 'single-select') {
							$SG(question_box + ' .sg-image-box').each(function() { 
										$SG(this).parent('.sg-imageselect-item').removeClass('sg-image-selected');
										$SG(this).find(icon + ' span').text('Not Selected');
										$SG(this).find('input').removeAttr('checked');
									});
							$SG(this).parent('.sg-imageselect-item').addClass('sg-image-selected');
							$SG(this).find(icon + ' span').text('Selected');
							$SG(this).find('input').attr('checked','checked');
						}
						if(stype == 'multi-select' || stype == 'multiple-select') {
							if($SG(this).find('input').is(':not(:checked)')) {
								$SG(this).parent('.sg-imageselect-item').addClass('sg-image-selected');
								$SG(this).find(icon + ' span').text('Selected');
								$SG(this).find('input').attr('checked','checked');
							} else {
								$SG(this).parent('.sg-imageselect-item').removeClass('sg-image-selected');
								$SG(this).find(icon + ' span').text('Not Selected');
								$SG(this).find('input').removeAttr('checked');
							}
						}
				});
		}
	}
	
	/*** ranking, new way ***/
	if (question.type == 'RANK') {
		
		// Table-based Ranking
		if (question.properties.display_type=='TABLE') {
			
			$(base + '-container').find('input').each(function() {
				
				$(this).click(function() {
					
					if (this.checked) {
						var i = $(this).attr("value") || "";
						
						for (subOpt in question.options) {
							var subInput = $(base + '-' + question.options[subOpt].id + '-' + i);
							
							if (this.id != subInput.attr('id')) {
								subInput.prop('checked', false);
							}
						}
					}
				});
			});
		}//Matt Null logic for sortable rank question
		else if(question.properties.display_type=='SORT'){
			//Sortable Ranking
			// the following selector (.sg-rank-sortbox ul) is used because of the way polls are rendered in the editor
			// this selector is okay to use because there will always be one question in the editor
			if(typeof admin_view == 'undefined'){
			 	$SG('.sg-rank-sortbox ul').sortable({
					stop: function(event,ui){
						var selected_order = $SG(base+'-sortbox').sortable('toArray');
	
						for(p in selected_order)
						{ 
							var pos = parseInt(p)+1;
							if(pos==1)
							{
								$SG('#'+selected_order[p]).addClass('sg-first-li');
							}
							else
							{
								$SG('#'+selected_order[p]).removeClass('sg-first-li');
							}
							if(typeof selected_order[p] != 'undefined' && selected_order[p].replace)
							{
								$SG('#'+selected_order[p].replace(/-handle$/,'')).val(pos);
								$SG('#'+selected_order[p].replace(/-handle$/,'-number')).html(pos+'.&nbsp;');
							}
						}
					}
				});
			}
			else{//this is done only for styling purposes
				$SG('.sg-rank-sortbox ul').addClass('ui-sortable');
			}
		}
		else
		{
			// Drag-Drop Ranking
			if(typeof admin_view == 'undefined'){
				 $SG(base+'-origin, '+base+'-target').sortable({
						connectWith: base+'-origin, '+base+'-target',
						placeholder: 'sg-sortable-placeholder',
						receive: function (event,ui,target){
							if(this.id.match(/-origin$/))return true;
							if(typeof question.properties.xnumber == 'undefined') return true;
							if(question.properties.xnumber<1) return true;
							if(typeof target=='undefined') target=this;
							var in_now = $SG(target).sortable('toArray').length-1;
							if(in_now >= question.properties.xnumber) $SG(ui.sender).sortable('cancel');
							},
						stop: function(event,ui){
							var selected_order = $SG(base+'-target').sortable('toArray');
							var omit_order = $SG(base+'-origin').sortable('toArray');
							for(p in selected_order)
							{
								var pos = parseInt(p)+1;
								if(pos==1)
								{
									$SG('#'+selected_order[p]).addClass('sg-first-li');
								}
								else
								{
									$SG('#'+selected_order[p]).removeClass('sg-first-li');
								}
								if(typeof selected_order[p] != 'undefined' && selected_order[p].replace)
								{
										$SG('#'+selected_order[p].replace(/-handle$/,'')).val(pos);
										$SG('#'+selected_order[p].replace(/-handle$/,'-number')).html(pos+'.&nbsp;');

								}
							}
							for(p in omit_order)
							{
								var pos = parseInt(p)+1;
								if(pos==1)
								{
									$SG('#'+omit_order[p]).addClass('sg-first-li');
								}
								else
								{
									$SG('#'+omit_order[p]).removeClass('sg-first-li');
								}
								if(typeof omit_order[p] != 'undefined' && omit_order[p].replace)
								{
									$SG('#'+omit_order[p].replace(/-handle$/,'')).val('');
									$SG('#'+omit_order[p].replace(/-handle$/,'-number')).html('');
								}
							}
							if($SG(base+'-target li').length<1)
							{
								$SG(base+'-target').closest('div').addClass('sg-rank-target-empty');
							}
							else
							{
								$SG(base+'-target').closest('div').removeClass('sg-rank-target-empty');
							}
						}
					});
			}
			//adjust height of receiver and lock height of origin (div height times number of divs)
			
			var orig_height = $SG(base+'-origin').outerHeight() + $SG(base+'-target').outerHeight();
			/** cv: 9/28/2010 This block deal with ranking dimentions when the !$#@ question is hidden by show hide **/
			if(orig_height == 0)
			{
			  var container = $SG(document.createElement("DIV"));
			  container.addClass("sg-rank-dragdrop");
			  container.html($SG(base+'-origin').parent().html());
			  container.css({visibility:"hidden", display:"block", position:"absolute"});
			  container.appendTo($SG("body"));
			  var orig_height = container.height();
			  container.remove();
			  
			  var container = $SG(document.createElement("DIV"));
			  container.addClass("sg-rank-dragdrop");
			  container.html($SG(base+'-base').parent().html());
			  container.css({visibility:"hidden", display:"block", position:"absolute"});
			  container.appendTo($SG("body"));
			  orig_height += container.height();
			  container.remove();
			} /** end show hide fix **/
			$SG(base+'-target').height(orig_height);
			$SG(base+'-origin').height(orig_height);
			
			
			if($SG(base+'-target li').length<1)
			{
				$SG(base+'-target').closest('div').addClass('sg-rank-target-empty');
			}
			else
			{
				$SG(base+'-target').closest('div').removeClass('sg-rank-target-empty');
			}
		}
	}
	/*continuous sum*/
	if(question.type=='CONT_SUM')
	{
		//for(p in question.properties) alert(p+': '+question.properties[p]);
		SO = this;
		var displaySum = false,
		total = 0;
		for(o in question.options)
		{
			var inp = 	base + '-' + question.options[o].id;
			if ($SG(inp).val().length > 0) displaySum = true; //we should display the sum.
			var SO = this;
			$SG(inp).blur(function(event){
							//this in context here is the textbox element.
							if(typeof event == "undefined"){event = window.event;} 
							var target = sgGetEventTarget(event);
							var qbase = target.id.replace(/-\d+$/,'');
							var counterElement = $SG('#'+qbase+'-counter');
							var total = SO.getContinuousSumTotal(this,question.properties);
							SO.displayContinuousSum(counterElement, total, question);
						});
			
		}
		//do the initial display here.
		if (displaySum) {
			var counterElement = $SG(base+'-counter'),
			stotal = this.getContinuousSumTotal(inp,question.properties);
			this.displayContinuousSum(counterElement, stotal, question);
		}
	}
	/* Tie other options to the radio buttons */
	if(question.options && question.type!='CONT_SUM')
	{
		SO = this;
		for (o in question.options)
		{
			/* Add advanced features to the 'Other' textbox */
			if(question.options[o].properties)
			{
				if(question.options[o].properties.other)  //properties.other might be right
				{
					var input = "#sgE-" + this.surveyObject.id + "-" +  this.page_id +'-'+ question.id +'-'+ question.options[o].id;
					var other = input + "-other";
					$SG(input).bind('click',{other:other},function(event){if($SG(this).attr('checked'))$SG(event.data.other).focus();});
					$SG(other).bind('keypress',{other:other,input:input},function(event) {if($SG(event.data.other).val() != "") $SG(event.data.input).attr('checked','checked');});
					$SG(other).bind('click',{other:other,input:input},function(event) {$SG(event.data.input).attr('checked','checked');});
				}
				/*add the js on the 'none of the above' checkbox*/
				if(question.options[o].properties.none) { 
					
					$SG(base+'-'+ question.options[o].id).click(function(){
						SO.set_nota(base+'-box',$SG(this)[0]);
					});
					
					/* Now, set proper checks when going forward or back in the survey */
					if( ($SG(base + ("-" + question.options[o].id)).length > 0) && $SG(base+'-'+ question.options[o].id)[0].checked) {
						SO.set_nota(base + '-box',$SG(base+'-'+ question.options[o].id)[0]);
					}
				}
			}
		}
	}
	/* Does this question have Max Words? */
	if(question.properties.max_words > 0)
	{console.log(base,this)
		var essay_id = base.replace('#','');
		var max_words_message = this.messages.max_words.replace(':max',question.properties.max_words).replace(':value','<span id="'+essay_id+'-maxwords">0</span>');
		$(base+'-element').after('<div class="sg-max-words">'+max_words_message+'</div>');
		for(o in question.options)
		{
			var elem = 	base + '-' + question.options[o].id;
			var current_words = base + "-maxwords";
			$SG(current_words).html($SG(elem).val().length > 0 ? ($SG(elem).val().split(" ")).length : 0);
			$SG(elem).keyup(function(){
				var x = $SG(this).val();
				//replace multiple spaces with just one
				x =x.replace(/[ ]+/g,' ');
				var l = $.trim(x).split(' ').length > 0 ? $.trim(x).split(' ').length : 0;
				if( l > parseInt(question.properties.max_words) ) 
				{
					$SG(elem).parents('div.sg-question-options').addClass('sg-validation-error');
				}
				else
				{
					$SG(elem).parents('div.sg-question-options').removeClass('sg-validation-error');
				}
				
				$SG(current_words).html(l);
			 });
			 //added a paste event handler for the case where someone copies and pastes text
			 $SG(elem).bind('paste',function(){
			 	var l = $.trim($SG(this).val()).split(' ').length > 0 ? $.trim($SG(this).val()).split(' ').length : 0;
				if( l > parseInt(question.properties.max_words) ) 
				{
					$SG('.sg-max-words').parents('div.sg-question-options').addClass('sg-validation-error');
				}
				else
				{
					$SG('.sg-max-words').parents('div.sg-question-options').removeClass('sg-validation-error');
				}
				
				$SG(current_words).html(l);
			 });
		}	
	}
	
	/* Dynamic Show/Hide Functions 
	   Show hide now works by compiling a 'Show Rules' array inside the Runtime array.
	*/
	
}

//Matt Null - force no repeats
SGSurvey.prototype.force_no_repeats = function(el) {
	
	el.each(function(){
		var parentEl = $(this);
		
		//only looking for selects now... can easily make the selector "select,input" etc
		parentEl.find('select').each(function() {
			
			$(this).change(function() {				
				var val = $(this).prop('selectedIndex');
				
				parentEl.find('select').not(this).each(function() {
					
					if (val == $(this).prop('selectedIndex')) {
						$(this).prop('selectedIndex', 0);
					}
				});
			});
		});
	});
}

/**
 * @author Matt Null
 * Handles all of the kiosk JS
 */
SGSurvey.prototype.runKioskMode = function(){
	var kioskIntro = $('#kiosk-intro');
	var kioskCloseButton = $('#kiosk-close-button');

	//attach events to top kiosk bar	
	$('#kiosk-start-new-survey').click(function(){
		window.location.href = window.location.href;
	});
	
	//if this is the first page
	if(kioskIntro.size() > 0){
		kioskIntro.show();
		$('.sg-question-set').find('.sg-question').hide();
		$('.sg-footer').hide();
		
		$('#kiosk-start-button').click(function(){
			kioskIntro.hide();
			$('.sg-question-set').find('.sg-question').slideDown(500);
			$('.sg-footer').fadeIn(500);
		});
	}
	else if(kioskCloseButton.size() > 0){ //its the last page
		this.KioskFinalPageCounter();
		kioskCloseButton.click(function(){
			window.location.href = window.location.href;
		});
	}
	
	//run the idle timeout script for kiosk
	if(this.surveyObject.currentpage != 1){
		var c = this;
		function startIdleTimeout(){
			window.kioskIdleTimeout = setTimeout(function(){
				window.location.href = window.location.href;
			}, c.surveyObject.options.is_kiosk.idle_timeout * 60000);
		}
		
		startIdleTimeout();
		
		//if the user interacts with the window, restart the idletimeout
		$(window).click(function(){
			window.clearTimeout(kioskIdleTimeout);
			startIdleTimeout();
		});
	}
};

/**
 * @author Matt Null
 * Handles all of the kiosk JS
 */
SGSurvey.prototype.KioskFinalPageCounter = function(){
	var countdownContainer = $('#kiosk-countdown');
	var finalPageCounter = parseInt(countdownContainer.html());

	setInterval(function(){
		var count = parseInt(countdownContainer.html());
		
		if(count == 0){
			return;
		}
		
		countdownContainer.html(count - 1);
	}, 1000);
	
	setTimeout(function(){
		window.location.href = window.location.href;
	},finalPageCounter * 1000);
};

function show_options(qid)
{
	alert(qid);
	for(o in S201516.surveyObject.questions[qid].options) 
	{
		alert(o+': '+S201516.surveyObject.questions[qid].options[o]);
		for(op in S201516.surveyObject.questions[qid].options[o])
			alert(op+': '+S201516.surveyObject.questions[qid].options[o][op]);
	}
}

/** sgTimer
*   This function handles timed checks on regular intervals.  
*
*
function sgTimer(id)
{
	// find the right object 
	for(i = 0; i < __sgregIDs.length;i++)
	{
		if(__sgregIDs[0].id == id)
		{
			__sgregIDs[0].object.Timer();
			
		}
	}
	setTimeout("sgTimer(" + id + ")" , __sgregIDs[0].object.timer_pulse);	
}
*/
/** 
*	This function gets the target of a particular event (most event handlers need this to work properly)
**/
function sgGetEventTarget(event)
{
	var targetElement = null;
	if(typeof event.target != "undefined")
	{
		targetElement = event.target;
	} 
	else 
	{
		targetElement = event.srcElement;
	};
	while(targetElement.nodeType == 3 && targetElement.parentNode != null)
	{
		targetElement = targetElement.parentNode;
	};
	return targetElement;
}
/** ported from old survey_render, could encapsulate if had time**/
function sgFloatingCalendar(datestr,element,top,left){if(typeof(cals)=="undefined")cals=new Array();if(typeof(cals[element.id+"_calander"])!="undefined"){cals[element.id+"_calander"].setDate(datestr);return(cals[element.id+"_calander"]);}this.dateValue=new Date();this.elm=element;this.positionTop=parseInt(top);this.positionLeft=parseInt(left);this.ident=element.id+"_calander";this.height=180;this.width=170;if(document.getElementById(this.ident)==null){this.domElement=document.createElement("div");this.domElement.className='sg_PopCal';this.domElement.style.display="none";this.domElement.style.position="absolute";var body=document.getElementsByTagName("body");body[0].appendChild(this.domElement);}else{this.domElement=document.getElementById(this.ident);}this.domElement.id=this.ident;this.domElement.style.top=this.positionTop;this.domElement.style.left=this.positionLeft;this.monthNames=new Array("January","February","March","April","May","June","July","August","September","October","November","December");this.monthAbbreviations=new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");this.dayHeaders=new Array("S","M","T","W","T","F","S");var parts=datestr.split("/");if(parts.length>=3){this.dateValue=new Date(parts[2],(parts[0]-1),parts[1]);}cals[element.id+"_calander"]=this;this.display=function(){this.updateContent();this.domElement.style.display="block";this.domElement.style.position="absolute";};this.alignToInput = function(){if(typeof(this.elm) != "undefined"){this.domElement.style.position = "absolute";var off = this.realOffset(this.elm);this.domElement.style.left = parseInt(off[0]) + parseInt(this.elm.offsetWidth) + "px";this.domElement.style.top = off[1] + "px";}}
this.realOffset = function(element) {var valueT = 0, valueL = 0;do {valueT += element.offsetTop  || 0;valueL += element.offsetLeft || 0;element = element.offsetParent;if (element) {if(element.tagName=='BODY') break;}} while (element);return [valueL, valueT];}
this.backMonth=function(){var year=this.dateValue.getFullYear();var month=this.dateValue.getMonth();var day=this.dateValue.getDate();if(month==0){month=11;year--;}else month--;this.dateValue=new Date(year,month,day);this.updateContent();};this.setDate=function(datestr){if(datestr==""){this.dateValue=new Date();}else{var parts=datestr.split("/");if(parts.length>=3){this.dateValue=new Date(parts[2],(parts[0]-1),parts[1]);}}};this.nextMonth=function(){var year=this.dateValue.getFullYear();var month=this.dateValue.getMonth();var day=this.dateValue.getDate();if(month==11){month=0;year++;}else month++;this.dateValue=new Date(year,month,day);this.updateContent();};this.updateContent=function(){var html='<div style="padding:3px;width:'+this.width+'px;height:'+this.height+'px;background-color:#fff;border:outset #eee 1px;overflow:hidden;" >';html=html+'<div class="sgCalContainer">';html=html+'<table width="100%" class="sg_CalHeader" cellspacing="0" cellpadding="0" >';html=html+'<tr  class="sg_CalMonthYearRow" style="text-align:left"  ><td class="sg_CalBackMonth" ><a href="#" onclick="cals[&quot;'+this.ident+'&quot;].backMonth();return(false);">&laquo;</a></td>';html=html+'<td  class="sg_CalMonthYear" style="text-align:center" >'+this.monthAbbreviations[this.dateValue.getMonth()]+' '+this.dateValue.getFullYear()+'</td>';html=html+'<td  class="sg_CalNextMonth" style="text-align:right" ><a href="#" onclick="cals[&quot;'+this.ident+'&quot;].nextMonth();return(false);">&raquo;</a></td></tr>';var scanner=new Date(this.dateValue);scanner.setDate(1);html=html+'</table><table width="100%" class="sg_CalBody" cellspacing="0" cellpadding="0" >';html=html+'<tr class="sg_CalDayLabels" ><th>S</th><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th></tr>';html=html+'<tr class="sg_CalDates" >';var day=scanner.getDay();var days=0;for(i=0;i<day;i++)html=html+'<td ></td>';while(scanner.getMonth()==this.dateValue.getMonth()){if(scanner.getDay()==0&&days<1)html=html+'<tr class="sg_CalDates" >';if(scanner.getDate()==this.dateValue.getDate())html=html+'<td class="sg_CalSelected"><b>';else html=html+'<td>';html=html+'<a href="#" onclick="cals[&quot;'+this.ident+'&quot;].dateSelect(\''+(scanner.getMonth()+1)+'/'+scanner.getDate()+'/'+scanner.getFullYear()+'\');return(false);">'+scanner.getDate()+'</a>';if(scanner.getDate()==this.dateValue.getDate())html=html+'</b>';html=html+'</td>';days++;if(scanner.getDay()==6){html=html+'</tr>';days=0;}scanner.setDate(scanner.getDate()+1);}html=html+'</tr>';html=html+'</table>';html=html+'<div style="text-align:center;" class="sg_CalClose" >[<a href="#" onclick="document.getElementById(\''+this.ident+'\').style.display = \'none\';return(false);" >close calendar</a>]</div>';html=html+'</div><iframe width="'+this.width+'" height="'+this.height+'" frameborder=0 border=0 src=""></iframe>';html=html+'</div>';this.domElement.innerHTML=html;};this.dateSelect=function(dateStr){if(typeof(this.elm)!="undefined"){this.elm.value=dateStr;}document.getElementById(this.ident).style.display='none';}}

	
var Survey = function() {}

Survey.prototype = {	

	/** 
	 * This function must be called after the class is instantiated.
	 * 
	 * @param {obj} oArgs
	 */
	init: function(oArgs) {
		this.sgSurvey = oArgs.sgSurvey;
		this.surveyObject = oArgs.surveyObject;
		this.pageId = oArgs.pageId;
		this.optionDepsMap = {};
	},
	
	/**
	 * This function updates the meta element of the 'target'.
	 * 
	 * @param {$, string} target
	 * @param {string} token
	 * @param {string} val
	 * 
	 */
	setMeta: function (target, token, val) {

		if (target instanceof $) {
			target = '#' + target.attr('id');
		}

		$(target.replace(/-box/g,'-meta')).each(function() {
			var exp = new RegExp(token+'=(.+?)&|$')
			var m = exp.exec(this.value);
			
			// was a match, it exists in there
			if (m.length>1) {
				this.value = this.value.replace(token + '=' + m[1], token + '=' + val);
			}
			else { //no match, add it in			
				this.value += '&' + token + '=' + val;
			}
		});
	},
	
	/**
	 * This function hides all the dependent questions passed to it.
	 * It also clears the data for the hidden questions.
	 * 
	 * @param {obj} deps
	 * 
	 */	
	hideDependents: function(deps) {
		for (var id in deps) {
			deps[id].hide();				
			this.setMeta(deps[id], 'hidden', 'true');				
			this.clearQuestionData(deps[id]);
			
			// if the dep is a group, hide all questions inside
			if (deps[id].hasClass('sg-type-group')) {
				var subQuests = [];
				
				deps[id].find('.sg-question').each(function() {
		//			console.log($(this));
					subQuests.push($(this));
				});
				
				this.hideDependents(subQuests);
			}
		}
	},
	
	/**
	 * This function shows all the dependent questions passed to it.
	 * 
	 * @param {$, obj} deps
	 * 
	 */		
	showDependents: function(deps) {

		for (var id in deps) {
			deps[id].show(); 
			this.setMeta(deps[id], 'hidden', 'false');
			
			// if the dep is a group, show all questions inside
			if (deps[id].hasClass('sg-type-group')) {
				var subQuests = [];
				
				deps[id].find('.sg-question').each(function() {
					subQuests.push($(this));
				});
				
				this.showDependents(subQuests);
			}
		}
	},
	
	/**
	 * This function resets a question.
	 * 
	 * @param {$} quest
	 * 
	 */	
	clearQuestionData: function( quest ) {
		
		// menu 
		if (quest.hasClass('sg-type-menu')) {
			quest.find('select').prop('selectedIndex', 0);
		}
		else {
			quest.find('input.sg-input').prop('checked', false);
			quest.find('input.sg-input[type="text"]').val(''); // textbox
			quest.find('textarea.sg-input').val(''); // textarea
		}
	},
	
	/**
	 * Set up the show / hide dependencies for a question.
	 * 
	 * @param {obj} question
	 */
	initShowHideTriggers: function(question) {
		
		var self = this;
		var base = "#sgE-" + this.surveyObject.id + "-" +  this.pageId +'-'+ question.id;
		
		this.optionDepsMap[question.id] = {};
		
		if (question.properties.hide_all_after_until_value == true) {
			this.surveyObject.hide_all_after = question.id;
		}
		
		//add the handler to show the others when it's clicked... fork on input type
		if (question.type == 'RADIO' || question.type == 'CHECKBOX' || question.type == 'MENU') {
						
			var dep, optId, optDeps, optDepsArr, optEl;
			var len = 0;
			
			function makeDomId(id) {
				return ['#sgE-', self.surveyObject.id, '-', self.pageId, '-', id, '-box'].join('');
			}
			
			// add listeners for menus
			if (question.type == 'MENU') {

				var triggerEl = $(base + '-element');
				
				triggerEl.bind('change', function() {
					self.checkQuestionDependents();
				});				
			}
			
			for (var o in question.options) {
				
				optId = base + '-' + question.options[o].id;
				
				// add listeners for radios and checkboxes
				if (question.type != 'MENU') {
					
					// this is the option element
					optEl = $(optId);
				
					optEl.bind('click', function() {
						self.checkQuestionDependents();
					});		
					
					$(optId + '-other').bind('click', {el:optEl}, function(ev) {
						ev.data.el.prop('checked', true);
						ev.data.el.trigger('click');
					});
				}
				
				// skip options without dependents
				if (!question.options[o].properties || !question.options[o].properties.dependent) {					
					continue;
				}
				
				optDeps = question.options[o].properties.dependent.split(/,/);
				optDepsArr = [];				
				len = optDeps.length;
				
				// loop through option specific dependents
				for (var i = 0; i < len; i++) {				
					
					dep = $(makeDomId(optDeps[i]));
					
					optDepsArr.push(dep);
				}
				
				// save opt/deps info to global list
				this.optionDepsMap[question.id][question.options[o].id] = {
					el: (question.type == 'MENU') ? triggerEl : optEl,
					deps: optDepsArr
				}
			}
		}
	},
	
	/**
	 * This function is the brains behind show/hide triggers. Everytime 
	 * it runs, it checks the status of the page and hides/shows the correct 
	 * questions. It uses recursion to check the status again everytime something
	 * changes.  
	 * 
	 * @param {array} testArr
	 */
	checkQuestionDependents: function(testArr) {
		
		var optMap, opt, el, optDep, depId, optionArr, isSelected;		
		var hideList = {};
		var showList = {};
		var hideArr = [];
		
		// loop through every question with dependents
		for (var qid in this.optionDepsMap) {
		
			optMap = this.optionDepsMap[qid];
			
			// loop through the options for this question
			for (var oid in optMap) {

				opt = optMap[oid];
				el = opt.el;
				optionArr = opt.deps;
				
				// loop through array of dependents for this option
				for (var i = 0; i < optionArr.length; i++) {
					
					optDep = optionArr[i];
					depId = optDep.attr('id');
					
					// whether the input is selected (for menus or checkbox/radio)
					isSelected = (el.is('select')) ? (el.val() == oid) : (el.is(':checked'));
						
					if (isSelected) {
						showList[depId] = optDep 
					}
					else {
						hideList[depId] = optDep
						hideArr.push(depId);
					}	
				}
			}
		}

		// remove any shows in the hide list
		for (var x in hideList) {

			if (showList[x]) {
				delete hideList[x];
			}
		}
		
		// if something has changed from the last time, run again
		if (!SGAPI.array.compare(testArr, hideArr)) {
			this.hideDependents(hideList);
			this.showDependents(showList);	
			this.checkQuestionDependents(hideArr);
		}
	},

	/** 
	 * This function combs the page for star box questions 
	 * and initializes their user interaction.
	 */
	initStarRanking: function() {

		// grab all star boxes
		var starBoxes = $("div.sg-star-box");

		// for each star box...
		starBoxes.each(function() {

			var stars = $(this).find("label");
			var count = stars.length;

			// attach events to all labels
			stars.each(function(i) {

				var star = $(this);					

				// add hover events to each star
				star.hover( 
					function() {

						for (var k = i; k >=0; k--) {
							$(stars[k]).addClass("sg-star-on");
						}
					},
					function() {

						for (var k = i; k >=0; k--) {

							var el = $(stars[k]);

							// only remove the class if the star is NOT permanently on
							if (!el.data("perm")) {
								el.removeClass("sg-star-on");
							}
						}
					});	

				// add click events to each star
				// we used mousedown because click had funny effects
				star.bind("mousedown", function() {

					for (var k = 0; k < count; k++) {

						var curStar = $(stars[k]);

						// if the current star is above the selected
						if (k > i) {									
							curStar	
								.removeClass("sg-star-on")
								.data("perm", false); // remove permanent flag
						}
						else {									
							curStar
								.addClass("sg-star-on")
								.data("perm", true); // add permanent flag
						}
					}						
				});					
				
				// add stars if radio buttom was already selected. 
				var radioIsChecked = star.find("input[type=radio]").is(':checked'); 
				
				if (radioIsChecked) {
					star.trigger("mousedown");
				}				
			});				
		});			
	},
	
	/** 
	 * This function combs the page for thumbs boxes and initializes their user interaction.
	 * @author Matt Null
	 */
	initThumbsQuestion : function(){
		var thumbBoxes = $('div.sg-thumb-box');
		
		thumbBoxes.each(function(){
			var thumbs = $(this).find('label');
			var thumb_inputs = $(this).find('input');
			
			thumb_inputs.each(function(){
				if($(this).attr('checked'))
				{
					if($(this).parent().hasClass('sg-thumb-up'))
					{
						$(this).parent().addClass('sg-thumb-up-on');
					}
					else if($(this).parent().hasClass('sg-thumb-down'))
					{
						$(this).parent().addClass('sg-thumb-down-on');
					}
				}
			});
			
			thumbs.mousedown(function(){
				if($(this).hasClass('sg-thumb-up')){
					$(this).addClass('sg-thumb-up-on');
					$('label.sg-thumb-down').removeClass('sg-thumb-down-on');
				}
				else{
					$(this).addClass('sg-thumb-down-on');
					$('label.sg-thumb-up').removeClass('sg-thumb-up-on');
				}
			});
		});
	},
	
	initGroup: function(base, parentSku, pipeCount) {
				
		//get some of the other info we need
		for (var qi in this.surveyObject.questions)	{
			
			if (this.surveyObject.questions[qi].id == parentSku) {
				
				var maxCount = this.surveyObject.questions[qi].properties.addasneeded_max;
				
				if (this.surveyObject.questions[qi].properties.displayfirst_add_as_needed != true) {
					maxCount = maxCount + 1;
				}
				
				var maxMsg = this.surveyObject.questions[qi].properties.addasneeded_max_message[this.surveyObject.language];
				
				break;
			}
		}
		
		var fullSku = base + parentSku;
		var button = $('#' + fullSku + '-' + 'button');
		var index = pipeCount || 0;
		
		// The button holds info about the group...magic.
		button.data({
			maxCount: maxCount,
			maxMsg: $('<div class="max-msg">' + maxMsg + '</div>'),
			count: index
		});
		
		if (index == 0) {
			
			// only grab the inputs that aren't part for the dummy or button
			var elmts = $('#' + fullSku + '-box')
				.find('[id^=' + base + ']')
				.filter(function() {
					return !(this.id.match(/dummy/) || this.id.match(/-button/));
				});
			
			// add piping with next index
			pipeify(elmts, ++index);

			button.data('count', index);
		}
		else if (index == maxCount) {
			button.hide();
			button.after(button.data('maxMsg'));
		}
		
		this.InitValidationHooks();
	},
	
	addGroup: function(base, parentSku) {

		var fullSku = base + parentSku;
		var button = $('#' + fullSku + '-' + 'button');
		var index = button.data('count');
		var maxCount = button.data('maxCount');
		
		// safety net to keep more groups from being added
		if (index == maxCount) {
			return false;
		}

		var dummyGroup = $('#dummy-group-' + parentSku);
		var newGroup = dummyGroup.clone().removeAttr('id');
		var elmts = newGroup.find('[id^=' + base + ']');

		// adding the piping requires more attention for ie 6/7
		if ($.browser.msie && $.browser.version < 8) {
			elmts = iePipeify(elmts, ++index);	
		}
		else {
			pipeify(elmts, ++index);
		}
		
		// add the group to page
		newGroup
			.insertBefore(button)
			.fadeIn();
		
		// hide button and add message when user can't add more
		if (index == maxCount) {
			button.hide();
			button.after(button.data('maxMsg'));
		}
		
		button.data('count', index);

		this.InitValidationHooks();

		return false;
	},
	
	removeGroup: function(link, base, parentSku) {
		
		var button = $('#' + base + parentSku + '-' + 'button');
		var index = button.data('count');
		
		$(link).parents('.sg-group:first').remove();
		
		// update index and show button
		button.data('count', --index).show();
		
		// remove the max message
		button.data('maxMsg').remove();
		
		return false;
	}
}

// CLASS HELPER FUNCTIONS //

/**
 * for ie6 and ie7 only.
 * creates new input elements from the dummy clone. Changes
 * the name and id to match the correct piping index.
 * 
 * @author pFred
 * @return {jquery} (new set of elements)
 */
function iePipeify(elmts, index) {

	elmts.each(function(i) {

		var el = $(this);
		var id = el.attr('id') || '';
		var newID = id.replace(/-dummy/,'') + '-pipe-' + index;

		if (el.is(':input')) {
			var isRadio = ((el.attr('type') || "").toLowerCase() == 'radio');

			var tag = this.nodeName;
			var className = el.attr('class');
			var type = el.attr('type');
			var value = el.attr('value');
			var title = el.attr('title');
			var size = el.attr('size');
			var rows = el.attr('rows');
			var cols = el.attr('cols');

			var newName = (isRadio) ? newID.replace(/-\d+-pipe/,'-pipe') : newID.replace(/-element/,'');
			var html = ['<', tag, ' name="', newName, '" id="', newID, '"'];

			if (type) {
				html.push(' type="', type, '"');
			}
			if (value) {
				html.push(' value="', value, '"');
			}
			if (className) {
				html.push(' class="', className, '"');
			}
			if (title) {
				html.push(' title="', title, '"');
			}
			if (size) {
				html.push(' size="', size, '"');
			}
			if (rows) {
				html.push(' rows="', rows, '"');
			}
			if (cols) {
				html.push(' cols="', cols, '"');
			}

			html.push('></', tag, '>');

			var newEl = document.createElement(html.join(''));
			
			// if this element is a select, we need to clone the options too
			if (tag.toLowerCase() == 'select') {
				
				var optElmts = el.find('option');
				var opt, optValue, optText, optHtml, newOpt;
				
				for (var k = 0, len = optElmts.length; k < len; k++) {
					opt = $(optElmts[k]);
					optValue = opt.attr('value');
					optText = opt.text();
					optHtml = ['<option value="', optValue, '"></option>'];
					
					newOpt = document.createElement(optHtml.join(''));
					newOpt.innerHTML = optText;
					
					newEl.appendChild(newOpt);
				}
			}

			elmts[i] = newEl

			el.before(newEl);
			el.remove();				
		}
		else {
			el.attr('id', newID);
		}
	});	

	return elmts;
}

/**
 * For a group of elements (jquery), changes the name and 
 * id to match the correct piping index.
 * 
 * @author pFred
 */
function pipeify(elmts, index) {

	elmts.each(function() {

		var input = $(this);
		var isRadio = ((input.attr('type') || "").toLowerCase() == 'radio');
		var id = input.attr('id') || '';
		var newID = id.replace(/-dummy/,'') + '-pipe-' + index;

		input.attr('id', newID);

		if (input.attr('name')) {

			var newName = (isRadio) ? newID.replace(/-\d+-pipe/,'-pipe') : newID.replace(/-element/,'');

			input.attr('name', newName);
		}
	});
}

// ADD TO GLOBAL NAMESPACE
SGAPI.survey = new Survey();
SGAPI.surveyData = [];

// new methods that use SGAPI.survey
SGSurvey.prototype.addGroup = SGAPI.survey.addGroup;
SGSurvey.prototype.initGroup = SGAPI.survey.initGroup;
SGSurvey.prototype.removeGroup = SGAPI.survey.removeGroup;

window.SG_init_page = SG_init_page;
window.SGSurvey = SGSurvey;

// javascript embeds will have content to load once this file loads
if (SGAPI.contentLoader) {
	
	for (var i = 0, len = SGAPI.contentLoader.length; i < len; i++) {
		SGAPI.contentLoader[i]($);
	}
}
	
})(SGAPI.jQuery);

