HEX
Server: LiteSpeed
System: Linux lp015.web24.net.au 2.6.32-954.3.5.lve1.4.93.el6.x86_64 #1 SMP Wed Oct 4 17:04:29 UTC 2023 x86_64
User: pgkdistr (10190)
PHP: 8.1.32
Disabled: opcache_get_status
Upload Files
File: /var/www/vhosts/pgkdistribution.com.au/citisolar.com.au/new/js/jotform.js
/*jslint nomen:false, debug:true, evil:true, vars:false, browser:true, forin:true, undef:false, white:false */
/**
 * JotForm Form object
 */
var JotForm = {
    /**
     * JotForm domain
     * @var String
     */
    url: "//www.jotform.com/", // Will get the correct URL from this.getServerURL() method
    /**
     * JotForm request server location
     * @var String
     */
    server: "//www.jotform.com/server.php", // Will get the correct URL from this.getServerURL() method
    /**
     * All conditions defined on the form
     * @var Object
     */
    conditions: {},
    /**
     * All calculations defined on the form
     * @var Object
     */
    calculations: {},
    /**
     * Condition Values
     * @var Object
     */
    condValues: {},
    /**
     * Progress bar object above form
     * @var Object
     */
    progressBar: false,    
    /**
     * All JotForm forms on the page
     * @var Array
     */
    forms: [],
    /**
     * Will this form be saved on page changes
     * @var Boolean
     */
    saveForm: false,
    /**
     * Array of extensions
     * @var Array
     */
    imageFiles: ["png", "jpg", "jpeg", "ico", "tiff", "bmp", "gif", "apng", "jp2", "jfif"],
    /**
     * array of autocomplete elements
     * @var Object
     */
    autoCompletes: {},
    /**
     * Array of default values associated with element IDs
     * @var Object
     */
    defaultValues: {},
    /**
     * Debug mode
     * @var Boolean
     */
    debug: false,
    /**
     * Check if the focused inputs must be highligted or not
     * @var Boolean
     */
    highlightInputs: true,
    /**
     * it will disable the automatic jump to top on form collapse
     * @var Boolean
     */
    noJump: false,
    /**
     * Indicates that form is still under initialization
     * @var Boolean
     */
    initializing: true,
    /**
     * Keeps the last focused input
     * @var Boolean
     */
    lastFocus: false,
    /**
     * Form's payment type, if any
     * @var String
     */
    payment: false,
    /**
     * Status of multipage save
     * @var Boolean
     */
    saving: false,
    /**
     * Texts used in the form
     * @var Object
     */
    texts: {
        confirmEmail:       'E-mail does not match',
        pleaseWait:         'Please wait...',
        confirmClearForm:   'Are you sure you want to clear the form',
        lessThan:           'Your score should be less than or equal to',
        incompleteFields:   'There are incomplete required fields. Please complete them.',
        required:           'This field is required.',
        requireOne:         'At least one field required.', 
        requireEveryRow:    'Every row is required.',
        requireEveryCell:   'Every cell is required.',
        email:              'Enter a valid e-mail address',
        alphabetic:         'This field can only contain letters',
        numeric:            'This field can only contain numeric values',
        alphanumeric:       'This field can only contain letters and numbers.',
        url:                'This field can only contain a valid URL',
        currency:           'This field can only contain currency values.',
        fillMask:           'Field value must fill mask.',
        uploadExtensions:   'You can only upload following files:',
        noUploadExtensions: 'File has no extension file type (e.g. .txt, .png, .jpeg)', 
        uploadFilesize:     'File size cannot be bigger than:',
        gradingScoreError:  'Score total should only be less than or equal to',
        inputCarretErrorA:  'Input should not less than the minimum value:',
        inputCarretErrorB:  'Input should not greater than the maximum value:',
        maxDigitsError:     'The maximum digits allowed is',
        freeEmailError:     'Free email accounts are not allowed',
        minSelectionsError: 'The minimum required number of selections is ',
        maxSelectionsError: 'The maximum number of selections allowed is ',
        pastDatesDisallowed:'Date must not be in the past.',
        multipleFileUploads_typeError: '{file} has invalid extension. Only {extensions} are allowed.',
        multipleFileUploads_sizeError: '{file} is too large, maximum file size is {sizeLimit}.',
        multipleFileUploads_minSizeError: '{file} is too small, minimum file size is {minSizeLimit}.',
        multipleFileUploads_emptyError: '{file} is empty, please select files again without it.',
        multipleFileUploads_onLeave: 'The files are being uploaded, if you leave now the upload will be cancelled.',
        multipleFileUploads_fileLimitError: 'Only {fileLimit} file uploads allowed.',
        generalError:       'There are errors on the form. Please fix them before continuing.',
        generalPageError:   'There are errors on this page. Please fix them before continuing.',
        wordLimitError:     'Too many words. The limit is',
        characterLimitError:'Too many Characters.  The limit is'
    },
    paymentTexts: {
        couponApply:        'Apply',
        couponChange:       'Change',
        couponEnter:        'Enter Coupon',
        couponExpired:      'Coupon is expired. Please try another one.',
        couponInvalid:      'Coupon is invalid. Please try another one.',
        couponValid:        'Coupon is valid.',
        couponBlank:        'Please enter a coupon.',
        shippingShipping:   'Shipping',
        totalTotal:         'Total',
        totalSubtotal:      'Subtotal',
        taxTax:             'Tax'
    },
    /**
     * Find the correct server url from forms action url, if there is no form use the defaults
     */
    getServerURL: function() {
        var form = $$('.jotform-form')[0];
        var action;
        
        if (form) {
            if((action = form.readAttribute('action'))){
                if(action.include('submit.php') || action.include('server.php')){
                    var n = !action.include('server.php')? "submit" : "server";
                    this.server = action.replace(n+'.php', 'server.php');
                    this.url    = action.replace(n+'.php', '');
                }else{
                    var d = action.replace(/\/submit\/.*?$/, '/');
                    this.server = d + 'server.php';
                    this.url    = d;
                }
                
            }
        }
    },
    /**
     * Changes only the given texsts
     * @param {Object} newTexts
     */
    alterTexts: function(newTexts, payment){
        if (payment) {
            Object.extend(this.paymentTexts, newTexts || {});
            this.changePaymentStrings(newTexts);
        } else {
            Object.extend(this.texts, newTexts || {});
        }
    },
    /**
     * A short snippet for detecting versions of IE in JavaScript
     * without resorting to user-agent sniffing
     */
    ie: function(){
        var undef,
            v = 3,
            div = document.createElement('div'),
            all = div.getElementsByTagName('i');
        
        while (
            div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
            all[0]
        );
        
        return v > 4 ? v : undef;
    },
    /**
     * Creates the console arguments
     */
    createConsole: function(){
        var consoleFunc = ['log', 'info', 'warn', 'error'];
        $A(consoleFunc).each(function(c){
            this[c] = function(){
                if(JotForm.debug){
                    if('console' in window){
                        try{
                            console[c].apply(this, arguments);
                        }catch(e){
                            if(typeof arguments[0] == "string"){
                                console.log( c.toUpperCase() + ": " + $A(arguments).join(', '));
                            }else{
                                if(Prototype.Browser.IE){
                                    alert(c+": "+arguments[0]);
                                }else{
                                    console[c](arguments[0]);
                                }
                            }
                        }
                    }
                }
            };
        }.bind(this));
        
        if(JotForm.debug){
            JotForm.debugOptions = document.readJsonCookie('debug_options');
        }
    },
    /**
     * Initiates the form and all actions
     */
    init: function(callback){
        var ready = function(){
            try {
                this.populateGet();
                
                if(document.get.debug == "1"){
                    this.debug = true;
                }
                this.createConsole();
                
                this.getServerURL();
                
                if(callback){ callback(); }
                
                //will load editMode script dynamically
                if ((document.get.mode == "edit" || document.get.mode == "inlineEdit" || document.get.mode == 'submissionToPDF') && document.get.sid) {
                    this.editMode();
                }
                
                this.noJump = ("nojump" in document.get);                
                this.uniqueID = this.uniqid();
                this.checkMultipleUploads();
                this.handleSavedForm();
                this.setTitle();
                this.getDefaults();
                
                if ($$('input[name="simple_fpc"]').length > 0) {
                    this.payment =  $$('input[name="simple_fpc"]')[0].getAttribute('data-payment_type');
                }
                
                if (this.payment === "paypalpro") {
                    this.handlePaypalPro();
                    this.isFormEmbedded();
                }
                
                if (this.payment === "paypalexpress") {
                    this.handlePaypalExpress();
                    this.isFormEmbedded();
                }
                
                // If coupon button exists, load checkCoupon
                if($('coupon-button')) {
                    this.handleCoupon();
                }
                
                if ($$('.paypal-button').length > 0 && $('use_paypal_button')) {
                    this.handlePaypalButtons();
                }
                
                this.handleFormCollapse();
                this.handlePages();
                
                if ( $$('.form-product-has-subproducts').length > 0 ) {
                    this.handlePaymentSubProducts();
                }

				// If form is hosted in an iframe, calculate the iframe height
				if (window.parent && window.parent != window) {
					this.handleIFrameHeight();
                    this.removeCover();
				}

                this.jumpToPage();

                this.highLightLines();
                this.setButtonActions();
                this.initGradingInputs();
                this.initSpinnerInputs();
                this.initNumberInputs();
                this.setConditionEvents();
                this.setCalculationEvents();
                this.runAllCalculations();
                this.setCalculationResultReadOnly();
                this.prePopulations();
                this.handleAutoCompletes();
                this.handleTextareaLimits();
                this.handleDateTimeChecks();
                this.handleOtherOptions(); // renamed from handleRadioButtons
                this.setFocusEvents();
                this.disableAcceptonChrome();
                this.handleScreenshot();
                
                $A(document.forms).each(function(form){
                    if (form.name == "form_" + form.id || form.name == "q_form_" + form.id) {
                        this.forms.push(form);
                    }
                }.bind(this));

                var hasCaptcha = $$('div[id^=recaptcha_input]').length;

                if (!hasCaptcha || $$('*[class*="validate"]').length > hasCaptcha) {
                    this.validator();
                };

                this.fixIESubmitURL();
                this.disableHTML5FormValidation();
                
                if($('progressBar')) {
                    this.setupProgressBar();
                }
                
                // if there is a donation field and it contains a calculation widget reference
                if ($$('input[id*="_donation"]').length > 0 && $$('input[id*="_donation"]')[0].getAttribute('data-custom-amount-field') > 0) {
                    this.handleDonationAmount();
                }
                
            } catch (err) {
                 JotForm.error(err);
            }

            this.initializing = false; // Initialization is over
        }.bind(this);
        
        if(document.readyState == 'complete' || (this.jsForm && document.readyState === undefined) ){
            ready();
        }else{
            document.ready(ready);
        }
    },
    handleIFrameHeight: function () {
    	var height;
    	if ($$('.form-collapse-table').length > 0) {
    		height = $$('body')[0].getHeight();
    	} else if ($$('.form-section').length > 1) {
    		var maxHeight = 0;
			var body = $$('body')[0];
    		var sections = $$('.form-section');

    		// First hide all the pages
    		sections.each(function(section) {
    			section.setStyle({display: 'none'});
    		}); 
			
			// Dislay each page sequentially, and find the body height
    		sections.each(function(section) {
    			section.setStyle({display: 'block'});
    			if (maxHeight < body.getHeight()) {
    				maxHeight = body.getHeight();
    			}
				section.setStyle({display: 'none'});
    		});

			// Display the first page
    		sections[0].setStyle({display: 'block'});
    		height = maxHeight;
    	} else {
    		//height = $$('body').first().getHeight();

            //augment jQuery's height implementation
            var jQueryHeight = Math.max(
                Math.max(document.body["scrollHeight"],0/*, document.documentElement["scrollHeight"]*/),
                Math.max(document.body["offsetHeight"], document.documentElement["offsetHeight"])
            );

            //height = Math.max(height, jQueryHeight);
            height = jQueryHeight;
    	}

	// if this is a captcha verification page, set height to 300 
	height = ( document.title === 'Please Complete' ) ? 300 : height;
        if("console" in window){
            if("log" in console){
                console.log('Debug : setting height to ',height,' from iframe');
            }
        }
    	window.parent.postMessage('setHeight:' + height, '*');
    },
    removeCover: function () {
        $$('.form-cover-wrapper').each(function (el) {
            el.remove();
        });
        $$('.form-all').each(function (el) {
            el.removeClassName('top-cover').removeClassName('left-cover').removeClassName('right-cover');
        });
    },
    fixIESubmitURL: function () {
        try{
            // IE on XP does not support TLS SSL 
            // http://en.wikipedia.org/wiki/Server_Name_Indication#Support
            if(this.ie() <= 8 && navigator.appVersion.indexOf('NT 5.')){
                $A(this.forms).each(function(form){
                    if(form.action.include("s://submit.")){
                       form.action = form.action.replace(/\/\/submit\..*?\//, "//secure.jotform.com/"); 
                    }
                });
            }
        }catch(e){}
    },
    screenshot  : false, // Cached version of screenshot
    passive     : false, // States if wishbox iis getting screenshot passively
    onprogress  : false, // Are we currently processing a screenshot?
    compact     : false, // Use the compact mode of the editor
    imageSaved  : false, // Check if the image saved by screenshot editor
    /**
     * Find screenshot buttons and set events
     * HIDE or SHOW according to the environment
     */
    handleScreenshot: function(){
        var $this = this;
        setTimeout(function(){
            $$('.form-screen-button').each(function(button){
                //$this.getContainer(button).hide();
                // If window parent has feedback then show screenshot
                if(window.parent && window.parent.JotformFeedbackManager){
                    $this.getContainer(button).show();                
                    button.observe('click', function(){
                        $this.passive = false;
                        try{
                            $this.takeScreenShot(button.id.replace('button_', ''));
                        }catch(e){
                            console.error(e);
                        }
                    });
                    setTimeout(function(){
                        $this.passive = !window.parent.wishboxInstantLoad;
                        $this.takeScreenShot(button.id.replace('button_', ''));
                    }, 0);
                }
            });
        }, 300);
    },
    getCharset: function(doc){    
        if(!doc){ doc = document; }
        
        return doc.characterSet || doc.defaultCharset || doc.charset || 'UTF-8';
    },
    /**
     * Convert number of bytes into human readable format
     *
     * @param integer bytes     Number of bytes to convert
     * @param integer precision Number of digits after the decimal separator
     * @return string
     */
    bytesToSize: function(bytes, precision) {
        var sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
        var posttxt = 0;
        if (bytes == 0) return 'n/a';
        if (bytes < 1024) { return Number(bytes) + " " + sizes[posttxt]; }
        while( bytes >= 1024 ) {
            posttxt++;
            bytes = bytes / 1024;
        }
        return bytes.toFixed(precision || 2) + " " + sizes[posttxt];
    },
    /*
    * Disables HTML5 validation for stopping browsers to stop submission process
    * (fixes bug of pending submissions when jotform validator accepts email field
    * and browsers' own validator doesn't ) 
    */
    disableHTML5FormValidation: function(){
        $$("form").each(function(f){
            f.setAttribute("novalidate",true);
        });
    },
    /**
     * When button clicked take the screenshot and display it in the editor
     */
    takeScreenShot: function(id){
        var p = window.parent;          // parent window
        var pleaseWait = '<div id="js_loading" '+
                         'style="position:fixed; z-index:10000000; text-align:center; '+
                         'background:#333; border-radius:5px; top: 20px; right: 20px; '+
                         'padding:10px; box-shadow:0 0 5 rgba(0,0,0,0.5);">'+
                         '<img src="'+this.url+'images/loader-black.gif" />'+
                         '<div style="font-family:verdana; font-size:12px;color:#fff;">'+
                         'Please Wait'+
                         '</div></div>';
                         
        if(this.onprogress){
            p.$jot(pleaseWait).appendTo('body');
            return;
        }
        
        if(p.wishboxCompactLoad){
            this.compact = true;
        }
        
        if(this.screenshot){
            if(this.compact){
                p.$jot('.jt-dimmer').hide();
            }else{
                p.$jot('.jt-dimmer, .jotform-feedback-link, .jt-feedback').hide();
            }
            
            p.jotformScreenshotURL = this.screenshot.data;
            this.injectEditor(this.screenshot.data, this.screenshot.shotURL);
            return;
        }
        
        this.scuniq = JotForm.uniqid(); // Unique ID to be used in the screenshot
        this.scID   = id;               // Field if which we will place the screen shot in
        var f = JotForm.getForm($('button_'+this.scID));
        this.sformID = f.formID.value;
        this.onprogress = true;
        var $this   = this;             // Cache the scope
        //this.wishboxServer = '//ec2-107-22-70-25.compute-1.amazonaws.com/wishbox-bot.php'; 
        this.wishboxServer = 'http://screenshots.jotform.com/wishbox-server.php'; //kemal: made this http since https not working anyway
        //this.wishboxServer = "//beta23.jotform.com/server.php";//JotForm.server;
        // Create a form element to make a hidden post. We need this to overcome xDomain Ajax restrictions
        var form = new Element('form', {action:this.wishboxServer, target:'screen_frame', id:'screen_form', method:'post', "accept-charset":'utf-8'}).hide();
        // Create a syntethic doctype for page source. This is the most common doctype so I choose this
        var doc  = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" >';
        // Hide Jotform specific page element on the parent, so they do not appear on screenshot
        
        /*if(this.compact){
            p.$jot('.jt-dimmer').hide();
        }else{*/
            p.$jot('.jt-dimmer, .jotform-feedback-link, .jt-feedback').hide();
        //}
        
        p.$jot('.hide-on-screenshot, .hide-on-screenshot *').css({'visibility':'hidden'});
        // Read the source of parent window
        var parentSource = p.document.getElementsByTagName('html')[0].innerHTML;
        parentSource = parentSource.replace(/(<noscript\b[^>]*>.*?<\/noscript>)+/gim, '');         // remove single line tags
        parentSource = parentSource.replace(/(<noscript\b[^>]*>(\s+.*\s+)+)+<\/noscript>/gim, ''); // remove multi line tags
        p.$jot('.hide-on-screenshot, .hide-on-screenshot *').css({'visibility':'visible'});
        parentSource = parentSource.replace(/(\<\/head\>)/gim, "<style>body,html{ min-height: 800px; }</style>$1");
        var ie = $this.ie();     
        // When it's the broken IE use a totally different aproach but IE9 works correctly so skip it
        if(ie !== undefined && ie < 9){
            parentSource = parentSource.replace(/(\<\/head\>)/gim, "<style>*{ border-radius:0 !important; text-shadow:none !important; box-shadow:none !important; }</style>$1");
        }

        if(this.passive){
            p.$jot('.jt-dimmer, .jotform-feedback-link, .jt-feedback').show();
        }else{
            p.$jot('.jotform-feedback-link').show();
            p.$jot(pleaseWait).appendTo('body');
        }
          
        // create form elements and place the values respectively
        var html  = new Element('textarea', {name:'html'});
        
        var nozip = this.getCharset(p.document).toLowerCase() !== 'utf-8';
        
        if(nozip){
            html.value    = encodeURIComponent(doc+parentSource+"</html>");
            form.insert(new Element('input', {type:'hidden', name:'nozip'}).putValue("1"));
        }else{
            form.insert(new Element('input', {type:'hidden', name:'nozip'}).putValue("0"));
            html.value    = encodeURIComponent(p.$jot.jSEND((doc+parentSource+"</html>")));
        }
        var charset   = new Element('input', {type:'hidden', name:'charset'}).putValue(this.getCharset(p.document));
        var height    = new Element('input', {type:'hidden', name:'height'}).putValue(parseFloat(p.$jot(p).height()));
        var scrollTop = new Element('input', {type:'hidden', name:'scrollTop'}).putValue(p.$jot(p).scrollTop());
        var url       = new Element('input', {type:'hidden', name:'url'}).putValue(p.location.href);
        var uid       = new Element('input', {type:'hidden', name:'uniqID'}).putValue(this.scuniq);
        var fid       = new Element('input', {type:'hidden', name:'formID'}).putValue(this.sformID);
        var action    = new Element('input', {type:'hidden', name:'action'}).putValue("getScreenshot");
        // This is the iframe that we will submit the form into
        var iframe    = new Element('iframe', {name:'screen_frame', id:'screen_frame_id'}).hide();
        // When iframe is loaded it usually means screenshot is completed but we still need to make sure.
        iframe.observe('load', function(){
            // Let's check server if screenshot correctly created there
            $this.checkScreenShot();
        });
        
        if(p.wishboxInstantLoad && (ie === undefined || ie > 8)){
            this.injectEditor(false, false);
        }
        
        // Insert all created elements on the page and directly submit the form
        form.insert(html).insert(height).insert(scrollTop).insert(action).insert(uid).insert(url).insert(fid).insert(charset);
        $(document.body).insert(form).insert(iframe);
        form.submit();
    },
    /**
     * Send a request to server and asks if given screenshot is created
     */
    checkScreenShot: function(){
        var $this = this;
        var p = window.parent;
        var count = 10; // will try 10 times after that it will fail
        
        p.$jot.getJSON('http://screenshots.jotform.com/queue/'+this.scuniq+'?callback=?',
            function(data) {
                if(data.success === true){
                    p.$jot.getJSON(data.dataURL+'?callback=?', function(res){
                        if($this.passive === false){
                            p.jotformScreenshotURL = res.data;
                            $this.injectEditor(res.data, res.shotURL); // If screenshot is created inject the editor on the page
                        }
                        $this.screenshot = res;
                        $this.onprogress = false;
                        // Remove the form and iframe since we don't need them anymore
                        $('screen_form') && $('screen_form').remove();
                        $('screen_frame_id') && $('screen_frame_id').remove();
                    });
                }else{
                    if((data.status == 'waiting' || data.status == 'working') && --count){
                        setTimeout(function(){
                            $this.checkScreenShot(); // If not try again. {TODO: We need to limit this check}
                        }, 1000);
                    }else{
                        alert('We are under heavy load right now. Please try again later.');
                        p.$jot('.jt-dimmer, .jotform-feedback-link').show();
                        p.$jot('.jt-feedback').show('slow');
                    }
                }
            }
        );
    },
    /**
     * Injects the screenshot editor on the page and sets necessery functions for editor to use
     */
    injectEditor: function(data, url){
        
        if(this.injected){
            return;
        }
        
        this.injected = true;
        var $this = this;
        var p     = window.parent;
        p.$jot('#js_loading').remove();
        
        // Ask for editor template code
        p.$jot.getJSON(this.server+'?callback=?', {
                action : 'getScreenEditorTemplate',
                compact: this.compact
            },
            function(res) {
                var iff  = '<iframe allowtransparency="true" id="wishbox-frame" src="" '+
                           'frameborder="0" style="display:none;border:none; ';
                    if(!$this.compact){
                        iff += 'position:fixed;top:0;width:100%;height:100%;left:0;z-index:100000000;';
                    }else{
                        iff += ('position:absolute;left:0;top:10px;height:'+(p.$jot(p).height()-120)+'px;width:'+((p.$jot(p).width()-100)-p.$jot('#js-form-content').width())+'px;');
                    }
                    iff += '" scrolling="no"></iframe>';
                var editorFrame;
                
                p.iframeWidth = ((p.$jot(p).width()-100)-p.$jot('#js-form-content').width());
                p.iframeHeight = (p.$jot(p).height()-120);
                
                // create an empty iframe on the page, we will then write the contents of this iframe manually
                if($this.compact){
                    editorFrame = p.$jot(iff).insertBefore('#js-form-content');
                }else{
                    editorFrame = p.$jot(iff).appendTo('body');
                }
                
                if($this.compact){
                    p.$jot('#js-form-content').css({  // when compact
                        'float':'right'
                    });
                }
                var ie = $this.ie();
                
                // When it's the broken IE use a totally different aproach but IE9 works correctly so skip it
                if(ie !== undefined && ie < 9){
                    // Set src for iframe inseat of writing the editor template in it.
                    editorFrame.attr('src', 'http://screenshots.jotform.com/opt/templates/screen_editor.html?shot='+url+'&uniq='+$this.scuniq);
                    // Put a close button outside of the iframe
                    var b = p.$jot('<button style="color:#fff;font-size:14px;background:#F59202;border:1px solid #Fa98a2;font-weight:bold;position:fixed;top:5px;right:40px;width:100px;z-index:100000001;">Close Editor</button>').appendTo('body');
                    // When close button clicked go fetch the saved image, if image is not saved then ask user are they sure?
                    b.click(function(){
                        
                        p.$jot.getJSON('http://screenshots.jotform.com/wishbox-server.php?callback=?', {
                            action: 'getImage',
                            uniqID: $this.scuniq
                        },function(res){
                            if(!res.success){
                                if(confirm('You haven\'t save your edits. Are you sure you want to close the editor?')){
                                    closeFrame();
                                    b.remove();
                                }
                            }else{
                                closeFrame();
                                b.remove();
                                
                                putImageOnForm(res.data, res.shotURL);
                            }
                        });
                    });
                }else{
                    // Write retrieved editor template into newly created iframe
                    var e = editorFrame[0];
                    var frameDocument = (e.contentWindow) ? e.contentWindow : (e.contentDocument.document) ? e.contentDocument.document : e.contentDocument;
                    frameDocument.document.open();
                    frameDocument.document.write(res.template);
                    setTimeout(function(){ frameDocument.document.close(); }, 200);
                    
                    // Cache the screenshot URL on parent window so editor can find it
                    p.jotformScreenshotURL = data;
                }
                
                // Closes the frame and removes all trace behind it
                var closeFrame = function(){
                    if($this.compact){
                        editorFrame.remove();
                        p.$jot('#js-form-content').css('width', '100%');
//                        p.$jot('.jt-content, .jt-title').css('width', 'auto');
                    }else{
                        editorFrame.hide('slow', function(){
                            editorFrame.remove();
                        });
                    }
                    $this.injected = false;
                    p.$jot('.jt-dimmer, .jotform-feedback-link').show();
                    p.$jot('.jt-feedback').show('slow');
                };
                
                // When image saved. Places it on the form
                var putImageOnForm = function(image, url){
                   // if(!$this.compact){
                        $('screen_'+$this.scID).update('<img width="100%" align="center" src="'+(url? url : image)+'" />');
                        $('data_'+$this.scID).value = image;
                        $('screen_'+$this.scID).up().show();
                   // }
                };
                
                // Cancel  and close the editor
                p.JotformCancelEditor = function(){
                    closeFrame();
                };
                
                // When editing completed retrive the edited screenshot code and place it on the form
                p.JotformFinishEditing = function(image){
                    closeFrame();
                    putImageOnForm(image);
                    $this.imageSaved = true;
                    if($this.compact){
                        setTimeout(function(){
                            $(document).fire('image:loaded');
                        }, 100);
                    }
                };
            }
        );
    },
    
    /**
     * Will get additional URL queries from SCRIPT embed or feedback widget
     */
    populateGet: function(){
        try{
            if('FrameBuilder' in window.parent && "get" in window.parent.FrameBuilder && window.parent.FrameBuilder.get != []){

                var outVals = {};
                var getVals = window.parent.FrameBuilder.get;
                $H(getVals).each(function(pair) {
                    if(typeof pair[1] === 'object') {
                        for(prop in pair[1]) {
                            outVals[pair[0] + "[" + prop + "]"] = pair[1][prop];
                        }
                    } else {
                        outVals[pair[0]] = pair[1];
                    }


                });
                document.get = Object.extend(document.get, outVals);
            }
        }catch(e){}
    },
    
    /**
     * Check if there are any multiple upload field. if any load multiple upload script
     */
    checkMultipleUploads: function(){
        if($$('.form-upload-multiple').length > 0){
            var script = document.createElement('script');
            script.type="text/javascript";
            script.src = "https://static-interlogyllc.netdna-ssl.com/file-uploader/fileuploader.js?v7";
            $(document.body).appendChild(script);
        }
    },
    /**
     * Php.js uniqueID generator
     * @param {Object} prefix
     * @param {Object} more_entropy
     */
    uniqid: function(prefix, more_entropy){
        if (typeof prefix == 'undefined') { prefix = ""; }
        var retId;
        var formatSeed = function(seed, reqWidth){
            seed = parseInt(seed, 10).toString(16); // to hex str
            if (reqWidth < seed.length) { return seed.slice(seed.length - reqWidth); }
            if (reqWidth > seed.length) { return Array(1 + (reqWidth - seed.length)).join('0') + seed; }
            return seed;
        };
        if (!this.php_js) { this.php_js = {}; }
        if (!this.php_js.uniqidSeed) { this.php_js.uniqidSeed = Math.floor(Math.random() * 0x75bcd15); }
        this.php_js.uniqidSeed++;
        retId = prefix;
        retId += formatSeed(parseInt(new Date().getTime() / 1000, 10), 8);
        retId += formatSeed(this.php_js.uniqidSeed, 5);
        if (more_entropy) { retId += (Math.random() * 10).toFixed(8).toString(); }
        return retId;
    },

    /**
     * Initiates multiple upload scripts
     */
    initMultipleUploads: function(){

        var self = this;

        $$('.form-upload-multiple').each(function(file){
            var parent = file.up('div'); 
            var f = JotForm.getForm(file);
            var formID = f.formID.value;
            var uniq = formID+"_"+JotForm.uniqueID;
            
            // Handle default validations. reuired field
            var className = file.className;
            if(className.include("validate[required]")){
                parent.addClassName("validate[required]");
                parent.validateInput = function(){
                    // Don't fire validations for hidden elements
                    if(!JotForm.isVisible(parent)){ 
                        JotForm.corrected(parent);
                        return true; 
                    }
                    if(parent.select('.qq-upload-list li').length < 1){
                        JotForm.errored(parent, JotForm.texts.required);
                        return false;
                    }else{
                        JotForm.corrected(parent);
                        return true;
                    }
                };
            }
            
            // Create temp upload folder key 
            var hidden = new Element('input', {type:'hidden', name:'temp_upload_folder'}).setValue(uniq);
            f.insert({top:hidden});
            
            // Handle limited extensions
            var exts = (file.readAttribute('file-accept') || "").strip();
            exts = (exts !== '*')? exts.split(', ') : [];
            
            // Handle sublabels
            var n, subLabel ="";
            if((n = file.next()) && n.hasClassName('form-sub-label')){ subLabel = n.innerHTML; }
            
            //Emre: to make editing "text of multifile upload button" possible (33318)
            var m,buttonText;
            if(m = file.previous('.qq-uploader-buttonText-value')){ buttonText = m.innerHTML; }
            if(!buttonText){ buttonText = "Upload a File"; };

            // Hasan
            // Get button style class
            var classNames = file.className.split(' '),
                buttonStyle = '';
            $A(classNames).each(function (className) {
                if (className.indexOf('form-submit-button-') === 0) {
                    buttonStyle = className;
                }
            });

            // Initiate ajax uploader
            var uploader = new qq.FileUploader({
                debug: JotForm.debug,
                element: parent,
                action: JotForm.server,
                subLabel: subLabel,
                buttonText: buttonText,
                buttonStyle: buttonStyle,
                fileLimit: file.readAttribute('file-limit'),
                sizeLimit: parseInt(file.readAttribute('file-maxsize'), 10) * 1024, // Set file size limit
                allowedExtensions: exts,
                messages: {
                   typeError: self.texts.multipleFileUploads_typeError,
                   sizeError: self.texts.multipleFileUploads_sizeError,
                   minSizeError: self.texts.multipleFileUploads_minSizeError,
                   emptyError: self.texts.multipleFileUploads_emptyError,
                   onLeave: self.texts.multipleFileUploads_onLeave,
                   fileLimitError: self.texts.multipleFileUploads_fileLimitError
                },
                onComplete: function(id, aa, result){
                    if(result.success){
                        // This is needed for validations.
                        // removes reuired message
                        parent.value="uploaded";
                        JotForm.corrected(parent);
                    }
                },
                showMessage: function(message){
                    // Display errors in JotForm's way
                    JotForm.errored(parent, message);
                    setTimeout(function(){
                        // JotForm.corrected(parent);
                    }, 3000);
                },
                params: {
                    action: 'multipleUpload',
                    field: file.name.replace('[]', ''),
                    folder: uniq
                }
            });
        });
    },
    
    /**
     * Hiddenly submits the form on backend
     */
    hiddenSubmit: function(frm){
        if(JotForm.currentSection){
            JotForm.currentSection.select('.form-pagebreak')[0].insert(
                new Element('div', {className:'form-saving-indicator'})
                    .setStyle('float:right;padding:21px 12px 10px')
                    .update('<img src="'+JotForm.url+'images/ajax-loader.gif" align="absmiddle" /> Saving...')
            );
        }
        
        /**
         * Wait just a little to set saving status. 
         * We need this because of the back button hack for last page. 
         * Last page back button has two click events they both should work 
         * but saving status prevents second one to be working
         */
        setTimeout(function(){ JotForm.saving = true; }, 10);
        
        if(!$('hidden_submit_form')){
            var iframe = new Element('iframe', {name:'hidden_submit', id:'hidden_submit_form'}).hide();
            iframe.observe('load', function(){
                JotForm.makeUploadChecks();
                $$('.form-saving-indicator').invoke('remove');
                JotForm.saving = false;
            });
            $(document.body).insert(iframe);
        }
        $('current_page').value = JotForm.currentSection.pagesIndex;
        frm.writeAttribute('target', 'hidden_submit');
        frm.insert({
            top: new Element('input', {
                type: 'hidden',
                name: 'hidden_submission',
                id:   'hidden_submission'
            }).putValue("1")
        });
        
        frm.submit();
        frm.writeAttribute('target', '');
        $('hidden_submission').remove();
    },
    /**
     * Checks the upload fields after hidden submission
     * If they are completed, then makes them empty to prevent
     * Multiple upload of the same file
     */
    makeUploadChecks: function(){
        var formIDField = $$('input[name="formID"]')[0];
        var a = new Ajax.Jsonp(JotForm.url+'server.php', {
            parameters: {
                action: 'getSavedUploadResults',
                formID: formIDField.value,
                sessionID: document.get.session
            },
            evalJSON: 'force',
            onComplete: function(t){
                var res = t.responseJSON;
                if (res.success) {                    
                    if(res.submissionID && !$('submission_id')){
                        formIDField.insert({
                            after: new Element('input', {
                                type: 'hidden',
                                name: 'submission_id',
                                id:   'submission_id'
                            }).putValue(res.submissionID)
                        });                        
                    }
                    JotForm.editMode(res, true); // Don't reset fields
                }
            }
        });
    },
    /**
     * Handles the form being saved stuation
     */
    handleSavedForm: function(){
        
        if(!('session' in document.get) || !(document.get.session.length > 0)){
            return;
        }
        JotForm.saveForm = true;
        
        var formIDField = $$('input[name="formID"]')[0];
        
        formIDField.insert({
            after: new Element('input', {
                type: 'hidden',
                name: 'session_id',
                id:  "session"
            }).putValue(document.get.session)
        });
        
        formIDField.insert({
            after: new Element('input', {
                type: 'hidden',
                id:'current_page',
                name: 'current_page'
            }).putValue(0)
        });
        
        var a = new Ajax.Jsonp(JotForm.url+'server.php', {
            parameters: {
                action: 'getSavedSubmissionResults',
                formID: formIDField.value,
                sessionID: document.get.session,
                URLparams: window.location.href
            },
            evalJSON: 'force',
            onComplete: function(t){
                var res = t.responseJSON;
                if (res.success) {
                    if(res.submissionID){
                        formIDField.insert({
                            after: new Element('input', {
                                type: 'hidden',
                                name: 'submission_id',
                                id:   'submission_id'
                            }).putValue(res.submissionID)
                        });    

                        try{
                            JotForm.editMode(res);
                        }catch(e){
                            console.error(e);
                        }
                        JotForm.openInitially = res.currentPage - 1;                    
                    }
                    
                }
            }
        });
    },
    /**
     * Place the form title on pages title to remove the Form text on there
     */
    setTitle: function(){
        // Do this only when page title is form. otherwise it can overwrite the users own title
        if(document.title == "Form"){
            var head;
            if((head = $$('.form-header')[0])){
                try{
                    document.title = head.innerHTML.stripTags().strip();
                    document.title = document.title.unescapeHTML();
                }catch(e){
                    document.title = head.innerHTML;
                }
            }
        }
    },
    
    /**
     * Sets the last focus event to keep latest focused element
     */
    setFocusEvents: function(){
        $$('.form-radio, .form-checkbox').each(function(input){ //Neil: use mousedown event for radio & checkbox (Webkit bug:181934)
            input.observe('mousedown', function(){
                JotForm.lastFocus = input;
            })  
        });
        $$('.form-textbox, .form-password, .form-textarea, .form-upload, .form-dropdown').each(function(input){
            input.observe('focus', function(){
                JotForm.lastFocus = input;
            });
        });
    },
    /** 
    * Disables Accept for Google Chrome browsers
    */
    disableAcceptonChrome: function(){
        if (!Prototype.Browser.WebKit) { return; }
        $$('.form-upload').each(function(input){
            if (input.hasAttribute('accept')) {
                var r = input.readAttribute('accept');
                input.writeAttribute('accept', '');
                input.writeAttribute('file-accept', r);
            }
        });
    },

    /**
     * Populate hidden field with user's browser info
     */
    populateBrowserInfo:function(id) {
        var OS = "Unknown OS";
        if (navigator.appVersion.indexOf("iPhone")!=-1) OS ="iOS iPhone";
        else if (navigator.appVersion.indexOf("iPad")!=-1) OS ="iOS iPad";
        else if (navigator.appVersion.indexOf("Android")!=-1) OS ="Android";
        else if (navigator.appVersion.indexOf("Win")!=-1) OS ="Windows";
        else if (navigator.appVersion.indexOf("Mac")!=-1) OS ="MacOS";
        else if (navigator.appVersion.indexOf("Linux")!=-1) OS ="Linux";

        var browser = "Unknown Browser";
        if(navigator.userAgent.indexOf("MSIE") !=-1) browser = "Internet Explorer";
        else if(navigator.userAgent.indexOf("Firefox") !=-1) browser ="Firefox";
        else if(navigator.userAgent.indexOf("Chrome") !=-1) browser ="Chrome";
        else if(navigator.userAgent.indexOf("Safari") !=-1) browser ="Safari";
        else if(navigator.userAgent.indexOf("Opera") !=-1) browser ="Opera";

        var offset = new Date().getTimezoneOffset();
        var sign = (offset < 0)?"+":"";
        var timeZone = 'GMT ' + sign +  -(offset/60);

        var lang = navigator.language || navigator.browserLanguage || navigator.userLanguage;

        var val = 'BROWSER: ' + browser + "\n";
        val += 'OS: ' + OS + "\n";
        val += 'LANGUAGE: ' + lang + "\n";  
        val += 'RESOLUTION: ' + screen.width + "*" + screen.height + "\n";
        val += 'TIMEZONE: ' + timeZone + "\n";
        val += 'USER AGENT: ' + navigator.userAgent + "\n";
        if($(id).value.length > 0)
            $(id).value += "\n";    
        $(id).value += val;
    },

    /**
     * Show Difference Between time ranges
     */
    displayTimeRangeDuration:function(id) {
        var displayDuration = function() {
            if($('input_'+id+'_hourSelectRange')) {
                var sHour = $('input_'+id+'_hourSelect').value;
                var sMin = $('input_'+id+'_minuteSelect').value;
                var sAMPM = $('input_'+id+'_ampm')?$('input_'+id+'_ampm').value:'no';
                var eHour = $('input_'+id+'_hourSelectRange').value;
                var eMin = $('input_'+id+'_minuteSelectRange').value;
                var eAMPM = $('input_'+id+'_ampmRange')?$('input_'+id+'_ampmRange').value:'no';
                var lab = $('input_'+id+'_ampmRange')?'_ampmRange':'_dummy';
                if(sHour.length > 0 && sMin.length > 0 && eHour.length > 0 && eMin.length > 0) {
                    if(sAMPM == 'PM' && sHour != 12) sHour = parseInt(sHour) + 12;
                    if(sAMPM == 'AM' && sHour == 12) sHour = 0;
                    if(eAMPM == 'PM' && eHour != 12) eHour = parseInt(eHour) + 12;
                    if(eAMPM == 'AM' && eHour == 12) eHour = 0;

                    var start = new Date(0, 0, 0, sHour, sMin, 0);
                    var end = new Date(0, 0, 0, eHour, eMin, 0);
                    var diff = end.getTime() - start.getTime();
                    if(diff < 0) { //end time is next day
                        end = new Date(0, 0, 1, eHour, eMin, 0);
                        diff = end.getTime() - start.getTime();
                    }
                    var hours = Math.floor(diff/1000/60/60);
                    diff -= hours*1000*60*60;
                    var min = Math.floor(diff / 1000 / 60);
                    if(min < 10) min = '0' + min;
                    $$('label[for=input_'+id+lab+']').first().update('<b>Total '+hours+':'+min+'</b>');
                    $$('label[for=input_'+id+lab+']').first().setStyle({'color': 'black'});
                } else {
                    $$('label[for=input_'+id+lab+']').first().update('&nbsp');
                }
            }
        };
        $('input_'+id+'_hourSelect').observe('change', displayDuration);
        $('input_'+id+'_minuteSelect').observe('change', displayDuration);
        $('input_'+id+'_hourSelectRange').observe('change', displayDuration);
        $('input_'+id+'_minuteSelectRange').observe('change', displayDuration);
        if($('input_'+id+'_ampm') && $('input_'+id+'_ampmRange')) {
            $('input_'+id+'_ampm').observe('change', displayDuration);
            $('input_'+id+'_ampmRange').observe('change', displayDuration);
        }
    },

    
    /**
     * Set current local time if nodefault not set
     */
    displayLocalTime:function(hh, ii, ampm) {
        if($(hh) && !$(hh).hasClassName('noDefault')) {
            var date = new Date();
            var hour = date.getHours();

            var currentAmpm = "";
            var twentyFour = true;
            if($(ampm)) {
                twentyFour = false;
                currentAmpm = (hour>11)?'PM':'AM';  
                hour = (hour>12)?hour-12:hour;
                hour = (hour == 0)?12:hour;
            }

            var min = date.getMinutes();
            var step = Number($(ii).options[2].value) - Number($(ii).options[1].value);
            min = Math.round(min/step) * step;
            min = this.addZeros(min, 2);
            if(min >= 60) { //ntw roll over to next hour/day
                min = "00";
                hour++;
                if(twentyFour){
                    if(hour == 24) hour = 0;
                } else {
                    if(currentAmpm == 'AM' && hour == 12) currentAmpm = 'PM';
                    else if(currentAmpm == 'PM' && hour == 12) currentAmpm = 'AM';
                    else if(hour == 13) hour = 1;
                }
            }

            $(hh).value = hour;
            $(ii).value = min;

            if($(hh + 'Range')) {
                $(hh + 'Range').value = hour;
                $(ii + 'Range').value = min;
            }
            if($(ampm)) {
                if(currentAmpm == 'PM') {
                    if($(ampm).select('option[value="PM"]').length > 0) $(ampm).value = 'PM';
                    if($(ampm + 'Range') && $(ampm + 'Range').select('option [value=PM]').length > 0) $(ampm + 'Range').value = 'PM';
                } else {
                    if($(ampm).select('option[value="AM"]').length > 0) $(ampm).value = 'AM';
                    if($(ampm + 'Range') && $(ampm + 'Range').select('option [value=AM]').length > 0) $(ampm + 'Range').value = 'AM';
                }
            }
        }
    },

    /**
     * Sets calendar to field
     * @param {Object} id
     */
    setCalendar: function(id, startOnMonday){
        try{
            var calendar = Calendar.setup({
                triggerElement:"input_" + id + "_pick",
                dateField:"year_" + id,
                closeHandler:JotForm.calendarClose,
                selectHandler:JotForm.formatDate,
                startOnMonday:startOnMonday
            });
            $('id_'+id).observe('keyup', function(){
                $('id_'+id).fire('date:changed');
            });
            if(! $('day_' + id).hasClassName('noDefault')){
                JotForm.formatDate({date:(new Date()), dateField:$('id_' + id)});
            }
            var openCalendar = function() {
                if (document.createEvent) {
                    var ele = this;
                    setTimeout(function() {
                        calendar.showAtElement(ele);
                    }, 50);
                }
            };
            if($('input_' + id + '_pick').hasClassName('showAutoCalendar')) {
                $('day_' + id).observe('focus', openCalendar);
                $('day_' + id).observe('click', openCalendar);
                $('month_' + id).observe('focus', openCalendar);
                $('month_' + id).observe('click', openCalendar);
                $('year_' + id).observe('focus', openCalendar);
                $('year_' + id).observe('click', openCalendar);
            }
            $('day_' + id).observe('blur', function() {JotForm.calendarClose(calendar);});
            $('month_' + id).observe('blur', function() {JotForm.calendarClose(calendar);});
            $('year_' + id).observe('blur', function() {JotForm.calendarClose(calendar);});
        }catch(e){
            JotForm.error(e);
        }
    },

    /**
     * load current date to datetime fields 
     * if element is set to read only
     */
    currentDateReadonly: function(id){
        try{
            if(! $('day_' + id).hasClassName('noDefault')){
                var date = new Date();
                var month = this.addZeros(date.getMonth() + 1, 2);
                var day = this.addZeros(date.getDate(), 2);
                var year = date.getYear() < 1000 ? date.getYear() + 1900 : date.getYear();

                $('month_' + id).value = month;
                $('day_' + id).value = day;
                $('year_' + id).value = year;
            }
        }catch(e){
            JotForm.error(e);
        }
    },

    calendarClose: function(calendar){
        var validations = calendar.dateField.className.replace(/.*validate\[(.*)\].*/, '$1').split(/\s*,\s*/);
        if(validations.include("required") || validations.include("disallowPast")) {
            calendar.dateField.validateInput();
        }
        calendar.hide();
    },

    /**
     * Collects all inital values of the fields and saves them as default values
     * to be restored later
     */
    getDefaults: function(){
        $$('.form-textbox, .form-dropdown, .form-textarea').each(function(input){
            if(input.hinted || input.value === ""){ return; /* continue; */ }
            
            JotForm.defaultValues[input.id] = input.value;
        });

        $$('.form-radio, .form-checkbox').each(function(input){
            if(!input.checked){ return; /* continue; */ }
            JotForm.defaultValues[input.id] = input.value;
        });
    },
    /**
     * Enables or disables the Other option on radiobuttons/checkboxes
     */
    handleOtherOptions: function(){
        
        $$('.form-radio-other-input, .form-checkbox-other-input').each(function(inp){
            inp.hint(inp.getAttribute('data-otherHint') || 'Other');
        });
        
        $$('.form-radio, .form-checkbox').each(function(input){
            
            var id = input.id.replace(/input_(\d+)_\d+/gim, '$1');
            
            if(id.match('other_')){
                id = input.id.replace(/other_(\d+)/, '$1');
            }
            
            if($('other_'+id)){
                var other = $('other_'+id);
                var other_input = $('input_'+id);
                var otherOption = input.type === 'radio' ? input : other;
                other_input.observe('keyup',function(){
                   other.value = other_input.value; 
                });
                other_input.observe('blur', function(){
                    other_input.value = other_input.value || other_input.getAttribute('data-otherHint');
                });
                other_input.observe('click', function(){
                    $('other_'+id).checked = true;
                    other_input.value = other_input.value === other_input.getAttribute('data-otherHint') ? '' : other_input.value;
                });
                // perform only on the "Other" option if input is check box
                otherOption.observe('click', function(){
                    
                    if(other.checked){
                        other_input.select();
                    }else{
                        if(other_input.hintClear){ other_input.hintClear(); }
                    }
                });
            }
        });
    },

    handleDateTimeChecks: function() {
        $$('[name$=\[month\]]').each(function(monthElement) {
            var questionId = monthElement.id.split('month_').last();
            var dateElement = $('id_' + questionId);
            if (!dateElement)
                return;

            var dayElement = dateElement.select('#day_' + questionId).first();
            var yearElement = dateElement.select('#year_' + questionId).first();
            var hourElement = dateElement.select('#hour_' + questionId).first();
            var minElement = dateElement.select('#min_' + questionId).first();
            var ampmElement = dateElement.select('#ampm_' + questionId).first();

            var dateTimeCheck = function() {
                var erroredElement = null;

                if (monthElement.value != "" || dayElement.value != "" || yearElement.value != "") {

                    var month = +monthElement.value;
                    var day = +dayElement.value;
                    var year = +yearElement.value;

                    if (isNaN(year) || year < 0) {
                        erroredElement = yearElement;
                    } else if (isNaN(month) || month < 1 || month > 12) {
                        erroredElement = monthElement;
                    } else if (isNaN(day) || day < 1) {
                        erroredElement = dayElement;
                    } else {
                        switch (month) {
                            case 2:
                                if ((year % 4 == 0) ? day > 29 : day > 28) {
                                    erroredElement = dayElement;
                                }
                                break;
                            case 4:
                            case 6:
                            case 9:
                            case 11:
                                if (day > 30) {
                                    erroredElement = dayElement;
                                }                            
                                break;
                            default:
                                if (day > 31) {
                                    erroredElement = dayElement;
                                }
                                break;
                        }
                    }
                }

                if (!erroredElement && hourElement && minElement && (hourElement.value != "" || minElement.value != "")) {
                    var hour = (hourElement.value.strip() == '') ? -1 : +hourElement.value;
                    var min = (minElement.value.strip() == '') ? - 1 : +minElement.value;
                    if (isNaN(hour) || (ampmElement ? (hour < 0 || hour > 12) : (hour < 0 || hour > 23))) {
                        erroredElement = hourElement;
                    } else if (isNaN(min) || min < 0 || min > 59) {
                        erroredElement = minElement;
                    }
                }

                if (erroredElement) {
                    if(erroredElement === hourElement || erroredElement === minElement) {
                        erroredElement.errored = false;
                        JotForm.errored(erroredElement, 'Enter a valid time');
                    } else {
                        erroredElement.errored = false;
                        JotForm.errored(erroredElement, 'Enter a valid date');
                    }
                    dateElement.addClassName('form-line-error');
                    dateElement.addClassName('form-datetime-validation-error');
                } else {
                    JotForm.corrected(monthElement);
                    JotForm.corrected(dayElement);
                    JotForm.corrected(yearElement);
                    if (hourElement && minElement) {
                        JotForm.corrected(hourElement);
                        JotForm.corrected(minElement);    
                    }
                    dateElement.removeClassName('form-line-error');
                    dateElement.removeClassName('form-datetime-validation-error');
                }
            };

            //fired when date is changed by calendar
            dateElement.observe('date:changed', dateTimeCheck);

            monthElement.observe('change', dateTimeCheck);
            dayElement.observe('change', dateTimeCheck);
            yearElement.observe('change', dateTimeCheck);
            if (hourElement && minElement) {
                hourElement.observe('change', dateTimeCheck);
                minElement.observe('change', dateTimeCheck);                
            }
        });
    },
    
    handleTextareaLimits: function(){
        $$('.form-textarea-limit-indicator span').each(function(el){
            var inpID = el.id.split('-')[0];
            if(!$(inpID)){return;} // cannot find the main element
            var limitType = el.readAttribute('type');
            var limit     = el.readAttribute('limit');
            var input = $(inpID);
            var count;

            var countText = function(){
                if(input.hasClassName('form-custom-hint')) {
                    el.update("0/" + limit);
                    return;
                }

                var contents;
                if(input.hasClassName("form-textarea") && input.up('div').down('.nicEdit-main')) { //rich text
                    contents = input.value.stripTags().replace(/&nbsp;/g, ' ');
                } else {
                    contents = input.value;
                }

                // remove html tags and space chars, to prevent wrong counts on text copied from MS WORD
                var cleaned_contents = contents.replace(/<.[^<>]*?>/g, ' ').replace(/&nbsp;|&#160;/gi, ' '); 

                if(limitType == 'Words'){
                    count = $A(cleaned_contents.split(/\s+/)).without("").length;
                }else if(limitType == 'Letters'){
                    count = cleaned_contents.length;
                }
                if(count > limit){
                    $(el.parentNode).addClassName('form-textarea-limit-indicator-error');
                    var msg = limitType === 'Words' ? JotForm.texts.wordLimitError : JotForm.texts.characterLimitError;
                    JotForm.errored(el.up('.form-line').down('textarea'), msg+" "+limit+'.');
                }else{
                    $(el.parentNode).removeClassName('form-textarea-limit-indicator-error');
                    JotForm.corrected(el.up('.form-line').down('textarea'));
                }
                el.update(count + "/" + limit);
            };
            countText();
            input.observe('change', countText);
            input.observe('focus', countText);
            input.observe('keyup', countText);

            //check whether rich text
            if(input.hasClassName("form-textarea") && input.up('div').down('.nicEdit-main')) {
                var cEditable = input.up('div').down('.nicEdit-main');
                cEditable.observe('keyup', function() {
                    input.value = cEditable.innerHTML;
                    countText();
                });
            }
        });
    },
    
    /**
     * Activates all autocomplete fields
     */
    handleAutoCompletes: function(){
        // Get all autocomplete fields
        $H(JotForm.autoCompletes).each(function(pair){
            var el = $(pair.key); // Field itself
            
            el.writeAttribute('autocomplete', 'off');
            
            var parent = $(el.parentNode); // Parent of the field for list to be inserted
            var values = $A(pair.value.split('|')); // Values for auto complete
            
            var lastValue; // Last entered value
            var selectCount = 0; // Index of the currently selected element
            //parent.setStyle('position:relative;z-index:1000;'); // Set parent position to relative for inserting absolute positioned list
            var liHeight = 0; // Height of the list element
            
            // Create List element with must have styles initially
            var list = new Element('div', {
                className: 'form-autocomplete-list'
            }).setStyle({
                listStyle: 'none',
                listStylePosition: 'outside',
                position: 'absolute',
                zIndex: '10000'
            }).hide();
            
            var render = function(){
                
                var dims = el.getDimensions(); // Dimensions of the input box
                var offs = el.cumulativeOffset();
                
                list.setStyle({
                    top: ((dims.height+offs[1])) + 'px',
                    left:offs[0]+'px',
                    width: ((dims.width < 1? 100 : dims.width) - 2) + 'px'
                });
                list.show();
            };
            
            // Insert list onto page
            // parent.insert(list);
            $(document.body).insert(list);
            
            list.close = function(){
                list.update();
                list.hide();
                selectCount = 0;
            };
            
            // Hide list when field get blurred
            el.observe('blur', function(){
                list.close();
            });
            
            // Search entry in values when user presses a key
            el.observe('keyup', function(e){
                var word = el.value;
                // If entered value is the same as the old one do nothing
                if (lastValue == word) {
                    return;
                }
                lastValue = word; // Set last entered word
                list.update(); // Clean up the list first
                if (!word) {
                    list.close();
                    return;
                } // If input is empty then close the list and do nothing
                // Get matches
                
                var fuzzy = el.readAttribute('data-fuzzySearch') == 'Yes';
                var matches;
                
                if (fuzzy) {
                    matches = values.collect(function(v) {
                    if (v.toLowerCase().include(word.toLowerCase())) {
                        return v;
                    }
                }).compact();
                } else {
                    matches = values.collect(function(v) {
                        if (v.toLowerCase().indexOf(word.toLowerCase()) == 0){
                            return v;
                        }
                    }).compact();
                }
                // If matches found
                var maxMatches = el.readAttribute('data-maxMatches');
                if(maxMatches > 0) matches = matches.slice(0,maxMatches);
                if (matches.length > 0) {
                    matches.each(function(match){
                        var li = new Element('li', {
                            className: 'form-autocomplete-list-item'
                        });
                        var val = match;
                        li.val = val;
                        try {
                            val = match.replace(new RegExp('(' + word + ')', 'gim'), '<b>$1</b>');
                        } 
                        catch (e) {
                            JotForm.error(e);
                        }
                        li.insert(val);
                        li.onmousedown = function(){
                            el.value = match;
                            list.close();
                        };
                        list.insert(li);
                    });
                    
                    render();
                    
                    // Get li height by adding margins and paddings for calculating 10 item long list height
                    liHeight = liHeight || $(list.firstChild).getHeight() + (parseInt($(list.firstChild).getStyle('padding'), 10) || 0) + (parseInt($(list.firstChild).getStyle('margin'), 10) || 0);
                    // limit list to show only 10 item at once        
                    list.setStyle({
                        height: (liHeight * ((matches.length > 9) ? 10 : matches.length) + 4) + 'px',
                        overflow: 'auto'
                    });
                } else {
                    list.close(); // If no match found clean the list and close
                }
            });
            
            // handle navigation through the list
            el.observe('keydown', function(e){
                
                //e = document.getEvent(e);
                var selected; // Currently selected item
                // If the list is not visible or list empty then don't run any key actions
                if (!list.visible() || !list.firstChild) {
                    return;
                }
                
                // Get the selected item
                selected = list.select('.form-autocomplete-list-item-selected')[0];
                if(selected){ selected.removeClassName('form-autocomplete-list-item-selected'); }
                
                switch (e.keyCode) {
                    case Event.KEY_UP: // UP
                        if (selected && selected.previousSibling) {
                            $(selected.previousSibling).addClassName('form-autocomplete-list-item-selected');
                        } else {
                            $(list.lastChild).addClassName('form-autocomplete-list-item-selected');
                        }
                        
                        if (selectCount <= 1) { // selected element is at the top of the list
                            if (selected && selected.previousSibling) {
                                $(selected.previousSibling).scrollIntoView(true);
                                selectCount = 0; // scroll element into view then reset the number
                            } else {
                                $(list.lastChild).scrollIntoView(false);
                                selectCount = 10; // reverse the list
                            }
                        } else {
                            selectCount--;
                        }
                        
                        break;
                    case Event.KEY_DOWN: // Down
                        if (selected && selected.nextSibling) {
                            $(selected.nextSibling).addClassName('form-autocomplete-list-item-selected');
                        } else {
                            $(list.firstChild).addClassName('form-autocomplete-list-item-selected');
                        }
                        
                        if (selectCount >= 9) { // if selected element is at the bottom of the list
                            if (selected && selected.nextSibling) {
                                $(selected.nextSibling).scrollIntoView(false);
                                selectCount = 10; // scroll element into view then reset the number
                            } else {
                                $(list.firstChild).scrollIntoView(true);
                                selectCount = 0; // reverse the list
                            }
                        } else {
                            selectCount++;
                        }
                        break;
                    case Event.KEY_ESC:
                        list.close(); // Close list when pressed esc
                        break;
                    case Event.KEY_TAB:
                    case Event.KEY_RETURN:
                        if (selected) { // put selected field into the input bıx
                            el.value = selected.val;
                            lastValue = el.value;
                        }
                        list.close();
                        if (e.keyCode == Event.KEY_RETURN) {
                            e.stop();
                        } // Prevent return key to submit the form
                        break;
                    default:
                        return;                
                }
            });
        });
        
    },
    
    /**
     * Returns the extension of a file
     * @param {Object} filename
     */
    getFileExtension: function(filename){
        return (/[.]/.exec(filename)) ? (/[^.]+$/.exec(filename))[0] : undefined;
    },
    
    /**
     * Fill fields from the get values prepopulate
     */
    prePopulations: function(){
{       // Event simulator
        Element.prototype.triggerEvent = function(eventName){
            if (document.createEvent) {
                var evt = document.createEvent('HTMLEvents');
                evt.initEvent(eventName, true, true);
                return this.dispatchEvent(evt);
            }
            if (this.fireEvent) {
                return this.fireEvent('on' + eventName);
            }
        }
}
        $H(document.get).each(function(pair){
            // Will skip very short URL keys to avoid mix-ups
            if(pair.key.length < 3){ return; /* continue; */ }
            
            var n = '[name*="_' + pair.key + '"]';
            var input;

            input = $$('.form-star-rating'+n)[0];
            if(input) {
                input.setRating(parseInt(pair.value));
                return;
            }

            input = $$('.form-slider'+n)[0]; //Add classname in builder?
            if(input) {
                input.setSliderValue(parseInt(pair.value));
                return;
            }

            input = $$('.form-textbox%s, .form-dropdown%s, .form-textarea%s, .form-hidden%s'.replace(/\%s/gim, n))[0];

            if(!input && pair.key.indexOf("[") > 0) {
                var name = pair.key.substr(0, pair.key.lastIndexOf('['));
                if(name.length > 0 && $$("select[name*="+name+"], input[name*="+name+"]").length > 0 ) {
                    var index = pair.key.substr(pair.key.lastIndexOf('[')+1).replace("]", "");
                    if($$("select[name*="+name+"], input[name*="+name+"]").length > index) {
                        var type = $$("select[name*="+name+"]").length > 0 ? "select" : $$("input[name*="+name+"]")[index].type;

                        switch (type) {
                            case "select":
                                $$("select[name*="+name+"]")[index].value = pair.value.replace(/\+/g, ' ');
                                break;
                            case "text":
                            case "tel":
                                $$("input[name*="+name+"]")[index].value = pair.value.replace(/\+/g, ' ');
                                break;
                            case "radio":
                            case "checkbox":
                                $$("input[name*="+name+"]")[index].checked = (pair.value == "true" || pair.value == 1);
                                break;
                        } 
                    }
                }
            }

            if(input && input.readAttribute('data-type') == 'input-grading') {
                var grades = pair.value.split(',');
                var stub = input.id.substr(0, input.id.lastIndexOf('_')+1);
                for(var i=0; i<grades.length; i++) {
                    if($(stub + i)) $(stub + i).value = grades[i];
                }
            } else if(input && (input.hasClassName('form-checkbox-other-input') || input.hasClassName('form-radio-other-input'))) {
                if(n.indexOf('[other]') > -1) {
                    input.value = pair.value.replace(/\+/g, ' ');
                    JotForm.defaultValues[input.id] = input.value;
                }
            } else if(input && input.hasClassName("form-textarea") && input.up('div').down('.nicEdit-main')) {
                input.up('div').down('.nicEdit-main').update(pair.value.replace(/\+/g, ' '));
            } else if (input) {
                input.value = pair.value.replace(/\+/g, ' ');
                JotForm.defaultValues[input.id] = input.value;
            }
            $$('.form-textbox%s, .form-textarea%s, .form-hidden%s'.replace(/\%s/gim, n)).each(function(input){
                //simulate 'keyup' event to execute conditions upon prepopulation
                input.triggerEvent('keyup');
            });
            $$('.form-dropdown%s'.replace(/\%s/gim, n)).each(function(input){
                //simulate 'change' event to execute conditions upon prepopulation
                input.triggerEvent('change');
            });
            $$('.form-checkbox%s, .form-radio%s'.replace(/\%s/gim, n)).each(function(input){
                //input.checked = $A(pair.value.split(',')).include(input.value);
                //Emre: when checkboxed is checked, total count does not increase on payment forms  (79814)
                if($A(pair.value.split(',')).include(input.value)){
                    input.click();
                } else if($A(pair.value.split(',')).include('other')) {
                    if((input.name.indexOf('[other]') > -1) || (input.id && input.id.indexOf('other_') > -1)) {
                        input.click(); //select other option
                    }
                }
            });

            //if textarea is hinted and has content remove the hint class
            if(input && input.hasClassName('form-textarea') && input.hasClassName('form-custom-hint') && input.hasContent) {
                input.removeClassName('form-custom-hint');
            }
        });
    },
    /**
     * Reset form while keeping the values of hidden fields
     * @param {Object} frm
     */
    resetForm: function(frm){
        var hiddens = $(frm).select('input[type="hidden"]');
        hiddens.each(function(h){ h.__defaultValue = h.value; });
        $(frm).reset();
        hiddens.each(function(h){ h.value = h.__defaultValue; });
        return frm;
    },
    /**
     * Bring the form data for edit mode
     *
     * dynamically load editMode function from form.edit.mode.js
     * it will add a function named editModeFunction to global scope
     */
    editMode: function(data, noreset, skipField){
        if(this.url.search("https") == -1){
          var preLink = "http://max.jotfor.ms/";
        }else{
          var preLink = "https://static-interlogyllc.netdna-ssl.com/";
        }

        if(!window.editModeFunction) {
            var self = this;
            this.loadScript(preLink + '/js/form.edit.mode.js?v_'+(new Date()).getTime(), function() {
                //editModeFunction is function name defined in form.edit.mode.js
                self.editMode = editModeFunction;
                self.editMode(data, noreset, skipField);
            });
        } else {
            self.editMode(data, noreset, skipField);
        }
    },
    /**
     * add the given condition to conditions array to be used in the form
     * @param {Object} qid id of the field
     * @param {Object} condition condition array
     */
    setConditions: function(conditions){

        conditions.reverse();

        JotForm.conditions = conditions;
         // Ozan, IMPORTANT NOTE: To enable chainig multiple field/email actions to a single/multiple conditions,
         // any "condition.action" is expected to be an array, regardless of "condition.type". Since old conditions
         // are stored in the database with a single action, "condition.action" is converted to an array, concatting 
         // the only action which condition has.
        conditions.each(function(condition) {
            condition.action = [].concat(condition.action); 
        });
    },

    setCalculations: function(calculations) {
        JotForm.calculations = calculations;
    },

    runConditionForId: function(id) {
        $H(JotForm.fieldConditions).each(function(pair){
            var conds = pair.value.conditions;
            $A(conds).each(function(cond){
                $A(cond.terms).each(function(term) {
                    if(term.field === id) {
                        JotForm.checkCondition(cond);
                    }
                });
            });
        });
    },

    otherConditionTrue: function(field, visibility) {
        var otherConditionTrue = false;
        $H(JotForm.fieldConditions).each(function(pair){
            var conds = pair.value.conditions;
            $A(conds).each(function(cond){
                $A(cond.action).each(function(action) {
                    if(action.field === field && action.visibility.toLowerCase() === visibility && action.hasOwnProperty('currentlyTrue') && action.currentlyTrue) {
                        otherConditionTrue = true;
                    }
                });
            });
        });
        return otherConditionTrue;
    },

    /**
     * Shows a field
     * @param {Object} field
     */
    showField: function(field){
        if(JotForm.otherConditionTrue(field, 'hide')) return;
        
        var element = null;
        var idField = $('id_' + field);
        var cidField = $('cid_' + field);
        var sectionField = $('section_' + field);

        if (sectionField && cidField) { // Form collapse
            element = sectionField;
        } else if (cidField && !idField) { // Heading
            element = cidField;
        } else { // Regular field
            element = idField;
        }

        if (!element) {
            return element;
        }

        element.removeClassName('form-field-hidden');
        
        // kemal:bug::#145986 Form collapse bug
        if(sectionField){
            if(element.hasClassName('form-section-closed')){ //if a closed form-section
                //check for .form-collapse-table has class form-collapse-hidden
                if(element.select('.form-collapse-table')[0].hasClassName('form-collapse-hidden')){
                    //element is hidden remove class add class
                    element.removeClassName('form-section-closed');
                    element.addClassName('form-section');
                    element.setStyle({
                        height:"auto",
                        overflow:"hidden"
                    });
                }else{
                    //element is visible do not add auto height
                    element.setStyle({
                        overflow:"hidden"
                    });
                }
            }else{
                //case for status = closed
                element.setStyle({
                    height:"auto",
                    overflow:"hidden"
                });
            }   
        }

        if(JotForm.getInputType(field) === 'widget') {
            JotForm.showWidget(field);
        }

        return element.show();
    },


    showWidget: function(id) {
        var referrer = document.getElementById("customFieldFrame_"+id) ? document.getElementById("customFieldFrame_" + id).src : false;
        var frame = (navigator.userAgent.indexOf("Firefox")!=-1) ? getIframeWindow(window.frames["customFieldFrame_" + id]) : window.frames["customFieldFrame_" + id];
        if(referrer && frame) {
            XD.postMessage(JSON.stringify({type:"show", qid: id}), referrer, frame);
        }
    },
    
    /**
     * Hides a field
     * @param {Object} field
     */
    hideField: function(field){
        if(JotForm.otherConditionTrue(field, 'show')) return;

        var idPrefix = 'id_';
        
        // For headings
        if($('cid_'+field) && !$('id_'+field)){
            idPrefix = 'cid_';
        }

       // For form collapses
        if($('cid_'+field) && $('section_'+field)){
            idPrefix='section_';
        }
        var element = $(idPrefix+field);
        
        if(element) {
            element.addClassName('form-field-hidden');
            return element.hide();
        }
    },
    
    /**
     * Checks the fieldValue by given operator string
     * @param {Object} operator
     * @param {Object} condValue
     * @param {Object} fieldValue
     */
    checkValueByOperator: function(operator, condValueOrg, fieldValueOrg){
        
        var fieldValue = Object.isBoolean(fieldValueOrg)? fieldValueOrg : fieldValueOrg.toString().strip().toLowerCase();
        var condValue  = Object.isBoolean(condValueOrg)? condValueOrg : condValueOrg.toString().strip().toLowerCase();

        // JotForm.log('if "%s" %s "%s"', fieldValue, operator, condValue, "\t\t\t=> Originals:", "Field: '", fieldValueOrg, "', Cond: '", condValueOrg,"'");

        switch (operator) {
            case "equals":
            case "quantityEquals":
            case "equalDate":
                return fieldValue == condValue;
            case "equalDay":
                return JotForm.getDayOfWeek(fieldValue) == condValue;
            case "notEquals":
            case "notEqualDate":
            case "quantityNotEquals":
                return fieldValue != condValue;
            case "notEqualDay":
                return JotForm.getDayOfWeek(fieldValue) != condValue;
            case "endsWith":
                return fieldValue.endsWith(condValue);
            case "notEndsWith":
                return !fieldValue.endsWith(condValue);
            case "startsWith":
                return fieldValue.startsWith(condValue);
            case "notStartsWith":
                return !fieldValue.startsWith(condValue);                
            case "contains":
                condValues = condValue.split(",");
                return $A(condValues).any(function(cv) { 
                    return fieldValue.include(cv.trim()); 
                });
            case "notContains":
                return !$A(condValues).any(function(cv) { 
                    return fieldValue.include(cv.trim()); 
                });
            case "greaterThan":
            case "quantityGreater":
                return (parseFloat(fieldValue, 10) || 0) > (parseFloat(condValue, 10) || 0);
            case "lessThan":
            case "quantityLess":
                //Emre: if Scale Rating doesn't have value it returns "true" so we need to check wheater its length is greater than 0 (52809)
                //fieldValue is string, not number
                if(fieldValue.length){
                    return (parseFloat(fieldValue, 10) || 0) < (parseFloat(condValue, 10) || 0);
                }else{
                    return false;
                }
            case "isEmpty":
                if(Object.isBoolean(fieldValue)){ return !fieldValue; }
                return fieldValue.empty();
            case "isFilled":
                if(Object.isBoolean(fieldValue)){ return fieldValue; }
                return !fieldValue.empty();
            case "before":
                return fieldValueOrg < condValueOrg;
            case "after":
                return fieldValueOrg > condValueOrg;
            default:
                JotForm.error("Could not find this operator", operator);
        }
        return false;
    },

    getDayOfWeek: function(date) {
        date = new Date(date);
        var days = ["sunday","monday","tuesday","wednesday","thursday","friday","saturday"];
        return days[date.getDay()];
    },
    
    typeCache: {},   // Cahcke the check type results for performance
    /**
     * 
     * @param {Object} id
     */
    getInputType: function(id){  
        if(JotForm.typeCache[id]){ return JotForm.typeCache[id]; }
        var type = false;
        if($('id_'+id) && $('id_'+id).readAttribute('data-type') == "control_text") {
            type = 'html';
        } else if($('input_'+id)){
            type = $('input_'+id).nodeName.toLowerCase() == 'input'? $('input_'+id).readAttribute('type').toLowerCase() : $('input_'+id).nodeName.toLowerCase();
            if($('input_'+id).hasClassName("form-radio-other-input")){
                type = "radio";
            }
            if($('input_'+id).hasClassName("form-checkbox-other-input")){
                type = "checkbox";
            }
            // Neil: set type for autocomplete fields
            if($('input_'+id).hasClassName('form-autocomplete')){
                type = "autocomplete";
            }

            if($('input_'+id).hasClassName('form-slider')){
                type = 'slider';
            }

            if($('input_'+id).hasClassName('form-widget')){
                type = 'widget';
            }
            
        }else if($('input_'+id+'_pick') || ($('id_'+id) && $('id_'+id).readAttribute('data-type') == "control_datetime")){
            type = 'datetime';
        }else if($('input_'+id+'_month')){
            type = 'birthdate';
        } else if($('input_'+id+'_hourSelect')) {
            type = 'time';
        } else if($$('#id_'+id +' .form-product-item').length > 0) {
            type = $$('#id_'+id +' .form-product-item')[0].select('input')[0].readAttribute('type').toLowerCase();
        } else if($$('#id_'+id +' .form-address-table').length > 0) {
            type = 'address';
        } else if($$('input[id^=input_' + id +'_]')[0] && $$('input[id^=input_' + id +'_]')[0].hasClassName('form-grading-input')) {
            type = 'grading';
        } else if($$('#id_'+id +' .pad').length > 0) {
            type = 'signature';
        } else {
            if($$('#id_'+id+' input')[0]){
                type = $$('#id_'+id+' input')[0].readAttribute('type').toLowerCase();
                if(type == "text" || type == 'tel'){
                    type = "combined";
                }
            }
        }
        JotForm.typeCache[id] = type;
        return type;
    },
    /**
     * Parses ISO Date string to a real date
     * @param {Object} str
     */
    strToDate: function(str){
        // When cannot parse return an invalid date
        var invalid = new Date(undefined);
        var match   = /(\d{4})\-(\d{2})-(\d{2})T?(\d{2})?\:?(\d{2})?/gim;
        
        if(str.empty()){ return invalid; }
        
        // if(!str.include("T")){ str += "T00:00"; }
        
        if(!match.test(str)){ return invalid; }
        
        var d = new Date();
        str.replace(match, function(all, year, month, day, hour, minutes){
            if(hour){
                d = new Date(parseInt(year, 10), parseInt(month, 10)-1, parseInt(day, 10), parseInt(hour, 10), parseInt(minutes, 10));
            } else {
                d = new Date(parseInt(year, 10), parseInt(month, 10)-1, parseInt(day, 10));
            }
            return all;
        });
        
        return d;
    },

    getBirthDate: function(id) {
        var day = $('input_'+id+'_day').getValue()||"%empty%";
        var month = $('input_'+id+'_month').selectedIndex||"%empty%";
        month = String(month);
        var year = $('input_'+id+'_year').getValue()||"%empty%";
        var date = year + "-" + (month.length==1?'0'+month:month) + "-" + (day.length==1?'0'+day:day);
        if(date.include("%empty%")) return "";
        return date;
    },

    get24HourTime: function(id) {
        var hour = $('input_'+id+'_hourSelect').getValue();
        if(hour == "") return "";
        var minute = $('input_' + id + '_minuteSelect').getValue();
        if(minute.length == 0) minute = "00";
        var ampm = ($('input_' + id + '_ampm'))?$('input_' + id + '_ampm').getValue():'';
        hour = Number(hour);
        if(ampm == 'PM' && hour != 12) {
            hour += 12;
        } else if(ampm == 'AM' && hour == 12) { 
            hour = 0;
        }
        hour = (hour<10)?"0"+hour:String(hour);
        return hour + minute;
    },
    
    getDateValue: function(id){
        var date = "";
        if($('year_'+id)){
            date += ($('year_'+id).value || "%empty%");
        }
        if($('month_'+id)){
            date += "-"+($('month_'+id).value || "%empty%");
        }
        if($('day_'+id)){
            date += "-"+($('day_'+id).value || "%empty%");
        }
        
        if(date.include("%empty%")){
            JotForm.info("Wrong date: " + date);
            return "";
        }
        var h="";
        if($('ampm_'+id)){
            if($('hour_'+id)){
                h = $('hour_'+id).value;
                if($('ampm_'+id).value == 'pm'){
                    h = parseInt(h, 10)+12;
                }
                if(h == "24"){
                    h = 0;
                }
                date += "T"+ ((h.length == 1? "0"+h : h) || "00");
            }
        }else{
            if($('hour_'+id)){
                h = $('hour_'+id).value;
                date += "T"+((h.length == 1? "0"+h : h) || "00");
            }
        }
        
        if($('min_'+id)){
            date += ":"+($('min_'+id).value || "00");
        }
        if(h === ""){
            date += "T00:00";
        }
        return date;
    },
    /**
     * 
     * @param {Object} condition
     */
    checkCondition: function(condition){
        var any=false, all=true;
        var filled;
        $A(condition.terms).each(function(term){
            var value;
            try{
                var fieldType = JotForm.getInputType(term.field);
                switch(fieldType){
                    case "combined":
                        if (['isEmpty', 'isFilled'].include(term.operator)) {
                            filled = $$('#id_'+term.field+' input').collect(function(e){ return e.value; }).any();
                            
                            if(JotForm.checkValueByOperator(term.operator, term.value, filled)){
                                any = true;
                            }else{
                                all = false;
                            }
                            
                            return; /* continue; */ 
                        }
                    break;
                    case "address":
                        if (['isEmpty', 'isFilled'].include(term.operator)) {
                            filled = $$('#id_'+term.field+' input').collect(function(e){ return e.value; }).any();
                            if(JotForm.checkValueByOperator(term.operator, term.value, filled)){
                                any = true;
                            }else{
                                all = false;
                            }
                        } else {
                            var option = $('input_'+term.field+'_country').select('option[value=' + term.value + ']');
                            if(term.operator == 'equalCountry') {
                                if(option[0].selected) {
                                    any = true;
                                }else{
                                    all = false;
                                }
                            } else if(term.operator == 'notEqualCountry') {
                                if(!option[0].selected) {
                                    any = true;
                                }else{
                                    all = false;
                                }
                            }
                        }
                    break;
                    case "birthdate":
                    case "datetime":
                        value = (fieldType=="datetime")?JotForm.getDateValue(term.field):JotForm.getBirthDate(term.field);
                        if(value === undefined){ return; /* continue; */ }
                        
                        if (['isEmpty', 'isFilled'].include(term.operator)) {
                            if(JotForm.checkValueByOperator(term.operator, term.value, value)){
                                any = true;
                            }else{
                                all = false;
                            }
                            
                        } else {
                            var termValue = term.value;
                            termValue = term.value.toLowerCase();
                            if(termValue.indexOf('today') > -1) {
                                var offset = parseInt(termValue.split('today')[1]) || 0;
                                var comparativeDate = new Date();
                                comparativeDate.setDate(comparativeDate.getDate() + offset);
                                var year = comparativeDate.getFullYear();
                                var month = comparativeDate.getMonth() + 1;
                                month = (month < 10)?'0' + month : month;
                                var day = comparativeDate.getDate();
                                day = (day < 10)?'0' + day : day;
                                termValue = year + "-" + month + "-" + day;
                            }

                            if(['equalDate', 'notEqualDate'].include(term.operator)){
                                if(JotForm.checkValueByOperator(term.operator, JotForm.strToDate(termValue), JotForm.strToDate(value.split('T')[0]))){
                                    any = true;
                                }else{
                                    all = false;
                                }
                            } else if(['equalDay', 'notEqualDay'].include(term.operator)) {
                                if(JotForm.checkValueByOperator(term.operator, termValue, JotForm.strToDate(value))){
                                    any = true;
                                }else{
                                    all = false;
                                }
                            }else{
                                if(JotForm.checkValueByOperator(term.operator, JotForm.strToDate(termValue), JotForm.strToDate(value))){
                                    any = true;
                                }else{
                                    all = false;
                                }
                            }
                        }
                    break;
                    case "time":
                        value = JotForm.get24HourTime(term.field);
                        var termValue = (!term.value)?"":term.value.replace(/:/, "");
                        if (termValue.length == 3) termValue = "0" + termValue;
                        if(term.operator == 'before'  && value.empty()) {
                            all = false;
                        } else {
                            if(JotForm.checkValueByOperator(term.operator, termValue, value))
                                any = true;
                            else
                                all = false;
                        }
                    break;
                    case "checkbox":
                    case "radio":
                        if (['isEmpty', 'isFilled'].include(term.operator)) {
                            filled = $$('#id_'+term.field+' input').collect(function(e){ return e.checked; }).any();
                            
                            if(JotForm.checkValueByOperator(term.operator, term.value, filled)){
                                any = true;
                            }else{
                                all = false;
                            }
                            
                            return; /* continue; */ 
                        }
                        if(term.value) term.value = term.value.replace(/&amp;/g, '&');

                        $$('#id_'+term.field+' input').each(function(input){
                            if(input.hasClassName('form-'+fieldType+'-other') &&  input.checked) {
                                value = '-- Other --';
                            } else {
                                value = input.checked? input.value : '';
                            }
                            
                            if(JotForm.checkValueByOperator(term.operator, term.value, value)){
                                any = true;
                            }else{
                                // If not equals item is found condition should fail
                                if(term.operator == 'notEquals' && term.value == value){
                                    any = false;
                                    all = false;
                                    throw $break;
                                }
                                
                                if (input.value == term.value || (input.hasClassName('form-'+fieldType+'-other') && term.value == '-- Other --')) {
                                    all = false;
                                }
                            }
                        });
                    break;
                    case "select":

                        if(term.value) term.value = term.value.replace(/&amp;/g, '&');

                        if($('input_'+term.field).multiple) {
                            if(term.operator == 'equals') {
                                var option = $('input_'+term.field).select('option[value=' + term.value + ']');
                                if(option.length > 0 && option[0].selected) {
                                    any = true;
                                }else{
                                    all = false;
                                }
                            } else if(term.operator == 'notEquals') {
                                var option = $('input_'+term.field).select('option[value=' + term.value + ']');
                                if(option.length > 0 && !option[0].selected) {
                                    any = true;
                                }else{
                                    all = false;
                                }
                            } else if(['isEmpty', 'isFilled'].include(term.operator)) {
                                var selected = false;
                                var arr = $('input_'+term.field).options;
                                for(var i = 0; i < arr.length; i++) {
                                    if(!arr[i].value.empty() && arr[i].selected == true) {
                                        selected = true;
                                    }
                                }
                                if(term.operator == 'isEmpty' ) {
                                    if(!selected) any = true;
                                    else all = false;
                                }
                                if(term.operator == 'isFilled') {
                                    if(selected) any = true;
                                    else all = false;
                                }
                            }
                        } else {
                            value = $('input_'+term.field).value;
                            if(value === undefined){return;/* continue; */}
                            if(JotForm.checkValueByOperator(term.operator, term.value, value)){
                                any = true;
                            }else{
                                all = false;
                            }
                        }
                    break;
                    case "grading":
                        if (['isEmpty', 'isFilled'].include(term.operator)) {
                            filled = $$('input[id^=input_' + term.field +'_]').collect(function(e){ return e.value; }).any();
                            if(JotForm.checkValueByOperator(term.operator, term.value, filled)){
                                any = true;
                            }else{
                                all = false;
                            }
                        } else {
                            value = $('grade_point_' + term.field).innerHTML.stripTags();
                            if(JotForm.checkValueByOperator(term.operator, term.value, value)){
                                any = true;
                            }else{
                                all = false;
                            }
                        }
                    break;  
                    case "file": 
                        if($('id_' + term.field).select('.qq-uploader').length > 0) {
                            value = $('id_' + term.field).select('.qq-upload-file').length > 0;
                        } else {
                            value = $('input_'+term.field).value;
                        }

                        if(value === undefined){return;/* continue; */}
                        if(JotForm.checkValueByOperator(term.operator, term.value, value, term.field)){
                            any = true;
                        }else{
                            all = false;
                        }
                    break;

                    case "textarea":
                        value = $('input_'+term.field).value;
                        if($('input_'+term.field).hinted){
                            value = "";
                        }
                        if(value === undefined){return;/* continue; */}
                        var rich = $('id_'+term.field).down('.nicEdit-main');
                        if(rich) {
                            value = value.stripTags().replace(/\s/g, ' ').replace(/&nbsp;/g, ' ');
                        }

                        if(JotForm.checkValueByOperator(term.operator, term.value, value, term.field)){
                            any = true;
                        }else{
                            all = false;
                        }
                    break;
                    default:
                        value = $('input_'+term.field).value;
                        if($('input_'+term.field).hinted){
                            value = "";
                        }
                        if(value === undefined){return;/* continue; */}
                        if(JotForm.checkValueByOperator(term.operator, term.value, value, term.field)){
                            any = true;
                        }else{
                            all = false;
                        }
                }
                
            }catch(e){ 
                JotForm.error(e);
            }
        });
        

        if(condition.type == 'field'){ // Field Condition
            // JotForm.log("any: %s, all: %s, link: %s", any, all, condition.link.toLowerCase());
            var isConditionValid = (condition.link.toLowerCase() == 'any' && any) || (condition.link.toLowerCase() == 'all' && all);

            condition.action.each(function(action) {

                if (isConditionValid) {
                    action.currentlyTrue = true;
                    if (action.visibility.toLowerCase() == 'show'){
                        JotForm.showField(action.field);
                    } else if (action.visibility.toLowerCase() == 'hide') {
                        JotForm.hideField(action.field);
                    } else if(action.visibility.toLowerCase() == 'showmultiple' && action.fields) {
                        action.fields.each(function(field) {
                            JotForm.showField(field);
                        });
                    } else if(action.visibility.toLowerCase() == 'hidemultiple' && action.fields) {
                        action.fields.each(function(field) {
                            JotForm.hideField(field);
                        });
                    }
                } else {
                    action.currentlyTrue = false;
                    if(action.visibility.toLowerCase() == 'show'){
                        JotForm.hideField(action.field);
                    } else if (action.visibility.toLowerCase() == 'hide') {
                        JotForm.showField(action.field);
                    } else if(action.visibility.toLowerCase() == 'showmultiple' && action.fields) {
                        action.fields.each(function(field) {
                            JotForm.hideField(field);
                        });
                    } else if(action.visibility.toLowerCase() == 'hidemultiple' && action.fields) {
                        action.fields.each(function(field) {
                            JotForm.showField(field);
                        });
                    }
                }

                
                if($('section_'+action.field)) {
                    JotForm.runAllCalculations(true);
                }
                if($('input_' + action.field) && $('input_' + action.field).triggerEvent) {
                    if(!condition.terms.any(function(term) { return term.field == action.field;})) {  //rule matches action so don't rerun to avoid infinite loop
                        $('input_' + action.field).triggerEvent('keyup'); //trigger calculations when hiding/showing
                    }
                }

            });
        } else if(condition.type == 'require') {
            var isConditionValid = (condition.link.toLowerCase() == 'any' && any) || (condition.link.toLowerCase() == 'all' && all);
            condition.action.each(function(action) {
                action.currentlyTrue = isConditionValid;

                if(!isConditionValid && JotForm.otherConditionTrue(action.field, action.visibility.toLowerCase())) {
                    return;
                }
                if (action.visibility.toLowerCase() == 'require'){
                    JotForm.requireField(action.field, isConditionValid);
                } else if (action.visibility.toLowerCase() == 'unrequire'){
                    JotForm.requireField(action.field, !isConditionValid);
                } else if (action.visibility.toLowerCase() == 'requiremultiple' && action.fields) {
                    action.fields.each(function(field) {
                        JotForm.requireField(field, isConditionValid);
                    });                        
                } else if (action.visibility.toLowerCase() == 'unrequiremultiple' && action.fields) {
                    action.fields.each(function(field) {
                        JotForm.requireField(field, !isConditionValid);
                    });     
                }
            });
        } else if(condition.type == 'mask') {
            condition.action.each(function(action) {
                if((condition.link.toLowerCase() == 'any' && any) || (condition.link.toLowerCase() == 'all' && all)) {
                    condition.conditionTrue = true;
                    JotForm.setQuestionMasking("#input_"+action.field, "textMasking", action.mask);
                    $("input_"+action.field).writeAttribute('masked', "true");
                } else {
                    condition.conditionTrue = false;
                    //if no other mask conditions for this field are true remove the mask
                    var removeMask = true;
                    $A(JotForm.conditions).each(function(cond){
                        if(cond.disabled == true) return; //go to next condition
                        if(cond.type !== 'mask') return;
                        if(!cond.conditionTrue) return;
                        $A(cond.action).each(function(act) {
                            if(act.field == action.field) {
                                removeMask = false; //there is a different true mask cond on this field so do not remove mask
                            }
                        });
                    });

                    if(removeMask) {
                        JotForm.setQuestionMasking("#input_"+action.field, "", "", true);
                        $("input_"+action.field).writeAttribute('masked', "false");
                    }
                }
            });

        } else if(condition.type == 'calculation') {
            if(!$("id_" + condition.action[0].resultField)) {
                return;
            }

            var calcs = JotForm.calculations;
            var cond = null;
            for(var i=0; i < calcs.length; i++) {
                if(calcs[i].conditionId === condition.id) {
                    calc = calcs[i];
                }
            }
            if((condition.link.toLowerCase() == 'any' && any) || (condition.link.toLowerCase() == 'all' && all)) {
                calc.conditionTrue = true;
                JotForm.checkCalculation(calc);
            } else {
                calc.conditionTrue = false;
                //check if any other conditions are true for this result field

                setTimeout(function(calc) {
                    var matchForThisResult = false;
                    for(var i=0; i < calcs.length; i++) {
                        if((condition.action[0].resultField == calcs[i].resultField && calcs[i].hasOwnProperty('conditionTrue') && calcs[i].conditionTrue)
                            && !(JotForm.getInputType(condition.action[0].resultField) === "html" && condition.action[0].replaceText !== calcs[i].replaceText)){
                                matchForThisResult = true;
                        }
                    }
                    if(!matchForThisResult) {
                        var resultField = condition.action[0].resultField;
                        var type = JotForm.getInputType(resultField);
                        if(["address", "combined", "datetime", "time"].include(type)) {
                            $('id_'+resultField).select('input').each(function(el) {
                                el.value = "";
                            });
                            $('id_'+resultField).select('select').each(function(el) {
                                el.selectedIndex = 0;
                            });

                            var triggerMe = $('input_' + resultField) ? $('input_' + resultField) : $('id_'+resultField).select('input').first();
                            if(triggerMe && triggerMe.triggerEvent) {
                                triggerMe.triggerEvent('keyup');
                            }
                        } else if(type === "html") {
                            try {
                                var output = calc.defaultValue ? calc.defaultValue : "";
                                var spans = $$("." + resultField + "_" + calc.replaceText);
                                if(spans.length == 0) {
                                    var contents = $('text_' + resultField).innerHTML;
                                    var re = new RegExp("\{"+calc.replaceText+"\\[?.*?\\]?\}","g");
                                    contents = contents.replace(re, '<span class="'+resultField + "_" + calc.replaceText+'">'+output+'</span>');
                                    $('text_' + resultField).update(contents);
                                } else {
                                    spans.each(function(span) {
                                        span.update(output);
                                    });
                                }
                            } catch(e) {
                                console.log(e);
                            }
                        } else {
                            if($('input_' + resultField)) {
                                $('input_' + resultField).value = '';
                                $('input_' + resultField).triggerEvent('keyup');
                                if($('input_' + resultField).hintClear) $('input_' + resultField).hintClear(); //ie8&9
                            }
                        }
                    }
                }, 50, calc);
            }
        } else { // Page condition
        
            JotForm.log("any: %s, all: %s, link: %s", any, all, condition.link.toLowerCase());
            if (JotForm.nextPage) {
                return;
            }
            if((condition.link.toLowerCase() == 'any' && any) || (condition.link.toLowerCase() == 'all' && all)){
                var action = condition.action[0];
                JotForm.info('Correct: Skip To: ' + action.skipTo);
                var sections = $$('.form-section:not([id^=section_])');
                if(action.skipTo == 'end'){
                    JotForm.nextPage = sections[sections.length - 1];
                }else{
                    JotForm.nextPage = sections[parseInt(action.skipTo.replace('page-', ''), 10)-1];
                }
                
            }else{
                
                JotForm.info('Fail: Skip To: page-' + JotForm.currentPage + 1);
                
                JotForm.nextPage = false; 
            }
        }
        JotForm.enableDisableButtonsInMultiForms();
    },
    currentPage: false,
    nextPage: false,
    previousPage: false,
    fieldConditions: {},
    
    setFieldConditions: function(field, event, condition){
        if(!JotForm.fieldConditions[field]){
            JotForm.fieldConditions[field] = {
                event: event,
                conditions:[]
            };
        }
        JotForm.fieldConditions[field].conditions.push(condition);
    },

    widgetsAsCalculationOperands: [],

    /*
    * Require or Unrequire a field
    */
    requireField: function(qid, req) {

        if(!$('id_'+qid)) return;

        $$('#id_' + qid + ' input, #id_' + qid + ' textarea, #id_' + qid + ' select').each(function(el) {

            //do not required non-necessary parts of combined field
            if(el.id === 'coupon-input' 
                || (el.type === 'hidden' && !el.up('.form-star-rating') && !el.hasClassName('form-widget'))
                || el.hasClassName('form-checkbox-other-input') || el.hasClassName('form-radio-other-input')
                || $A(['prefix', 'middle', 'suffix', 'addr_line2', 'state']).any(function(name) {return el.name.indexOf("["+name+"]") > -1;})) {
                return;
            }

            //get all validations
            var validations = [];
            if(el.className.indexOf('validate[') > -1) {
                validations = el.className.substr(el.className.indexOf('validate[') + 9);
                validations = validations.substr(0, validations.indexOf(']')).split(/\s*,\s*/);
            } else {
                validations = [];
            }

            //remove all validation from class
            el.className = el.className.replace(/validate\[.*\]/, '');

            //remove required from validations array
            for (var i=validations.length-1; i>=0; i--) {
                if (validations[i] === 'required') {
                    validations.splice(i, 1);
                }
            }

            if(req) {
                validations.push('required'); //add required to validations
            } else {
                el.removeClassName('form-validation-error')
            }

            //add validations back to class
            if(validations.length > 0) {
                el.addClassName('validate['+ validations.join(',') +']');
            }

            JotForm.setFieldValidation(el);
        });
        if(req) {
            if($('label_'+qid) && !$('label_'+qid).down('.form-required')) {
                $('label_'+qid).insert('<span class="form-required">*</span>');
            }
        } else {
            if($('label_'+qid) && $('label_'+qid).down('.form-required')) {
                $('label_'+qid).down('.form-required').remove();
            }

            //remove any existing errors
            if($("id_"+qid).down('.form-error-message')) {
                $("id_"+qid).down('.form-error-message').remove();
            }
            $("id_"+qid).removeClassName('form-line-error');
        }
    },

    /**
     * When widget value is updated check whether to trigger calculation
     */
    triggerWidgetCalculation: function(id) {
        if(JotForm.widgetsAsCalculationOperands.include(id)) { 
            if (document.createEvent) {
                var evt = document.createEvent('HTMLEvents');
                evt.initEvent('change', true, true);
                $('input_' + id).dispatchEvent(evt);
            } else if ($('input_' + id).fireEvent) {
                return $('input_' + id).fireEvent('onchange');
            }
        }
    },

    
    setCalculationResultReadOnly: function() {
        $A(JotForm.calculations).each(function(calc, index) {
            if(calc.readOnly && $('input_' + calc.resultField) != null) {
                $('input_' + calc.resultField).setAttribute('readOnly', 'true');
            }
        });
    },

    setCalculationEvents: function() {
        var setCalculationListener = function(el, ev, calc) {
            $(el).observe(ev, function() {
                if(ev === "paste") { //same action as other events but wait for the text to be pasted
                    setTimeout(function() {
                        el.addClassName('calculatedOperand');
                        JotForm.checkCalculation(calc);
                    },10);
                } else {
                    el.addClassName('calculatedOperand');
                    JotForm.checkCalculation(calc);
                }
            });
        };

        $A(JotForm.calculations).each(function(calc, index) {
            if(!calc.operands) return;
            var ops = calc.operands.split(',');
            for(var i = 0; i < ops.length; i++) {
                
                var opField = ops[i];
                if(!opField || opField.empty() || !$('id_' + opField)) continue;

                var type = JotForm.getInputType(opField),
                    ev;
                switch (type) {
                    case "widget":
                        setCalculationListener($('id_' + opField), 'change', calc);
                        JotForm.widgetsAsCalculationOperands.push(opField);
                        break;
                        
                    case 'radio':
                    case 'checkbox':
                        setCalculationListener($('id_' + opField), 'click', calc);
                        if($('input_'+opField)) {
                            setCalculationListener($('id_' + opField), 'keyup', calc);
                        }
                        break;
                    
                    case 'select':
                    case 'file':
                        setCalculationListener($('id_' + opField), 'change', calc);
                        break;
                    
                    case 'datetime':
                        setCalculationListener($('id_' + opField), 'date:changed', calc);
                        $$("#id_" + opField + ' select').each(function(el) {
                            setCalculationListener($(el), 'change', calc);
                        });
                        break;
                    
                    case 'time':
                    case 'birthdate':
                        $$("#id_" + opField + ' select').each(function(el) {
                            setCalculationListener($(el), 'change', calc, index);
                        });                        
                        break;

                    case 'address':
                        setCalculationListener($('id_' + opField), 'change', calc, index);
                        setCalculationListener($('id_' + opField), 'blur', calc, index);
                        setCalculationListener($('id_' + opField), 'keyup', calc, index);
                        $$("#id_" + opField + ' select').each(function(el) {
                            setCalculationListener($(el), 'change', calc, index);
                        });
                        break;

                    case 'number':
                        setCalculationListener($('id_' + opField), 'keyup', calc, index);
                        setCalculationListener($('id_' + opField), 'paste', calc, index);
                        setCalculationListener($('id_' + opField), 'click', calc, index);
                        break;

                    default:
                        setCalculationListener($('id_' + opField), 'change', calc, index);
                        setCalculationListener($('id_' + opField), 'blur', calc, index);                    
                        setCalculationListener($('id_' + opField), 'keyup', calc, index);
                        setCalculationListener($('id_' + opField), 'paste', calc, index);
                        break;
                }
            }
        });
    },

    calcValues: [],

    setCalculationValues: function(calculationValues, id) {
        JotForm.calcValues[id] = calculationValues.split('|');
    },

    runAllCalculations:function(ignoreEditable) {
        $A(JotForm.calculations).each(function(calc, index) {
            if(!(ignoreEditable && !calc.readOnly)) {
                JotForm.checkCalculation(calc);
            }
        });
    },

    checkCalculation: function(calc) {
        if(calc.hasOwnProperty('conditionTrue') && !calc.conditionTrue) {
            return '';
        }

        var result = calc.resultField;
        var showBeforeInput = calc.showBeforeInput;
        var ignoreHidden = calc.ignoreHiddenFields;
 
        if(!$('id_' + result)) return;
        try {
            if(!['text', 'email', 'textarea', 'calculation', 'combined', 'address', 'datetime', 'time', 'html'].include(JotForm.getInputType(result))) return;
        } catch(e) {
            console.log(e);
        }

        var combinedObject = {};

        var getValue = function(data, numeric) {

            if(!$('id_' + data)) return '';
            if(!$('id_' + data).hasClassName('calculatedOperand') && showBeforeInput) return ''; //no input yet so ignore field
            if(ignoreHidden && !JotForm.isVisible($('id_' + data))) {
                return numeric ? 0 : '';
            }

            var type = JotForm.getInputType(data);
            var val ='';
            switch (type) {
                case 'radio':
                    $$("#id_" + data + ' input[type="radio"]').each(function(rad, i) {
                        if(rad.checked) {
                            //grab calculation value
                            if(JotForm.calcValues[data] && i < JotForm.calcValues[data].length) {
                                val = JotForm.calcValues[data][i];
                            } else {
                                val = rad.value;
                            }
                        }
                    });
                    break;

                case 'checkbox':

                    var valArr = [];
                    $$("#id_" + data + ' input[type="checkbox"]').each(function(chk, i) {
                        if(chk.checked) {
                            if(JotForm.calcValues[data] && i < JotForm.calcValues[data].length) { //use calculation value instead of option
                                valArr.push(JotForm.calcValues[data][i]);
                            } else {
                                valArr.push(chk.value);
                            }
                        }
                    });

                    if(numeric) { 
                        val = valArr.inject(0, function(accum, thisVal) { 
                            return accum + (parseFloat(thisVal.replace(/-?([^0-9])/g,"$1").replace(/[^0-9\.-]/g,"")) || 0); 
                        });
                    } else {
                        val = valArr.join();
                    }
                    break;

                case 'select':
                    //grab calculation value
                    if(JotForm.calcValues[data] && $('input_' + data).selectedIndex < JotForm.calcValues[data].length) {
                        val = JotForm.calcValues[data][$('input_' + data).selectedIndex];
                    } else {
                        val = $('input_' + data).value;
                    }
                    break;

                case 'number':
                    if($$("#id_" + data + ' input[type="number"]').length > 1) { //ranges
                        var valArr = [];
                        $$("#id_" + data + ' input[type="number"]').each(function(el) { 
                            valArr.push(el.value);
                        });
                        val = valArr.join(' ');
                    } else {
                        if(!$('input_' + data).value.empty() && !isNaN($('input_' + data).value)) {
                            val = parseFloat($('input_' + data).value);
                        }
                    }
                    break;

                case 'combined':
                case 'grading':
                    var valArr = [];
                    combinedObject = {};
                    $$("#id_" + data + ' input[type="text"]').each(function(el) {
                        if(!el.value.empty()) {
                            valArr.push(el.value);

                            var id = el.id.replace(/_.*/, "");
                            combinedObject[id] = el.value;
                        }

                    });
                    $$("#id_" + data + ' input[type="tel"]').each(function(el) {
                        if(!el.value.empty()) {
                            valArr.push(el.value);

                            var id = el.id.replace(/input_[0-9].*_+/, "");
                            combinedObject[id] = el.value;
                            
                        }
                    });
                    val = valArr.join(' ');
                    break;

                case 'datetime':
                    var valArr = [];
                    if(numeric) {
                        valArr.push($("month_" + data).value);
                        valArr.push($("day_" + data).value);
                        valArr.push($("year_" + data).value);
                    } else {
                        $$("#id_" + data + ' input[type="tel"]').each(function(el) {
                            valArr.push(el.value);

                            var id = el.id.replace(/_.*/, "");
                            combinedObject[id] = el.value;
                        });

                        $$("#id_" + data + ' select').each(function(el) {
                            var id = el.id.replace(/_.*/, "");
                            combinedObject[id] = el.value;
                        });
                    }
                    
                    $$("#id_" + data + ' select').each(function(el) {
                        valArr.push(el.value);
                    });

                    //if numeric calculation calculate the number of days in epoch
                    if(numeric) {
                        var hours = mins = ampm = '';
                        if(valArr.length > 4 && !valArr[3].empty() && !valArr[4].empty()) {
                            hours = parseInt(valArr[3]);
                            //convert to 24hours
                            if(valArr.length == 6 && !valArr[5].empty()) {
                                ampm = valArr[5];
                                if(ampm == 'PM' && hours != 12) {
                                    hours += 12;
                                } else if(ampm == 'AM' && hours == 12) { 
                                    hours = 0;
                                }
                            }
                            mins = valArr[4];
                        }
                        var millis = new Date(valArr[2], valArr[0]-1, valArr[1], hours, mins).getTime();
                        val = millis/60/60/24/1000;
                    } else {
                        if(valArr.length > 2 && !valArr[0].empty() && !valArr[1].empty() && !valArr[0].empty()) {
                            val = valArr[0] + '/' + valArr[1] + '/' + valArr[2];
                        }
                        if(valArr.length > 4 && !valArr[3].empty() && !valArr[4].empty()) {
                            val += ' ' + valArr[3] + ':' + valArr[4]; 
                            if(valArr.length == 6 && !valArr[5].empty()) val += ' ' + valArr[5]; //ampm
                        }
                    }

                    break;

                case 'time':
                    var valArr = [];
                    combinedObject = {};
                    $$("#id_" + data + ' select').each(function(el) {
                        valArr.push(el.value);
                    });
                    if(numeric) {
                        var hour, mins, ampm = '';
                        hours = parseInt(valArr[0]) || 0;
                        if(valArr.length == 3 && !valArr[2].empty()) {
                            ampm = valArr[2];
                            if(ampm == 'PM' && hours != 12) {
                                hours += 12;
                            } else if(ampm == 'AM' && hours == 12) { 
                                hours = 0;
                            }
                        }
                        mins = valArr[1];
                        var millis = Date.UTC('1970', '0', '1', hours, mins);
                        val = millis/60/60/1000;
                    } else {
                        if(!valArr[0].empty() && !valArr[1].empty()) {
                            val = valArr[0] + ':' + valArr[1];
                            if(valArr.length > 2 && !valArr[2].empty()) val += ' ' + valArr[2];
                        }

                        $$("#id_" + data + ' select').each(function(el) {
                            var id = el.id.replace(/.*_.*_/, "");
                            combinedObject[id] = el.value;
                        });
                    }
                    break;

                case 'birthdate':
                    var valArr = [];
                    $$("#id_" + data + ' select').each(function(el) {
                        valArr.push(el.value);
                    });
                    if(!valArr[0].empty() && !valArr[1].empty() && !valArr[2].empty()) {
                        val = valArr[0] + ' ' + valArr[1] + ' ' + valArr[2];
                    } 
                    break;

                case 'address':
                    var valArr = [];
                    combinedObject = {};
                    $$("#id_" + data + ' input[type="text"]').each(function(el) {
                        if(!el.value.empty()) {
                            valArr.push(el.value);

                            var id = el.id.replace(/input_[0-9].*_+/, "");
                            combinedObject[id] = el.value;
                        }

                    });
                    $$("#id_" + data + ' select').each(function(el) {
                        if(!el.value.empty()) {
                            valArr.push(el.value);

                            var id = el.id.replace(/input_[0-9].*_+/, "");
                            combinedObject[id] = el.value;
                        }
                    });
                    val = valArr.join(', ');
                    break;

                case 'file':
                    val = $('input_' + data).value;
                    val = val.substring(val.lastIndexOf("\\") + 1);
                    break;

                case 'textarea':
                    if($('input_' + data) && typeof $('input_' + data).value !== 'undefined') {
                        val = $('input_' + data).value;
                        var rich = $('id_'+data).down('.nicEdit-main');
                        if(rich) {
                            val = val.stripTags().replace(/\s/g, ' ').replace(/&nbsp;/g, ' ');
                        }
                    }
                    break;
                default:
                    if($('input_' + data) && typeof $('input_' + data).value !== 'undefined') {
                        val = $('input_' + data).value;
                    }
                    break;
            }

            if(numeric && typeof val !== 'number') {
                val = val.replace(/-?([^0-9])/g,"$1").replace(/[^0-9\.-]/g,"");
                if(val < 0) { //ntw 343248 - this is to patch a weirdness in the parser whereby x+-y will not parse
                    val = '(' + val + ')';
                }
            }

            if(numeric && val==='') {
                val = 0;
            }

            return val;
        };

        var calculate = function(equation, numeric) {
            var out = '';
            var acceptableFunctions = {"abs":Math.abs,"acos":Math.acos,"acosh":Math.acosh,"asin":Math.asin,"asinh":Math.asinh,"atan":Math.atan,
                    "atanh":Math.atanh,"atan2":Math.atan2,"cbrt":Math.cbrt,"ceil":Math.ceil,"cos":Math.cos,"cosh":Math.cosh,"exp":Math.exp,"expm1":Math.expm1,
                    "floor":Math.floor,"fround":Math.fround,"hypot":Math.hypot,"imul":Math.imul,"log":Math.log,"log1p":Math.log1p,"log10":Math.log10,
                    "log2":Math.log2,"max":Math.max,"min":Math.min,"pow":Math.pow,"random":Math.random,"round":Math.round,"sign":Math.sign,"sin":Math.sin,
                    "sinh":Math.sinh,"sqrt":Math.sqrt,"tan":Math.tan,"tanh":Math.tanh,"toSource":Math.toSource,"trunc":Math.trunc,"E":Math.E,"LN2":Math.LN2,
                    "LN10":Math.LN10,"LOG2E":Math.LOG2E,"LOG10E":Math.LOG10E,"PI":Math.PI,"SQRT1_2":Math.SQRT1_2,"SQRT2":Math.SQRT2};             
            for(var i = 0; i < equation.length; i++) {

                character = equation.charAt(i);

                if(character === '[' && !numeric) {
                    var end = equation.indexOf(']', i);
                    try {
                        var num = calculate(equation.substring(i+1, end), true);
                        if(num) {
                            if(num.replace(/[0-9\.,]/g, "").length > 0) { //normal calc string
                                num = new MathProcessor().parse(num);
                                num = num.toFixed(calc.decimalPlaces);
                                if(!calc.showEmptyDecimals) {
                                    num = parseFloat(num);
                                }
                                if(!isFinite(num)) {
                                    num = 0;
                                }
                            } else { //comma separated "number" string
                                if(num.indexOf(".") > -1) {
                                    var decimalPart = 0 + num.substr(num.lastIndexOf("."));
                                    var multi = Math.pow(10, calc.decimalPlaces);
                                    decimalPart = (Math.round(decimalPart * multi)/multi).toFixed(calc.decimalPlaces);

                                    if(!calc.showEmptyDecimals) {
                                        decimalPart = parseFloat(decimalPart).toString();
                                    }

                                    var wholePart = num.substr(0, num.lastIndexOf("."));
                                    num = wholePart + decimalPart.substr(1);
                                }
                            }
                            out += num;
                        }
                    } catch(e) {
                        console.log('exception in ' + calc.conditionId + " : " + num  + "(" + equation + ")");
                    }
                    i = end;
                } else if(equation.substr(i, 3) === '|*|') {
                    try {
                        i+=3;
                        var end = equation.indexOf('|*|', i);
                        if(end === -1) continue;
                        var specOp = equation.substring(i, end);
                        i += end+2-i;
                        if(equation.charAt(i+1) === '(' || (equation.charAt(i+1) === '[' && equation.charAt(i+2) === '(')) {
                            i += (equation.charAt(i+1) === '[') ? 3 : 2;
                            var endSpecial = -1;
                            var balance = 1;
                            for(var k=i;k<equation.length;k++) {
                                if(equation.charAt(k) === ')') {
                                    balance--;
                                    if(balance === 0) {
                                        endSpecial = k;
                                        break;
                                    }
                                } else if(equation.charAt(k) === '(') {
                                    balance++;
                                }
                            }

                            if(endSpecial === -1) continue;
                            var args = equation.substring(i, endSpecial);
                            args = args.split(',');
                            var originalArgs = args.slice(0);
                            for(var j=0;j<args.length;j++) {
                                args[j] = calculate(args[j], true);
                                if(args[j]) {
                                    args[j] = new MathProcessor().parse(args[j]);
                                }
                            }
                            i += endSpecial-i;
                            if(specOp === 'dateString') {
                                out += new Date(args[0]*24*60*60*1000).toDateString();
                                if(equation.charAt(i) === ']') {
                                    i++;
                                } else {
                                    equation = equation.substr(0, i+1) + '[' + equation.substr(i+1);
                                }
                            } else if(specOp === 'nth') {
                                var n = args[0];
                                args = args.splice(1);
                                args = args.sort(function(a,b){
                                    if(parseInt(a) > parseInt(b)) return 1;
                                    if(parseInt(b) > parseInt(a)) return -1;
                                    return 0;
                                });
                                args = args.reverse();
                                out += args[parseInt(n)-1];
                            } else if(specOp === 'avg' || specOp === 'avgNoZero') {
                                var len = sum = 0;
                                for(var j = 0; j < args.length; j++){
                                    if(parseFloat(args[j]) > 0) {
                                        len++;
                                        sum += parseFloat(args[j]);
                                    }
                                }
                                out += specOp === 'avg' ? sum/args.length : sum/len;
                            } else if(specOp === 'count'){
                                var field = originalArgs[0];
                                field = field.replace(/[\{\}]/g,'');
                                var type = JotForm.getInputType(field);
                                var len = $$("#id_" + field + ' input[type="'+type+'"]:checked').length;
                                out += len;
                            } else if(specOp === 'commaSeparate') {
                                if(typeof args[0] == "number") {
                                    var parts = args[0].toString().split(".");
                                    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
                                    out += parts.join(".");
                                } else {
                                    out += args[0];
                                }
                            } else {
                                out += acceptableFunctions[specOp].apply(undefined, args);
                            }
                            
                        } else if(specOp === 'random') {
                            out += Math.random();
                        } else {
                            out += acceptableFunctions[specOp];
                        }
                    } catch(e) {
                        console.log(e);
                    }
                } else if(character === '{') {
                    var end = equation.indexOf('}', i);
                    var qid = equation.substring(i+1, end);
                    var val = getValue(qid, numeric);
                    if(val === '' && numeric) return false;
                    out += val;
                    
                    i += end-i;
                } else {
                    out += character;
                }
            }
            return out;
        };
        
        var output = calculate(calc.equation);
        if(parseFloat(output) === 0 && JotForm.defaultValues['input_' + result]) {
            output = JotForm.defaultValues['input_' + result]; 
        }

        var resultFieldType = JotForm.getInputType(result);
        switch(resultFieldType) {
            case "html":
                try {

                    if(output.empty() && calc.defaultValue) {
                        output = calc.defaultValue;
                    }

                    var spans = $$("." + result + "_" + calc.replaceText);
                    if(spans.length == 0) {
                        var contents = $('text_' + result).innerHTML;
                        var re = new RegExp("\{"+calc.replaceText+"\(\\[.*?\\]\){0,1}\}","g");

                        contents = contents.replace(re, '<span class="'+result + "_" + calc.replaceText+'">'+output+'</span>');
                        $('text_' + result).update(contents);
                    } else {
                        spans.each(function(span) {
                            span.update(output);
                        });
                    }
                } catch(e) {
                    console.log(e);
                }

                break;
            case "address":
            case "combined":
            case "datetime":
            case "time":
                for(var inputId in combinedObject) {
                    if($('id_'+result).select('input[id*='+inputId+'], select[id*='+inputId+']').length > 0) {
                        $('id_'+result).select('input[id*='+inputId+'], select[id*='+inputId+']').first().value = combinedObject[inputId];
                    }
                }
                break;
            default:
                if($('input_' + result).hinted === true){ //IE8&9 make sure inserted value is not hinted
                    $('input_' + result).clearHint();
                }

                $('input_' + result).value = output;

                if(output && output.length === 0 && $('input_' + result).hintClear) { //IE8&9 if value is empty reapply hint
                    $('input_' + result).hintClear();
                }
        }

        var infiniteLoop = function() {
            // prevent calculation&condition infinite loop by limiting the nuber of times 
            // a calculation can be run on an element in a 500ms period
            var timestamp = new Date().getTime();
            var msPart = timestamp % 1000;
            if(msPart < 500){
                msPart = "0";
            }else{
                msPart = "1";
            }
            var secPart = parseInt(timestamp/1000);
            var antiLoopKey = 'input_'+result+'-'+secPart+'-'+msPart;

            //create global antiLoop variable if not created yet
            if(!("__antiLoopCache" in window)){
                window.__antiLoopCache = {};
            }
            if(antiLoopKey in window.__antiLoopCache){
                window.__antiLoopCache[antiLoopKey]++;
                if(window.__antiLoopCache[antiLoopKey] > 9) {
                    return true; //only allow same calc to trigger nine times in half a second - multiple are needed for things like sliders that change quickly
                }
            }else{
                window.__antiLoopCache[antiLoopKey] = 1;
            }
            return false; //not infinite loop
        }

        if(infiniteLoop()) {
            return;
        }

        var triggerMe = $('input_' + result) ? $('input_' + result) : $('id_'+result).select('input').first();
        if(!triggerMe) return;
        if (document.createEvent) {
            var evt = document.createEvent('HTMLEvents');
            evt.initEvent('keyup', true, true);
            triggerMe.dispatchEvent(evt);
        }
        if (triggerMe.fireEvent) {
            triggerMe.fireEvent('onkeyup');
        }
    },

    widgetsWithConditions: [],

    /**
     * When widget value is updated check whether to trigger conditions
     */
    triggerWidgetCondition: function(id) { 
        if(JotForm.widgetsWithConditions.include(id)) { 
            if (document.createEvent) {
                var evt = document.createEvent('HTMLEvents');
                evt.initEvent('change', true, true);
                $('input_' + id).dispatchEvent(evt);
            } else if ($('input_' + id).fireEvent) {
                return $('input_' + id).fireEvent('onchange');
            }
        }
    },

    /**
     * Sets all events and actions for form conditions
     */
    setConditionEvents: function(){
        try {
            $A(JotForm.conditions).each(function(condition){

                if(condition.disabled == true) return; //go to next condition

                if (condition.type == 'field' || condition.type == 'calculation' || condition.type == 'require' || condition.type == 'mask') {
                    
                    // Loop through all rules
                    $A(condition.terms).each(function(term){
                        var id = term.field;

                        switch (JotForm.getInputType(id)) {
                            case "widget":
                                JotForm.setFieldConditions('input_' + id, 'change', condition);
                                JotForm.widgetsWithConditions.push(id);
                            break;
                            case "combined":
                            case "email":
                                JotForm.setFieldConditions('id_' + id, 'autofill', condition);
                            break;
                            case "address":
                                JotForm.setFieldConditions('id_' + id, 'autofill', condition);
                                JotForm.setFieldConditions('input_'+term.field+'_country', 'change', condition);
                            break;
                            case "datetime":
                                JotForm.setFieldConditions('id_' + id, 'date:changed', condition);
                            break;
                            case "birthdate":
                                JotForm.setFieldConditions('input_'+id+'_day', 'change', condition);
                                JotForm.setFieldConditions('input_'+id+'_month', 'change', condition);
                                JotForm.setFieldConditions('input_'+id+'_year', 'change', condition);
                            break;
                            case "time":
                                JotForm.setFieldConditions('input_'+id+'_hourSelect', 'change', condition);
                                JotForm.setFieldConditions('input_'+id+'_minuteSelect', 'change', condition);
                                JotForm.setFieldConditions('input_'+id+'_ampm', 'change', condition);
                            case "select":
                            case "file":
                                JotForm.setFieldConditions('input_' + id, 'change', condition);
                                break;
                            case "checkbox":
                            case "radio":
                                JotForm.setFieldConditions('id_' + id, 'click', condition);
                                break;
                            case "number":
                                JotForm.setFieldConditions('input_' + id, 'number', condition);
                                break;
                            case "autocomplete": // Neil: Set custom event for autocomplete fields (classname: "form-autocomplete")
                                JotForm.setFieldConditions('input_' + id, 'autocomplete', condition);
                                break;
                            case "grading":
                                JotForm.setFieldConditions('id_' + id, 'keyup', condition);
                                break;
                            case "text":
                                JotForm.setFieldConditions('input_' + id, 'autofill', condition);
                                break;
                            default: // text, textarea, dropdown
                                JotForm.setFieldConditions('input_' + id, 'keyup', condition);
                        }
                    });
                    
                } else {


                    if(document.get.mode == "edit" || document.get.mode == "inlineEdit") { //only run page condition on last page that a condition field exists so we don't jump prematurely based on populated data
                        
                        var isLaterPage = function(current, testing) {
                            var nexts = $$('.form-pagebreak-next');
                            for(var i=0; i<nexts.length; i++) {
                                var btn = nexts[i];
                                if(btn == current) return true;
                                if(btn == testing) return false;
                            }
                        };


                        var highestPage = false;
                        $A(condition.terms).each(function(term){
                            var id = term.field;
                            if (term.field.indexOf("_") !== -1) {
                                id = term.field.split("_")[0];
                            }
                            
                            var nextButton = JotForm.getSection($('id_' + id)).select('.form-pagebreak-next')[0];
                            if (!nextButton) {
                                return;
                            }
                            var pageNumber = parseInt(nextButton.id.substring(nextButton.id.lastIndexOf("_")+1));
                            if(!highestPage || isLaterPage(highestPage, nextButton)) {
                                highestPage = nextButton;
                            }
                        });

                        if(highestPage) {
                            highestPage.observe('mousedown', function(){
                                JotForm.checkCondition(condition);
                            });
                        }
                    } else {
                        $A(condition.terms).each(function(term){
                            var id = term.field;
                            
                            // if this is a product quantity option (e.g. 4_quantity_1009_0)
                            if (term.field.indexOf("_") !== -1) {
                                // get ID (4)
                                id = term.field.split("_")[0];
                            }
                            
                            var nextButton = JotForm.getSection($('id_' + id)).select('.form-pagebreak-next')[0];
                            if (!nextButton) {
                                return;
                            }

                            nextButton.observe('mousedown', function(){
                                // JotForm.warn('Checking ' + $('label_' + id).innerHTML.strip());
                                JotForm.checkCondition(condition);
                            });
                        });
                    }
                }
            });
            
            $H(JotForm.fieldConditions).each(function(pair){
                var field = pair.key;
                var event = pair.value.event;
                var conds = pair.value.conditions;
                
                // JotForm.info("Has Condition:", field, $(field));
                // If field is not found then continue
                if(!$(field)){ return; }
                if(event == "autocomplete"){ // if event type is trigger by autocomplete, listen to blur and keyup events
                    $(field).observe('blur', function(){
                        $A(conds).each(function(cond){
                            JotForm.checkCondition(cond);
                        });
                        }).run('blur');
                    $(field).observe('keyup', function(){
                        $A(conds).each(function(cond){
                            JotForm.checkCondition(cond);
                        });
                        }).run('keyup');
                } else if(event == "number") {
                    $(field).observe('change', function(){
                        $A(conds).each(function(cond){
                            JotForm.checkCondition(cond);
                        });
                        }).run('change');
                    $(field).observe('keyup', function(){
                        $A(conds).each(function(cond){
                            JotForm.checkCondition(cond);
                        });
                    }).run('keyup'); 
                } else if(event == "autofill") {
                    $(field).observe('blur', function(){
                        $A(conds).each(function(cond){
                            JotForm.checkCondition(cond);
                        });
                        }).run('blur');
                    $(field).observe('keyup', function(){
                        $A(conds).each(function(cond){
                            JotForm.checkCondition(cond);
                        });
                        }).run('keyup');

                    if(!(!Prototype.Browser.IE9 && !Prototype.Browser.IE10 && Prototype.Browser.IE)) {
                        $(field).observe('change', function(){
                            $A(conds).each(function(cond){
                                JotForm.checkCondition(cond);
                            });
                            }).run('change');
                    }
                } else {
                    $(field).observe(event, function(){
                        $A(conds).each(function(cond){
                            JotForm.checkCondition(cond);
                        });
                    }).run(event);
                }
            });
        }catch(e){ 
            JotForm.error(e); 
        }
    },
    
    /**
     * Changes payment strings upon form load 
    * @param {type} text
     * @returns {undefined}
     */
    
    changePaymentStrings: function (text) {
        if ($('coupon-header') && text.couponEnter) {
            $('coupon-header').innerHTML = text.couponEnter;
        }
        if ($('shipping-text') && text.shippingShipping) {
            $('shipping-text').innerHTML = text.shippingShipping + ':';
        }
        if ($('tax-text') && text.taxTax) {
            $('tax-text').innerHTML = text.taxTax + ':';
        }
        if ($('subtotal-text') && text.totalSubtotal) {
            $('subtotal-text').innerHTML = text.totalSubtotal + ':';
        }
        if ($('total-text') && text.totalTotal) {
            $('total-text').innerHTML = text.totalTotal + ':';
        }
    },
    /*
     * Handles custom amount payment with values from calculation widget
     */        
    
    handleDonationAmount: function () {
        var donationField = $$('input[id*="_donation"]')[0];
        var calcField = $('input_' + donationField.getAttribute('data-custom-amount-field'));
        // if calculation widget does not exist
        if (!calcField) {
            return;
        }

        var getVal = function() {
            var val = calcField.value;
            if(typeof val !== 'number') {
                val = val.replace(/[^0-9\.]/gi, "");
            }
            return !isNaN(val) && val > 0 ? val : 0;
        }


        // get value from calculation widget
        setTimeout(function(){
            donationField.value = getVal();
        }, 1000);
        // observe calc widget value changes 
        // prototype can't observe changes initiated by a js function to a field value
        // so we use Form.element.Observer which checks for changes every 'x' milliseconds
        new Form.Element.Observer(
            calcField,
            0.5,  // 500 milliseconds
            function(el, value){
                donationField.value =  getVal();
            }
        );
    },
    
    /**
     * Checks whether form should process a payment
     * @returns {Boolean}
     */
    
    isPaymentSelected: function () {
        var selected = false;
        var paymentFieldId = $$('input[name="simple_fpc"]')[0].value;
        var paymentField = $('id_' + paymentFieldId);
        
        if ( $$('input[name="simple_fpc"]').length < 1) {
            return false;
        }
        // if with payment field but hidden by condition
        // or inside conditionally-hidden (not collapsed) form collapse section
        if (paymentField && (paymentField.getStyle('display') === "none"  
                || !JotForm.isVisible(paymentField) && JotForm.getSection(paymentField).id)
        ) { 
            return false;
        }
        // if this is a multi-item product or subscription
        if (window.productID) {
            // check if at least one product is selected
            $H(window.productID).each(function(pair) {
                var elem = $(pair.value);
                if (elem.checked) {
                    selected = true;
                    throw $break;
                }
            });
        // if this is a donation
        } else if ($('input_' + paymentFieldId + '_donation')) {
                var elem = $('input_' + paymentFieldId + '_donation');
                if (/^\d+(?:\.\d+)?$/.test(elem.getValue())) {
                    selected = elem.getValue() > 0;
                }
        // if this is a hidden single item     
        } else {
            selected = $$('input[name*="q' + paymentFieldId +'"][type="hidden"]').length > 0;
        }
        return selected;
    },
            
    /**
     * Toggles between paypal button and regular submit button
     * @param {type} show
     * @returns {unresolved}
     */
     
    togglePaypalButtons: function(show) {
        var paymentFieldId = $$('input[name="simple_fpc"]')[0].value;
        // if this is paypal pro and credit card payment is selected
        if ($('input_' + paymentFieldId + '_paymentType_express') 
                && !$('input_' + paymentFieldId + '_paymentType_express').checked) 
        {
                show = false;
        }
        // if checkout button is not to be used
        if ($$('.paypal-button').length < 1 || !$('use_paypal_button')) {
            return;
        }
        // replace all submit buttons with express checkout buttons
        $$('.form-submit-button').each(function(btn){
            if (show) {
                btn.siblings()[0].show();
                btn.hide();
            } else {
                btn.siblings()[0].hide();
                btn.show();
            }
        });
    },
          
    /*
     * Handles toggling between PayPal checkout buttons
     * and ordinary submit buttons
     * @returns {undefined}
     */
     
    handlePaypalButtons: function () {
        var products = window.productID;
        var requiredPayment = false;
        var paymentFieldId = $$('input[name="simple_fpc"]')[0].value;
        // check if payment is required 
        if (products) {
            $H(products).each(function(p){
                // if required
                if ($(p.value).getAttribute('class').indexOf('[required]') > -1) {
                    requiredPayment = true;
                    throw $break;
                }
            });
        } else if ($('input_' + paymentFieldId + '_donation')) {
            requiredPayment = $('input_' + paymentFieldId + '_donation').getAttribute('class').indexOf('required') > -1;
        }
        // toggle upon form load
        JotForm.togglePaypalButtons(requiredPayment || JotForm.isPaymentSelected());
        
        // set button trigger if payment is not required
        if (!requiredPayment) {
            $H(products).each(function(p) {
                $(p.value).observe('click', function() {
                    JotForm.togglePaypalButtons(JotForm.isPaymentSelected());
                });
            });
        }
    },
    
    /*
     * Checks whether form is embedded or not
     * Sends 'embeddedForm' input value
     * @returns {undefined}
     */
    isFormEmbedded: function () {
        var form = $$('.jotform-form')[0];
        var embedded = Number(window !== window.top);
        form.insert(new Element('input', {
            type: 'hidden',
            name: 'embeddedForm'
            }).putValue(embedded)
        );
    },
    
    /**
     * Handles Paypal Express actions
     * @returns {undefined}
     */
    
    handlePaypalExpress: function () {
        if (typeof _paypalExpress !== "function" || $('express_category').getAttribute('data-digital_goods') === "No") {
            return;
        }
        var paypalExpress = new _paypalExpress();
        paypalExpress.init();
    },
    
    /**
     * Handles the payment subproducts behavior
     */
    
    handlePaymentSubProducts: function(){
        
        var heights = [];                   // container for the heights of the products when opened and closed
        var optionValues = [];              // container for the values of the properties when opened and closed
        var sections = $$('.form-section'); // get the sections if there are page breaks
        var productPage = false;            // page where the payment field is
        
        $$('.form-product-has-subproducts').each(function(sp){
            // if this form has page breaks, 
            if (sections.length > 1) {
                // get the page where the payment field is
                productPage = productPage ? productPage : sections.filter(function(p){
                    return sp.descendantOf(p);
                })[0];
                // if this page is hidden
                if (!productPage.isVisible()) {
                    // show page temporarily
                    productPage.setStyle({'display' : 'block'});
                    // get the height of the product
                    heights[sp.id] = [sp.parentNode.getHeight(), $$('label[for="' + sp.id + '"]')[0].getHeight()];
                    // hide the page
                    productPage.setStyle({'display' : 'none'});
                } else {
                    heights[sp.id] = [sp.parentNode.getHeight(), $$('label[for="' + sp.id + '"]')[0].getHeight()];
                }
            } else {
                heights[sp.id] = [sp.parentNode.getHeight(), $$('label[for="' + sp.id + '"]')[0].getHeight()];
            }
            
            showSubProducts(sp);
            sp.observe('click', function(){
                showSubProducts(this);
            });
        });
        
        function showSubProducts(el){
            
            var productSpan = el.parentNode;
            
            if(!el.checked){
                productSpan.shift({
                    height: heights[el.id][1],
                    duration: 0.3
                });
                // clear the values array
                optionValues[el.id] = [];
                
                $$('#' + el.id + '_subproducts select,' + '#' + el.id + '_subproducts input[type="text"]').each(function(field, i){
                    // capture the values
                    var fieldValue = field.tagName === "select" ? field.getSelected().value : field.value;
                    if(fieldValue){
                        optionValues[el.id].push([field.id, fieldValue]);
                    }
                    // pause calculation functions to avoid potential browser crash
                    field.stopObserving();
                    // clear values
                    if(field.tagName === "SELECT"){
                        field.selectedIndex = 0;
                    } else {
                        field.value = 0;
                    }
                });
            } else {
                productSpan.shift({
                    height: heights[el.id][0]-10,
                    duration: 0.3
                });
                // populate values
                if(optionValues[el.id] && optionValues[el.id].length > 0){
                    optionValues[el.id].each(function(vv){
                        // pause calculation functions to avoid potential browser crash
                        $(vv[0]).stopObserving();
                        if($(vv[0]).tagName === "SELECT"){
                            $(vv[0]).selectOption(vv[1]);
                        } else {
                            $(vv[0]).value = vv[1];
                        }
                    });
                }
            }
            // resume calculation
            setTimeout(JotForm.totalCounter(JotForm.prices), 300);
        };
    },
    /*
     * sets currency formatting for payment fields
     */
    
    setCurrencyFormat: function (curr, useDecimal) {
        // currencies without decimal values
        var noDecimal = ['BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VUV', 'XAF', 'XOF', 'XPF'];
        var decimalPlaces = noDecimal.indexOf(curr) > -1 || !useDecimal ? 0 : 2;
        this.currencyFormat = {
            curr: curr,
            decimal: decimalPlaces
        };
    },
            
    /**
     * Calculates the payment total with quantites
     * @param {Object} prices
     */
    countTotal: function(prices){
        var prices = prices || JotForm.prices;
        var discounted = false;
        // If a coupon is entered and verified
        if(Object.keys(JotForm.discounts).length > 0) {
            discounted = true;
            // if this is a discount for order total
            if (JotForm.discounts.total || JotForm.discounts.shipping) {
                var type  = JotForm.discounts.type,
                    rate  = JotForm.discounts.rate,
                    minimum = JotForm.discounts.minimum,
                    code = JotForm.discounts.code;
                
            } else {
                // If for product items
                for(var pid in prices) {
                    for(var kkey in JotForm.discounts) {
                        if(pid.indexOf(kkey)!== -1) {
                            prices[pid].discount = JotForm.discounts[kkey];
                        } 
                    }
                }
            }
        } else {
            $H(prices).each(function(p){
                delete prices[p.key].discount;
            });
        }
        
        var total = 0;          // total for the whole payment field
        var subTotal = 0;       // subtotal for all items selected, excluding shipping or taxes
        var itemSubTotal = [];  // subtotal for a group of subproducts
        var shippingTotal = 0;  // total shipping cost
        var taxTotal = 0;       // total tax cost
        var taxRate = 0;        // uniform tax rate (percentage) for the non-exempted products
        var decimal = JotForm.currencyFormat.decimal; // number of decimal places to use
        
        $H(prices).each(function(pair){
            var isSetupFee = pair.value.recurring ? true : false; // is there a setup fee for this subscription?
            var isStripe = typeof Stripe === "function";    // is this a stripe payment field
            total = parseFloat(total);                  // total for the whole payment field
            var productShipping = 0;                    // shipping cost for current product
            var price = parseFloat(pair.value.price);   // price for the individual product
            var taxAmount = 0;                          // tax amount for the individual product
            var subproduct = false;                     // is this a subproduct?
            var parentProductKey;                       // subproduct's parent key (see http://www.jotform.com/help/264-Create-Sub-Products-Based-on-a-Product-Option)
            var recur = pair.value.recurring;           // subscription's recurring payment amount

            // get the parent product id if this is a subproduct
            if (pair.key.split('_').length === 4) {
                subproduct = true;
                // get the parent product key/id
                parentProductKey = pair.key.split('_');
                parentProductKey.pop();
                parentProductKey = parentProductKey.join("_");
                // initalize item subtotal for this subproduct group
                itemSubTotal[parentProductKey] = itemSubTotal[parentProductKey] || 0;
            } else {
                parentProductKey = pair.key;
            }
            
            // if product has special pricing, use selected option's corresponding price
            if ($(pair.value.specialPriceField)) { 
                var specialPriceField = $(pair.value.specialPriceField);
                // if this special priced product option is expanded
                // Note: expanded options are inserted on the form as hidden input fields
                if(pair.value.child && pair.value.specialPriceField.split("_").length === 4){
                    var idx = pair.value.specialPriceField.split("_")[3];
                    price = parseFloat(pair.value.specialPriceList[idx]);
                } else {
                    price = parseFloat(pair.value.specialPriceList[specialPriceField.getSelected().index]);
                    if($(pair.key + '_price')) {
                        $(pair.key + '_price').siblings('.freeCurr').each(function(el) { el.style.display = 'inline';});
                    }
                }
            }
            // If there is a coupon, apply the discount rate to the price
            if (pair.value.discount) {
                var discount = pair.value.discount.split('-');
                /*
                 * sample discount values:
                 * 50-percent ( 50% off for this product )
                 * 50-fixed ( $50 off for this product )
                 * 50-percent-first ( 50% off on first payment for this subscription item)
                 * 50-percent-all (50 % off on all payments for this subscription item)
                 * 50-fixed-all ( $50 off on all payments)
                 */
                
                // if this is a discount for product
                if (!discount[2]) {
                    price = price - ( ( discount[1] === 'fixed' ) ? discount[0] : price * ( discount[0] / 100 ) );
                    price = price < 0 ? 0 : price;
                } else {
                    if (discount[2] === "all") {
                        // calculate discount to recurring charge
                        if (isSetupFee) {
                            recur = recur - ( ( discount[1] === 'fixed' ) ? discount[0] : recur * ( discount[0] / 100 ) );
                            recur = recur < 0 ? 0 : recur;
                        }
                        // if this is Stripe and there is a setup fee
                        if (isStripe && isSetupFee) {
                            // calculate setup fee
                            var setupFee = price - recur;
                            setupFee = setupFee - ( ( discount[1] === 'fixed' ) ? discount[0] : setupFee * ( discount[0] / 100 ) );
                            setupFee = setupFee < 0 ? 0 : setupFee;
                            price = Number(recur) + Number(setupFee);
                        } else {
                            // calculate recurring price
                            price = price - ( ( discount[1] === 'fixed' ) ? discount[0] : price * ( discount[0] / 100 ) );
                            price = price < 0 ? 0 : price;
                        }
                    } else if (discount[2] === "first") {
                        if (isSetupFee) {
                            if (isStripe) {
                                /**
                                 * Neil: Stripe is a special case since their api does not offer a setup fee, so we do a separate charge for the setup fee
                                 * So first payment = recurring charge + separate charge
                                 * Therefore subscription discount for first payment actually applies only to the setup fee (first payment - recurring charge))
                                 */
                                var setupFee = price - recur;
                                setupFee = setupFee - ( ( discount[1] === 'fixed' ) ? discount[0] : setupFee * ( discount[0] / 100 ) );
                                setupFee = setupFee < 0 ? 0 : setupFee;
                                price = Number(recur) + Number(setupFee);
                                
                            } else {
                                price = price - ( ( discount[1] === 'fixed' ) ? discount[0] : price * ( discount[0] / 100 ) );
                                price = price < 0 ? 0 : price;
                            }
                        }
                    } else if (discount[2] === "stripe_native") {
                        // if native stripe coupon is used and there is a setup fee
                        if (isSetupFee) {
                            var setupFee = price - recur;
                            price = recur = recur - ( ( discount[1] === 'fixed' ) ? discount[0] : recur * ( discount[0] / 100 ) );
                            price += Number(setupFee);
                        } else {
                            // calculate recurring price
                            price = price - ( ( discount[1] === 'fixed' ) ? discount[0] : price * ( discount[0] / 100 ) );
                            price = price < 0 ? 0 : price;
                        }
                    }
                }
                
            }
            
            // If there is no recurring payment (i.e., not a subscription), update the price
            if (!pair.value.recurring ) {
                var priceText = $(pair.key + '_price') ?  $(pair.key + '_price') : $(pair.key.replace(pair.key.substring(pair.key.lastIndexOf("_")), "") + '_price') || null;
                if (priceText) {
                    var oldPriceText = priceText.innerHTML;
                    if (pair.value.price === "0" && !pair.value.specialPriceList) {
                        $(priceText).update(' Free');
                    } else {
                        $(priceText).update(parseFloat(price).formatMoney(decimal));
                    }
                    }
            } else {
                var setupfeeText = $(pair.key + '_setupfee');
                priceText = $(pair.key + '_price');
                if (priceText) {
                    // if a setup fee is not present, pair.value.price (price) is the subscription's price  
                    // otherwise, pair.value.price is the subscription's first payment amount and the subscription's price becomes pair.value.recurring (recur)
                    var priceAmount = isSetupFee ? recur : price;
                    $(priceText).update(parseFloat(priceAmount).formatMoney(decimal));
                }
                if (setupfeeText) {
                    $(setupfeeText).update(parseFloat(price).formatMoney(decimal));
                }
            }
            
            // If there is a tax, get the total tax rate including location surcharges
            if (pair.value.tax) {
                var tax = pair.value.tax;
                taxRate = parseFloat(tax.rate);
                // if location surcharge dropdown exists and there is a selected value, get the corresponding surcharge value
                if($$('select[id*="input_' + tax.surcharge.field + '"]').length > 0 
                        && $$('select[id*="input_' + tax.surcharge.field + '"]')[0].getSelected().value){
                    var selectedIndex = $$('select[id*="input_' + tax.surcharge.field + '"]')[0].getSelected().index - 1; // we subtract 1 to the index because the first index has empty value
                    taxRate += tax.surcharge.rates[selectedIndex] ? parseFloat(tax.surcharge.rates[selectedIndex][0]) : 0;
                }
                // if location surcharge text box exists and there is a value;
                if ($$('input[id="input_' + tax.surcharge.field + '"]').length > 0 
                        && !$$('input[id="input_' + tax.surcharge.field + '"]')[0].value.empty()) {
                    $H(tax.surcharge.rates).each(function(r){
                        if (r[1][1].toLowerCase() === $$('input[id="input_' + tax.surcharge.field + '"]')[0].value.toLowerCase()) {
                            taxRate += Number(r[1][0]);
                            throw $break;
                        }
                    });
                }
            }
                    
            if ($(pair.key).checked) {
                if ($(pair.value.quantityField) || $(pair.value.specialPriceField)) {
                    //if there is a quantity option and special pricing isn't based on it
                    if ($(pair.value.quantityField) && (pair.value.specialPriceField !== pair.value.quantityField)) {
                    // use different calculation method for custom quantity (textbox) option
                        if($(pair.value.quantityField).readAttribute('type') == "text") {
                            price = $(pair.value.quantityField).value ? price * Math.abs(parseInt($(pair.value.quantityField).value, 10)) : 0;
                        }
                        else {
                            price = price * parseInt(($(pair.value.quantityField).getSelected().text || 0 ) , 10);
                        }
                    }
                    
                    // if this is a subproduct, add the price to the subtotal
                    if (subproduct) {
                        itemSubTotal[parentProductKey] += price;
                    }
                    
                    // update item subtotal if available
                    if ($(parentProductKey  + '_item_subtotal') && !isNaN(price)) {
                        if (!subproduct) {
                            $(parentProductKey+ '_item_subtotal').update(parseFloat(price).formatMoney(decimal)); 
                        } else {
                            $(parentProductKey+ '_item_subtotal').update(parseFloat(itemSubTotal[parentProductKey]).formatMoney(decimal)); 
                        }
                    }
                    
                }
                
                // if this product is taxed, calculate the tax amount
                if (pair.value.tax) {
                    taxAmount = price * (taxRate/100);
                }
                // add shipping if it is available
                if (pair.value.shipping && pair.value.shipping.firstItem) {
                    var shipping = pair.value.shipping;
                    var qty = $(pair.value.quantityField) ? ($(pair.value.quantityField).readAttribute('type') === "text" ? parseInt($(pair.value.quantityField).value) : parseInt($(pair.value.quantityField).getSelected().text || 0)) : 1;
                    if (qty === 1){
                        productShipping = parseFloat(shipping.firstItem);
                    } 
                    if (qty > 1 ) {
                        productShipping = !parseFloat(shipping.addItem) ? parseFloat(shipping.firstItem) : parseFloat(shipping.firstItem) + parseFloat(shipping.addItem) * (qty -1);
                    }
                }
                taxTotal += taxAmount; // accummulate tax amounts for each product
                shippingTotal += productShipping;  // accumulate shipping total
                subTotal += price; // accumulate total for all items, without shipping/discount/tax
                total += price + productShipping + taxAmount;   // overall total
                
            } else {
                if ($(pair.key + '_item_subtotal') || isNaN(price)) {
                    $(pair.key + '_item_subtotal').update("0.00"); 
                }
            }
        });
        
        if (total === 0 || isNaN(total)) {
            total = "0.00";
        }
        if ($('coupon-button')) {
            var couponInput = $($('coupon-button').getAttribute('data-qid') + '_coupon');
        }
        // if there is a total discount
        if (JotForm.discounts.total) {
            if(subTotal >= minimum) {
                var reduce = type === "fixed" ? rate : (rate / 100) * parseFloat(subTotal);
                subTotal = subTotal > reduce ? subTotal - reduce : 0 ;
                total = total - reduce;
                couponInput.value = code;
            } else {
                reduce = 0;
                // clear (hidden) coupon input if total is less than required minimum 
                couponInput.value = '';
            }
            // insert discount indicator
            $$('.form-payment-total')[0].insert({'top':JotForm.discounts.container});
            $('discount_total').update(parseFloat(reduce).formatMoney(decimal));
        }
        
        // if there is a shipping discount
        if (JotForm.discounts.shipping && shippingTotal > 0 && subTotal >= minimum) {
            var reduce = type === "fixed" ? rate : (rate / 100) * parseFloat(shippingTotal);
            var oldShippingTotal = shippingTotal;
            shippingTotal = shippingTotal > reduce ? shippingTotal - reduce : 0;
            total = total - (oldShippingTotal - shippingTotal);
        }
        // assign total to global var;
        this.paymentTotal = Number(total);
        // for PaypalPro only
        if($('creditCardTable')){
            // if total is zero and a valid coupon has been entered
            if(this.paymentTotal === 0 && discounted ){
                $('creditCardTable').hide();
            } else if($$('input[id*="paymentType_credit"]')[0].checked){
                $('creditCardTable').show();
            }
        }
        // update payment subtotal
        if ($("payment_subtotal")){
            $("payment_subtotal").update(parseFloat(subTotal).formatMoney(decimal));
        }
        // update tax figures
        if ($("payment_tax")){
            $("payment_tax").update(parseFloat(taxTotal).formatMoney(decimal)); 
            $("payment_tax_rate").update('(' + parseFloat(taxRate) + '%)');
        }
        // update shipping cost total
        if ($("payment_shipping")) {
            $("payment_shipping").update(parseFloat(shippingTotal).formatMoney(decimal));
        }
        // update overall total
        if ($("payment_total")) {
            $("payment_total").update(parseFloat(total).formatMoney(decimal));
        }
    },
    prices: {},
    /**
     * Sets the events for dynamic total calculation
     * @param {Object} prices
     */
    totalCounter: function(prices){
        // format money function
        Number.prototype.formatMoney = function(c, d, t){
        var n = this, 
            c = isNaN(c = Math.abs(c)) ? 2 : c, 
            d = d === undefined ? "." : d, 
            t = t === undefined ? "," : t, 
            s = n < 0 ? "-" : "", 
            i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "", 
            j = (j = i.length) > 3 ? j % 3 : 0;
           return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
         };
        
        // Assign form's initial prices to JotForm.prices object
        // so we can use it later
        JotForm.prices = prices;
        // count total price upon loading the form (Bug:168425)
        document.observe('dom:loaded',JotForm.countTotal(prices));
        $H(prices).each(function(pair){
            $(pair.key).observe('click', function(){
                JotForm.countTotal(prices);
            });
            // if tax is present
            if (pair.value.tax) {
                var surcharge = pair.value.tax.surcharge;
                // observe change event for surcharge location field
                // for dropdowns
                if ($$('select[id*="input_' + surcharge.field + '"]').length > 0) {
                    $$('select[id*="input_' + surcharge.field + '"]')[0].observe('change',function(){
                        setTimeout(JotForm.countTotal(), 500);
                    });
                }
                // for text fields (address:state)
                if ($$('input[id="input_' + surcharge.field + '"]').length > 0) {
                    $$('input[id="input_' + surcharge.field + '"]')[0].observe('keyup', function(){
                        setTimeout(JotForm.countTotal(), 500);
                    });
                }
            }


            var triggerAssociatedElement = function(el) {
                var prodID = $(el).id.match(/input_([0-9]*)_quantity_/) || $(el).id.match(/input_([0-9]*)_custom_/);
                setTimeout(function() {
                    if(prodID && $('id_' + prodID[1])) {
                        $('id_' + prodID[1]).triggerEvent('click');
                    }
                }, 100);
            };
            
            if ($(pair.value.quantityField)) {
                function countQuantityTotal(){
                        if(JotForm.isVisible($(pair.value.quantityField))){
                            // Neil: temporary fix for 287973
                            // because we run the change event for quantity upon loading (to evaluate the conditions), 
                            // the associated product checkbox should not change if quantity did not change value
                            if($(pair.value.quantityField).tagName !== 'SELECT' ||  $(pair.value.quantityField).getSelected().index > 0){
                                $(pair.key).checked = !($(pair.value.quantityField).getValue() <= 0) ? true : false;
                            }
                            JotForm.countTotal(prices);
                        }
                    }

                $(pair.value.quantityField).observe('change', function(){
                    setTimeout(countQuantityTotal,50);
                    triggerAssociatedElement(this);

                });
                // calculate total for custom quantity (text box)
                $(pair.value.quantityField).observe('keyup', function(){
                    setTimeout(countQuantityTotal,50);
                    triggerAssociatedElement(this);
                });
            }
            if ($(pair.value.specialPriceField)) {
                function countSpecialTotal(){
                        if(JotForm.isVisible($(pair.value.specialPriceField))){
                            // because we run the change event for quantity upon loading (to evaluate the conditions), 
                            // the associated product checkbox should not change if quantity did not change value
                            if($(pair.value.specialPriceField).tagName !== 'SELECT' ||  $(pair.value.specialPriceField).getSelected().index > 0){
                                $(pair.key).checked = true;
                            }
                            JotForm.countTotal(prices);
                        }
                    }
                $(pair.value.specialPriceField).observe('change', function(){
                    setTimeout(countSpecialTotal,50);
                    triggerAssociatedElement(this);
                });
                $(pair.value.specialPriceField).observe('keyup', function(){
                    setTimeout(countSpecialTotal,50);
                });
            }
        });
    },
    
    /**
     * Holds discount rates from verified coupon codes 
     */
    discounts: {},
    
    /**
     * Handles payment coupon code verification
     */
    
    handleCoupon: function() {
        var $this = this;
        JotForm.countTotal(JotForm.prices);
        if($('coupon-button')) {
            var cb = $('coupon-button'),
                cl = $('coupon-loader'),
                cm = $('coupon-message'),
                ci = $('coupon-input');
            
            cb.innerHTML = this.paymentTexts.couponApply;
            var formID = $$('input[name="formID"]')[0].value;
            // prevent enter from submitting the form on coupon input
            ci.observe('keypress', function(e) {
                if(e.keyCode === 13) {
                    e.preventDefault();
                    cb.click();
                    ci.blur();
                }
            });
            
            // reset coupon inputs
            ci.enable();
            $$('input[name="coupon"]')[0].value = "";
            
            // verify the coupon on click
            cb.observe('click', function (){
                if (ci.value) {
                    cb.hide();
                    cl.show();
                    ci.value = ci.value.replace(/\s/g, "");
                    cb.disable();
                    var a = new Ajax.Jsonp(JotForm.server, {
                        parameters: {
                            action: 'checkCoupon',
                            coupon: ci.value,
                            formID: formID,
                            stripe: ci.hasAttribute('stripe'),
                            paymentID: $$('input[name="simple_fpc"]')[0].value
                        },
                        evalJSON: 'force',
                        onComplete: function(t){
                            t = t.responseJSON || t;
                            if (t.success) {
                                console.log(t.message);
                                if (t.message.indexOf('{') === -1) {
                                    if(t.message === "expired"){
                                        cm.innerHTML = $this.paymentTexts.couponExpired;
                                    } else {
                                        cm.innerHTML = $this.paymentTexts.couponInvalid;
                                    }
                                    ci.select();
                                    cl.hide();
                                    cb.show();
                                    cb.enable();
                                } else {
                                    cl.hide();
                                    cb.show();
                                    cm.innerHTML = $this.paymentTexts.couponValid;
                                    JotForm.applyCoupon(t.message);
                                }
                            }
                        }
                    });
                } else {
                    $('coupon-message').innerHTML = $this.paymentTexts.couponBlank;
                }
            });
        }
    },
    /** 
     *  Applies coupon to prices on the front-end
     *  @param {Object} discount
     */
    
    applyCoupon: function(discount) {
        var $this = this;
        discount = JSON.parse(discount);
        JotForm.discounts = {};
        
        var cb = $('coupon-button'),
            cl = $('coupon-loader'),
            cm = $('coupon-message'),
            ci = $('coupon-input'),
            cf = $(cb.getAttribute('data-qid') + '_coupon'); // Hidden input for passing coupon to server (submit)
        cb.stopObserving('click');
        if(cf){
            cf.value = discount.code;
        }
        cb.enable();
        ci.disable();
        cb.innerHTML = this.paymentTexts.couponChange;
        // When 'Change' button is clicked
        cb.observe('click', function(){
            // Clear hidden coupon input value
            cf.value = '';
            // Remove all original prices
            oldPrice.each(function(op){
                op.remove();
            });
            // Remove "Discount" indicator container if present
            if(JotForm.discounts.container){
                JotForm.discounts.container.remove();
            }
            //
            $$('span[id*="_price"]').each(function(field, id){                
                $(field).removeClassName('underlined');
            });
            $$('span[id*="_setupfee"]').each(function(field, id){                
                $(field).removeClassName('underlined');
            });
            // clear discounts object
            JotForm.discounts = {};
            cb.stopObserving('click');
            cm.innerHTML = "";
            cb.innerHTML = $this.paymentTexts.couponApply;
            ci.enable();
            ci.select();
            JotForm.handleCoupon();
        });
        var pair = [], oldPrice = [];
        // if this discount applies to product/subscription items
        // and discount applies to ALL items
        if (discount.products && discount.products.length > 0) {
            if(discount.products.include('all')){
                discount.products = []; 
                for(var key in productID) {
                    discount.products.push(productID[key].slice(-4));
                }
            }
        }
        // if the discount's payment type is product
        if (!discount.paymentType || (discount.paymentType && discount.paymentType === "product")) {
            // if this is a discount for individual items
            if(discount.apply === "product") {

                $A(discount.products).each(function(pid){
                    JotForm.discounts[pid] = discount.rate + '-' + discount.type;
                    $$('span[id*="_price"]').each(function(field, id){
                        if(field.id.indexOf(pid) > -1){
                            $(field).addClassName('underlined');
                        }
                    });

                    if($$('label[for*="' + pid + '"] span.form-product-details b')[0]){
                        var priceContainer = $$('label[for*="' + pid + '"] span.form-product-details b')[0];
                        /*  The original price will be decreased by countTotal
                         *  The lines below will copy the unmodified original price and insert it before 
                         *  the discounted price
                         */ 
                        oldPrice[pid] = new Element('span');
                        var span = new Element('span', {style: 'text-decoration:line-through'});
                        span.insert(priceContainer.innerHTML.replace("price", "price_old"));
                        oldPrice[pid].insert({top: '&nbsp'});
                        oldPrice[pid].insert(span);
                        oldPrice[pid].insert({bottom: '&nbsp'});
                        priceContainer.insert({top: oldPrice[pid]}); 
                    }
                });
            } else if (discount.apply === "total") {
                // if discount is for order total (excluding tax, shipping, etc)
                var discountHTML = $$('.form-payment-total b')[0].innerHTML.replace('Total:','Discount:').replace('payment_total','discount_total').replace('<span>','<span> - ');
                // if this is a discount for the order total
                // add discount properties to JotForm.discounts 
                // to be evaluated by countTotal
                JotForm.discounts = {
                    total: true,
                    code: discount.code,
                    minimum: discount.minimum,
                    type: discount.type,
                    rate: discount.rate,
                    container : new Element('span').insert(discountHTML + '<br><br>').setStyle({fontSize:'10px'})
                };
            } else {
                JotForm.discounts = {
                    shipping: true,
                    code: discount.code,
                    minimum: discount.minimum,
                    type: discount.type,
                    rate: discount.rate
                };
            }
        } else {
            
            // Neil: subscription coupons can either be applied to
            // a) first payment only (if first payment is specified)
            // b) all payments -- recurring and first payment
            
            // if the discount's payment type is subscription
            $A(discount.products).each(function(pid){ 
                JotForm.discounts[pid] = discount.rate + '-' + discount.type;
                // specify to which does this discount apply
                if (discount.apply) {
                    JotForm.discounts[pid] += "-" + discount.apply;
                }
                
                $$('span[id*="_price"]').each(function(field, id){
                    // if price container is found and there is a setup fee and this discount applies 
                    // to ALL payment for the current subscription item
                    // set style underlined, to note that the price was changed because of the discount
                    if (field.id.indexOf(pid) > -1 &&  $$('span[id*="' + pid + '_setupfee"]').length > 0 && discount.apply === "all"){
                        $(field).addClassName('underlined');
                        throw $break;
                    }
                });
                
                $$('span[id*="_setupfee"]').each(function(field, id){
                    if (field.id.indexOf(pid) > -1){
                        $(field).addClassName('underlined');
                        throw $break;
                    }
                });
            });
        }
        
        
        // call countTotal to update the prices
        JotForm.countTotal(JotForm.prices);
    },

    /**
     * Properly sets the public key for Stripe if any
     */
    setStripeSettings: function( pubkey, add_qid )
    {
        //check if the Stripe v1 library is loaded
        if (
            (pubkey || add_qid) && typeof Stripe === 'function' &&
            typeof Stripe.setPublishableKey === 'function' &&
            typeof _StripeValidation === 'function'
        )
        {
            var clean_pubkey = pubkey.replace(/\s+/g, '');
            Stripe.setPublishableKey( clean_pubkey );

            //set the validation
            var stripeV = new _StripeValidation();
                stripeV.setAddress_qid(add_qid);
                stripeV.init();
        }
    },

    /**
     * Initialize filepickerIO uploader
     * @param options - the filepickerIO options
     */
    setFilePickerIOUpload: function( options )
    {
        //check if filepickerIO script is available
        if (
            options && typeof filepicker === "object" &&
            typeof _JF_filepickerIO === "function"
        )
        {
            //start the filepickerIO Uploader
            var fp = new _JF_filepickerIO();
            fp.init(options);
        }
        else
        {
            console.error("filepicker OR _JF_filepickerIO object library are missing");
        }
    },

    /**
     * Initiates the capctha element
     * @param {Object} id
     */
    initCaptcha: function(id){
        /**
         * When captcha image requested on foreign pages
         * It gives error on initial load, probably because
         * SCRIPT embed. However when we delay the execution 
         * Image request this problems resolves.
         */
        setTimeout(function(){
            // https://submit.jotformpro.com certificate has compatibility issues with IE8 #418400
            var UA = navigator.userAgent.toLowerCase(),
                IE = (UA.indexOf('msie') != -1) ? parseInt(UA.split('msie')[1], 10) : false;
            if (IE && IE < 9) {
                // IE 8 and below
                if (UA.indexOf('windows nt 5.1') != -1 || UA.indexOf('windows xp') != -1 || UA.indexOf('windows nt 5.2') != -1) {
                    // windows XP
                    JotForm.server = "https://www.jotform.com/server.php";
                }
            }
            
            var a = new Ajax.Jsonp(JotForm.server, {
                parameters: {
                    action: 'getCaptchaId'
                },
                evalJSON: 'force',
                onComplete: function(t){
                    t = t.responseJSON || t;
                    if (t.success) {
                        $(id + '_captcha').src = 'https://www.jotform.com/server.php?action=getCaptchaImg&code=' + t.num;
                        $(id + '_captcha_id').value = t.num;
                    }
                }
            });
        }, 150);
    },
    /**
     * Relads a new image for captcha
     * @param {Object} id
     */
    reloadCaptcha: function(id){
        $(id + '_captcha').src = JotForm.url+'images/blank.gif';
        JotForm.initCaptcha(id);
    },
    /**
     * Zero padding for a given number
     * @param {Object} n
     * @param {Object} totalDigits
     */
    addZeros: function(n, totalDigits){
        n = n.toString();
        var pd = '';
        if (totalDigits > n.length) {
            for (i = 0; i < (totalDigits - n.length); i++) {
                pd += '0';
            }
        }
        return pd + n.toString();
    },
    /**
     * @param {Object} d
     */
    formatDate: function(d){
        var date = d.date;
        var month = JotForm.addZeros(date.getMonth() + 1, 2);
        var day = JotForm.addZeros(date.getDate(), 2);
        var year = date.getYear() < 1000 ? date.getYear() + 1900 : date.getYear();
        var id = d.dateField.id.replace(/\w+\_/gim, '');
        $('month_' + id).value = month;
        $('day_' + id).value = day;
        $('year_' + id).value = year;
        $('id_'+id).fire('date:changed');
    },
    /**
     * Highlights the lines when an input is focused
     */
    highLightLines: function(){
        
        // Highlight selected line
        $$('.form-line').each(function(l, i){
            l.select('input, select, textarea, div, table div, button').each(function(i){
                
                i.observe('focus', function(){
                    if (JotForm.isCollapsed(l)) {
                        JotForm.getCollapseBar(l).run('click');
                    }
                    if(!JotForm.highlightInputs){ return; }
                    l.addClassName('form-line-active');
                    // for descriptions
                    if(l.__classAdded){ l.__classAdded = false; }
                }).observe('blur', function(){
                    if(!JotForm.highlightInputs){ return; }
                    l.removeClassName('form-line-active');
                });
            });
        });
    },
    /**
     * Gets the container FORM of the element
     * @param {Object} element
     */
    getForm: function(element){
        element = $(element);
        if (!element.parentNode) {
            return false;
        }
        if (element && element.tagName == "BODY") {
            return false;
        }
        if (element.tagName == "FORM") {
            return $(element);
        }
        return JotForm.getForm(element.parentNode);
    },
    /**
     * Gets the container of the input
     * @param {Object} element
     */
    getContainer: function(element){
        element = $(element);
        if (!element.parentNode) {
            return false;
        }
        if (element && element.tagName == "BODY") {
            return false;
        }
        if (element.hasClassName("form-line")) {
            return $(element);
        }
        return JotForm.getContainer(element.parentNode);
    },
    
    /**
     * Get the containing section the element
     * @param {Object} element
     */
    getSection: function(element){
        element = $(element);
        if (!element.parentNode) {
            return false;
        }
        if (element && element.tagName == "BODY") {
            return false;
        }
        if ((element.hasClassName("form-section-closed") || element.hasClassName("form-section")) && !element.id.match(/^section_/)) {
            return element;
        }
        return JotForm.getSection(element.parentNode);
    },
    /**
     * Get the fields collapse bar
     * @param {Object} element
     */
    getCollapseBar: function(element){
        element = $(element);
        if (!element.parentNode) {
            return false;
        }
        if (element && element.tagName == "BODY") {
            return false;
        }
        if (element.hasClassName("form-section-closed") || element.hasClassName("form-section")) {
            return element.select('.form-collapse-table')[0];
        }
        return JotForm.getCollapseBar(element.parentNode);
    },
    /**
     * Check if the input is collapsed
     * @param {Object} element
     */
    isCollapsed: function(element){
        element = $(element);
        if (!element.parentNode) {
            return false;
        }
        if (element && element.tagName == "BODY") {
            return false;
        }
        if (element.className == "form-section-closed") {
            return true;
        }
        return JotForm.isCollapsed(element.parentNode);
    },
    /**
     * Check if the input is visible
     * @param {Object} element
     */
    isVisible: function(element){
        element = $(element);
        if (!element.parentNode) {
            return false;
        }

        if(element.hasClassName('always-hidden')) {
            return false;
        }
        
        if (element && element.tagName == "BODY") {
            return true;
        }
        
        //exception for rich text editor because element is never visible
        if(element.hasClassName("form-textarea") && element.up('div').down('.nicEdit-main') 
                && (element.up('.form-line') && JotForm.isVisible(element.up('.form-line')))) {
            
            return true;
        }

        if (element.style.display == "none" || element.style.visibility == "hidden") {
            return false;
        }

        return JotForm.isVisible(element.parentNode);
    },
    
    /**
     * Emre: to eneable/disable all submit buttons in multi-forms
     */
    enableDisableButtonsInMultiForms: function() {
        var allButtons = $$('.form-submit-button');
        allButtons.each(function(b) {
            if(b.up('ul.form-section')) {
                if(b.up('ul.form-section').style.display == "none") {
                    b.disable();
                } else {
                    if(b.className.indexOf("disabled") == -1){
                        b.enable();
                    }
                }
            }
        });
    },
    
    /**
     * Enables back the buttons
     */
    enableButtons: function(){
        setTimeout(function(){
            $$('.form-submit-button').each(function(b){
                b.enable();
                b.innerHTML = b.oldText;
            });
        }, 60);
    },
    
    /**
     * Sets the actions for buttons
     * - Disables the submit when clicked to prevent double submit.
     * - Adds confirmation for form reset
     * - Handles the print button
     */
    setButtonActions: function(){

        $$('.form-submit-button').each(function(b){
            b.oldText = b.innerHTML;
            b.enable(); // enable previously disabled button

            //Emre: to provide sending form with with clicking "enter" button in Multi-page forms
            //JotForm.enableDisableButtonsInMultiForms();
            if(getQuerystring('qp') === "") {
                b.observe('click', function(){
                    setTimeout(function(){
                        //Emre: to display all submit buttons
                        if(!$$('.form-error-message')[0] && !$$('.form-textarea-limit-indicator-error')[0]){ //Emre: when limit text are is used, submit button doesn't work (51335)
                           var allButtons  = $$('.form-submit-button');
                           allButtons.each(function(bu){
                               bu.innerHTML = JotForm.texts.pleaseWait;
                              //Emre: submit button problem (51335)
                               bu.addClassName('lastDisabled');
                               bu.disable();
                           });
                        }
                    }, 50);
                });
            }
        });

        $$('.form-submit-reset').each(function(b){
            b.onclick = function(){
                if (!confirm(JotForm.texts.confirmClearForm)) {
                    return false;
                }

                //clear all errors after clear form called start feature request 154829
                $$(".form-line-error").each(function(tmp){
                    tmp.removeClassName("form-line-error");

                });

                $$(".form-error-message",".form-button-error").each(function(tmp){
                    tmp.remove();
                });
                //clear all errors after form called end 
                //feature request 154940  must reset any form char limits for textareas start

                    $$(".form-textarea-limit-indicator > span").each(function(tmp){
                        var raw = tmp.innerHTML;
                        tmp.innerHTML = raw.replace(raw.substring(0,raw.indexOf("/")),"0" );

                    });

                //feature request implementation end
                
                //bugfix 187865  also reset grading tools total field
                $$("span[id^=grade_point_]").each(function(tmp){
                  tmp.innerHTML = 0;
                });
                $$(".form-grading-error").each(function(tmp){
                  tmp.innerHTML = ""; //also remove any previous grading errors
                });
                //bugfix end
                //note: TODO: instead of distinctively handling corner cases, it is best to fire a form change event that will trigger correct behaviour -kemal 


                //b#423200 ensure that radios/chks are reset to defaults when autofill is enabled
                var autofill = $$('form')[0].readAttribute('data-autofill');
                if(autofill) {
                    setTimeout(function() {
                        for(var inputId in JotForm.defaultValues) {
                            var input = $(inputId);
                            if(input && (input.type == "radio" || input.type == "checkbox")) {
                                input.checked = true;
                            }
                        }
                    }, 40);
                }

                setTimeout(function(){
                    JotForm.runAllConditions();
                }, 50);
            };
        });
        
        $$('.form-submit-print').each(function(print_button){
        
            print_button.observe("click", function(){
                $(print_button.parentNode).hide();
                //nicedit compatibility start: 
                var hidden_nicedits_arr = []; //nicedit.js rich text editors require special actions this will hold them to allow us to restore them to later stage
                var nicedit_textarea_to_hide = []; //after print completed textareas will be shown, we do not want nicedit textareas to be shown
                //nicedit compatibility end 

                //omer - detecting media print style rules
                /*
                fileCount = document.styleSheets.length;
                injectedCss = document.styleSheets[fileCount-1];
                printStyle = '';

                for(i=0; i<injectedCss.cssRules.length; i++) {
                    if(injectedCss.cssRules[i].media) {
                        if (injectedCss.cssRules[i].media[0]=="print") {
                            printStyle += injectedCss.cssRules[i].cssText;
                        }
                    }
                }
                */
                //omer

                $$('.form-textarea, .form-textbox').each(function(el){
                    
                    if(!el.type){ // type of slider is undefined
                       el.value = el.value || '0'; // to protect problem when slider has no value
                    }
                    //Emre: to prevent css problem on "Date Time" so <span> must be added(66610)
                    var dateSeparate;
                    if(dateSeparate = el.next('.date-separate')){
                        dateSeparate.hide();
                    }
                    //Emre: we must specify "width" and "height" to prevent getting new line
                    var elWidth = "";
                    if(el.value.length < el.size){
                        elWidth = "width:" + el.size*9 + "px;";
                    }

                    //kemal: 'display:inline-block' added to prevent bug:219794 phone field prints miss aligned. display:inline-block only added el is of Phone Field
                    if(el.id.indexOf("_area") != -1 || el.id.indexOf("_phone") != -1 || (el.id.indexOf("_country") != -1 && el.readAttribute('type') == 'tel')){
                        elWidth += " display:inline-block;"
                    }

                    //nicedit compatibility start: kemal: richtext editor compatibility: 1st check if el is form-textarea and also is a rich text editor
                    if(el.hasClassName("form-textarea") && "nicEditors" in window){ //"nicEditors" in window added for somehow if this check fails, do not give errors
                        $$("#cid_"+el.id.split("_")[1]+" > div:nth-child(1)").each(function(tmpel){
                            if(tmpel.readAttribute("unselectable") == "on"){
                                for(var i=0; i<nicEditors.editors.length;i++){
                                    nicEditors.editors[i].nicInstances[0].saveContent(); 
                                }
                                //update richtext value
                                $$("#cid_"+el.id.split("_")[1]+" > div").each(function(richtextdivs){
                                    richtextdivs.hide();
                                    hidden_nicedits_arr.push(richtextdivs); //push hidden divs to hidden_nicedits_arr to be later shown
                                });
                                nicedit_textarea_to_hide.push(el);// push textarea of nicedit, to be later hidden, because after print process completes we show all textareas by default
                            }
                        });
                    }
                    //nicedit compatibility end 


                    /*el.insert({
                        before: new Element('div', {
                            className: 'print_fields'
                        }).update(el.value.replace(/\n/g, '<br>')).setStyle('padding:1px 4px; min-height:18px;' + elWidth)
                    }).hide();*/
                });
                window.print();
                
                /*$$('.form-textarea, .form-textbox, .date-separate').invoke('show');

                //nicedit compatibility start: also show hidden richtextEditor divs and hide richtextEditor textareas start
                for(var i=0; i<hidden_nicedits_arr.length;i++){hidden_nicedits_arr[i].show();}
                for(var i=0; i<nicedit_textarea_to_hide.length;i++){nicedit_textarea_to_hide[i].hide();}
                //nicedit compatibility end

                $$('.print_fields').invoke('remove');*/
                $(print_button.parentNode).show();
            });
            
        });
    },

    /**
    * These will correct any errors in a tool with a validations
    * especially in hidden mode. Thus it will ignore the said validation
    */
    hasHiddenValidationConflicts: function( input )
    {
        var hiddenOBJ = input.up('li.form-line');
        return hiddenOBJ && (hiddenOBJ.hasClassName('form-field-hidden') || hiddenOBJ.up('ul.form-section').hasClassName('form-field-hidden'));
    },

    /**
     * Handles the functionality of control_grading tool
     */
    initGradingInputs: function(){
        
        var _this = this;//JotForm object

        $$('.form-grading-input').each(function(item){

          //register a blur event to validate the
          item.observe('blur', function(){
            item.validateGradingInputs();
          });
          item.observe('keyup', function(){
            item.validateGradingInputs();
          });

          //create a function that will check the validity of inputs
          //attach it to the items/grading inputs
          item.validateGradingInputs = function()
          {
            var item = this,
              id = item.id.replace(/input_(\d+)_\d+/, "$1"),
              total = 0,
              _parentNode = $(item.parentNode.parentNode),
              numeric = /^(\d+[\.]?)+$/,
              isNotNumeric = false;

            //correct any errors first that is attach in the item obj
            item.errored = false;

            _parentNode.select(".form-grading-input").each(function(sibling){
                if ( sibling.value && !numeric.test( sibling.value ) )
                {
                  isNotNumeric = true;
                  throw $break;
                }
                total += parseFloat(sibling.value) || 0;
            });

            //check if hidden, if so return its valid
            if( _this.hasHiddenValidationConflicts(item) ) return JotForm.corrected(item);

            //if not numeric then return an error
            if( isNotNumeric ) {
              return JotForm.errored( item, JotForm.texts.numeric );
            }

            if($("grade_total_" + id)) {
                //set the grade error notifier to empty
                $("grade_error_" + id).innerHTML = "";
                //set the allowed total to the grade_point notifier
                var allowed_total = parseFloat( $("grade_total_" + id).innerHTML );
                $("grade_point_" + id).innerHTML = total;

                if ( total > allowed_total) 
                {
                    //do the error display
                    $("grade_error_" + id ).innerHTML = ' ' + JotForm.texts.lessThan + ' <b>' + allowed_total + '</b>.';
                    return JotForm.errored(item, JotForm.texts.gradingScoreError + " " + allowed_total );
                }
                else
                {
                  //remove error display
                  return JotForm.corrected(item);
                }
            } else {
                return JotForm.corrected(item);
            }
          }
        });
    },
    /**
     * Handles the functionality of control_spinner tool
     */
    initSpinnerInputs: function()
    {
        var _this = this;//JotForm object

        $$('.form-spinner-input').each(function(item){

          //register a blur/change event to validate the data
          item.observe('blur', function(){
            item.validateSpinnerInputs();
          }).observe('change', function(){
            item.validateSpinnerInputs();
          });

          //register an event when the carret is clicked
          var c_parent = item.up('table.form-spinner'),
              c_up = c_parent.select('td.form-spinner-up')[0],
              c_down = c_parent.select('td.form-spinner-down')[0];

          c_up.observe('click', function(e){
              item.validateSpinnerInputs();
          });
          c_down.observe('click', function(e){
              item.validateSpinnerInputs();
          });

          //create a function that will check the validity of inputs
          //attach it to the items/spinner inputs
          item.validateSpinnerInputs = function()
          {
            var item = this,
            id = item.id.replace(/input_(\d+)_\d+/, "$1"),
            numeric = /^(-?\d+[\.]?)+$/,
            numericDotStart = /^([\.]\d+)+$/,  //accept numbers starting with dot
            userInput = item.value || 0;

            //correct any errors first that is attach in the item obj
            item.errored = false;

            //check if hidden, if so return its valid
            if( _this.hasHiddenValidationConflicts(item) ) return JotForm.corrected(item);

            if( userInput && !numeric.test( userInput ) &&  !numericDotStart.test( userInput ) )
            {
                return JotForm.errored( item, JotForm.texts.numeric );
            }

            //read the min and max val total, and check for inputs
            var min_val = parseInt( item.readAttribute('data-spinnermin') ) || false,
                max_val = parseInt( item.readAttribute('data-spinnermax') ) || false;

            if( min_val && userInput < min_val )
            {
              return JotForm.errored(item, JotForm.texts.inputCarretErrorA + " " + min_val );
            }
            else if ( max_val && userInput > max_val )
            {
              return JotForm.errored(item, JotForm.texts.inputCarretErrorB + " " + max_val );
            }
            else
            {
              //remove error display
              return JotForm.corrected(item);
            }
          }
        });
    },


    /**
     * Handles the functionality of control_number tool
     */
    initNumberInputs: function()
    {
        var _this = this;//JotForm object
      
        $$('.form-number-input').each(function(item){

          //register a blur/change event to validate the data
          item.observe('blur', function(){
            item.validateNumberInputs();
          }).observe('change', function(){
            item.validateNumberInputs();
          }).observe('keypress', function(event) {
            // Backspace, tab, enter, end, home, left, right
            // We don't support the del key in Opera because del == . == 46.
            var controlKeys = [8, 9, 13, 35, 36, 37, 39];
            // IE doesn't support indexOf
            var isControlKey = controlKeys.join(",").match(new RegExp(event.which));
            // Some browsers just don't raise events for control keys. Easy.
            // e.g. Safari backspace.
            if (!event.which || // Control keys in most browsers. e.g. Firefox tab is 0
                (49 <= event.which && event.which <= 57) || // Always 1 through 9
                (48 == event.which && $(this).attr("value")) || // No 0 first digit
                (46 == event.which) || (45 == event.which) || (43 == event.which) || // ., -, +
                isControlKey) { // Opera assigns values for control keys.
                return;
            } else {
            event.preventDefault();
            }
          });

          //create a function that will check the validity of inputs
          //attach it to the items/number inputs
          item.validateNumberInputs = function()
          {
            var item = this,
            id = item.id.replace(/input_(\d+)_\d+/, "$1"),
            numeric = /^(-?\d+[\.]?)+$/,
            numericDotStart = /^([\.]\d+)+$/;  //accept numbers starting with dot

            //correct any errors first that is attach in the item obj
            item.errored = false;

            //check if hidden, if so return its valid
            if( _this.hasHiddenValidationConflicts(item) ) return JotForm.corrected(item);

            if( item.value && !numeric.test( item.value ) && !numericDotStart.test( item.value ) && input.hinted !== true) 
            {
                return JotForm.errored( item, JotForm.texts.numeric );
            }

            //read the min and max val total, and check for inputs
            var min_val = parseInt( item.readAttribute('data-numbermin') ),
                max_val = parseInt( item.readAttribute('data-numbermax') ),
                max_len = parseInt( item.readAttribute('maxlength') );

            if( max_len && item.value && item.value.length > max_len )
            {
              return JotForm.errored(item,  JotForm.texts.maxDigitsError + " " + max_len );
            }
            else if( ( min_val || min_val == 0 ) && parseInt( item.value ) < min_val )
            {
              // item.value = min_val;
              return JotForm.errored(item, JotForm.texts.inputCarretErrorA + " " + min_val );
            }
            else if ( max_val && parseInt( item.value ) > max_val )
            {
              // item.value = max_val;
              return JotForm.errored(item, JotForm.texts.inputCarretErrorB + " " + max_val );
            }
            else
            {

                var error = false
                if(item.up('.form-matrix-table')) {
                    item.up('.form-matrix-table').select('input').each(function(el) {
                        if((el !== item) && el.hasClassName('form-validation-error')) {
                            error = true;
                        }
                    });

                }
                //remove error display
                if(!error) {
                    return JotForm.corrected(item);
                }
            }
          }
        });
    },
    /**
     * Handles the pages of the form
     */
    backStack: [],
    currentSection: false,

    handlePages: function(){
        var $this = this;
        var pages = [];
        var last;
        
        // 345261: by default, back button containers gets its width from the label to maintain alignment
        // if they are wider than half the form, resize them
        if($$('.form-label-left').length > 0 ){
            var labelWidth = parseInt($$('.form-label-left')[0].getStyle('width')),
                formWidth = parseInt($$('.form-all')[0].getStyle('width')),
                backButtonWidth = labelWidth > formWidth/2 ? formWidth/2 : labelWidth;
            $$('.form-pagebreak-back-container').each(function(back){
                // resize only if no custom css has been used
                if(back.style.width === ''){
                    back.style.width = (backButtonWidth - 14) + 'px';
                }
            });
        }
        
        $$('.form-pagebreak').each(function(page, i){
            var section = $(page.parentNode.parentNode);
            if (i >= 1) {
                // Hide other pages
                section.hide();
            }else{
                JotForm.currentSection = section;
            }
            pages.push(section); // Collect pages
            
            section.pagesIndex = i+1;

            function stopEnterKey(evt) {
                var evt = (evt) ? evt : ((event) ? event : null);
                var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
                if ((evt.keyCode == 13) && (node.type == "text")) { return false; }
                if(evt.keyCode == 13 && evt.target.hasClassName('form-pagebreak-next') && evt.target.triggerEvent) {
                    evt.target.triggerEvent('mousedown');
                }
            }
            document.onkeypress = stopEnterKey;
            
            section.select('.form-pagebreak-next').invoke('observe', 'click', function(){ // When next button is clicked

                if(JotForm.saving){return;}
                if (JotForm.validateAll(JotForm.getForm(section), section) || getQuerystring('qp') !== "") {

                	if (window.parent && window.parent != window) {
                		window.parent.postMessage('scrollIntoView', '*');
                	}

                    if(JotForm.nextPage){
                        JotForm.backStack.push(section.hide()); // Hide current
                        JotForm.currentSection = JotForm.nextPage.show();

                        //Emre: to prevent page to jump to the top (55389)
                        if(!$this.noJump){
                            JotForm.currentSection.scrollIntoView(true);
                        }

                        JotForm.enableDisableButtonsInMultiForms();
                    }else if (section.next()) { // If there is a next page

                        JotForm.backStack.push(section.hide()); // Hide current
                        // This code will be replaced with condition selector
                        JotForm.currentSection = section.next().show();

                        //show widgets
                        JotForm.currentSection.select('.form-line').each(function(el) {
                            var id = el.id.split("_")[1];
                            if(JotForm.getInputType(id) === 'widget') {
                                JotForm.showWidget(id);
                            }
                        });

                        //Emre
                        if(!$this.noJump && window.parent == window){
                            JotForm.currentSection.scrollIntoView(true);
                        }

                        JotForm.enableDisableButtonsInMultiForms();
                    }

                    JotForm.nextPage = false;
                    if(JotForm.saveForm){
                        JotForm.hiddenSubmit(JotForm.getForm(section));
                    }

                    JotForm.runAllCalculations(true);
                } else {
                    try {
                        $$('.form-button-error').invoke('remove');
                        $$('.form-pagebreak-next').each(function(nextButton){
                            var errorBox = new Element('div', {className:'form-button-error'});
                            errorBox.insert(JotForm.texts.generalPageError);
                            $(nextButton.parentNode.parentNode).insert(errorBox);
                        });
                    } catch(e) {
                        // couldnt find 'next button'
                    }
                }
            });
            
            section.select('.form-pagebreak-back').invoke('observe', 'click', function(){ // When back button is clicked

            	if (window.parent && window.parent != window) {
            		window.parent.postMessage('scrollIntoView', '*');
            	}
            	
                if(JotForm.saving){return;}
                section.hide();
                JotForm.currentSection = JotForm.backStack.pop().show();
                //Emre
                if(!$this.noJump && window.parent == window){
                    JotForm.currentSection.scrollIntoView(true);
                }

                JotForm.nextPage = false;

                JotForm.enableDisableButtonsInMultiForms();

                if(JotForm.saveForm){
                    JotForm.hiddenSubmit(JotForm.getForm(section));
                }
                //clear if there is an error bar near back-next buttons
                $$('.form-button-error').invoke('remove');

                setTimeout(function() {
                    JotForm.runAllCalculations(true); //so newly hidden fields may be excluded 
                }, 10);
            });
        });
        
        // Handle trailing page
        if (pages.length > 0) {
            var allSections = $$('.form-section:not([id^=section_])');
            if (allSections.length > 0) {
                last = allSections[allSections.length - 1];
            }
            
            // if there is a last page
            if (last) {
                last.pagesIndex = allSections.length;
                pages.push(last); // add it with the other pages
                last.hide(); // hide it until we open it
                var li = new Element('li', {
                    className: 'form-input-wide'
                });
                var cont = new Element('div', {
                    className: 'form-pagebreak'
                });
                var backCont = new Element('div', {
                    className: 'form-pagebreak-back-container'
                });
                var back = $$('.form-pagebreak-back-container')[0].select('button')[0];
                
                back.observe('click', function(){
                    if(JotForm.saving){return;}
                    last.hide();
                    JotForm.nextPage = false;
                });
                
                backCont.insert(back);
                cont.insert(backCont);
                li.insert(cont);
                last.insert(li);
            }
        }     
    },
    /**
    * Go straight to page on form load
    */
    jumpToPage: function() {
        var page = document.get.jumpToPage;
        var sections = $$('.form-section:not([id^=section_])');
        
        if(!(page && page > 1) || page > sections.length ) return; //no page to jump to

        sections[0].hide();
        sections[page-1].show();
        
        if(page>2) JotForm.backStack = sections.splice(0, page-1); //so the back button will go to the previous pages and not the first
        
        JotForm.runAllCalculations(true); //so newly hidden fields may be excluded 
    },
    /**
     * Handles the functionality of Form Collapse tool
     */
    handleFormCollapse: function(){
        var $this = this;
        var openBar = false;
        var openCount = 0;
        $$('.form-collapse-table').each(function(bar){
            var section = $(bar.parentNode.parentNode);
            //section.setUnselectable();  //ntw - bug#209358  - If anyone knows why this line exists please tell me - prevents selection in firefox under collapses and I cannot see that it performs any other function
            if (section.className == "form-section-closed") {
                section.closed = true;
            } else {
                if (section.select('.form-collapse-hidden').length < 0) {
                    openBar = section;
                    openCount++;
                }
            }
            bar.observe('click', function(){
            
                if (section.closed) {
                
                    section.setStyle('overflow:visible; height:auto');
                    var h = section.getHeight();
                    
                    if (openBar && openBar != section && openCount <= 1) {
                        openBar.className = "form-section-closed";
                        openBar.shift({
                            height: 60,
                            duration: 0.5
                        });
                        openBar.select('.form-collapse-right-show').each(function(e){
                            e.addClassName('form-collapse-right-hide').removeClassName('form-collapse-right-show');
                        });
                        openBar.closed = true;
                    }
                    openBar = section;
                    section.setStyle('overflow:hidden; height:60px');
                    // Wait for focus
                    setTimeout(function(){
                        section.scrollTop = 0;
                        section.className = "form-section";
                    }, 1);
                    
                    section.shift({
                        height: h,
                        duration: 0.5,
                        onEnd: function(e){
                            e.scrollTop = 0;
                            e.setStyle("height:auto;");
                            if(!$this.noJump){
                                e.scrollIntoView();
                            }
                        }
                    });
                    section.select('.form-collapse-right-hide').each(function(e){
                        e.addClassName('form-collapse-right-show').removeClassName('form-collapse-right-hide');
                    });
                    section.closed = false;
                } else {
                
                    section.scrollTop = 0;
                    section.shift({
                        height: 60,
                        duration: 0.5,
                        onEnd: function(e){
                            e.className = "form-section-closed";
                        }
                    });
                    
                    //Emre: Added if because of preventing collapse open/close bug
                    if(openBar){
                        openBar.select('.form-collapse-right-show').each(function(e){
                            e.addClassName('form-collapse-right-hide').removeClassName('form-collapse-right-show');
                        });
                    }

                    section.closed = true;
                }
            });
        });
    },
    /**
     *  Handles Paypal Pro payment methods
     *  and field validations
     */
    handlePaypalPro: function(){
        if ($('creditCardTable')) {
            var thisForm = $$('.jotform-form')[0];
            var paymentFieldId = $$('input[name="simple_fpc"]')[0].value;
            Event.observe(thisForm, 'submit' , function (event) {
                if (JotForm.isPaymentSelected()) {
                    // default error
                    var errors = "";
                    JotForm.corrected($$('.paymentTypeRadios')[0]);
                    // if no payment method is selected
                    if (!$$('.paymentTypeRadios')[0].checked && !$$('.paymentTypeRadios')[1].checked) {
                        errors = "You must select a payment method";
                    }
                    // if payment method is credit card
                    if ($('input_' + paymentFieldId + '_paymentType_credit').checked) {
                        $$('#id_' + paymentFieldId + ' [class*="cc"]').each(function (cc){
                            if (!cc.getValue()) {
                                errors = "All fields are required";
                                throw $break;
                            }
                        });
                    }
                    // if there are errors
                    if (errors) {
                        JotForm.errored($$('.paymentTypeRadios')[0], errors);
                        Event.stop(event);
                    } else {
                        JotForm.corrected($$('.paymentTypeRadios')[0]);
                    }
                }
            });
            $$('.paymentTypeRadios').each(function(radio){
                radio.observe('click', function(){
                    if (radio.checked && radio.value === "express") {
                        $('creditCardTable').hide();
                    }
                    // If credit is selected and payment total is greater than zero or if there is no discount coupon
                    if (radio.checked && radio.value === "credit" && ( JotForm.paymentTotal > 0 || Object.keys(JotForm.discounts).length === 0 ) ) {
                        $('creditCardTable').show();
                    }
                    JotForm.corrected($$('.paymentTypeRadios')[0]);
                    // toggle checkout buttons
                    JotForm.togglePaypalButtons(radio.checked && radio.value === "express");
                });
            });
        }
    },
    
    /**
     * Creates description boxes next to input boxes
     * @param {Object} input
     * @param {Object} message
     */
    description: function(input, message){
        // v2 has bugs, v3 has stupid solutions
        if(message == "20"){ return; } // Don't remove this or some birthday pickers will start to show 20 as description
        
        var lineDescription = false;
        if(!$(input)){
            var id = input.replace(/[^\d]/gim, '');
            if($("id_"+id)){
                input = $("id_"+id);
                lineDescription = true;
            }else if($('section_'+id)){
                input = $('section_'+id);
                lineDescription = true;
            }else{
                return; /* no element found to display a description */             
            }
        }
        
        if($(input).setSliderValue){
            input = $($(input).parentNode);            
        }
        
        var cont = JotForm.getContainer(input);
        if(!cont){
            return;
        }
        var right = false;
        
        var bubble = new Element('div', { className: 'form-description'});
        var arrow = new Element('div', { className: 'form-description-arrow' });
        var arrowsmall = new Element('div', { className: 'form-description-arrow-small' });
        var content = new Element('div', { className: 'form-description-content' });
        var indicator;
        
        if("desc" in document.get && document.get.desc == 'v2'){
            right = true;
            cont.insert(indicator = new Element('div', {className:'form-description-indicator'}));
            bubble.addClassName('right');
        }
        
        content.insert(message);
        bubble.insert(arrow).insert(arrowsmall).insert(content).hide();
        
        cont.insert(bubble);
        
        if((cont.getWidth()/2) < bubble.getWidth()){
            bubble.setStyle('right: -' + ( cont.getWidth() - ( right ? 100 : 20 ) ) + 'px');
        }
        
        if(right){
            var h = indicator.measure('height');
            arrow.setStyle('top:'+((h /2) - 20)+'px');
            arrowsmall.setStyle('top:'+((h /2) - 17)+'px');
            
            $(cont).mouseEnter(function(){
                cont.setStyle('z-index:10000');
                if(!cont.hasClassName('form-line-active')){
                    cont.addClassName('form-line-active');
                    cont.__classAdded = true;
                }
                bubble.show();
            }, function(){
                if(cont.__classAdded){
                    cont.removeClassName('form-line-active');
                    cont.__classAdded = false;
                }
                cont.setStyle('z-index:0');
                bubble.hide();
            });
            $(input).observe('keydown', function(){
                cont.setStyle('z-index:0');
                bubble.hide();
            });
        }else{
            if(lineDescription){
                $(input).mouseEnter(function(){
                    cont.setStyle('z-index:10000');
                    bubble.show();
                }, function(){
                    cont.setStyle('z-index:0');
                    bubble.hide();
                });
            }else{
                $(cont).mouseEnter(function(){
                    cont.setStyle('z-index:10000');
                    bubble.show();
                }, function(){
                    cont.setStyle('z-index:0');
                    bubble.hide();
                });
                $(input).observe('keyup', function(){
                    cont.setStyle('z-index:0');
                    bubble.hide();
                });
                $(input).observe('focus', function(){
                    cont.setStyle('z-index:10000');
                    bubble.show();
                });
                $(input).observe('blur', function(){
                    cont.setStyle('z-index:0');
                    bubble.hide();
                });
            }
        }
    },
    
    /**
     * do all validations at once and stop on the first error
     * @param {Object} form
     * @param {string} scopeSelector, used for selector scopes on following selectors :
     *   form-textarea-limit-indicator-error and form-datetime-validation-error    
     */
    validateAll: function(form, scopeSelector){
        
        var _log = function(){
            if(window.location.href.indexOf('stripeDebug') !== -1){
                console.log.apply(console,arguments);
            }
        }

        if(getQuerystring('qp') !== "") {return true;}
        var ret = true;
        
        if(scopeSelector == undefined){
            scopeSelector = $$('body')[0];
        }

        if(scopeSelector.select('.form-textarea-limit-indicator-error')[0]){
            _log('set to false because .form-textarea-limit-indicator-error');
            ret = false;
        }

        if (scopeSelector.select('.form-datetime-validation-error').first()) {
            _log('set to false because .form-datetime-validation-error');
            ret = false;
        }
        
        if(window.signatureForm){
            _log('signature form');
            var pads = jQuery(".pad");

            for(var i=0; i<pads.length; i++){
                var pad = pads[i];
                if(jQuery(pad).attr("data-required")==="true"){
                    if(jQuery(pad).parent().parent().parent().is(":visible")){
                        var w = jQuery(pad).parent().parent()
                        if(jQuery(pad).jSignature('getData','base30')[1].length == 0){
                            ret = false;
                            if(w.find(".form-line-error").length==0){
                                w.append('<div class="form-line-error" style="float:left;">'+
                                    '<div class="form-error-message">'+
                                    '<img src="http://mustafa.jotform.pro/images/exclamation-octagon.png" align="left" style="margin-right:5px;">'+
                                    '<div class="form-error-arrow">'+
                                    '<div class="form-error-arrow-inner"></div>'+
                                    '</div>'+
                                    'This field is required</div></div>');
                            }
                        } else {
                          w.find(".form-line-error").remove();
                        }   
                    }             
                }
            }
        }

        if(window.JCFServerCommon !== undefined) {
            _log('widgets detected');
            var widgetInputs = $$('.widget-required');
            widgetInputs.each(function(el) {
                if(JotForm.isVisible(el)) {
                    if($(JotForm.currentSection) && $(JotForm.currentSection).select('.form-section').length > 0) {
                        if(el.up('.form-section').id === $(JotForm.currentSection).select('.form-section')[0].id){
                            if(el.value.length === 0) {
                                ret = false;
                            }
                        }
                    } else {
                        if(el.up('.form-section').visible()){
                            if(el.value.length === 0) {
                                ret = false;
                            }
                        }                    
                    }
                }
            });
        }

        var c = "";
        if(form && form.id){
            c = "#"+form.id+" ";
        }
        
        $$(c + '*[class*="validate"]').each(function(input){
            _log('looping inputs with validation :');
            _log(input);
            if(input.validateInput === undefined){_log('no required continuing'); return; /* continue; */ }
            if (!(!!input.validateInput && input.validateInput())) {
                ret = JotForm.hasHiddenValidationConflicts(input);
                _log('ret setted '+ret);
            }
        });
        _log('final ret value '+ret);
        return ret;
    },
    
    /**
     * When an input is errored
     * @param {Object} input
     * @param {Object} message
     */
    errored: function(input, message){
        
        input = $(input);
        
        if (input.errored) {
            return false;
        }
        
        if(input.runHint){
            input.runHint();
        }/*else{
            //input.select();
        }*/

        if(this.url.search("https") == -1){
          var preLink = "http://max.jotfor.ms/";
        }else{
          var preLink = "https://static-interlogyllc.netdna-ssl.com/";
          // var preLink = "https://www.jotform.com/";
        }
        
        if (JotForm.isCollapsed(input)) {

            var collapse = JotForm.getCollapseBar(input);
            if (!collapse.errored) {
                collapse.select(".form-collapse-mid")[0].insert({
                    top: '<img src="'+preLink+'images/exclamation-octagon.png" align="bottom" style="margin-right:5px;"> '
                }).setStyle({ color: 'red' });
                collapse.errored = true;
            }
        }
        var container = JotForm.getContainer(input);

        input.errored = true;
        input.addClassName('form-validation-error');
        container.addClassName('form-line-error');
        var insertEl = container;
        
        //if(JotForm.debug){
            insertEl = container.select('.form-input')[0];
            if (!insertEl) {
                insertEl = container.select('.form-input-wide')[0];
            }
            if(!insertEl){
                insertEl = container;
            }
        //}
        insertEl.select('.form-error-message').invoke('remove');

        insertEl.insert(new Element('div', {
            className: 'form-error-message'
        }).insert('<img src="'+preLink+'images/exclamation-octagon.png" align="left" style="margin-right:5px;"> ' + message).insert(
        new Element('div', {className:'form-error-arrow'}).insert(new Element('div', {className:'form-error-arrow-inner'}))));
        
        return false;
    },
    
    /**
     * When an input is corrected
     * @param {Object} input
     */
    corrected: function(input){
        JotForm.hideButtonMessage();
        input = $(input);
        input.errored = false;
        if (JotForm.isCollapsed(input)) {
            var collapse = JotForm.getCollapseBar(input);
            if (collapse.errored) {
                collapse.select(".form-collapse-mid")[0].setStyle({
                    color: ''
                }).select('img')[0].remove();
                collapse.errored = false;
            }
        }
        var container = JotForm.getContainer(input);
        if(!container){ return true; }
        container.select(".form-validation-error").invoke('removeClassName', 'form-validation-error');
        container.removeClassName('form-line-error');
        container.select('.form-error-message').invoke('remove');
        return true;
    },
    
    hideButtonMessage: function(){
        $$('.form-button-error').invoke('remove');
    },
    
    showButtonMessage: function(){
        this.hideButtonMessage();
        
        $$('.form-submit-button').each(function(button){
            var errorBox = new Element('div', {className:'form-button-error'});
            errorBox.insert('<p>' + JotForm.texts.generalError + '</p>');
            $(button.parentNode.parentNode).insert(errorBox);
        });
    },
    
    /**
     * Sets all validations to forms
     */
    validator: function(){
        
        if(this.debugOptions && this.debugOptions.stopValidations){
            this.info('Validations stopped by debug parameter');
            return true;
        }
        var $this = this;
        
        $A(JotForm.forms).each(function(form){ // for each JotForm form on the page 
            if (form.validationSet) {
                return; /* continue; */
            }
            
            form.validationSet = true;
            form.observe('submit', function(e){ // Set on submit validation
                try {
                    if($$('.form-submit-button') && $$('.form-submit-button').length > 0) {
                        //only submit form if a submit button is visible
                        var aSubmitIsVisible = false;
                        $$('.form-submit-button').each(function(el) {
                            if(JotForm.isVisible(el.parentNode)) {
                                aSubmitIsVisible = true;
                                return;
                            }
                        });
                        if(!aSubmitIsVisible) {
                            JotForm.enableButtons();
                            e.stop();
                        }
                    }

                    if (!JotForm.validateAll(form)) {
                        JotForm.enableButtons();
                        JotForm.showButtonMessage();
                        // scroll into view the latest visible submit button (b#434086)
                        var visSubmit = [];
                        $$('.form-submit-button').each(function(but){
                            if (JotForm.isVisible(but)) {
                                visSubmit.push(but);
                            };
                        });
                        if (visSubmit.length > 0) {
                            visSubmit[visSubmit.length-1].scrollIntoView();
                        }

                        e.stop();
                        return;
                    }

                    //if 'other' not checked disable corresponding textbox
                    $$('.form-radio-other,.form-checkbox-other').each(function(el) {
                        if(!el.checked && el.next()) {
                            el.next().disable();
                        }
                    });

                    $$('textarea.form-textarea:first-child').each(function(el) {
                        if(el.value) {
                            function escapeHtml(text) {
                              return text
                                  .replace(/&/g, "&amp;")
                                  .replace(/</g, "&lt;")
                                  .replace(/>/g, "&gt;")
                                  .replace(/"/g, "&quot;")
                                  .replace(/'/g, "&#039;");
                            }
                            el.value = escapeHtml(el.value);
                            textEl = new Element('div');
                            textEl.innerHTML = el.value;
                            el.up().appendChild(textEl);
                            el.hide();
                        }
                    });

                    JotForm.runAllCalculations(true);
                } catch (err) {
                    JotForm.error(err);
                    e.stop();
                    return;
                }

                //enable any disabled(readonly) time dropdowns so they are submitted with the form
                $$('.time-dropdown').each(function(el) { el.enable();});

                // We will clear the contents of hidden fields, users don't want see the hidden fields on subscriptions
                $$('.form-field-hidden input', '.form-field-hidden select', '.form-field-hidden textarea').each(function(input) {
                    if(input.name == "simple_fpc") { // do not clear this field's value
                        return;
                    }
                    if (input.tagName == 'INPUT' && ['checkbox', 'radio'].include(input.type)) {
                        input.checked = false;
                    } else {
                        input.clear();
                    }
                });

                if(JotForm.compact && JotForm.imageSaved == false){
                    e.stop();
                    window.parent.saveAsImage();
                    // JotForm.enableButtons();
                    $(document).observe('image:loaded', function(){
                        var block;
                        $(document.body).insert(block = new Element('div').setStyle('position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.85);'));
                        block.insert('<table height="100%" width="100%"><tr><td align="center" valign="middle" style="font-family:Verdana;color:#fff;font-size:16px;">Please Wait...</td></tr></table>');
                        setTimeout(function(){
                            form.submit();
                        }, 1000);
                    });
                    return;
                }

                //validation for grading when the form is submitted
                var grading_inputs = form.select('.form-grading-input');
                if( grading_inputs )
                {
                  grading_inputs.each(function(item){
                    //call the validator function to validate the data
                    var validate = item.validateGradingInputs();
                    if( !validate )
                    {
                      e.stop();//stop submitting the form
                    }
                  });
                }

                //validation fo spinners when the form is submitted
                var spinner_inputs = form.select('.form-spinner-input');
                if( spinner_inputs )
                {
                  spinner_inputs.each(function(item){
                    //call the validator function to validate the data
                    var validate = item.validateSpinnerInputs();
                    if( !validate )
                    {
                      e.stop();//stop submitting the form
                    }
                  });
                }

                //validation fo numbers when the form is submitted
                var number_inputs = form.select('.form-number-input');
                if( number_inputs )
                {
                  number_inputs.each(function(item){
                    //call the validator function to validate the data
                    var validate = item.validateNumberInputs();
                    if( !validate )
                    {
                      e.stop();//stop submitting the form
                    }
                  });
                }
            });
            
            // for each validation element
            $$('#'+form.id+' *[class*="validate"]').each(function(input){
                JotForm.setFieldValidation(input);
            });
            
            $$('.form-upload').each(function(upload){
               
                try {

                    var required = !!upload.validateInput;
                    var exVal = upload.validateInput || Prototype.K;
                    
                    upload.validateInput = function(){

                        //clean any errors first if any
                        upload.errored = false;

                        if (exVal() !== false) { // Make sure other validation completed
                            
                            if(!upload.files){ return true; } // If files are not provied then don't do checks
                            
                            var acceptString = upload.readAttribute('accept') || upload.readAttribute('file-accept') || "";
                            var maxsizeString = upload.readAttribute('maxsize') || upload.readAttribute('file-maxsize') || "";
                            
                            var accept = acceptString.strip().toLowerCase().split(/\s*\,\s*/gim);
                            var maxsize = parseInt(maxsizeString, 10) * 1024;
                            
                            var file = upload.files[0];
                            if (!file) {
                                return true;
                            } // No file was selected
                            
                            //Emre: to prevent extension of file problem in firefox7 (47183)
                            if(!file.fileName){ file.fileName = file.name; }
                
                            var ext = "";
                            if( JotForm.getFileExtension(file.fileName) ){
                                ext = JotForm.getFileExtension(file.fileName);
                            }
                            
                            if (!ext){
                                return JotForm.errored(upload, JotForm.texts.noUploadExtensions);
                            }

                            if ( acceptString != "*" && !accept.include(ext) && !accept.include(ext.toLowerCase())) {
                                return JotForm.errored(upload, JotForm.texts.uploadExtensions + '<br/>' + acceptString);
                            }

                            //check if validation if real image is set to yes
                            //if so check again if the meta data is correct and only if the extension is correct
                            var validateImage = upload.readAttribute('data-imagevalidate') || false;
                            var validatedImageExt = "jpeg, jpg, png, gif, bmp";
                            if((accept.include(ext) || accept.include(ext.toLowerCase()) ) && //for the accepted extensions
                                validateImage && ( validateImage === 'yes' || validateImage === 'true' ) &&
                                (validatedImageExt.include(ext) || validatedImageExt.include(ext.toLowerCase()) ) && //for the accepted valid images
                                typeof window.FileReader != 'undefined' //only for modern browsers that supports it
                            ){
                                //initiate the FileReader
                                var binary_reader = new FileReader();
                                binary_reader.onloadend = function(e) {
                                    function ab2str(buf) {
                                    var binaryString = '',
                                        bytes = new Uint8Array(buf),
                                        length = bytes.length;
                                    for (var i = 0; i < length; i++) {
                                        binaryString += String.fromCharCode(bytes[i]);
                                    }
                                    return binaryString;
                                    }
                                    var args = {
                                        filename: file.name,
                                        size: file.size,
                                        //convert string to binary
                                        binary: ab2str(e.target.result)
                                    };
                                    ImageInfo.loadInfo(args, function(){
                                        var info = ImageInfo.getAllFields(file.name);
                                        if( info.format === 'UNKNOWN' ){
                                            return JotForm.errored(upload, "You have uploaded an invalid image file type.");
                                        }
                                    });
                                }
                              //read file as buffer array (binaryString is deprecated)
                              binary_reader.readAsArrayBuffer(file);
                            }

                            //Emre: to prevent file.fileSize being undefined in Firefox 7 (48526)
                            //Emre: to prevent file upload not to work in Firefox 3.
                            if(!file.fileSize){ file.fileSize = file.size; }

                            if (file.fileSize > maxsize) {
                                return JotForm.errored(upload, JotForm.texts.uploadFilesize + ' ' + maxsizeString + 'Kb');
                            }
                            
                            return JotForm.corrected(upload);
                        }
                    };
                    
                    if (!required) {
                        upload.addClassName('validate[upload]');
                        upload.observe('blur', upload.validateInput);
                        }
                } catch (e) {

                    JotForm.error(e);

                }

            }); 
        });
    },


    /*
    * set validation function on field
    */
    setFieldValidation: function(input) {
        var $this = this;
        var reg = {
            email: /^\S[a-z0-9\/.!#$%&'*+\/=?\^_`{|}~\-]*(?:\.[a-z0-9!#$%&'*+\/=?\^_`{|}~\-]+)*@(?:[a-z0-9](?:[a-z0-9\-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9\-]*[a-z0-9])$/i,
            alphanumeric: /^[a-zA-ZæøåäöÆØÅÄÖ0-9\s]+$/,
            numeric: /^(-?\d+[\.]?)+$/,
            numericDotStart: /^([\.]\d+)+$/,  //accept numbers starting with dot
            currency: /^-?[\$\£]?\d*,?\d*(\.\d\d)?¥?$/, 
            alphabetic: /^[a-zA-ZæøåäöÆØÅÄÖ\s]+$/,
            url: /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?/
        };
        var validations = input.className.replace(/.*validate\[(.*)\].*/, '$1').split(/\s*,\s*/);
        
        input.validateInput = function(deep)
        {
            if (!JotForm.isVisible(input)) {
                return true; // if it's hidden then user cannot fill this field then don't validate
            }
            
            if(!$(input.parentNode).hasClassName('form-matrix-values') && !input.hasClassName('form-subproduct-option')) //ntw
                JotForm.corrected(input); // First clean the element
            
            var vals = validations;
            
            if(input.hinted === true){
                input.clearHint();
                setTimeout(function(){
                    input.hintClear();
                }, 150);
            } // Clear hint value if exists

            //change where it deploys
            //to first check the data  of this inputs before going to the next with a validate[*] class
            if( input.readAttribute('data-type') === 'input-spinner' && input.value )
            {
                return input.validateSpinnerInputs();
            }
            else if( input.readAttribute('data-type') === 'input-grading' && input.value )
            {
                return input.validateGradingInputs();
            }
            else if( input.readAttribute('data-type') === 'input-number' && input.value )
            {
                return input.validateNumberInputs();
            }

            if(input.up('.form-line').down('.form-textarea-limit-indicator-error')) {
                var span = input.up('.form-line').down('.form-textarea-limit-indicator span');
                var msg = span.readAttribute('type') === 'Words' ? JotForm.texts.wordLimitError : JotForm.texts.characterLimitError;
                return JotForm.errored(input, msg+" "+span.readAttribute('limit')+'.');
            }

            if(vals.include('disallowFree')) {
                var freeEmails = ['gmail','aim','outlook','hotmail', 'yahoo','mail','inbox'];
                for(var i=0; i<freeEmails.length; i++) {
                    if(input.value.indexOf("@" + freeEmails[i] + ".") > -1) {
                        return JotForm.errored(input, JotForm.texts.freeEmailError);
                    }
                }
            }

            if(vals.include('minSelection')) {
                var minSelection = parseInt(input.readAttribute('data-minSelection'));
                var numberChecked = 0;
                input.up('.form-line').select('input[type=checkbox]').each(function(check) {
                     if(check.checked) numberChecked++;
                });
                if(numberChecked > 0 && numberChecked < minSelection) {
                    return JotForm.errored(input, JotForm.texts.minSelectionsError + minSelection + '.');
                }
            }

            if(vals.include('maxSelection')) {
                var maxSelection = parseInt(input.readAttribute('data-maxSelection'));
                var numberChecked = 0;
                input.up('.form-line').select('input[type=checkbox]').each(function(check) {
                     if(check.checked) numberChecked++;
                });
                if(numberChecked > maxSelection) {
                    return JotForm.errored(input, JotForm.texts.maxSelectionsError + maxSelection + '.');
                }
            }

            if(vals.include('disallowPast')) {
                var id = input.id.split('_').last();
                var inputtedDate = JotForm.getDateValue(id).split('T')[0];
                var dat =  new Date();
                var month = (dat.getMonth()+1 < 10)? '0'+(dat.getMonth()+1):dat.getMonth()+1;
                var day = (dat.getDate() < 10) ? '0' + dat.getDate() : dat.getDate();
                var currentDate = dat.getFullYear() + "-" + month + "-" + day;

                if(JotForm.checkValueByOperator('before', JotForm.strToDate(currentDate), JotForm.strToDate(inputtedDate))) {
                    return JotForm.errored(input, JotForm.texts.pastDatesDisallowed);
                }
            }

            //Emre confirmation email (36639)
            if (vals.include("Email_Confirm")) {
                //console.log("if (vals.include(\"Email_Confirm\")) {");
                var idEmail = input.id.replace(/.*_(\d+)(?:_confirm)?/gim, '$1'); //confirm email id is like "input_4_confirm"
                if(($('input_' + idEmail).value != $('input_' + idEmail + '_confirm').value)){
                    return JotForm.errored(input, JotForm.texts.confirmEmail);
                } else if (($('input_' + idEmail + '_confirm').value) && (!reg.email.test($('input_' + idEmail + '_confirm').value))) {
                    return JotForm.errored(input, JotForm.texts.email);
                }
            }
            if (vals.include("required")) {
                if (input.tagName == 'INPUT' && input.readAttribute('type') == "file") { // Upload
                    if(input.value.empty() && !input.uploadMarked){
                        return JotForm.errored(input, JotForm.texts.required);
                    }else{
                        return JotForm.corrected(input);
                    }
                } else if (input.tagName == "INPUT" && (input.readAttribute('type') == "radio" || input.readAttribute('type') == "checkbox")) {

                    if($(input.parentNode).hasClassName('form-matrix-values')){ // This is in a matrix
                        
                        var ty = input.readAttribute('type');
                        var matrixRows = {};
                        var oneChecked = false;
                        var oneEmpty = false;
                        input.up('table').select('input').each(function(e){
                            if(!(e.name in matrixRows)){matrixRows[e.name] = false;}
                            if(matrixRows[e.name] !== true){matrixRows[e.name] = e.checked;}
                            if(matrixRows[e.name] === true){oneChecked = true;}
                            if('value' in e && e.value.strip(" ").empty()) {oneEmpty = true;}
                        });
                        if(vals.include("requireOneAnswer")) {
                          if(!oneChecked) 
                            return JotForm.errored(input, JotForm.texts.requireOne);
                        } else if(vals.include('requireEveryCell') && oneEmpty) {
                            return JotForm.errored(input, JotForm.texts.requireEveryCell);
                        } else if( ! $H(matrixRows).values().all()){
                            return JotForm.errored(input, JotForm.texts.requireEveryRow);
                        } else {
                            return JotForm.corrected(input);
                        }
                    
                    }else {
                        var baseInputName = input.name.substr(0,input.name.indexOf('['));
                        var otherInputName = baseInputName + '[other]';
                        var checkboxArray = [];
                            // If 'Other' input exists;
                            if (document.getElementsByName(otherInputName)[0]) {
                                // Assign all checkboxes including 'Other' to array
                                checkboxArray = $A(document.getElementsByName(baseInputName + '[]')); 
                                checkboxArray[checkboxArray.length] = document.getElementsByName(otherInputName)[0];
                                    // Validate each checkbox
                                if ( ! checkboxArray.map(function(e){ return e.checked; }).any()) {
                                        return JotForm.errored(input, JotForm.texts.required);
                                }
                            } else {
                                if ( ! $A(document.getElementsByName(input.name)).map(function(e){
                                    if (JotForm.isVisible(e)) {
                                        // if this is an sub product checkbox (expanded)
                                        if (e.readAttribute('type') === "checkbox" && e.value.indexOf('_expanded') > -1) {
                                            // if not selected
                                            if (!e.checked) {
                                                return false;
                                            } else {
                                                // check if any of the quantities are filled
                                                return $A($$('#' + e.id + '_subproducts .form-subproduct-quantity')).map(function(cb) { return cb.getSelected().value > 0 || cb.value > 0; }).any();
                                            }
                                        } else {
                                            return e.checked;
                                        }
                                    }
                                }).any()) {
                                    // for paypalpro payment type radio
                                    if (input.hasClassName('paymentTypeRadios')) {
                                        return JotForm.errored(input, "Please select payment method.");
                                    }
                                    return JotForm.errored(input, JotForm.texts.required);
                                }
                            }
                        
                    }
                } else if((input.tagName == "INPUT" || input.tagName == "SELECT") && $(input.parentNode).hasClassName('form-matrix-values')) {
                        var matrixRows = {};
                        var oneEntry = false;
                        var oneEmpty = false;

                        input.up('table').select(input.tagName).each(function(e){
                            if(!(e.name in matrixRows)){matrixRows[e.name] = false;}
                            if(matrixRows[e.name] !== true){matrixRows[e.name] = (e.value && !e.value.strip(" ").empty());}
                            if(matrixRows[e.name] === true){oneEntry = true;}
                            if('value' in e && e.value.strip(" ").empty()) {oneEmpty = true;}
                        });
                        if(vals.include("requireEveryRow") && ! $H(matrixRows).values().all()) {
                            return JotForm.errored(input, JotForm.texts.requireEveryRow);
                        } else if(vals.include("requireOneAnswer") && !oneEntry) {
                            return JotForm.errored(input, JotForm.texts.requireOne);
                        } else if(vals.include('requireEveryCell') && oneEmpty) {
                            return JotForm.errored(input, JotForm.texts.requireEveryCell);
                        } else {
                            return JotForm.corrected(input);
                        }
                } else if ((input.tagName === "INPUT" || input.tagName === "SELECT") && input.hasClassName('form-subproduct-option')) {
                    // if this is a subproduct quantity option 
                    if (input.hasClassName('form-subproduct-quantity')) {
                        var qID = input.id.replace(/_[0-9]*_[0-9]*$/, '');
                        // if the corresponding checkbox is  checked
                        if ($(qID.replace(/_quantity/, '')).checked) {
                            // if any of the quantities are greater than 0
                            if ($A($$('[id*="' + qID + '"]')).map(function(vl){
                                return (vl.getSelected().value > 0 || vl.value > 0);
                            }).any()) {
                                return JotForm.corrected(input); // corrected
                            } else {
                                return JotForm.errored(input, JotForm.texts.required); // errored
                            }
                        }
                    }
                } else if (input.name && input.name.include("[")) {
                    try{
                        var cont = $this.getContainer(input);
                        // Ozan, bugfix: 133419, both input and select fields should be selected
                        var checkValues = cont.select('input,select[name*=' + input.name.replace(/\[.*$/, '') + ']').map(function(e){
                            // If this is an address field and country is not United States or Canada 
                            // then don't require state name
                            if(e.hasClassName('form-address-state')){
                                var country = cont.select('.form-address-country')[0].value;
                                if(country != 'United States' && country != 'Canada' && country != 'Please Select'){
                                    e.removeClassName('form-validation-error');
                                    e.__skipField = true;
                                    return false;
                                }
                            }else{
                                if(e.__skipField){
                                    e.__skipField = false;
                                }
                            }
                            
                            // If this is a custom quantity textbox
                            if (e.id.match(/input_[0-9]_quantity_[0-9]+_[0-9]+/) && e.type == 'text') {
                                
                                var cb = $(((e.id.replace('_quantity', '')).match(/input_[0-9]_[0-9]+/))[0]);
                                var allProducts = $$('[id*="' + e.id.match(/input_[0-9]*/)[0] +  '"][type="' + cb.getAttribute('type') + '"]');
                                
                                if ((cb.checked && (isNaN(e.value) || e.value == 0 || e.value.empty())) // if a product is selected and qty is not valid
                                     || !allProducts.map(function(c) { return c.checked }).any() // if there are no products selected
                                ) {
                                    e.addClassName('form-validation-error');
                                    return true;
                                }
                            }
                            var innerVals = e.className.replace(/.*validate\[(.*)\].*/, '$1').split(/\s*,\s*/);
                            if(innerVals.include('required') && JotForm.isVisible(e)){
                                if(e.value.empty() || e.value.strip() == 'Please Select'){
                                    e.addClassName('form-validation-error');
                                    return true;
                                }
                            }
                            e.removeClassName('form-validation-error');
                            return false;
                        });
                        
                        if (checkValues.any()) {
                            return JotForm.errored(input, JotForm.texts.required);
                        }
                    }catch(e){
                        // This can throw errors on internet explorer
                        JotForm.error(e);
                        return JotForm.corrected(input);
                    }
                }
                if(input.__skipField){
                    return JotForm.corrected(input);
                }
                if(input.tagName.toLowerCase() === 'textarea' && input.hasClassName('form-custom-hint')) {
                    return JotForm.errored(input, JotForm.texts.required);
                }
                if(input.hasClassName("form-textarea") && input.up('div').down('.nicEdit-main')) { //rich text area
                    var val = input.up('div').down('.nicEdit-main').innerHTML.stripTags().replace(/\s/g, '').replace(/&nbsp;/g, '');
                    if(val.empty()) {
                        return JotForm.errored(input, JotForm.texts.required);
                    } 
                } else if ( (!input.value || input.value.strip(" ").empty() || input.value.replace('<br>', '').empty() || input.value == 'Please Select') && !(input.readAttribute('type') == "radio" || input.readAttribute('type') == "checkbox") && !$(input.parentNode).hasClassName('form-matrix-values')) {
                    return JotForm.errored(input, JotForm.texts.required);
                }

                vals = vals.without("required");
                
            } else if (input.value.empty()) {
                // if field is not required and there is no value 
                // then skip other validations
                return true;
            }
            
            if (!vals[0]) {
                return true;
            }

            switch (vals[0]) {
                case "Email":
                    if (!reg.email.test(input.value)) {
                        return JotForm.errored(input, JotForm.texts.email);
                    }
                    break;
                case "Alphabetic":
                    if (!reg.alphabetic.test(input.value)) {
                        return JotForm.errored(input, JotForm.texts.alphabetic);
                    }
                    break;
                case "Numeric":
                    if (!reg.numeric.test(input.value) && !reg.numericDotStart.test(input.value)) {
                        return JotForm.errored(input, JotForm.texts.numeric);
                    }
                    break;
                case "AlphaNumeric":
                    if (!reg.alphanumeric.test(input.value)) {
                        return JotForm.errored(input, JotForm.texts.alphanumeric);
                    }
                    break;
                case "Url":
                    if (!reg.url.test(input.value)) {
                        return JotForm.errored(input, JotForm.texts.url);
                    }
                    break;
                case "Currency": 
                    if(!reg.currency.test(input.value)) {
                        return JotForm.errored(input, JotForm.texts.currency);
                    }
                    break;
                case "Fill Mask":
                    if(input.readAttribute("masked") == "true" && !jQuery(input).inputmask("isComplete")) {
                        return JotForm.errored(input, JotForm.texts.fillMask);
                    }
                    break;

                default:
                    // throw ("This validation is not valid (" + vals[0] + ")");
            }
            return JotForm.corrected(input);
        };
        var validatorEvent = function(e){
            setTimeout(function(){ // to let focus event to work
                if($this.lastFocus && ($this.lastFocus == input || $this.getContainer($this.lastFocus) != $this.getContainer(input))){
                    input.validateInput();
                }else if(input.type == "hidden" || input.type == 'file'){
                    input.validateInput(); // always run on hidden/upload elements
                } 
            }, 10);
        };
        
        if(input.type == 'hidden' || input.type == 'file'){
            input.observe('change', validatorEvent);
        }else{
            input.observe('blur', validatorEvent);
        }
        if(input.type == 'checkbox' || input.type == 'radio'){
            input.observe('click', function() {
                input.validateInput();
            });
        }

        if(input.hasClassName("form-textarea") && input.up('div').down('.nicEdit-main')) { //rich text area
            input.up('div').down('.nicEdit-main').observe('blur', validatorEvent);
        }

        if(input.up('.form-spinner')) {
            var spinnerEvent = function() {input.validateInput();};
            input.up('.form-spinner').down('.form-spinner-up').observe('click', spinnerEvent);
            input.up('.form-spinner').down('.form-spinner-down').observe('click', spinnerEvent);                  
        }
    },


    /**
     * Initiate facebook login operations
     * Check if user is already loggedin
     * watch login events to automatically populate fields
     * disable submits until login is completed
     */
    FBInit: function(){
        // Disable the Submit's here, form will not submit until integration is completed
        JotForm.FBNoSubmit = true;
        // Check if user is logged-in or not
        FB.getLoginStatus(function(response) {
            //Emre: facebook changed "response" properties (57298)
            if (response.authResponse) { // user is already logged in
                JotForm.FBCollectInformation(response.authResponse.userID);
            } else {    // user is not logged in. "JotForm.FBCollectInformation" is binded to facebook login event.
                FB.Event.subscribe('auth.login', function(response) {
                    JotForm.FBCollectInformation(response.authResponse.userID);
                });
            }
        });
    },
    /**
     * Request the logged-in users information from Facebook and populate hidden fields
     * Enable submit buttons and remove description
     */
    FBCollectInformation: function(id){
        JotForm.FBNoSubmit = false; // Enable submit buttons
        
        // Seek through all hidden FB inputs on the form to collect Requested
        // User information fields. Merge all field data with fields ID so we can put the
        // Associated data into correct input.
        // f is for form field id in DOM, d is for facebook db column name.
        var fls = $$('.form-helper').collect(function(el){ 
            var f = "";
            var d = el.readAttribute('data-info').replace("user_", ""); // Remove user_ prefix because it's not in the
            // Some permission names are different than FB users table
            // So we have to fix them
            switch(d){
                case "location":
                    f = "current_location";
                break;
                case "can_be_anyvalue": // for demoing
                    f = "place correct one here";
                break;
                default:
                    f = d;
            }
            return [f, el.id];
        });
        // Convert fls array to key value pair for easier and faster matching
        var fields = {};
        $A(fls).each(function(p){ fields[p[0]] = p[1]; });
        
        try{
            var columns = $H(fields).keys().join(", ");
            var query = FB.Data.query('SELECT '+columns+' FROM user WHERE uid={0}', id);
            
            query.wait(function(rows) {
                var inp;
                // 0th row has the query result we'll loop through results
                // and place existing fields into correct inputs
                $H(rows[0]).each(function(pair){
                    if( ( inp = $(fields[pair.key]) ) ){
                        // Some values must be converted to string before putting into fields
                        switch(pair.key){
                            case "current_location":
                                inp.value = pair.value.name;
                            break;
                            case "website":
                                inp.value = pair.value.split(/\s+/).join(", ");
                            break;
                            default:
                                inp.value = pair.value;
                        }
                    }
                });
                
                JotForm.bringOldFBSubmissionBack(id);
                
                var hidden = new Element('input', {type:'hidden', name:'fb_user_id'}).setValue(id);
                var form = JotForm.getForm(inp);
                form.insert({top:hidden});
            });
        }catch(e){
            console.error(e);
        }
        
        // Hide label description and display Submit buttons
        // Because user has completed the FB login operation and we have collected the info
        $$('.fb-login-buttons').invoke('show');
        $$('.fb-login-label').invoke('hide');
    },
    
    bringOldFBSubmissionBack: function(id){
        
        var formIDField = $$('input[name="formID"]')[0];
        
        var a = new Ajax.Jsonp(JotForm.url+'server.php', {
            parameters: {
                action: 'bringOldFBSubmissionBack',
                formID: formIDField.value,
                fbid: id
            },
            evalJSON: 'force',
            onComplete: function(t){
                var res = t.responseJSON;
                if (res.success) {
                    JotForm.editMode(res, true, ['control_helper', 'control_fileupload']); // Don't reset fields
                }
            }
        });
    },

    /**
     *  Placeholder for a deleted function to prevent script errors
     *  on forms saved in the past
     */
    
    hideSubmissionEmptyFields: function(formID) {
        
    },
    
    setCustomHint: function( elem, value )
    {
      var element = $(elem) || null,
          new_value = value.replace(/<br>/gim, "\n") || "";//replace any br to \n

      //add a class to the control to denote that is using a custom hint
      //as well as write the custom hint into the data-hint attrib
      element.addClassName('custom-hint-group').writeAttribute('data-customhint', value).writeAttribute('customhinted', "true");

      //set that the control has no content
      //check if it has a content, especially default data
      element.hasContent = ( element.value && element.value.replace(/\n/gim, "<br>") != value ) ? true : false;

      //function to show the custom placeholder
      element.showCustomPlaceHolder = function()
      {
        if( !this.hasContent )
        {
          this.value = new_value;
          //exclude spellcheck onto the control
          this.writeAttribute("spellcheck", "false").addClassName('form-custom-hint');
        }
      };

      //function to hide the custom placeholder
      element.hideCustomPlaceHolder = function()
      {
        if( !this.hasContent )
        {
          this.value = "";
          //exclude spellcheck onto the control
          this.removeClassName('form-custom-hint').removeAttribute('spellcheck');
        }
      };

      //add events to the control
      element.observe('focus',function(e){
          this.hideCustomPlaceHolder();
      }).observe('blur', function(e){
          this.showCustomPlaceHolder();
      }).observe('keyup', function(e){
          //this will determine if the control has a value
          this.hasContent = ( this.value.length > 0 && this.value !== new_value) ? true : false;
      }).observe('paste', function(e) {
            $this = this;
            setTimeout(function() {
                $this.hasContent = ( $this.value.length > 0 && $this.value !== new_value) ? true : false;
            }, 2);
      });

      //catch the submission of a form, and remove all custom placeholder
      //since we are using the said trick, this needs to be done
      element.up('form.jotform-form').observe('submit',function(){
        this.select('.custom-hint-group').each(function(elem){
          elem.hideCustomPlaceHolder();
        });
      });

      //initiate the custom placeholders
      element.showCustomPlaceHolder();

    },

    /*
    ** Return true if field has any kind of content - user inputted or otherwise and does not have error
    */
    fieldHasContent: function(id) {
        
        if($('id_'+id).hasClassName('form-line-error')) return false;
        if($('id_'+id).select('.form-custom-hint').length > 0) return false;

        var type = JotForm.getInputType(id);
        switch(type){
            case "address":
            case "combined":
                return $$('#id_'+id+' input').collect(function(e){ return e.value; }).any();
            case "number":
                return $$('#id_'+id+' input').collect(function(e){ return e.value && e.value != 0; }).any();
            case "birthdate":
                return JotForm.getBirthDate(id);
            case "datetime":
                var date = JotForm.getDateValue(id); 
                return !(date == "T00:00" || date == '');
            case "time":
                return JotForm.get24HourTime(id);
            case "checkbox":
            case "radio":
                return $$('#id_'+id+' input').collect(function(e){ return e.checked; }).any();
            case "select":
                return $$('#id_'+id+' select').collect(function(e){ return e.value; }).any();
            case "grading":
                return $$('input[id^=input_' + id +'_]').collect(function(e){ return e.value; }).any();
            case "signature":
                return jQuery("#id_" + id).find(".pad").jSignature('getData','base30')[1].length > 0;
            case "slider":
                return $('input_'+id).value > 0;
            case "file":
                if($$('#id_'+id+' input')[0].readAttribute('multiple') === 'multiple') {
                    return $('id_'+id).select('.qq-upload-list li').length > 0;
                } else {
                    return $('input_'+id).value;
                }
                break;
            default:
                if($('input_'+id) && $('input_'+id).value) {
                    return $('input_'+id).value;
                } else {
                    return false;
                }

        }
    },

    /*
    ** Show progress bar on screen and set up listeners
    */
    setupProgressBar: function() {
        JotForm.progressBar = new ProgressBar("progressBar", {'height':'20px', 'width': '95%'});
        var countFields = ['select','radio','checkbox','file','combined','email','address','combined','datetime','time',
        'birthdate','number','radio','number','radio','autocomplete','radio','text','textarea','signature', 'div', 'slider'];
        var totalFields = 0;
        var completedFields = 0;

        var updateProgress = function() {
            completedFields = 0;
            $$('.form-line').each(function(el) {
                var id = el.id.split("_")[1];
                var type = JotForm.getInputType(id);
                if($A(countFields).include(type)) {
                    if(JotForm.fieldHasContent(id)) {
                        completedFields++;
                    }
                }
            });

            var percentage = parseInt(100/totalFields*completedFields);
            if(isNaN(percentage)) percentage = 0;
            JotForm.progressBar.setPercent(percentage);
            $('progressPercentage').update(percentage + '% ');
            $('progressCompleted').update(completedFields);
            if(percentage == 100) {
                $('progressSubmissionReminder').show();
            } else {
                $('progressSubmissionReminder').hide();
            }
        };

        var setListener = function(el, ev) {
            $(el).observe(ev, function() {
                updateProgress();
            });
        };        

        $$('.form-line').each(function(el) {
            var id = el.id.split("_")[1];
            var type = JotForm.getInputType(id);
            if(!countFields.include(type)) {
                return;
            }

            totalFields++;
            switch (type) {
                case 'radio':
                case 'checkbox':
                    setListener($('id_' + id), 'click');
                    break;
                
                case 'select':
                case 'file':
                    setListener($('id_' + id), 'change');
                    break;
                
                case 'datetime':
                    setListener($('id_' + id), 'date:changed');
                    $$("#id_" + id + ' select').each(function(el) {
                        setListener($(el), 'change');
                    });
                    break;
                
                case 'time':
                case 'birthdate':
                    $$("#id_" + id + ' select').each(function(el) {
                        setListener($(el), 'change');
                    });                        
                    break;

                case 'address':
                    setListener($('id_' + id), 'keyup');
                    break;

                case 'number':
                    setListener($('id_' + id), 'keyup');
                    setListener($('id_' + id), 'click');
                    break;

                case 'signature':
                    setListener($('id_' + id), 'click');
                    break;

                default:
                    setListener($('id_' + id), 'keyup');
                    break;
            }
        });
        $('progressTotal').update(totalFields);

        updateProgress();
    },

    updateAreaFromRich: function(id) {
        try {
            var rich = $('id_'+id).down('.nicEdit-main');
            var txtarea = $('id_'+id).down('textarea');
            if(rich && txtarea) {
                rich.observe('keyup', function(){
                    txtarea.value = rich.innerHTML;
                    if(txtarea.triggerEvent) txtarea.triggerEvent('keyup');
                });
            }
        }catch(e){
            console.error(e);
        }
    },


    /**
     * Responsible on handling AutoFill feature,
     * this will also help to ensure that it will not conflict
     * on customHint trick if any
     */
    autoFillInitialize: function( params )
    {
      //initialize autoFill plugin for jquery
      var formID = $$('input[name="formID"]')[0].value;
      params.name = 'form_' + formID;
      var _form = 'form#' + formID;
      var form   = $$(_form)[0];

      //write an attribute to the form denoting that it uses a autoFill
      form.writeAttribute('data-autofill', 'true');

      /**
       * Will handle conflicts of the autoFill
       * especially custom hints, grading total computation
       */
      var _conflicts = {
        _handleCustomHint: function( data )
        {
          //get the data that was generated in the autoFill plugin
          var pfields = data.protectedfields;
          var pfieldsdata = data.protectedfieldsdata;
          var inc = 0;

          //loop through the stored data
          $H( pfieldsdata ).each(function(_fielddata){

            var _field = pfields[inc];
            var field = $(_field);
            var fieldata = _fielddata[1];

            //get the value on where the data is restored
            var value = ( fieldata.newinputvalue ) ? fieldata.newinputvalue.replace(/\n/gim, "<br>") : false;

            if( field.hasAttribute('data-customhint') || field.hasAttribute('customhinted') )
            {
              //get the value of the element
              var hint = field.readAttribute('data-customhint');

              // alert('customhinted:' + hint " | " + value);
              if( hint && value && hint != value ) {
                field.removeClassName('form-custom-hint');
                field.hasContent = true;
              }
            }
            else if( field.hasAttribute('hinted') || field.hinted ) //this is for IE relateds
            {
              //get the old input value and compare it to the newvalue of the input
              //if not match turn the color of the hint to black
              //seems to be a bug when using the .hint() function in IE
              var hint = ( fieldata.oldinputvalue ) ? fieldata.oldinputvalue.replace(/\n/gim, "<br>") : false;

              // alert('hinted:' + hint " | " + value);
              if( hint && value && hint != value ) {
                field.setStyle({color: "#000"});
              }
            }

            inc++;
          });
        },
        /**
        * Will handle the total of grading inputs if set
        */
        _handleGradingTotal: function( data )
        {
          if( $$('.form-grading-input').length > 0 && $("grade_total_" + id))
          {
            var total = 0, id = null;
            $$('.form-grading-input').each(function(input){
              id = input.id.replace(/input_(\d+)_\d+/, "$1"),
              total += parseFloat(input.value) || 0;
            });

            $("grade_point_" + id).innerHTML = total;
          }
        },
        /*
        * Move text from textfield to rich text div
        */
        _handleRichText: function(data) {
            $$('.nicEdit-main').each(function(richArea) {
                var txtarea = richArea.up('.form-line').down('textarea');
                if(txtarea) {
                    richArea.innerHTML = txtarea.value;
                }
            });
        }
      };

      //initiate jquery autoFill
      jQuery( _form ).autoFill({
        timeout: ( Number(params.timeout) > 0 ) ? params.timeout : 4,
        excludeFields: ["formID", "simple_spc", "temp_upload_folder"],
        ttl: params.ttl,
        allowBindOnChange: (params.bindChange && params.bindChange == 'on') ? true : false,
        onBeforeSave: function() {},
        onSave: function() {},
        onRelease: function() {},
        onBeforeRestore: function() {},
        onRestore: function(data)
        {
          //check for custom hints
          var restoredDatas = this.restoredData[0];
          // console.log( restoredDatas );
          if( restoredDatas )
          {
            //resolve conflicts in customHint if any
            _conflicts._handleCustomHint( restoredDatas );

            //resolve grading total computation if any
            _conflicts._handleGradingTotal( restoredDatas );

            _conflicts._handleRichText( restoredDatas );
          }
        }
      });

      this.autoFillDeployed = true;

      this.runAllConditions();

    },

    runAllConditions: function() {
        $H(JotForm.fieldConditions).each(function(pair){
            var field = pair.key;
            var event = pair.value.event;
            if(!$(field)){ return; }
            $(field).run(event);
        });
    },

    /**
     * Set masking for an specific question question
     * supports input type='text' only
     */
    setQuestionMasking: function( toSelector, type, maskValue, unmask )
    {

      var unmask = ( unmask ) ? unmask : false
        , extendedMask = {};

      //extend the definitions to accept other characters
      extendedMask['#'] = {
        validator: "[0-9]",
        cardinality: 1
      };

      //include more mask options for specific questions
      if ( type === "textMasking" )
      {
        extendedMask['@'] = {
          validator: "[A-Za-z\u0410-\u044F\u0401\u0451]",
          cardinality: 1
        };
      }

      jQuery.extend(jQuery.inputmask.defaults.definitions, extendedMask);

      //initiate masking for phones.
      if( unmask )
      {
        jQuery( toSelector ).inputmask('remove');
      }
      else
      {
        jQuery( toSelector ).inputmask( maskValue, { "placeholder": "_" } );
      }
    },

    /**
     * Helper that will handle input masking
     * this depends on the users masking format
     */
    setInputTextMasking: function( elem, maskValue, unmask )
    {
        setTimeout(function() { //wait for prepopulations to be run before setting the mask
            JotForm.setQuestionMasking( "#" + elem, 'textMasking', maskValue, unmask );
        }, 10);
    },

    /**
     * Will handle the Phone Validation
     * this depends on the users masking format
     */
    setPhoneMaskingValidator: function( elem, maskValue, unmask )
    {
        setTimeout(function() { //wait for prepopulations to be run before setting the mask
            JotForm.setQuestionMasking( "#" + elem, 'phoneMasking', maskValue, unmask );
        }, 10);
    },

    /**
     * will load external script file
     * currently it is used to import editMode function
     */
    loadScript: function() {

        var toLoad = arguments.length;
        var callback;
        var hasCallback = arguments[toLoad - 1] instanceof Function;
        var script;
        function onloaded() {
            toLoad --;
            if (!toLoad) {
                callback();
            }
        }
        if (hasCallback) {
            toLoad --;
            callback = arguments[arguments.length - 1];
        } else {
            callback = function() {}; // noop
        }
        for (var i = 0; i < toLoad; i ++) {
            script = document.createElement('script');
            script.src = arguments[i];
            //script.onload = script.onerror = onloaded; //hidden field (uploadedBefore) loading twice #417671

            if(typeof(script.addEventListener) != 'undefined'){
                script.addEventListener('load', callback, false);
            }else{
                //for IE8
                var handleScriptStateChangeIE8 = function(){
                    if(script.readyState == 'loaded'){
                        callback();
                    }
                }
                script.attachEvent('onreadystatechange',handleScriptStateChangeIE8);
            }

            (
                document.head ||
                document.getElementsByTagName('head')[0]
            ).appendChild(script);
        }
    }  
};
function getQuerystring(key, default_){
  if (default_==null) default_=""; 
  key = key.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regex = new RegExp("[\\?&]"+key+"=([^&#]*)");
  var qs = regex.exec(window.location.href);
  if(qs == null)
    return default_;
  else
    return qs[1];
}
// We have to put this event because it's the only way to catch FB load
window.fbAsyncInit = JotForm.FBInit.bind(JotForm);