PageSourceSearch

https://www.thecharlottepost.com/js/library_scripts.js?v=2023.10.10

js thecharlottepost.com collected 2026-10-02 04:02:48 UTC 82,175 bytes, 2,624 lines download raw bytes

1/**
2 * Global Freedom vars and Util functions
3 * @param init
4 * @preserve
5 *
6 */
7var Freedom = Freedom || {
8    'config': {},
9    'notifications': [],
10    'UI': {},
11    'ajax': {},
12    'view': {}
13};
14function isWhite(){
15    return String(window.location.href).indexOf('admin.php') == -1
16}
17Freedom.getQueryParameters = function(queryString) {
18    var queryString = typeof queryString == 'string' ? queryString : location.search.substring(1);
19    var queryParameters = {},
20        re = /([^&=]+)=([^&]*)/g, m;
21
22    while (m = re.exec(queryString)) {
23        queryParameters[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
24    }
25
26    return queryParameters;
27};
28
29// these are old and are only for existing code. do not use
30function MakeTag(tag, val) {
31    return IsValid(val) ? '&' + tag + '=' + val : '';
32}
33
34function MakeURL(url) {
35    var u = location.href.split('#')[0].split('&')[0];
36    var j = u.indexOf('.php');
37    if(j > -1) {
38        var i = url.split('&')[0].indexOf('.php');
39        if(i > -1) url = url.substring(i + 4);
40        url = u.substring(0, j + 4) + '?' + url;
41        url = url.replace('?&', '?');
42        return url.replace('??', '?');
43    } else {
44        //hurls are on if 'php' cant be found
45        if ( isWhite() ){
46            //base tag should take care of the prefix
47            u = 'index.php?';
48        }
49    }
50    var c = u.charAt(u.length - 1);
51    if(c != '?' && c != '&') {
52        u += (u.indexOf('?') == -1) ? '?' : '&';
53    }
54    u += url;
55    return u.replace('/?', '?');
56}
57
58function IsValid(obj) {
59    return(obj != null && typeof(obj) != 'undefined');
60}
61
62
63/**
64 * Returns a function, that, as long as it continues to be invoked, will not
65 * be triggered. The function will be called after it stops being called for
66 * N milliseconds. If `immediate` is passed, trigger the function on the
67 * leading edge, instead of the trailing.
68 *
69 * @param func
70 * @param wait
71 * @param immediate
72 * @returns {function(...[*]=)}
73 */
74function debounce(func, wait, immediate) {
75    var timeout;
76
77    return function() {
78        var context = this,
79            args = arguments;
80
81        var callNow = immediate && !timeout;
82
83        clearTimeout(timeout);
84
85        timeout = setTimeout(function() {
86
87            timeout = null;
88
89            if (!immediate) {
90                func.apply(context, args);
91            }
92        }, wait);
93
94        if (callNow) func.apply(context, args);
95    }
96}
97
98function setCookie(e,t,o){var n=new Date;n.setTime(n.getTime()+24*o*60*60*1e3);var r="expires="+n.toUTCString();document.cookie=e+"="+t+";"+r+";path=/"}
99function getCookie(e){for(var t=e+"=",o=document.cookie.split(";"),n=0;n<o.length;n++){for(var r=o[n];" "==r.charAt(0);)r=r.substring(1);if(0==r.indexOf(t))return r.substring(t.length,r.length)}return""}
100
101
102function isOverflown(_a) {
103    var clientWidth = _a.clientWidth, clientHeight = _a.clientHeight, scrollWidth = _a.scrollWidth, scrollHeight = _a.scrollHeight;
104    return scrollHeight > clientHeight || scrollWidth > clientWidth;
105}
106function goToUrl(url) {
107    window.location.href = url;
108    return false;
109}
110
111'use strict';
112
113/**
114 * Collection of javascript functions used by commerce_checkout form
115 * @param init
116 * @preserve
117 *
118 */
119function CommerceToolkit( init ){
120
121    //private global vars
122    var g_jsonUrl        = 'index.php?src=commerce&srctype=ajax';
123    var g_fieldPrefix    = 'formField_';
124    var g_multipageId    = $( 'input[ name$="multipage_id" ]' ).val();
125    var g_postedVars     = '';
126    var g_resetState     = true;
127    var g_hiddenShipping = false;
128    var g_useFormData    = false;
129    var self = this;
130
131
132    $.ajaxSetup( { url: g_jsonUrl, type : 'GET', dataType: 'json' } );
133
134    requestJson( 'set_form_id', { multipage_id: g_multipageId } );
135
136    if( init == undefined || init == true ){
137        g_postedVars = requestJson( 'get_posted_vars', { multipage_id: g_multipageId } );
138    }
139
140    //private requestJson synchronous requests,
141    function requestJson( cmd, data ){
142
143        if( data == undefined ){
144            data  = {};
145        }
146
147        data.cmd = cmd;
148        let jqXHR  = $.ajax( { data: data, async: false } );
149
150        if (jqXHR) {
151            try {
152                return JSON.parse(jqXHR.responseText);
153            } catch (e) {
154                console.error('JSON Parse error');
155            }
156        } else {
157            return { status: -1, data: {} };
158        }
159
160    }//requestJson
161
162
163    //private
164    function setInnerHtmlById( elementId, html ){
165
166        $( "#" + elementId).html(html);
167    }
168
169    function setInputValue( fieldName, value ){
170
171        $('input[ name$="' + fieldName + '" ]').val(value);
172    }
173
174    function getInputValue( fieldName ){
175
176        return $('input[ name$="' + fieldName + '" ]').val();
177    }
178
179    //private
180    function setOption( fieldName, value ){
181
182        $('select[ name$="' + fieldName + '" ]').val('').val(value);
183
184    }
185
186    //private
187    function ajaxSelectOptions( fieldName, commerceFunc, defaultVal, alwaysCallback ){
188
189        if( alwaysCallback == undefined ){
190            alwaysCallback = function(){};
191        }
192
193
194        var data = {};
195        data.cmd = commerceFunc;
196
197        var jqXHR = $.ajax( { data: data } )
198            .done( function( data  ) {
199
200                setSelectOptions( fieldName, data, defaultVal );
201
202            })//done
203            .fail( function() {
204                data = '<option>Request failed to fetch options</option>';
205                setSelectOptions( fieldName, data, '' );
206
207            })//fail
208            .always ( alwaysCallback );
209
210
211    }//ajaxSelectOptions
212
213
214    function setSelectOptions( fieldName, data, defaultVal ){
215
216        $('select[ name$="' + fieldName + '" ]').html(data);
217        var postedVal = getPostedValue( fieldName );
218        setOption( fieldName, postedVal );
219
220        setDefaultOption( fieldName, defaultVal );
221    }
222
223
224    function setDefaultOption( fieldName, defaultVal ){
225
226        if( $('select[ name$="' + fieldName + '" ]').val() == '' ){
227            setOption( fieldName, defaultVal );
228        }
229
230    }//setDefaultOption
231
232
233    //private
234    function getPostedValue( fieldName ){
235
236        var prefixedFieldName = g_fieldPrefix + fieldName;
237
238        return g_postedVars[ prefixedFieldName ] || '';
239
240    }
241
242    function disableInput( fieldName ){
243
244        $(':input[ name$="' + fieldName + '" ]').attr('disabled', 'disabled');
245    }
246
247    function enableInput( fieldName ){
248
249        $(':input[ name$="' + fieldName + '" ]').removeAttr('disabled');
250    }
251
252
253
254    function addHiddenField( objParent, fieldName, value ){
255
256        objParent.append( '<input type="hidden" value="' + value + '" name="' + g_fieldPrefix + fieldName + '" id="hiddenField_' + fieldName + '" >' );
257
258    }
259
260
261    function togglePaymentType( total ){
262
263        if( total == 0 ){
264            //if final price is 0 disable payment option
265            setOption( 'payment_type' , '' );
266            //fire change event
267            $('select[ name$="payment_type" ]').change();
268            //disable payment
269            disableInput( 'payment_type' );
270
271        } else {
272            enableInput( 'payment_type' );
273        }
274    }
275
276
277    ///////////////////////  PUBLIC  ///////////////////////
278
279
280
281    /**
282     * SetFinalTotal
283     */
284    this.SetFinalTotal = function ( inputName ){
285
286        if( inputName == undefined ){
287            inputName  = 'cart_final_total';
288        }
289
290        var data = {};
291        data.cmd = 'get_final_total';
292
293        $.ajax( { data: data } )
294            . done( function( data  ) {
295                setInputValue( inputName, data );
296
297                togglePaymentType( data );
298
299            });//done
300
301    };//SetTotal
302
303    /**
304     * SetSubTotal
305     */
306    this.SetSubTotal = function ( inputName ){
307
308        if( inputName == undefined ){
309            inputName  = 'cart_subtotal';
310        }
311
312        var data = {};
313        data.cmd = 'get_subtotal';
314
315        $.ajax( { data: data } )
316            . done( function( data  ) {
317                setInputValue( inputName, data );
318            });//done
319    };//SetSubTotal
320
321    /**
322     * SetSurcharge
323     */
324    this.SetSurcharge = function ( inputName ){
325
326        if( inputName == undefined ){
327            inputName  = 'cart_surcharge';
328        }
329
330        var data = {};
331        data.cmd = 'get_surcharge';
332
333        $.ajax( { data: data } )
334            . done( function( data  ) {
335                setInputValue( inputName, data );
336            });//done
337
338    };//SetSurcharge
339
340    /**
341     * SetShippingPrice
342     */
343    this.SetShippingPrice = function ( inputName ){
344
345        if( inputName == undefined ){
346            inputName  = 'cart_shipping';
347        }
348
349        var data = {};
350        data.cmd = 'get_shipping_price';
351
352        $.ajax( { data: data } )
353            . done( function( data  ) {
354                setInputValue( inputName, data );
355            });//done
356
357    };//SetShippingPrice
358
359    /**
360     * SetTax
361     */
362    this.SetTax = function ( inputName ){
363
364        if( inputName == undefined ){
365            inputName  = 'cart_tax';
366        }
367
368        var data = {};
369        data.cmd = 'get_tax';
370
371        $.ajax( { data: data } )
372            . done( function( data  ) {
373                setInputValue( inputName, data );
374            });//done
375
376    };//SetTax
377
378
379    /**
380     * EstimateTax
381     */
382    this.EstimateTax = function( state ){
383
384        var data = {};
385        data.state = state;
386
387        return requestJson( 'get_estimated_tax', data );
388
389    };
390
391
392    /**
393     * SetSummary
394     */
395    this.SetSummary = function(){
396
397        var data = {};
398        data.cmd = 'get_summary';
399
400
401        $.ajax( { data: data } )
402            . done( function( data  ) {
403                setInnerHtmlById( 'cart_subtotal'   , data.subtotal );
404
405                if( data.coupon_amuont != '' ){
406                    $('#cart_coupon_row').show();
407                    setInnerHtmlById( 'cart_coupon'     , data.coupon_amuont );
408                }else{
409                    $('#cart_coupon_row').hide();
410                }
411
412                setInnerHtmlById( 'cart_surcharge'  , data.surcharge );
413                setInnerHtmlById( 'cart_shipping'   , data.shipping );
414
415                if( data.tax_1 != '' && data.tax_2 != '' ){
416
417                    $('#cart_tax_total_row').hide();
418                    $('#cart_tax_inc_row').hide();
419
420                    $('#cart_tax_1_row').show();
421                    setInnerHtmlById( 'cart_tax_1'        , data.tax_1 );
422
423                    $('#cart_tax_2_row').show();
424                    setInnerHtmlById( 'cart_tax_2'        , data.tax_2 );
425
426
427                } else{
428
429                    $('#cart_tax_1_row').hide();
430                    $('#cart_tax_2_row').hide();
431                    $('#cart_tax_total_row').hide();
432                    $('#cart_tax_inc_row').hide();
433
434                    if( data.tax_total != '' ) {
435
436                        $('#cart_tax_total_row').show();
437                        setInnerHtmlById( 'cart_tax_total'        , data.tax_total );
438                    }else if( data.tax_inc != '' ){
439
440                        $('#cart_tax_inc_row').show();
441                        setInnerHtmlById( 'cart_tax_inc'        , data.tax_inc );
442
443                    }
444
445
446                }
447
448
449
450                setInnerHtmlById( 'cart_total'      , data.total );
451
452                if( data.giftcard_amuont != '' ){
453                    $('#cart_giftcard_row').show();
454                    $('#cart_final_total_row').show();
455                    setInnerHtmlById( 'cart_giftcard'   , data.giftcard_amuont );
456                    setInnerHtmlById( 'cart_final_total', data.final_total );
457                } else {
458                    $('#cart_giftcard_row').hide();
459                    $('#cart_final_total_row').hide();
460                }
461
462                //this will set any hidden fields on the form
463                setInputValue( 'cart_subtotal'   , data.subtotal );
464                setInputValue( 'cart_coupon'     , data.coupon_amuont );
465                setInputValue( 'cart_surcharge'  , data.surcharge );
466                setInputValue( 'cart_shipping'   , data.shipping );
467                setInputValue( 'cart_tax_1'      , data.tax_1 );
468                setInputValue( 'cart_tax_2'      , data.tax_2 );
469                setInputValue( 'cart_total'      , data.total );
470                setInputValue( 'cart_giftcard'   , data.giftcard_amuont );
471                setInputValue( 'cart_final_total', data.final_total_raw );
472
473                togglePaymentType( data.final_total_raw );
474
475                CommerceToolkit.HideChargesSummary( '' );
476
477            })//done
478            . fail(function(){
479                var naVal = 'N/A';
480                setInnerHtmlById( 'cart_subtotal'   , naVal );
481                setInnerHtmlById( 'cart_coupon'     , naVal );
482                setInnerHtmlById( 'cart_surcharge'  , naVal );
483                setInnerHtmlById( 'cart_shipping'   , naVal );
484                setInnerHtmlById( 'cart_tax_total'  , naVal);
485                setInnerHtmlById( 'cart_total'      , naVal );
486                setInnerHtmlById( 'cart_giftcard'   , naVal );
487                setInnerHtmlById( 'cart_final_total', naVal );
488
489            });//fail
490
491    };
492
493
494    /**
495     * SetPayments
496     */
497    this.SetPayments = function (loadOptions){
498
499        var fieldName = 'payment_type';
500
501        var elementPaymentType = $( 'select[ name$="'+fieldName+'" ]');
502
503        elementPaymentType.prepend('<option value="">-- Select -- </option>');
504
505        if(loadOptions === true) {
506            var jqXHR = ajaxSelectOptions(fieldName, 'get_payments', null, function () {
507                elementPaymentType.change();
508            });
509        }
510
511        //event handler
512        elementPaymentType . change( function(){
513            CommerceToolkit.HidePaymentSections();
514
515            var selectedValue = $(this).val();
516
517            if (selectedValue === '' && CommerceToolkit.GetValue( 'cart_final_total' ) == 0 ){
518                selectedValue = 'free';
519            }
520
521            $('#commerceCheckoutSection_' + selectedValue).show();
522            $('#commerceCheckoutSection_' + selectedValue + ':input').removeAttr('disabled');
523
524        });
525
526    };//SetPayments
527
528    /**
529     * SetCreditCards
530     */
531    this.SetCreditCards = function (){
532
533        var fieldName = 'card_type';
534
535        var elementPaymentType = $( 'select[ name$="'+fieldName+'" ]');
536
537        var jqXHR = ajaxSelectOptions( fieldName, 'get_credit_cards', null, function(){ elementPaymentType.change(); } );
538
539    };//SetCreditCards
540    /**
541     * SetCreditCards
542     */
543    this.SetAutoCardType = function (){
544
545        $( 'input[name$=card_number]' ).on('keyup', function () {
546            var $cardType = _creditCardTypeFromNumber( $(this).val()  );
547            $( 'select[name$=card_type]' ).val( $cardType );
548        } );
549    };//SetCreditCards
550
551    function _creditCardTypeFromNumber( num ) {
552        // first, sanitize the number by removing all non-digit characters.
553        num = num.replace( /[^\d]/g, '' );
554        // now test the number against some regexes to figure out the card type.
555        if ( num.match( /^5[1-5]\d{0,14}$/ ) ) {
556            return 'mastercard';
557        } else if ( num.match( /^4\d{0,15}$/ ) ) {
558            return 'visa';
559        } else if ( num.match( /^3[47]\d{0,13}$/ ) ) {
560            return 'amex';
561        } else if ( num.match( /^6011\d{0,12}$/ ) ) {
562            return 'discover';
563        }
564        return '';
565    }
566
567    /**
568     * SetCountries
569     */
570    this.SetCountries = function ( defaultVal ){
571
572
573        if( defaultVal == undefined ){
574            defaultVal = '';
575        }
576
577
578        var billCountryObj = $('select[ name$="bill_country" ]');
579        var shipCountryObj = $('select[ name$="ship_country" ]');
580
581        billCountryObj . change( function(){
582            var country = $(this).val();
583            countriesOnChangeEventHandler( 'bill_state', country );
584        });
585
586        shipCountryObj . change( function(){
587            var country = $(this).val();
588            countriesOnChangeEventHandler( 'ship_state', country );
589        });
590
591        var data = {};
592        data.cmd = 'get_countries';
593
594        $.ajax( { data: data } )
595            . done( function( data  ) {
596
597                if( data == 'United States' ){
598
599                    //if United States only turn country selects into hidden fields
600
601                    var billCountryParent = billCountryObj.parent();
602
603                    billCountryParent.html( '<span class="unitedStatesValue">' +data +'</span>');
604                    addHiddenField( billCountryParent.parent(), 'bill_country', data );
605
606                    var shipCountryParent = shipCountryObj.parent();
607
608                    shipCountryParent.html( data );
609                    addHiddenField( shipCountryParent, 'ship_country', data );
610
611                }else{
612                    setSelectOptions( 'bill_country', data, defaultVal );
613                    setSelectOptions( 'ship_country', data, defaultVal );
614
615                }
616
617            })//done
618            .fail( function() {
619
620                data = '<option>Request failed to fetch country options</option>';
621
622                setSelectOptions( 'bill_country', data, defaultVal );
623                setSelectOptions( 'ship_country', data, defaultVal );
624
625            })//fail;
626            .always ( function(){
627
628                g_resetState = false;
629                billCountryObj.change();
630
631                g_resetState = false;
632                shipCountryObj.change();
633
634                //if shiping as billing, hide shipping inputs
635                toggleShippingInputs();
636            });
637
638
639        //private event handler
640        function countriesOnChangeEventHandler( stateFieldName, country ){
641
642            var stateSelectObj = $('select[ name$="' + stateFieldName + '"]');
643            var stateInputObj  = $('#textField_' + stateFieldName + '');
644
645            if( country == 'Canada' || country == 'United States' ){
646                //set state/province
647                stateSelectObj.show();
648                stateSelectObj.removeAttr( 'disabled' );
649
650                stateInputObj.hide();
651                stateInputObj.attr( 'disabled', 'disabled' );
652
653                $( stateSelectObj ).find( 'optgroup[ label!="' + country + '"]' ).hide();
654                $( stateSelectObj ).find( 'optgroup[ label="' + country + '"]' ).show();
655
656                if( g_resetState == true ){
657                    setOption( stateFieldName, '' );
658                }
659
660            } else {
661
662                stateSelectObj.hide();
663                stateSelectObj.attr( 'disabled', 'disabled' );
664
665                stateInputObj.show();
666                stateInputObj.removeAttr( 'disabled' );
667
668                if( g_resetState == true ){
669                    stateInputObj.val( '' );
670                }
671            }
672
673            g_resetState = true;
674
675
676        }//countriesOnChangeEventHandler
677
678
679
680        function toggleShippingInputs(){
681
682            var elementContext = $( 'input[ name$="bill_same_as" ]' );
683
684            //attach event handler
685            elementContext.on('change', _toggleShippingInputStates ).triggerHandler('change');
686
687            //when refreshed or posted back
688            // if( elementContext.is(':checked') ){
689            // 	elementContext.click();//fire the event to disable inputs, will uncheck
690            // 	elementContext.attr( 'checked','checked' );//make it checked after click event
691            // }
692
693        }
694
695        function _toggleShippingInputStates() {
696
697            var elementContext = $( 'input[ name$="bill_same_as" ]' );
698
699            if( elementContext.is(':checked') ){
700
701                disableInput( 'ship_firstname' );
702                disableInput( 'ship_lastname' );
703                disableInput( 'ship_companyname' );
704                disableInput( 'ship_address1' );
705                disableInput( 'ship_address2' );
706                disableInput( 'ship_city' );
707                disableInput( 'ship_state' );
708                disableInput( 'ship_province' );
709                disableInput( 'ship_zip' );
710                disableInput( 'ship_country' );
711
712            } else {
713                enableInput( 'ship_firstname' );
714                enableInput( 'ship_lastname' );
715                enableInput( 'ship_companyname' );
716                enableInput( 'ship_address1' );
717                enableInput( 'ship_address2' );
718                enableInput( 'ship_city' );
719                enableInput( 'ship_state' );
720                enableInput( 'ship_province' );
721                enableInput( 'ship_zip' );
722                enableInput( 'ship_country' );
723
724            }
725        }
726
727        window.f_commerce_tsi = _toggleShippingInputStates;
728
729    };//SetCountries
730
731
732    /**
733     * SetStates
734     */
735    this.SetStates = function ( defaultVal ){
736
737        if( defaultVal == undefined ){
738            defaultVal = '';
739        }
740
741        var data = {};
742        data.cmd = 'get_states';
743
744        addStateInputField( 'bill_state' );
745        addStateInputField( 'ship_state' );
746
747
748        var JqXHR = $.ajax( { data: data } )
749            . done( function( data  ) {
750                setSelectOptions( 'bill_state', data, defaultVal );
751                setSelectOptions( 'ship_state', data, defaultVal );
752            })//done
753            . fail( function() {
754                data = '<option>Request failed to fetch state options</option>';
755
756                setSelectOptions( 'bill_state', data, defaultVal );
757                setSelectOptions( 'ship_state', data, defaultVal );
758            });//fail;
759
760
761        //private
762        //if selected country is not US or Canada allow to type in state/province
763        function addStateInputField( fieldName ){
764
765            var objParent = $('select[ name$="' + fieldName + '"]' ) . parent();
766
767            var postedVal = getPostedValue( fieldName );
768            if( postedVal == undefined ){
769                postedVal = '';
770            }
771
772            objParent.append( '<input type="text" value="' + postedVal + '" name="' + g_fieldPrefix + fieldName + '" id="textField_' + fieldName + '" >' );
773            $('#textField_' + fieldName ).attr( 'disabled', 'disabled' ).hide();
774        }
775
776        return JqXHR;
777
778    };//SetStates
779
780
781    /**
782     * SetExpiration
783     */
784    this.SetExpirationField = function (){
785
786        var $input = $('#IDFormField_card_year_0');
787        var today = new Date();
788        var year = parseInt(today.getFullYear());
789
790        $input.html('');
791        $input.append("<option value=''>
791 </option>");
792
793        for (i=0; i<25; i++){
794            value = year + i;
795            $input.append("<option value='"+value+"'>"+value+"</option>");
796        }
797
798    }
799
800    /**
801     * SetShipping
802     */
803    this.SetShipping = function (bindChangeEvent, bUseFormData)
804    {
805        _setShipping(bindChangeEvent, bUseFormData);
806    }
807
808    //private
809    function _setShipping( bindChangeEvent, bUseFormData ){
810
811
812        if( bindChangeEvent == undefined ){
813            bindChangeEvent = true;
814        }
815
816        if( typeof( bUseFormData ) == "undefined" ){
817            g_useFormData = false;
818        } else {
819            g_useFormData = bUseFormData;
820        }
821
822        var fieldName = 'shipping_type';
823
824        var data = loadData( g_useFormData );
825
826        data.cmd         = 'get_shipping';
827
828        var shippingElement = $( 'select[ name$="'+fieldName+'" ]');
829
830
831        $.ajax( { data: data } )
832            . done( function( data  ) {
833
834                if( data == '*' ){ //free shipping
835                    if( g_hiddenShipping == false ){
836                        createFreeShippingSpan( data );
837                        g_hiddenShipping = true;
838                    }
839
840                    toggleShippingElement( true );
841
842                    shippingElement . html(  new Option( 'FREE', data  ) ).val( data );
843
844                } else {
845                    if( g_hiddenShipping == true ){
846                        toggleShippingElement( false );
847                    }
848
849                    var defaultVal = '';
850                    if( g_useFormData == true ){
851                        defaultVal = shippingElement.val();
852                    } else {
853                        defaultVal = getPostedValue( fieldName );
854                    }
855
856                    shippingElement . html( data );
857                    setOption( fieldName, defaultVal );
858
859                }
860
861                //fire event for reload or posting back
862                shippingElement.change();
863
864            })//done
865            . fail( function() {
866                shippingElement . html( '<option>Request failed to fetch shipping options</option>' );
867            });//fail
868
869
870        if( bindChangeEvent == true ){
871            //event handler
872            shippingElement . change( function(){
873
874                var shippingType = $(this).val();
875
876                var data = loadData( g_useFormData );
877
878                data.cmd           = 'set_shipping_info';
879                data.shipping_type = shippingType;
880
881                $.ajax( { data: data } )
882                    . done( function(){
883
884                        //refresh totals
885                        self.SetSummary();
886                    });//done
887
888
889            });//change
890
891        }//if
892
893        function createFreeShippingSpan( value ){
894
895            var parent = shippingElement.parent();
896
897            parent.append( '<span id="freeShippingSpan">FREE</span>' );
898
899        }
900
901
902        function toggleShippingElement( enableHidden ){
903
904            if( enableHidden == true ){
905
906                $('#freeShippingSpan').show();
907
908                shippingElement.hide();
909
910            }else{
911
912                $('#freeShippingSpan').hide();
913
914                shippingElement.show();
915
916            }
917        }
918
919
920        function loadData( bUseForm ){
921
922            var data = {};
923
924
925            var fieldPrefix = g_fieldPrefix;
926            var billSameAs = false;
927
928            if( bUseForm == false ){
929                if( g_postedVars[ fieldPrefix + 'bill_same_as' ] == 1 ){
930                    billSameAs = true;
931                }
932            } else {
933                billSameAs = $('[ name$="' + fieldPrefix + 'bill_same_as" ]' ).prop( 'checked' );
934            }
935
936
937            if( billSameAs == true ){
938                fieldPrefix = fieldPrefix + 'bill_';
939            } else {
940                fieldPrefix = fieldPrefix + 'ship_';
941            }
942
943            if( bUseForm == false ){
944
945                data.city    = g_postedVars[ fieldPrefix + 'city'];
946                data.zip     = g_postedVars[ fieldPrefix + 'zip'];
947                data.state   = g_postedVars[ fieldPrefix + 'state'];
948                data.country = g_postedVars[ fieldPrefix + 'country'];
949
950            } else {
951
952                data.city    = $( '[ name$="' + fieldPrefix + 'city" ]' ).val();
953                data.zip     = $( '[ name$="' + fieldPrefix + 'zip" ]' ).val();
954                data.state   = $( '[ name$="' + fieldPrefix + 'state" ]' ).val();
955                data.country = $( '[ name$="' + fieldPrefix + 'country" ]' ).val();
956
957            }
958
959            return data;
960        }
961
962    };//SetShipping
963
964    /**
965     * AddRefreshShippingButton
966     */
967    this.AddRefreshShippingButton = function( value ){
968
969        if( value == undefined ){
970            value  = 'Refresh';
971        }
972
973        var data = {};
974
975        var objShippingCombo = $( ':input[ name$="shipping_type" ]' );
976
977
978        var objContainer = objShippingCombo.parent();
979
980        objContainer.append( '<input type="button" class="button" value="' + value + '" id="refreshShippingBtn" >' );
981
982
983        var objRefreshBtn = $("#refreshShippingBtn");
984
985        objRefreshBtn . click( function(){
986            _setShipping( false, true );
987        });
988
989        /*on submit recalculate shipping in case some data changed*/
990        $('#refreshShippingBtn')
991            . closest( 'form' )
992            . submit( function(){
993
994                $.ajaxSetup( { async: false } );//need to wait for the call to finish before submitting
995                _setShipping( false, true );
996
997            });
998
999    };
1000
1001
1002    /**
1003     * SetMiniCartHtml
1004     */
1005    this.SetMiniCartHtml = function ( elementId, hideTotals ){
1006
1007        if( hideTotals == undefined ){
1008            hideTotals  = false;
1009        }
1010
1011        var data = {};
1012        data.cmd = 'get_cart';
1013
1014        $.ajax( { data: data } )
1015            . done( function( data  ) {
1016                setInnerHtmlById( elementId, data );
1017
1018                if( hideTotals == true ){
1019                    $('#shoppingCartCheckoutSummary').hide();
1020                }
1021            })//done
1022            . fail( function() {
1023                setInnerHtmlById( elementId, 'Mini cart failed to load.' );
1024            });//fail;
1025
1026    };//SetMiniCartHtml
1027
1028
1029
1030    /**
1031     * AddApplyGiftCardButton
1032     */
1033    this.AddApplyGiftCardButton = function( value, hideMessage ){
1034
1035        if( value == undefined ){
1036            value  = 'Apply';
1037        }
1038
1039        var hideMessageDuration = 1800;
1040
1041        if( hideMessage == undefined || hideMessage !== false ){
1042            hideMessage = true;
1043        }
1044
1045        if( $.isNumeric( hideMessage ) ){
1046            hideMessageDuration = hideMessage;
1047            hideMessage = true;
1048        }
1049
1050        var data = {};
1051
1052        var objGiftCard = $( ':input[ name$="giftcard_code" ]' );
1053
1054        //check if gift card already applied to the cart
1055        //show it in the input box, don't rely on POST
1056        data.cmd = 'get_applied_giftcard';
1057        $.ajax( { data: data } )
1058            . done( function( data  ) {
1059                objGiftCard.val( data );
1060            });//done
1061
1062
1063
1064        var objContainer = objGiftCard.parent();
1065
1066        objContainer.append( '<input type="button" class="button" value="' + value + '" id="applyGiftCardBtn" ><br /><span id="applyGiftCardMessage"></span>' );
1067
1068        var objApplyBtn = $( '#applyGiftCardBtn' );
1069
1070        objApplyBtn . click( function(){
1071
1072            data.cmd           = 'apply_giftcard';
1073            data.giftcard_code = objGiftCard.val();
1074
1075            $.ajax( { data: data } )
1076                . done( function( data  ) {
1077
1078                    if( data.applied == 0 ){
1079                        objGiftCard.val( '' );
1080                    }
1081
1082                    $( '#applyGiftCardMessage' ).html( data.giftcard ).fadeIn();
1083
1084                    if( hideMessage == true ) {
1085                        $( '#applyGiftCardMessage' ).delay( hideMessageDuration ).fadeOut();
1086                    }
1087                    //refresh totals
1088                    self.SetSummary();
1089                });//done
1090
1091        });
1092
1093
1094    };
1095
1096    /**
1097     * AddApplyCouponButton
1098     */
1099    this.AddApplyCouponButton = function( value, hideMessage ){
1100
1101        if( value == undefined ){
1102            value  = 'Apply';
1103        }
1104
1105        var hideMessageDuration = 1800;
1106
1107        if( hideMessage == undefined || hideMessage !== false ){
1108            hideMessage = true;
1109        }
1110
1111        if( $.isNumeric( hideMessage ) ){
1112            hideMessageDuration = hideMessage;
1113            hideMessage = true;
1114        }
1115
1116        var data = {};
1117
1118        var objCouponTxt = $( ':input[ name$="coupon_code" ]' );
1119
1120
1121        //check if coupon already applied to the cart
1122        //show it in the input box, don't rely on POST
1123        data.cmd = 'get_applied_coupon';
1124        $.ajax( { data: data } )
1125            . done( function( data  ) {
1126                objCouponTxt.val( data );
1127            });//done
1128
1129
1130
1131        var objContainer = objCouponTxt.parent();
1132
1133        objContainer.append( '<input type="button"  class="button" value="' + value + '" id="applyCouponBtn" ><br /><span id="applyCouponMessage"></span>' );
1134
1135        var objApplyBtn = $( '#applyCouponBtn' );
1136
1137        objApplyBtn . click( function(){
1138
1139            data.cmd = 'apply_coupon';
1140            data.coupon_code = objCouponTxt.val();
1141
1142            $.ajax( { data: data } )
1143                . done( function( data  ) {
1144
1145                    if( data.applied == 0 ){
1146                        objCouponTxt.val( '' );
1147                    }
1148
1149                    $( '#applyCouponMessage' ).html( data.coupon ).fadeIn();
1150                    if( hideMessage == true ) {
1151                        $( '#applyCouponMessage' ).delay( hideMessageDuration ).fadeOut();
1152                    }
1153
1154                    if( data.refresh_shipping == 1 ){
1155                        //refresh Shipping
1156                        _setShipping( false );
1157                    }
1158                    else{
1159                        //refresh totals
1160                        self.SetSummary();
1161                    }
1162                });//done
1163
1164        });
1165
1166    }
1167
1168}//CommerceToolkit
1169
1170/**
1171 * Static Fetch States - for estimaters and such
1172 */
1173CommerceToolkit.FetchStates = function(defaultVal, fieldName){
1174
1175    if( defaultVal == undefined ){
1176        defaultVal = '';
1177    }
1178
1179    var data = {};
1180    data.cmd = 'get_states';
1181
1182    var JqXHR = $.ajax( { data: data } )
1183        . done( function( data  ) {
1184            setSelectOptions( fieldName, data, defaultVal );
1185        })//done
1186        . fail( function() {
1187            data = '<option value="'+defaultVal+'">'+defaultVal+'</option>';
1188
1189            setSelectOptions( fieldName, data, defaultVal );
1190        });//fail;
1191
1192    function setSelectOptions(fieldName, data, defaultVal)
1193    {
1194        $( 'select[ name$="'+fieldName+'" ]').html( data ).val(defaultVal);
1195
1196    }
1197}
1198
1199/**
1200 * Static HidePaymentSections
1201 */
1202CommerceToolkit.HidePaymentSections = function(){
1203
1204    $('#commerceCheckoutSection_creditcard').hide();
1205    $('#commerceCheckoutSection_creditcard:input').attr( 'disabled', 'disabled' );
1206
1207    $('#commerceCheckoutSection_echeck').hide();
1208    $('#commerceCheckoutSection_echeck:input').attr( 'disabled', 'disabled' );
1209
1210    $('#commerceCheckoutSection_check').hide();
1211    $('#commerceCheckoutSection_check:input').attr( 'disabled', 'disabled' );
1212
1213    $('#commerceCheckoutSection_purchaseorder').hide();
1214    $('#commerceCheckoutSection_purchaseorder:input').attr( 'disabled', 'disabled' );
1215
1216    $('#commerceCheckoutSection_bill').hide();
1217
1218    $('#commerceCheckoutSection_cod').hide();
1219
1220    $('#commerceCheckoutSection_creditcard_external').hide();
1221
1222    $('#commerceCheckoutSection_free').hide();
1223
1224};
1225
1226CommerceToolkit.AddPayPalToPaymentTypes = function( paypalOption ){
1227
1228    if( paypalOption == undefined  ){
1229        paypalOption = 'paypal';
1230    }
1231
1232    $('select[ name$="payment_type" ]').append( new Option( 'PayPal', paypalOption ) ).val( payp
1232alOption );
1233};
1234
1235/**
1236 * Static HideChargesSummary
1237 */
1238CommerceToolkit.HideChargesSummary = function( visibility ){
1239
1240    if( visibility == undefined ){
1241        visibility = 'hidden';
1242    }
1243    $('#cart_charges_summary').css('visibility', visibility );
1244};
1245
1246/**
1247 * Static HideNewUserSection
1248 */
1249CommerceToolkit.HideNewUserSection = function( sectionId ){
1250
1251    if( sectionId == undefined ){
1252        sectionId = 'commerceCheckoutSection_newuser';
1253    }
1254
1255    if( CommerceToolkit.GetValue( 'user_authenticated' ) == 'true' ){
1256        $('#' + sectionId ).hide();
1257        $('#' + sectionId + ' :input').prop( 'disabled', true ).prop('autocomplete', false);
1258    }
1259};
1260
1261
1262/**
1263 * Static GetValue
1264 */
1265CommerceToolkit.GetValue = function( fieldName ){
1266
1267    return $('[name*="' + fieldName + '"]:enabled') . val();
1268};
1269
1270/**
1271 * Static ValidateShipping
1272 */
1273CommerceToolkit.ValidateShipping = function( arrErrorMessage ){
1274
1275    if( arrErrorMessage == undefined ){
1276        arrErrorMessage = [];
1277        arrErrorMessage['shipping_type'] = "Select shipping \n";
1278    }
1279
1280    if( CommerceToolkit.GetValue( 'shipping_type' ) == '' ){
1281        alert( arrErrorMessage['shipping_type'] );
1282        $('[name*="shipping_type"]').focus();
1283        return false;
1284    }
1285
1286    return true;
1287};
1288
1289/**
1290 * Static ValidatePayment
1291 */
1292CommerceToolkit.ValidatePayment = function( arrErrorMessage ){
1293
1294    var error = '';
1295
1296    if( arrErrorMessage == undefined ){
1297        arrErrorMessage = [];
1298
1299        arrErrorMessage['card_name'  ] = "Enter name on card \n";
1300        arrErrorMessage['card_type'  ] = "Select card type \n";
1301        arrErrorMessage['card_number'] = "Enter card number \n";
1302        arrErrorMessage['card_cvv'   ] = "Enter card cvv number \n";
1303        arrErrorMessage['card_month' ] = "Select expiration month \n";
1304        arrErrorMessage['card_year'  ] = "Select expiration year \n";
1305
1306        arrErrorMessage['bank_name'     ] = "Enter bank name \n";
1307        arrErrorMessage['bank_acct_name'] = "Enter account name \n";
1308        arrErrorMessage['bank_aba_code' ] = "Enter ABA code \n";
1309        arrErrorMessage['bank_acct_num' ] = "Enter account number \n";
1310        arrErrorMessage['bank_acct_type'] = "Enter account type \n";
1311
1312        arrErrorMessage['po_company'] = "Enter company name \n";
1313        arrErrorMessage['po_agent'  ] = "Enter agent name \n";
1314        arrErrorMessage['po_number' ] = "Enter PO number \n";
1315
1316        arrErrorMessage['check_type'          ] = "Select check type \n";
1317        arrErrorMessage['check_bank_name'     ] = "Enter bank name \n";
1318        arrErrorMessage['check_number'        ] = "Enter check number \n";
1319        arrErrorMessage['check_routing_number'] = "Enter routing number \n";
1320        arrErrorMessage['check_account_number'] = "Enter account number \n";
1321        arrErrorMessage['id_type'             ] = "Enter ID type \n";
1322        arrErrorMessage['id_number'           ] = "Enter ID number \n";
1323        arrErrorMessage['id_exp_month'        ] = "Select ID expiration month \n";
1324        arrErrorMessage['id_exp_year'         ] = "Select ID expiration year \n";
1325
1326    }
1327
1328    //payment validation
1329    if( CommerceToolkit.GetValue( 'cart_final_total' ) > 0 ){
1330
1331        if( CommerceToolkit.GetValue( 'payment_type' ) == '' ){
1332            error += "Select payment type \n";
1333            $('[name*="payment_type"]').focus();
1334        } else {
1335
1336
1337            switch( CommerceToolkit.GetValue( 'payment_type' ) ) {
1338                case 'creditcard':
1339                    var cardnumber = CommerceToolkit.GetValue( 'card_number' );
1340                    var cardtype   = CommerceToolkit.GetValue( 'card_type' );
1341
1342                    if( CommerceToolkit.GetValue( 'card_name'   ) == '' ){ error += arrErrorMessage['card_name'  ]; }
1343                    if( cardtype == ''   ){ error += arrErrorMessage['card_type'  ]; }
1344                    if( cardnumber == '' ){
1345                        error += arrErrorMessage['card_number'];
1346                    } else {
1347                        var ccValidation = CommerceCreditCard.ValidateCreditCard( cardnumber , cardtype );
1348                        if( ccValidation != 'OK' ){
1349                            error += ccValidation;
1350                        }
1351                    }
1352                    if( CommerceToolkit.GetValue( 'card_cvv'    ) == '' ){ error += arrErrorMessage['card_cvv'   ]; }
1353                    if( CommerceToolkit.GetValue( 'card_month'  ) == '' ){ error += arrErrorMessage['card_month' ]; }
1354                    if( CommerceToolkit.GetValue( 'card_year'   ) == '' ){ error += arrErrorMessage['card_year'  ]; }
1355
1356                    break;
1357                case 'echeck':
1358                    if( CommerceToolkit.GetValue( 'bank_name'      ) == '' ){ error += arrErrorMessage['bank_name'     ]; }
1359                    if( CommerceToolkit.GetValue( 'bank_acct_name' ) == '' ){ error += arrErrorMessage['bank_acct_name']; }
1360                    if( CommerceToolkit.GetValue( 'bank_aba_code'  ) == '' ){ error += arrErrorMessage['bank_aba_code' ]; }
1361                    if( CommerceToolkit.GetValue( 'bank_acct_num'  ) == '' ){ error += arrErrorMessage['bank_acct_num' ]; }
1362                    if( CommerceToolkit.GetValue( 'bank_acct_type' ) == '' ){ error += arrErrorMessage['bank_acct_type']; }
1363
1364                    break;
1365                case 'purchaseorder':
1366                    if( CommerceToolkit.GetValue( 'po_company'  ) == '' ){ error += arrErrorMessage['po_company']; }
1367                    if( CommerceToolkit.GetValue( 'po_agent'    ) == '' ){ error += arrErrorMessage['po_agent'  ]; }
1368                    if( CommerceToolkit.GetValue( 'po_number'   ) == '' ){ error += arrErrorMessage['po_number' ]; }
1369
1370                    break;
1371                case 'check':
1372                    if( CommerceToolkit.GetValue( 'check_type'           ) == '' ){ error += arrErrorMessage['check_type'          ]; }
1373                    if( CommerceToolkit.GetValue( 'check_bank_name'      ) == '' ){ error += arrErrorMessage['check_bank_name'     ]; }
1374                    if( CommerceToolkit.GetValue( 'check_number'         ) == '' ){ error += arrErrorMessage['check_number'        ]; }
1375                    if( CommerceToolkit.GetValue( 'check_routing_number' ) == '' ){ error += arrErrorMessage['check_routing_number']; }
1376                    if( CommerceToolkit.GetValue( 'check_account_number' ) == '' ){ error += arrErrorMessage['check_account_number']; }
1377                    if( CommerceToolkit.GetValue( 'id_type'              ) == '' ){ error += arrErrorMessage['i
1377d_type'             ]; }
1378                    if( CommerceToolkit.GetValue( 'id_number'            ) == '' ){ error += arrErrorMessage['id_number'           ]; }
1379                    if( CommerceToolkit.GetValue( 'id_exp_month'         ) == '' ){ error += arrErrorMessage['id_exp_month'        ]; }
1380                    if( CommerceToolkit.GetValue( 'id_exp_year'          ) == '' ){ error += arrErroMessage['id_exp_year'         ]; }
1381
1382                    break;
1383                default:
1384
1385            }//switch
1386
1387        }
1388
1389
1390        if( error != '' ){
1391            alert( error );
1392            return false;
1393        }
1394    }
1395
1396    return true;
1397};
1398
1399
1400
1401/**
1402 * Static ValidateAddress
1403 */
1404CommerceToolkit.ValidateAddress = function( prefix, arrErrorMessage ){
1405
1406    var error = '';
1407
1408    if( arrErrorMessage == undefined ){
1409        arrErrorMessage = [];
1410
1411        arrErrorMessage[ prefix + 'address1'   ] = "Enter address line 1 \n";
1412        arrErrorMessage[ prefix + 'state'      ] = "Select or enter state \n";
1413        arrErrorMessage[ prefix + 'zip'        ] = "Enter zip/postal code \n";
1414        arrErrorMessage[ prefix + 'zip_format' ] = "Enter zip/postal code in correct format ( US:NNNNN or NNNNN-NNNN, CA:ANA NAN )  \n";
1415        arrErrorMessage[ prefix + 'country'    ] = "Select country \n";
1416    }
1417
1418    if( CommerceToolkit.GetValue( prefix + 'address1' ) == '' ){ error += arrErrorMessage[ prefix + 'address1' ]; }
1419
1420    var billcountry = CommerceToolkit.GetValue( prefix + 'country' );
1421
1422    if( billcountry == '' ){ error += arrErrorMessage[ prefix + 'country' ]; }
1423    else {
1424        if( billcountry == 'United States' || billcountry == 'Canada' ){
1425
1426            if( CommerceToolkit.GetValue( prefix + 'state' ) == '' ){ error += arrErrorMessage[ prefix + 'state' ]; }
1427
1428            var billzip = CommerceToolkit.GetValue( prefix + 'zip' );
1429            if( billzip == '' ){ error += arrErrorMessage[ prefix + 'zip' ]; }
1430            else{
1431                if( billcountry == 'United States' ){
1432                    var REGEX_zip =  /(^\d{5}$)|(^\d{5}-\d{4}$)/;//NNNNN or NNNNN-NNNN
1433                } else if( billcountry == 'Canada' ){
1434                    var REGEX_zip =  /(^[a-zA-Z]\d{1}[a-zA-Z](\-| |)\d{1}[a-zA-Z]\d{1}$)/;//ANA NAN
1435                }
1436
1437                if( !REGEX_zip.test( billzip ) ){
1438                    error += arrErrorMessage[ prefix + 'zip_format' ];
1439                }
1440            }
1441
1442        } else {
1443
1444            if( CommerceToolkit.GetValue( prefix + 'zip' ) == '' ){ error += arrErrorMessage[ prefix + 'zip' ]; }
1445        }
1446    }
1447
1448    if( error != '' ){
1449        alert( error );
1450        return false;
1451    }
1452
1453    return true;
1454
1455};
1456
1457
1458/**
1459 * Static ValidateBillingAddress
1460 */
1461CommerceToolkit.ValidateBillingAddress = function( arrErrorMessage ){
1462
1463    var error = '';
1464
1465    if( arrErrorMessage == undefined ){
1466        arrErrorMessage = [];
1467
1468        arrErrorMessage['bill_address1'   ] = "Enter billing address line 1 \n";
1469        arrErrorMessage['bill_state'      ] = "Select or enter billing state \n";
1470        arrErrorMessage['bill_zip'        ] = "Enter billing zip/postal code \n";
1471        arrErrorMessage['bill_zip_format' ] = "Enter billing zip/postal code in correct format ( US:NNNNN or NNNNN-NNNN, CA:ANA NAN )\n";
1472        arrErrorMessage['bill_country'    ] = "Select billing country \n";
1473    }
1474
1475
1476    return CommerceToolkit.ValidateAddress( 'bill_', arrErrorMessage );
1477};
1478
1479/**
1480 * Static ValidateShippingAddress
1481 */
1482CommerceToolkit.ValidateShippingAddress = function( arrErrorMessage ){
1483
1484    var error = '';
1485
1486    if( arrErrorMessage == undefined ){
1487        arrErrorMessage = new Array();
1488
1489        arrErrorMessage['ship_address1'   ] = "Enter shipping address line 1 \n";
1490        arrErrorMessage['ship_state'      ] = "Select or enter shipping state \n";
1491        arrErrorMessage['ship_zip'        ] = "Enter shipping zip/postal code \n";
1492        arrErrorMessage['ship_zip_format' ] = "Enter shipping zip/postal code in correct format ( US:NNNNN or NNNNN-NNNN, CA:ANA NAN )\n";
1493        arrErrorMessage['ship_country'    ] = "Select shipping country \n";
1494    }
1495
1496    return CommerceToolkit.ValidateAddress( 'ship_', arrErrorMessage );
1497};
1498
1499
1500function CommerceAjaxCart(settings){
1501
1502
1503    var self = this,
1504        opts = {
1505            cartLayout: '',
1506            beforeUpdate: function(data, cmd){},
1507            afterUpdate: function(cart, cmd){
1508                if(opts.cartLayout != '') {
1509                    $('.'+opts.cartLayout).replaceWith(cart);
1510                }
1511            },
1512
1513        };
1514
1515    opts = $.extend(true, opts, settings);
1516
1517    self.initAdd =  function _initAdd()
1518    {
1519        //console.log('init add');
1520        $(document).on('submit', 'form.cart_add', function(e){
1521            e.preventDefault();
1522            // before send callback
1523            var data = {
1524                sku : encodeURIComponent($(this).find('input[name="sku"]').val()),
1525                quantity: $(this).find('input[name="quantity"]').val(),
1526                refno: $(this).attr('relid'),
1527
1528            }
1529            if(data.sku == 'undefined') {
1530                delete data.sku;
1531                getChoices.call(this, data);
1532            }
1533
1534            sendRequest('add', data);
1535            return false;
1536        });
1537    }
1538
1539    self.initDel = function _initDel(selector)
1540    {
1541        //console.log('init del');
1542        $(document).on('click', selector, function(e){
1543            e.preventDefault();
1544
1545            var sku = $(this).data('itemsku');
1546
1547            var data = {sku: sku}
1548            sendRequest('del', data)
1549            return false;
1550        } );
1551    };
1552
1553    self.initSet = function(selector, event)
1554    {
1555        //console.log('init set');
1556        var _event = event || 'click';
1557        $(document).on(_event, selector, function(e){
1558
1559            e.preventDefault();
1560            var data = $(this).closest( 'form').find('.shoppingFormQuantity').serialize();
1561
1562            sendRequest('set', data);
1563
1564            return false;
1565        });
1566
1567    };
1568
1569    self.initClear = function(selector)
1570    {
1571        //console.log('init clear');
1572        $(document).on('click', selector, function(e){
1573
1574            e.preventDefault();
1575
1576            sendRequest('clear', {});
1577
1578            return false;
1579        });
1580    };
1581
1582    function sendRequest(action, data)
1583    {
1584
1585        if(opts.beforeUpdate.call(this, data, action) === false ){
1586            return false;
1587        }
1588        var base_url = 'index.php?src=commerce&srctype=ajax&cmd=update_cart'
1589
1590        var _data = {}, senddata =  '';
1591
1592        _data.cart_cmd = action;
1593
1594        if(opts.cartLayout != ''){
1595            _data.cart_view = opts.cartLayout;
1596        }
1597
1598        if(typeof(data) == 'object'){
1599            senddata = $.extend(data, _data);
1600        } else {
1601            senddata = data + '&'+ $.param(_data);
1602        }
1603
1604        $.ajax({
1605            url: base_url,
1606            type: 'GET',
1607            data: senddata,
1608            dataType: 'json',
1609            success: function(rsp) {
1610                opts.afterUpdate.call(this, rsp.data, action);
1611            },
1612        });
1613    }
1614
1615    function getChoices(data){
1616
1617        var choice1 = $(this).find('select[name="choice"]');
1618        if (choice1.length) {
1619            data.choice = choice1.val();
1620        }
1621
1622        var choice2 = $(this).find('select[name="choice_2"]');
1623        if (choice2.length) {
1624            data.choice_2 = choice2.val();
1625        }
1626
1627        var choice3 = $(this).find('select[name="choice_3"]');
1628        if (choice3.length) {
1629            data.choice_3 = choice3.val();
1630        }
1631
1632    }
1633
1634}
1635
1636function CommerceCreditCard(){}/*Namespace*/
1637
1638/**
1639 * @return {string}
1640 */
1641CommerceCreditCard.ValidateCreditCard = function(cardnumber, cardname){
1642    /**
1643     * This code was taken from http://www.braemoor.co.uk/software/creditcard.shtml
1644     * Author:     John Gardner
1645     * Modifications: Accrisoft
1646     */
1647    var ccErrorNo = 0;
1648    var ccErrors = [];
1649
1650    ccErrors [0] = "Unknown card type";
1651    ccErrors [1] = "No card number provided";
1652    ccErrors [2] = "Credit card number is in invalid format";
1653    ccErrors [3] = "Credit card number is invalid";
1654    ccErrors [4] = "Credit card number has an inappropriate number of digits";
1655    ccErrors [5] = "Warning! This credit card number is associated with a scam attempt";
1656    ccErrors [6] = "Card type does not match credit card number";
1657
1658
1659    // Array to hold the permitted card characteristics
1660    var cards = [];
1661
1662    // Define the cards we support. You may add addtional card types as follows.
1663
1664    //  Name:         As in the selection box of the form - must be same as user's
1665    //  Length:       List of possible valid lengths of the card number for the card
1666    //  prefixes:     List of possible prefixes for the card
1667    //  checkdigit:   Boolean to say whether there is a check digit
1668
1669    cards [0] = {name: "Visa",
1670        length: "13,16",
1671        prefixes: "4",
1672        checkdigit: true};
1673    cards [1] = {name: "MasterCard",
1674        length: "16",
1675        prefixes: "51,52,53,54,55",
1676        checkdigit: true};
1677    cards [2] = {name: "DinersClub",
1678        length: "14,16",
1679        prefixes: "30,36,54,55",
1680        checkdigit: true};
1681    cards [3] = {name: "AmEx",
1682        length: "15",
1683        prefixes: "34,37",
1684        checkdigit: true};
1685    cards [4] = {name: "Discover",
1686        length: "16",
1687        prefixes: "6011,622,64,65",
1688        checkdigit: true};
1689    cards [5] = {name: "JCB",
1690        length: "16",
1691        prefixes: "35",
1692        checkdigit: true};
1693
1694    function identifyCardType( cardNo ){
1695
1696        for(var  c = 0; c < cards.length - 1; c++ ){
1697
1698            var prefix = cards[c].prefixes.split(",");
1699
1700            for (var i = 0; i < prefix.length; i++ ) {
1701                var exp = new RegExp ("^" + prefix[i]);
1702                if (exp.test ( cardNo ) ){
1703                    return cards[c].name;
1704                }
1705            }
1706        }
1707        return '';
1708    }
1709
1710    function checkCreditCard(cardnumber, cardname) {
1711
1712
1713        // Establish card type
1714        var cardType = -1;
1715        for (var i=0; i<cards.length; i++) {
1716
1717            // See if it is this card (ignoring the case of the string)
1718            if (cardname.toLowerCase () == cards[i].name.toLowerCase()) {
1719                cardType = i;
1720                break;
1721            }
1722        }
1723
1724        // If card type not found, report an error
1725        if (cardType == -1) {
1726            ccErrorNo = 0;
1727            return false;
1728        }
1729
1730        // Ensure that the user has provided a credit card number
1731        if (cardnumber.length == 0)  {
1732            ccErrorNo = 1;
1733            return false;
1734        }
1735
1736        // Now remove any spaces from the credit card number
1737        cardnumber = cardnumber.replace (/\s/g, "");
1738
1739        // Check that the number is numeric
1740        var cardNo = cardnumber;
1741        var cardexp = /^[0-9]{13,19}$/;
1742        if (!cardexp.exec(cardNo))  {
1743            ccErrorNo = 2;
1744            return false;
1745        }
1746
1747        //identify card type by number and check against cardname
1748        var cardTypeFromNumber = identifyCardType( cardNo );
1749
1750        if( cardTypeFromNumber.toLowerCase() !=  cardname.toLowerCase() ){
1751            ccErrorNo = 6;
1752            return false;
1753        }
1754
1755
1756        // Now check the modulus 10 check digit - if required
1757        if (cards[cardType].checkdigit) {
1758            var checksum = 0;                                  // running checksum total
1759            var mychar = "";                                   // next char to process
1760            var j = 1;                                         // takes value of 1 or 2
1761
1762            // Process each digit one by one starting at the right
1763            var calc;
1764            for (i = cardNo.length - 1; i >= 0; i--) {
1765
1766                // Extract the next digit and multiply by 1 or 2 on alternative digits.
1767                calc = Number(cardNo.charAt(i)) * j;
1768
1769                // If the result is in two digits add 1 to the checksum total
1770                if (calc > 9) {
1771                    checksum = checksum + 1;
1772                    calc = calc - 10;
1773                }
1774
1775                // Add the units element to the checksum total
1776                checksum = checksum + calc;
1777
1778                // Switch the value of j
1779                if (j ==1) {j = 2} else {j = 1};
1780            }
1781
1782            // All done - if checksum is divisible by 10, it is a valid modulus 10.
1783            // If not, report an error.
1784            if (checksum % 10 != 0)  {
1785                ccErrorNo = 3;
1786                return false;
1787            }
1788        }
1789
1790        // Check it's not a spam number
1791        if (cardNo == '5490997771092064') {
1792            ccErrorNo = 5;
1793            return false;
1794        }
1795
1796        // The following are the card-specific checks we undertake.
1797        var LengthValid = false;
1798        var PrefixValid = false;
1799
1800        // We use these for holding the valid lengths and prefixes of a card type
1801        var lengths = [];
1802
1803        // Load an array with the valid prefixes for this card
1804        var prefix = cards[cardType].prefixes.split(",");
1805
1806        // Now see if any of them match what we have in the card number
1807        for (i=0; i<prefix.length; i++) {
1808            var exp = new RegExp ("^" + prefix[i]);
1809            if (exp.test (cardNo)) PrefixValid = true;
1810        }
1811
1812        // If it isn't a valid prefix there's no point at looking at the length
1813        if (!PrefixValid) {
1814            ccErrorNo = 3;
1815            return false;
1816        }
1817
1818        // See if the length is valid for this card
1819        lengths = cards[cardType].length.split(",");
1820        for (j=0; j<lengths.length; j++) {
1821            if (cardNo.length == lengths[j]) LengthValid = true;
1822        }
1823
1824        // See if all is OK by seeing if the length was valid. We only check the length if all else was
1825        // hunky dory.
1826        if (!LengthValid) {
1827            ccErrorNo = 4;
1828            return false;
1829        }
1830
1831        // The credit card is in the required format.
1832        return true;
1833    }
1834
1835
1836    if( checkCreditCard( cardnumber, cardname ) == false ){
1837        return  ccErrors[ ccErrorNo ];
1838    } else {
1839        return 'OK';
1840    }
1841
1842
1843};//CommerceCreditCard
1844
1845
1846/**
1847 * @desc Commerce options
1848 * @author zmart
1849 */
1850
1851window.jQuery || document.write('<s' + 'cript type="text/javascript" src="/freedom_html/common/jquery/jquery.min.js"><\/s' + 'cript>');
1852
1853//poetry
1854
1855
1856(function($, window, document, undefined) {
1857
1858    var optcon = {};
1859
1860    $.extend( optcon, {
1861
1862        bInitiated   : false,
1863
1864        aOptionForms : [],
1865        aOptionSets  : [],
1866
1867        dLastForm    : null,
1868
1869        fAddOptionSet : function(oOptionSet){ return this.aOptionSets.push(oOptionSet); },
1870
1871        fAddOptionForm : function(dFormEntity) {
1872            if(!dFormEntity)
1873                return false;
1874
1875            if( this.bInitiated == false )
1876                this.pf_init();
1877
1878            if( dFormEntity.find('#shoppingOption1').length )
1879                this.aOptionForms.push(dFormEntity);
1880
1881            if( $(dFormEntity).attr('id') == this.dLastForm.attr('id') )
1882                this.pf_done();
1883
1884            return true;
1885        },
1886
1887        pf_init : function() {
1888            this.bInitiated = true;
1889            this.dLastForm  = $('form[id^="item_"]:last');
1890        },
1891
1892        pf_done : function() {
1893
1894            for (var x in this.aOptionForms)
1895            {
1896                var $f      = $(this.aOptionForms[x]);
1897                var optSet  = this.aOptionSets[x];
1898
1899                CommerceOptions.setSKUPriceViaForm($f, optSet);
1900
1901                var $optSelects = $f.find('div[id^="shoppingOption"] select')
1902                    .change({combos: optSet, coform: $f}, function(e){
1903                        var comboData  = e.data.combos;
1904                        var parentForm = e.data.coform;
1905                        CommerceOptions.setSKUPriceViaForm(parentForm, comboData);
1906                    });
1907
1908            }
1909
1910        },
1911
1912        setSKUPriceViaForm : function(dFormEntity, aComboData) {
1913
1914            var sValString = CommerceOptions.getOptionValuesFromForm(dFormEntity);
1915
1916            if( typeof aComboData[sValString] !== 'undefined' && aComboData[sValString].price ){
1917
1918                var dPriceEntity = $('#item_price_'+dFormEntity.attr('relid') );
1919
1920                if( aComboData[sValString].status == 'discontinued' ){
1921                    dPriceEntity.html( 'Item discontinued' );
1922                    $( ':submit', dFormEntity ).prop( 'disabled' , true );//addToCart btn
1923                    return;
1924                }
1925
1926                $( ':submit', dFormEntity ).prop( 'disabled' , false );
1927
1928                var sPrice = aComboData[sValString].price;
1929
1930                if(  sPrice != '' && sPrice != '0.00' ) {
1931                    dPriceEntity.html(sPrice);
1932                } else {
1933                    dPriceEntity.html( dPriceEntity.attr('origprice') );
1934                }
1935            }
1936        },
1937
1938        getOptionValuesFromForm : function(dFormEntity){
1939
1940            var co_sels = dFormEntity.find('div[id^="shoppingOption"] select');
1941
1942            var joinAnd = '', comboVal = '';
1943
1944            for( var co_x = 0; co_x < co_sels.length; co_x++ )
1945            {
1946                comboVal += joinAnd + $(co_sels[co_x]).val();
1947                joinAnd = ',';
1948            }
1949
1950            return comboVal;
1951        }
1952
1953    });
1954
1955    window.CommerceOptions = optcon;
1956
1957})(jQuery, window, document);
1958/*!
1959 * jQuery Cookie Plugin v1.4.1
1960 * https://github.com/carhartl/jquery-cookie
1961 *
1962 * Copyright 2006, 2014 Klaus Hartl
1963 * Released under the MIT license
1964 */
1965(function (factory) {
1966    if (typeof define === 'function' && define.amd) {
1967        // AMD (Register as an anonymous module)
1968        define(['jquery'], factory);
1969    } else if (typeof exports === 'object') {
1970        // Node/CommonJS
1971        module.exports = factory(require('jquery'));
1972    } else {
1973        // Browser globals
1974        factory(jQuery);
1975    }
1976}(function ($) {
1977
1978    var pluses = /\+/g;
1979
1980    function encode(s) {
1981        return config.raw ? s : encodeURIComponent(s);
1982    }
1983
1984    function decode(s) {
1985        return config.raw ? s : decodeURIComponent(s);
1986    }
1987
1988    function stringifyCookieValue(value) {
1989        return encode(config.json ? JSON.stringify(value) : String(value));
1990    }
1991
1992    function parseCookieValue(s) {
1993        if (s.indexOf('"') === 0) {
1994            // This is a quoted cookie as according to RFC2068, unescape...
1995            s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
1996        }
1997
1998        try {
1999            // Replace server-side written pluses with spaces.
2000            // If we can't decode the cookie, ignore it, it's unusable.
2001            // If we can't parse the cookie, ignore it, it's unusable.
2002            s = decodeURIComponent(s.replace(pluses, ' '));
2003            return config.json ? JSON.parse(s) : s;
2004        } catch(e) {}
2005    }
2006
2007    function read(s, converter) {
2008        var value = config.raw ? s : parseCookieValue(s);
2009        return $.isFunction(converter) ? converter(value) : value;
2010    }
2011
2012    var config = $.cookie = function (key, value, options) {
2013
2014        // Write
2015
2016        if (arguments.length > 1 && !$.isFunction(value)) {
2017            options = $.extend({}, config.defaults, options);
2018
2019            if (typeof options.expires === 'number') {
2020                var days = options.expires, t = options.expires = new Date();
2021                t.setMilliseconds(t.getMilliseconds() + days * 864e+5);
2022            }
2023
2024            return (document.cookie = [
2025                encode(key), '=', stringifyCookieValue(value),
2026                options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
2027                options.path    ? '; path=' + options.path : '',
2028                options.domain  ? '; domain=' + options.domain : '',
2029                options.secure  ? '; secure' : ''
2030            ].join(''));
2031        }
2032
2033        // Read
2034
2035        var result = key ? undefined : {},
2036            // To prevent the for loop in the first place assign an empty array
2037            // in case there are no cookies at all. Also prevents odd result when
2038            // calling $.cookie().
2039            cookies = document.cookie ? document.cookie.split('; ') : [],
2040            i = 0,
2041            l = cookies.length;
2042
2043        for (; i < l; i++) {
2044            var parts = cookies[i].split('='),
2045                name = decode(parts.shift()),
2046                cookie = parts.join('=');
2047
2048            if (key === name) {
2049                // If second argument (value) is a function it's a converter...
2050                result = read(cookie, value);
2051                break;
2052            }
2053
2054            // Prevent storing a cookie that we couldn't decode.
2055            if (!key && (cookie = read(cookie)) !== undefined) {
2056                result[name] = cookie;
2057            }
2058        }
2059
2060        return result;
2061    };
2062
2063    config.defaults = {};
2064
2065    $.removeCookie = function (key, options) {
2066        // Must not alter options, thus extending a fresh object...
2067        $.cookie(key, '', $.extend({}, options, { expires: -1 }));
2068        return !$.cookie(key);
2069    };
2070
2071}));
2072
2073
2074function initMinicalClick() {
2075    var timer;
2076    var delay = 1500;
2077
2078    if($('#eventsGlance').length === 0 ){
2079        return;
2080    }
2081    $('#eventsGlance .calendarDays td').on( 'click',function(){
2082        if ( $(this).closest('#eventsGlance').hasClass('smallCalendar') ) {
2083            var currentTd = $(this);
2084            clearTimeout(timer);
2085            if ( currentTd.hasClass('hovered') ) {
2086                currentTd.removeClass('hovered');
2087                currentTd.find('.glanceInner').hide();
2088            }
2089            else {
2090                $('#eventsGlance .calendarDays td').removeClass('hovered');
2091                $('#eventsGlance .calendarDays td .eventsInner').hide();
2092                var currentInner = currentTd.find('.glanceInner');
2093                if(currentInner ) {
2094                    currentInner.show();
2095                    var halfwidth = currentInner.width() / 2;
2096                    if(currentInner.width() / 2 > currentInner.offset().left){
2097                        currentTd.addClass('left')
2098                    } else if ( halfwidth > (window.innerWidth - (currentTd.offset().left + currentTd.outerWidth())) ){
2099                        currentTd.addClass('right')
2100
2101                    }
2102                }
2103                setTimeout(function () {
2104                    currentTd.addClass('hovered');
2105                    currentTd.hover(function () {
2106                        clearTimeout(timer);
2107                    }, function () {
2108                        timer = setTimeout(function () {
2109                            $('#eventsGlance .calendarDays td').removeClass('hovered');
2110                            $('#eventsGlance .calendarDays td .eventsInner').hide();
2111                        }, delay);
2112                    });
2113                }, 5);
2114
2115            }
2116        }
2117    });
2118
2119    $(window).on('resize', function(){
2120        if ( $('#eventsGlance').length > 0 ) {
2121            if ( window.innerWidth > 740 ) { $('#eventsGlance').removeClass('smallCalendar').addClass('largeCalendar') }
2122            else {
2123                $('#eventsGlance').addClass('smallCalendar').removeClass('largeCalendar');
2124            }
2125        }
2126    });
2127}
2128$(initMinicalClick);
2129
2130/**
2131 * initCollapsibleSections
2132 * @param selector
2133 *
2134 */
2135function initCollapsibleSections(selector) {
2136    if(selector == undefined){
2137        selector = 'body';
2138    }
2139    var $containingElement = $(selector);
2140
2141    $containingElement.find('span.collapsibleHeader').removeClass('collapsibleHeader').closest('p, div, h1, h2, h3, h4, h5, h6').addClass('collapsibleHeader');    // move class to containing block element if it's on a span
2142    $containingElement.find('span.collapsibleContentEnd').removeClass('collapsibleContentEnd').closest('p, div, h1, h2, h3, h4, h5, h6, table').addClass('collapsibleContentEnd');    // move class to containing block element if it's on a span
2143    $containingElement.find('.collapsibleHeader').on('click', function(){
2144        var $this = $(this);
2145        if($this.hasClass('active')) $this.removeClass('active').next('.collapsibleContent').slideUp();
2146        else {
2147            $this.siblings('.collapsibleHeader.active').removeClass('active').next('.collapsibleContent').slideUp();   // close other open sections
2148            $this.addClass('active').next().slideDown();
2149        }
2150    }).each(function(){
2151        $(this).nextUntil('.collapsibleHeader, .collapsibleContentEnd').wrapAll('<div class="collapsibleContent"></div>');
2152    });
2153}
2154//init on doc ready
2155$(initCollapsibleSections);
2156/**
2157 * Mobile Menu Functions
2158 */
2159function initMobileNav() {
2160    //trigger, accordian, and append top bar
2161    var mobileNavTriggers = $('[data-mobile-nav-trigger]');
2162    var mobileNavOverlay = document.querySelector('[data-mobile-nav-overlay]');
2163    // Mobile nav button open/close
2164    mobileNavTriggers.each(function(i,trigger) {
2165        $(trigger).on('click', function() {
2166            mobileNavTriggers.each(function(i,trigger) {  $(trigger).toggleClass('is-active'); });
2167            document.body.classList.toggle('is-mobilenav-open');
2168        });
2169    });
2170    // Mobile nav overlay close
2171    if(mobileNavOverlay) {
2172        mobileNavOverlay.addEventListener('click', function () {
2173            mobileNavTriggers.each(function (i, trigger) {
2174                trigger.classList.remove('is-active');
2175            });
2176            document.body.classList.remove('is-mobilenav-open');
2177        });
2178
2179    }
2180
2181}
2182
2183var checkMobileTrigger = function() {
2184
2185    var header = document.querySelector('[data-header]');
2186    if(header) {
2187        var nav = header.querySelector('[data-nav]');
2188        //header.classList.toggle('has-mobile-trigger', isOverflown(nav));
2189
2190        //option 2 - for top level with dropdowns
2191        var topLi = nav.children;
2192        var found = false
2193        for( var i = topLi.length-1; i >=0; i--){
2194            if(topLi[i].offsetTop > 0 ){
2195                topLi[i].classList.add('is-overflown');
2196                found = true;
2197            } else {
2198                topLi[i].classList.remove('is-overflown');
2199                // the rest should be fine
2200            }
2201        }
2202        header.classList.toggle('has-mobile-trigger', found);
2203
2204    }
2205};
2206
2207window.addEventListener('resize', debounce(checkMobileTrigger, 250));
2208
2209$(function(){
2210    checkMobileTrigger();
2211    initMobileNav();
2212})
2213/**
2214 * My account Tweaks
2215 * Auto called on doc ready
2216 */
2217function applyMyAccountEdits() {
2218
2219    // Wrap contents of myaccountFormSection with h3
2220    $('.myaccountFormSection, td.formTextHeading').wrapInner('<h3></h3>');
2221
2222    //Change image labels
2223    $('.tr_image_preview td').first().html('Image');
2224    $('.tr_image_upload td').first().html('Upload Image');
2225
2226    // Apply Proper Classes to Form Buttons
2227    $('.myaccountButton').addClass('button');
2228    $('.cancelButton').addClass('hollow alert');
2229
2230}
2231$(applyMyAccountEdits);
2232
2233
2234/**
2235 * Side menu - show only if it has content
2236 */
2237function checkSideMenu() {
2238
2239    var hasSidebarContent = false
2240    if ( $('.sideMenu-nav a').length > 0 ) {
2241        hasSidebarContent = true;
2242    }
2243    if ( $('#sideBanners a').length ) {
2244        hasSidebarContent = true;
2245    }
2246    if ( $('.content-body [data-sidebar-item]').length ) {
2247        hasSidebarContent = true
2248        $('.content-body [data-sidebar-item]').detach().appendTo('.content-sidebar');
2249    }
2250
2251    if(hasSidebarContent){
2252        $('.content-sidebar').show();
2253    }
2254}
2255/**
2256 * Set Up interior header banner ad image and move h1.pageTitle into header
2257 * @note - needs parameters / improvement
2258 *
2259 */
2260function interiorHeaderBanner() {
2261    var header = document.getElementById('interiorHeaderBanner');
2262    if(header) {
2263        var bannerImageTarget = header.querySelector('.pageHeader-background');//remove this div if the site wont use banner images
2264        if(bannerImageTarget) {
2265            //use template tags to prevent scripts and  images from loading
2266            var bannerSrcEl = document.getElementById('interiorHeaderSource');
2267            var bannerOverrideEl = document.getElementById('interiorHeaderOverride');
2268
2269            var bannerImgSrc = false;
2270            if (bannerOverrideEl != null) {
2271                bannerImgSrc = bannerOverrideEl.querySelector('img').src
2272            } else if (bannerSrcEl && bannerSrcEl.querySelector('img')) {
2273                bannerImgSrc = bannerSrcEl.querySelector('img').src
2274            }
2275
2276            if (bannerImgSrc) {
2277                bannerImageTarget.style.backgroundImage = 'url(' + bannerImgSrc + ')';
2278                header.classList.add('pageHeader--hasImage');
2279                header.classList.add('pageHeader--splitImage');
2280
2281            } else {
2282                bannerImageTarget.classList.add('noImage');
2283            }
2284        }
2285
2286        //Move Page Titles
2287        //first look for full .pageHeader
2288        if ($('.js-moveToPageHeader').length) {
2289            $('#interiorHeaderBanner .pageHeader-content').html($('.js-moveToPageHeader').html());
2290            $('.js-moveToPageHeader').remove();
2291        } else if ($('#contentControl h1.pageTitle').length) {
2292            //then look for just .pageTitle and move to h1.heroTitle
2293            var headerTextComponent = $('#contentControl  h1.pageTitle').remove().text();
2294            $('#interiorHeaderBanner  h1').text(headerTextComponent);
2295        }
2296        $('#interiorHeaderBanner .pageHeader-content').removeClass('loading');
2297    }
2298}
2299//init on doc ready
2300$(interiorHeaderBanner);
2301/**
2302 * set up the ajax add to cart functionality
2303 *
2304 */
2305function initAjaxCart(){
2306
2307    var cartLayout = 'commerce_shoppingcart_mini';
2308
2309    var $oCart = new CommerceAjaxCart({
2310        'cartLayout' : cartLayout,
2311        beforeUpdate: function(data, cmd){
2312            var input = $('form[relid="'+data['refno']+'"]').find('.cartAddSubmit input');
2313            input.val('Adding...');
2314            return true;
2315        },
2316        afterUpdate: function(cart, cmd){
2317            //this = jquery xhr object
2318            var $showExpandedCart = $('.'+cartLayout +' .expandableMiniCart').hasClass('expanded');
2319            $('.'+cartLayout).replaceWith(cart);
2320            if($showExpandedCart){
2321                $('.'+cartLayout +' .expandableMiniCart').addClass('expanded');
2322            }
2323            $('.shoppingCartTable tr.product').each(function(i, el){if(i%2){ $(el).addClass('even')}});
2324
2325            var urlparams = Freedom.getQueryParameters(this.url);
2326            var input = $('form[relid="'+urlparams['refno']+'"]').find('.cartAddSubmit input');
2327            input.delay(300).queue(function(next){ $(this).css('color', '#006998').val('Added!'); next();}).queue(function(next){
2328                $(this).css('color', '#FFF');
2329                next();
2330            });
2331        }
2332    });
2333    $oCart.initSet('.shoppingFormQuantity', 'keyup');
2334    $oCart.initAdd();
2335    $oCart.initDel('.deletesku');
2336}
2337
2338/**
2339 * Count to Library and init functions
2340 * Must be called manually
2341 * @preserve
2342 */
2343// countTo library - see https://github.com/mhuggins/jquery-countTo
2344!function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof exports?t(require("jquery")):t(jQuery)}(function(t){var e=function(o,i){this.$element=t(o),this.options=t.extend({},e.DEFAULTS,this.dataOptions(),i),this.init()};e.DEFAULTS={from:0,to:0,speed:1e3,refreshInterval:100,decimals:0,formatter:function(t,e){return t.toFixed(e.decimals)},onUpdate:null,onComplete:null},e.prototype.init=function(){this.value=this.options.from,this.loops=Math.ceil(this.options.speed/this.options.refreshInterval),this.loopCount=0,this.increment=(this.options.to-this.options.from)/this.loops},e.prototype.dataOptions=function(){var t={from:this.$element.data("from"),to:this.$element.data("to"),speed:this.$element.data("speed"),refreshInterval:this.$element.data("refresh-interval"),decimals:this.$element.data("decimals")},e=Object.keys(t);for(var o in e){var i=e[o];void 0===t[i]&&delete t[i]}return t},e.prototype.update=function(){this.value+=this.increment,this.loopCount++,this.render(),"function"==typeof this.options.onUpdate&&this.options.onUpdate.call(this.$element,this.value),this.loopCount>=this.loops&&(clearInterval(this.interval),this.value=this.options.to,"function"==typeof this.options.onComplete&&this.options.onComplete.call(this.$element,this.value))},e.prototype.render=function(){var t=this.options.formatter.call(this.$element,this.value,this.options);this.$element.text(t)},e.prototype.restart=function(){this.stop(),this.init(),this.start()},e.prototype.start=function(){this.stop(),this.render(),this.interval=setInterval(this.update.bind(this),this.options.refreshInterval)},e.prototype.stop=function(){this.interval&&clearInterval(this.interval)},e.prototype.toggle=function(){this.interval?this.stop():this.start()},t.fn.countTo=function(o){return this.each(function(){var i=t(this),n=i.data("c
2344ountTo"),s="object"==typeof o?o:{},r="string"==typeof o?o:"start";(!n||"object"==typeof o)&&(n&&n.stop(),i.data("countTo",n=new e(this,s))),n[r].call(n)})}});
2345
2346function throttle(t, n) {
2347  var i = !1;
2348  return function () {
2349    i || (t.apply(this, arguments), i = !0, setTimeout(function () {
2350      i = !1
2351    }, n))
2352  }
2353}
2354
2355function handleCounterScroll(els){
2356
2357  var windowHeight = window.innerHeight;
2358  var windowTop = window.pageYOffset;
2359
2360  els.each(function(){
2361
2362    if( $(this).hasClass('counter-ran') ){ return true; }
2363
2364    var offsetTop = $(this).offset().top;
2365    let triggerPoint = offsetTop - windowHeight; // top of element hit bottom of page
2366
2367    triggerPoint += 50// additional offset
2368
2369    if (windowTop >= triggerPoint) {
2370      var number =  $(this).text();
2371      var finalNumber = parseFloat( number.replace(',', '') );
2372      var decimals =  number.indexOf('.') >= 0 ? number.substr(number.indexOf('.')+1).length : 0;
2373
2374      $(this).countTo({'to': finalNumber, 'decimals': decimals,  formatter: function (v, o) { return parseFloat(v.toFixed(o.decimals)).toLocaleString();}});
2375      $(this).addClass('counter-ran');
2376    }
2377
2378  });
2379
2380}
2381
2382function initCountOnScroll(selector) {
2383
2384  var $counterElements = $(selector);
2385  if($counterElements.length == 0){ return;}
2386  handleCounterScroll($counterElements);
2387
2388  window.addEventListener(
2389      'scroll',
2390      throttle(function(){
2391        handleCounterScroll($counterElements);
2392      }, 200)
2393  );
2394}
2395function initLoginPopup(force){
2396  // ajax login form. See event detail for example.
2397  // simply add to page : <div class="reveal" id="loginModal" data-reveal data-animation-in="slide-in-up"></div>
2398  // call initLoginPopup after doc ready
2399
2400  $('#loginModal').on('open.zf.reveal', function(){
2401    console.log('modal opened');
2402  });
2403
2404  $('#loginModal').on('closed.zf.reveal',function(){
2405    console.log('modal closed');
2406    createSeenLoginCookie();
2407  });
2408  $('#loginModal').on('submit', '#formLogin', function(e){
2409    e.preventDefault();
2410    console.log('form submitted');
2411    $(this).addClass('processing');
2412    $.ajax({url:'index.php', type: 'POST', data: $(this).serialize()})
2413    .done(function(response){
2414      if ($(response).find('#loginPopup').length) {
2415        console.log('Found Login in Response');
2416        setModalHtml(response);
2417      } else {
2418        $.cookie('seenloginpopup', 'yes');
2419        console.log('Creating Seen Login Cookie!');
2420        location.reload();
2421      }
2422    });
2423  });
2424
2425  function setModalHtml(data, triggerOpen){
2426    $('#loginModal').html( data +' <button class="close-button" data-close aria-label="Close Login Popup" type="button"><span aria-hidden="true">&times;</span></button>');
2427    if(triggerOpen === true){
2428      $('#loginModal').foundation('open');
2429    }
2430
2431  }
2432  function createSeenLoginCookie(){
2433    console.log('Creating Seen Login Cookie!');
2434    //$.cookie('seenloginpopup', 'yes');
2435  }
2436  if(force || (!$.cookie('USERAUTH'))) {
2437    $.get('index.php?src=membership&srctype=membership_login_ajax&direct=y', function(data) {
2438      console.log($(data).find('#loginPopup').length);
2439      if ($(data).find('#loginPopup').length) {
2440
2441        setModalHtml(data, true);
2442      } else {
2443        createSeenLoginCookie();
2444        location.reload();
2445      }
2446    });
2447  } else {
2448    setModalHtml("<p>You are already logged in! <br> If you still can't access the intended content, you may not have permissions.</p>", false);
2449  }
2450}
2451
2452/**
2453 *  used in admin comment listers
2454 */
2455function EditCommentReq(id, inlineFlag, commerceDir ) {
2456    var url = 'src=comments&cmd=get';
2457    url += MakeTag('comment_id', id);
2458    url += MakeTag('inline', inlineFlag);
2459    if( commerceDir == 1 ){ url += MakeTag('commerceDir', commerceDir );}
2460    $.ajax({url: MakeURL(url),  dataType: 'json', success:EditCommentRsp});
2461}
2462/**
2463 * used in admin comment listers
2464*/
2465function EditCommentRsp(rsp) {
2466    var jsonRsp = rsp.data;
2467
2468//    console.log(jsonRsp);
2469    CloseDialogAndSave = function() { //Redefine CloseDialogAndSave to save changes before closing
2470        var sUrl = 'admin.php?src=comments&cmd=set&comment_id='+jsonRsp['comment_id'];
2471        $.ajax({
2472            type     : 'post',
2473            dataType : 'json',
2474            url      : sUrl,
2475            async    : false,
2476            data     :$('#dialogComment').serialize(),
2477            success  : function(rsp){
2478
2479                Freedom.UI.notify(rsp.message, rsp.status == 'ok'? 'sucess': 'error');
2480                var $table = $('#'+jsonRsp['tableId']);
2481                try {
2482                    $table.freedomTable().refresh();
2483                } catch ( err ) {
2484                    if ( typeof console == 'object' ) {
2485                        console.log('error: ' + err);
2486                    }
2487                }
2488            }
2489        });
2490
2491        CloseDialog();
2492    }
2493
2494
2495    jsonRsp.type = 'OK_CANCEL';
2496    ShowFreedomDialog('', jsonRsp);
2497}
2498
2499/**
2500 * used white
2501 */
2502function SaveComment(id, rspHandler) {
2503    var url = 'src=comments&cmd=set';
2504    url += MakeTag('comment_id', id);
2505    url += MakeTagFromID('public', 'yes');
2506    url += MakeTagFromID('user_alias', '', true);
2507    url += MakeTagFromID('user_email', '', true);
2508    url += MakeTagFromID('notify_blogger', 'no');
2509
2510    if($('#captchaStatus').length > 0) {
2511        url += MakeTagFromID('recaptcha_challenge_field', '');
2512        url += MakeTagFromID('recaptcha_response_field', '');
2513    }
2514
2515    if( $('#g-recaptcha-response').length > 0 ) {
2516        url += MakeTagFromID('g-recaptcha-response', '');
2517    }
2518
2519    url += MakeTag('comment_text', encodeURIComponent($('#comment_text').val()));
2520
2521    rspHandler = IsValid(rspHandler) ? rspHandler: function() { window.location.reload(); }
2522
2523    $.ajax({url: MakeURL(url),
2524        dataType: 'html',
2525        success:rspHandler});
2526
2527}
2528
2529function MakeTagFromID(id, defaultValue, escapeValue) {
2530    var val = defaultValue;
2531    var obj = document.getElementById(id);
2532    if (IsValid(obj)) {
2533        if ((obj.type == 'checkbox') || (obj.type == 'radio')) val = obj.checked ? 'yes': 'no';
2534        else if (IsValid(obj.value)) val = IsValid(escapeValue) ? encodeURIComponent(obj.value) : obj.value;
2535    }
2536    return MakeTag(id, val);
2537}
2538
2539/**
2540 * used white
2541 */
2542function InitializeAjaxLogin(classLogin, classContent) {
2543    var selLogin = '.' + classLogin;
2544    var selContent = '.' + classContent;
2545    if(IsValid($.cookie('USERAUTH')) && $.cookie('USERAUTH').length > 20) {
2546        $(selLogin).hide();
2547        $(selContent).show();
2548        return;
2549    }
2550
2551    $(selContent).hide();
2552
2553    $(document).keypress(function(e) {
2554        var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
2555        if(key == 13 && $(selLogin).is(':visible')) $('#login_submit').trigger('click');
2556    });
2557
2558    $('#login_submit').click(function(e) {
2559        var uid = $('#uid').val();
2560        var pwd = $('#pwd').val();
2561        $.ajax({
2562            type: 'GET',
2563            url: MakeURL('src=comments&cmd=login&uid=' + uid + '&pwd=' + pwd),
2564            dataType: 'json',
2565            success: function(rsp) {
2566
2567                if(rsp.status == 'ok') {
2568                    $(selContent).show();
2569                    $(selLogin).hide();
2570
2571                    var userData = rsp.data;
2572
2573                    $('#user_alias').val(userData['user_alias']);
2574                    $('#user_email').val(userData['user_email']);
2575                }
2576                else {
2577                    $('#loginStatus').text(rsp.message);
2578                }
2579            }
2580        });
2581    });
2582}
2583
2584function FreedomComments(node){
2585
2586    var self = this;
2587    var $commentListerWrapper = $(node);
2588    self.init = function(){
2589        $commentListerWrapper.find('.prevnext a').each(function(i, el) {
2590            if (!IsValid($(this).data('oldHREF'))) $(this).data('oldHREF', $(this).attr('href')).attr('href', 'javascript:void(0);');
2591        }).click(function() {
2592                $.ajax({
2593                    url: $(this).data('oldHREF'),
2594                    data: {direct: 'y'},
2595                    success: refreshCommentsLister,
2596                    dataType: 'html'
2597
2598                })
2599            });
2600    };
2601
2602    function refreshCommentsLister(response, status, xhr){
2603        $commentListerWrapper.empty();
2604        $commentListerWrapper.html(response);
2605        self.init();
2606
2607    }
2608}
2609
2610jQuery(document).ready(function($) {
2611    //white facing only
2612    if( String(window.location).indexOf('admin.php') == -1 ) {
2613
2614        if($('.comments_lister').length > 0){
2615
2616            $('.comments_lister').each(function(i, element){
2617                var fc1 = new FreedomComments(element);
2618                fc1.init();
2619
2620            });
2621
2622        }
2623    }
2624});

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.