PageSourceSearch

https://www.meridianwinds.com/1791280034/c/cart/cart.js

js meridianwinds.com collected 2026-10-06 16:20:08 UTC 80,092 bytes, 2,309 lines download raw bytes

1/* Shopping Cart (2017 version) */
2
3Array.prototype.remove = function(from, to) {
4    var rest = this.slice((to || from) + 1 || this.length);
5    this.length = from < 0 ? this.length + from : from;
6    return this.push.apply(this, rest);
7};
8
9if (!window.domesticCountry) {
10    window.domesticCountry = 'United States';
11}
12
13var linkStyles = 'color: #fff !important; text-decoration:underline !important; font-family: Arial !important; font-size: 12px !important; font-weight: normal !important;';
14var checkoutUrl = window.CheckoutUrl;
15if (checkoutUrl.indexOf('?') < 0) {
16    checkoutUrl += "?1";
17}
18var editcartUrl = window.EditCartUrl;
19if (editcartUrl.indexOf('?') < 0) {
20    editcartUrl += "?1";
21}
22
23//module to make cart requests synchronous
24var requestModule = (function() {
25    var instance;
26    var readyForNext = true;
27
28    var addItemToCart = function(postData) {
29        return new Promise(function (resolve) {
30            var intervalId = setInterval(function() {
31                if (readyForNext === true) {
32                    var cartUuid = getCartUuidFromCookie();
33
34                    resolve(sendCartItem(cartUuid, postData));
35
36                    clearInterval(intervalId);
37                }
38            }, 100);
39        });
40    }
41
42    var sendCartItem = function(cartUuid, postData) {
43        readyForNext = false;
44        var axios = getAxiosInstance();
45
46        return axios.post("/api/cart/" + cartUuid + "/item", postData).then(function(response) {
47            if (response && response.data && response.data.success) {
48                if (response.data.uuid) {
49                    setCartUuidCookie(response.data.uuid);
50                }
51                if (response.data.data) {
52                    CreateCartArray(response.data.data);
53                    ShowCart(true);
54                }
55            } else {
56                alert('There was an error adding this item to your cart.');
57            }
58        })
59            .catch(function (error) {
60                var errorMessage = error.response && error.response.data && error.response.data.error;
61
62                alert(errorMessage || 'There was an error adding this item to your cart.');
63            })
64            .finally(function() {
65                readyForNext = true;
66            });
67    }
68
69    var createInstance = function() {
70        return {
71            addItemToCart: addItemToCart
72        }
73    }
74
75    return {
76        getInstance: function() {
77            return instance || (instance = createInstance());
78        }
79    }
80}());
81
82function Set_Cart_Cookie_Cookie(name, value, expires, path, domain, secure) {
83    var today = new Date();
84    today.setTime(today.getTime());
85
86    if (expires) {
87        expires = expires * 1000 * 60 * 60 * 24;
88    }
89    var expires_date = new Date(today.getTime() + (expires));
90
91    if (domain == '') {
92        domain = document.domain.split('.');
93        if (domain[domain.length - 1].toLowerCase() == 'au' || domain[domain.length - 1].toLowerCase() == 'uk' || domain[domain.length - 1].toLowerCase() == 'nz' || domain[domain.length - 1].toLowerCase() == 'za') {
94            domain = domain[domain.length - 3] + '.' + domain[domain.length - 2] + '.' + domain[domain.length - 1];
95        } else {
96            domain = domain[domain.length - 2] + '.' + domain[domain.length - 1];
97        }
98    }
99
100    while (value.substring(0, 4) == 'null') {
101        value = value.substring(4);
102    }
103
104    value = escape(value);
105    var count = 0;
106    var lastIndex = 0;
107
108    while (value.length > lastIndex) {
109
110        var segment = value.substring(lastIndex, lastIndex + 4000);
111        if (value.length > lastIndex + 4000) {
112            var lastPos = segment.lastIndexOf('%');
113            if (lastPos > 0) {
114                segment = segment.substring(0, lastPos);
115                lastIndex = lastIndex + lastPos;
116            }
117            else {
118                lastIndex = lastIndex + 4000;
119            }
120        }
121        else {
122            lastIndex = lastIndex + 4000;
123        }
124
125        document.cookie = name + (count > 0 ? count : '') + "=" + segment +
126            ( ( expires ) ? ";expires=" + expires_date.toGMTString() : "" ) +
127            ( ( path ) ? ";path=" + path : "" ) +
128            ( ( domain ) ? ";domain=" + domain : "" ) +
129            ( ( secure ) ? ";secure" : "" );
130
131        count++;
132    }
133
134    if (count > 0) {
135        // Delete any leftover cookies if the amount to be stored is shrinking (they are removing items from the shopping cart)
136        document.cookie = name + (count > 0 ? count : '') + "=" +
137            ( ( path ) ? ";path=" + path : "") +
138            ( ( domain ) ? ";domain=" + domain : "" ) +
139            ";expires=Thu, 01-Jan-1970 00:00:01 GMT";
140    }
141}
142
143function trimUuid(uuid) {
144    var trimmed = '';
145    if(typeof uuid === 'string') {
146        trimmed = uuid.substr(0,36);
147    }
148    return trimmed;
149}
150
151function setCartUuidCookie(uuid) {
152    uuid = trimUuid(uuid);
153    var name = 'cart_id';
154    var days = 31;
155    var expires = "";
156    var date = new Date();
157    date.setTime(date.getTime() + (days*24*60*60*1000));
158    expires = "; expires=" + date.toUTCString();
159    document.cookie = name + "=" + (uuid || "")  + expires + "; path=/";
160}
161function getCartUuidFromCookie() {
162    var name = 'cart_id';
163    var nameEQ = name + "=";
164    var ca = document.cookie.split(';');
165    for(var i=0;i < ca.length;i++) {
166        var c = ca[i];
167        while (c.charAt(0)==' ') {
168            c = c.substring(1,c.length);
169        }
170        if (c.indexOf(nameEQ) == 0) {
171            var uuid = c.substring(nameEQ.length,c.length);
172            return trimUuid(uuid);
173        }
174    }
175    return null;
176}
177
178function getAxiosInstance() {
179    if (window.knobby && window.knobby.module_website_vue_use_one_lib_for_all_places) {
180        const config = {};
181        if (this.cartJWT) {
182            config.headers = {
183                Authorization: 'Bearer ' + window.cartJWT,
184            };
185        }
186        return axios.create(config);
187    } else {
188        let instance = axios.create();
189        if (window.cartJWT) {
190            instance.defaults.headers.common['Authorization'] = 'Bearer ' + window.cartJWT;
191        }
192        return instance;
193    }
194}
195
196
197function addItemToCartData(data, classPackageData) {
198    var postData = {
199        'item_data': encodeURIComponent(data)
200    };
201
202    // Pass Class packageData with the class to avoid async race conditions
203    if (classPackageData && Array.isArray(classPackageData) && classPackageData.length > 0){
204        postData['class_package_data'] = classPackageData;
205    }
206
207    return requestModule.getInstance().addItemToCart(postData);
208}
209
210function Set_Cart_Cookie_Db(name, value, expires, path, domain, secure) {
211    var cartUuid = getCartUuidFromCookie(); // may be null, server will return one
212
213    var axios = getAxiosInstance();
214    var data = {};
215    data.uuid = cartUuid;
216    data.cart_contents = value;
217
218    axios.post("/api/cart/data", data).then(function(response) {
219        if(response && response.data && response.data.uuid) {
220            setCartUuidCookie(response.data.uuid);
221        }
222    });
223
224    // TODO - handle the unhappy cases
225    // TODO - no, really do it.
226}
227
228// Cart
229function Set_Cart_Cookie(name, value, expires, path, domain, secure) {
230    if(name == 'cart') {
231        Set_Cart_Cookie_Db(name, value, expires, path, domain, secure);
232        CreateCartArray(value);
233    } else {
234        Set_Cart_Cookie_Cookie(name, value, expires, path, domain, secure);
235    }
236}
237
238function Get_Cart_Cookie_Cookie(check_name) {
239    var a_all_cookies = document.cookie.split(';');
240    var a_temp_cookie = '';
241    var cookie_name = '';
242    var cookie_value = '';
243    var b_cookie_found = false;
244    var retVal = null;
245    var count = 0;
246
247    do {
248
249        b_cookie_found = false;
250
251        for (i = 0; i < a_all_cookies.length; i++) {
252            a_temp_cookie = a_all_cookies[i].split('=');
253
254            cookie_name = a_temp_cookie[0].replace(/^\s+|\s+$/g, '');
255
256            if (cookie_name == check_name + (count > 0 ? count : '')) {
257                b_cookie_found = true;
258
259                if (a_temp_cookie.length > 1) {
260                    cookie_value = unescape(a_temp_cookie[1].replace(/^\s+|\s+$/g, ''));
261                }
262
263                retVal = (retVal === null ? '' : retVal) + cookie_value;
264                break;
265            }
266            a_temp_cookie = null;
267            cookie_name = '';
268        }
269
270        count++;
271
272    } while (b_cookie_found == true);
273
274    return retVal;
275}
276
277// Cart
278function Get_Cart_Cookie(check_name) {
279    if(check_name == 'cart') {
280        return BuildCookieFromArray();
281    } else {
282        return Get_Cart_Cookie_Cookie(check_name);
283    }
284}
285
286function Delete_Cart_Cookie(name, path, domain) {
287    var count = 0;
288    while (Get_Cart_Cookie(name + (count > 0 ? count : ''))) {
289
290        if (domain == '') {
291            domain = document.domain.split('.');
292            if (domain[domain.length - 1].toLowerCase() == 'au' || domain[domain.length - 1].toLowerCase() == 'uk' || domain[domain.length - 1].toLowerCase() == 'nz' || domain[domain.length - 1].toLowerCase() == 'za') {
293                domain = domain[domain.length - 3] + '.' + domain[domain.length - 2] + '.' + domain[domain.length - 1];
294            } else {
295                domain = domain[domain.length - 2] + '.' + domain[domain.length - 1];
296            }
297        }
298
299        document.cookie = name + (count > 0 ? count : '') + "=" +
300            ( ( path ) ? ";path=" + path : "") +
301            ( ( domain ) ? ";domain=" + domain : "" ) +
302            ";expires=Thu, 01-Jan-1970 00:00:01 GMT";
303
304        count++;
305    }
306
307}
308
309// Item Page?
310function showAddToWaitlistDialog(id, title, storeId, type) {
311
312    window.storeId = storeId;
313
314    if (type === "PSLR") {
315
316        var key = '';
317        var titleAddOn = ' ';
318        for (var i = 0; i < window['numAttributes' + id]; i++) {
319            key += (key.length > 0 ? '-' : '') + $('#attribute_' + id + '_' + i).val();
320            titleAddOn += (titleAddOn.length > 0 ? ' - ' : '') + window['attributeValues' + id][i][$('#attribute_' + id + '_' + i).val()];
321        }
322
323        title += titleAddOn;
324
325        if (key == '') {
326            key = '0';
327        }
328
329        window.currentProductId = id;
330        window.selected_wait_list_item_id = window['prices' + id][key]['pslrId'];
331        window.selected_wait_list_type_id = 1;
332    } else if (type === "EVENT") {
333
334        window.currentProductId = id;
335        window.selected_wait_list_item_id = id;
336        window.selected_wait_list_type_id = 2;
337    } else {
338
339        return;
340    }
341
342    $("#wait_list_added_span").html("");
343    $("#overlayWaitListForm").replaceWith('');
344
345    var markup = getWaitListDialogMarkup(title);
346
347    $(document.body).append(markup);
348
349    populateWaitListFormWithCookie();
350
351    showWaitListSaveButton();
352
353    $("#wait_list_contact_email").change(function() {
354
355        var email = $("#wait_list_contact_email").val();
356        var collection = new WaitListCollection(window.storeId);
357        collection.getExistingContactInfoByEmail(window.selected_wait_list_item_id, email, function(data) {
358
359            populateWaitListFormWithData(data);
360            showWaitListSaveButton(email);
361        });
362    });
363
364    $("#wait_list_contact_first_name").change(function() {
365
366        showWaitListSaveButton();
367    });
368
369    $("#wait_list_contact_last_name").change(function() {
370
371        showWaitListSaveButton();
372    });
373
374    $("#overlayWaitListForm").dialog({width: 300, dialogClass: 'dlgWaitList'});
375
376    // For some reason the close button is removed with responsive websites.  We'll put it back here.
377    $(".dlgWaitList > .ui-dialog-titlebar > .ui-dialog-titlebar-close").html('<span class="ui-button-icon-primary ui-icon ui-icon-closethick"></span>');
378}
379
380function getWaitListDialogMarkup(title) {
381
382    var appendString = '';
383
384    appendString += '<div id="overlayWaitListForm" title="ADD TO WAIT LIST" class="wait-list-container">';
385
386    appendString += '<div class="form-container">';
387    appendString += '<div class="form-row">';
388    appendString += '<div class="product-name">';
389    appendString += title;
390    appendString += '</div>';
391    appendString += '</div>';
392
393    appendString += '<div class="form-row">';
394    appendString += '<div class="form-title">';
395    appendString += 'Email Address:';
396    appendString += '</div><input class="form-input" placeholder="" id="wait_list_contact_email">';
397    appendString += '</div>';
398
399    appendString += '<div class="form-row">';
400    appendString += '<div class="form-title">';
401    appendString += 'First Name:';
402    appendString += '</div><input class="form-input" placeholder="" id="wait_list_contact_first_name">';
403    appendString += '</div>';
404
405    appendString += '<div class="form-row">';
406    appendString += '<div class="form-title">';
407    appendString += 'Last Name:';
408    appendString += '</div><input class="form-input" placeholder="" id="wait_list_contact_last_name">';
409    appendString += '</div>';
410
411    appendString += '<div class="form-row">';
412    appendString += '<div class="form-title">';
413    appendString += 'Phone:';
414    appendString += '</div><input class="form-input" placeholder="" id="wait_list_contact_phone">';
415    appendString += '</div>';
416
417    appendString += '<div class="form-row">';
418    appendString += '<div class="form-title">';
419    appendString += 'Quantity:';
420    appendString += '</div><input class="form-input" value="1" id="wait_list_quantity">';
421    appendString += '</div>';
422
423    appendString += '<button class="wait-list-btn" onClick="javascript:SaveToWaitList()" id="wait_list_save_button">Add to Wait List</button>'
424    appendString += '</div>';
425    appendString += '</div>';
426    return appendString;
427}
428
429function populateWaitListFormWithCookie() {
430
431    var waitlist_data = Get_Cart_Cookie('waitlist');
432    if (waitlist_data !== null) {
433
434        var contact = JSON.parse(waitlist_data);
435        populateWaitListFormWithData(contact);
436    }
437}
438
439function populateWaitListFormWithData(contact) {
440
441    if (contact === null) {
442
443        $("#wait_list_contact_first_name").val("");
444        $("#wait_list_contact_last_name").val("");
445        $("#wait_list_contact_phone").val("");
446        window.selected_wait_list_id = null;
447        window.selected_wait_list_contact_rel_id = null;
448        window.selected_pos_customer_id = null;
449    }
450    else {
451        if (contact.email !== null) {
452
453            $("#wait_list_contact_email").val(contact.email);
454        }
455        if (contact.first_name !== undefined && contact.first_name !== null) {
456
457            $("#wait_list_contact_first_name").val(contact.first_name);
458        }
459        if (contact.last_name !== undefined && contact.last_name !== null) {
460
461            $("#wait_list_contact_last_name").val(contact.last_name);
462        }
463        if (contact.phone !== undefined && contact.phone !== null) {
464
465            $("#wait_list_contact_phone").val(contact.phone);
466        }
467        if (contact.wait_list_id !== undefined && contact.wait_list_id !== null) {
468
469            window.selected_wait_list_id = contact.wait_list_id;
470        }
471        if (contact.wait_list_contact_rel_id !== undefined && contact.wait_list_contact_rel_id !== null) {
472
473            window.selected_wait_list_contact_rel_id = contact.wait_list_contact_rel_id;
474        }
475        if (contact.pos_customer_id !== undefined && contact.pos_customer_id !== null) {
476
477            window.selected_pos_customer_id = contact.pos_customer_id;
478        }
479    }
480}
481
482function showWaitListSaveButton(email) {
483
484    if (email === undefined) {
485
486        email = $("#wait_list_contact_email").val();
487    }
488
489    var first_name = $("#wait_list_contact_first_name").val();
490    var last_name = $("#wait_list_contact_last_name").val();
491
492    if (isEmailValid(email) && first_name.length > 0 && last_name.length > 0) {
493
494        $("#wait_list_save_button").show();
495        return true;
496    }
497    else {
498
499        $("#wait_list_save_button").hide();
500        return false;
501    }
502}
503
504function isEmailValid(email) {
505
506    if (email !== undefined && email.length > 0) {
507
508        var reg = /^([A-Za-z0-9_\-\.\+])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
509        return (reg.test(email));
510    } else {
511
512        return false;
513    }
514}
515
516function SaveToWaitList() {
517
518    var wait_list = new WaitList();
519    var contact = new WaitListContact();
520    contact.email = $("#wait_list_contact_email").val();
521    contact.first_name = $("#wait_list_contact_first_name").val();
522    contact.last_name = $("#wait_list_contact_last_name").val();
523    contact.phone = $("#wait_list_contact_phone").val();
524    contact.quantity = $("#wait_list_quantity").val();
525    if (window.selected_pos_customer_id !== undefined) {
526        contact.pos_customer_id = window.selected_pos_customer_id;
527    }
528    if (window.selected_wait_list_contact_rel_id !== undefined) {
529        contact.wait_list_contact_rel_id = window.selected_wait_list_contact_rel_id;
530    }
531    if (window.selected_wait_list_id !== undefined) {
532        contact.wait_list_id = window.selected_wait_list_id;
533    }
534    wait_list.contacts.push(contact);
535    wait_list.store_id = window.storeId;
536    wait_list.item_id = window.selected_wait_list_item_id;
537    wait_list.item_type_id = window.selected_wait_list_type_id;
538    wait_list.save(function(response) {
539
540        if (response.contact !== undefined && response.contact !== null) {
541
542            Set_Cart_Cookie('waitlist', JSON.stringify(response.contact), '', '/', '', '');
543            $("#wait_list_added_span_" + window.currentProductId).html(' ' + contact.quantity + ' added to wait list');
544        }
545    });
546
547    closeWaitListModal();
548}
549
550// Class
551function closeWaitListModal() {
552
553    $("#overlayWaitListForm").dialog("close");
554}
555
556// Class
557function SaveWaitListContact(contact) {
558
559    var wait_list = new WaitList();
560    wait_list.contacts.push(contact);
561    wait_list.store_id = contact.store_id;
562    wait_list.item_id = contact.item_id;
563    wait_list.item_type_id = contact.item_type_id;
564    wait_list.save(function (response) {
565
566        if (response.contact !== undefined && response.contact !== null) {
567
568            Set_Cart_Cookie('waitlist', JSON.stringify(response.contact), '', '/', '', '');
569            $("#wait_list_added_span_" + contact.item_id).html(' ' + contact.quantity + ' added to wait list');
570        }
571    });
572}
573
574// Cart
575function CreateCartArray(cart) {
576    tuples = cart.split(";;");
577    window.cartArray = new Array();
578    for (i = 0; i < tuples.length; i++) {
579        parts = tuples[i].split("##");
580        window.cartArray[i] = parts;
581    }
582}
583
584function isCartWidgetHideWhenEmptyEnabled() {
585    return !!(window.knobby && window.knobby.module_website_cart_widget_hide_when_empty);
586}
587
588function cartTotalItems() {
589    var totalItems = 0;
590    for (var i = 0; i < window.cartArray.length; i++) {
591        var row = window.cartArray[i];
592        if (row[0] == 'product' && row[1].indexOf('PITEM') == -1) {
593            totalItems += Number(row[4]);
594        }
595    }
596    return totalItems;
597}
598
599// Cart - Makes cart visible and shows actual cart
600function ShowCart(forceExpand) {
601    var oldCart = window.cartVersion != 2017;
602    var cartDiv = $("#cartDiv");
603    var cartDivMobile = $("#cartDivMobile");
604
605    if (window.cartMode === undefined || window.cartMode == false) {
606        window.cartMode = 'normal';
607    }
608
609    if (window.cartMode == 'hidden') {
610        cartDiv.hide();
611        cartDivMobile.hide();
612    } else {
613        if (oldCart) {
614          var cart = '';
615          if (Get_Cart_Cookie('cart')) {
616              cart = Get_Cart_Cookie('cart');
617          }
618
619          if (window.cartMode == 'wide') {
620              CreateCartArray(cart);
621              cartDiv.hide();
622              cartDivMobile.hide();
623              WideCart();
624          } else if (window.cartMode == 'mobile') {
625              CreateCartArray(cart);
626              cartDiv.hide();
627              cartDivMobile.hide();
628              MobileCart(forceExpand);
629          } else {
630              CreateCartArray(cart);
631              var hasItems = isCartWidgetHideWhenEmptyEnabled() ? cartTotalItems() > 0 : cart.length > 0;
632              if (hasItems) {
633                  var toShow = true;
634                  if (GetCartArrayValueByKey('mode') == 'collapsed' && forceExpand != true) {
635                      CollapseCart();
636                  } else {
637                      toShow = ExpandCart();
638                  }
639
640                  if (toShow !== false) {
641                      cartDiv.fadeIn();
642                      cartDivMobile.fadeIn();
643                  }
644
645                  return;
646              } else {
647                  cartDiv.hide();
648                  cartDivMobile.hide();
649              }
650          }
651        } else {
652          var cart = Get_Cart_Cookie('cart');
653          if (cart && cart.length > 0) {
654              CreateCartArray(cart);
655              toShow = ExpandCart();
656              if (toShow !== false) {
657                  cartDiv.fadeIn();
658              }
659          } else {
660              cartDiv.hide();
661              cartDivMobile.hide();
662          }
663        }
664    }
665}
666
667// Cart
668function BuildCookieFromArray() {
669    var newCart = '';
670    for (var i = 0; i < window.cartArray.length; i++) {
671        if (i > 0) {
672            newCart += ';;';
673        }
674        newCart += window.cartArray[i].join("##");
675    }
676    return newCart;
677}
678
679function dataToCookieString(productId,productTitle,productPrice,productC
679ount,productWeight,productCountType,productSku,requiresDownloadEmailAddress,minQuantity,maxQuantity,notes
680    ,isTimed,holdingId,in_shipping,in_taxes,in_productType,pslrId,in_hasAttendees,isDiscountEligible,productImagePath,productImageStyle,class_attendees
681    ,deptId,categoryIdList,displayPrice,unitType,soldInIncrements,wishlistItemId, rto_items) {
682
683    //delimiter is ## so if this string ends with # we need to change it so I just add a space to the end of the string
684
685    if (
686        isNaN(productCount)
687        || isNaN(minQuantity)
688        || isNaN(minQuantity)
689    ) {
690        return '';
691    }
692    productCount = parseFloat(productCount);
693    minQuantity = parseFloat(minQuantity);
694    maxQuantity = parseFloat(maxQuantity);
695
696    if (productTitle.length > 0 && productTitle.charAt(productTitle.length - 1) == '#') {
697        productTitle = productTitle + " ";
698    }
699    if (productCount < minQuantity) {
700        var humanQuantity = minQuantity;
701        if (!!window.measurementUnit && window.measurementUnit == 'Yard') {
702
703            if (humanQuantity === '0.25') {
704                humanQuantity = '1/4';
705            } else if (humanQuantity === '0.5') {
706                humanQuantity = '1/2';
707            } else if (humanQuantity === '0.75') {
708                humanQuantity = '3/4';
709            }
710
711        }
712
713        alert('Please select a quantity greater than ' + humanQuantity);
714        return '';
715    }
716    if (productCount > maxQuantity) {
717        alert('Please select a quantity less than ' + maxQuantity);
718        return '';
719    }
720
721
722
723
724    var cookieData = ';;product##' + productId +
725        '##' + productTitle +
726        '##' + productPrice +
727        '##' + productCount +
728        '##' + productWeight +
729        '##' + productCountType +
730        '##' + productSku +
731        '##' + requiresDownloadEmailAddress +
732        '##' + minQuantity +
733        '##' + maxQuantity +
734        '##' + notes +
735        '##' + isTimed +
736        '##' + holdingId +
737        '##' + in_shipping +
738        '##' + in_taxes +
739        '##' + in_productType +
740        '##' + pslrId +
741        '##' + in_hasAttendees +
742        '##' + isDiscountEligible +
743        '##' + productImagePath +
744        '##' + productImageStyle +
745        '##' + class_attendees +
746        '##' + deptId +
747        '##' + categoryIdList +
748        '##' + displayPrice +
749        '##' + unitType +
750        '##' + soldInIncrements +
751        '##' + wishlistItemId;
752
753    if (rto_items !== undefined) {
754        cookieData += '##' + rto_items;
755    }
756    return cookieData;
757
758}
759
760// Cart - This is what renders the expanded version of the cart in the upper corner
761/** @return {boolean} */
762function ExpandCart() {
763    var oldCart = window.cartVersion != 2017;
764    var cartDiv = $("#cartDiv");
765    var cartDivMobile = $("#cartDivMobile");
766
767    var products = '';
768    var subtotal = 0;
769    var subtotal_to_discount = 0;
770    var giftCardSubtotal = 0;
771    var totalItems = 0;
772    var numProducts = 0;
773    var numGiftCards = 0;
774
775    if (oldCart) {
776        UpdateCouponsInCartArrayAndCookie();
777    }
778
779    // Item totals
780    for (var i = window.cartArray.length - 1; i >= 0; i--) {
781        var row = window.cartArray[i];
782        if (row[0] == 'product') {
783            if (row[1].indexOf('PITEM') > -1) {
784                continue;
785            }
786            totalItems += Number(row[4]);
787            var displayPrice = 0;
788            if (row[25]) {
789                displayPrice = row[25];
790            } else {
791                displayPrice = row[3];
792            }
793
794            var amount = Math.round(fractionalMultiplication(parseFloat(displayPrice), row[4]) * 100) / 100;
795
796            if (row.length > 16 && row[16] == 'GC') {
797                giftCardSubtotal += amount;
798                numGiftCards++;
799            } else {
800                numProducts++;
801                subtotal += amount;
802
803                // 19 - discount_eligible
804                if (row[19] === "true") {
805                    subtotal_to_discount += amount;
806                }
807            }
808
809            if (oldCart) {
810                var replaceTitle = window.cartArray[i][2].replace(/\+/g, ' ');
811                try {
812                    replaceTitle = JSON.parse(replaceTitle);
813                } catch (e) {}
814
815                products +=
816                    '<div style="font-size: 12px !important; line-height: 20px; border-bottom: 1px solid #999; padding-bottom:5px; margin-bottom: 10px;">' +
817                    '<div style="line-height: 14px; font-size: 11px !important; margin-bottom:4px;">' +
818                    replaceTitle +
819                    '</div>' +
820                    '<div><b>' + formatCurrency(displayPrice) + '</b></div>' +
821                    '<span style="font-size: 10px; color: #999;">quantity: ' + row[4] + '</span><br><br>' +
822                    '</div>';
823            }
824        }
825    }
826
827    // Don't show cart div if there are no items
828    if (numProducts == 0 && giftCardSubtotal == 0) {
829        return false;
830    }
831
832    // Calculate discounts
833    // This version of the cart should not require calculating the coupon as it only intends to show quantity of items
834    // however, I've kept it as the mobile version still shows a total amount
835    for (var i = window.cartArray.length - 1; i >= 0; i--) {
836        if (window.cartArray[i][0] == 'coupon' || window.cartArray[i][0] == 'couponV2') {
837            if (oldCart) {
838                var couponInfo = GetCouponInfo(window.cartArray[i]);
839                var discount = Math.round(CalculateDiscount(subtotal_to_discount, i) * 100) / 100;
840                if (discount > 0) {
841                    subtotal -= discount;
842                    products +=
843                        '<div style="font-size: 12px !important; line-height: 20px; border-bottom: 1px solid #999; padding-bottom:5px; margin-bottom: 10px;">' +
844                        '<div style="line-height: 14px; font-size: 11px !important; margin-bottom:4px;">' +
845                        couponInfo.title.replace(/\+/g, ' ') +
846                        '</div>' +
847                        '<div><b>- ' + formatCurrency(discount) + '</b></div>' +
848                        '</div>';
849                }
850
851            }
852        }
853    }
854
855    // Update subtotal
856    subtotal += giftCardSubtotal;
857    subtotal = Math.round(subtotal * 100) / 100;
858
859    if (oldCart) {
860        // Gift Card Payments
861        var giftCardPayments = 0;
862        for (var i = window.cartArray.length - 1; i >= 0; i--) {
863            if (window.cartArray[i][0] == 'giftcard') {
864                giftCardPayments += Math.round(window.cartArray[i][3] * 100) / 100;
865            }
866        }
867
868        var giftCardRows = '';
869        if (giftCardPayments > 0) {
870            if (subtotal < giftCardPayments) {
871                giftCardPayments = subtotal;
872            }
873            giftCardRows = '<span style="color: #ccc; font-size: 14px;"><b>Gift Cards = ' + formatCurrency(giftCardPayments) + '</b></span><br>';
874            subtotal -= giftCardPayments;
875        }
876
877    }
878
879    // Mobile bottom div
880    cartDivMobile.html(
881        '<div style="padding:10px;" onclick="location=\'' + editcartUrl + '\'">' +
882        '<table width="100%"><tr>' +
883        '<td style="text-align: left; cursor: pointer; color: #fff;">' +
884        '<img style="width:23px; height:18px; vertical-align:middle; margin-bottom: 4px;" src="https://images.rainpos.com/view-cart.png">&nbsp;&nbsp;&nbsp;Cart - ' + (totalItems) + ' items' +
885        '</td>' +
886        '<td style="text-align: right; cursor: pointer; color: #fff;">' + formatCurrency(subtotal) + '</td>' +
887        '</tr></table></div>'
888    );
889
890    if (!oldCart || window.ABCart == 'B') {
891        // Full page upper corner bullet
892        cartDiv.attr('style', 'display:none; top: 10px; right: 10px; padding: 0px; width: 150px; background: none;');
893        cartDiv.html(
894            '<div class="btnViewCart" onclick="location=\'' + editcartUrl + '\'" >' +
895            '<img style="width:23px; height:18px; vertical-align:middle; margin-bottom: 4px;" src="https://images.rainpos.com/view-cart.png">' +
896            ' &nbsp;' + (totalItems) + ' Item' + (totalItems != 1 ? 's' : '') +
897            '</div>'
898        );
899    } else {
900        cartDiv.html(
901            '<div style="display:table; height:28px; text-align:right; width:100%;">' +
902            '  <span style="display:table-cell; width:20px;"></span>' +
903            '  <span style="vertical-align:middle; text-align:center; display:table-cell; color: #ccc; font-family: Arial; font-size: 12px !important;">' +
904            '    <a href="' + editcartUrl + '" style="' + linkStyles + '">View Cart</a>' +
905            '  </span>' +
906            '  <span style="vertical-align:middle; width:20px; display:table-cell; color: #ccc; font-family: Arial; font-size: 12px !important;">' +
907            '    <a href="javascript:CollapseCart();"><img border=0 width=16 height=11 src="https://images.rainpos.com/btn-collapse.png"></a>' +
908            '  </span>' +
909            '</div>' +
910
911            '<div style="width: 100%; top: 30px; right: 0px; border-top: 1px solid #888; margin-bottom:10px;"></div>' +
912            '<div class="btnViewCart" onclick="ProceedToCheckout(\'no\');" style="font-size:14px; font-family: Arial !important;">Proceed to Checkout &raquo;</div>' +
913            '<div style="text-align:left; margin-top:10px; margin-bottom:10px; padding: 10px; color: #fff; height: 200px; overflow:auto; background: url(https://images.rainpos.com/cart-bg-2a.png) repeat;">' +
914            products +
915            '</div>' +
916            giftCardRows +
917            '<div style="color: #ddd; font-size: 14px !important; padding:4px;">Subtotal = ' + formatCurrency(subtotal) + '</div>' +
918            '<div style="line-height:20px;">' +
919            '<a href="' + editcartUrl + '&enterCoupon=true" style="' + linkStyles + '">Enter Coupon</a><br>' +
920            (window.paymentProcessor === undefined || window.paymentProcessor == false || window.paymentProcessor == 'paypal' ? '' : '<a href="' + editcartUrl + '&enterGiftcard=true" style="' + linkStyles + '">Enter Gift Card</a><br>') +
921            '<a href="' + editcartUrl + '" style="' + linkStyles + '">View Cart</a>' +
922            '</div>' +
923            '<div class="btnViewCart" onclick="ProceedToCheckout(\'no\');" style="font-size:14px; font-family: Arial !important; margin-bottom: 10px; margin-top: 5px;">Proceed to Checkout &raquo;</div>' +
924            MakeCartForm() +
925            '');
926    }
927
928    return true;
929}
930
931/** @return {string} */
932function ProductAttributeKeyGet(in_productId, in_attributeIndex) {
933    // Get the key
934    var key = '';
935    for (var i = 0; i < window['numAttributes' + in_productId]; i++) {
936        key += (key.length > 0 ? '-' : '') + $('#attribute_' + in_productId + '_' + i).val();
937    }
938
939    if (key == '') {
940        key = '0';
941    }
942
943    return key;
944}
945
946// Used by the product page - probably does not belong in this file
947function handleProductOptionChanged(in_productId, in_attributeIndex) {
948    var newPrice = '';
949    var isSale;
950    var integer = $("#integer" + in_productId);
951    var fraction = $("#fraction" + in_productId);
952    var currentIntegerVal = parseInt(integer.val());
953    var currentFractionVal = parseFloat(fraction.val());
954    var minFraction = window.siteMinimumFraction;
955
956    // Get the key
957    var key = ProductAttributeKeyGet(in_productId, in_attributeIndex);
958    var pslrId = parseInt(window['prices' + in_productId][key]['pslrId']);
959
960     // Show propper Custom fields and hide others
961    $('#product-details-pricing-table .custom-fields').hide();
962    $('#product-details-pricing-table .custom-fields-' + pslrId).show();
963
964    // Set font colors to black for attributes that are available for the just-selected attribute, and gray for those that aren't available
965
966    var reserve = 0;
967    var outOfStock = false;
968
969    if (window['prices' + in_productId][key]) {
970        var temp = window['prices' + in_productId][key]['salePrice'];
971        // Is the selected product option on sale?
972        isSale = (parseFloat(window['prices' + in_productId][key]['salePrice']) > 0.0 ? true : false);
973
974        // Set price label
975        $('#spanPriceLabel' + in_productId).html((isSale == true ? 'SALE:' : 'Price:'));
976
977        // Set price value
978        if (isSale == true) {
979            newPrice = '<strike>' + formatCurrency(window['prices' + in_productId][key]['price']) + '</strike> &nbsp;<b><span style="color:#ff0000;">' + formatCurrency(window['prices' + in_productId][key]['salePrice']) + '</span></b>';
980        } else {
981            newPrice = formatCurrency(window['prices' + in_productId][key]['finalDisplayPrice']);
982        }
983        $('#spanPrice' + in_productId).html(newPrice);
984
985        // Set quantity dropdowns
986
987        // Integer
988        var maxInteger = Math.floor(parseFloat(window['prices' + in_productId][key]['quantity']));
989        if (currentIntegerVal > maxInteger) {
990            currentIntegerVal = maxInteger;
991        }
992        var startInteger = (window['isFabric' + in_productId] == true ? 0 : 1);
993        var soldInIncrements = window['soldInIncrements' + in_productId];
994        integer.html("");
995        for (var i = startInteger; i <= maxInteger; i++) {
996                if ((i === 0) && ((minFraction === 1) || (minFraction === '1'))) {
997                    continue;
998                }
999
1000
1001            if ((i % soldInIncrements) > 0) {
1002                continue;
1003            }
1004            integer.append("<option value=\'" + i + "\' " + (currentIntegerVal == i ? 'selected' : '') + ">" + i + "</option>");
1005        }
1006        $('#maxInteger' + in_productId).val(maxInteger);
1007
1008        if(maxInteger <= 0 && (typeof maxFraction === 'undefined' && !window['isFabric' + in_productId])) {
1009            outOfStock = true;
1010        }
1011
1012        // Fraction
1013        if (window['isFabric' + in_productId] == true) {
1014            var increment = (window.measurementUnit == 'Meter' ? 10 : 25);
1015            var maxFraction = Math.floor(parseFloat(window['prices' + in_productId][key]['quantity']) * 100) % 100;
1016            maxFraction = (maxFraction - (maxFraction % increment)) / 100;
1017            if (currentIntegerVal == 0 && currentFractionVal == 0) {
1018                currentFractionVal = maxFraction;
1019            } else if (currentIntegerVal == maxInteger && currentFractionVal > maxFraction) {
1020                currentFractionVal = maxFraction;
1021            }
1022            $('#maxFraction' + in_productId).val(maxFraction);
1023
1024            fraction.html("");
1025            var startVal = 0;
1026            if (currentIntegerVal == 0) {
1027                if (minFraction && (minFraction > 0) && (minFraction < 1)) {
1028                    startVal = Math.floor(window.siteMinimumFraction * 100);
1029                } else {
1030                    startVal = (window.measurementUnit === 'Meter') ? 10 : 25;
1031                }
1032
1033            }
1034            for (var i = startVal; i < 100; i += increment) {
1035                var decimal = (i / 100);
1036                if (maxInteger == currentIntegerVal && maxFraction < decimal) {
1037                    break;
1038                }
1039                var appendStr = '';
1040                if (window.measurementUnit == 'Meter' && currentIntegerVal == 0 && decimal == .3 && window.siteMinimumFraction == 'fat quarter') {
1041                    appendStr += "<option value=\'0.25\' " + (currentFractionVal == 0.25 ? 'selected' : '') + ">Fat Quarter</option>";
1042                }
1043                appendStr += "<option value=\'" + decimal + "\' " + (currentFractionVal == decimal ? 'selected' : '') + ">";
1044                if (window.measurementUnit == 'Meter') {
1045                    appendStr += decimal;
1046                } else {
1047                    appendStr += (decimal == 0.25 ? (currentIntegerVal == 0 && window.siteMinimumFraction == 'fat quarter' ? 'Fat Quarter' : '1/4') : (decimal == 0.5 ? '1/2' : (decimal == 0.75 ? '3/4' : decimal)));
1048                }
1049                appendStr += "</option>";
1050                fraction.append(appendStr);
1051            }
1052        }
1053
1054        // WishList
1055        if (typeof wishlistApp != 'undefined' && wishlistApp) {
1056
1057            var qtyInteger = $("#integer" + in_productId);
1058            var qtyFraction = $("#fraction" + in_productId);
1059            var qtyIntegerVal = parseInt(qtyInteger.val());
1060            var qtyFractionVal = parseFloat(qtyFraction.val());
1061
1062            // Handle NaN
1063            if (!qtyIntegerVal) {
1064                qtyIntegerVal = 0;
1065                if ((minFraction === 1) || (minFraction === '1')) {
1066                    qtyIntegerVal = 1;
1067                }
1068            }
1069            if (!qtyFractionVal) {
1070                qtyFractionVal = 0;
1071            }
1072
1073            wishlistApp.$root.$emit('update_pslr_qty', {pslr_id: pslrId, qty: (qtyIntegerVal + qtyFractionVal)});
1074        }
1075    } else {
1076        outOfStock = true
1077    }
1078
1079    if (window['isFabric' + in_productId] === true && window['prices' + in_productId][key]['quantity'] < minimumQuantity) {
1080        outOfStock = true;
1081    }
1082
1083    var newPriceNumber = Number(newPrice.replace(/[^0-9\.-]+/g,""));
1084    var freeProductNotAllowed =
1085        newPriceNumber <= 0 &&
1086        (typeof window['freeProductsAllowed'] !== 'undefined' && window['freeProductsAllowed'] === false);
1087
1088    if (freeProductNotAllowed) {
1089        $('[id^=add-to-cart-btn-' + in_productId + ']').attr('disabled','disabled');
1090        $('[id^=add-to-cart-btn-' + in_productId + ']').html('Product Unavailable');
1091    } else {
1092        $('[id^=add-to-cart-btn-' + in_productId + ']').removeAttr("disabled");
1093        $('[id^=add-to-cart-btn-' + in_productId + ']').html('Add to Cart');
1094    }
1095
1096    if (outOfStock || (reserve > 0 && maxInteger == 0 && (window['isFabric' + in_productId] != true || maxFraction == 0))) {
1097        $('[id^=integer' + in_productId + ']').hide();
1098        $('[id^=fraction' + in_productId + ']').hide();
1099        $('[id^=add-to-cart-btn-' + in_productId + ']').hide();
1100        $('[id^=reserve' + in_productId + ']').html('<span style="color:#f00;">Out of Stock</span>').show();
1101    } else {
1102        $('[id^=integer' + in_productId + ']').show();
1103        $('[id^=fraction' + in_productId + ']').show();
1104        $('[id^=add-to-cart-btn-' + in_productId + ']').show();
1105        $('[id^=reserve' + in_productId + ']').hide();
1106    }
1107
1108    var conditionalSelect = $('#conditional-select');
1109    if (!conditionalSelect) {
1110        return;
1111    }
1112
1113    var conditionOptions = window['prices' + in_productId][key]['conditional_option']
1114
1115    if (conditionOptions) {
1116        $.each(conditionOptions, function (i, item) {
1117            conditionalSelect.append($('<option>', {
1118                value: item.value,
1119                text : item.label,
1120                selected: i === 0.
1121            }));
1122        });
1123        conditionalSelect.attr('data-key', key);
1124        conditionalSelect.trigger('change');
1125    } else {
1126        conditionalSelect.parent().parent().css('display','none');
1127    }
1128}
1129
1130// Cart
1131function formatCurrency(num) {
1132    num = num.toString().replace(/\$|\,/g, '');
1133    if (isNaN(num)) {
1134        num = "0";
1135    }
1136    sign = (num == (num = Math.abs(num)));
1137    num = Math.floor(num * 100 + 0.50000000001);
1138    cents = num % 100;
1139    num = Math.floor(num / 100).toString();
1140    if (cents < 10) {
1141        cents = "0" + cents;
1142    }
1143    for (var i = 0; i < Math.floor((num.length - (1 + i)) / 3); i++) {
1144        num = num.substring(0, num.length - (4 * i + 3)) + ',' +
1145            num.substring(num.length - (4 * i + 3));
1146    }
1147    return (((sign) ? '' : '-') + window.displayCurrencySymbol + num + '.' + cents + ' ' + window.displayCurrency);
1148}
1149
1150// Rental Cart (Outdoor)
1151function addRentalToCart(rentalDataId, price) {
1152    if (isRentalInCart(rentalDataId)) {
1153        updateRentalPrice(rentalDataId, price);
1154    } else {
1155        AddProductToCart('', 'sale', rentalDataId, 'Rental', price, 0, 'integer', '', 'no', 1, 1, 0, '', '', 0, '', 'RENTAL', '', 'false', '', '');
1156    }
1157}
1158
1159function isRentalInCart(rentalDataId) {
1160    var cart = Get_Cart_Cookie('cart');
1161    if (cart && cart.length > 0 && window.cartArray) {
1162        for (var i = 0; i < window.cartArray.length; i++) {
1163            if (window.cartArray[i][1] == 'RENTAL' + rentalDataId) {
1164                return true;
1165            }
1166        }
1167    }
1168    return false;
1169}
1170
1171function updateRentalPrice(rentalDataId, price) {
1172    var cart = Get_Cart_Cookie('cart');
1173    if (cart && cart.length > 0 && window.cartArray) {
1174        for (var i = 0; i < window.cartArray.length; i++) {
1175            if (window.cartArray[i][1] == 'RENTAL' + rentalDataId) {
1176                window.cartArray[i][3] = price;
1177                updateCart();
1178                return;
1179            }
1180        }
1181    }
1182}
1183
1184function updateCart() {
1185    Set_Cart_Cookie('cart', BuildCookieFromArray(), '', '/', '', '');
1186}
1187
1188function addWishlistProductToCart(item, qty, maxQty, unitType) {
1189
1190    var productId = item.product_id;
1191    var pslrId = item.item_id;
1192
1193    var prices = item.prices;
1194    var price = prices['price'];
1195    if(prices['sale_price'] > 0 && prices['sale_price'] < price) {
1196        price = prices['sale_price'];
1197    }
1198
1199    var notes = '';
1200    console.log('add '+ qty +'product ' + productId + ' pslr ' + pslrId);
1201
1202    var min = 0;
1203    if(item.qty_on_hand > 0 || item.unlimitedWebInventory === 1) {
1204        min = 1;
1205    }
1206    var discountEligibility = item.discount_eligible;
1207
1208    // (in_businessEmail, in_paymentAction, productId, productTitle, productPrice, productWeight, productCountType, productSku, requiresDownloadEmailAddress, minQuantity, maxQuantity, isTimed, in_notes, in_shipping, in_taxes, inlineAddToCartBtn, in_productType, in_hasAttendees, isDiscountEligible, productImagePath, productImageStyle, requireClassAttendees,
1209    // pslrId, packageData, holdingId, deptId, categoryIdList, displayPrice, unitType, soldInIncrements,qty, wishlist_id
1210    AddProductToCart(
1211        '',
1212        'sale',
1213        productId,
1214        item.title,
1215        price,
1216        item.weight,
1217        item.productCountType,
1218        item.sku,
1219        'no',
1220        min,
1221        maxQty,
1222        0,
1223        notes,
1224        '',
1225        item.bitmap_tax,
1226        '',
1227        'PSLR',
1228        '',
1229        discountEligibility,
1230        item.thumbnail,
1231        '',
1232        false,
1233        pslrId,
1234        null,
1235        null,
1236        item.department_id,
1237        JSON.parse(item.category_ids),
1238        null,
1239        unitType,
1240        null,
1241        qty,
1242        item.wishlist_item_id
1243    );
1244}
1245
1246
1247// RTO Cart (Music)
1248function addRtoToCartWithCondition(token, pslrId, conditionId, schoolDistrictId, schoolId, studentName, selectedMaintenance, selectedProtection, conditionPiiId) {
1249    conditionPiiId = (conditionPiiId === undefined) ? null : conditionPiiId;
1250    var request = {
1251        pslr_id: pslrId,
1252        condition_id: conditionId,
1253        school_district_id: schoolDistrictId,
1254        school_id: schoolId,
1255        student_name: studentName,
1256        selected_maintenance: selectedMaintenance,
1257        selected_protection: selectedProtection,
1258        condition_pii_id: conditionPiiId
1259    };
1260
1261    $.ajax({
1262        url: '/api/rto/online/contract',
1263        type: 'POST',
1264        dataType: 'json',
1265        contentType: 'application/json',
1266        data: JSON.stringify(request),
1267        headers: {
1268            Authorization: 'Bearer ' + token
1269        },
1270        success: function(result) {
1271            if (result.result != 'success') {
1272                alert('There was an error adding your rental to the cart.');
1273            } else {
1274                var notes = '';
1275                if (result.taxable_amount) {
1276                    notes = JSON.stringify({taxable_amount:result.taxable_amount});
1277                }
1278
1279                var rto_items = null;
1280                if (result.rto_items !== undefined) {
1281                    rto_items = JSON.stringify({
1282                        rto_principle_payment: result.rto_items.rto_principle_payment,
1283                        rto_down_payment: result.rto_items.rto_down_payment,
1284                        rto_product_tax_bitmap: result.rto_items.rto_product_tax_bitmap,
1285                        rto_maintenance_payment: result.rto_items.rto_maintenance_payment,
1286                        rto_maintenance_tax_bitmap: result.rto_items.rto_maintenance_tax_bitmap,
1287                        rto_insurance_payment: result.rto_items.rto_insurance_payment,
1288                        rto_insurance_tax_bitmap: result.rto_items.rto_insurance_tax_bitmap,
1289                        rto_security_deposit: result.rto_items.rto_security_deposit,
1290                        rto_initial_payments: result.rto_items.rto_initial_payments,
1291                        rto_interest_rate: result.rto_items.rto_interest_rate,
1292                        rto_interest_tax_bitmap: result.rto_items.rto_interest_tax_bitmap,
1293                    });
1294                }
1295                AddProductToCart('', 'sale', result.rto_id, result.title + ' - Rental', result.due, result.weight, 'integer', '', 'no', 1, 1, 0, notes, '', 0, '', 'RTO', '', 'false', '', '', false, pslrId, null, conditionId, null, null, null, null, null, null, null, rto_items);
1296            }
1297        }
1298    });
1299}
1300
1301function createAndAddOsrToCart(token, rentalId, variationId, conditionId, maintenance, protection, student, customerInfo, image, addons) {
1302    var config = {
1303        headers: {
1304            Authorization: 'Bearer ' + token,
1305        }
1306    };
1307
1308    var data = {
1309        rentalId: rentalId,
1310        variationId: variationId,
1311        conditionId: conditionId,
1312        maintenance: maintenance,
1313        protection: protection,
1314        student: student,
1315        customerInfo: customerInfo,
1316        addons: addons,
1317    };
1318
1319    return axios.post('/api/online-school-rentals/cart-contract', data, config)
1320        .then(function (response) {
1321            var data = response.data;
1322
1323            if (!data || !data.rto_id) {
1324                return Promise.reject(new Error('Error on contract creation'));
1325            }
1326
1327            var rtoItems = data.rto_items ? {
1328                rto_principle_payment: data.rto_items.rto_principle_payment,
1329                rto_down_payment: data.rto_items.rto_down_payment,
1330                rto_product_tax_bitmap: data.rto_items.rto_product_tax_bitmap,
1331                rto_maintenance_payment: data.rto_items.rto_maintenance_payment,
1332                rto_maintenance_tax_bitmap: data.rto_items.rto_maintenance_tax_bitmap,
1333                rto_insurance_payment: data.rto_items.rto_insurance_payment,
1334                rto_insurance_tax_bitmap: data.rto_items.rto_insurance_tax_bitmap,
1335                rto_security_deposit: data.rto_items.rto_security_deposit,
1336                rto_initial_payments: data.rto_items.rto_initial_payments,
1337                rto_interest_rate: data.rto_items.rto_interest_rate,
1338                rto_interest_tax_bitmap: data.rto_items.rto_interest_tax_bitmap,
1339            } : null;
1340
1341            return AddOsrToCart(
1342                data.rto_id,
1343                data.title,
1344                data.due,
1345                data.weight,
1346                {taxable_amount: data.taxable_amount},
1347                image,
1348                data.pslr_id,
1349                conditionId,
1350                rtoItems
1351            );
1352        });
1353}
1354
1355function AddOsrToCart(productId, productTitle, productPrice, productWeight, notes, productImagePath, pslrId, holdingId, rtoItems) {
1356    // Get custom fields & notes
1357    productId = 'RTO' + productId;
1358    notes = notes ? JSON.stringify(notes) : '';
1359    rtoItems = rtoItems ? JSON.stringify(rtoItems) : null;
1360
1361    var cookieData = dataToCookieString(
1362        productId, productTitle, productPrice, 1, productWeight, 'integer', '',
1363        'no', 1, 1, notes, 0, holdingId, '',
1364        0, 'OSR', pslrId || '', '', 'false', productImagePath, '',
1365        '', null, JSON.stringify(null), productPrice, 'each', 1, null, rtoItems
1366    );
1367
1368    if (cookieData === '') {
1369        return Promise.reject(new Error('Wrong cart item data'));
1370    }
1371
1372    var promise = addItemToCartData(cookieData);
1373
1374    if (window.facebookPixelId) {
1375        fbq('track', 'AddToCart', {
1376            currency: window.currency,
1377            value: productPrice,
1378            content_name: productTitle,
1379            content_ids: [productId],
1380            content_type: 'product',
1381            contents: [{
1382                'id': productId,
1383                'quantity': 1
1384            }]
1385        });
1386    }
1387
1388    addGAEvent(productId, productTitle, productPrice, 1);
1389
1390    return promise;
1391}
1392
1393// Cart
1394
1395
1396function yardLoop(maxFractionVal, siteMinimumFraction, fraction, currFractionVal, intVal, maxIntVal){
1397    //we could probably be clever and do something cool like the meter loop...but not enough values to make it worth it
1398    fraction.html("");
1399    if(currFractionVal > maxFractionVal && intVal >= maxIntVal){
1400        currFractionVal = maxFractionVal;
1401    }
1402    if (intVal === 0) {
1403        if (window.siteMinimumFraction === 'fat quarter') {
1404            fraction.append("<option " + (currFractionVal < 0.5 ? "selected" : "") + " value=\'0.25\'>Fat Quarter</option>");
1405        }
1406        if (window.siteMinimumFraction === '0.25' || window.siteMinimumFraction === '') {
1407            fraction.append("<option " + (currFractionVal < 0.5 ? "selected" : "") + " value=\'0.25\'>1/4</option>");
1408        }
1409    } else {
1410        fraction.append("<option value=\'0\'>0</option>");
1411        if (intVal < maxIntVal || maxFractionVal >= 0.25) {
1412            fraction.append("<option " + (currFractionVal === 0.25 ? "selected" : "") + " value=\'0.25\'>1/4</option>");
1413        }
1414    }
1415    if (intVal < maxIntVal || maxFractionVal >= 0.5) {
1416        fraction.append("<option " + (currFractionVal === 0.5 ? "selected" : "") + " value=\'0.5\'>1/2</option>");
1417    }
1418    if (intVal < maxIntVal || maxFractionVal >= 0.75) {
1419        fraction.append("<option " + (currFractionVal === 0.75 ? "selected" : "") + " value=\'0.75\'>3/4</option>");
1420    }
1421}
1422
1423function meterLoop(startingFraction, currentFraction, fraction, maxFractionValue, intVal, maxIntVal){
1424
1425    var i = parseFloat(startingFraction);
1426    if(intVal<maxIntVal){
1427        maxFractionValue = .9
1428    }
1429    if(currentFraction < i ){
1430        currentFraction = i;
1431    }
1432    if(currentFraction > maxFractionValue && intVal >= maxIntVal){
1433        currentFraction = maxFractionValue;
1434    }
1435    if (startingFraction === .25 ){
1436        fraction.append("<option " + (currentFraction === .25  ? "selected" : "") + " value=\'0.25\'>Fat Quarter</option>");
1437        i = parseFloat(.3);
1438    }
1439    for(i; i <= maxFractionValue ; i += .1 ){
1440        var count = i.toFixed(1);
1441        fraction.append("<option " + (currentFraction == count ? "selected" : "") + " value=\'"+ count +"\'>"+ count.replace(/^0+/,"")+"</option>");
1442        if (i === .2 && intVal === 0 ){
1443            fraction.append("<option " + (currentFraction === .25  ? "selected" : "") + " value=\'0.25\'>Fat Quarter</option>");
1444        }
1445    }
1446    return fraction;
1447}
1448
1449// TODO - This function is a little better, but still messy, and needs additional refactoring and automated tests
1450function checkFabricMinimum(id, maxQuantity)
1451{
1452    var minFraction = window.siteMinimumFraction;
1453    var minFractionVal = (minFraction === 'fat quarter') ? 0.25 : minFraction;
1454
1455    var intVal = parseInt($("#integer" + id).val());
1456    var fraction = $("#fraction" + id);
1457    var currFractionVal = parseFloat(fraction.val());
1458
1459    var maxIntVal;
1460    var maxFractionVal;
1461
1462    if (typeof maxQuantity === 'undefined') {
1463        maxIntVal = parseInt($("#maxInteger" + id).val());
1464        maxFractionVal = parseFloat($("#maxFraction" + id).val());
1465    } else {
1466        maxQuantity = parseFloat(maxQuantity);
1467        maxIntVal = Math.floor(maxQuantity);
1468        maxFractionVal = Math.floor((maxQuantity * 100) % 100) / 100;
1469    }
1470
1471    // WishList
1472
1473    if ((typeof wishlistApp !== 'undefined') && wishlistApp) {
1474        var key = ProductAttributeKeyGet(id, 0);
1475        var pslrId = parseInt(window['prices' + id][key]['pslrId']);
1476
1477        wishlistApp.$root.$emit('update_pslr_qty', {pslr_id: pslrId, qty: (intVal + currFractionVal)});
1478    }
1479
1480    // Fractional handling
1481
1482    if (window.measurementUnit === 'Meter') {
1483        fraction.html("");
1484        if (intVal === 0) {
1485            meterLoop(minFractionVal, currFractionVal, fraction, maxFractionVal, intVal, maxIntVal);
1486        } else {
1487            meterLoop('0', currFractionVal, fraction, maxFractionVal, intVal, maxIntVal);
1488        }
1489
1490    } else {
1491            yardLoop(maxFractionVal, siteMinimumFraction, fraction, currFractionVal, intVal, maxIntVal);
1492    }
1493}
1494
1495function getPslrIdFromUI(productId)
1496{
1497    // Find which PSLR is selected
1498    var key = '';
1499    for (var i = 0; i < window['numAttributes' + productId]; i++) {
1500        key += (key.length > 0 ? '-' : '') + $('#attribute_' + productId + '_' + i).val();
1501    }
1502    if (key == '') {
1503        key = '0';
1504    }
1505    pslrId = window['prices' + productId][key]['pslrId'];
1506    return pslrId;
1507}
1508
1509function getQuantityFromUI(productId)
1510{
1511    quantity = 1;
1512    if (typeof inlineAddToCartBtn !== 'undefined') {
1513        quantity = parseInt(document.getElementById('inlineInteger' + productId).value) + parseFloat(document.getElementById('inlineFraction' + productId).value);
1514    } else {
1515        var element = document.getElementById('integer' + productId);
1516        var element2 = document.getElementById('fraction' + productId);
1517        quantity = 0;
1518        if (element) {
1519            quantity += parseInt(element.value);
1520        }
1521        if (element2) {
1522            quantity += parseFloat(element2.value);
1523        }
1524    }
1525    return quantity;
1526}
1527
1528function getNotesFromUI(productId) {
1529    var notes = '';
1530    var noteObjects = $(".class" + productId);
1531    noteObjects.each(function(i) {
1532        if (notes === 'return') {
1533            return;
1534        }
1535        var noteName = $(this).attr('name');
1536        var noteValue = '';
1537
1538        if ($(this).is(':checkbox')) {
1539            noteValue = ($(this).is(":checked") ? 'checked' : 'not checked');
1540        }
1541        else {
1542            noteValue = $.trim($(this).val());
1543        }
1544
1545        if ($(this).attr('required') == true && noteValue == '') {
1546            alert(noteName + ' is a required field.');
1547            notes = 'return';
1548            return;
1549        }
1550
1551        if (notes == '') {
1552            notes = {};
1553        }
1554        notes[noteName] = noteValue;
1555    });
1556
1557    if (notes == 'return') {
1558        return;
1559    }
1560    return notes;
1561}
1562
1563function createItem(productId, productTitle, productPrice, productWeight, productCountType, productSku, requiresDownloadEmailAddress, minQuantity, maxQuantity, isTimed, in_notes, in_shipping, in_taxes, inlineAddToCartBtn, in_productType, in_hasAttendees, isDiscountEligible, productImagePath, productImageStyle, requireClassAttendees, pslrId, packageData, holdingId, deptId, categoryIdList, displayPrice, unitType, soldInIncrements, quantity, wishlistItemId, rto_items, conditionId, conditions, addonId) {
1564    if (in_productType === 'PSLR') {
1565        if (!pslrId) {
1566            pslrId = getPslrIdFromUI(productId);
1567        }
1568
1569        // Get Quantity
1570        if (!quantity) {
1571            quantity = getQuantityFromUI(productId);
1572        }
1573
1574        var notes = in_notes;
1575        if (!notes) {
1576            notes = getNotesFromUI(productId);
1577        }
1578
1579        var pslr = {
1580            type: in_productType,
1581            pslr_id: pslrId,
1582            product_id: productId,
1583            quantity: quantity,
1584            notes: notes,
1585            wishlistItemId: wishlistItemId || 0,
1586            title: productTitle,
1587        };
1588
1589        if (conditionId) {
1590            pslr['condition'] = conditionId;
1591        } else {
1592            var condition = getConditional(productId);
1593            if (condition) {
1594                pslr['condition'] = condition.id;
1595            }
1596        }
1597
1598        if (conditions) {
1599            pslr['conditions'] = conditions;
1600        }
1601
1602        if (window.knobby && window.knobby['module_comment_sold']) {
1603            pslr.sku = productSku;
1604            pslr.price = productPrice;
1605        }
1606        if (addonId) {
1607            pslr['addon_id'] = addonId;
1608        }
1609
1610        return pslr;
1611    }
1612    return null;
1613}
1614
1615function getConditional(productId) {
1616    if (!document.getElementById('conditional-select')) {
1617        return null;
1618    }
1619
1620    if (document.getElementById('conditional-select') === null) {
1621        return null;
1622    }
1623
1624    var key = ProductAttributeKeyGet(productId, 0);
1625
1626    var value = document.getElementById('conditional-select').value;
1627
1628    var conditional = window['prices' + productId][key]['conditional'];
1629
1630    if (!conditional) {
1631        return null;
1632    }
1633
1634    return conditional.find(function (v) {
1635        return parseInt(v.item_condition_id) === parseInt(value);
1636    });
1637}
1638
1639function getConditionQuantity(productId, conditionId, key = null) {
1640    key = key === null ? ProductAttributeKeyGet(productId, 0) : key;
1641
1642    var conditionQuantity = window['prices' + productId][key]['conditional_quantity'].find(function (v) {
1643        return parseInt(v.condition_id) === parseInt(conditionId);
1644    });
1645
1646    return conditionQuantity ? parseInt(conditionQuantity.quantity) : 0;
1647}
1648
1649function addClassToCart(classId, eventId, requireAttendees, packageData, class_id_str) {
1650    if (requireAttendees) {
1651        var result = verifyClassAttendees('CLASS' + eventId);
1652        if (!result) {
1653            return;
1654        }
1655    }
1656
1657    var selectedComponents = [];
1658    var packageId = null;
1659    if (packageData && packageData.available && packageData.option === 'classAndPackage') {
1660        packageId = packageData.packageId;
1661        if (packageData.components) {
1662            packageData.components.forEach(function(c) {
1663                selectedComponents.push(c.selectedItem);
1664            });
1665        }
1666    }
1667
1668    var item = {
1669        type: 'CLASS',
1670        event_id: eventId,
1671        class_id: classId,
1672        package_id: packageId,
1673        components: selectedComponents,
1674        class_attendees: getClassAttendees('CLASS' + eventId),
1675    }
1676    addItemToCart(item);
1677}
1678
1679function addItemToCart(item, productId) {
1680    if (!isValidConditionQuantityInCart(item, productId)) {
1681        if (!item.hasOwnProperty('conditions')) {
1682            decreaseActualConditionQuantity(productId, item.condition);
1683        }
1684
1685        alert('There was an error adding this item to your cart.');
1686        return Promise.resolve();
1687    }
1688
1689    var promise = requestModule.getInstance().addItemToCart({
1690        item: item,
1691    });
1692
1693    // Google Analytics
1694    if (item.type === 'PSLR') {
1695        if (item.quantity > 0) {
1696            addGAEvent(item.product_id, item.title, item.price, item.quantity);
1697        }
1698    }
1699
1700    if (window.knobby && window.knobby['module_comment_sold']) {
1701        if (typeof item.type !== 'undefined' && item.type.toLowerCase() === 'pslr') {
1702            //we want to fire event only for pslr items
1703            var data = {
1704                product: {
1705                    sku: item.pslr_id || item.sku,
1706                    price: parseFloat(item.price),
1707                    currency: window.currency || 'USD',
1708                    quantity: item.quantity,
1709                }
1710            }
1711            try {
1712                videeoCommand('addToCart', data);
1713            } catch (e) {
1714                console.warn(e);
1715            }
1716        }
1717    }
1718
1719    return promise;
1720}
1721
1722/**
1723 * Adds a product to the cart (pre-2017 version).
1724 * When adding parameters, make sure to also add them for GetAttendees()
1725 */
1726function AddProductToCart(in_businessEmail, in_paymentAction, productId, productTitle, productPrice, productWeight, productC
1726ountType, productSku, requiresDownloadEmailAddress, minQuantity, maxQuantity, isTimed, in_notes, in_shipping, in_taxes, inlineAddToCartBtn, in_productType, in_hasAttendees, isDiscountEligible, productImagePath, productImageStyle, requireClassAttendees, pslrId, packageData, holdingId, deptId, categoryIdList, displayPrice, unitType, soldInIncrements, quantity, wishlistItemId, rto_items, conditionId, conditions) {
1727    if (window.location.search.indexOf('ie') == -1) { // IE still can't use the new product page.
1728        if (requireClassAttendees) {
1729            var result = verifyClassAttendees(productId);
1730            if (!result) {
1731                return;
1732            }
1733        }
1734
1735        var item = createItem(productId, productTitle, productPrice, productWeight, productCountType, productSku, requiresDownloadEmailAddress, minQuantity, maxQuantity, isTimed, in_notes, in_shipping, in_taxes, inlineAddToCartBtn, in_productType, in_hasAttendees, isDiscountEligible, productImagePath, productImageStyle, requireClassAttendees, pslrId, packageData, holdingId, deptId, categoryIdList, displayPrice, unitType, soldInIncrements, quantity, wishlistItemId, rto_items, conditionId, conditions);
1736        if (item) {
1737            addItemToCart(item, productId);
1738            return;
1739        }
1740    }
1741
1742    unitType = unitType || 'each';
1743    soldInIncrements = soldInIncrements || 1;
1744
1745    if (in_businessEmail !== null) {
1746        window.businessEmail = in_businessEmail;
1747    }
1748
1749    if(typeof deptId === 'undefined') {
1750        deptId = null;
1751    }
1752    if(typeof categoryIdList === 'undefined') {
1753        categoryIdList = [];
1754    }
1755
1756    // Class Package Items
1757    var classPackage = false;
1758    var classPackageData = [];
1759    if (productId.indexOf('CLASS') > -1) {
1760        // Overloading here - it's just too much work to add new fields and we want to redo all this anyway
1761        var classUid = new Date().getTime();
1762        productSku = classUid;
1763        if (packageData && packageData.available) {
1764            classPackage = true;
1765            if (packageData.option == 'classAndPackage') {
1766                in_productType = 'PACKAGE';
1767                pslrId = packageData.packageId;
1768                productWeight = packageData.class_price;
1769                if (packageData.components) {
1770                    packageData.components.forEach(function(c) {
1771                        var s = c.selectedItem;
1772                        var packageItemData = AddProductToCart(null, null, 'PITEM' + packageData.packageId, s.title, s.price, 0, null, '', 'no', 1, 1, 0, null, 0, 0, false, 'PSLR', '', false, '', '', '', s.pslrId, null, classUid);
1773                        if (packageItemData) {
1774                            classPackageData.push(packageItemData);
1775                        }
1776                    });
1777                }
1778            }
1779        }
1780    }
1781
1782    categoryIdList = JSON.stringify(categoryIdList);
1783
1784    var class_attendees = "";
1785    if (requireClassAttendees) {
1786
1787        class_attendees = getClassAttendees(productId);
1788        if (class_attendees.no_value != undefined) {
1789
1790            alert("Attendee Name Required");
1791            $("#" + class_attendees.input_id).focus();
1792            return;
1793        }
1794    }
1795
1796    // Set defaults
1797    if (!pslrId) {
1798        pslrId = '';
1799    }
1800
1801    if (!requiresDownloadEmailAddress || requiresDownloadEmailAddress == 'undefined') {
1802        requiresDownloadEmailAddress = "no";
1803    }
1804
1805    if (!minQuantity || minQuantity == 'undefined') {
1806        if (productCountType == 'fraction') {
1807            minQuantity = 0.25;
1808        } else {
1809            minQuantity = 1;
1810        }
1811    }
1812
1813    if (!maxQuantity || maxQuantity == 'undefined') {
1814        maxQuantity = 100;
1815    }
1816
1817    if (!isTimed || isTimed == 'undefined') {
1818        isTimed = 0;
1819    }
1820
1821    if ((!in_shipping || in_shipping == 'undefined') && in_shipping !== 0) {
1822        in_shipping = '';
1823    }
1824
1825    if ((!in_taxes || in_taxes == 'undefined') && in_taxes !== 0) {
1826        in_taxes = '';
1827    }
1828
1829    // Get current cart
1830    var cart = '';
1831    if (Get_Cart_Cookie('cart')) {
1832        cart = Get_Cart_Cookie('cart');
1833    }
1834
1835    var productCount = null;
1836    if (quantity > 0) {
1837        productCount = quantity;
1838    } else if (productCountType !== null) {
1839        if (in_productType == 'RENTAL' || in_productType == 'RTO') {
1840            productCount = 1;
1841        } else if (inlineAddToCartBtn) {
1842            productCount = parseInt(document.getElementById('inlineInteger' + productId).value) + parseFloat(document.getElementById('inlineFraction' + productId).value);
1843        } else {
1844            var element = document.getElementById('integer' + productId);
1845            var element2 = document.getElementById('fraction' + productId);
1846            productCount = 0;
1847            if (element) {
1848                productCount += parseInt(element.value);
1849            }
1850            if (element2) {
1851                productCount += parseFloat(element2.value);
1852            }
1853        }
1854    } else {
1855        productCount = 1;
1856    }
1857
1858    // Get custom fields & notes
1859    var notes = '';
1860    if (in_notes != 'undefined' && in_notes != '') {
1861        notes = in_notes;
1862    } else {
1863        var noteObjects = $(".class" + productId);
1864        noteObjects.each(function(i) {
1865            if (notes == 'return') {
1866                return;
1867            }
1868            var noteName = $(this).attr('name');
1869            var noteValue = '';
1870
1871            if ($(this).is(':checkbox')) {
1872                noteValue = ($(this).is(":checked") ? 'checked' : 'not checked');
1873            }
1874            else {
1875                noteValue = $.trim($(this).val());
1876            }
1877            if ($(this).attr('requiredField') == 'true' && noteValue == '') {
1878                noteName = noteName.replace(/_/g, ' ');
1879                alert(noteName + ' is a required field.');
1880                notes = 'return';
1881                return;
1882            }
1883
1884
1885            if (notes == '') {
1886                notes = {};
1887            }
1888            notes[noteName] = noteValue;
1889        });
1890
1891        if (notes == 'return') {
1892            return;
1893        }
1894        if (notes != '') {
1895            notes = JSON.stringify(notes);
1896        }
1897    }
1898
1899    // Product ID is modified here, so make sure it goes after anything that relies on the Product ID.
1900    // Handle PSLR information
1901    if (in_productType == 'PSLR') {
1902        // Find selected PSLR
1903        var key = '';
1904        var titleAddOn = '';
1905        for (var i = 0; i < window['numAttributes' + productId]; i++) {
1906            key += (key.length > 0 ? '-' : '') + $('#attribute_' + productId + '_' + i).val();
1907            titleAddOn += (titleAddOn.length > 0 ? ' - ' : '') + window['attributeValues' + productId][i][$('#attribute_' + productId + '_' + i).val()];
1908        }
1909        if (key == '') {
1910            key = '0';
1911        }
1912
1913        // Fix data
1914        productTitle += (titleAddOn.length > 0 ? ': ' : '') + titleAddOn;
1915        if (window['prices' + productId]) {
1916            productWeight = window['prices' + productId][key]['weight'];
1917            productPrice = window['prices' + productId][key]['finalPrice'];
1918            displayPrice = window['prices' + productId][key]['finalDisplayPrice'];
1919            productSku = window['prices' + productId][key]['sku'];
1920            maxQuantity = window['prices' + productId][key]['quantity'];
1921            pslrId = window['prices' + productId][key]['pslrId'];
1922        }
1923
1924        // Get the option image if no image specified
1925        if (!productImagePath && $('#productImage' + productId).length) {
1926            var optionImage = $('#productImage' + productId).attr('src');
1927            if (optionImage && optionImage.length > 0) {
1928                productImagePath = optionImage;
1929            }
1930        }
1931    }
1932    // Gift Cards
1933    else if (in_productType == 'GC') {
1934        productPrice = $("#GCValue").val();
1935        displayPrice = productPrice;
1936        productId += Math.floor(Math.random() * 1000);
1937    } else if (in_productType == 'RENTAL') {
1938        productId = 'RENTAL' + productId;
1939    } else if (in_productType == 'RTO') {
1940        productId = 'RTO' + productId;
1941    } else if (in_productType == 'SUBSCRIPTION') {
1942        productId = 'SUBSCRIPTION' + productId;
1943    }
1944
1945    if (!displayPrice) {
1946        displayPrice = productPrice;
1947    }
1948
1949    // create path for timed inventory ajax calls
1950    if (isTimed == 1) {
1951        var cartUrl = '/module/product.htm?timed=1';
1952        if (isAdminUrl(location.host)) {
1953            cartUrl = location.pathname.substring(0, location.pathname.indexOf('/', 2)) + cartUrl;
1954        }
1955    }
1956    if (!holdingId) {
1957        holdingId = ''; // timed inventory variable
1958    }
1959
1960    var cookieData = dataToCookieString(productId,productTitle,productPrice,productC
1960ount,productWeight,productCountType,productSku,requiresDownloadEmailAddress,minQuantity,maxQuantity,notes
1961        ,isTimed,holdingId,in_shipping,in_taxes,in_productType,pslrId,in_hasAttendees,isDiscountEligible,productImagePath,productImageStyle,class_attendees
1962        ,deptId,categoryIdList,displayPrice,unitType,soldInIncrements,wishlistItemId, rto_items);
1963
1964    // For packageData, we add it as part of the class
1965    if (productId.indexOf('PITEM') > -1) {
1966        return encodeURIComponent(cookieData);
1967    }
1968
1969    if (cookieData === '') {
1970        return ;
1971    }
1972    addItemToCartData(cookieData, classPackageData);
1973
1974    var contentId = productSku ? productSku : productId;
1975    if (window.facebookPixelId) {
1976        fbq('track', 'AddToCart', {
1977            currency: window.currency,
1978            value: productPrice,
1979            content_name: productTitle,
1980            content_ids: [contentId],
1981            content_type: 'product',
1982            contents: [{
1983                'id': contentId,
1984                'quantity': productCount
1985            }]
1986        });
1987    }
1988
1989    addGAEvent(contentId, productTitle, productPrice, productCount);
1990}
1991
1992function verifyClassAttendees(productId) {
1993    var classAttendees = getClassAttendees(productId);
1994    if (classAttendees.no_value !== undefined) {
1995        // TODO: No alerts
1996        alert("Attendee Name Required");
1997        $("#" + classAttendees.input_id).focus();
1998        return false;
1999    }
2000    return true;
2001}
2002
2003function getClassAttendees(class_id_str) {
2004
2005    var return_value = "";
2006    var classToken = "CLASS";
2007    var pos = class_id_str.indexOf(classToken);
2008    if (pos > -1) {
2009
2010        var event_id = class_id_str.substr(pos + classToken.length);
2011        return_value = getAttendeesJson(event_id);
2012    }
2013    return return_value;
2014}
2015
2016function getAttendeesJson(in_event_id) {
2017
2018    var jsn = "";
2019    var attendees = $(".attendee");
2020    if (attendees) {
2021
2022        var names = [];
2023
2024        for (var i = 0; i < attendees.length; i++) {
2025
2026            var ele = attendees[i];
2027            var event_id = ele.attributes["eventid"].value;
2028
2029            if (in_event_id == event_id && ele.value.length > 0) {
2030
2031                names.push(ele.value);
2032            }
2033        }
2034        if (names.length === 0) {
2035
2036            jsn = {no_value: 1, input_id: "event_" + in_event_id + "_attendee_1", numberOfAttendees: parseInt($('#qty').val())};
2037        } else {
2038
2039            jsn = JSON.stringify(names);
2040        }
2041    }
2042    return jsn;
2043}
2044
2045function CalculateDiscount(subtotal, i) {
2046    var discount = 0;
2047    if (window.cartArray[i][0] == 'coupon' || window.cartArray[i][0] == 'couponV2') {
2048        var couponInfo = GetCouponInfo(window.cartArray[i]);
2049        if (couponInfo.couponType == 'dollar_off') {
2050            // Calculate discount
2051            if (subtotal > couponInfo.minDollarAmount) {
2052                discount = couponInfo.dollarOffAmount;
2053            }
2054            discount = Math.round(discount * 100) / 100;
2055        }
2056        else if (couponInfo.couponType == 'percent_off') {
2057            if (subtotal > couponInfo.minDollarAmount) {
2058                discount = Number(subtotal) * (Number(couponInfo.percentOff) / 100);
2059                discount = Math.round(discount * 100) / 100;
2060            }
2061
2062        }
2063        if(couponInfo.maxDiscount && couponInfo.maxDiscount < discount) {
2064            discount = couponInfo.maxDiscount;
2065        }
2066    }
2067
2068    if (discount + 0.01 > subtotal) {
2069        discount = subtotal - 0.01;
2070    }
2071
2072    return discount;
2073}
2074
2075function GetCouponInfo(row) {
2076    if (!row) {
2077        return null;
2078    }
2079
2080    var couponInfo = {};
2081    couponInfo['version'] = row[0];
2082    couponInfo['couponType'] = row[1];
2083    couponInfo['title'] = row[2];
2084    if (couponInfo.version == 'couponV2') {
2085        couponInfo['number'] = row[3];
2086        couponInfo['couponId'] = row[4];
2087        if (couponInfo.couponType == 'dollar_off') {
2088            couponInfo['minDollarAmount'] = row[5];
2089            couponInfo['dollarOffAmount'] = row[6];
2090        } else if (couponInfo.couponType == 'percent_off') {
2091            couponInfo['percentOff'] = row[5];
2092        }
2093    } else {
2094        if (couponInfo.couponType == 'dollar_off') {
2095            couponInfo['minDollarAmount'] = row[3];
2096            couponInfo['dollarOffAmount'] = row[4];
2097            couponInfo['maxDiscount'] = row[5];
2098        }
2099
2100        if (couponInfo.couponType == 'percent_off') {
2101            couponInfo['percentOff'] = row[3];
2102            couponInfo['minDollarAmount'] = row[4];
2103            couponInfo['maxDiscount'] = row[5];
2104        }
2105
2106        if (row.length >= 7) {
2107            couponInfo['number'] = row[6]; // coupon_id
2108        }
2109        if (row.length >= 8) {
2110            couponInfo['start_date'] = row[7];
2111        }
2112        if (row.length >= 9) {
2113            couponInfo['end_date'] = row[8];
2114        }
2115    }
2116    return couponInfo;
2117}
2118
2119function isAdminUrl(url) {
2120    if (typeof adminUrls != 'undefined') {
2121        var length = adminUrls.length;
2122        for (var i = 0; i < length; i++) {
2123            if (adminUrls[i] == url || 'www.' + adminUrls[i] == url || 'my-' + adminUrls[i] == url || 'www.my-' 
2123+ adminUrls[i] == url) {
2124                return true;
2125            }
2126        }
2127    }
2128    return false;
2129}
2130
2131function onChangeConditionalSelect(productId) {
2132    changeConditional(productId);
2133    window.vueEventHub.$eventHub.$emit('product-style-variant-changed');
2134}
2135
2136function changeConditional(productId) {
2137    var condition = getConditional(productId);
2138
2139    if (!condition) {
2140        return;
2141    }
2142
2143    if (window.knobby && window.knobby['module_improved_waitlist']) {
2144        var conditionSelect = $('#conditional-select');
2145        conditionSelect.attr('selected-id', condition.id);
2146        conditionSelect.attr('selected-name', condition.name);
2147    }
2148
2149    var price = condition.hasOwnProperty('display_price') ? condition.display_price.price : 0;
2150
2151    var priceHtml = formatCurrency(price);
2152
2153    var sale = condition.hasOwnProperty('display_price') ? condition.display_price.sale_price : 0;
2154
2155    if (+sale > 0) {
2156        priceHtml = '<strike>' + formatCurrency(price) + '</strike>&nbsp;<b><span style="color: #ff0000">' + formatCurrency(sale) + '</span></b>'
2157    }
2158
2159    document.getElementById('spanPrice' + productId).innerHTML = priceHtml;
2160    changQuantity(productId, condition.id);
2161}
2162
2163function changQuantity(productId, conditionId) {
2164    var isUnlimited = +$('#maxInteger' + productId).val() === 1000;
2165
2166    var quantity = isUnlimited === true ? 1000 : getConditionQuantity(productId, conditionId);
2167
2168    var quantitySelect = $('#integer' + productId);
2169    quantitySelect.find('option').remove()
2170
2171    var reserve = $('#reserve' + productId);
2172    var addBtn = $('#add-to-cart-btn-' + productId);
2173    var addToWaitlistBtn = $('#waitlist-wrapper');
2174
2175    if (quantity === 0) {
2176        reserve.css('display', 'block');
2177        quantitySelect.css('display', 'none')
2178        addBtn.css('display', 'none');
2179        addToWaitlistBtn.css('display', 'inline-block');
2180
2181        return;
2182    }
2183    reserve.css('display', 'none');
2184    quantitySelect.css('display', 'block');
2185    addToWaitlistBtn.css('display', 'none');
2186    addBtn.css('display', 'inline-block');
2187
2188    for(var i = 0; i < quantity; i++) {
2189        quantitySelect.append($('<option>', {
2190            value: i + 1,
2191            text : i + 1,
2192        }));
2193    }
2194}
2195function findCartItemsByProductId(productId) {
2196    return window.cartArray.filter(function (item) {
2197        if (item[0] !== 'product'){
2198            return false;
2199        }
2200
2201        return parseInt(item[1].replace('PSLR', '')) === parseInt(productId);
2202    });
2203}
2204function isValidConditionQuantityInCart(item, currentProductId) {
2205    if (!window.cartArray.length) {
2206        return true;
2207    }
2208
2209    var cart = findCartItemsByProductId(currentProductId);
2210
2211    if (!cart.length) {
2212        return true;
2213    }
2214
2215    var isValidConditionQuantity = function (condition, inCartQuantity) {
2216        var quantity = getConditionQuantity(currentProductId, condition);
2217
2218        return quantity >= inCartQuantity;
2219    };
2220
2221    var CONDITION_INDEX = 30;
2222    var QUANTITY_INDEX = 4;
2223
2224    for (var i = 0; i < cart.length; i++) {
2225        var cartItem = cart[i];
2226
2227        var condition = +cartItem[CONDITION_INDEX];
2228        var quantity = +cartItem[QUANTITY_INDEX];
2229
2230        if (item.conditions) {
2231            for (var j = 0; j < item.conditions; j++) {
2232                if (!isValidConditionQuantity(item.conditions[j].condition, quantity) && +item.conditions[j].condition === condition) {
2233                    return false;
2234                }
2235            }
2236
2237            return true;
2238        }
2239
2240        if (condition !== +item.condition) {
2241            continue;
2242        }
2243
2244        if (!isValidConditionQuantity(condition, quantity)) {
2245            return false;
2246        }
2247    }
2248
2249    return true;
2250}
2251
2252function getInCartQuantity(productId, conditionId, defaultQuantity = 1) {
2253    var cart = findCartItemsByProductId(productId);
2254
2255    if (!cart) {
2256        return defaultQuantity;
2257    }
2258
2259    var CONDITION_INDEX = 30;
2260    var QUANTITY_INDEX = 4;
2261
2262    for (var i = 0; i < cart.length; i++) {
2263        var cartItem = cart[i];
2264        if (+cartItem[CONDITION_INDEX] === +conditionId) {
2265            return +cartItem[QUANTITY_INDEX];
2266        }
2267    }
2268
2269    return defaultQuantity;
2270}
2271
2272function decreaseActualConditionQuantity(productId, conditionId, key = null) {
2273    key = key === null ? ProductAttributeKeyGet(productId, 0) : key;
2274
2275    var conditionQuantity = window['prices' + productId][key]['conditional_quantity'].find(function (v) {
2276        return parseInt(v.condition_id) === parseInt(conditionId);
2277    });
2278
2279    conditionQuantity.quantity = conditionQuantity.quantity - getInCartQuantity(productId, conditionId);
2280}
2281
2282function addGAEvent(productId, productTitle, productPrice, productC
2282ount) {
2283    if (window.knobby && window.knobby['module_flag_google_analytics_v4']) {
2284        if (window.googleAnalyticsId) {
2285            gtag('event', 'add_to_cart', {
2286                currency: window.currency || 'USD',
2287                value: parseFloat(productPrice),
2288                items: [{
2289                    item_id: productId,
2290                    item_name: productTitle,
2291                    quantity: productCount,
2292                    price: productPrice,
2293                }]
2294            });
2295        }
2296    } else {
2297        if (window.googleAnalyticsId) {
2298            gtag('event', 'add_to_cart', {
2299                "items": [{
2300                    id: productId,
2301                    name: productTitle,
2302                    quantity: productCount,
2303                    price: productPrice,
2304                    currency: window.currency,
2305                }]
2306            });
2307        }
2308    }
2309}

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.