PageSourceSearch

https://www.annie50.com/wp-content/plugins/gravityforms/js/gravityforms.js

js annie50.com collected 2026-09-27 02:05:09 UTC 48,740 bytes, 1,464 lines download raw bytes

1
2// "prop" method fix for previous versions of jQuery (1.5 and below)
3if( typeof jQuery.fn.prop === 'undefined' ) {
4    jQuery.fn.prop = jQuery.fn.attr;
5}
6
7jQuery(document).ready(function(){
8    //Formatting free form currency fields to currency
9    jQuery(document).bind('gform_post_render', gformBindFormatPricingFields);
10});
11
12function gformBindFormatPricingFields(){
13    jQuery(".ginput_amount, .ginput_donation_amount").bind("change", function(){
14        gformFormatPricingField(this);
15    });
16
17    jQuery(".ginput_amount, .ginput_donation_amount").each(function(){
18        gformFormatPricingField(this);
19    });
20}
21
22//------------------------------------------------
23//---------- CURRENCY ----------------------------
24//------------------------------------------------
25function Currency(currency){
26    this.currency = currency;
27
28    this.toNumber = function(text){
29        if(this.isNumeric(text))
30            return parseFloat(text);
31
32        return gformCleanNumber(text, this.currency["symbol_right"], this.currency["symbol_left"], this.currency["decimal_separator"]);
33    };
34
35    this.toMoney = function(number){
36        if(!this.isNumeric(number))
37            number = this.toNumber(number);
38
39        if(number === false)
40            return "";
41
42        number = number + "";
43        negative = "";
44        if(number[0] == "-"){
45
46            number = parseFloat(number.substr(1));
47			negative = '-';
48        }
49        money = this.numberFormat(number, this.currency["decimals"], this.currency["decimal_separator"], this.currency["thousand_separator"]);
50
51		if ( money == '0.00' ){
52			negative = '';
53		}
54
55        var symbol_left = this.currency["symbol_left"] ? this.currency["symbol_left"] + this.currency["symbol_padding"] : "";
56        var symbol_right = this.currency["symbol_right"] ? this.currency["symbol_padding"] + this.currency["symbol_right"] : "";
57
58		money =  negative + this.htmlDecode(symbol_left) + money + this.htmlDecode(symbol_right);
59
60		return money;
61    };
62
63    this.numberFormat = function(number, decimals, dec_point, thousands_sep, padded){
64        var padded = typeof padded == 'undefined';
65        number = (number+'').replace(',', '').replace(' ', '');
66        var n = !isFinite(+number) ? 0 : +number,
67        prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
68        sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep, dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
69        s = '',
70
71        toFixedFix = function (n, prec) {
72            var k = Math.pow(10, prec);
73            return '' + Math.round(n * k) / k;
74        };
75
76        if(decimals == '0') {
77            s = ('' + Math.round(n)).split('.');
78        } else
79        if(decimals == -1) {
80            s = ('' + n).split('.');
81        } else {
82            // Fix for IE parseFloat(0.55).toFixed(0) = 0;
83            s = toFixedFix(n, prec).split('.');
84        }
85
86        if (s[0].length > 3) {
87            s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
88        }
89
90        if(padded) {
91            if ((s[1] || '').length < prec) {
92                s[1] = s[1] || '';
93                s[1] += new Array(prec - s[1].length + 1).join('0');
94            }
95        }
96
97        return s.join(dec);
98    }
99
100    this.isNumeric = function(number){
101        return gformIsNumber(number);
102    };
103
104    this.htmlDecode = function(text) {
105        var c,m,d = text;
106
107        // look for numerical entities &#34;
108        var arr=d.match(/&#[0-9]{1,5};/g);
109
110        // if no matches found in string then skip
111        if(arr!=null){
112            for(var x=0;x<arr.length;x++){
113                m = arr[x];
114                c = m.substring(2,m.length-1); //get numeric part which is refernce to unicode character
115                // if its a valid number we can decode
116                if(c >= -32768 && c <= 65535){
117                    // decode every single match within string
118                    d = d.replace(m, String.fromCharCode(c));
119                }else{
120                    d = d.replace(m, ""); //invalid so replace with nada
121                }
122            }
123        }
124        return d;
125    };
126}
127
128function gformCleanNumber(text, symbol_right, symbol_left, decimal_separator){
129    var clean_number = '',
130        float_number = '',
131        digit = '',
132        is_negative = false;
133
134    //converting to a string if a number as passed
135    text = text + " ";
136
137    //Removing symbol in unicode format (i.e. &#4444;)
138    text = text.replace(/&.*?;/, "");
139
140    //Removing symbol from text
141    text = text.replace(symbol_right, "");
142    text = text.replace(symbol_left, "");
143
144    //Removing all non-numeric characters
145    for(var i=0; i<text.length; i++){
146        digit = text.substr(i,1);
147        if( (parseInt(digit) >= 0 && parseInt(digit) <= 9) || digit == decimal_separator )
148            clean_number += digit;
149        else if(digit == '-')
150            is_negative = true;
151    }
152
153    //Removing thousand separators but keeping decimal point
154    for(var i=0; i<clean_number.length; i++) {
155        digit = clean_number.substr(i,1);
156        if (digit >= '0' && digit <= '9')
157            float_number += digit;
158        else if(digit == decimal_separator){
159            float_number += ".";
160        }
161    }
162
163    if(is_negative)
164        float_number = "-" + float_number;
165
166    return gformIsNumber(float_number) ? parseFloat(float_number) : false;
167}
168
169function gformGetDecimalSeparator(numberFormat){
170    var s;
171    switch (numberFormat){
172        case 'currency' :
173            var currency = new Currency(gf_global.gf_currency_config);
174            s = currency.currency["decimal_separator"];
175            break;
176        case 'decimal_comma' :
177            s = ',';
178            break;
179        default :
180            s = "."
181     }
182    return s;
183}
184
185function gformIsNumber(n) {
186  return !isNaN(parseFloat(n)) && isFinite(n);
187}
188
189function gformIsNumeric(value, number_format){
190
191    switch(number_format){
192        case "decimal_dot" :
193            var r = new RegExp("^(-?[0-9]{1,3}(?:,?[0-9]{3})*(?:\.[0-9]+)?)$");
194            return r.test(value);
195        break;
196
197        case "decimal_comma" :
198            var r = new RegExp("^(-?[0-9]{1,3}(?:\.?[0-9]{3})*(?:,[0-9]+)?)$");
199            return r.test(value);
200        break;
201    }
202    return false;
203}
204
205//------------------------------------------------
206//---------- MULTI-PAGE --------------------------
207//------------------------------------------------
208function gformDeleteUploadedFile(formId, fieldId, deleteButton){
209    var parent = jQuery("#field_" + formId + "_" + fieldId);
210
211    var fileIndex = jQuery(deleteButton).parent().index();
212
213    parent.find(".ginput_preview").eq(fileIndex).remove();
214
215    //displaying single file upload field
216    parent.find("input[type=\"file\"]").removeClass("gform_hidden");
217
218    //displaying post image label
219    parent.find(".ginput_post_image_file").show();
220
221    //clearing post image meta fields
222    parent.find("input[type=\"text\"]").val('');
223
224    //removing file from uploaded meta
225    var filesJson = jQuery('#gform_uploaded_files_' + formId).val();
226
227    if(filesJson){
228        var files = jQuery.secureEvalJSON(filesJson);
229        if(files) {
230            var inputName = "input_" + fieldId;
231            var $multfile = parent.find("#gform_multifile_upload_" + formId + "_" + fieldId );
232            if( $multfile.length > 0 ) {
233                files[inputName].splice(fileIndex, 1);
234                var settings = $multfile.data('settings');
235                var max = settings.gf_vars.max_files;
236                jQuery("#" + settings.gf_vars.message_id).html('');
237                if(files[inputName].length < max)
238                    gfMultiFileUploader.toggleDisabled(settings, false);
239
240            } else {
241                files[inputName] = null;
242            }
243
244            jQuery('#gform_uploaded_files_' + formId).val(jQuery.toJSON(files));
245        }
246    }
247}
248
249
250//------------------------------------------------
251//---------- PRICE -------------------------------
252//------------------------------------------------
253var _gformPriceFields = new Array();
254var _anyProductSelected;
255
256function gformIsHidden(element){
257    return element.parents('.gfield').not(".gfield_hidden_product").css("display") == "none";
258}
259
260function gformCalculateTotalPrice(formId){
261
262    if(!_gformPriceFields[formId])
263        return;
264
265    var price = 0;
266
267    _anyProductSelected = false; //Will be used by gformCalculateProductPrice().
268    for(var i=0; i<_gformPriceFields[formId].length; i++){
269        price += gformCalculateProductPrice(formId, _gformPriceFields[formId][i]);
270    }
271
272    //add shipping price if a product has been selected
273    if(_anyProductSelected){
274        /shipping price
275        var shipping = gformGetShippingPrice(formId)
276        price += shipping;
277    }
278
279    //gform_product_total filter. Allows uers to perform custom price calculation
280    if(window["gform_product_total"])
281        price = window["gform_product_total"](formId, price);
282
283
284    price = gform.applyFilters('gform_product_total', price, formId);
285
286    //updating total
287    var totalElement = jQuery(".ginput_total_" + formId);
288    if( totalElement.length > 0 ) {
289
290        var currentTotal = totalElement.next().val();
291
292        if( currentTotal == price ) {
293            return;
294        }
295
296        totalElement.next().val( price ).change();
297        totalElement.html( gformFormatMoney( price ) );
298
299    }
300}
301
302function gformGetShippingPrice(formId){
303    var shippingField = jQuery(".gfield_shipping_" + formId + " input[type=\"hidden\"], .gfield_shipping_" + formId + " select, .gfield_shipping_" + formId + " input:checked");
304    var shipping = 0;
305    if(shippingField.length == 1 && !gformIsHidden(shippingField)){
306        if(shippingField.attr("type") && shippingField.attr("type").toLowerCase() == "hidden")
307            shipping = shippingField.val();
308        else
309            shipping = gformGetPrice(shippingField.val());
310    }
311
312    return gformToNumber(shipping);
313}
314
315function gformGetFieldId(element){
316    var id = jQuery(element).attr("id");
317    var pieces = id.split("_");
318    if(pieces.length <=0)
319        return 0;
320
321    var fieldId = pieces[pieces.length-1];
322    return fieldId;
323
324}
325
326function gformCalculateProductPrice(form_id, productFieldId){
327
328    var suffix = "_" + form_id + "_" + productFieldId;
329
330
331    //Drop down auto-calculating labels
332    jQuery(".gfield_option" + suffix + ", .gfield_shipping_" + form_id).find("select").each(function(){
333
334        var dropdown_field = jQuery(this);
335        var selected_price = gformGetPrice(dropdown_field.val());
336        var field_id = dropdown_field.attr("id").split("_")[2];
337        dropdown_field.children("option").each(function(){
338            var choice_element = jQuery(this);
339            var label = gformGetOptionLabel(choice_element, choice_element.val(), selected_price, form_id, field_id);
340            choice_element.html(label);
341        });
342		dropdown_field.trigger('chosen:updated');
343    });
344
345
346    //Checkboxes labels with prices
347    jQuery(".gfield_option" + suffix).find(".gfield_checkbox").find("input").each(function(){
348        var checkbox_item = jQuery(this);
349        var id = checkbox_item.attr("id");
350        var field_id = id.split("_")[3];
351        var label_id = id.replace("choice_", "#label_");
352        var label_element = jQuery(label_id);
353        var label = gformGetOptionLabel(label_element, checkbox_item.val(), 0, form_id, field_id);
354        label_element.html(label);
355    });
356
357
358    //Radio button auto-calculating lables
359    jQuery(".gfield_option" + suffix + ", .gfield_shipping_" + form_id).find(".gfield_radio").each(function(){
360        var selected_price = 0;
361        var radio_field = jQuery(this);
362        var id = radio_field.attr("id");
363        var fieldId = id.split("_")[3];
364        var selected_value = radio_field.find("input:checked").val();
365
366        if(selected_value)
367            selected_price = gformGetPrice(selected_value);
368
369        jQuery(this).find("input").each(function(){
370            var radio_item = jQuery(this);
371            var label_id = radio_item.attr("id").replace("choice_", "#label_");
372            var label_element = jQuery(label_id);
373            var label = gformGetOptionLabel(label_element, radio_item.val(), selected_price, form_id, fieldId);
374            label_element.html(label);
375        });
376    });
377
378	var price = gformGetBasePrice(form_id, productFieldId);
379	var quantity = gformGetProductQuantity( form_id, productFieldId );
380
381	//calculating options if quantity is more than 0 (a product was selected).
382	if( quantity > 0 ) {
383
384		jQuery(".gfield_option" + suffix).find("input:checked, select").each(function(){
385			if(!gformIsHidden(jQuery(this)))
386				price += gformGetPrice(jQuery(this).val());
387		});
388
389		/setting global variable if quantity is more than 0 (a product was selected). Will be used when calculating total
390		_anyProductSelected = true;
391	}
392
393    price = price * quantity;
394    price = Math.round(price * 100) / 100;
395
396    return price;
397}
398
399function gformGetProductQuantity( formId, productFieldId ) {
400
401	//If product is not selected
402	if ( ! gformIsProductSelected( formId, productFieldId )){
403		return 0;
404	}
405
406    var quantity,
407        quantityInput = jQuery( '#ginput_quantity_' + formId + '_' + productFieldId);
408
409    if( quantityInput.length > 0 ) {
410
411        quantity = ! gformIsNumber( quantityInput.val() ) ? 0 : quantityInput.val();
412
413    } else {
414
415        quantityElement = jQuery( '.gfield_quantity_' + formId + '_' + productFieldId);
416        quantity = 1;
417
418        if( quantityElement.find( 'select' ).length > 0 ) {
419            quantity = quantityElement.find( 'select' ).val();
420        } else if( quantityElement.find( 'input' ).length > 0 ) {
421            quantity = quantityElement.find( 'input' ).val();
422        }
423
424        if( ! gformIsNumber( quantity ) )
425            quantity = 0;
426
427    }
428
429    quantity = parseFloat( quantity );
430
431    return quantity;
432}
433
434
435function gformIsProductSelected( formId, productFieldId ) {
436
437	var suffix = "_" + formId + "_" + productFieldId;
438
439	var productField = jQuery("#ginput_base_price" + suffix + ", .gfield_donation" + suffix + " input[type=\"text\"], .gfield_product" + suffix + " .ginput_amount");
440	if( productField.val() && ! gformIsHidden(productField) ){
441		return true;
442	}
443	else
444	{
445		productField = jQuery(".gfield_product" + suffix + " select, .gfield_product" + suffix + " input:checked, .gfield_donation" + suffix + " select, .gfield_donation" + suffix + " input:checked");
446		if( productField.val() && ! gformIsHidden(productField) ){
447			return true;
448		}
449	}
450
451	return false;
452}
453
454function gformGetBasePrice(formId, productFieldId){
455
456    var suffix = "_" + formId + "_" + productFieldId;
457    var price = 0;
458    var productField = jQuery("#ginput_base_price" + suffix+ ", .gfield_donation" + suffix + " input[type=\"text\"], .gfield_product" + suffix + " .ginput_amount");
459    if(productField.length > 0){
460        price = productField.val();
461
462        //If field is hidden by conditional logic, don't count it for the total
463        if(gformIsHidden(productField)){
464            price = 0;
465        }
466    }
467    else
468    {
469        productField = jQuery(".gfield_product" + suffix + " select, .gfield_product" + suffix + " input:checked, .gfield_donation" + suffix + " select, .gfield_donation" + suffix + " input:checked");
470        var val = productField.val();
471        if(val){
472            val = val.split("|");
473            price = val.length > 1 ? val[1] : 0;
474        }
475
476        //If field is hidden by conditional logic, don't count it for the total
477        if(gformIsHidden(productField))
478            price = 0;
479
480    }
481
482    var c = new Currency(gf_global.gf_currency_config);
483    price = c.toNumber(price);
484    return price === false ? 0 : price;
485}
486
487function gformFormatMoney(text){
488    if(!gf_global.gf_currency_config)
489        return text;
490
491    var currency = new Currency(gf_global.gf_currency_config);
492    return currency.toMoney(text);
493}
494
495function gformFormatPricingField(element){
496    if(gf_global.gf_currency_config){
497        var currency = new Currency(gf_global.gf_currency_config);
498        var price = currency.toMoney(jQuery(element).val());
499        jQuery(element).val(price);
500    }
501}
502
503function gformToNumber(text){
504    var currency = new Currency(gf_global.gf_currency_config);
505    return currency.toNumber(text);
506}
507
508function gformGetPriceDifference(currentPrice, newPrice){
509
510    //getting price difference
511    var diff = parseFloat(newPrice) - parseFloat(currentPrice);
512    price = gformFormatMoney(diff);
513    if(diff > 0)
514        price = "+" + price;
515
516    return price;
517}
518
519function gformGetOptionLabel(element, selected_value, current_price, form_id, field_id){
520    element = jQuery(element);
521    var price = gformGetPrice(selected_value);
522    var current_diff = element.attr('price');
523    var original_label = element.html().replace(/<span(.*)<\/span>/i, "").replace(current_diff, "");
524
525    var diff = gformGetPriceDifference(current_price, price);
526    diff = gformToNumber(diff) == 0 ? "" : " " + diff;
527    element.attr('price', diff);
528
529    //don't add <span> for drop down items (not supported)
530    var price_label = element[0].tagName.toLowerCase() == "option" ? " " + diff : "<span class='ginput_price'>" + diff + "</span>";
531    var label = original_label + price_label;
532
533    //calling hook to allow for custom option formatting
534    if(window["gform_format_option_label"])
535        label = gform_format_option_label(label, original_label, price_label, current_price, price, form_id, field_id);
536
537    return label;
538}
539
540function gformGetProductIds(parent_class, element){
541    var classes = jQuery(element).hasClass(parent_class) ? jQuery(element).attr("class").split(" ") : jQuery(element).parents("." + parent_class).attr("class").split(" ");
542    for(var i=0; i<classes.length; i++){
543        if(classes[i].substr(0, parent_class.length) == parent_class && classes[i] != parent_class)
544            return {formId: classes[i].split("_")[2], productFieldId: classes[i].split("_")[3]};
545    }
546    return {formId:0, fieldId:0};
547}
548
549function gformGetPrice(text){
550    var val = text.split("|");
551    var currency = new Currency(gf_global.gf_currency_config);
552
553    if(val.length > 1 && currency.toNumber(val[1]) !== false)
554         return currency.toNumber(val[1]);
555
556    return 0;
557}
558
559function gformRegisterPriceField(item){
560
561    if(!_gformPriceFields[item.formId])
562        _gformPriceFields[item.formId] = new Array();
563
564    //ignore price fields that have already been registered
565    for(var i=0; i<_gformPriceFields[item.formId].length; i++)
566        if(_gformPriceFields[item.formId][i] == item.productFieldId)
567            return;
568
569    //registering new price field
570    _gformPriceFields[item.formId].push(item.productFieldId);
571}
572
573function gformInitPriceFields(){
574
575    jQuery(".gfield_price").each(function(){
576
577        var productIds = gformGetProductIds("gfield_price", this);
578        gformRegisterPriceField(productIds);
579
580       jQuery(this).find("input[type=\"text\"], input[type=\"number\"], select").change(function(){
581
582           var productIds = gformGetProductIds("gfield_price", this);
583           if(productIds.formId == 0)
584                productIds = gformGetProductIds("gfield_shipping", this);
585
586           jQuery(document).trigger('gform_price_change', [productIds, this]);
587           gformCalculateTotalPrice(productIds.formId);
588       });
589
590       jQuery(this).find("input[type=\"radio\"], input[type=\"checkbox\"]").click(function(){
591           var productIds = gformGetProductIds("gfield_price", this);
592           if(productIds.formId == 0)
593                productIds = gformGetProductIds("gfield_shipping", this);
594
595           jQuery(document).trigger('gform_price_change', [productIds, this]);
596           gformCalculateTotalPrice(productIds.formId);
597       });
598
599    });
600
601    for(formId in _gformPriceFields){
602
603        //needed when implementing for in loops
604        if(!_gformPriceFields.hasOwnProperty(formId))
605            continue;
606
607        gformCalculateTotalPrice(formId);
608    }
609
610}
611
612
613//-------------------------------------------
614//---------- PASSWORD -----------------------
615//-------------------------------------------
616function gformShowPasswordStrength(fieldId){
617    var password = jQuery("#" + fieldId).val();
618    var confirm = jQuery("#" + fieldId + "_2").val();
619
620    var result = gformPasswordStrength(password, confirm);
621
622    var text = window['gf_text']["password_" + result];
623
624    jQuery("#" + fieldId + "_strength").val(result);
625    jQuery("#" + fieldId + "_strength_indicator").removeClass("blank mismatch short good bad strong").addClass(result).html(text);
626}
627
628// Password strength meter
629function gformPasswordStrength(password1, password2) {
630    var shortPass = 1, badPass = 2, goodPass = 3, strongPass = 4, mismatch = 5, symbolSize = 0, natLog, score;
631
632    if(password1.length <=0)
633        return "blank";
634
635    // password 1 != password 2
636    if ( (password1 != password2) && password2.length > 0)
637        return "mismatch";
638
639    //password < 4
640    if ( password1.length < 4 )
641        return "short";
642
643    if ( password1.match(/[0-9]/) )
644        symbolSize +=10;
645    if ( password1.match(/[a-z]/) )
646        symbolSize +=26;
647    if ( password1.match(/[A-Z]/) )
648        symbolSize +=26;
649    if ( password1.match(/[^a-zA-Z0-9]/) )
650        symbolSize +=31;
651
652    natLog = Math.log( Math.pow(symbolSize, password1.length) );
653    score = natLog / Math.LN2;
654
655    if (score < 40 )
656        return "bad";
657
658    if (score < 56 )
659        return "good";
660
661    return "strong";
662
663}
664
665//----------------------------
666//------ LIST FIELD ----------
667//----------------------------
668var gfield_original_title = "";
669function gformAddListItem(element, max){
670
671    if(jQuery(element).hasClass("gfield_icon_disabled"))
672        return;
673
674    var tr = jQuery(element).closest('tr');
675    var clone = tr.clone();
676    var tabindex = clone.find(":input:last").attr("tabindex");
677
678    clone.find("input, select").attr("tabindex", tabindex).not(":checkbox, :radio").val("");
679    clone.find(":checkbox, :radio").prop("checked", false);
680    clone = gform.applyFilters( 'gform_list_item_pre_add', clone );
681
682    tr.after(clone);
683    gformToggleIcons(tr.parent(), max);
684    gformAdjustClasses(tr.parent());
685}
686
687function gformDeleteListItem(element, max){
688    var tr = jQuery(element).parent().parent();
689    var parent = tr.parent();
690    tr.remove();
691    gformToggleIcons(parent, max);
692    gformAdjustClasses(parent);
693}
694
695function gformAdjustClasses(table){
696    var rows = table.children();
697    for(var i=0; i<rows.length; i++){
698        var odd_even_class = (i+1) % 2 == 0 ? "gfield_list_row_even" : "gfield_list_row_odd";
699        jQuery(rows[i]).removeClass("gfield_list_row_odd").removeClass("gfield_list_row_even").addClass(odd_even_class);
700    }
701}
702
703function gformToggleIcons(table, max){
704    var rowCount = table.children().length;
705    if(rowCount == 1){
706        table.find(".delete_list_item").css("visibility", "hidden");
707    }
708    else{
709        table.find(".delete_list_item").css("visibility", "visible");
710    }
711
712    if(max > 0 && rowCount >= max){
713        gfield_original_title = table.find(".add_list_item:first").attr("title");
714        table.find(".add_list_item").addClass("gfield_icon_disabled").attr("title", "");
715    }
716    else{
717        var addIcons = table.find(".add_list_item");
718        addIcons.removeClass("gfield_icon_disabled");
719        if(gfield_original_title)
720            addIcons.attr("title", gfield_original_title);
721    }
722}
723
724
725//-----------------------------------
726//------ CREDIT CARD FIELD ----------
727//-----------------------------------
728function gformMatchCard(id) {
729
730    var cardType = gformFindCardType(jQuery('#' + id).val());
731    var cardContainer = jQuery('#' + id).parents('.gfield').find('.gform_card_icon_container');
732
733    if(!cardType) {
734
735        jQuery(cardContainer).find('.gform_card_icon').removeClass('gform_card_icon_selected gform_card_icon_inactive');
736
737    } else {
738
739        jQuery(cardContainer).find('.gform_card_icon').removeClass('gform_card_icon_selected').addClass('gform_card_icon_inactive');
740        jQuery(cardContainer).find('.gform_card_icon_' + cardType).removeClass('gform_card_icon_inactive').addClass('gform_card_icon_selected');
741    }
742}
743
744function gformFindCardType(value) {
745
746    if(value.length < 4)
747        return false;
748
749    var rules = window['gf_cc_rules'];
750    var validCardTypes = new Array();
751
752    for(type in rules) {
753
754        //needed when implementing for in loops
755        if(!rules.hasOwnProperty(type))
756            continue;
757
758
759        for(i in rules[type]) {
760
761            if(!rules[type].hasOwnProperty(i))
762                continue;
763
764            if(rules[type][i].indexOf(value.substring(0, rules[type][i].length)) === 0) {
765                validCardTypes[validCardTypes.length] = type;
766                break;
767            }
768
769        }
770    }
771
772    return validCardTypes.length == 1 ? validCardTypes[0].toLowerCase() : false;
773}
774
775function gformToggleCreditCard(){
776    if(jQuery("#gform_payment_method_creditcard").is(":checked"))
777        jQuery(".gform_card_fields_container").slideDown();
778    else
779        jQuery(".gform_card_fields_container").slideUp();
780}
781
782
783//----------------------------------------
784//------ CHOSEN DROP DOWN FIELD ----------
785//----------------------------------------
786
787function gformInitChosenFields(fieldList, noResultsText){
788    return jQuery(fieldList).each(function(){
789
790        var element = jQuery( this );
791
792        // RTL support
793        if( jQuery( 'html' ).attr( 'dir' ) == 'rtl' ) {
794            element.addClass( 'chosen-rtl chzn-rtl' );
795        }
796
797        // only initialize once
798        if( element.is(":visible") && element.siblings(".chosen-container").length == 0 ){
799            var options = gform.applyFilters( 'gform_chosen_options', { no_results_text: noResultsText }, element );
800            element.chosen( options );
801        }
802
803    });
804}
805
806//----------------------------------------
807//--- CURRENCY FORMAT NUMBER FIELD -------
808//----------------------------------------
809
810function gformInitCurrencyFormatFields(fieldList){
811    jQuery(fieldList).each(function(){
812        var $this = jQuery(this);
813        $this.val( gformFormatMoney( jQuery(this).val() ) );
814    }).change( function( event ) {
815            jQuery(this).val( gformFormatMoney( jQuery(this).val() ) );
816        });
817}
818
819
820
821//----------------------------------------
822//------ CALCULATION FUNCTIONS -----------
823//----------------------------------------
824
825var GFCalc = function(formId, formulaFields){
826
827    this.patt = /{[^{]*?:(\d+(\.\d+)?)(:(.*?))?}/i;
828    this.exprPatt = /^[0-9 -/*\(\)]+$/i;
829    this.isCalculating = {};
830
831    this.init = function(formId, formulaFields) {
832
833        var calc = this;
834        jQuery(document).bind("gform_post_conditional_logic", function(){
835            for(var i=0; i<formulaFields.length; i++) {
836                var formulaField = jQuery.extend({}, formulaFields[i]);
837                calc.runCalc(formulaField, formId);
838            }
839        });
840
841        for(var i=0; i<formulaFields.length; i++) {
842            var formulaField = jQuery.extend({}, formulaFields[i]);
843            this.runCalc(formulaField, formId);
844            this.bindCalcEvents(formulaField, formId);
845        }
846
847    }
848
849    this.runCalc = function(formulaField, formId) {
850
851        var calcObj      = this,
852            field        = jQuery('#field_' + formId + '_' + formulaField.field_id),
853            formulaInput = jQuery('#input_' + formId + '_' + formulaField.field_id),
854            previous_val = formulaInput.val(),
855            formula      = gform.applyFilters( 'gform_calculation_formula', formulaField.formula, formulaField, formId, calcObj ),
856            expr         = calcObj.replaceFieldTags( formId, formula, formulaField ).replace(/(\r\n|\n|\r)/gm,""),
857            result       = '';
858
859        if(calcObj.exprPatt.test(expr)) {
860            try {
861
862                //run calculation
863                result = eval(expr);
864
865            } catch( e ) { }
866        }
867
868        // if result is postive infinity, negative infinity or a NaN, defaults to 0
869        if( ! isFinite( result ) )
870            result = 0;
871
872        // allow users to modify result with their own function
873        if( window["gform_calculation_result"] ) {
874            result = window["gform_calculation_result"](result, formulaField, formId, calcObj);
875            if( window.console )
876                console.log( '"gform_calculation_result" function is deprecated since version 1.8! Use "gform_calculation_result" JS hook instead.' );
877        }
878
879        // allow users to modify result with their own function
880        result = gform.applyFilters( 'gform_calculation_result', result, formulaField, formId, calcObj );
881
882        // allow result to be custom formatted
883        var formattedResult = gform.applyFilters( 'gform_calculation_format_result', false, result, formulaField, formId, calcObj );
884
885        var numberFormat = gf_global.number_formats[formId][formulaField.field_id];
886
887        //formatting number
888        if( formattedResult !== false) {
889            result = formattedResult;
890        }
891        else if( field.hasClass( 'gfield_price' ) || numberFormat == "currency") {
892
893            result = gformFormatMoney(result ? result : 0);
894        }
895        else {
896
897            var decimalSeparator = ".";
898            var thousandSeparator = ",";
899
900            if(numberFormat == "decimal_comma"){
901                decimalSeparator = ",";
902                thousandSeparator = ".";
903            }
904
905            result = gformFormatNumber(result, !gformIsNumber(formulaField.rounding) ? -1 : formulaField.rounding, decimalSeparator, thousandSeparator);
906        }
907
908        //If value doesn't change, abort.
909        //This is needed to prevent an infinite loop condition with conditional logic
910        if( result == previous_val )
911            return;
912
913        // if this is a calculation product, handle differently
914        if(field.hasClass('gfield_price')) {
915            formulaInput.text(result);
916            jQuery('#ginput_base_price_' + formId + '_' + formulaField.field_id).val(result).trigger('change');
917            gformCalculateTotalPrice(formId);
918        } else {
919            formulaInput.val(result).trigger('change');
920        }
921
922    }
923
924
925    this.bindCalcEvents = function(formulaField, formId) {
926
927        var calcObj = this;
928        var formulaFieldId = formulaField.field_id;
929        var matches = getMatchGroups(formulaField.formula, this.patt);
930
931        calcObj.isCalculating[formulaFieldId] = false;
932
933        for(var i in matches) {
934
935            if(! matches.hasOwnProperty(i))
936                continue;
937
938            var inputId = matches[i][1];
939            var fieldId = parseInt(inputId);
940            var input = jQuery('#field_' + formId + '_' + fieldId).find('input[name="input_' + inputId + '"], select[name="input_' + inputId + '"]');
941
942            if(input.prop('type') == 'checkbox' || input.prop('type') == 'radio') {
943                jQuery(input).click(function(){
944                    calcObj.bindCalcEvent(inputId, formulaField, formId, 0);
945                });
946            } else
947            if(input.is('select') || input.prop('type') == 'hidden') {
948                jQuery(input).change(function(){
949                    calcObj.bindCalcEvent(inputId, formulaField, formId, 0);
950                });
951            } else {
952                jQuery(input).keydown(function(){
953                    calcObj.bindCalcEvent(inputId, formulaField, formId);
954                }).change(function(){
955                    calcObj.bindCalcEvent(inputId, formulaField, formId, 0);
956                });
957            }
958
959            // allow users to add custom methods for triggering calculations
960            gform.doAction( 'gform_post_calculation_events', matches[i], formulaField, formId, calcObj );
961
962        }
963
964    }
965
966    this.bindCalcEvent = function(inputId, formulaField, formId, delay) {
967
968        var calcObj = this;
969        var formulaFieldId = formulaField.field_id;
970
971        delay = delay == undefined ? 345 : delay;
972
973        if(calcObj.isCalculating[formulaFieldId][inputId])
974            clearTimeout(calcObj.isCalculating[formulaFieldId][inputId]);
975
976        calcObj.isCalculating[formulaFieldId][inputId] = window.setTimeout(function() {
977            calcObj.runCalc(formulaField, formId);
978        }, delay);
979
980    }
981
982    this.replaceFieldTags = function( formId, expr, formulaField ) {
983
984        var matches = getMatchGroups(expr, this.patt);
985        var origExpr = expr;
986
987        for(i in matches) {
988
989            if(! matches.hasOwnProperty(i))
990                continue;
991
992            var inputId = matches[i][1];
993            var fieldId = parseInt(inputId);
994            var columnId = matches[i][3];
995            var value = 0;
996
997            var input = jQuery('#field_' + formId + '_' + fieldId).find('input[name="input_' + inputId + '"], select[name="input_' + inputId + '"]');
998
999            // radio buttons will return multiple inputs, checkboxes will only return one but it may not be selected, filter out unselected inputs
1000            if( input.length > 1 || input.prop('type') == 'checkbox' )
1001                input = input.filter(':checked');
1002
1003            var isVisible = window['gf_check_field_rule'] ? gf_check_field_rule( formId, fieldId, true, '' ) == 'show' : true;
1004
1005            if( input.length > 0 && isVisible ) {
1006
1007                var val = input.val();
1008                val = val.split( '|' );
1009
1010                if( val.length > 1 ) {
1011                    value = val[1];
1012                } else {
1013                    value = input.val();
1014                }
1015
1016            }
1017
1018            var numberFormat = gf_global.number_formats[formId][fieldId];
1019            if( ! numberFormat )
1020                numberFormat = gf_global.number_formats[formId][formulaField.field_id];
1021
1022            var decimalSeparator = gformGetDecimalSeparator(numberFormat);
1023
1024            // allow users to modify value with their own function
1025            value = gform.applyFilters( 'gform_merge_tag_value_pre_calculation', value, matches[i], isVisible, formulaField, formId );
1026
1027            value = gformCleanNumber( value, '', '', decimalSeparator );
1028            if( ! value )
1029                value = 0;
1030
1031            expr = expr.replace( matches[i][0], value );
1032        }
1033
1034        return expr;
1035    }
1036
1037    this.init(formId, formulaFields);
1038
1039}
1040
1041function gformFormatNumber(number, rounding, decimalSeparator, thousandSeparator){
1042
1043    if(typeof decimalSeparator == "undefined"){
1044        if(window['gf_global']){
1045            var currency = new Currency(gf_global.gf_currency_config);
1046            decimalSeparator = currency.currency["decimal_separator"];
1047        }
1048        else{
1049            decimalSeparator = ".";
1050        }
1051    }
1052
1053    if(typeof thousandSeparator == "undefined"){
1054        if(window['gf_global']){
1055            var currency = new Currency(gf_global.gf_currency_config);
1056            thousandSeparator = currency.currency["thousand_separator"];
1057        }
1058        else{
1059            thousandSeparator = ",";
1060        }
1061    }
1062
1063    var currency = new Currency();
1064    return currency.numberFormat(number, rounding, decimalSeparator, thousandSeparator, false)
1065}
1066
1067function gformToNumber(text) {
1068    var currency = new Currency(gf_global.gf_currency_config);
1069    return currency.toNumber(text);
1070}
1071
1072function getMatchGroups(expr, patt) {
1073
1074    var matches = new Array();
1075
1076    while(patt.test(expr)) {
1077
1078        var i = matches.length;
1079        matches[i] = patt.exec(expr)
1080        expr = expr.replace('' + matches[i][0], '');
1081
1082    }
1083
1084    return matches;
1085}
1086
1087
1088//----------------------------------------
1089//------ JAVASCRIPT HOOK FUNCTIONS -------
1090//----------------------------------------
1091
1092var gform = {
1093	hooks: { action: {}, filter: {} },
1094	addAction: function( action, callable, priority, tag ) {
1095		gform.addHook( 'action', action, callable, priority, tag );
1096	},
1097	addFilter: function( action, callable, priority, tag ) {
1098		gform.addHook( 'filter', action, callable, priority, tag );
1099	},
1100	doAction: function( action ) {
1101		gform.doHook( 'action', action, arguments );
1102	},
1103	applyFilters: function( action ) {
1104		return gform.doHook( 'filter', action, arguments );
1105	},
1106	removeAction: function( action, tag ) {
1107		gform.removeHook( 'action', action, tag );
1108	},
1109	removeFilter: function( action, priority, tag ) {
1110		gform.removeHook( 'filter', action, priority, tag );
1111	},
1112	addHook: function( hookType, action, callable, priority, tag ) {
1113		if ( undefined == gform.hooks[hookType][action] ) {
1114			gform.hooks[hookType][action] = [];
1115		}
1116		var hooks = gform.hooks[hookType][action];
1117		if ( undefined == tag ) {
1118			tag = action + '_' + hooks.length;
1119		}
1120		gform.hooks[hookType][action].push( { tag:tag, callable:callable, priority:priority } );
1121	},
1122	doHook: function( hookType, action, args ) {
1123
1124        // splice args from object into array and remove first index which is the hook name
1125        args = Array.prototype.slice.call(args, 1);
1126
1127		if ( undefined != gform.hooks[hookType][action] ) {
1128			var hooks = gform.hooks[hookType][action], hook;
1129			/sort by priority
1130			hooks.sort(function(a,b){return a["priority"]-b["priority"]});
1131			for( var i=0; i<hooks.length; i++) {
1132                hook = hooks[i].callable;
1133                if(typeof hook != 'function')
1134                    hook = window[hook];
1135				if ( 'action' == hookType ) {
1136                    hook.apply(null, args);
1137				} else {
1138                    args[0] = hook.apply(null, args);
1139				}
1140			}
1141		}
1142		if ( 'filter'==hookType ) {
1143			return args[0];
1144		}
1145	},
1146	removeHook: function( hookType, action, priority, tag ) {
1147		if ( undefined != gform.hooks[hookType][action] ) {
1148			var hooks = gform.hooks[hookType][action];
1149			for( var i=hooks.length-1; i>=0; i--) {
1150				if ((undefined==tag||tag==hooks[i].tag) && (undefined==priority||priority==hooks[i].priority)){
1151					hooks.splice(i,1);
1152				}
1153			}
1154		}
1155	}
1156};
1157
1158
1159//----------------------------------------
1160//------ MULTIFILE UPLOAD FUNCTIONS ------
1161//----------------------------------------
1162
1163(function (gfMultiFileUploader, $) {
1164    gfMultiFileUploader.uploaders = {};
1165    var strings = typeof gform_gravityforms != 'undefined' ? gform_gravityforms.strings : {};
1166    var imagesUrl = typeof gform_gravityforms != 'undefined' ? gform_gravityforms.vars.images_url : "";
1167
1168
1169	$(document).bind('gform_post_render', function(e, formID){
1170
1171		$("form#gform_" + formID + " .gform_fileupload_multifile").each(function(){
1172			setup(this);
1173		});
1174		var $form = $("form#gform_" + formID);
1175		if($form.length > 0){
1176			$form.submit(function(){
1177				var pendingUploads = false;
1178				$.each(gfMultiFileUploader.uploaders, function(i, uploader){
1179					if(uploader.total.queued>0){
1180						pendingUploads = true;
1181						return false;
1182					}
1183				});
1184				if(pendingUploads){
1185					alert(strings.currently_uploading);
1186					window["gf_submitting_" + formID] = false;
1187					$('#gform_ajax_spinner_' + formID).remove();
1188					return false;
1189				}
1190			});
1191		}
1192
1193	});
1194
1195	$(document).bind("gform_post_conditional_logic", function(e,formID, fields, isInit){
1196		if(!isInit){
1197			$.each(gfMultiFileUploader.uploaders, function(i, uploader){
1198				uploader.refresh();
1199			});
1200		}
1201	});
1202
1203    $(document).ready(function () {
1204        if((typeof adminpage !== 'undefined' && adminpage === 'toplevel_page_gf_edit_forms')|| typeof plupload == 'undefined'){
1205            $(".gform_button_select_files").prop("disabled", true);
1206        } else if (typeof adminpage !== 'undefined' && adminpage.indexOf('_page_gf_entries') > -1) {
1207            $(".gform_fileupload_multifile").each(function(){
1208                setup(this);
1209            });
1210        }
1211    });
1212
1213    gfMultiFileUploader.setup = function (uploadElement){
1214        setup( uploadElement );
1215    };
1216
1217    function setup(uploadElement){
1218        var settings = $(uploadElement).data('settings');
1219
1220        var uploader = new plupload.Uploader(settings);
1221        formID = uploader.settings.multipart_params.form_id;
1222        gfMultiFileUploader.uploaders[settings.container] = uploader;
1223        var formID;
1224        var uniqueID;
1225
1226        uploader.bind('Init', function(up, params) {
1227            if(!up.features.dragdrop)
1228                $(".gform_drop_instructions").hide();
1229            var fieldID = up.settings.multipart_params.field_id;
1230            var maxFiles = parseInt(up.settings.gf_vars.max_files);
1231            var initFileCount = countFiles(fieldID);
1232            if(maxFiles > 0 && initFileCount >= maxFiles){
1233                gfMultiFileUploader.toggleDisabled(up.settings, true);
1234            }
1235
1236        });
1237
1238        gfMultiFileUploader.toggleDisabled = function (settings, disabled){
1239
1240            var button = typeof settings.browse_button == "string" ? $("#" + settings.browse_button) : $(settings.browse_button);
1241            button.prop("disabled", disabled);
1242        };
1243
1244        function addMessage(messagesID, message){
1245            $("#" + messagesID).prepend("<li>" + message + "</li>");
1246        }
1247
1248        uploader.init();
1249
1250        uploader.bind('FilesAdded', function(up, files) {
1251            var max = parseInt(up.settings.gf_vars.max_files),
1252                fieldID = up.settings.multipart_params.field_id,
1253                totalCount = countFiles(fieldID),
1254                disallowed = up.settings.gf_vars.disallowed_extensions,
1255                extension;
1256
1257            if( max > 0 && totalCount >= max){
1258                $.each(files, function(i, file) {
1259                    up.removeFile(file);
1260                    return;
1261                });
1262                return;
1263            }
1264            $.each(files, function(i, file) {
1265
1266                extension = file.name.split('.').pop();
1267
1268                if($.inArray(extension, disallowed) > -1){
1269                    addMessage(up.settings.gf_vars.message_id, file.name + " - " + strings.illegal_extension);
1270                    up.removeFile(file);
1271                    return;
1272                }
1273
1274                if ((file.status == plupload.FAILED) || (max > 0 && totalCount >= max)){
1275                    up.removeFile(file);
1276                    return;
1277                }
1278
1279                var size = typeof file.size !== 'undefined' ? plupload.formatSize(file.size) : strings.in_progress;
1280                var status = '<div id="'
1281                    + file.id
1282                    + '" class="ginput_preview">'
1283                    + file.name
1284                    + ' (' + size + ') <b></b> '
1285                    + '<a href="javascript:void(0)" title="' + strings.cancel_upload + '" onclick=\'$this=jQuery(this); var uploader = gfMultiFileUploader.uploaders.' + up.settings.container + ';uploader.stop();uploader.removeFile(uploader.getFile("' + file.id +'"));$this.after("' + strings.cancelled + '"); uploader.start();$this.remove();\'>' + strings.cancel + '</a>'
1286                    + '</div>';
1287
1288                $('#' + up.settings.filelist).prepend(status);
1289                totalCount++;
1290
1291            });
1292
1293            up.refresh(); // Reposition Flash
1294
1295            var formElementID = "form#gform_" + formID;
1296            var uidElementID = "input:hidden[name='gform_unique_id']";
1297            var uidSelector = formElementID + " " + uidElementID;
1298            var $uid = $(uidSelector);
1299            if($uid.length==0){
1300                $uid = $(uidElementID);
1301            }
1302
1303            uniqueID = $uid.val();
1304            if('' === uniqueID){
1305                uniqueID = generateUniqueID();
1306                $uid.val(uniqueID);
1307            }
1308
1309
1310            if(max > 0 && totalCount >= max){
1311                gfMultiFileUploader.toggleDisabled(up.settings, true);
1312                addMessage(up.settings.gf_vars.message_id, strings.max_reached)
1313            }
1314
1315
1316            up.settings.multipart_params.gform_unique_id = uniqueID;
1317            up.start();
1318
1319        });
1320
1321        uploader.bind('UploadProgress', function(up, file) {
1322            var html = file.percent + "%";
1323            $('#' + file.id + " b").html(html);
1324        });
1325
1326        uploader.bind('Error', function(up, err) {
1327            if(err.code === plupload.FILE_EXTENSION_ERROR){
1328                var extensions = typeof up.settings.filters.mime_types != 'undefined' ? up.settings.filters.mime_types[0].extensions /* plupoad 2 */ : up.settings.filters[0].extensions;
1329                addMessage(up.settings.gf_vars.message_id, err.file.name + " - " + strings.invalid_file_extension + " " + extensions);
1330            } else if (err.code === plupload.FILE_SIZE_ERROR) {
1331                addMessage(up.settings.gf_vars.message_id, err.file.name + " - " + strings.file_exceeds_limit);
1332            } else {
1333                var m = "<li>Error: " + err.code +
1334                    ", Message: " + err.message +
1335                    (err.file ? ", File: " + err.file.name : "") +
1336                    "</li>";
1337
1338                addMessage(up.settings.gf_vars.message_id, m);
1339            }
1340            $('#' + err.file.id ).html('');
1341
1342            up.refresh(); // Reposition Flash
1343        });
1344
1345        uploader.bind('FileUploaded', function(up, file, result) {
1346            var response = $.secureEvalJSON(result.response);
1347            if(response.status == "error"){
1348                addMessage(up.settings.gf_vars.message_id, file.name + " - " + response.error.message);
1349                $('#' + file.id ).html('');
1350                return;
1351            }
1352
1353            var html = '<strong>' + file.name + '</strong>';
1354            var formId = up.settings.multipart_params.form_id;
1355            var fieldId = up.settings.multipart_params.field_id;
1356            html = "<img "
1357                + "class='gform_delete' "
1358                + "src='" + imagesUrl + "/delete.png' "
1359                + "onclick='gformDeleteUploadedFile(" + formId + "," + fieldId + ", this);' "
1360                + "alt='"+ strings.delete_file + "' "
1361                + "title='" + strings.delete_file
1362                + "' /> "
1363                + html;
1364
1365            html = gform.applyFilters( 'gform_file_upload_markup', html, file, up, strings, imagesUrl );
1366
1367            $( '#' + file.id ).html( html );
1368
1369            var fieldID = up.settings.multipart_params["field_id"];
1370
1371            if(file.percent == 100){
1372                if(response.status && response.status == 'ok'){
1373                    addFile(fieldID, response.data);
1374                }  else {
1375                    addMessage(up.settings.gf_vars.message_id, strings.unknown_error + ': ' + file.name);
1376                }
1377            }
1378
1379
1380
1381        });
1382
1383        function getAllFiles(){
1384            var selector = '#gform_uploaded_files_' + formID,
1385                $uploadedFiles = $(selector), files;
1386            files = $uploadedFiles.val();
1387            files = '' === files ? {}
1387 : $.parseJSON(files);
1388            return files;
1389        }
1390
1391        function getFiles(fieldID){
1392            var allFiles = getAllFiles();
1393            var inputName = getInputName(fieldID);
1394
1395            if(typeof allFiles[inputName] == 'undefined')
1396                allFiles[inputName] = [];
1397            return allFiles[inputName];
1398        }
1399
1400        function countFiles(fieldID){
1401            var files = getFiles(fieldID);
1402            return files.length;
1403        }
1404
1405        function addFile(fieldID, fileInfo){
1406
1407            var files = getFiles(fieldID);
1408
1409            files.unshift(fileInfo);
1410            setUploadedFiles(fieldID, files);
1411        }
1412
1413        function setUploadedFiles(fieldID, files){
1414            var allFiles = getAllFiles();
1415            var $uploadedFiles = $('#gform_uploaded_files_' + formID);
1416            var inputName = getInputName(fieldID);
1417            allFiles[inputName] = files;
1418            $uploadedFiles.val($.toJSON(allFiles));
1419        }
1420
1421        function getInputName(fieldID){
1422            return "input_" + fieldID;
1423        }
1424
1425        // fixes drag and drop in IE10
1426        $("#" + settings.drop_element).on({
1427            "dragenter": ignoreDrag,
1428            "dragover": ignoreDrag
1429        });
1430
1431        function ignoreDrag( e ) {
1432            e.preventDefault();
1433        }
1434    }
1435
1436
1437    function generateUniqueID() {
1438        return 'xxxxxxxx'.replace(/[xy]/g, function (c) {
1439            var r = Math.random() * 16 | 0, v = c == 'x' ? r : r & 0x3 | 0x8;
1440            return v.toString(16);
1441        });
1442    }
1443
1444
1445}(window.gfMultiFileUploader = window.gfMultiFileUploader || {}, jQuery));
1446
1447
1448//----------------------------------------
1449//------ GENERAL FUNCTIONS -------
1450//----------------------------------------
1451
1452function gformInitSpinner( formId, spinnerUrl ) {
1453
1454    if( typeof spinnerUrl == 'undefined' || ! spinnerUrl )
1455        spinnerUrl = gform.applyFilters( "gform_spinner_url", gf_global.spinnerUrl, formId );
1456
1457	jQuery('#gform_' + formId).submit(function () {
1458		if (jQuery('#gform_ajax_spinner_' + formId).length == 0) {
1459			jQuery('#gform_submit_button_' + formId + ', #gform_wrapper_' + formId + ' .gform_next_button, #gform_send_resume_link_button_' + formId)
1460				.after('<img id="gform_ajax_spinner_' + formId + '"  class="gform_ajax_spinner" src="' + spinnerUrl + '" alt="" />');
1461		}
1462	});
1463
1464}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.