// "prop" method fix for previous versions of jQuery var originalPropMethod = jQuery.fn.prop; jQuery.fn.prop = function() { if(typeof originalPropMethod == 'undefined') { return jQuery.fn.attr.apply(this, arguments); } else { return originalPropMethod.apply(this, arguments); } } //Formatting free form currency fields to currency jQuery(document).ready(function(){ jQuery(".ginput_amount, .ginput_donation_amount").bind("change", function(){ gformFormatPricingField(this); }); jQuery(".ginput_amount, .ginput_donation_amount").each(function(){ gformFormatPricingField(this); }); }); //------------------------------------------------ //---------- CURRENCY ---------------------------- //------------------------------------------------ function Currency(currency){ this.currency = currency; this.toNumber = function(text){ if(this.isNumeric(text)) return parseFloat(text); return gformCleanNumber(text, this.currency["symbol_right"], this.currency["symbol_left"], this.currency["decimal_separator"]); }; this.toMoney = function(number){ if(!this.isNumeric(number)) number = this.toNumber(number); if(number === false) return ""; number = number + ""; negative = ""; if(number[0] == "-"){ negative = "-"; number = parseFloat(number.substr(1)); } money = this.numberFormat(number, this.currency["decimals"], this.currency["decimal_separator"], this.currency["thousand_separator"]); var symbol_left = this.currency["symbol_left"] ? this.currency["symbol_left"] + this.currency["symbol_padding"] : ""; var symbol_right = this.currency["symbol_right"] ? this.currency["symbol_padding"] + this.currency["symbol_right"] : ""; money = negative + this.htmlDecode(symbol_left) + money + this.htmlDecode(symbol_right); return money; }; this.numberFormat = function(number, decimals, dec_point, thousands_sep, padded){ var padded = typeof padded == 'undefined'; number = (number+'').replace(',', '').replace(' ', ''); var n = !isFinite(+number) ? 0 : +number, prec = !isFinite(+decimals) ? 0 : Math.abs(decimals), sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep, dec = (typeof dec_point === 'undefined') ? '.' : dec_point, s = '', toFixedFix = function (n, prec) { var k = Math.pow(10, prec); return '' + Math.round(n * k) / k; }; if(decimals == '0') { s = ('' + Math.round(n)).split('.'); } else if(decimals == -1) { s = ('' + n).split('.'); } else { // Fix for IE parseFloat(0.55).toFixed(0) = 0; s = toFixedFix(n, prec).split('.'); } if (s[0].length > 3) { s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep); } if(padded) { if ((s[1] || '').length < prec) { s[1] = s[1] || ''; s[1] += new Array(prec - s[1].length + 1).join('0'); } } return s.join(dec); } this.isNumeric = function(number){ return gformIsNumber(number); }; this.htmlDecode = function(text) { var c,m,d = text; // look for numerical entities " var arr=d.match(/&#[0-9]{1,5};/g); // if no matches found in string then skip if(arr!=null){ for(var x=0;x= -32768 && c <= 65535){ // decode every single match within string d = d.replace(m, String.fromCharCode(c)); }else{ d = d.replace(m, ""); //invalid so replace with nada } } } return d; }; } function gformCleanNumber(text, symbol_right, symbol_left, decimal_separator){ //converting to a string if a number as passed text = text + " "; //Removing symbol in unicode format (i.e. ᅜ) text = text.replace(/&.*?;/, "", text); //Removing symbol from text text = text.replace(symbol_right, ""); text = text.replace(symbol_left, ""); //Removing all non-numeric characters var clean_number = ""; var is_negative = false; for(var i=0; i= 0 && parseInt(digit) <= 9) || digit == decimal_separator ) clean_number += digit; else if(digit == '-') is_negative = true; } //Removing thousand separators but keeping decimal point var float_number = ""; for(var i=0; i= '0' && char <= '9') float_number += char; else if(char == decimal_separator){ float_number += "."; } } if(is_negative) float_number = "-" + float_number; return gformIsNumber(float_number) ? parseFloat(float_number) : false; } function gformIsNumber(n) { return !isNaN(parseFloat(n)) && isFinite(n); } function gformIsNumeric(value, number_format){ switch(number_format){ case "decimal_dot" : var r = new RegExp("^(-?[0-9]{1,3}(?:,?[0-9]{3})*(?:\.[0-9]+)?)$"); return r.test(value); break; case "decimal_comma" : var r = new RegExp("^(-?[0-9]{1,3}(?:\.?[0-9]{3})*(?:,[0-9]+)?)$"); return r.test(value); break; } return false; } //------------------------------------------------ //---------- MULTI-PAGE -------------------------- //------------------------------------------------ function gformDeleteUploadedFile(formId, fieldId){ var parent = jQuery("#field_" + formId + "_" + fieldId); //hiding preview parent.find(".ginput_preview").hide(); //displaying file upload field parent.find("input[type=\"file\"]").removeClass("gform_hidden"); //displaying post image label parent.find(".ginput_post_image_file").show(); //clearing post image meta fields parent.find("input[type=\"text\"]").val(''); //removing file from uploaded meta var files = jQuery.secureEvalJSON(jQuery('#gform_uploaded_files_' + formId).val()); if(files){ files["input_" + fieldId] = null; jQuery('#gform_uploaded_files_' + formId).val(jQuery.toJSON(files)); } } //------------------------------------------------ //---------- PRICE ------------------------------- //------------------------------------------------ var _gformPriceFields = new Array(); var _anyProductSelected; function gformIsHidden(element){ return element.parents('.gfield').not(".gfield_hidden_product").css("display") == "none"; } function gformCalculateTotalPrice(formId){ if(!_gformPriceFields[formId]) return; var price = 0; _anyProductSelected = false; //Will be used by gformCalculateProductPrice(). for(var i=0; i<_gformPriceFields[formId].length; i++){ price += gformCalculateProductPrice(formId, _gformPriceFields[formId][i]); } //add shipping price if a product has been selected if(_anyProductSelected){ //shipping price var shipping = gformGetShippingPrice(formId) price += shipping; } //gform_product_total filter. Allows uers to perform custom price calculation if(window["gform_product_total"]) price = window["gform_product_total"](formId, price); //updating total var totalElement = jQuery(".ginput_total_" + formId); if(totalElement.length > 0){ totalElement.next().val(price); totalElement.html(gformFormatMoney(price)); } } function gformGetShippingPrice(formId){ var shippingField = jQuery(".gfield_shipping_" + formId + " input[type=\"hidden\"], .gfield_shipping_" + formId + " select, .gfield_shipping_" + formId + " input:checked"); var shipping = 0; if(shippingField.length == 1 && !gformIsHidden(shippingField)){ if(shippingField.attr("type") && shippingField.attr("type").toLowerCase() == "hidden") shipping = shippingField.val(); else shipping = gformGetPrice(shippingField.val()); } return gformToNumber(shipping); } function gformGetFieldId(element){ var id = jQuery(element).attr("id"); var pieces = id.split("_"); if(pieces.length <=0) return 0; var fieldId = pieces[pieces.length-1]; return fieldId; } function gformCalculateProductPrice(formId, productFieldId){ var price = gformGetBasePrice(formId, productFieldId); var suffix = "_" + formId + "_" + productFieldId; //Drop down auto-calculating labels jQuery(".gfield_option" + suffix + ", .gfield_shipping_" + formId).find("select").each(function(){ var selected_price = gformGetPrice(jQuery(this).val()); var fieldId = gformGetFieldId(this); jQuery(this).children("option").each(function(){ var label = gformGetOptionLabel(this, jQuery(this).val(), selected_price, formId, fieldId); jQuery(this).html(label); }); }); //Checkboxes labels with prices jQuery(".gfield_option" + suffix).find(".gfield_checkbox").find("input").each(function(){ var fieldId = gformGetFieldId(jQuery(this).parents(".gfield_checkbox")); var element = jQuery(this).next(); var label = gformGetOptionLabel(element, jQuery(this).val(), 0, formId, fieldId); element.html(label); }); //Radio button auto-calculating lables jQuery(".gfield_option" + suffix + ", .gfield_shipping_" + formId).find(".gfield_radio").each(function(){ var selected_price = 0; var selected_value = jQuery(this).find("input:checked").val(); var fieldId = gformGetFieldId(this); if(selected_value) selected_price = gformGetPrice(selected_value); jQuery(this).find("input").each(function(){ var label_element = jQuery(this).next(); var label = gformGetOptionLabel(label_element, jQuery(this).val(), selected_price, formId, fieldId); label_element.html(label); }); }); jQuery(".gfield_option" + suffix).find("input:checked, select").each(function(){ if(!gformIsHidden(jQuery(this))) price += gformGetPrice(jQuery(this).val()); }); var quantity; var quantityInput = jQuery("#ginput_quantity_" + formId + "_" + productFieldId); if(quantityInput.length > 0){ quantity = !gformIsNumber(quantityInput.val()) ? 0 : quantityInput.val(); } else{ quantityElement = jQuery(".gfield_quantity_" + formId + "_" + productFieldId); quantity = 1; if(quantityElement.find("input").length > 0) quantity = quantityElement.find("input").val(); else if (quantityElement.find("select").length > 0) quantity = quantityElement.find("select").val(); if(!gformIsNumber(quantity)) quantity = 0; } quantity = parseFloat(quantity); //setting global variable if quantity is more than 0 (a product was selected). Will be used when calculating total if(quantity > 0) _anyProductSelected = true; price = price * quantity; price = Math.round(price * 100) / 100; return price; } function gformGetBasePrice(formId, productFieldId){ var suffix = "_" + formId + "_" + productFieldId; var price = 0; var productField = jQuery("#ginput_base_price" + suffix+ ", .gfield_donation" + suffix + " input[type=\"text\"], .gfield_product" + suffix + " .ginput_amount"); if(productField.length > 0){ price = productField.val(); //If field is hidden by conditional logic, don't count it for the total if(gformIsHidden(productField)){ price = 0; } } else { productField = jQuery(".gfield_product" + suffix + " select, .gfield_product" + suffix + " input:checked, .gfield_donation" + suffix + " select, .gfield_donation" + suffix + " input:checked"); var val = productField.val(); if(val){ val = val.split("|"); price = val.length > 1 ? val[1] : 0; } //If field is hidden by conditional logic, don't count it for the total if(gformIsHidden(productField)) price = 0; } var c = new Currency(gf_global.gf_currency_config); price = c.toNumber(price); return price === false ? 0 : price; } function gformFormatMoney(text){ if(!gf_global.gf_currency_config) return text; var currency = new Currency(gf_global.gf_currency_config); return currency.toMoney(text); } function gformFormatPricingField(element){ if(gf_global.gf_currency_config){ var currency = new Currency(gf_global.gf_currency_config); var price = currency.toMoney(jQuery(element).val()); jQuery(element).val(price); } } function gformToNumber(text){ var currency = new Currency(gf_global.gf_currency_config); return currency.toNumber(text); } function gformGetPriceDifference(currentPrice, newPrice){ //getting price difference var diff = parseFloat(newPrice) - parseFloat(currentPrice); price = gformFormatMoney(diff); if(diff > 0) price = "+" + price; return price; } function gformGetOptionLabel(element, selected_value, current_price, form_id, field_id){ element = jQuery(element); var price = gformGetPrice(selected_value); var current_diff = element.attr('price'); var original_label = element.html().replace(//i, "").replace(current_diff, ""); var diff = gformGetPriceDifference(current_price, price); diff = gformToNumber(diff) == 0 ? "" : " " + diff; element.attr('price', diff); //don't add for drop down items (not supported) var price_label = element[0].tagName.toLowerCase() == "option" ? " " + diff : "" + diff + ""; var label = original_label + price_label; //calling hook to allow for custom option formatting if(window["gform_format_option_label"]) label = gform_format_option_label(label, original_label, price_label, current_price, price, form_id, field_id); return label; } function gformGetProductIds(parent_class, element){ var classes = jQuery(element).hasClass(parent_class) ? jQuery(element).attr("class").split(" ") : jQuery(element).parents("." + parent_class).attr("class").split(" "); for(var i=0; i 1 && currency.toNumber(val[1]) !== false) return currency.toNumber(val[1]); return 0; } function gformRegisterPriceField(item){ if(!_gformPriceFields[item.formId]) _gformPriceFields[item.formId] = new Array(); //ignore price fields that have already been registered for(var i=0; i<_gformPriceFields[item.formId].length; i++) if(_gformPriceFields[item.formId][i] == item.productFieldId) return; //registering new price field _gformPriceFields[item.formId].push(item.productFieldId); } function gformInitPriceFields(){ jQuery(".gfield_price").each(function(){ var productIds = gformGetProductIds("gfield_price", this); gformRegisterPriceField(productIds); jQuery(this).find("input[type=\"text\"], input[type=\"number\"], select").change(function(){ var productIds = gformGetProductIds("gfield_price", this); if(productIds.formId == 0) productIds = gformGetProductIds("gfield_shipping", this); gformCalculateTotalPrice(productIds.formId); }); jQuery(this).find("input[type=\"radio\"], input[type=\"checkbox\"]").click(function(){ var productIds = gformGetProductIds("gfield_price", this); if(productIds.formId == 0) productIds = gformGetProductIds("gfield_shipping", this); gformCalculateTotalPrice(productIds.formId); }); }); for(formId in _gformPriceFields) gformCalculateTotalPrice(formId); } //------------------------------------------- //---------- PASSWORD ----------------------- //------------------------------------------- function gformShowPasswordStrength(fieldId){ var password = jQuery("#" + fieldId).val(); var confirm = jQuery("#" + fieldId + "_2").val(); var result = gformPasswordStrength(password, confirm); var text = window['gf_text']["password_" + result]; jQuery("#" + fieldId + "_strength").val(result); jQuery("#" + fieldId + "_strength_indicator").removeClass("blank mismatch short good bad strong").addClass(result).html(text); } // Password strength meter function gformPasswordStrength(password1, password2) { var shortPass = 1, badPass = 2, goodPass = 3, strongPass = 4, mismatch = 5, symbolSize = 0, natLog, score; if(password1.length <=0) return "blank"; // password 1 != password 2 if ( (password1 != password2) && password2.length > 0) return "mismatch"; //password < 4 if ( password1.length < 4 ) return "short"; if ( password1.match(/[0-9]/) ) symbolSize +=10; if ( password1.match(/[a-z]/) ) symbolSize +=26; if ( password1.match(/[A-Z]/) ) symbolSize +=26; if ( password1.match(/[^a-zA-Z0-9]/) ) symbolSize +=31; natLog = Math.log( Math.pow(symbolSize, password1.length) ); score = natLog / Math.LN2; if (score < 40 ) return "bad"; if (score < 56 ) return "good"; return "strong"; } //---------------------------- //------ LIST FIELD ---------- //---------------------------- var gfield_original_title = ""; function gformAddListItem(element, max){ if(jQuery(element).hasClass("gfield_icon_disabled")) return; var tr = jQuery(element).parent().parent(); var clone = tr.clone(); clone.find("input, select").val("").attr("tabindex", clone.find('input:last').attr("tabindex")); tr.after(clone); gformToggleIcons(tr.parent(), max); gformAdjustClasses(tr.parent()); } function gformDeleteListItem(element, max){ var tr = jQuery(element).parent().parent(); var parent = tr.parent(); tr.remove(); gformToggleIcons(parent, max); gformAdjustClasses(parent); } function gformAdjustClasses(table){ var rows = table.children(); for(var i=0; i 0 && rowCount >= max){ gfield_original_title = table.find(".add_list_item:first").attr("title"); table.find(".add_list_item").addClass("gfield_icon_disabled").attr("title", ""); } else{ var addIcons = table.find(".add_list_item"); addIcons.removeClass("gfield_icon_disabled"); if(gfield_original_title) addIcons.attr("title", gfield_original_title); } } function gformMatchCard(id) { var cardType = gformFindCardType(jQuery('#' + id).val()); var cardContainer = jQuery('#' + id).parents('.gfield').find('.gform_card_icon_container'); if(!cardType) { jQuery(cardContainer).find('.gform_card_icon').removeClass('gform_card_icon_selected gform_card_icon_inactive'); } else { jQuery(cardContainer).find('.gform_card_icon').removeClass('gform_card_icon_selected').addClass('gform_card_icon_inactive'); jQuery(cardContainer).find('.gform_card_icon_' + cardType).removeClass('gform_card_icon_inactive').addClass('gform_card_icon_selected'); } } function gformFindCardType(value) { if(value.length < 4) return false; var rules = window['gf_cc_rules']; var validCardTypes = new Array(); for(type in rules) { for(i in rules[type]) { if(rules[type][i].indexOf(value.substring(0, rules[type][i].length)) === 0) { validCardTypes[validCardTypes.length] = type; break; } } } return validCardTypes.length == 1 ? validCardTypes[0].toLowerCase() : false; } //---------------------------------------- //------ CHOSEN DROP DOWN FIELD ---------- //---------------------------------------- function gformInitChosenFields(fieldList, noResultsText){ return jQuery(fieldList).each(function(){ var element = jQuery(this); //only initialize once if(element.is(":visible") && element.siblings(".chzn-container").length == 0){ jQuery(this).chosen({no_results_text: noResultsText}); } }); } //---------------------------------------- //------ CALCULATION FUNCTIONS ----------- //---------------------------------------- var GFCalc = function(formId, formulaFields){ this.patt = /{[^{]*?:(\d+(\.\d+)?)(:(.*?))?}/i; this.exprPatt = /^[0-9 -/*\(\)]+$/i; this.isCalculating = {}; this.init = function(formId, formulaFields) { var calc = this; jQuery(document).bind("gform_post_conditional_logic", function(){ for(var i in formulaFields) { var formulaField = jQuery.extend({}, formulaFields[i]); calc.runCalc(formulaField, formId); } }); for(var i in formulaFields) { var formulaField = jQuery.extend({}, formulaFields[i]); this.runCalc(formulaField, formId); this.bindCalcEvents(formulaField, formId); } } this.runCalc = function(formulaField, formId) { var calcObj = this; var formulaInput, expr; var field = jQuery('#field_' + formId + '_' + formulaField.field_id); formulaInput = jQuery('#input_' + formId + '_' + formulaField.field_id); var previous_val = formulaInput.val(); expr = calcObj.replaceFieldTags(formId, formulaField.formula, formulaField.numberFormat); result = ''; if(calcObj.exprPatt.test(expr)) { try { //run calculation result = eval(expr); } catch (e) {} } // allow users to modify result with their own function if(window["gform_calculation_result"]) result = window["gform_calculation_result"](result, formulaField, formId); //formatting number if(field.hasClass('gfield_price')) { result = gformFormatMoney(result ? result : 0); } else{ var decimalSeparator, thousandSeparator; if(formulaField.numberFormat == "decimal_comma"){ decimalSeparator = ","; thousandSeparator = "."; } else if(formulaField.numberFormat == "decimal_dot"){ decimalSeparator = "."; thousandSeparator = ","; } result = gformFormatNumber(result, !gformIsNumber(formulaField.rounding) ? -1 : formulaField.rounding, decimalSeparator, thousandSeparator); } //If value doesn't change, abort. //This is needed to prevent an infinite loop condition with conditional logic if(result == previous_val) return; // if this is a calucation product, handle differently if(field.hasClass('gfield_price')) { formulaInput.text(result); jQuery('#ginput_base_price_' + formId + '_' + formulaField.field_id).val(result).trigger('change'); gformCalculateTotalPrice(formId); } else { formulaInput.val(result).trigger('change'); } } this.bindCalcEvents = function(formulaField, formId) { var calcObj = this; var formulaFieldId = formulaField.field_id; var matches = getMatchGroups(formulaField.formula, this.patt); calcObj.isCalculating[formulaFieldId] = false; for(i in matches) { var inputId = matches[i][1]; var fieldId = parseInt(inputId); var input = jQuery('#field_' + formId + '_' + fieldId).find('input[name="input_' + inputId + '"], select[name="input_' + inputId + '"]'); if(input.prop('type') == 'checkbox' || input.prop('type') == 'radio') { jQuery(input).click(function(){ calcObj.bindCalcEvent(inputId, formulaField, formId, 0); }); } else if(input.is('select') || input.prop('type') == 'hidden') { jQuery(input).change(function(){ calcObj.bindCalcEvent(inputId, formulaField, formId, 0); }); } else { jQuery(input).keydown(function(){ calcObj.bindCalcEvent(inputId, formulaField, formId); }).change(function(){ calcObj.bindCalcEvent(inputId, formulaField, formId, 0); }); } } } this.bindCalcEvent = function(inputId, formulaField, formId, delay) { var calcObj = this; var formulaFieldId = formulaField.field_id; delay = delay == undefined ? 345 : delay; if(calcObj.isCalculating[formulaFieldId][inputId]) clearTimeout(calcObj.isCalculating[formulaFieldId][inputId]); calcObj.isCalculating[formulaFieldId][inputId] = window.setTimeout(function() { calcObj.runCalc(formulaField, formId); }, delay); } this.replaceFieldTags = function(formId, expr, numberFormat) { var matches = getMatchGroups(expr, this.patt); for(i in matches) { var inputId = matches[i][1]; var fieldId = parseInt(inputId); var columnId = matches[i][3]; var value = 0; var input = jQuery('#field_' + formId + '_' + fieldId).find('input[name="input_' + inputId + '"], select[name="input_' + inputId + '"]'); // radio buttons will return multiple inputs, checkboxes will only return one but it may not be selected, filter out unselected inputs if(input.length > 1 || input.prop('type') == 'checkbox') input = input.filter(':checked'); var isVisible = window["gf_check_field_rule"] ? gf_check_field_rule(formId, fieldId, true, "") == "show" : true; if(input.length > 0 && isVisible) { var val = input.val(); val = val.split('|'); if(val.length > 1) { value = val[1]; } else { value = input.val(); } } var decimalSeparator = "."; if(numberFormat == "decimal_comma"){ decimalSeparator = ","; } else if(numberFormat == "decimal_dot"){ decimalSeparator = "."; } else if(window['gf_global']){ var currency = new Currency(gf_global.gf_currency_config); decimalSeparator = currency.currency["decimal_separator"]; } value = gformCleanNumber(value, "", "", decimalSeparator); if(!value) value = 0; expr = expr.replace(matches[i][0], value); } return expr; } this.init(formId, formulaFields); } function gformFormatNumber(number, rounding, decimalSeparator, thousandSeparator){ if(typeof decimalSeparator == "undefined"){ if(window['gf_global']){ var currency = new Currency(gf_global.gf_currency_config); decimalSeparator = currency.currency["decimal_separator"]; } else{ decimalSeparator = "."; } } if(typeof thousandSeparator == "undefined"){ if(window['gf_global']){ var currency = new Currency(gf_global.gf_currency_config); thousandSeparator = currency.currency["thousand_separator"]; } else{ thousandSeparator = ","; } } var currency = new Currency(); return currency.numberFormat(number, rounding, decimalSeparator, thousandSeparator, false) } function gformToNumber(text) { var currency = new Currency(gf_global.gf_currency_config); return currency.toNumber(text); } function getMatchGroups(expr, patt) { var matches = new Array(); while(patt.test(expr)) { var i = matches.length; matches[i] = patt.exec(expr) expr = expr.replace('' + matches[i][0], ''); } return matches; }