PageSourceSearch

https://donate.esnorcal.org/_themes/standard/standard.js?v=2026-09-22T11:37:44

js esnorcal.org collected 2026-09-29 04:57:04 UTC 124,298 bytes, 3,187 lines download raw bytes

1///<reference path="../../_includes/core.js" />
2///<reference path="../../_includes/webforms.lib.js" />
3///<reference path="../../_includes/webforms.ui.js" />
4
5//strict mode enabled to enforce code quality (more secure and stable code) within the theme scope - see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode
6'use strict';
7 
8//define theme version
9var themeName = 'CharityEngine Standard Web Form';
10var themeVersion = 1.0;
11
12//core subscription service for state storage (required)
13var themeUIStateConfig = {}; //Form.getUIStateOrDefault();
14var themeLoaded = false;
15
16var gl_firtPaymentMethodButtonElement = null; //deprecated, do not use (12.6.2024)
17
18var originalButtonText = '';
19 
20function callUIUpdatesForAmountOrPaymentChange(fromPaymentMethodChangedEvent) {
21
22    console.log('**STD THM: callUIUpdatesForAmountOrPaymentChange');
23
24    updateSubmitButtonTextBasedOnAmount();
25    showHidePaymentInfoBlockBasedOnAmount(fromPaymentMethodChangedEvent);
26    showHidePaymentSectionsBasedOnCurrency();
27
28}
29
30function updateSubmitButtonTextBasedOnAmount() {
31    
32    console.log('**STD THM: updateSubmitButtonTextBasedOnAmount');    
33     
34    if(WebFormContext.Form.EnableProcessButtonLabelAmountSync)
35    {
36
37        var donateButton = Form.GetNextButton();
38        var chosenFrequency = '';
39
40        if (frequencyDropdown != null && !isBlank(frequencyDropdown.getValue()) && frequencyDropdown.tagName == 'SELECT')
41            chosenFrequency = getDropDownSelectedText(frequencyDropdown);
42
43        //don't want to show total on receipt or error page
44        if (WebFormContext.Form.StepNumber != 3 && donateButton != null)
45        {
46
47            if (Form.paymentSection.isPaymentBlockPresent() || Form.amountSection.isAmountBlockPresent())
48            {
49
50                if (Form.paymentSection.isPaymentBlockPresent()) 
51                    Form.paymentSection.updateProcessingFees(); 
52
53                var subButtText = '';
54                if (!isBlank(originalButtonText))
55                    subButtText = originalButtonText;
56
57                var curSymb = '$';
58                if (!isBlank(getCurrencySymbol()))
59                    curSymb = getCurrencySymbol();
60
61                var giftAmount = formatCurrency(Form.GetTransactionAmount(), true, curSymb);
62
63                var tixSelElems = document.querySelectorAll('.TicketSectionContainer');
64                if (tixSelElems != null && tixSelElems.length > 0)
65                { 
66                    console.log('**STD THM: populate button using transaction amount (ticket configuration present)');
67                    donateButton.value = subButtText + ' ' + giftAmount;
68                }
69                else
70                {
71                     
72                    var selectedFrequencyId = null;
73                    if (frequencyDropdown != null && !isBlank(frequencyDropdown.getValue()))
74                        selectedFrequencyId = frequencyDropdown.getValue().toIntZeroIfInvalid();
75                     
76                    if (selectedFrequencyId != null) {
77
78                        //one time will not have frequency
79                        if (selectedFrequencyId <= 0) {
80                            console.log('**STD THM: populate button using transaction amount (frequency value is none)');
81                            donateButton.value = subButtText + ' ' + giftAmount;
82                        }
83                        else
84                        {
85
86                            //frequency is daily, monthly, annually, etc.
87                            var recurringAmt = Form.GetRecurringAmount();
88                            if (recurringAmt > 0) {
89                                console.log('**STD THM: populate button using recurring amount');
90                                donateButton.value = subButtText + ' ' + formatCurrency(recurringAmt, true, curSymb) + ' ' + chosenFrequency;
91                            }
92                            else
93                            {
94                                console.log('**STD THM: populate recurring button using transaction amount (no recurring element)');
95                                donateButton.value = subButtText + ' ' + giftAmount + ' ' + chosenFrequency; //default to one-time amount if recurring field is not defined
96                            }
97
98                        }
99
100                    }
101                    else
102                    { 
103                        console.log('**STD THM: populate button using transaction amount (no frequency field)');
104                        donateButton.value = subButtText + ' ' + giftAmount;
105                    }
106
107                }
108
109            }
110
111        }
112
113    }
114
115}
116
117function addFrequencyGiftStringHtml(amountInputElem, containerId, giftAmounts) {
118
119    var giftAmountContainer = document.createElement("div");
120    giftAmountContainer.setAttribute('id', containerId);
121
122    amountInputElem.parentNode.parentNode.insertBefore(giftAmountContainer, amountInputElem.parentNode);
123
124    for (var i = 0; i < giftAmounts.length; i++) {
125
126        var showAmount = (!isBlank(giftAmounts[i].Value) && giftAmounts[i].Value != '0' && giftAmounts[i].Value != '0.00');
127
128        var giftAmountBtn = document.createElement("span");
129
130        var cssClass = 'giftAmountBtn';
131
132        if (!showAmount)
133            cssClass += ' hideCurrencySymbol';
134
135        giftAmountBtn.setAttribute('class', cssClass);
136        giftAmountBtn.setAttribute('onclick', 'updateAmountTextBoxOnBtnClick(' + giftAmounts[i].Value + ')');
137        giftAmountBtn.setAttribute('data-value', giftAmounts[i].Value); //Worst poattern ever, requires CSS layer cake for business logic.  Not manipulatable via DOM.  Aweful
138         
139        if(showAmount)
140            giftAmountBtn.innerHTML = formatCurrency(giftAmounts[i].Value, false);//re-evaluate if cents are needed
141
142        if (giftAmounts[i].Value != giftAmounts[i].Label && !isBlank(giftAmounts[i].Label)) { 
143
144            if (!isBlank(giftAmountBtn.innerHTML))
145                giftAmountBtn.innerHTML += ' | ';
146
147            giftAmountBtn.innerHTML += giftAmounts[i].Label;        
148
149        }
150
151        if (giftAmounts[i].Value == amountInputElem.value)
152            giftAmountBtn.setAttribute('class', 'giftAmountBtn active');
153
154        document.getElementById(containerId).insertBefore(giftAmountBtn, null);
155
156    }
157
158}
159
160function highlightChosenAskStringOptionOnDonorClick(amount, containerId) {
161
162    if (document.getElementById(containerId) != null) {
163
164        var giftAmountBtn = document.getElementById(containerId).querySelectorAll('.giftAmountBtn');
165        if (giftAmountBtn != null) 
166            for (var i = 0; i < giftAmountBtn.length; i++) {
167
168                giftAmountBtn[i].classList.remove('active');
169
170                if (amount == giftAmountBtn[i].getAttribute('data-value'))
171                    giftAmountBtn[i].classList.add('active');
172
173            } 
174
175    }
176
177}
178
179function getPaymentMethodElement() {
180
181    var retVal = null;
182
183    for (var x = 0; x < WebFormContext.Form.Fields.length; x++)
184        if (WebFormContext.Form.Fields[x].DataMapping.PaymentMethod && !isBlank(WebFormContext.Form.Fields[x].DomId))
185            retVal = document.getElementById(WebFormContext.Form.Fields[x].DomId);                    
186
187    return retVal;
188
189}
190
191function getAmountInputElement() {
192
193    var retVal = null;
194
195    for (var x = 0; x < WebFormContext.Form.Fields.length; x++)
196        if (WebFormContext.Form.Fields[x].DataMapping.TransactionAmount && !isBlank(WebFormContext.Form.Fields[x].DomId))
197            retVal = document.getElementById(WebFormContext.Form.Fields[x].DomId);                    
198
199    return retVal;
200
201}
202
203function getRecurringAmountInputElement() {
204
205    var retVal = null;
206
207    for (var x = 0; x < WebFormContext.Form.Fields.length; x++)
208        if (WebFormContext.Form.Fields[x].DataMapping.RecurringAmount && !isBlank(WebFormContext.Form.Fields[x].DomId))
209            retVal = document.getElementById(WebFormContext.Form.Fields[x].DomId);
210
211    return retVal; 
212
213}
214 
215function getInKindTypeElement() {
216
217    var retVal = null;
218
219    for (var x = 0; x < WebFormContext.Form.Fields.length; x++)
220        if (WebFormContext.Form.Fields[x].DataMapping.InKindType && !isBlank(WebFormContext.Form.Fields[x].DomId))
221            retVal = document.getElementById(WebFormContext.Form.Fields[x].DomId);                    
222
223    return retVal;
224
225}
226
227function getTributeTypeDomId() {
228
229    var retVal = '';
230
231    for (var x = 0; x < WebFormContext.Form.Fields.length; x++)
232        if (WebFormContext.Form.Fields[x].Type.Id == 24 && !isBlank(WebFormContext.Form.Fields[x].DomId)) { 
233            retVal = WebFormContext.Form.Fields[x].DomId;                    
234            break;
235        }
236
237    return retVal;
238
239}
240
241function getTributeTypeElement() {     
242    return document.getElementById(getTributeTypeDomId());
243}
244
245function getTributeNameDomId() {
246
247    var retVal = '';
248
249    for (var x = 0; x < WebFormContext.Form.Fields.length; x++)
250        if (WebFormContext.Form.Fields[x].Type.Id == 25 && !isBlank(WebFormContext.Form.Fields[x].DomId)) { 
251            retVal = WebFormContext.Form.Fields[x].DomId;                      
252            break;
253        }
254
255    return retVal;
256
257}
258
259function getTributeNameElement() {     
260    return document.getElementById(getTributeNameDomId());
261}
262
263function legacyAmountClickerHandler() {
264
265    console.log('**STD THM: legacy amount clicker');
266
267    var idxAttr = $(this).attr('data-index');
268    var indexVal = idxAttr != null ? idxAttr : $(this).parent().attr('data-index');
269
270    var chosenFrequency = $('.frequencyOptionsContainer input:checked label').text();
271    var giftStringContainer = '';
272    if (chosenFrequency == 'One-Time')
273        giftStringContainer = '.One-TimeAmount';
274    else if (chosenFrequency == 'Monthly')
275        giftStringContainer = '.MonthlyAmount';
276
277    setPaymentAmountUIByIndex(indexVal, giftStringContainer);
278
279    legacyAmountChangedPaymentSectionToggle();            
280
281}
282
283function initializeAmountTextbox(amountField) {
284
285    //no double tappity tappy
286    if (amountField != null && document.getElementById('amountCurrencyAddon') == null) {   
287        
288        amountField.setAttribute('placeholder', '0.00');
289        amountField.insertAdjacentHTML('beforebegin', '<span id="amountCurrencyAddon">' + getCurrencySymbol() + '</span>');
290
291        var amountFieldCurrencyAddon = document.getElementById('amountCurrencyAddon');
292        if (amountFieldCurrencyAddon != null) {
293            amountFieldCurrencyAddon.innerText = getCurrencySymbol();
294            amountField.style.setProperty('padding-left', (amountFieldCurrencyAddon.offsetWidth + 10) + 'px', 'important');
295        }
296
297    }
298
299}
300
301function initializePaymentAmountSection(eventData) {
302
303    console.log('**STD THM: init payment amount section'); 
304
305    //add key up event to amount field if its a textbox (4.1.2023)
306    //note: this can be removed if needed as it is an optional belt & suspenders for certain browsers and duplciates change event
307    var amtTb = getAmountInputElement();    
308    if (amtTb != null && amtTb.tagName.toLowerCase() == 'input' && amtTb.getAttribute('type') != null && amtTb.getAttribute('type').toLowerCase() == 'text') {
309        
310        amtTb.addEventListener('keyup', function () { console.log('**STD THM: standard theme key up button refresh event to amount input'); callUIUpdatesForAmountOrPaymentChange(); });
311
312    }
313
314    //add key up to recurring amount field (4.26.2023)
315    var recAmtTb = getRecurringAmountInputElement();
316    if (recAmtTb != null && recAmtTb.tagName.toLowerCase() == 'input' && recAmtTb.getAttribute('type') != null && recAmtTb.getAttribute('type').toLowerCase() == 'text') {
317        
318        recAmtTb.addEventListener('keyup', function () { console.log('**STD THM: standard theme key up button refresh event to recurring amount input'); callUIUpdatesForAmountOrPaymentChange(); });
319
320    }
321
322    //bind user interaction events
323    if (Form.amountSection.isAmountBlockPresent())
324    {
325
326        console.log('**STD THM: framework gift string event config');
327
328        //miscellaneous defaults, styling & DOM manipulation       
329        if(!isBlank(Form.amountSection.getAmountFieldDomID()))
330            amountField = document.getElementById(Form.amountSection.getAmountFieldDomID());
331
332        if (amountField != null)
333        { 
334
335            var oneTimeAmounts = Form.amountSection.getOneTimeAmounts();
336            if (oneTimeAmounts != null)
337                addFrequencyGiftStringHtml(amountField, 'oneTimeGiftAmountContainer', oneTimeAmounts);                             
338
339            var dailyAmounts = Form.amountSection.getDailyAmounts();
340            if(dailyAmounts != null)
341                addFrequencyGiftStringHtml(amountField, 'dailyGiftAmountContainer', dailyAmounts);
342
343            var weeklyAmounts = Form.amountSection.getWeeklyAmounts();
344            if (weeklyAmounts != null)
345                addFrequencyGiftStringHtml(amountField, 'weeklyGiftAmountContainer', weeklyAmounts);
346
347            var biMonthlyAmounts = Form.amountSection.getBiMonthlyAmounts();
348            if (biMonthlyAmounts != null)
349                addFrequencyGiftStringHtml(amountField, 'biMonthlyGiftAmountContainer', biMonthlyAmounts);
350
351            var monthlyAmounts = Form.amountSection.getMonthlyAmounts();
352            if (monthlyAmounts != null)
353                addFrequencyGiftStringHtml(amountField, 'monthlyGiftAmountContainer', monthlyAmounts);                             
354
355            var quarterlyAmounts = Form.amountSection.getQuarterlyAmounts();
356            if (quarterlyAmounts != null)
357                addFrequencyGiftStringHtml(amountField, 'quarterlyGiftAmountContainer', quarterlyAmounts);
358
359            var biAnnualAmounts = Form.amountSection.getBiAnnualAmounts();
360            if (biAnnualAmounts != null)
361                addFrequencyGiftStringHtml(amountField, 'biAnnualGiftAmountContainer', biAnnualAmounts);
362
363            var annualAmounts = Form.amountSection.getAnnualAmounts();
364            if (annualAmounts != null)
365                addFrequencyGiftStringHtml(amountField, 'annualGiftAmountContainer', annualAmounts);
366
367        }
368         
369        var frequencyField = document.getElementById(Form.amountSection.getFrequencyFieldDomID());
370        if (frequencyField != null)  
371            refreshAmountStringUIByFrequency(frequencyField.value, false); 
372
373        //if (amountField != null)        
374        //    initializeAmountTextbox(amountField);         
375
376        if (WebFormContext.Form.Type.Id == FORM_TYPES.Pledge && Form.amountSection.getSectionContainer() != null) {
377
378            var pledgeDate = Form.amountSection.getSectionContainer().querySelector('.isRecurringStartDate');
379
380            if (pledgeDate != null) {
381                
382                pledgeDate.setAttribute('placeholder', nowFormattedMMDDYYYYLeadingZeroes());
383                autoAddSlashesToDateField(pledgeDate);
384
385            }
386
387        }
388
389        //IMPORTANT: this never fires because there are no calls in this teme to Form.setDonationAmount(amount,freqId)!!! (11.9.2024)
390        Form.amountSection.onAmountChanged(function (evData) {
391
392            var amount = getDonationAmount();
393
394            console.log('**STD THM: standard theme amount change event handler: ' + amount);
395
396            if (amount != null) {
397
398                switch (evData.frequencyId.toString()) {
399                    case DONATION_FREQUENCIES.ONE_TIME.toString():
400                        highlightChosenAskStringOptionOnDonorClick(amount, 'oneTimeGiftAmountContainer');
401                        break;
402                    case DONATION_FREQUENCIES.DAILY.toString():
403                        highlightChosenAskStringOptionOnDonorClick(amount, 'dailyGiftAmountContainer');
404                        break;
405                    case DONATION_FREQUENCIES.WEEKLY.toString():
406                        highlightChosenAskStringOptionOnDonorClick(amount, 'weeklyGiftAmountContainer');
407                        break;
408                    case DONATION_FREQUENCIES.BIMONTHLY.toString():
409                        highlightChosenAskStringOptionOnDonorClick(amount, 'biMonthlyGiftAmountContainer');
410                        break;
411                    case DONATION_FREQUENCIES.MONTHLY.toString():
412                        highlightChosenAskStringOptionOnDonorClick(amount, 'monthlyGiftAmountContainer');
413                        break;
414                    case DONATION_FREQUENCIES.QUARTERLY.toString():
415                        highlightChosenAskStringOptionOnDonorClick(amount, 'quarterlyGiftAmountContainer');
416                        break;
417                    case DONATION_FREQUENCIES.BIANNUALLY.toString():
418                        highlightChosenAskStringOptionOnDonorClick(amount, 'biAnnualGiftAmountContainer');
419                        break;
420                    case DONATION_FREQUENCIES.ANNUALLY.toString():
421                        highlightChosenAskStringOptionOnDonorClick(amount, 'annualGiftAmountContainer');
422                        break;
423                }
424
425            }
426
427            callUIUpdatesForAmountOrPaymentChange();
428
429        });
430
431    }
432    else //needed for event forms that don't use the system block for the additioal donation section
433    {
434
435        //WOW - do not ever follow this pattern of gross jquery reaping with no API support.  Only thing I see missing is a few setTimeout hacks.
436
437        console.log('**STD THM: legacy gift string setup');
438
439        // bind click events for donation radio buttons (isCost list)
440        $('.isCost.tsRadioButtonLists label').on('click', legacyAmountClickerHandler);
441        $('.isCost.tsRadioButtonLists input[type="radio"]').on('click', legacyAmountClickerHandler);
442
443        // bind blur, input, and keyup events for custom donation amount text input
444        $('.isCost.tsRadioButtonLists span[data-other="other"] + input')
445            .on('blur', legacyAmountClickerHandler)
446            .on('input keyup', legacyAmountClickerHandler);
447
448        // set placeholder on custom donation input
449        $('.isCost.tsRadioButtonLists span[data-other="other"] + input').attr('placeholder', '0');
450
451        if ($('.TicketSectionContainer').length)
452        {
453
454            if (themeUIStateConfig.EventAdditionalDonationOn) 
455                setPaymentAmountUIByIndex(themeUIStateConfig.SelectedAmountOptionIndex, '.DonationAmount');
456            else
457                themeUIStateConfig.SelectedAmountOptionIndex = -1;
458
459        }
460
461    }
462
463    updateCurrencySymbol();
464
465    console.log('**STD THM: intialize theme amount and currency input styles');
466
467    var currencyDropdown = Form.GetCurrencyFieldElement();
468    if (currencyDropdown != null)
469    {
470       
471        //hide currency selector if there are not more than one
472        if (currencyDropdown.options.length <= 1)
473            currencyDropdown.vanish();
474
475        currencyDropdown.addEventListener('change', function () {
476            updateCurrencySymbol();
477        });
478
479    }
480     
481    var amtInputTmp = getAmountInputElement(); 
482    if (amtInputTmp != null)
483        initializeAmountTextbox(amtInputTmp); 
484
485    if (amtInputTmp != null && currencyDropdown != null && currencyDropdown.options.length > 1) {
486
487        var amtRowContainer = getFirstParentWithClass(amtInputTmp, 'tsFormRows');
488        var curRowContainer = getFirstParentWithClass(currencyDropdown, 'tsFormRows');
489         
490        if (amtRowContainer != null && curRowContainer != null) {
491                         
492            amtRowContainer.addClassNames('half first');
493            curRowContainer.addClassNames('half last');
494
495        }         
496
497        if (amtRowContainer.id == curRowContainer.id)
498            amtRowContainer.setAttribute('style', 'display: flex; width: 100%; gap: 10px; margin-right: 0px;');  
499
500    }
501
502}
503
504function legacyAmountChangedPaymentSectionToggle() {
505
506    console.log('**STD THM: LEGACY LEGACY LEGACY, EVENT FORM ZERO amount changed to: ' + Form.GetTransactionAmount());
507    //console.log('legacy amount changed pay section id: ' + document.getElementById(Form.paymentSection.getSectionContainerId()).style.display);
508
509    if (Form.GetTransactionAmount() > 0)
510        showPaymentSection();
511    else
512        hidePaymentSection();
513
514    callUIUpdatesForAmountOrPaymentChange();
515
516}
517
518function updateCurrencySymbol() {
519
520    console.log('**STD THM: update currency symbol');
521
522    var giftBtns = document.querySelectorAll('.giftAmountBtn');
523    if (giftBtns != null)  
524        for (var i = 0; i < giftBtns.length; i++) 
525            giftBtns[i].setAttribute('data-currency', getCurrencySymbol());
526
527    //var amountFieldCurrencyAddon = document.getElementById('amountCurrencyAddon');
528    //if (amountFieldCurrencyAddon != null && amountField != null) {
529    //    amountFieldCurrencyAddon.innerText = getCurrencySymbol();
530    //    amountField.style.setProperty('padding-left', (amountFieldCurrencyAddon.offsetWidth + 10) + 'px', 'important');
531    //}
532         
533    callUIUpdatesForAmountOrPaymentChange();
534
535}
536 
537function getCurrencySymbol() {
538
539    var currencySymbol = Form.amountSection.getCurrency();
540
541    var curDd = Form.GetCurrencyFieldElement();
542    if (curDd != null && curDd.options.length > 1)
543    {
544        var selectedCurrency = curDd.value;
545        currencySymbol = currencyMap[selectedCurrency].Symbol;
546    }
547
548    return currencySymbol;
549
550}
551
552function updateAmountTextBoxOnBtnClick(amount) {
553
554    if (amountField != null)
555    {
556        amountField.value = amount;
557        amountField.dispatchEvent(new Event('change'));
558    }
559
560}
561
562function getPaymentButtonByIndex(optionIndex, giftStringContainer) {
563
564    var retVal = null;
565
566    var daOptions = document.querySelectorAll(giftStringContainer + '.isCost.tsRadioButtonLists span');
567    if (daOptions != null && daOptions.length > 0)
568        for (var x = 0; x < daOptions.length; x++)
569            if (daOptions[x].getAttribute('data-index') == optionIndex.toString())
570            {
571                retVal = daOptions[x];
572                break;
573            }
574
575    return retVal;
576
577}
578
579function setPaymentAmountUIByIndex(optionIndex, giftStringContainer) {
580
581    console.log('**STD THM: payment amount UI set called with index: ' + optionIndex);
582
583    themeUIStateConfig.SelectedAmountOptionIndex = optionIndex;
584
585    //clear all    
586    $(giftStringContainer + '.isCost.tsRadioButtonLists label').removeClass('active');
587
588    var selOpt = getPaymentButtonByIndex(optionIndex, giftStringContainer);
589
590    if (selOpt != null)
591    {
592
593        var selOptLab = selOpt.querySelector('label');
594        selOptLab.addClassName('active');
595
596        //let's make sure we select the actual form field because Jquery and its injections are just an overlay, right?
597        var selOptFld = selOpt.querySelector('input[type="radio"]');
598
599        //console.log('fld.id: ' + selOptFld.id);        
600        selOptFld.checked = true;
601
602        var prntIdId = selOpt.parentNode.id.replace('ctl00_', '');
603        var onChangeFuncName = 'on_' + prntIdId + '_changed';
604
605        eval(onChangeFuncName + '(getPaymentButtonByIndex(optionIndex, giftStringContainer))');
606
607        //toggle other option text box        
608        if (selOptLab.innerText.toLowerCase() == 'other')
609            $(giftStringContainer + '.tsRadioButtonLists span[data-other="other"] + input').show();
610        else
611            $(giftStringContainer + '.tsRadioButtonLists span[data-other="other"] + input').hide();
612
613    }
614    else
615    {
616        console.log('**STD THM: no selected option returned for index: ' + optionIndex);
617        $('label.DonationAmount + input[type="hidden"]').val(-1);
618    }
619
620    if (Form.paymentSection.isPaymentBlockPresent()) 
621        Form.paymentSection.updateProcessingFees(); 
622
623    callUIUpdatesForAmountOrPaymentChange();
624
625}
626
627function getRecurringOptionCount() {
628
629    var retVal = 0;
630
631    if (frequencyDropdown != null)
632        for (var x = 0; x < frequencyDropdown.options.length; x++)
633            if (frequencyDropdown.options[x].value.toIntZeroIfInvalid() > 0)
634                retVal++;
635
636    return retVal;
637
638}
639
640function getFirstRecurringOptionText() {
641
642    var retVal = '';
643
644    if (getRecurringOptionCount() == 1)
645        for (var x = 0; x < frequencyDropdown.options.length; x++)
646            if (frequencyDropdown.options[x].value.toIntZeroIfInvalid() > 0) { 
647                retVal = frequencyDropdown.options[x].text;
648                break;
649            }
650
651    return retVal;
652
653}
654
655function initializePaymentFrequencySection() {
656
657    if (frequencyRow != null && frequencyRow.querySelector('label') != null) 
658        frequencyRow.querySelector('label').vanish();    
659
660    if (frequencyDropdown != null) {
661
662        frequencyDropdown.insertAdjacentHTML('beforeBegin', '<span class="frequencyOptionsContainer"><input class="frequencyOptions" id="phantom_frequency_onetime" type="radio" name="frequencyOption"><label id="phantom_frequency_onetime_btn" for="phantom_frequency_onetime">
662One Time</label></span>');
663
664        var recurringToggleText = 'Recurring';
665
666        if (getRecurringOptionCount() == 1)
667            recurringToggleText = getFirstRecurringOptionText();
668
669        frequencyDropdown.insertAdjacentHTML('beforeBegin', '<span class="frequencyOptionsContainer"><input class="frequencyOptions" id="phantom_frequency_recurring" type="radio" name="frequencyOption"><label id="phantom_frequency_recurring_btn" for="phantom_frequency_recurring">' + recurringToggleText + '</label></span>');
670
671        var oneTimeOption = getDropDownOptionByValue(frequencyDropdown, 0);
672        if (oneTimeOption != null) 
673            oneTimeOption.vanish(); //don't show one-time option in dropdown        
674        else if (document.getElementById('phantom_frequency_onetime_btn') != null) {
675
676            document.getElementById('phantom_frequency_onetime_btn').vanish();
677
678            if (document.getElementById('phantom_frequency_recurring_btn') != null)
679            {
680                document.getElementById('phantom_frequency_recurring_btn').addClassName('w-100');
681                document.getElementById('phantom_frequency_recurring_btn').addClassName('ml-0');
682            }
683
684        }
685
686        frequencyDropdown.vanish(); //hide by default
687
688        var defaultFrequency = Form.amountSection.getDonationFrequencyId();
689        if (defaultFrequency == DONATION_FREQUENCIES.ONE_TIME) {
690            document.querySelector('#phantom_frequency_onetime').checked = true;
691            frequencyDropdown.vanish();
692        }
693        else {
694            document.querySelector('#phantom_frequency_recurring').checked = true;
695            showFrequencyDropDownIfMoreThanOne();
696        }
697
698        //bind user interaction events
699        frequencyDropdown.addEventListener('change', function () {
700            console.log('**STD THM: payment frequency changed event');
701            callUIUpdatesForAmountOrPaymentChange();
702        });
703
704        var selectedRecurringAmount = 0;
705
706        document.getElementById('phantom_frequency_onetime').addEventListener('change', function () {
707
708            //save selected recurring frequency before changing 
709            selectedRecurringAmount = frequencyDropdown.getValue();
710
711            setFrequencyUIState(DONATION_FREQUENCIES.ONE_TIME);
712
713            frequencyDropdown.vanish();
714
715        });
716
717        document.getElementById('phantom_frequency_recurring').addEventListener('change', function () {
718
719            if (selectedRecurringAmount > 0) 
720                setFrequencyUIState(selectedRecurringAmount); //select frequency user set before toggling to one time            
721            else 
722                setFrequencyUIState(frequencyDropdown.options[1].value); //select first recurring frequency            
723
724            showFrequencyDropDownIfMoreThanOne();
725
726        });
727
728    }
729
730    if (Form.amountSection.isAmountBlockPresent() && Form.paymentSection.isPaymentBlockPresent())
731    {
732
733        //when changed
734        Form.amountSection.onFrequencyChanged(function (eventData) {
735             
736            adjustThemePayPalToggleForFrequency(eventData.frequencyId);
737            adjustThemeApplePalToggleForFrequency(eventData.frequencyId);
738            adjustThemeDafPayToggleForFrequency(eventData.frequencyId);
739
740        });
741         
742        //on form load
743        adjustThemePayPalToggleForFrequency(Form.amountSection.getDonationFrequencyId());
744        adjustThemeApplePalToggleForFrequency(Form.amountSection.getDonationFrequencyId());
745        adjustThemeDafPayToggleForFrequency(Form.amountSection.getDonationFrequencyId());
746
747    }
748
749}
750
751function showFrequencyDropDownIfMoreThanOne() {
752
753    if(getRecurringOptionCount() > 1)
754        frequencyDropdown.show();
755
756}
757
758function adjustThemePayPalToggleForFrequency(frequencyId) {
759
760    if (frequencyId != DONATION_FREQUENCIES.ONE_TIME && !WebFormContext.PaymentSectionMetaData.EnablePayPalSubscriptions)
761        hidePayPalOptions();
762    else { 
763        showPayPalToggle(frequencyId);
764        payPalApi.RefreshButton(); //required to toggle paypal buttons for one-time vs. recurring
765    }
766
767}
768
769function adjustThemeApplePalToggleForFrequency(frequencyId) {
770
771    if (frequencyId != DONATION_FREQUENCIES.ONE_TIME && !WebFormContext.PaymentSectionMetaData.EnableApplePaySubscriptions)                 
772        hideApplePayOptions();            
773    else
774        showApplePayToggle(); 
775
776}
777
778function adjustThemeDafPayToggleForFrequency(frequencyId, checkCurrency = true) {
779
780    if (frequencyId != DONATION_FREQUENCIES.ONE_TIME)
781        hideDafPayOptions();
782    else {
783        showDafPayToggle();
784
785        if (checkCurrency)
786            adjustThemeDafPayToggleForCurrency(Form.GetCurrencyId(), false)
787    }
788        
789
790}
791
792function adjustThemeDafPayToggleForCurrency(currencyId, checkFrequency = true) {
793
794    if (currencyId != 15)
795        hideDafPayOptions();
796    else {
797        showDafPayToggle();
798
799        if (checkFrequency)
800            adjustThemeDafPayToggleForFrequency(Form.amountSection.getDonationFrequencyId(), false);
801    }
802        
803}
804
805function initializeContactInfoSection() {
806
807    var contactSection = Form.contactSection.getSectionContainer();
808
809    //TODO: look at why when you hide a field, it still shows the label and row
810    if (contactSection != null) {
811
812        //toggle phone field row display based Show Phone Number config
813        if (contactSection.querySelector('.isPhone') != null) 
814            getFirstParentWithClass(contactSection.querySelector('label.PhoneNumber'), 'tsFormRows').show();        
815        else
816        {
817
818            if (contactSection.querySelector('label.PhoneNumber') != null) 
819                getFirstParentWithClass(contactSection.querySelector('label.PhoneNumber'), 'tsFormRows').vanish();            
820
821        }
822
823        //toggle phone field type row display based Show Phone Number config
824        if (contactSection.querySelector('.tsPhoneClassSelectors ') != null) 
825            getFirstParentWithClass(contactSection.querySelector('label.PhoneType'), 'tsFormRows').show();        
826        else {
827
828            if (contactSection.querySelector('label.PhoneType') != null) 
829                getFirstParentWithClass(contactSection.querySelector('label.PhoneType'), 'tsFormRows').vanish();            
830
831        }
832
833        //toggle contact type and org field row display based Allow Donate as Org config
834        if (contactSection.querySelector('.isDonorCompanyName') != null && contactSection.querySelector('.tsDropDownLists_sysContactTypes') != null) {
835
836            getFirstParentWithClass(contactSection.querySelector('.tsDropDownLists_sysContactTypes'), 'tsFormRows').show();
837            getFirstParentWithClass(contactSection.querySelector('label.OrganizationName'), 'tsFormRows').show();
838
839            var contactTypeDD = contactSection.querySelector('.tsDropDownLists_sysContactTypes');
840            if (contactTypeDD != null && contactTypeDD.tagName.toLowerCase() == 'select') {
841
842                //hide household
843                var householdDropDownElem = getDropDownOptionByValue(contactTypeDD, 3);
844                if(householdDropDownElem != null)
845                    householdDropDownElem.vanishOption();
846
847                toggleOrgNameFieldDisplay(contactTypeDD.value);
848
849                contactTypeDD.addEventListener('change', function () {
850
851                    toggleOrgNameFieldDisplay(contactTypeDD.value);
852
853                });
854
855            }
856
857        }
858        else
859        {
860
861            if (contactSection.querySelector('.tsDropDownLists_sysContactTypes') != null)
862                getFirstParentWithClass(contactSection.querySelector('.tsDropDownLists_sysContactTypes'), 'tsFormRows').vanish();
863
864            if (contactSection.querySelector('label.OrganizationName') != null)
865                getFirstParentWithClass(contactSection.querySelector('label.OrganizationName'), 'tsFormRows').vanish();
866
867        }
868
869    }
870
871}
872
873function toggleOrgNameFieldDisplay(contactType) {
874
875    var firstNameInputElem = Form.contactSection.getSectionContainer().querySelector('input.isDonorFirstName');
876    var lastNameInputElem = Form.contactSection.getSectionContainer().querySelector('input.isDonorLastName');
877
878    var orgNameInputElem = Form.contactSection.getSectionContainer().querySelector('input.isDonorCompanyName');
879
880    if (contactType == 2) {  //person        
881
882        if (firstNameInputElem != null && lastNameInputElem != null) {
883            enableOrDisableRequiredValidator(firstNameInputElem, 'enable');
884            enableOrDisableRequiredValidator(lastNameInputElem, 'enable');
885        }
886
887        if (orgNameInputElem != null)
888        { 
889            getFirstParentWithClass(orgNameInputElem, 'tsFormRows').vanish();
890            orgNameInputElem.value = '';
891            enableOrDisableRequiredValidator(orgNameInputElem, 'disable');
892        }
893
894    }
895    else
896    {
897        
898        if (firstNameInputElem != null && lastNameInputElem != null) {
899            enableOrDisableRequiredValidator(firstNameInputElem, 'disable');
900            enableOrDisableRequiredValidator(lastNameInputElem, 'disable');
901        }
902
903        if (orgNameInputElem != null) { 
904            getFirstParentWithClass(orgNameInputElem, 'tsFormRows').show();
905            enableOrDisableRequiredValidator(orgNameInputElem, 'enable');
906        }
907
908    }
909
910}
911
912function hidePayPalToggle() {
913
914    if (paypalToggleContainer != null)
915        paypalToggleContainer.vanish();
916
917}
918
919function showPayPalToggle(frequencyId) {
920
921    //pledge and membership not supported for now because we need to allow capture of billing id without processing (5.13.2023)
922    if (paypalToggleContainer != null && WebFormContext.Form.Type.Id != FORM_TYPES.Pledge && WebFormContext.Form.Type.Id != FORM_TYPES.Membership) {
923
924        paypalToggleContainer.show();
925
926        if (frequencyId != null && paypalToggleContainer != null) {
927
928            if (frequencyId == DONATION_FREQUENCIES.MONTHLY && paypalToggleContainer.querySelector('#paypalToggleLabel') != null)
929                paypalToggleContainer.querySelector('#paypalToggleLabel').innerText = "PayPal";
930            else if (payPalApi.PaypalVenmoCheckOutEnabled && frequencyId == DONATION_FREQUENCIES.ONE_TIME && paypalToggleContainer.querySelector('#paypalToggleLabel') != null)
931                paypalToggleContainer.querySelector('#paypalToggleLabel').innerText = "PayPal/Venmo";
932
933        }
934
935    }
936}
937
938function hidePayPalOptions() {
939
940    hidePayPalToggle();
941    payPalApi.HideButton();
942
943    //reset form of payment if paypal is currently displayed
944    var curPayMethodId = Form.PaymentSection.GetSelectedPaymentMethodId();
945    if (curPayMethodId == PAYMENT_METHODS.PAYPAL.toString())
946        resetPaymentMethodForUnknownSelection();
947
948}
949
950function showGooglePayToggle() {
951    
952    if (document.getElementById('googlePayToggleContainer') != null)
953        document.getElementById('googlePayToggleContainer').show();
954
955}
956
957function hideGooglePayToggle() {
958    
959    if (document.getElementById('googlePayToggleContainer') != null)
960        document.getElementById('googlePayToggleContainer').vanish();
961
962}
963
964function hideGooglePayOptions() {
965    hideGooglePayToggle();
966    googlePayApi.HideButton();
967}
968
969function showApplePayToggle() {
970
971    if (document.getElementById('applePayToggleContainer') != null)
972        document.getElementById('applePayToggleContainer').show();
973
974}
975
976function hideApplePayToggle() {
977
978    if (document.getElementById('applePayToggleContainer') != null)
979        document.getElementById('applePayToggleContainer').vanish();
980
981}
982
983function hideApplePayOptions() {
984
985    hideApplePayToggle();
986    applePayApi.HideButton();
987
988    //reset form of payment if apply pay is currently displayed
989    var curPayMethodId = Form.PaymentSection.GetSelectedPaymentMethodId();
990    if (curPayMethodId == PAYMENT_METHODS.CREDIT_CARD.toString()) { 
991
992        var activeToggleBtn = getActivePaymentToggleButton();
993        if(activeToggleBtn != null && activeToggleBtn.getAttribute('data-walletTypeId') != null && elem.getAttribute('data-walletTypeId').toIntZeroIfInvalid().toString() == WALLET_TYPES.APPLE_PAY.toString())
994            resetPaymentMethodForUnknownSelection();
995
996    }
997
998}
999
1000function showDafPayToggle() {
1001
1002    if (document.getElementById('dafPayToggleContainer') != null)
1003        document.getElementById('dafPayToggleContainer').show();
1004
1005}
1006
1007function hideDafPayToggle() {
1008
1009    if (document.getElementById('dafPayToggleContainer') != null)
1010        document.getElementById('dafPayToggleContainer').vanish();
1011
1012}
1013
1014function hideDafPayOptions() {
1015
1016    hideDafPayToggle();
1017    dafPayApi.HideButton();
1018
1019    //reset form of payment if dafpay is currently displayed
1020    var curPayMethodId = Form.PaymentSection.GetSelectedPaymentMethodId();
1021    console.log('**STD THM: Hide Daf Pay current payment method: ' + curPayMethodId);
1022    if (curPayMethodId == PAYMENT_METHODS.SOFT_CREDIT.toString())
1023        resetPaymentMethodForUnknownSelection();
1024
1025}
1026
1027function setFrequencyUIState(frequencyId) {
1028
1029    console.log('**STD THM: set frequency state: ' + frequencyId);
1030
1031    themeUIStateConfig.SelectedFrequencyId = frequencyId;
1032
1033    if (Form.AmountSection.isAmountBlockPresent())
1034    {
1035
1036        refreshAmountStringUIByFrequency(frequencyId, true);
1037         
1038        Form.AmountSection.setFrequency(frequencyId);
1039                 
1040    }
1041    else
1042    {
1043        
1044        setSelectedValue(frequencyDropdown, frequencyId);
1045
1046        if(document.getElementById(frequencyDropdown.id + '_selectedIndexValue') != null)
1047            document.getElementById(frequencyDropdown.id + '_selectedIndexValue').value = frequencyDropdown.selectedIndex;
1048 
1049    }
1050
1051    //explicit change event fires and handles this if the form has amount and payment section
1052    if (!Form.AmountSection.isAmountBlockPresent() || !Form.paymentSection.isPaymentBlockPresent()) {
1053        adjustThemePayPalToggleForFrequency(frequencyId);
1054        adjustThemeApplePalToggleForFrequency(frequencyId);
1055        adjustThemeDafPayToggleForFrequency(frequencyId);
1056    }
1057
1058    if (Form.paymentSection.isPaymentBlockPresent()) 
1059        Form.paymentSection.updateProcessingFees(); 
1060
1061    callUIUpdatesForAmountOrPaymentChange();
1062
1063}
1064
1065function handleFrequencyChangedCallback() {
1066
1067    var frequencyField = document.getElementById(Form.amountSection.getFrequencyFieldDomID());
1068    if (frequencyField != null)
1069        refreshAmountStringUIByFrequency(frequencyField.value, true);
1070
1071}
1072
1073function refreshAmountStringUIByFrequency(frequencyId, isUserInitiatiedChange) {
1074
1075    //do NOT reset the amount on confirmation pages or when hitting the back button
1076    if (isUserInitiatiedChange && document.getElementById(Form.amountSection.getAmountFieldDomID()) != null) 
1077        document.getElementById(Form.amountSection.getAmountFieldDomID()).value = Form.amountSection.getDefaultAmountForFrequency(frequencyId);    
1078
1079    var oneTimeGiftBtnContainer = document.getElementById('oneTimeGiftAmountContainer');
1080    var dailyGiftBtnContainer = document.getElementById('dailyGiftAmountContainer');
1081    var weeklyGiftBtnContainer = document.getElementById('weeklyGiftAmountContainer');
1082    var biMonthlyGiftBtnContainer = document.getElementById('biMonthlyGiftAmountContainer');
1083    var monthlyGiftBtnContainer = document.getElementById('monthlyGiftAmountContainer');
1084    var quarterlyGiftBtnContainer = document.getElementById('quarterlyGiftAmountContainer');
1085    var biAnnualGiftBtnContainer = document.getElementById('biAnnualGiftAmountContainer');
1086    var annualGiftBtnContainer = document.getElementById('annualGiftAmountContainer');
1087     
1088    //hide all
1089    if (oneTimeGiftBtnContainer != null) oneTimeGiftBtnContainer.vanish();
1090    if (dailyGiftBtnContainer != null) dailyGiftBtnContainer.vanish();
1091    if (weeklyGiftBtnContainer != null) weeklyGiftBtnContainer.vanish();
1092    if (biMonthlyGiftBtnContainer != null) biMonthlyGiftBtnContainer.vanish();
1093    if (monthlyGiftBtnContainer != null) monthlyGiftBtnContainer.vanish();
1094    if (quarterlyGiftBtnContainer != null) quarterlyGiftBtnContainer.vanish();
1095    if (biAnnualGiftBtnContainer != null) biAnnualGiftBtnContainer.vanish();
1096    if (annualGiftBtnContainer != null) annualGiftBtnContainer.vanish();
1097
1098    var defaultAmtVal = Form.amountSection.getDefaultAmountForFrequency(frequencyId);
1099
1100    switch (frequencyId.toString()) {
1101        case DONATION_FREQUENCIES.ONE_TIME.toString():
1102            if (oneTimeGiftBtnContainer != null) oneTimeGiftBtnContainer.show();
1103            if (oneTimeGiftBtnContainer != null) setAskStringButtonStateByFrequency(oneTimeGiftBtnContainer, defaultAmtVal);
1104            break;
1105        case DONATION_FREQUENCIES.DAILY.toString():
1106            if (dailyGiftBtnContainer != null) dailyGiftBtnContainer.show();
1107            if (dailyGiftBtnContainer != null) setAskStringButtonStateByFrequency(dailyGiftBtnContainer, defaultAmtVal);
1108            break;
1109        case DONATION_FREQUENCIES.WEEKLY.toString():
1110            if (weeklyGiftBtnContainer != null) weeklyGiftBtnContainer.show();
1111            if (weeklyGiftBtnContainer != null) setAskStringButtonStateByFrequency(weeklyGiftBtnContainer, defaultAmtVal);
1112            break;
1113        case DONATION_FREQUENCIES.BIMONTHLY.toString():
1114            if (biMonthlyGiftBtnContainer != null) biMonthlyGiftBtnContainer.show();
1115            if (biMonthlyGiftBtnContainer != null) setAskStringButtonStateByFrequency(biMonthlyGiftBtnContainer, defaultAmtVal);
1116            break;
1117        case DONATION_FREQUENCIES.MONTHLY.toString():
1118            if (monthlyGiftBtnContainer != null) monthlyGiftBtnContainer.show();
1119            if (monthlyGiftBtnContainer != null) setAskStringButtonStateByFrequency(monthlyGiftBtnContainer, defaultAmtVal);
1120            break;
1121        case DONATION_FREQUENCIES.QUARTERLY.toString():
1122            if (quarterlyGiftBtnContainer != null) quarterlyGiftBtnContainer.show();
1123            if (quarterlyGiftBtnContainer != null) setAskStringButtonStateByFrequency(quarterlyGiftBtnContainer, defaultAmtVal);
1124            break;
1125        case DONATION_FREQUENCIES.BIANNUALLY.toString():
1126            if (biAnnualGiftBtnContainer != null) biAnnualGiftBtnContainer.show();
1127            if (biAnnualGiftBtnContainer != null) setAskStringButtonStateByFrequency(biAnnualGiftBtnContainer, defaultAmtVal);
1128            break;
1129        case DONATION_FREQUENCIES.ANNUALLY.toString():
1130            if (annualGiftBtnContainer != null) annualGiftBtnContainer.show();
1131            if (annualGiftBtnContainer != null) setAskStringButtonStateByFrequency(annualGiftBtnContainer, defaultAmtVal);
1132            break;
1133    }
1134     
1135}
1136
1137function setAskStringButtonStateByFrequency(askStringContainer, defaultAmt) {
1138
1139    var askBtns = askStringContainer.querySelectorAll('.giftAmountBtn');
1140    for (var i = 0; i < askBtns.length; i++) {
1141        askBtns[i].classList.remove('active');
1142        if (askBtns[i].getAttribute('data-value') == getDonationAmount()) //don't highlight if user entered custom amount and we're re-initalizing for confirmation page/hitting back button
1143            askBtns[i].classList.add('active');
1144    }
1145
1146}
1147
1148function inializeTributeSection() {
1149
1150    //note: this is an example of ovverridding the database functionality by adding business logic to not initialize the tribute section based on the step - i.e. if the database says show it on the confirmation page, this ignores that
1151    if (WebFormContext.Form.StepNumber != FORM_STEPS.PROCESS)
1152    {
1153         
1154        var tribSect = Form.getTributeSectionMetaData();
1155        if (tribSect != null && tribSect.Visible)
1156        {
1157
1158            //inject tribute selector above section
1159            $('.TributeSectionContainer').before('<div class="tsFormRows" id="tributeRow"><input id="tributeToggle" type="checkbox"><label for="tributeToggle">Dedicate this donation?</label></div>');
1160
1161            //bind user interaction events
1162            $('#tributeToggle').on('change', function () {
1163
1164                if ($(this).is(':checked'))
1165                    showTributeSection();
1166                else
1167                    hideTributeSection();
1168
1169            });
1170
1171            //set default state from UI state
1172            var tribToggleCb = document.getElementById('tributeToggle');
1173
1174            if (tribToggleCb != null)
1175            {
1176
1177                if (themeUIStateConfig.IsTributeGift)
1178                {
1179                    tribToggleCb.checked = true;
1180                    showTributeSection();
1181                }
1182                else
1183                {
1184                    tribToggleCb.checked = false;
1185                    hideTributeSection();
1186                }
1187
1188            }
1189
1190        }
1191        else
1192            console.log('**STD THM: do not initialize tribute section due to section render state');
1193
1194    }
1195
1196}
1197
1198function showTributeSection() {
1199
1200    //IMPORTANT - do not show for processed step!!!    
1201    if (WebFormContext.Form.StepNumber == 1 || WebFormContext.Form.StepNumber == 2)
1202    {
1203
1204        themeUIStateConfig.IsTributeGift = true;
1205
1206        $(tributeSection).slideDown();
1207
1208        //enable tribute section validators
1209        reqTributeFields.forEach(function (field) {
1210            enableOrDisableRequiredValidator(document.querySelector(field), 'enable');
1211        });
1212
1213        reShowTributeSectionInputs();
1214
1215        Form.FireTributeShownEvent();
1216
1217        Form.FireTributeVisibilityChangedEvent(true);
1218
1219    }
1220
1221}
1222
1223function hideTributeSection() {
1224
1225    themeUIStateConfig.IsTributeGift = false;
1226
1227    $(tributeSection).slideUp();
1228
1229    //disable tribute section validators
1230    reqTributeFields.forEach(function (field) {
1231        enableOrDisableRequiredValidator(document.querySelector(field), "disable");
1232    });
1233
1234    disableTributeAcknowledgeeEmailRequiredValidator();
1235
1236    Form.FireTributeHiddenEvent();
1237
1238    Form.FireTributeVisibilityChangedEvent(false);
1239
1240}
1241
1242function handleTributeAcknowledgementTypeClick(elem) {
1243
1244    if (elem != null) {
1245
1246        //clear jquery mayhem
1247        var rbElems = document.querySelectorAll('input.annoucementTypes');
1248        if (rbElems != null && rbElems.length > 0)
1249            for (var x = 0; x < rbElems.length; x++) {
1250                rbElems[x].setAttribute('checked', '');
1251                rbElems[x].nextSibling.removeClassName('active');
1252            }
1253
1254        //now check this one for jquery
1255        elem.setAttribute('checked', 'checked');
1256        elem.nextSibling.addClassName('active');
1257
1258        //set current state value
1259        setTributeAcknowledgmentUIState(elem.getAttribute('data-mode'));
1260
1261    }
1262
1263}
1264
1265function reShowTributeSectionInputs() {
1266
1267    setTributeAcknowledgmentUIState(getCurrentSelectedTributeDataModeAttributeOrDefault());
1268
1269}
1270
1271function getCurrentSelectedTributeDataModeAttributeOrDefault() {
1272
1273    var retVal = 'none';
1274
1275    var activeElem = document.querySelector('input.annoucementTypes:checked');
1276    if (activeElem != null)
1277        retVal = activeElem.getAttribute('data-mode');
1278
1279    return retVal;
1280
1281}
1282
1283function inializeTributeAcknowledgeeSection() {
1284
1285    var showEmailAck = true;
1286    var showMailAck = true;
1287
1288    var noAcknowledgementLabel = 'No Announcement';
1289    var emailAcknowledgementLabel = 'Email Announcement';
1290    var mailAcknowledgementLabel = 'Mail Announcement';    
1291
1292    console.log('STANDARD TH WebFormContext.TributeSectionMetaData: ' + WebFormContext.TributeSectionMetaData);
1293
1294    //check for form context
1295    if (WebFormContext.TributeSectionMetaData != null) {
1296
1297        showEmailAck = WebFormContext.TributeSectionMetaData.EnableEmailAcknowledgement;
1298        showMailAck = WebFormContext.TributeSectionMetaData.EnableMailAcknowledgement;
1299
1300        //special for none becuase no icon (5.8.2023)
1301        if(!isBlank(WebFormContext.TributeSectionMetaData.NoAcknowledgementLabel))
1302            noAcknowledgementLabel = WebFormContext.TributeSectionMetaData.NoAcknowledgementLabel;
1303
1304        emailAcknowledgementLabel = WebFormContext.TributeSectionMetaData.EmailAcknowledgementLabel;
1305        mailAcknowledgementLabel = WebFormContext.TributeSectionMetaData.MailAcknowledgementLabel;
1306
1307    }
1308
1309    console.log('STANDARD TH showEmailAck: ' + showEmailAck);
1310
1311    //inject tribute type selector buttons if enabled
1312    if (showEmailAck || showMailAck) {
1313
1314        var atr = document.createElement('div');
1315        atr.id = 'announcementToggleRow';
1316        atr.setAttribute('class', 'tsFormRows');
1317
1318        atr.innerHTML += '<span class="announcementTypeContainer"><input id="noToggle" class="annoucementTypes" type="radio" data-mode="none" onclick="handleTributeAcknowledgementTypeClick(this)"><label id="noToggleLabel" for="noToggle">' + noAcknowledgementLabel + '</label></span>';
1319
1320        if (showEmailAck)
1321            atr.innerHTML += '<span class="announcementTypeContainer"><input id="emailToggle" class="annoucementTypes" type="radio" data-mode="email" onclick="handleTributeAcknowledgementTypeClick(this)"><label id="emailToggleLabel" for="emailToggle">' + emailAcknowledgementLabel + '</label></span>';
1322        else
1323            themeUIStateConfig.TributeAcknowledgementMode = 'letter'; //reset to letter if no email
1324
1325        if (showMailAck)
1326            atr.innerHTML += '<span class="announcementTypeContainer"><input id="mailToggle" class="annoucementTypes" type="radio" data-mode="letter" onclick="handleTributeAcknowledgementTypeClick(this)"><label id="mailToggleLabel" for="mailToggle">' + mailAcknowledgementLabel + '</label></span>';
1327
1328        //major hack city here, probably Hogue - what happens if the hack stomp class "TributeName" is removed, WHO CARES - ITS THE FUCKING CATALINA WINE-MIXER, DALE!
1329        //why don't we look for our first-class section structure and build aroudn our system section layout versus this
1330        var tributeNameField = getTributeNameElement(); // document.querySelector('.Tribute_XX_Name');
1331
1332        console.log('STANDARD TH tributeNameField: ' + tributeNameField);
1333
1334        if (tributeNameField != null) {
1335
1336            var prnt = tributeNameField.firstParentWithClass('tsFormRows');
1337            if (prnt != null)
1338                prnt.after(atr);
1339
1340        }
1341         
1342        //set default state
1343        switch (themeUIStateConfig.TributeAcknowledgementMode) {
1344            case 'none':
1345                if (document.getElementById('noToggle') != null) { 
1346                    document.getElementById('noToggle').checked = true;
1347                    document.getElementById('noToggleLabel').addClassName('active');
1348                }
1349                break;
1350            case 'email':
1351                if (document.getElementById('emailToggle') != null) {
1352                    document.getElementById('emailToggle').checked = true;
1353                    document.getElementById('emailToggleLabel').addClassName('active');
1354                }
1355                break;
1356            case 'letter':
1357                if (document.getElementById('mailToggle') != null) {
1358                    document.getElementById('mailToggle').checked = true;
1359                    document.getElementById('mailToggleLabel').addClassName('active');
1360                }
1361                break;
1362        }
1363
1364    }
1365    else
1366        themeUIStateConfig.TributeAcknowledgementMode = 'none'; //reset to none if no options
1367        
1368    setTributeAcknowledgmentUIState(themeUIStateConfig.TributeAcknowledgementMode);
1369
1370}
1371
1372function disableTributeAcknowledgeeEmailRequiredValidator() {
1373         
1374    if (tributeAckEmailSection != null && tributeAckEmailSection[0] != null && document.getElementById(tributeAckEmailSection[0].id) != null) { 
1375
1376        var tributeEmailAddressField = document.getElementById(tributeAckEmailSection[0].id); //.querySelector('input.AcknowledgeeEmailAddress');        
1377        if(tributeEmailAddressField != null)
1378            enableOrDisableRequiredValidator(tributeEmailAddressField, 'disable');
1379
1380    }
1381
1382}
1383
1384function enableTributeAcknowledgeeEmailRequiredValidator() {
1385
1386    if (tributeAckEmailSection != null && tributeAckEmailSection[0] != null && document.getElementById(tributeAckEmailSection[0].id) != null) { 
1387
1388        var tributeEmailAddressField = document.getElementById(tributeAckEmailSection[0].id); //.querySelector('input.AcknowledgeeEmailAddress');
1389        if(tributeEmailAddressField != null)
1390            enableOrDisableRequiredValidator(tributeEmailAddressField, 'enable');
1391
1392    }
1393
1394}
1395
1396function hideJqueryLoopy(elemArray) {
1397
1398    if (elemArray != null)
1399        for (var x = 0; x < elemArray.length; x++)             
1400            elemArray[x].closest('.tsFormRows').vanish();        
1401
1402}
1403
1404function showJqueryLoopy(elemArray) {
1405
1406    if (elemArray != null)
1407        for (var x = 0; x < elemArray.length; x++)
1408            elemArray[x].closest('.tsFormRows').show();
1409
1410}
1411
1412function setTributeAcknowledgmentUIState(mode) {    
1413
1414    themeUIStateConfig.TributeAcknowledgementMode = mode;
1415
1416    //hide all by default
1417    hideJqueryLoopy(tributeAckNameSection); //$(tributeAckNameSection).hide();
1418    hideJqueryLoopy(tributeAckAddressSection);
1418 // $(tributeAckAddressSection).hide();
1419    hideJqueryLoopy(tributeAckEmailSection); //$(tributeAckEmailSection).hide();
1420    hideJqueryLoopy(tributeAckMessageSection); //$(tributeAckMessageSection).hide();
1421
1422    //always disable email validator if present
1423    disableTributeAcknowledgeeEmailRequiredValidator();
1424
1425    //console.log('STANDARD THEM TRIB MODE: ' + mode);
1426    switch (mode) {
1427        case 'email':
1428
1429            showJqueryLoopy(tributeAckNameSection); // $(tributeAckNameSection).show();
1430            showJqueryLoopy(tributeAckEmailSection); // $(tributeAckEmailSection).show();
1431            showJqueryLoopy(tributeAckMessageSection); // $(tributeAckMessageSection).show();
1432
1433            enableTributeAcknowledgeeEmailRequiredValidator();
1434
1435            break;
1436        case 'letter':
1437            showJqueryLoopy(tributeAckNameSection); // $(tributeAckNameSection).show();
1438            showJqueryLoopy(tributeAckAddressSection); // $(tributeAckAddressSection).show();
1439            showJqueryLoopy(tributeAckMessageSection); // $(tributeAckMessageSection).show();
1440            break;
1441    }
1442
1443}
1444
1445function handlePaymentMethodSelected(elem) {
1446
1447    //clear first 
1448    var ptElems = document.querySelectorAll('.paymentTypes');
1449    for (var x = 0; x < ptElems.length; x++)
1450    {
1451        ptElems[x].checked = false;
1452        ptElems[x].removeClassName('active');
1453        ptElems[x].nextSibling.removeClassName('active');
1454    }
1455
1456    elem.checked = true;
1457    elem.addClassName('active');
1458    elem.nextSibling.addClassName('active');
1459
1460    //check for payment types show hide 
1461    var elemPayTypeId = elem.getAttribute('data-paymentId');    
1462
1463    console.log('**STD THM: show hide button for payment METHOD: ' + elemPayTypeId);
1464 
1465    Form.ShowNextButton();            
1466
1467    if (elemPayTypeId != null) {
1468
1469        if (elemPayTypeId.toString() == PAYMENT_METHODS.PAYPAL.toString())
1470            Form.HideNextButton();      
1471        else 
1472            Form.ShowNextButton();   
1473
1474    }    
1475
1476    //hide for all wallets
1477    if (elem.getAttribute('data-walletTypeId') != null && elem.getAttribute('data-walletTypeId').toIntZeroIfInvalid() > 0) 
1478        Form.HideNextButton();            
1479 
1480    Form.paymentSection.setPaymentMethod(elem.getAttribute('data-paymentId'), elem.getAttribute('data-walletTypeId'));
1481
1482    //adding to account for some difficult to track donw legacy bad-brain Jquery that's overreaching and showing everything with a class outside of our code flow - typical nightmare pattern
1483    Form.paymentSection.hideNativePaymentMethodSelector();
1484
1485}
1486
1487function resetPaymentMethodForUnknownSelection() {
1488
1489    var curPayMethodId = Form.PaymentSection.GetSelectedPaymentMethodId();
1490
1491    console.log('**STD THM: reset payment method with current id: ' + curPayMethodId);
1492
1493    //zero is one-click
1494    var paymentToggleToUse = null;
1495
1496    if (curPayMethodId > 0)
1497        paymentToggleToUse = getVisiblePaymentToggleByPaymentMethodId(curPayMethodId);
1498
1499    if (paymentToggleToUse == null)        
1500        paymentToggleToUse = tryGetFirstVisiblePaymentToggleButton(); //lookup first visible and use it
1501                    
1502    if (paymentToggleToUse != null) { 
1503
1504        console.log('**STD THM: reset payment method for unknown state (' + paymentToggleToUse.getAttribute('data-paymentId') + ')');
1505
1506        handlePaymentMethodSelected(paymentToggleToUse);
1507
1508    }
1509    else
1510        console.log('**STD THM: unable to reset payment method for unknown state (no toggle button)');
1511
1512}
1513
1514function getActivePaymentToggleButton() {
1515
1516    var retVal = null;
1517
1518    var paymentToggles = document.querySelectorAll('input.paymentTypes');
1519    if (paymentToggles != null && paymentToggles.length > 0) {
1520
1521        for (var x = 0; x < paymentToggles.length; x++)
1522            if(paymentToggles[x].hasClassName('active'))
1523            {
1524                retVal = paymentToggles[x];
1525                break;
1526            }
1527
1528    }
1529
1530    return retVal;
1531
1532}
1533
1534function getVisiblePaymentToggleByPaymentMethodId(paymentMethodId) {
1535
1536    //console.log('**STD THM: get payment toggle by payment method id ' + paymentMethodId);
1537
1538    var retVal = null;
1539
1540    var paymentToggles = document.querySelectorAll('input.paymentTypes');
1541    if (paymentToggles != null && paymentToggles.length > 0) {
1542
1543        for (var x = 0; x < paymentToggles.length; x++) 
1544            if(paymentToggles[x].tryGetAttributeValue('data-paymentid').toIntZeroIfInvalid() == paymentMethodId && paymentToggles[x].parentNode.isVisible())
1545            {
1546                retVal = paymentToggles[x];
1547                break;
1548            } 
1549
1550    }
1551
1552    return retVal;
1553
1554}
1555
1556function tryGetFirstVisiblePaymentToggleButton() {
1557
1558    var retVal = null;
1559
1560    if (retVal == null && document.getElementById('ccToggle') != null && document.getElementById('ccToggle').parentNode.isVisible())
1561        retVal = document.getElementById('ccToggle');
1562
1563    if (retVal == null && document.getElementById('achToggle') != null && document.getElementById('achToggle').parentNode.isVisible())
1564        retVal = document.getElementById('achToggle');
1565
1566    if (retVal == null && document.getElementById('paymentMethodNoneToggle') != null && document.getElementById('paymentMethodNoneToggle').parentNode.isVisible())
1567        retVal = document.getElementById('paymentMethodNoneToggle');
1568
1569    if (retVal == null && document.getElementById('paypalToggle') != null && document.getElementById('paypalToggle').parentNode.isVisible())
1570        retVal = document.getElementById('paypalToggle');
1571
1572    if (retVal == null && document.getElementById('dafPayToggle') != null && document.getElementById('dafPayToggle').parentNode.isVisible())
1573        retVal = document.getElementById('dafPayToggle');
1574         
1575    return retVal;
1576
1577}
1578
1579var gl_creditCardPaymentMethodAvailable = false;
1580
1581function initializePaymentMethodSection(eventData) {    
1582
1583    console.log('**STD THM: init payment method section');
1584
1585    //initialize in-kind type
1586    var inKindTypeElem = getInKindTypeElement();
1587    if (inKindTypeElem != null) {
1588
1589        console.log('**STD THM: try initialize theme inkind payment method section')
1590
1591        //set payment method hidden field to type in-kind
1592        var pmElem = getPaymentMethodElement();
1593        if (pmElem != null) {
1594
1595            var pmElemCont = getFirstParentWithClass(pmElem, 'tsFormRows');
1596            pmElemCont.vanish();
1597
1598        }
1599         
1600    }
1601    else
1602    { 
1603
1604        console.log('**STD THM: try initialize theme regular payment method section');
1605
1606        var paymentMethodId = eventData.paymentMethodId;
1607        var paymentSectionContainer = Form.paymentSection.getSectionContainer();
1608        if (paymentSectionContainer != null)
1609        {
1610
1611            //inject payment method selector buttons
1612            var paymentTypeToggleRow = '<div id="paymentToggleRow" class="tsFormRows">';
1613
1614            //IMPORTANT: core framework dependencies on payment method 1 value being on form
1615            gl_creditCardPaymentMethodAvailable = (Form.paymentSection.hasPaymentMethodIdFieldValue(1) && (!Form.paymentSection.isPaymentBlockPresent() || (Form.paymentSection.isPaymentBlockPresent() && Form.paymentSection.isCreditCardEnabled())));
1616
1617            //IMPORTANT: core framework dependencies on payment method 2 value being on form
1618            var showBankOption = (Form.paymentSection.hasPaymentMethodIdFieldValue(2) && (!Form.paymentSection.isPaymentBlockPresent() || (Form.paymentSection.isPaymentBlockPresent() && Form.paymentSection.isACHEnabled())));
1619
1620            //IMPORTANT: core framework dependencies on payment method 9 value being on form (paypal handles conditional checks in core api)            
1621            var showPayPalOption = (Form.paymentSection.hasPaymentMethodIdFieldValue(9) && Form.paymentSection.isPayPalEnabled());
1622
1623            //console.log('show paypal form type: ' + WebFormContext.Form.Type.Id + ' (' + WebFormContext.Form.Type.Id + ',' + FORM_TYPES.PLEDGE + ') (' + (WebFormContext.Form.Type.Id == FORM_TYPES.PLEDGE).toString() + ')');
1624            //pledge and membership not supported for now because we need to allow capture of billing id without processing (6.5.2023)
1625            if (WebFormContext.Form.Type.Id == FORM_TYPES.Pledge || WebFormContext.Form.Type.Id == FORM_TYPES.Membership)
1626                showPayPalOption = false; 
1627
1628            //IMPORTANT: core framework dependencies on payment method 2 value being on form
1629            var showOtherOption = Form.paymentSection.hasPaymentMethodIdFieldValue(7);
1630
1631            //IMPORTANT: core framework dependency in payment method soft credit to work properly (dafpay handles conditional checks in core api)
1632            var showDafPayOption = (Form.paymentSection.hasPaymentMethodIdFieldValue(10) && Form.paymentSection.isDafPayEnabled()); 
1633             
1634            var showInKindOption = Form.paymentSection.hasPaymentMethodIdFieldValue(6);
1635             
1636            console.log('**STD THM: gl_creditCardPaymentMethodAvailable: ' + gl_creditCardPaymentMethodAvailable);
1637            console.log('**STD THM: showBankOption: ' + showBankOption);
1638            console.log('**STD THM: showPayPalOption: ' + showPayPalOption);
1639            console.log('**STD THM: showInKindOption: ' + showInKindOption);  
1640            console.log('**STD THM: showDafPayOption: ' + showDafPayOption);
1641
1642            var btnCount = 0;
1643
1644            if (gl_creditCardPaymentMethodAvailable)
1645            {
1646
1647                paymentTypeToggleRow += '<span class="paymentTypeContainer">'
1648                    + '<input id="ccToggle" class="paymentTypes" type="radio" data-paymentId="1"><label id="ccToggleLabel" for="ccToggle">Credit Card</label>'
1649                    + '</span>';
1650 
1651                btnCount++;                
1652
1653            }
1654
1655            if (showBankOption)
1656            {
1657
1658                paymentTypeToggleRow += '<span class="paymentTypeContainer">'
1659                    + '<input id="achToggle" class="paymentTypes" type="radio" data-paymentId="2"><label id="achToggleLabel" for="achToggle">Bank Account</label>'
1660                    + '</span>';
1661 
1662                var achAccountNumberInput = document.querySelector('.tsTextBoxes.isAchAccountNumber');
1663                var achAccountNumberToolTipContainer = document.createElement('div');
1664                achAccountNumberToolTipContainer.setAttribute('class', 'ach-help-tip-container');
1665                achAccountNumberToolTipContainer.innerHTML = '<span class="ach-help-tip help-tip"><p><img src="../../_sysimages/achhelper.png"></p></span>';
1666
1667                if (achAccountNumberInput != null)
1668                    achAccountNumberInput.parentNode.appendChild(achAccountNumberToolTipContainer);
1669
1670                var achRoutingNumberInput = document.querySelector('.tsTextBoxes.isAchRoutingNumber');
1671                var achRoutingNumberToolTipContainer = document.createElement('div');
1672                achRoutingNumberToolTipContainer.setAttribute('class', 'ach-help-tip-container');
1673                achRoutingNumberToolTipContainer.innerHTML = '<span class="ach-help-tip help-tip"><p><img src="../../_sysimages/achhelper.png"></p></span>';
1674
1675                if (achRoutingNumberInput != null)
1676                    achRoutingNumberInput.parentNode.appendChild(achRoutingNumberToolTipContainer);
1677
1678                btnCount++;
1679
1680            }
1681
1682            //add none for if present
1683            if (WebFormContext.Form.Type.Id == FORM_TYPES.Pledge && showOtherOption) { 
1684
1685                paymentTypeToggleRow += '<span class="paymentTypeContainer">'
1686                    + '<input id="paymentMethodNoneToggle" class="paymentTypes" type="radio" data-paymentId="7"><label id="noneToggleLabel" for="paymentMethodNoneToggle">Other</label>'
1687                    + '</span>';
1688 
1689                btnCount++;
1690
1691            }
1692
1693            if (showPayPalOption) { 
1694
1695                paymentTypeToggleRow += '<span class="paymentTypeContainer">'
1696                    + '<input id="paypalToggle" class="paymentTypes" type="radio" data-paymentId="9"><label id="paypalToggleLabel" for="paypalToggle">PayPal</label>'
1697                    + '</span>';
1698                     
1699                btnCount++;
1700
1701            }
1702
1703            if (showDafPayOption) {
1704
1705                paymentTypeToggleRow += '<span id="dafPayToggleContainer" class="paymentTypeContainer">'
1706                    + '<input id="dafPayToggle" class="paymentTypes" type="radio" data-paymentId="10"><label id="dafPayToggleLabel" for="dafPayToggle">Donor Advised Fund</label>'
1707                    + '</span>';
1708                     
1709                btnCount++;
1710
1711            }
1712
1713            paymentTypeToggleRow += '</div>';
1714
1715            //hide the system provided payment selector
1716            if (Form.paymentSection.getPaymentMethodsCount() <= 1 || btnCount > 0)
1717                Form.paymentSection.hideNativePaymentMethodSelector(); // <--HIDES THE PARENT ROW - PROBABLY WRONG
1718
1719            var ocBlockRow = document.querySelector('div.OneClickSectionContainer');
1720            var paymentMethodSectionTitle = Form.paymentSection.getSectionContainer().querySelector("legend");
1721
1722            if (ocBlockRow != null)
1723                ocBlockRow.insertAdjacentHTML('afterend', paymentTypeToggleRow);
1724            else if (paymentMethodSectionTitle != null)            
1725                paymentMethodSectionTitle.insertAdjacentHTML('afterend', paymentTypeToggleRow);            
1726
1727            //bind click events (was change)
1728            if (gl_creditCardPaymentMethodAvailable)
1729                document.getElementById('ccToggle').addEventListener('click', function () { handlePaymentMethodSelected(document.getElementById('ccToggle')); });
1730
1731            if (showBankOption)
1732                document.getElementById('achToggle').addEventListener('click', function () { handlePaymentMethodSelected(document.getElementById('achToggle')); });
1733
1734            if (document.getElementById('paymentMethodNoneToggle') != null)
1735                document.getElementById('paymentMethodNoneToggle').addEventListener('click', function () { handlePaymentMethodSelected(document.getElementById('paymentMethodNoneToggle')); });
1736
1737            if (document.getElementById('paypalToggle') != null)
1738                document.getElementById('paypalToggle').addEventListener('click', function () { handlePaymentMethodSelected(document.getElementById('paypalToggle')); });            
1739
1740            if (document.getElementById('dafPayToggle') != null)
1741                document.getElementById('dafPayToggle').addEventListener('click', function () { handlePaymentMethodSelected(document.getElementById('dafPayToggle')); });     
1742
1743            //set default state 
1744            if (document.getElementById('paypalButton') == null && paypalToggleContainer != null)
1745                paypalToggleContainer.remove();            
1746             
1747            var initPaymentMethodEventElem = null;
1748
1749            switch (paymentMethodId.toString()) {
1750                case PAYMENT_METHODS.CREDIT_CARD.toString():
1751
1752                    //console.log('cc state init');
1753                    if (gl_creditCardPaymentMethodAvailable)
1754                    {
1755
1756                        document.getElementById('ccToggle').checked = true;
1757                        document.getElementById('ccToggleLabel').addClassName('active');
1758
1759                        initPaymentMethodEventElem = document.getElementById('ccToggle');
1760
1761                    }
1762
1763                    break;
1764                case PAYMENT_METHODS.ACH.toString():
1765
1766                    //console.log('ach state init');
1767                    if (showBankOption)
1768                    {
1769
1770                        document.getElementById('achToggle').checked = true;
1771                        document.getElementById('achToggleLabel').addClassName('active');
1772
1773                        initPaymentMethodEventElem = document.getElementById('achToggle');
1774
1775                    }
1776
1777                    break;
1778                case PAYMENT_METHODS.NONE.toString():
1779
1780                    if (document.getElementById('paymentMethodNoneToggle') != null)
1781                        initPaymentMethodEventElem = document.getElementById('paymentMethodNoneToggle');
1782
1783                    break;
1784                case PAYMENT_METHODS.PAYPAL.toString():
1785
1786                    //console.log('pp state init');
1787                    if (showPayPalOption)
1788                    {
1789
1790                        document.getElementById('paypalToggle').checked = true;
1791                        document.getElementById('paypalToggleLabel').addClassName('active');
1792
1793                        initPaymentMethodEventElem = document.getElementById('paypalToggle');
1794
1795                    }
1796
1797                    break;
1798                case PAYMENT_METHODS.SOFT_CREDIT.toString():
1799                     
1800                    if (showDafPayOption)
1801                    {
1802
1803                        document.getElementById('dafPayToggle').checked = true;
1804                        document.getElementById('dafPayToggleLabel').addClassName('active');
1805
1806                        initPaymentMethodEventElem = document.getElementById('dafPayToggle');
1807
1808                    }
1809
1810                    break;
1811            }        
1812
1813            convertCreditCardTypeDropDownToImage();            
1814
1815            if (document.getElementById('cc-type-images-container') != null && document.getElementById('cc-type-images-container').firstParentWithClass('tsFormRows') != null)
1816                document.getElementById('cc-type-images-container').firstParentWithClass('tsFormRows').style.marginBottom = "0px"; // $('#cc-type-images-container').closest('.tsFormRows').css('margin-bottom', '0');
1817
1818            //Payment Method Section Initialization for old Standard-out-of-the-Box Forms NOT using System Payment Block
1819            if (!Form.paymentSection.isPaymentBlockPresent())
1820            {
1821
1822                //da, da, da da - get an array from a mashup of things - just throwing unstructured DOM-based stuff in a bag and let's wait for it to break
1823                ccSection = $('.CardNumber, #cc-type-images-container, .ExpirationMonth, .ExpirationYear, .nameOnCard, .isCcCvvCode').closest('.tsFormRows');
1824                achSection = $('.RoutingNumber, .AccountNumber, .isAchNameOnAccount').closest('.tsFormRows');
1825                achTypeSection = $('.AccountType').closest('.tsFormRows');
1826                paypalSection = $('.PayPal').closest('.tsFormRows');
1827
1828            }
1829
1830            setPaymentInfoUIState(paymentMethodId);
1831
1832            Form.paymentSection.onAchAccountTypeChanged(function (eventData) {
1833                updateBankAccountTypeUIState(eventData.bankAccountTypeId);
1834            });
1835
1836            Form.paymentSection.onCreditCardTypeChanged(function (data) {
1837                console.log('**STD THM: credit card type changed event fired');
1838                callUIUpdatesForAmountOrPaymentChange();
1839            });
1840
1841            if (initPaymentMethodEventElem != null)
1842                handlePaymentMethodSelected(initPaymentMethodEventElem);
1843
1844        }
1845        else
1846            console.log('**STD THM: Payment section was not found');
1847
1848    }
1849      
1850}
1851
1852//callback to avoid race conditions with google API
1853function themeGooglePayButtonRenderHandler() {
1854
1855    console.log('**STD THM: theme google pay button render handler');
1856
1857    //inject button
1858    //check for native button and make sure we're not double-tapping
1859    if (gl_creditCardPaymentMethodAvailable && document.getElementById('paymentToggleRow') != null && document.getElementById('googlePayToggle') == null && googlePayApi.GetButtonElement() != null) { // document.querySelector('.gpay-button') != null) {
1860         
1861        var prnElem = document.createElement('span');
1862        prnElem.id = 'googlePayToggleContainer';
1863        prnElem.setAttribute('class', 'paymentTypeContainer');
1864
1865        prnElem.innerHTML = '<input id="googlePayToggle" class="paymentTypes" type="radio" data-paymentId="1" data-walletTypeId="1"><label id="googlePayToggleLabel" for="googlePayToggle">Google Pay</label>';
1866
1867        document.getElementById('paymentToggleRow').appendChild(prnElem);
1868
1869        if (document.getElementById('googlePayToggle') != null)
1870            document.getElementById('googlePayToggle').addEventListener('click', function () { handlePaymentMethodSelected(document.getElementById('googlePayToggle')); });
1871
1872        //hide by default - must be selected
1873        googlePayApi.HideButton();
1874
1875    }
1876
1877}
1878
1879function themeApplePayButtonRenderHandler() {
1880
1881    console.log('**STD THM: theme apple pay button render handler');
1882
1883    if (applePayApi.IsApplePayApiAvailable()) {
1884
1885        if (document.getElementById('paymentToggleRow') != null && document.getElementById('applePayToggle') == null && applePayApi.GetButtonElement() != null) {
1886
1887            var prnElem = document.createElement('span');
1888            prnElem.id = 'applePayToggleContainer';
1889            prnElem.setAttribute('class', 'paymentTypeContainer');
1890
1891            prnElem.innerHTML = '<input id="applePayToggle" class="paymentTypes" type="radio" data-paymentId="1" data-walletTypeId="2"><label id="applePayToggleLabel" for="applePayToggle">Apple Pay</label>';
1892
1893            document.getElementById('paymentToggleRow').appendChild(prnElem);
1894
1895            if (document.getElementById('applePayToggle') != null)
1896                document.getElementById('applePayToggle').addEventListener('click', function () { handlePaymentMethodSelected(document.getElementById('applePayToggle')); });
1897
1898            //hide by default - must be selected
1899            applePayApi.HideButton();
1900
1901        }
1902
1903    }
1904    else
1905        console.log('**STD THM: skip theme apple pay button creation because ApplePay is not available');
1906     
1907}
1908
1909function manuallyEnablePaymentFieldValidators() {
1910
1911    if (reqCCFields != null && reqCCFields.length > 0)
1912        for (var x = 0; x < reqCCFields.length; x++)
1913            if(document.querySelector(reqCCFields[x]) != null && document.querySelector(reqCCFields[x]).ParentNode.isVisible())
1914                enableOrDisableRequiredValidator(document.querySelector(reqCCFields[x]), 'enable');
1915
1916    if (reqACHFields != null && reqACHFields.length > 0)
1917        for (var x = 0; x < reqACHFields.length; x++)
1918            if(document.querySelector(reqACHFields[x]) != null && document.querySelector(reqACHFields[x]).ParentNode.isVisible())
1919                enableOrDisableRequiredValidator(document.querySelector(reqACHFields[x]), 'enable');
1920
1921}
1922
1923function manuallyDisablePaymentFieldValidators() {
1924
1925    if (reqCCFields != null && reqCCFields.length > 0)
1926        for (var x = 0; x < reqCCFields.length; x++)
1927            if(document.querySelector(reqCCFields[x]) != null)
1928                enableOrDisableRequiredValidator(document.querySelector(reqCCFields[x]), 'disable');
1929
1930    if (reqACHFields != null && reqACHFields.length > 0)
1931        for (var x = 0; x < reqACHFields.length; x++)
1932            if(document.querySelector(reqACHFields[x]) != null)
1933                enableOrDisableRequiredValidator(document.querySelector(reqACHFields[x]), 'disable');
1934
1935}
1936
1937function setPaymentInfoUIState(paymentMethodId, walletTypeId) {
1938
1939    console.log('**STD THM: set payment info UI state: ' + paymentMethodId + ' , ' + walletTypeId);
1940
1941    //duplicate cut & paste code from Forms API for forms that do not have the payment block defined (hmmmmmm)
1942    if (!Form.paymentSection.isPaymentBlockPresent())
1943    {
1944
1945        themeUIStateConfig.PaymentMethodId = paymentMethodId;
1946
1947        $(ccSection).hide();
1948        $(achSection).hide();
1949        $(achTypeSection).hide();
1950        $(paypalSection).hide();
1951
1952        hideBillingInfoSection();
1953
1954        console.log('**STD THM: HIDE NEXT BUTTON IN THEME IF NO PAYMENT BLOCK???');
1955
1956        //this whole things is extremely suspicious
1957        Form.HideNextButton();   
1958
1959        manuallyDisablePaymentFieldValidators();
1960 
1961    }
1962
1963    payPalApi.HideButton();
1964
1965    googlePayApi.HideButton();
1966
1967    applePayApi.HideButton();
1968     
1969    dafPayApi.HideButton();
1970
1971    if (!isBlank(walletTypeId)) {
1972
1973        console.log('**STD THM: toggle payment method ui with WALLET : ' + walletTypeId);
1974
1975        switch (walletTypeId) {
1976            case WALLET_TYPES.GOOGLE_PAY.toString():
1977
1978                hideBillingInfoDifferentOptions();
1979
1980                showProcessingFeesToggle();
1981
1982                googlePayApi.ShowButton();
1983
1984                break;
1985            case WALLET_TYPES.APPLE_PAY.toString():
1986
1987                hideBillingInfoDifferentOptions();
1988
1989                showProcessingFeesToggle();
1990
1991                applePayApi.ShowButton();
1992
1993                break;
1994        }
1995
1996    }
1997    else
1998    {
1999
2000        console.log('**STD THM: toggle payment method ui with id: ' + paymentMethodId);
2001
2002        Form.ShowNextButton();   
2003
2004        switch (paymentMethodId.toString()) {
2005            case PAYMENT_METHODS.ONECLICK_DONATION.toString():
2006
2007                if (isOneClickShown() && WebFormContext.Form.StepNumber == FORM_STEPS.CONFIRMATION)
2008                    oneClick_yesButtonClick();
2009                     
2010                break;
2011            case PAYMENT_METHODS.CREDIT_CARD.toString():
2012
2013                console.log('**STD THM: show credit card view (isPaymentBlockPresent): ' + Form.paymentSection.isPaymentBlockPresent());
2014
2015                //duplicate cut & paste code from Forms API for forms that do not have the payment block defined (hmmmmmm)
2016                if (!Form.paymentSection.isPaymentBlockPresent()) {
2017
2018                    $(ccSection).show();
2019
2020                    if (reqCCFields != null && reqCCFields.length > 0)
2021                        for (var x = 0; x < reqCCFields.length; x++)
2022                            if(document.querySelector(reqCCFields[x]) != null && document.querySelector(reqCCFields[x]).ParentNode.isVisible())
2023                                enableOrDisableRequiredValidator(document.querySelector(reqCCFields[x]), 'enable');
2024                    
2025                }
2026
2027                //show billing diff
2028                if (document.getElementById('billingDiffToggleContainer') != null)
2029                    document.getElementById('billingDiffToggleContainer').show(); 
2030
2031                showProcessingFeesToggle();
2032                 
2033                break;
2034            case PAYMENT_METHODS.ACH.toString():
2035                 
2036                var selectedBankAccountTypeId = Form.paymentSection.getSelectedBankAccountTypeId();
2037                updateBankAccountTypeUIState(selectedBankAccountTypeId);
2038
2039                //duplicate cut & paste code from Forms API for forms that do not have the payment block defined (hmmmmmm)
2040                if (!Form.paymentSection.isPaymentBlockPresent()) {
2041
2042                    $(achSection).show();
2043
2044                    if (reqACHFields != null && reqACHFields.length > 0)
2045                        for (var x = 0; x < reqACHFields.length; x++)
2046                            if(document.querySelector(reqACHFields[x]) != null && document.querySelector(reqACHFields[x]).ParentNode.isVisible())
2047                                enableOrDisableRequiredValidator(document.querySelector(reqACHFields[x]), 'enable');
2048
2049                    if ($(achTypeSection).find('span[fieldoption_id]').length > 1) {
2050
2051                        $(achTypeSection).show();
2052
2053                        var checkingType = $(achTypeSection).find('label:contains("Checking")');
2054                        var savingType = $(achTypeSection).find('label:contains("Savings")');
2055
2056                        if (!$(savingType).hasClass('active'))
2057                            $(checkingType).addClass('active');
2058
2059                        $(savingType).click(function () {
2060                            $(this).addClass('active');
2061                            $(checkingType).removeClass('active');
2062                        });
2063
2064                        $(checkingType).click(function () {
2065                            $(this).addClass('active');
2066                            $(savingType).removeClass('active');
2067                        });
2068
2069                    }
2070
2071                }
2072
2073                hideBillingInfoDifferentOptions();
2074
2075                showProcessingFeesToggle();
2076                 
2077                break;
2078            case PAYMENT_METHODS.PAYPAL.toString():
2079
2080                hideBillingInfoDifferentOptions();
2081
2082                showProcessingFeesToggle();
2083
2084                payPalApi.ShowButton();
2085
2086                Form.HideNextButton();   
2087
2088                break;
2089            case PAYMENT_METHODS.SOFT_CREDIT.toString():
2090
2091                console.log('**STD THM: Set Payment Method to SOFT CREDIT (DAFpay)');
2092
2093                hideBillingInfoDifferentOptions();
2094
2095                hideProcessingFeesToggle(true);
2096
2097                dafPayApi.ShowButton();
2098
2099                Form.HideNextButton();   
2100
2101                break;
2102            case PAYMENT_METHODS.NONE.toString():
2103
2104                hideBillingInfoDifferentOptions();
2105
2106                hideProcessingFeesToggle();
2107
2108                break;            
2109        }
2110
2111    }
2112
2113    //if (typeof (oneClickPaymentFieldsVisible) != 'undefined' && WebFormContext.Form.StepName == 'Confirmation Step' && paymentMethodId.toString() != '0') 
2114    //    oneClickPaymentFieldsVisible = false;     
2115
2116    showPaymentSection(); //always show, call to handle amount after this should hide whole section if shown
2117
2118    console.log('**STD THM: Set Payment Method - oneClickDisplayState: ' + oneClickDisplayState());
2119     
2120    togglePaymentMethodToggleButtonsForOneClickState();
2121
2122    gl_firstPaymentInfoInitializationCompleted = true;
2123
2124}
2125
2126var gl_firstPaymentInfoInitializationCompleted = false;
2127
2128function hideBillingInfoDifferentOptions() {
2129
2130    //hide billing diff check box
2131    if (document.getElementById('billingDiffToggleContainer') != null)
2132        document.getElementById('billingDiffToggleContainer').vanish();
2133
2134    hideBillingInfoSection();
2135
2136}
2137
2138function showProcessingFeesToggle() {
2139
2140    if (document.getElementById('payProcessingFeeSystemSectionContainer') != null)
2141        document.getElementById('payProcessingFeeSystemSectionContainer').show();
2142
2143}
2144
2145function hideProcessingFeesToggle(clearSelection) {
2146
2147    if (document.getElementById('payProcessingFeeSystemSectionContainer') != null) {
2148        document.getElementById('payProcessingFeeSystemSectionContainer').vanish();
2149
2150        if (document.getElementById('payProcessingFeeOptInCheckbox') != null && clearSelection) {
2151            var cbFee = document.getElementById('payProcessingFeeOptInCheckbox');
2152
2153            cbFee.checked = false;
2154            cbFee.dispatchEvent(new Event('change'));
2155        }
2156    }
2157
2158}
2159
2160function updateBankAccountTypeUIState(selectBankAccountTypeId) {
2161
2162    if (Form.paymentSection.isPaymentBlockPresent()) {
2163        
2164        if (Form.paymentSection.isACHEnabled()) {
2165
2166            if (Form.paymentSection.getSelectedBankAccountTypeField() != null && Form.paymentSection.getSelectedBankAccountTypeId() > 0) {
2167
2168                var bankTypeRBs = Form.paymentSection.getSelectedBankAccountTypeField().querySelectorAll('input[type="radio"]');
2169
2170                if(bankTypeRBs != null && bankTypeRBs.length > 0)
2171                    for (var i = 0; i < bankTypeRBs.length; i++)
2172                        if(bankTypeRBs[i].previousSibling != null)
2173                        {
2174                            
2175                            bankTypeRBs[i].previousSibling.removeClassName('active');
2176
2177                            if (bankTypeRBs[i].checked)
2178                                bankTypeRBs[i].previousSibling.addClassName('active');
2179
2180                        }
2181
2182            }
2183
2184        }
2185
2186    }
2187    else
2188    {
2189
2190        if ($(achTypeSection).find('span[fieldoption_id]').length > 1)
2191        {
2192
2193            $(achTypeSection).show();
2194
2195            var checkingType = $(achTypeSection).find('label:contains("Checking")');
2196            var savingType = $(achTypeSection).find('label:contains("Savings")');
2197        
2198            switch (selectBankAccountTypeId.toString())
2199            {
2200                case BANK_ACCOUNT_TYPES.SAVINGS.toString():
2201                    $(checkingType).removeClass('active');
2202                    $(savingType).addClass('active');
2203                    break;
2204                case BANK_ACCOUNT_TYPES.CHECKING.toString():
2205                    $(savingType).removeClass('active');
2206                    $(checkingType).addClass('active');
2207                    break;
2208            }
2209
2210        }
2211
2212    }
2213
2214}
2215 
2216function showBillingInfoSection() {
2217
2218    themeUIStateConfig.IsBillingInfoDifferent = true;
2219
2220    $(billingSection).slideDown();
2221
2222    reqBillingFields.forEach(function (field) {
2223        enableOrDisableRequiredValidator(document.querySelector(field), 'enable');
2224    });
2225
2226}
2227
2228function hideBillingInfoSection() {
2229
2230    themeUIStateConfig.IsBillingInfoDifferent = false;
2231
2232    $(billingSection).slideUp();
2233
2234    reqBillingFields.forEach(function (field) {
2235        enableOrDisableRequiredValidator(document.querySelector(field), 'disable');
2236    });
2237
2238}
2239
2240function initializeEventTicketInfoSection() {
2241
2242    console.log('**STD THM: init event ticket info section');
2243
2244    var ticketTotal = getTicketTotalAmount();
2245
2246    //inject new DOM elements & manipulate
2247    if (ticketTotal > 0)
2248        $('.ts_sys_ReadOnlyFields_ticketSubTotal').last().closest('.tsFormRows').append('<div id="ticketTotalContainer" class="tsFormRows">Ticket Total: $<span id="ticketTotalAmount">' + ticketTotal + '</span></div>');
2249    else
2250        $('.ts_sys_ReadOnlyFields_ticketSubTotal').last().closest('.tsFormRows').append('<div id="ticketTotalContainer" class="tsFormRows">Ticket Total: $<span id="ticketTotalAmount">0.00</span></div>');
2251
2252    //bind user interaction events 
2253    if ($('.TicketSectionContainer').length && $('.DonationSectionContainer').length)
2254    {
2255
2256        if (Form.stepNumber === FORM_STEPS.INITIAL || Form.stepNumber === FORM_STEPS.CONFIRMATION)
2257        {
2258
2259            $('.DonationSectionContainer').before('<div id="additionalDonationToggleContainer" class="tsFormRows"><label for="additionalDonationToggle">Would you like to make an additional donation?</label><input id="additionalDonationToggle" type="checkbox"></div>');
2260
2261            $('#additionalDonationToggle').on('change', function () {
2262
2263                if ($(this).is(':checked'))
2264                    showAdditionalDonationOption();
2265                else
2266                    hideAdditionalDonationOption();
2267
2268            });
2269
2270        }
2271
2272    }
2273
2274    $('.event-info-row span.tsSysTicketSoldOut').closest('.event-info-row').addClass('sold-out');
2275    $('.event-ticket-row input.tsSysTicketSoldOut').closest('.event-ticket-row').addClass('ce-disabled');
2276
2277    $('.SubTotal.tsSysTicketSoldOut').closest('.tsFormRows').css('display', 'none');
2278    $('.ts_sys_ReadOnlyFields_ticketSoldOutMessage:empty').closest('.tsFormRows').hide();
2279
2280    for (var x = 0; x < WebFormContext.Form.Fields.length; x++) {
2281
2282        if (WebFormContext.Form.Fields[x].Type.Id == FORM_FIELD_TYPES.TICKET_QUANTITY_SYSTEM) {
2283    
2284            var ticketQuantityElem = document.getElementById(WebFormContext.Form.Fields[x].DomId);
2285
2286            if (ticketQuantityElem != null) {
2287
2288                ticketQuantityElem.addEventListener('change', function () {
2289    
2290                    var qtyRequested = getFormTicketQuantityInputValue(this); //parseInt(this.getValue());               
2291                    var qtyAvailable = getFormTicketQuantityInputMa
2291xValue(this); //parseInt(this.getAttribute('data-maxvalue'));
2292
2293                    var fieldParentRow = this.firstParentWithClass('event-ticket-row');
2294                    var fieldWarningMessageElem = fieldParentRow.querySelector('warning-msg');
2295
2296                    if (qtyRequested > qtyAvailable) {
2297
2298                        if (fieldWarningMessageElem == null)
2299                        {
2300                            var wrnMsg = document.createElement('span');
2301                            wrnMsg.addClassName('warning-msg');
2302                            wrnMsg.innerHTML = 'The number of tickets you want to purchase exceeds the amount available.  Please change quantity to <strong>' + qtyAvailable + '</strong> or less.';
2303                            fieldParentRow.appendChild(wrnMsg);
2304                        }
2305
2306                        fieldParentRow.querySelector('warning-msg').show();
2307
2308                        var thisSubtotalElem = fieldParentRow.ParentNode.querySelector('span.SubTotal');
2309                        if (thisSubtotalElem != null)
2310                            thisSubtotalElem.innerText = '0.00';
2311
2312                    }
2313                    else if (fieldWarningMessageElem != null)
2314                        fieldWarningMessageElem.vanish();
2315    
2316                    var ticketTotal = 0;
2317
2318                    //beware of hack-city race condition
2319                    var ticketIdVal = getFormTicketQuantityInputTicketId(this); //this.getAttribute('data-ticket-id').toIntZeroIfInvalid();
2320                    ts_clapi_multiplyTextBoxValueEnterResultInSystemTicketFields(this, ticketIdVal, ts_global_jsFw_ticketElements);
2321                     
2322                    var subTotLabels = document.querySelectorAll('span.SubTotal');
2323                    if (subTotLabels != null && subTotLabels.length > 0)
2324                        for (var y = 0; y < subTotLabels.length; y++)                             
2325                            ticketTotal += parseFloat(subTotLabels[y].innerText.replace(',', ''));                        
2326
2327                    document.getElementById('ticketTotalAmount').innerHTML = formatCurrency(ticketTotal, true);  //this block of code should be replaced by a donor section event.
2328
2329                    callUIUpdatesForAmountOrPaymentChange();
2330                     
2331                });
2332    
2333            }            
2334    
2335        }  
2336
2337    }
2338     
2339    //set default state from UI state
2340    var additionalDonationToggleCb = document.getElementById('additionalDonationToggle');
2341
2342    if (additionalDonationToggleCb != null && WebFormContext.Form.StepNumber !== 3)
2343    {
2344
2345        if (themeUIStateConfig.EventAdditionalDonationOn)
2346        {
2347            additionalDonationToggleCb.checked = true;
2348            showAdditionalDonationOption();
2349        }
2350        else
2351        {
2352            additionalDonationToggleCb.checked = false;
2353            hideAdditionalDonationOption();
2354        }
2355
2356    }
2357
2358}
2359
2360function showAdditionalDonationOption() {
2361
2362    console.log('**STD THM: toggle event additional donation option on');
2363    
2364    themeUIStateConfig.EventAdditionalDonationOn = true;
2365
2366    if (themeUIStateConfig.SelectedAmountOptionIndex > 0)
2367        setPaymentAmountUIByIndex(themeUIStateConfig.SelectedAmountOptionIndex);
2368    else
2369        setPaymentAmountUIByIndex(1);
2370
2371    $('.DonationSectionContainer').slideDown();  //this block of code should be replaced by a donor section event.
2372
2373    callUIUpdatesForAmountOrPaymentChange();
2374
2375}
2376
2377function hideAdditionalDonationOption() {
2378
2379    console.log('**STD THM: toggle event additional donation option off');
2380
2381    themeUIStateConfig.EventAdditionalDonationOn = false;
2382
2383    themeUIStateConfig.SelectedAmountOptionIndex = -1;
2384    setPaymentAmountUIByIndex(themeUIStateConfig.SelectedAmountOptionIndex);
2385
2386    $('.DonationSectionContainer').slideUp();
2387
2388    callUIUpdatesForAmountOrPaymentChange();
2389
2390}
2391
2392function trySetMembershipTypeAmount() {
2393    
2394    var membTpElem = Form.GetMembershipTypeFieldElement();    
2395    if (membTpElem != null && membTpElem.hasClassName('ceMembershipFormTemplate') && WebFormContext.Form.MembershipTypes != null && WebFormContext.Form.MembershipTypes.length > 0) {
2396         
2397        var membTpAmt = 0.00;
2398
2399        var curMemTpId = membTpElem.getValue().toIntZeroIfInvalid();
2400        if (curMemTpId > 0)
2401            for (var x = 0; x < WebFormContext.Form.MembershipTypes.length; x++)
2402                if (WebFormContext.Form.MembershipTypes[x].Id == curMemTpId) {
2403                    membTpAmt = WebFormContext.Form.MembershipTypes[x].DefaultRate;
2404                    break;
2405                }
2406
2407        //set amount field
2408        var amtFld = Form.GetFirstAmountFieldElement();
2409        if (amtFld != null) { 
2410            //console.log('**STD THM: set membership amount to: ' + membTpAmt);
2411            amtFld.value = membTpAmt;
2412            callUIUpdatesForAmountOrPaymentChange();
2413        }
2414
2415    }
2416
2417}
2418
2419function handleMembershipTypeChanged(cbParams) {
2420
2421    trySetMembershipTypeAmount();
2422    
2423}
2424
2425//One-Click Giving Event Overrides
2426//********************************
2427
2428function oneClickDisplayState() {
2429
2430    var retVal = 'notpresent';
2431
2432    if (isOneClickShown()) {
2433
2434        if (oneClickShowPaymentFieldsState())
2435            retVal = 'paymentinfo_shown';
2436        else
2437            retVal = 'oneclick_shown';
2438
2439    }
2440
2441    return retVal;
2442
2443}
2444
2445function togglePaymentMethodToggleButtonsForOneClickState() {
2446
2447    if(oneClickDisplayState() == 'oneclick_shown')
2448        hidePaymentMethodToggleButtons();
2449    else if (!gl_firstPaymentInfoInitializationCompleted)
2450        showPaymentMethodToggleButtons();
2451
2452}
2453
2454function isOneClickShown() {
2455
2456    return (typeof oneClickWidgetRendered != 'undefined' && oneClickWidgetRendered); //Global Context Variable (should not be changed)
2457    
2458}
2459
2460function oneClickShowPaymentFieldsState() {
2461
2462    return (typeof (oneClickPaymentFieldsVisible) != 'undefined' && oneClickPaymentFieldsVisible); //Global Context Variable (should not be changed
2463
2464}
2465
2466function oneClick_initializeCompleteHandler() {
2467
2468    console.log('**STD THM: ONE-CLICK giving initialization complete event handler: ' + oneClickDisplayState());
2469
2470    togglePaymentMethodToggleButtonsForOneClickState();
2471
2472}
2473
2474function oneClick_overrideEnabledFormRenderer() {
2475
2476    console.log('**STD THM: ONE-CLICK giving override enabled renderer');
2477    
2478    //race condition
2479    if (themeLoaded)
2480    {        
2481    
2482        //race condition    
2483        hidePaymentInfoForOneClick();
2484    
2485        setPaymentInfoUIState('0'); //0: oneclick, 7: none
2486    
2487        var bidToggleCb = document.getElementById('billingDiffToggle');
2488        if (bidToggleCb != null)
2489        {
2490            bidToggleCb.checked = false;
2491            hideBillingInfoSection();
2492        }        
2493
2494    }    
2495
2496}
2497
2498function oneClick_userDismissHandler() {
2499
2500    console.log('**STD THM: ONE-CLICK giving user dismiss event handler');
2501
2502    resetPaymentMethodForUnknownSelection();
2503     
2504}
2505
2506function oneClick_overrideDismissFormRenderer() {
2507
2508    console.log('**STD THM: ONE-CLICK giving override dismiss renderer');
2509
2510    showPaymentInfoForOneClick();    
2511
2512}
2513
2514function hidePaymentInfoForOneClick() {
2515
2516    console.log('**STD THM: ONE-CLICK HIDE payment info for ONE CLICK');
2517     
2518    hidePaymentMethodToggleButtons();
2519
2520    if (document.getElementById('billingDiffToggleContainer') != null)
2521        document.getElementById('billingDiffToggleContainer').vanish();
2522    
2523    var nonOneClickPaymentRows = document.getElementById(Form.paymentSection.getSectionContainerId()).querySelectorAll('.tsFormRows:not(.OneClickSectionContainer)');
2524    for (var i = 0; i < nonOneClickPaymentRows.length; i++)         
2525        nonOneClickPaymentRows[i].vanish();     
2526    
2527    googlePayApi.HideButton();
2528    
2529    applePayApi.HideButton();
2530    
2531    dafPayApi.HideButton();
2532     
2533}
2534
2535function showPaymentInfoForOneClick() {
2536
2537    console.log('**STD THM: ONE-CLICK SHOW payment info for ONE CLICK');
2538     
2539    showPaymentMethodToggleButtons();
2540
2541    if (document.getElementById('billingDiffToggleContainer') != null)
2542        document.getElementById('billingDiffToggleContainer').show();
2543    
2544    var nonOneClickPaymentRows = document.getElementById(Form.paymentSection.getSectionContainerId()).querySelectorAll('.tsFormRows:not(.OneClickSectionContainer)');
2545    for (var i = 0; i < nonOneClickPaymentRows.length; i++) 
2546        nonOneClickPaymentRows[i].show(); 
2547    
2548    googlePayApi.ShowButton();
2549    
2550    applePayApi.ShowButton();
2551    
2552    dafPayApi.ShowButton();    
2553
2554}
2555
2556function oneClick_yesButtonClickAfter() {
2557
2558    console.log('**STD THM: **STD THM: ONE-CLICK Yes Button Click');
2559
2560    Form.paymentSection.setPaymentMethod(PAYMENT_METHODS.ONECLICK_DONATION.toString());    
2561
2562}
2563//************************************
2564//One-Click Giving Event Overrides END
2565
2566//Custom Theme Validation
2567//************************************
2568
2569function getTicketQuantityFieldCount() {
2570
2571    var retVal = 0;
2572
2573    for (var x = 0; x < WebFormContext.Form.Fields.length; x++)
2574        if (WebFormContext.Form.Fields[x].Type.Id == FORM_FIELD_TYPES.TICKET_QUANTITY_SYSTEM)
2575            retVal++;
2576
2577    return retVal;
2578
2579}
2580
2581function getTicketSelectionQuantity() {
2582
2583    var retVal = 0;
2584
2585    for (var x = 0; x < WebFormContext.Form.Fields.length; x++)
2586        if (WebFormContext.Form.Fields[x].Type.Id == FORM_FIELD_TYPES.TICKET_QUANTITY_SYSTEM) { 
2587
2588            var ticketQuantityElem = document.getElementById(WebFormContext.Form.Fields[x].DomId);
2589            if (ticketQuantityElem != null)
2590                retVal += getFormTicketQuantityInputValue(ticketQuantityElem); //ticketQuantityElem.getValue().toIntZeroIfInvalid();
2591
2592        }
2593
2594
2595    return retVal;
2596
2597}
2598
2599function clearTicketSelectionQuantityValidationErrors() {
2600
2601    var retVal = 0;
2602
2603    for (var x = 0; x < WebFormContext.Form.Fields.length; x++)
2604        if (WebFormContext.Form.Fields[x].Type.Id == FORM_FIELD_TYPES.TICKET_QUANTITY_SYSTEM) { 
2605
2606            var ticketQuantityElem = document.getElementById(WebFormContext.Form.Fields[x].DomId);
2607            if (ticketQuantityElem != null)
2608                ticketQuantityElem.removeClassName('error');                
2609
2610        }
2611
2612
2613    return retVal;
2614
2615}
2616
2617function setTicketSelectionQuantityValidationErrors() {
2618
2619    var retVal = 0;
2620
2621    for (var x = 0; x < WebFormContext.Form.Fields.length; x++)
2622        if (WebFormContext.Form.Fields[x].Type.Id == FORM_FIELD_TYPES.TICKET_QUANTITY_SYSTEM) { 
2623
2624            var ticketQuantityElem = document.getElementById(WebFormContext.Form.Fields[x].DomId);
2625            if (ticketQuantityElem != null)
2626                ticketQuantityElem.addClassName('error');                
2627
2628        }
2629
2630
2631    return retVal;
2632
2633}
2634
2635function ts_clientCustom_onSubmit() {
2636
2637    console.log('**STD THM: standard theme custom submit validation fired');
2638
2639    var retVal = true;
2640
2641    var tixCnt = getTicketQuantityFieldCount();
2642    if (tixCnt > 0)
2643    {        
2644
2645        console.log('**STD THM: theme custom validation found ' + tixCnt + ' ticket quantity fields - begin minimum ticket selection validation');
2646
2647        clearError();
2648        clearTicketSelectionQuantityValidationErrors();
2649
2650        retVal = (getTicketSelectionQuantity() > 0);
2651
2652        if (!retVal)
2653        { 
2654
2655            displayError('Please select a ticket to register');            
2656
2657            setTimeout(function () {
2658
2659                var defDotNetValElem = document.querySelector('div.tsValidationSummaryMessages');
2660                if (defDotNetValElem != null)
2661                    defDotNetValElem.vanish();
2662
2663                 }, 500);
2664
2665            setTicketSelectionQuantityValidationErrors();
2666
2667        }
2668
2669    }
2670
2671    return retVal;
2672
2673}
2674
2675//************************************
2676//Custom Theme Validation
2677
2678var paypalToggleContainer = null;
2679var frequencyRow = null;
2680var frequencyDropdown = null;
2681var amountField = null;
2682
2683var reqTributeFields = []; //'.Tribute_XXX_Type', '.Tribute_XXX_Name'
2684
2685if (!isBlank(getTributeTypeDomId()))
2686    reqTributeFields.push('#' + getTributeTypeDomId());
2687
2688if (!isBlank(getTributeNameDomId()))
2689    reqTributeFields.push('#' + getTributeNameDomId());
2690      
2691var tributeSection = null;
2692var tributeAckNameSection = null;
2693var tributeAckAddressSection = null;
2694var tributeAckEmailSection = null;
2695var tributeAckMessageSection = null;
2696
2697var reqCCFields = ['.CardNumber', '.ExpirationMonth', '.ExpirationYear', '.CVVCode'];
2698var reqACHFields = ['.RoutingNumber', '.AccountNumber'];
2699var ccSection = null;
2700var achSection = null;
2701var paypalSection = null;
2702
2703var achTypeSection = null;
2704
2705var hiddenMethodField = null;
2706
2707var reqBillingFields = ['.BillingStreetAddress', '.BillingStateorProvince', '.BillingCity', '.BillingPostalCode', '.BillingAddress1', '.BillingPostalCode', '.BillingCity', '.BillingState', '.BillingCountry'];
2708
2709var billingSection = null;
2710
2711function showHidePaymentInfoBlockBasedOnAmount(fromPaymentMethodChangedEvent) {
2712
2713    var paymentMethod = Form.paymentSection.getSelectedPaymentMethodId();
2714    var total = Form.GetTransactionAmount();
2715    var recurringTotal = Form.GetRecurringAmount();
2716    //var promoDiscount = Form.GetPromoCodeDiscountAmount();
2717
2718    console.log('**STD THM: showHidePaymentInfoBlockBasedOnAmount fired with payment method ' + paymentMethod + ' and amount ' + total);
2719     
2720    //if (total == '0.00' && recurringTotal == '0.00')
2721    if (total.toString().toDecimalZeroIfInvalid() <= 0 && recurringTotal.toString().toDecimalZeroIfInvalid() <= 0)
2722    {
2723
2724        console.log('**STD THM: Hide Payment Section for No Tranasction Amount');
2725
2726        if (reqCCFields != null && reqCCFields.length > 0)
2727            for (var x = 0; x < reqCCFields.length; x++)
2728                if(document.querySelector(reqCCFields[x]) != null)
2729                    enableOrDisableRequiredValidator(document.querySelector(reqCCFields[x]), 'disable');
2730
2731        if (reqACHFields != null && reqACHFields.length > 0)
2732            for (var x = 0; x < reqACHFields.length; x++)
2733                if(document.querySelector(reqACHFields[x]) != null)
2734                    enableOrDisableRequiredValidator(document.querySelector(reqACHFields[x]), 'disable');
2735                         
2736        hidePaymentSection();
2737            
2738    }
2739    else if (WebFormContext.Form.StepName != 'Initial Step')
2740    {
2741
2742        console.log('**STD THM: Hide Payment Section for Not Initial Step');
2743
2744        hidePaymentSection();
2745
2746    }
2747    else if (document.body.hasClassName('page-3')) {
2748
2749        if (!Form.paymentSection.showPaymentBlockOnErrorView()) {
2750
2751            console.log('**STD THM: Hide Payment Section for preview of error view');
2752
2753            hidePaymentSection();
2754
2755        }
2756
2757    } 
2758    else if (document.body.hasClassName('page-4')) {
2759
2760        if (!Form.paymentSection.showPaymentBlockOnReceiptView()) {
2761
2762            console.log('**STD THM: Hide Payment Section for preview of receipt view');
2763
2764            hidePaymentSection();
2765
2766        }
2767
2768    }
2769    else
2770    {
2771        
2772        if (Form.paymentSection.isPaymentBlockPresent() && WebFormContext.Form.StepName == 'Initial Step') {
2773             
2774            console.log('**STD THM: Show Payment Section ' + Form.paymentSection.getSectionContainerId() + ' (' + document.getElementById(Form.paymentSection.getSectionContainerId()) + ') for Dollar Amount Greater Than Zero');
2775
2776            showPaymentSection();
2777
2778            //bug city with one click and going from $0 hidden state!!!            
2779            //if(!fromPaymentMethodChangedEvent) //prevent recursion
2780            //    Form.paymentSection.setPaymentMethod(paymentMethod);
2781
2782        }
2783        else
2784            console.log('**STD THM: SKIPPING show payment section for dollar amount greater than zero!!!!!!!!!');
2785
2786    }
2787
2788}
2789
2790function showHidePaymentSectionsBasedOnCurrency() {
2791    //DafPay should only be available for USD
2792    adjustThemeDafPayToggleForCurrency(Form.GetCurrencyId());
2793}
2794
2795function showPaymentSection() {
2796     
2797    if(Form.paymentSection.isPaymentBlockPresent() && document.getElementById(Form.paymentSection.getSectionCont
2797ainerId()) != null)
2798        document.getElementById(Form.paymentSection.getSectionContainerId()).show();
2799
2800}
2801
2802function hidePaymentSection() {
2803     
2804    if(Form.paymentSection.isPaymentBlockPresent() && document.getElementById(Form.paymentSection.getSectionContainerId()) != null)
2805        document.getElementById(Form.paymentSection.getSectionContainerId()).vanish();
2806
2807}
2808
2809function showPaymentMethodToggleButtons() {
2810
2811    if (document.getElementById('paymentToggleRow') != null)
2812        document.getElementById('paymentToggleRow').show();
2813
2814}
2815
2816function hidePaymentMethodToggleButtons() {
2817
2818    if (document.getElementById('paymentToggleRow') != null)
2819        document.getElementById('paymentToggleRow').vanish();
2820
2821}
2822
2823function initializeThemeState() {
2824
2825    //Get UI state 
2826    themeUIStateConfig = Form.GetUIStateOrDefault();
2827
2828    console.log('**STD THM: Theme state initialization started for ' + themeName + ' version ' + themeVersion.toString());
2829
2830    console.log('**STD THM: theme state: ' + JSON.stringify(themeUIStateConfig));
2831
2832    //read original button text
2833    if (document.getElementById('ctl00_nextButt') != null && !isBlank(document.getElementById('ctl00_nextButt').value))
2834        originalButtonText = document.getElementById('ctl00_nextButt').value;
2835
2836}
2837
2838function getWebFormAdditionalPaymentWidgetElement() {
2839    var retVal = null;
2840
2841    for (var x = 0; x < WebFormContext.Form.Fields.length; x++)
2842        if (WebFormContext.Form.Fields[x].Type.Id == 115)
2843            retVal = document.getElementById(WebFormContext.Form.Fields[x].DomId);
2844
2845    return retVal;
2846
2847}
2848 
2849function initializeTheme() {
2850
2851    console.log('**STD THM: Theme initialization started for ' + themeName + ' version ' + themeVersion.toString());
2852
2853    console.log('**STD THM: Form Mode: ' + WebFormContext.Form.RenderMode);
2854    console.log('**STD THM: Form Step: ' + WebFormContext.Form.StepName);
2855    console.log('**STD THM: Form View: ' + WebFormContext.Form.RenderedViewName);
2856
2857    //INITIALIZE SLOP DEPENDENCIES
2858    var tribTypeFld = getTributeTypeElement();
2859    if (tribTypeFld != null)
2860        tribTypeFld.addClassName('TributeType');
2861
2862    var tribNameFld = getTributeNameElement();
2863    if (tribNameFld != null)
2864        tribNameFld.addClassName('TributeName');
2865
2866    var additionalDonFld = getWebFormAdditionalPaymentWidgetElement();
2867    if (additionalDonFld != null) {
2868        additionalDonFld.addClassName('DonationAmount');
2869
2870        var additionalDonFldLabel = additionalDonFld.parentElement.querySelector('label.tsFormLabels');
2871        if (additionalDonFldLabel != null)
2872            additionalDonFldLabel.addClassName('DonationAmount');
2873    }
2874
2875    //Payment Amount Section Initialization
2876    //-------------------------------------
2877    achTypeSection = $('.AccountType').closest('.tsFormRows');
2878
2879    if(document.getElementById('paypalToggle') != null)
2880        paypalToggleContainer = getFirstParentWithClass(document.getElementById('paypalToggle'), 'paymentTypeContainer');
2881
2882    //Payment Frequency Section Initialization
2883    //----------------------------------------
2884   
2885    frequencyRow = getFirstParentWithClass(document.getElementById(Form.amountSection.getFrequencyFieldDomID()), 'tsFormRows');
2886    frequencyDropdown = document.getElementById(Form.amountSection.getFrequencyFieldDomID());
2887
2888    if (frequencyDropdown != null && frequencyDropdown.tagName == 'SELECT')
2889        initializePaymentFrequencySection();        
2890
2891    //Contact Section Initialization
2892    //------------------------------
2893    initializeContactInfoSection();
2894
2895    //Tribute Section Initialization
2896    //------------------------------
2897    tributeSection = $('.TributeSectionContainer');
2898
2899    if (document.querySelector('.TributeSectionContainer') != null)
2900    {
2901
2902        //tributeAckNameSection = $('.RecipientFirstName, .RecipientLastName').closest('.tsFormRows');
2903        tributeAckNameSection = [];
2904        for (var x = 0; x < WebFormContext.Form.Fields.length; x++) { 
2905
2906            var fld = WebFormContext.Form.Fields[x];
2907            if ((fld.Type.Id == 34 || fld.Type.Id == 36) && !isBlank(fld.DomId)) { 
2908
2909                if(fld.Type.Id == 34)
2910                    document.getElementById(fld.DomId).addClassName('RecipientFirstName');
2911                else
2912                    document.getElementById(fld.DomId).addClassName('RecipientLastName');
2913
2914                tributeAckNameSection.push(document.getElementById(fld.DomId).closest('.tsFormRows'));                                                  
2915
2916            }
2917
2918        }
2919
2920        //tributeAckAddressSection = $('.AcknowledgeeAddress1, .AcknowledgeeAddress2, .AcknowledgeePostalCode, .AcknowledgeeCity, .AcknowledgeeState, .AcknowledgeeCountry').closest('.tsFormRows');
2921        tributeAckAddressSection = [];
2922        for (var x = 0; x < WebFormContext.Form.Fields.length; x++) { 
2923
2924            var fld = WebFormContext.Form.Fields[x];
2925            if ((fld.Type.Id == 41 || fld.Type.Id == 42 || fld.Type.Id == 45 || fld.Type.Id == 46 || fld.Type.Id == 47 || fld.Type.Id == 48) && !isBlank(fld.DomId)) { 
2926
2927                switch (fld.Type.Id) {
2928                    case 41:
2929                        document.getElementById(fld.DomId).addClassName('AcknowledgeeAddress1');
2930                        break;
2931                    case 42:
2932                        document.getElementById(fld.DomId).addClassName('AcknowledgeeAddress2');
2933                        break;                   
2934                    case 45:
2935                        document.getElementById(fld.DomId).addClassName('AcknowledgeeCity');
2936                        break;
2937                    case 46:
2938                        document.getElementById(fld.DomId).addClassName('AcknowledgeeState');
2939                        break;
2940                    case 47:
2941                        document.getElementById(fld.DomId).addClassName('AcknowledgeePostalCode');
2942                        break;
2943                    case 48:
2944                        document.getElementById(fld.DomId).addClassName('AcknowledgeeCountry');
2945                        break;
2946                }
2947
2948                tributeAckAddressSection.push(document.getElementById(fld.DomId).closest('.tsFormRows'));                                                  
2949
2950            }
2951
2952        }
2953          
2954        //tributeAckEmailSection = $('.AcknowledgeeEmailAddress').closest('.tsFormRows');
2955        tributeAckEmailSection = [];
2956        for (var x = 0; x < WebFormContext.Form.Fields.length; x++) { 
2957
2958            var fld = WebFormContext.Form.Fields[x];
2959            if ((fld.Type.Id == 56) && !isBlank(fld.DomId) && document.getElementById(fld.DomId) != null) { 
2960                document.getElementById(fld.DomId).addClassName('AcknowledgeeEmailAddress');
2961                tributeAckEmailSection.push(document.getElementById(fld.DomId));                                                  
2962            }
2963
2964        }
2965
2966        //tributeAckMessageSection = $('.PersonalMessage').closest('.tsFormRows');
2967        tributeAckMessageSection = [];
2968        for (var x = 0; x < WebFormContext.Form.Fields.length; x++) { 
2969
2970            var fld = WebFormContext.Form.Fields[x];
2971            if ((fld.Type.Id == 32) && !isBlank(fld.DomId) && document.getElementById(fld.DomId) != null) { 
2972                document.getElementById(fld.DomId).addClassName('PersonalMessage');
2973                tributeAckMessageSection.push(document.getElementById(fld.DomId));                                                  
2974            }
2975
2976        }
2977
2978        inializeTributeSection();        
2979
2980        inializeTributeAcknowledgeeSection();
2981
2982        disableTributeAcknowledgeeEmailRequiredValidator(); //needed at startup because inializeTributeAcknowledgeeSection enables validator as default
2983
2984    }
2985
2986    //Billing Info Section Initialization
2987    //-------------------------------------
2988    var billingSectionContainer = document.createElement('div');
2989    billingSectionContainer.setAttribute('id', 'BillingSection');
2990
2991    var billingSectionFields = $('.BillingStateorProvince, .BillingUnitorApartmentNumber, .BillingStreetAddress, .BillingAddress1, .BillingAddress2, .BillingPostalCode, .BillingCity, .BillingState, .BillingCountry').closest('.tsFormRows');
2992    $(billingSectionFields).wrapAll(billingSectionContainer);
2993
2994    billingSection = document.getElementById('BillingSection');
2995
2996    console.log('STANDRD theme billing section: ' + billingSection);
2997
2998    //add billing info different toggle button and show hide
2999    //*************************************************** */
3000
3001    //inject billing selector above section
3002    var billingAddressSectionToggleMarkup = '<div id="billingDiffToggleContainer" class="tsFormRows"><input id="billingDiffToggle" type="checkbox"><label for="billingDiffToggle">Is your billing info different?</label></div>';
3003
3004    if (Form.paymentSection.isPaymentBlockPresent() && billingSection != null)
3005        billingSection.insertAdjacentHTML('beforeBegin', billingAddressSectionToggleMarkup);
3006    else
3007        $('.BillingAddress1').closest('.tsFormRows').before(billingAddressSectionToggleMarkup);
3008
3009    //hide billing section by default - important for one click giving
3010    //different than hideBillingInfoSection() because we don't want to actually change the state for IsBillingInfoDifferent
3011    //billingSection.vanish();
3012    //$(billingSection).hide();
3013
3014    //bind user interaction events 
3015    var billingInfoDifferentCheckbox = document.getElementById('billingDiffToggle');
3016    if (billingInfoDifferentCheckbox != null) {
3017
3018        billingInfoDifferentCheckbox.addEventListener('change', function () {
3019
3020            if (document.getElementById('billingDiffToggle').checked)
3021                showBillingInfoSection();
3022            else
3023                hideBillingInfoSection();
3024
3025        });
3026        
3027        if (themeUIStateConfig.IsBillingInfoDifferent) {
3028            billingInfoDifferentCheckbox.checked = true;
3029            showBillingInfoSection();
3030        }
3031        else {
3032            billingInfoDifferentCheckbox.checked = false;
3033            hideBillingInfoSection();
3034        }        
3035
3036    }
3037
3038    //******************************************************* */
3039    //end add billing info different toggle button and show hide
3040
3041    //miscellaneous class style casting
3042    //---------------------------------
3043    $('.single-line-address-contact').addClass('three-quarter first');
3044    $('.isDonorUnitNumber').addClass('one-quarter');
3045
3046    //removed jquery hack for .Amount and .Currency and moved to structured payment method section initialization (4.26.2023) //.Amount, .Currency, .BillingStateorProvince, .BillingUnitorApartmentNumber, .BillingStreetAddress, 
3047    $('.isDonorFirstName, .isDonorAddress1, .isDonorCity, .AcknowledgeeAddress1, .AcknowledgeePostalCode, .AcknowledgeeState, .BillingAddress1, .BillingStreetAddress, .BillingPostalCode, .BillingState, .BillingStateorProvince').closest('.tsFormRows').addClass('half first');
3048    $('.isDonorLastName, .isDonorAddress2, .isDonorState_id, .AcknowledgeeAddress2, .AcknowledgeeCity, .AcknowledgeeCountry, .BillingAddress2, .BillingUnitorApartmentNumber, .BillingCity, .BillingCountry').closest('.tsFormRows').addClass('half last');
3049
3050    $('.RecipientFirstName').closest('.tsFormRows').addClass('half first');
3051    $('.RecipientLastName').closest('.tsFormRows').addClass('half last');
3052
3053    $('.ExpirationMonth').closest('.tsFormRows').addClass('half first');
3054    $('.ExpirationYear').closest('.tsFormRows').addClass('half last');
3055
3056    //logic for phone type input[type="text"] 
3057    var phoneFldElem = document.querySelector('.isPhone');    
3058    var phoneTypeFldElem = document.querySelector('.tsPhoneClassSelectors');    
3059
3060    if (phoneFldElem != null && phoneTypeFldElem != null)
3061    {
3062        phoneFldElem.parentNode.addClassNames('half first');
3063        phoneTypeFldElem.parentNode.addClassNames('half last');
3064    }    
3065
3066    //Event Ticket Section Initialization
3067    //-----------------------------------
3068    initializeEventTicketInfoSection();
3069
3070    console.log('**STD THM: ' + themeName + ' theme version ' + themeVersion.toString() + ' initialized');
3071
3072    console.log('**STD THM: Current Step: ' + WebFormContext.Form.StepName + ' (' + WebFormContext.Form.StepNumber.toString() + ')');
3073    console.log('**STD THM: Rendered View: ' + WebFormContext.Form.RenderedViewName + ' (' + WebFormContext.Form.RenderedViewNumber.toString() + ')');
3074
3075    themeLoaded = true;
3076
3077    var membTpElem = Form.GetMembershipTypeFieldElement();
3078    if (membTpElem != null && membTpElem.hasClassName('ceMembershipFormTemplate'))
3079    { 
3080
3081        trySetMembershipTypeAmount();
3082
3083        //disable amount & currency if found
3084        var amtFld = Form.GetFirstAmountFieldElement();
3085        if (amtFld != null) { 
3086            amtFld.addClassName('readOnlyMode');
3087            amtFld.setAttribute('readonly', 'readonly');
3088        }
3089
3090        var curDdFld = Form.GetCurrencyFieldElement();
3091        if (curDdFld != null) { 
3092            curDdFld.addClassName('readOnlyMode');
3093            curDdFld.setAttribute('readonly', 'readonly');
3094        }
3095
3096    }
3097     
3098    Form.paymentSection.onPaymentMethodChanged(function (eventData) {
3099
3100        console.log('**STD THM: payment section method changed event fired');
3101
3102        setPaymentInfoUIState(eventData.paymentMethodId, eventData.walletTypeId);
3103
3104        callUIUpdatesForAmountOrPaymentChange(true);
3105
3106    });
3107
3108    Form.paymentSection.onPayProcessingFeeOptionChanged(function (data) {
3109
3110        console.log('**STD THM: pay processing fees option changed event fired');
3111
3112        callUIUpdatesForAmountOrPaymentChange();
3113
3114    });
3115
3116    Form.onPromoCodeChanged(function (data) {
3117
3118        console.log('**STD THM: promo code call back for standard theme fired');        
3119
3120        callUIUpdatesForAmountOrPaymentChange(); //legacyAmountChangedPaymentSectionToggle();
3121
3122    });
3123
3124    callUIUpdatesForAmountOrPaymentChange();
3125
3126    //Required Field Indication
3127    //-------------------------------------
3128    if (WebFormContext.Form.StepName == 'Initial Step' && WebFormContext.Form.RenderedViewName == 'Initial View')
3129        hideAllFieldValidationMarkers();
3130 
3131    //do not love the below
3132    var allRows = document.querySelectorAll('.tsFormRows');
3133    for (var x = 0; x < allRows.length; x++) 
3134        if ((!allRows[x].querySelector('span.tsVal_itemMarker:not([id*="regex"])') && (allRows[x].querySelector('.tsTextBoxes') || allRows[x].querySelector('.tsDropDownLists'))) && !allRows[x].hasClassName('event-info-row')) {
3135
3136            var rowLabel = allRows[x].querySelector('label.tsFormLabels');
3137            if (rowLabel != null && !isBlank(rowLabel.innerHTML) && rowLabel.innerHTML != '&nbsp;' && !rowLabel.hasClassName('ceMembershipFormTemplate') && !rowLabel.hasClassName('SubTotal')) { 
3138
3139                //omit special fields - e.g. single line address
3140                var isNotApplicableField = false;
3141
3142                var labelFldElem = getFieldForLabel(rowLabel);
3143                if (labelFldElem != null && labelFldElem.hasClassName('tsTextBoxes_sysSingleLineAddress'))
3144                    isNotApplicableField = true;
3145                
3146                if(!isNotApplicableField)
3147                    rowLabel.innerHTML = rowLabel.innerHTML + '<span style="color:#818a91">&nbsp;(not required)</span>';            
3148
3149            }
3150
3151        }        
3152
3153    if (isOneClickShown())
3154    {
3155
3156        console.log('**STD THM: Trigger One Click View On Startup (theme loaded: ' + themeLoaded + ')');
3157
3158        //always hide payment info on startup for one-click
3159        //oneClick_overrideEnabledFormRenderer();
3160        //hidePaymentMethodToggleButtons();
3161        if (WebFormContext.Form.StepName == 'Initial Step')
3162            oneClick_overrideEnabledFormRenderer();
3163        else if (WebFormContext.Form.StepName == 'Confirmation Step' && themeUIStateConfig.PaymentMethodId == 0)
3164            oneClick_overrideEnabledFormRenderer();                
3165
3166    }    
3167
3168    //hide payment block on error view
3169    if(WebFormContext.Form.RenderedViewName == 'Error View')
3170        hidePaymentSection();
3171
3172    //IMPORTANT: theme initialized callback must fire last   
3173    console.log('**STD THM: Fire theme initialized event in base forms api');
3174    Form.FireThemeInitializedEvent();
3175
3176}
3177
3178//Now let's initialize the theme stuff
3179Form.RegisterPreInitializeCallBack(initializeThemeState);  
3180Form.RegisterInitializedCallBack(initializeTheme); 
3181
3182Form.AmountSection.RegisterInitializedCallBack(initializePaymentAmountSection); 
3183Form.PaymentSection.RegisterInitializedCallBack(initializePaymentMethodSection); 
3184
3185Form.AmountSection.RegisterPaymentFrequencyChangedCallBack(handleFrequencyChangedCallback);
3186
3187Form.RegisterMembershipTypeChangedCallBack(handleMembershipTypeChanged);

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.