PageSourceSearch

https://bookings.willenlake.org.uk/shop/includes/js_include.js?v=1789729035

js willenlake.org.uk collected 2026-09-30 10:59:36 UTC 133,399 bytes, 3,071 lines download raw bytes

1if(typeof currency === 'undefined') currency = "£";
2if(typeof currencySym === 'undefined') currencySym = currency;
3if(typeof WS_USER === 'undefined') WS_USER = $('#WS_USER').val() != '' ? $('#WS_USER').val() : '';
4if(typeof showActivityPricingBreakdown === 'undefined') showActivityPricingBreakdown = false;
5if(typeof usePricingTypeColors === 'undefined') usePricingTypeColors = true;
6if(typeof showSpacesFree === 'undefined') showSpacesFree = false;
7if(typeof showPricingTypes === 'undefined') showPricingTypes = false;
8if(typeof displayVerifyMembershipDetails === 'undefined') displayVerifyMembershipDetails = false;
9if(typeof lblProductUpsellsUpgrade === 'undefined') lblProductUpsellsUpgrade = "Upgrade!";
10if(typeof lblFree === 'undefined') lblFree = "Free";
11if(typeof userId === 'undefined') userId = "";
12if(typeof FB_event_id === 'undefined') FB_event_id = "";
13if(typeof isVouchersOnlyCategory === 'undefined') isVouchersOnlyCategory = false;
14
15var ga4AddToCartProducts = [];
16window.dataLayer = window.dataLayer || [];
17var noAvailabilityWording;
18if(typeof noAvailabilityWording === "undefined" || noAvailabilityWording == "") noAvailabilityWording = "Unavailable";
19
20var tmpCatetoryId = 0;
21var tmpProductId = 0;
22var arrSelectedProducts = {};
23
24$.fn.isInViewport = function() {
25	var elementTop = $(this).offset().top;
26	var elementBottom = elementTop + $(this).outerHeight();
27	
28	var viewportTop = $(window).scrollTop();
29	var viewportBottom = viewportTop + $(window).height();
30	
31	return elementBottom > viewportTop && elementTop < viewportBottom;
32};
33
34function getTextColor(hex) {
35    if(hex != undefined) {
36        const red = parseInt(hex.substring(0, 2), 16);
37        const green = parseInt(hex.substring(2, 4), 16);
38        const blue = parseInt(hex.substring(4, 6), 16);
39        const brightness = red*0.299 + green*0.587 + blue*0.114;
40        
41        if(brightness > 150) {
42            return "#000000";
43        } else {
44            return "#FFFFFF";
45        }	
46    }
47}
48
49var webcamReady = false;
50
51function takeUserPhoto(userKey) {
52    $("#photoUserKey").val(userKey);
53    
54    $("#divCustomerPhotoContainer").show();
55    $("#divMyCamera").hide();
56    $("#divPhotoOptions").show();
57    $("#divPhotoButtons").hide();
58    $("#divUploadPhoto").hide();
59    $("#divUploadPhotoError").hide();
60    
61    if(ismobile) uploadPhoto();
62    
63    $("#modalCustomerPhoto").modal("show");
64}
65
66$(document).on('click', '[data-action="takeUserPhoto"]', function (e) {
67    e.preventDefault();
68    takeUserPhoto($(this).data('userkey'));
69});
70
71function openCamera() {
72    $("#divCustomerPhotoContainer").hide();
73    $("#divPhotoOptions").hide();
74    $("#divPhotoButtons").show();
75    
76	resetPhoto();
77}
78
79$(document).on('click', '[data-action="openCamera"]', function (e) {
80    e.preventDefault();
81    openCamera();
82});
83
84function resetPhoto() {
85    if(!webcamReady) {
86        if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
87            Webcam.set({
88                width: 240,
89                height: 320,
90                dest_width: 480,
91                dest_height: 640,
92                image_format: "jpeg",
93                jpeg_quality: 90,
94                
95            });
96        } else {
97            Webcam.set({
98                width: 320,
99                height: 240,
100                dest_width: 320,
101                dest_height: 240,
102                image_format: "jpeg",
103                jpeg_quality: 90
104            });
105        }
106        Webcam.attach("#divMyCamera");
107        webcamReady = true;
108    }
109    Webcam.unfreeze();
110    
111    $("#btnTakePhoto").show();
112    $("#btnRetakePhoto").hide();
113    $("#btnSavePhoto").hide();
114    $("#divMyCamera").show();
115}
116$(document).on('click', '[data-action="resetPhoto"]', function (e) {
117    e.preventDefault();
118    resetPhoto();
119});
120
121function takePhoto() {
122    Webcam.freeze();
123    $("#btnTakePhoto").hide();
124    $("#btnRetakePhoto").show();
125    $("#btnSavePhoto").show();
126}
127$(document).on('click', '[data-action="takePhoto"]', function (e) {
128    e.preventDefault(); // replaces the old "return false;" — stops the # navigation
129    takePhoto();
130});
131
132function savePhoto() {
133    var userKey = $("#photoUserKey").val();
134    
135    Webcam.snap(function(data_uri) {
136        Webcam.upload(data_uri, "/shop/ajax.php?saveUserPhoto=1&userKey="+userKey, function(code, text) {
137            if(code == 200) {
138                $("#userImageSaved_"+userKey).val("1");
139                $("#userImage_"+userKey).html("<img class=\"img-thumbnail\" src=\""+data_uri+"\" class=\"img-thumbnail\" data-imagesrc=\""+data_uri+"\" style=\"width:150px;\">");
140                $("#modalCustomerPhoto").modal("hide");
141            }
142        });
143    });
144}
145$(document).on('click', '[data-action="savePhoto"]', function (e) {
146    e.preventDefault(); // replaces the old "return false;" — stops the # navigation
147    savePhoto();
148});
149
150function uploadPhoto() {
151    $("#divPhotoOptions").hide();
152    $("#divPhotoButtons").hide();
153    $("#divUploadPhoto").show();
154}
155$(document).on('click', '[data-action="uploadPhoto"]', function (e) {
156    e.preventDefault(); // replaces the old "return false;" — stops the # navigation
157    uploadPhoto();
158});
159
160$(document).on("change", "#uploadCustomerPhoto", function() {
161    if($(this).prop("files") && $(this).prop("files")[0]) {
162        var tmpImage = URL.createObjectURL($(this).prop("files")[0]);
163        $(".modal-user-profile-picture").attr("src", tmpImage); // set src to blob url
164    }
165});
166
167function savePhotoUploaded() {
168	var userKey = $("#photoUserKey").val();
169    
170    var fileData = $("#uploadCustomerPhoto").prop("files")[0];
171    var formData = new FormData();
172    formData.append("file", fileData);
173    
174    $.ajax({
175        method: "POST",
176        url: "/shop/ajax.php?saveUserPhoto=1&userKey="+userKey+"&fileUpload=1",
177        data: formData,
178        cache: false,
179        contentType: false,
180        processData: false,
181        dataType: "json",
182    }).done(function(data) {
183        if(data.result) {
184            const tmpImage = URL.createObjectURL(fileData);
185            
186            $("#userImageSaved_"+userKey).val("1");
187		    $("#userImage_"+userKey).html("<img class=\"img-thumbnail\" src=\""+tmpImage+"\" class=\"img-thumbnail\" data-imagesrc=\""+tmpImage+"\" style=\"width:150px;\">");
188		    $("#modalCustomerPhoto").modal("hide");
189        } else {
190            $("#divUploadPhotoError").html("Whoops! There was an error uploading your photo. Please try again.").show();
191        }
192    });
193}
194
195
196$(document).on('click', '[data-action="savePhotoUploaded"]', function (e) {
197    e.preventDefault(); // replaces the old "return false;" — stops the # navigation
198    savePhotoUploaded();
199});
200
201$(document).on("click", ".img-thumbnail", function(e) {
202    var imageSRC = $(this).data("imagesrc");
203    
204    $("#divModalImage").html("<img src=\""+imageSRC+"\" class=\"img-responsive\">");
205    $("#modalImage").modal("show");
206});
207
208function updateShipping() {
209    var shippingOptionId = $('input[name="shippingOption"]:checked').val();
210    
211    $.post("/shop/ajax.php", { "updateShippingOption":1, "shippingOptionId":shippingOptionId }, function(data) {
212    	if(data) {
213            window.location.reload(true);
214	    }
215    }, "json");
216}
217
218function getProductsByCategory(catId){
219	if(!loadingProducts) {
220		loadingProducts = true;
221		
222		$.ajax({
223			url: '/shop/ajax.php',
224			type: 'POST',
225			data: { "getProductsByCategory":1, "pageNo":pageNo, "catId":catId, "ajax":1 },
226			
227			dataType: 'json',
228			success: function(data) {
229				loadingProducts = false;
230				pageNo = data.pageNo;
231				pages 	= data.pages;
232				html = "";
233				$.each( data.results, function( key, product ) {
234					productname = product.name;
235					productname = productname.replace(/[^a-zA-Z ]/g, "").toLowerCase();
236					
237
238					html += '<li data-productname="'+productname+'" class="list-group-item productItem">';
239					html += '<div class="row justify-content-center align-items-center" id="product_'+key+'">';
240					html += '	<div class="col-4 col-sm-3 col-md-2 col-lg-1">';
241					html += '		<img src="'+product.thumbimg+'" alt=""/>';
242					html += '	</div>';
243					html += '	<div class="col-8 col-sm-6 col-md-7 col-lg-9">';
244					html += '		<div class="d-flex align-items-center flex-wrap flex-md-nowrap">';
245					html += '			<div class="flex-grow-1">';
246					html += '				<div class="d-flex align-items-center">';
247					html += '					<h3 class="mb-0">'+product.name+'</h3>';
248					html += '				</div>';
249					html += '				'+showprice(product.price);
250					html += '			</div>';
251					html += '			<div class="flex-grow-0">';
252					html += '				<div class="input-group mt-3 mt-md-0">';
253					html += '					<div class="input-group-prepend">';
254					html += '						<button onClick="decreaseQuantity('+key+'); return false;" class="qty-btn" value="-">-</button>';
255					html += '					</div>';
256					
257					html += '					<input type="number" class="form-control qty qty-input" name="qty" id="qty_'+key+'" value="1" max="{$product.extra.maxqty}" min="1" rel="10"/>';
258					html += '					<div class="input-group-append">';
259					html += '						<button onClick="increaseQuantity('+key+'}); return false;" class="qty-btn" value="+">+</button>';
260					html += '					</div>';
261					html += '				</div>';
262					html += '			</div>';
263					html += '		</div>';
264					html += '	</div>';
265					html += '	<div class="col-12 col-sm-3 col-md-3 col-lg-2">';
266					html += '		<div id="addButton_'+key+'" class="btn btn-primary w-100 mt-3 mt-sm-0" onClick="addProductToBasket(\''+key+'\', \''+productname+'\');return false;">Add</div>';
267					html += '	</div>';
268					html += '</div>';
269					html += '</li>';
270				});
271				
272				$("#productWrapper").append(html);
273				
274				if (pageNo == pages){
275					loadedAllProducts =true;
276					$("#productLoader").addClass("d-none");
277				}else{
278				}
279			},
280			fail: function(data){
281			},
282			complete: function(data){
283			}
284		},'json');
285	}
286	else{
287	}
288}
289
290$('#foodSearch').on("input keyup change", function () {
291	searchProducts();
292});
293
294function searchProducts() {
295	// Haven't loaded all products yet, let's load them first otherwise we won't show a full list of results
296	if (!loadedAllProducts){
297		getProductsByCategory();
298		setTimeout(function(){
299			searchProducts();
300		}, 3000);
301	}else{
302		var search = $("#foodSearch").val().toLowerCase();
303		var emptySearch = (search.length == 0);
304		//$(".productItem").removeClass("text-success").removeClass("text-danger");
305		
306		if (emptySearch) {
307			$(".productItem").removeClass("d-none");
308			//$(".productItem").removeClass("text-success").removeClass("text-danger");
309			return;
310		}
311			
312		$(".productItem").each(function() {
313			if ($(this).data("productname").toLowerCase().indexOf(search) !== -1) {
314				//$(this).addClass("text-success");
315				$(this).removeClass("d-none");
316			} else {
317				//$(this).addClass("text-danger");
318				$(this).addClass("d-none");
319			}
320		});
321	}
322}
323
324function increaseQuantity(productid, showMsgOnMax = ''){
325	currentQty = $('#qty_'+productid).val();
326
327	var qty = parseInt(parseInt($('#qty_'+productid).val()) + 1);
328	
329	var maxqty = $('#qty_'+productid).attr('rel');
330	if (qty <= maxqty){
331		$('#qty_'+productid).val(qty);
332	}
333    //SD option to show popup if max qty reached
334    if(qty > maxqty && showMsgOnMax != '') {
335        genAlertMsg('Notice', showMsgOnMax);
336    }
337}
338
339function decreaseQuantity(productid){
340	currentQty = $('#qty_'+productid).val();
341	if (currentQty == $('#qty_'+productid).data("minqty")) {
342		var qty = 0;
343	}else{
344		var qty = parseInt(parseInt($('#qty_'+productid).val()) - 1);
345	}
346	var minqty = $('#qty_'+productid).attr('min');
347	if (qty >= minqty){
348		$('#qty_'+productid).val(qty);
349	}
350}
351
352function addProductToBasket(productid, prodname, qty = "") {
353	//alert("this one...");
354	$("#addButton_" + productid).html("<div class=\"spinner-grow text-light\" role=\"status\"><span class=\"sr-only\">Loading...</span></div>");
355	name = prodname;
356	qty = parseInt($("#qty_" + productid).val());
357    
358    //OD added isNaN 2021-08-03. Issue on bluebell dairy with qty not being added
359    if (qty < 1 || isNaN(qty)){ qty = 1;}
360	$.post("/shop/ajax.php", { "addProductToBasketNew": 1, "productid": productid, "qty": qty, "ajax": 1 }, function (data) {
361		$("#addButton_" + productid).html("Add");
362		var x = parseFloat(data.basketgrosstotal);
363		$('#basket-confirm-msg').html("You've added <b>" +qty+" "+ prodname + "</b> to your basket <br /> <p>your total is "+showprice(x));
364		$('#basket-add-confirmation').addClass('slideUp');
365		$(".addButton_" + productid).html("Add to basket");
366		setTimeout(
367			function(){
368				$('#basket-add-confirmation').removeClass('slideUp');					
369			}, 3000);
370		//adds up total qty of items not just products.
371		var y = 0;
372		for(var i = 0; i < data.result.products.length; i++)
373		{
374			y += parseFloat(data.result.products[i].qty);
375		}
376		$('.badge').html(data.count);
377
378		if (data.basketgrosstotal != "0") {
379
380		} else {
381
382		}
383	}, 'json');
384}
385
386/*
387--------------------------------------------------
388START - CATEGORY & GROUP PRODUCTS
389--------------------------------------------------
390*/
391$(document).ready(function() {
392	$("#modalBuyMembershipVoucher").on('hidden.bs.modal', function(event) {
393		$("#divBuyMembershipVoucher").find('input[type="text"]').val("0");
394	})
395    
396    // Book Now
397    $(".divCategoryProducts, #productTotalWrap").on("click", ".btnMemberBookNow", function() {
398        var productId = parseInt($(this).data("productid"));
399        var categoryId = $("#categoryId").val();
400        var locationId = $("#locationId_"+productId).val();
401        
402        // Description added via extra info fields and injected into data-description against button in category.tpl
403        const description = $(this).data("description");
404        
405        $("#locationId").val(locationId);
406        $("#btnBookNow").hide();
407        
408        if(productId > 0 && locationId > 0) {
409            $.ajax({
410                url: "/shop/ajax.php",
411                type: "POST",
412                async: false,
413                data: { "getMemberCategoryProducts":1, "categoryId":categoryId, "locationId":locationId, "productId":productId },
414                dataType: "json",
415                success: function(data) {
416                    var excludeFromAdditionalTicketsSection = 0;
417                    if(typeof data.product.extra.excludeFromAdditionalTicketsSection != "undefined") {
418                        excludeFromAdditionalTicketsSection = data.product.extra.excludeFromAdditionalTicketsSection;
419                    }
420                    
421                    // Member Products
422                    var html = '<div class="list-group">';
423                    var count = 1;
424                    $.each(data.memberProducts, function(key, memberProduct) {
425                        if(memberProduct.bookingLimitReached == 1) {
426                            html+= '<input type="checkbox">';
427                            html+= '<label class="list-group-item disabled" aria-disabled="true">'+memberProduct.name+' ('+memberProduct.membershipName+') - Booking Limit Reached</label>';
428                        } else if(memberProduct.inBasket == 1) {
429                            html+= '<input type="checkbox">';
430                            html+= '<label class="list-group-item disabled" aria-disabled="true">'+memberProduct.name+' ('+memberProduct.membershipName+') - In Basket</label>';
431                        } else if(memberProduct.productId > 0) {
432                            html+= '<input type="hidden" name="products['+count+'][id]" id="productId_'+count+'" value="'+memberProduct.productId+'">';
433                            html+= '<input type="hidden" name="products['+count+'][price]" id="memberPrice_'+count+'" value="'+memberProduct.minPrice+'">';
434                            html+= '<input type="hidden" name="products['+count+'][userId]" id="userId_'+count+'" value="'+memberProduct.userId+'">';
435                            html+= '<input type="hidden" name="products['+count+'][membershipId]" id="membershipId_'+count+'" value="'+memberProduct.membershipId+'">';
436                            html+= '<input type="hidden" name="products['+count+'][membershipProductId]" id="membershipProductId_'+count+'" value="'+memberProduct.membershipProductId+'">';
437                            html+= '<input type="checkbox" class="chkProduct_'+memberProduct.productId+'" name="products['+count+'][qty]" id="productQty_'+count+'" data-count="'+count+'" value="1">';
438                            html+= '<label class="list-group-item list-group-item-action font-weight-bold d-flex align-items-center" for="productQty_'+count+'">';
439                                html+= '<span class="me-3 mr-3">'+memberProduct.name+' ('+memberProduct.membershipName+')';
440                                if(!memberProduct.creditBasedPayment) html+= '&nbsp;-&nbsp;From '+showprice(memberProduct.minPrice)+'';
441                                html+= '</span>';
442                                html+= '<span class="btn btn-primary ml-auto ms-auto btn-add-member"></span>';
443                            html+= '</label>';
444                            count++;
445                        } else {
446                            //html += '<input type="checkbox">';
447                            //html += '<label class="list-group-item disabled" aria-disabled="true">'+memberProduct.name+' ('+memberProduct.membershipName+') - No Products Available</label>';
448                        }
449                    });
450                    html += '</div>';
451                    $("#divMemberProducts").html(html);
452                    
453                    // Additional Tickets
454                    if(excludeFromAdditionalTicketsSection != 1) {
455                        var html = "<h3>Additional Tickets</h3>";
456                        html+= "<p>Please only add tickets if you are attending with guests</p>";
457                        html+= '<div class="list-group">\
458                            <input type="hidden" name="products['+count+'][id]" id="productId_'+count+'" value="'+data.product.id+'">\
459                            <input type="hidden" name="products['+count+'][price]" id="price_'+data.product.id+'" value="'+data.product.extra.minprice+'">\
460                            <input type="hidden" id="standardPrice_'+data.product.id+'" value="'+data.product.extra.minprice+'">\
461                            <div class="list-group-item list-group-item-action">\
462                                <div class="d-block d-sm-flex w-100 justify-content-between">\
463                                    <div>\
464                                        <h5 class="mb-0">
464'+data.product.name+'</h5>';
465                                        if(data.product.extra.minprice){ 
466                                            html += '<small>From <span id="spanPrice_'+data.product.id+'">' + showprice(data.product.extra.minprice)+'</span></small>';
467                                        }
468                                    html+= '</div>\
469                                    <div class="d-flex align-items-center">\
470                                        <div>\
471                                            <div class="input-group input-group-quantity justify-content-end ml-auto inputQtySelector">\
472                                                <div class="input-group-prepend">\
473                                                    <button type="button" class="btn btn-primary qtyIncrement" data-count="'+count+'" data-add="-1">-</button>\
474                                                </div>\
475                                                <input type="number" class="form-control text-center border product_'+data.product.id+'" name="products['+count+'][qty]" id="productQty_'+count+'" data-count="'+count+'" data-productid="'+data.product.id+'" data-minqty="'+data.product.extra.minqty+'" data-maxqty="'+data.product.extra.maxqty+'" placeholder="0" autocomplete="off">\
476                                                <div class="input-group-append">\
477                                                    <button type="button" class="btn btn-primary qtyIncrement" data-count="'+count+'" data-add="1">+</button>\
478                                                </div>\
479                                            </div>\
480                                        </div>\
481                                    </div>\
482                                </div>\
483                            </div>\
484                        </div>';
485                        
486                        $("#divAdditionalProducts").html(html);
487                    }
488                    
489                    $("#modalMemberBookNow #extraDescription").html(description);
490                    $("#modalMemberBookNow").modal("show");
491                }
492            });
493        }
494    });
495    
496    // Qty +/-
497    $("#divAdditionalProducts").on("click", ".qtyIncrement", function() {
498        var count = parseInt($(this).data("count"));
499        var add = parseInt($(this).data("add"));
500      
501        var qty = ($("#productQty_"+count).val()*1);
502        var minQty = parseInt($("#productQty_"+count).data("minqty")) || 1;
503        var maxQty = parseInt($("#productQty_"+count).data("maxqty")) || 999;
504        var newQty = qty + add;
505        
506        if(add == 1) {
507            if(maxQty == -1) {
508                return false;
509            } else if(newQty < minQty) {
510                newQty = minQty;
511            } else if(newQty > maxQty) {
512                newQty = maxQty;
513            }
514        } else if(add == -1) {
515            if(minQty == -1) {
516                return false;
517            } else if(qty == 0 || newQty == 0) {
518                newQty = "";
519            } else if(newQty < minQty) {
520                newQty = minQty;
521            }
522        }
523        
524        $("#productQty_"+count).val(newQty);
525        
526        checkProductsTotal();
527    });
528    
529    // Edit Qty
530    $("#divSingleProducts #divMemberProducts, #divAdditionalProducts").on("change", "[id^='productQty_']", function() {
531        if($(this).is(":checkbox")) {
532            var memberProduct = true;
533        } else {
534            var memberProduct = false;
535            var qty = ($(this).val()*1);
536            var minQty = parseInt($(this).data("minqty"));
537            var maxQty = parseInt($(this).data("maxqty"));
538            
539            if(minQty == -1 || maxQty == -1) {
540                // Don't change qty if either min or max is disabled
541            } else if(qty == 0) {
542                qty = "";
543            } else if(qty < minQty) {
544                qty = minQty;
545            } else if(qty > maxQty) {
546                qty = maxQty;
547            }
548            
549            $(this).val(qty);
550        }
551        
552        checkProductsTotal(memberProduct);
553    });
554    
555    // Qty +/-
556    $("#divGroupedProducts").on("click", ".qtyIncrement", function() {
557        var newAvailabilityCheck = parseInt($("#newAvailabilityCheck").val()) || 0;
558        if(newAvailabilityCheck == 1) {
559            var count = parseInt($(this).data("count"));
560            var add = parseInt($(this).data("add"));
561            
562            var qtyElement = $("#productQty_"+count);
563            var productId = parseInt(qtyElement.data("productid")) || 0;
564			var qty = (qtyElement.val() * 1);
565            var minQty = parseInt(qtyElement.data("minqty")) || 1;
566            var maxQty = parseInt(qtyElement.data("maxqty")) || 999;
567            var newQty = qty + add;
568            
569            if(add == 1) {
570                if(maxQty == -1) {
571                    return false;
572                } else if(newQty < minQty) {
573                    newQty = minQty;
574                } else if(newQty > maxQty) {
575                    newQty = maxQty;
576                }
577            } else if(add == -1) {
578                if(minQty == -1) {
579                    return false;
580                } else if(qty == 0 || newQty == 0) {
581                    newQty = 0;
582                } else if(newQty < minQty) {
583                    // #065261 - AT 29/10/25
584                    //newQty = minQty;
585                    newQty = 0;
586                }
587            }
588            if(newQty == 0) newQty = "";
589            
590            qtyElement.val(newQty);
591            
592            getGroupedProductsTotal(false, true);
593        } else {
594            if(WS_USER == "continuum") {
595                qtyContent = $(this).html();
596                $(this).html('<div class="spinner-border spinner-border-sm text-light" role="status"><span class="sr-only">Loading...</span></div>');
597            }
598            
599            let overrideQtyVal = '';
600            
601            var count = parseInt($(this).data("count"));
602            var add = parseInt($(this).data("add"));
603            
604            var productId = $("#productId_"+count).val();
605            var qty = ($("#productQty_"+count).val()*1);
606            var minQty = parseInt($("#productQty_"+count).data("minqty")) || 1;
607            var maxQty = parseInt($("#productQty_"+count).data("maxqty")) || 999;
608            var newQty = qty + add;
609            
610            //SD show popup mesage if they reach the max option
611            if ($(this).data("showmsgonmax") && newQty > maxQty) {
612                genAlertMsg('Notice', $(this).data("showmsgonmax"))
613            }
614            //SD option to show a custom modal
615            if ($(this).data("showmodalonmax")) {
616                let countCheckedMembers = parseInt(document.getElementById('divMemberProducts').querySelectorAll('input[type="checkbox"]:checked').length);
617                newQtyPlusMembers = newQty + countCheckedMembers;
618                console.log(newQtyPlusMembers)
619                //work out new maxQty here
620                let mQ = maxQty - countCheckedMembers
621                if (newQtyPlusMembers > (mQ + 1)) {
622                    //overrideQtyVal = newQtyPlusMembers+'+'
623                    overrideQtyVal = newQty-1
624                    let modalId = $(this).data("modaltoshow")
625                    $('#'+modalId).modal('show')
626                }
627            }
628            
629            if(add == 1) {
630                if(maxQty == -1) {
631                    return false;
632                } else if(newQty < minQty) {
633                    newQty = minQty;
634                } else if(newQty > maxQty) {
635                    newQty = maxQty;
636                }
637            } else if(add == -1) {
638                if(minQty == -1) {
639                    return false;
640                } else if(qty == 0 || newQty == 0) {
641                    newQty = "";
642                } else if(newQty < minQty) {
643                    // #065261 - AT 29/10/25
644                    //newQty = minQty;
645                    newQty = 0;
646                }
647            }
648            overrideQtyVal != '' ? $("#productQty_" + count).val(overrideQtyVal) : $("#productQty_" + count).val(newQty);
649            
650            if(newQty > 0) {
651                $("#btnBuyVoucher_"+productId).prop("disabled", false);
652            } else {
653                $("#btnBuyVoucher_"+productId).prop("disabled", true);
654            }
655            //SD call this from website js file for bespoke functionality
656            if (typeof besChangeGroupedProductsQty === "function") {
657                besChangeGroupedProductsQty(this, newQty)
658            }
659            if(WS_USER == "continuum"){
660                $(this).html(qtyContent); 
661            }
662            getGroupedProductsTotal();
663        }
664	});
665    
666    // Edit Qty
667    $("#divGroupedProducts").on("change", "[id^='productQty_'], [id^
667='productId_']", function() {
668        var newAvailabilityCheck = parseInt($("#newAvailabilityCheck").val()) || 0;
669        
670        if($(this).is(":checkbox") || $(this).is("select")) {
671            var memberProduct = true;
672            
673            if($(this).is("select")) {
674                var membershipProductId = parseInt($(this).find(":selected").data("membershipproductid"));
675                if(membershipProductId > 0) {
676                    var count = parseInt($(this).data("count"));
677                    $("#membershipProductId_"+count).val(membershipProductId)
678                }
679            }
680        } else {
681            var memberProduct = false;
682            
683            var productId = parseInt($(this).data("productid"));
684            var qty = ($(this).val()*1);
685            var minQty = parseInt($(this).data("minqty")) || 1;
686            var maxQty = parseInt($(this).data("maxqty")) || 999;
687            
688            if(minQty == -1 || maxQty == -1) {
689                // Don't change qty if either min or max is disabled
690            } else if(qty > 0 && qty < minQty) {
691                qty = minQty;
692            } else if(qty > maxQty) {
693                qty = maxQty;
694            }
695            
696            if(qty > 0) {
697                $("#btnBuyVoucher_"+productId).prop("disabled", false);
698            } else {
699                $("#btnBuyVoucher_"+productId).prop("disabled", true);
700            }
701            
702            if(qty == 0) qty = "";
703            $(this).val(qty);
704        }
705        
706        getGroupedProductsTotal(memberProduct, newAvailabilityCheck);
707	});
708    
709    // Buy Voucher
710    $(".divCategoryProducts, #divGroupedProducts, #divAvailableProducts, .divProduct").on("click", ".buyVoucher", function() {
711        var productId = parseInt($(this).data("productid"));
712        var productPrice = $(this).data("productprice");
713		var minQty = parseInt($(this).data("minqty"));
714		var maxQty = parseInt($(this).data("maxqty"));
715        var fixVoucherType = parseInt($(this).data("fixvouchertype"));
716        var locationId = parseInt($("#locationId").val()) || 0;
717        var voucherOptionData = $(this).data("voucheroption");
718        var voucherOption = -1; //  0, 1 and 2 are actual values. -1 indicates the data attribute is not set
719        if (typeof voucherOptionData !== 'undefined') {
720            voucherOption = parseInt(voucherOptionData);
721            console.log("voucherOption: ", voucherOption);
722        } else {
723            console.log("voucherOption does not exist.");
724        }
725
726        // HC- inject max qty to voucher modal input field 07-06-2022
727        $("#buyVoucherQty").attr({"max": maxQty})
728        $("#buyVoucherQty").attr({"min": minQty})
729
730        if(typeof WS_USER === "undefined") WS_USER = $("#WS_USER").val() != "" ? $("#WS_USER").val() : "";
731        
732        if(locationId < 1) locationId = parseInt($("#location_"+productId).val()) || 0;
733        if(locationId == 0) locationId = parseInt($(this).data("locationid")) || 0;
734        if(locationId == 0) locationId = parseInt($("#locationId_"+productId).val()) || 0;
735        
736        if(productId > 0 && locationId > 0) {
737            $.ajax({
738                url: "/booking/ajax.php",
739                type: "GET",
740                async: false,
741                data: { "getProductVoucherType":1, "productId":productId, "locationId":locationId },
742                dataType: "json",
743                success: function(data) { 
744					console.log("getProductVoucherType");
745                    // DD - 10/9/22 - This ajax call could be returning additional arrays. If it is,
746                    // we need to handle this here to make it backwards compatible
747                    var includesExtras = false;
748                    console.log(data);
749                    if(typeof data.products != 'undefined') {
750                        var productsarr = data.products;
751                        data = data.pricingoptions;
752                        includesExtras = true;
753                    }
754                    
755                    if(data && Object.keys(data).length > 0) {
756                        $("#buyVoucherProductId").val(productId);
757                       // $("#productPrice").html('Price: 'showprice(productPrice));
758                        $("#buyVoucherLocationId").val(locationId);
759						if (minQty > 0){
760							$("#buyVoucherQty").val(minQty);
761                            $("#btnAddVoucher").show();
762						}
763						
764                        var html = '<select class="form-control" name="pricingtype" id="buyVoucherPricingTypeId">';
765                        var html2 = ""
766                        html += '<option value="" selected disabled>Please select...</option>';
767						
768						count = 0;
769                        var defaultPrice = false;
770                        var thisPrice = 0;
771                        var allPricesEqual = true;
772						
773						console.log("Fixed voucher type: "+fixVoucherType);
774						if (data.hasOwnProperty(fixVoucherType)){
775							console.log("has fixed voucher in array "+fixVoucherType);
776						}else{
777							console.log("does not have fixed voucher in array "+fixVoucherType);
778						}
779						
780						if (fixVoucherType > 0 && !data.hasOwnProperty(fixVoucherType)) {
781							fixVoucherType = 0;
782							console.log("Fixed voucher type doesn't match, unset this so other types are offered");
783						}
784						
785                        $.each(data, function(key, pricingtype) {
786							//console.log(fixVoucherType + " - "+key+ " price:"+thisPrice)
787							if (fixVoucherType > 0 && fixVoucherType == key){
788								 thisPrice = pricingtype.price;
789							}
790							if (fixVoucherType == 0){
791								thisPrice = pricingtype.price;
792							}
793                            if(thisPrice > 0 && thisPrice != pricingtype.price) {
794                            	allPricesEqual = false;
795                            	console.log('not equal');
796                            }
797                            
798                            if (fixVoucherType > 0){
799								 if(fixVoucherType == key){
800									html += "<option value=\""+key+"\" ";
801									 html += "selected";
802									 html += ">"+pricingtype.name+" (" + showprice(pricingtype.price) + ")";
803									count++;
804                                    html2 = "<div class='col pt-3'>Price: " + showprice(pricingtype.price) + "</div>";
805								 }
806							}else{
807								html += "<option value=\""+key+"\" ";
808								if (count == 0){
809									html += "selected";
810								}
811								html += ">"+pricingtype.name+" (" + showprice(pricingtype.price) + ")";
812								count++;
813							}
814                                
815                                //if(Object.keys(data).length == 1 || (fixVoucherType > 0 && fixVoucherType == key)){
816                                   
817                                //    defaultPrice = true;
818                                //}
819                                
820                            
821                        });
822                        
823                        html += '</select>';
824                        
825                        $("#divVoucherPricingTypes").html(html);
826                        if(count > 1) {
827                            $('#buyVoucherQty').val(0);
828                            $('#btnAddVoucher').hide();
829                        } else {
830                            $('#buyVoucherQty').val(1);
831                            $('#btnAddVoucher').show();
832                        }
833						
834						if(minQty == maxQty) {
835							$("#buyVoucherQtyWrap").addClass("d-none");
836						} else {
837							$("#buyVoucherQtyWrap").removeClass("d-none");
838						}
839						
840						// AW - no point showing the pricing type if there is only one.
841						if(count == 1 || defaultPrice || allPricesEqual) {
842							console.log("--"+thisPrice);
843                            if(WS_USER == 'silverstone') {
844							    $("#productPrice").html('<span class="text-xl">'+showprice(thisPrice)+' each</span>');
845                            } else {
846                                $("#productPrice").html(showprice(thisPrice)+' each');
847                            }
848							$("#voucherTypeWrap").addClass("d-none");
849                            // Price should be shown for continuum pages #044566, but this change results in 500 error. Beatrix
850                            // if(WS_USER === "continuum"){
851                            //    $("#voucherTypeWrap").html(html2); 
852                            // }
853							if (count > 1){
854								$("#voucherTypeWrap").removeClass("d-none");
855							}
856						} else {
857							$("#voucherTypeWrap").removeClass("d-none");
858						}
859
860                        // DD - 10/9/22 - If we have extras included, build the extras container
861                        if(includesExtras) {
862                            $('#buyVoucherPostedOptionsContainer').show();
863                            $('#buyVoucherOptions').show();
864                            // We need to build the extras' html
865                            html = '';
866                            var count = 0;
867                            var prodpriceorpostage = 0;
868                            $.each(productsarr, function(key, prod) {
869                                console.log(prod);
870                                count++;
871                                if(count == 1) {
872                                    $('#voucherExtraId').val(prod.id);
873                                    html+= '<div class="row no-gutters">';
874                                }
875                                prodpriceorpostage = prod.price;
876                                if(prodpriceorpostage == 0) {
877                                    prodpriceorpostage = prod.postage;
878                                }
879                                html+= '<div onclick="selectVoucherExtra(this);" data-extraid="'+prod.id+'" class="col-6 p-3 text-center cursor-pointer">';
880                                html+= '<img data-type="voucherextraimage" src="'+prod.image+'" class="rounded '+(count == 1 ? 'selected-voucher-extra' : '')+'">';
881                                html+= '<div class="mt-2">';
882                                html+= prod.name;
883                                html+= '</div>';
884                                html+= '<div>';
885                                html+= '<small class="text-muted">+&pound;'+prodpriceorpostage+'</small>';
886                                html+= '</div>';
887                                html+= '</div>';
888                            });
889                            console.log('html: '+html);
890                            if(html != '') {
891                                html+= '</div>';
892                                $('#buyVoucherPostedProducts').html(html);
893                            }
894                        } else if(voucherOption == 2) {
895                            //  voucherOption == 2 means the voucher is set to "both" so it can be digital or posted. So show the 2 options for those.
896                            //  voucherOption == 0 means "digital" and voucherOption == 1 means "posted". In both cases we don't need to show an option
897                            $('#buyVoucherPostedOptionsContainer').hide();
898                            $('#buyVoucherOptions').show();
899                        }
900                        else {
901                            $('#buyVoucherOptions').hide();
902                        }
903						
904						if(minQty == maxQty && count == 1) {
905							addVoucher();
906						} else {
907							$("#modalBuyVoucher").modal("show");
908						}
909                    } else {
910                        $("#divVoucherPricingTypes").html("Oops, something's gone wrong. Please try again later...");
911						$("#modalBuyVoucher").modal("show");
912                    }
913                }
914            });
915        }
916    });
917    
918    // Buy Voucher Qty +/-
919    $("#divBuyVoucher").on("click", ".qtyIncrement", function() {
920        var count = parseInt($(this).data("count"));
921		var add = parseInt($(this).data("add"));
922		var qty = ($("#buyVoucherQty").val()*1);
923       
924        var minQty = $("#buyVoucherQty").attr("min") ? $("#buyVoucherQty").attr("min") : 1;
925        var maxQty = $("#buyVoucherQty").attr("max") ? $("#buyVoucherQty").attr("max") : 999;
926        var newQty = qty + add;
927		
928		var disabledTicket = parseInt($(this).data("disabledticket"));
929        
930        if(add == 1) {
931            if(newQty < minQty) {
932                newQty = minQty;
933            } else if(newQty > maxQty) {
934                newQty = maxQty;
935            }
936            if (disabledTicket == 1) {
937				$('.carerTicket').removeClass('d-none');
938			}
939        } else if(add == -1) {
940            if(qty == 0 || newQty == 0) {
941                newQty = "";
942				if (disabledTicket == 1) {
943					$('.carerTicket').addClass('d-none');
944				}   
945            } else if(newQty < minQty) {
946                newQty = minQty;
947				if (disabledTicket == 1) {
948					$('.carerTicket').removeClass('d-none');
949				}   
950            }
951        }
952        
953        $("#buyVoucherQty").val(newQty);
954        checkBuyVoucher();
955	});
956    
957    $("#divBuyVoucher").on("keydown", "#buyVoucherQty", function(e) {
958        let keyPressed = e.key;
959        let isNumber = !isNaN(parseFloat(keyPressed));
960        
961        if(isNumber || keyPressed == "Backspace") {
962            
963        } else {
964            e.preventDefault();
965        }
966    });
967    
968    // Edit Buy Voucher Qty
969    $("#divBuyVoucher").on("change", "#buyVoucherQty", function() {
970        var qty = ($(this).val()*1);
971        var minQty = this.min ? this.min : 1;
972        var maxQty = this.max ? this.max : 99;
973        
974        if(isNaN(parseFloat(qty))) qty = "";
975        
976        if(qty == 0) {
977            qty = "";
978        } else if(qty < minQty) {
979            qty = minQty;
980        } else if(qty > maxQty) {
981            qty = maxQty;
982        }
983        
984        $(this).val(qty);
985        checkBuyVoucher();
986	});
987    
988    $("#divBuyVoucher").on("change", "#buyVoucherPricingTypeId", function() {
989        checkBuyVoucher();
990    });
991    
992    var url = window.location.href;
993    if(url.indexOf("added=1") > -1) {
994        $("#modalBuyVoucherSuccess").modal("show");
995    }
996    
997    // Buy Membership Voucher
998    $(".divCategoryProducts, #divGroupedProducts, #divAvailableProducts, .divProduct").on("click", ".btnBuyMembershipVoucher", function() {
999        var locationId = parseInt($(this).data("locationid"));
1000        var productId = parseInt($(this).data("productid"));
1001        if(productId > 0 && locationId > 0) {
1002            $.ajax({
1003                url: "/shop/ajax.php",
1004                type: "POST",
1005                async: false,
1006                data: { "ajax":1, "getProductById":1, "productId":productId, "locationId":locationId },
1007                dataType: "json",
1008                success: function(data) {
1009                    var membership = data.product.extra.membership;
1010                    
1011                    $("#buyMembershipVoucherLocationId").val(locationId);
1012                    $("#buyMembershipVoucherProductId").val(productId);
1013                    $("#buyMembershipVoucherMaximumUsers").val(membership.maximumUsers);
1014                    $("#buyMembershipVoucherOption").val(membership.otherSettings.voucherOption);
1015                    
1016                    if(membership.includeAdults == 1) {
1017                        var adultsLbl = "";
1018                        if(membership.pricePerUserType == 1) {
1019                            if(membership.adultPrice > 0) {
1020                                adultsLbl+= showprice(membership.adultPrice);
1021                            } else {
1022                                adultsLbl+= lblFree;
1023                            }
1024                        }
1025                        if(membership.requiredAdults > 0) {
1026                            $("#buyMembershipVoucherAdults").attr({"min": membership.requiredAdults});
1027                            $("#buyMembershipVoucherAdults").val(membership.requiredAdults);
1028                            adultsLbl+= "Min: <strong>"+membership.requiredAdults+"</strong>";
1029                        }
1030                        if(membership.maximumAdults > 0) {
1031                            $("#buyMembershipVoucherAdults").attr({"max": membership.maximumAdults});
1032                            if(adultsLbl != "") adultsLbl+= "&nbsp;";
1033                            adultsLbl+= "Max: <strong>"+membership.maximumAdults+"</strong>";
1034                        }
1035                        if(typeof membership.childAgeRange.from != "undefined" && membership.childAgeRange.from > 0 && membership.childAgeRange.to > 0) {
1036                            if(adultsLbl != "") adultsLbl+= "&nbsp;";
1037                            adultsLbl+= "("+(parseInt(membership.childAgeRange.to)+1)+"+)";
1038                        }
1039                        adultsLbl = (adultsLbl != "") ? "Adults<br/><span class=\"d-block font-weight-normal\" style=\"font-size:12px;\">"+adultsLbl+"</span>" : "Adults";
1040                        $("#lblBuyMembershipVoucherAdults").html(adultsLbl);
1041                        
1042                        $("#divBuyMembershipVoucherAdults").show();
1043                    } else {
1044                        $("#divBuyMembershipVoucherAdults").hide();
1045                    }
1046                    
1047                    if(membership.includeChildren == 1) {
1048                        var childLbl = "";
1049                        if(membership.pricePerUserType == 1) {
1050                            if(membership.childPrice > 0) {
1051                                childLbl+= showprice(membership.childPrice);
1052                            } else {
1053                                childLbl+= lblFree;
1054                            }
1055                        }
1056                        if(membership.requiredChildren > 0) {
1057                            $("#buyMembershipVoucherChildren").attr({"min": membership.requiredChildren});
1058                            $("#buyMembershipVoucherChildren").val(membership.requiredChildren);
1059                            childLbl+= "Min: <strong>"+membership.requiredChildren+"</strong>";
1060                        }
1061                        if(membership.maximumChildren > 0) {
1062                            $("#buyMembershipVoucherChildren").attr({"max": membership.maximumChildren});
1063                            if(childLbl != "") childLbl+= "&nbsp;";
1064                            childLbl+= "Max: <strong>"+membership.maximumChildren+"</strong>";
1065                        }
1066                        if(typeof membership.childAgeRange.from != "undefined" && membership.childAgeRange.from > 0 && membership.childAgeRange.to > 0) {
1067                            if(childLbl != "") childLbl+= "&nbsp;";
1068                            childLbl+= "("+membership.childAgeRange.from+"-"+membership.childAgeRange.to+")";
1069                        }
1070                        childLbl = (childLbl != "") ? "Children<br/><span class=\"d-block font-weight-normal\" style=\"font-size:12px;\">
1070"+childLbl+"</span>" : "Children";
1071                        $("#lblBuyMembershipVoucherChildren").html(childLbl);
1072                        
1073                        $("#divBuyMembershipVoucherChildren").show();
1074                    } else {
1075                        $("#divBuyMembershipVoucherChildren").hide();
1076                    }
1077                    
1078                    if(membership.includeSeniors == 1) {
1079                        var seniorsLbl = "";
1080                        if(membership.pricePerUserType == 1) {
1081                            if(membership.seniorPrice > 0) {
1082                                seniorsLbl+= showprice(membership.seniorPrice);
1083                            } else {
1084                                seniorsLbl+= lblFree;
1085                            }
1086                        }
1087                        seniorsLbl = (seniorsLbl != "") ? "Seniors<br/><span class=\"d-block font-weight-normal\" style=\"font-size:12px;\">"+seniorsLbl+"</span>" : "Seniors";
1088                        $("#lblBuyMembershipVoucherSeniors").html(seniorsLbl);
1089                        
1090                        $("#divBuyMembershipVoucherSeniors").show();
1091                    } else {
1092                        $("#divBuyMembershipVoucherSeniors").hide();
1093                    }
1094                    
1095                    if(membership.includeStudents == 1) {
1096                        var studentsLbl = "";
1097                        if(membership.pricePerUserType == 1) {
1098                            if(membership.studentPrice > 0) {
1099                                studentsLbl+= showprice(membership.studentPrice);
1100                            } else {
1101                                studentsLbl+= lblFree;
1102                            }
1103                        }
1104                        studentsLbl = (studentsLbl != "") ? "Students<br/><span class=\"d-block font-weight-normal\" style=\"font-size:12px;\">"+studentsLbl+"</span>" : "Students";
1105                        $("#lblBuyMembershipVoucherStudents").html(studentsLbl);
1106                        
1107                        $("#divBuyMembershipVoucherStudents").show();
1108                    } else {
1109                        $("#divBuyMembershipVoucherStudents").hide();
1110                    }
1111                    
1112                    if(membership.includeDisabled == 1) {
1113                        var disabledLbl = "";
1114                        if(membership.pricePerUserType == 1) {
1115                            if(membership.disabledPrice > 0) {
1116                                disabledLbl+= showprice(membership.disabledPrice);
1117                            } else {
1118                                disabledLbl+= lblFree;
1119                            }
1120                        }
1121                        disabledLbl = (disabledLbl != "") ? "Disabled<br/><span class=\"d-block font-weight-normal\" style=\"font-size:12px;\">"+disabledLbl+"</span>" : "Disabled";
1122                        $("#lblBuyMembershipVoucherDisabled").html(disabledLbl);
1123                        
1124                        $("#divBuyMembershipVoucherDisabled").show();
1125                    } else {
1126                        $("#divBuyMembershipVoucherDisabled").hide();
1127                    }
1128                    
1129                    if(membership.includeCarers == 1) {
1130                        var carersLbl = "";
1131                        if(membership.pricePerUserType == 1) {
1132                            if(membership.carerPrice > 0) {
1133                                carersLbl+= showprice(membership.carerPrice);
1134                            } else {
1135                                carersLbl+= lblFree;
1136                            }
1137                        }
1138                        carersLbl = (carersLbl != "") ? "Carers<br/><span class=\"d-block font-weight-normal\" style=\"font-size:12px;\">"+carersLbl+"</span>" : "Carers";
1139                        $("#lblBuyMembershipVoucherCarers").html(carersLbl);
1140                        
1141                        $("#divBuyMembershipVoucherCarers").show();
1142                    } else {
1143                        $("#divBuyMembershipVoucherCarers").hide();
1144                    }
1145                    
1146                    if(membership.includeChildminders == 1) {
1147                        var childmindersLbl = "";
1148                        if(membership.pricePerUserType == 1) {
1149                            if(membership.childminderPrice > 0) {
1150                                childmindersLbl+= showprice(membership.childminderPrice);
1151                            } else {
1152                                childmindersLbl+= lblFree;
1153                            }
1154                        }
1155                        childmindersLbl = (childmindersLbl != "") ? "Childminders<br/><span class=\"d-block font-weight-normal\" style=\"font-size:12px;\">"+childmindersLbl+"</span>" : "Childminders";
1156                        $("#lblBuyMembershipVoucherChildminders").html(childmindersLbl);
1157                        
1158                        $("#divBuyMembershipVoucherChildminders").show();
1159                    } else {
1160                        $("#divBuyMembershipVoucherChildminders").hide();
1161                    }
1162                    
1163                    checkBuyMembershipVoucher();
1164                    $("#modalBuyMembershipVoucher").modal("show");
1165                }
1166            });
1167        }
1168    });
1169    
1170    // Buy Membership Voucher Qty +/-
1171    $("#divBuyMembershipVoucher").on("click", ".qtyIncrement", function() {
1172        var type = $(this).data("type");
1173		var add = parseInt($(this).data("add"));
1174        
1175        if(type == "adults") {
1176            var qtyElement = $("#buyMembershipVoucherAdults");
1177        } else if(type == "children") {
1178            var qtyElement = $("#buyMembershipVoucherChildren");
1179        } else if(type == "seniors") {
1180            var qtyElement = $("#buyMembershipVoucherSeniors");
1181        } else if(type == "students") {
1182            var qtyElement = $("#buyMembershipVoucherStudents");
1183        } else if(type == "disabled") {
1184            var qtyElement = $("#buyMembershipVoucherDisabled");
1185        } else if(type == "carers") {
1186            var qtyElement = $("#buyMembershipVoucherCarers");
1187        } else if(type == "childminders") {
1188            var qtyElement = $("#buyMembershipVoucherChildminders");
1189        }
1190        
1191		var qty = (qtyElement.val()*1);
1192        var minQty = qtyElement.attr("min") ? qtyElement.attr("min") : 0;
1193        var maxQty = qtyElement.attr("max") ? qtyElement.attr("max") : 999;
1194        var newQty = qty + add;
1195        
1196        if(add == 1) {
1197            if(newQty < minQty) {
1198                newQty = minQty;
1199            } else if(newQty > maxQty) {
1200                newQty = maxQty;
1201            }
1202        } else if(add == -1) {
1203            if(newQty < minQty) {
1204                newQty = minQty;
1205            }
1206        }
1207        
1208        if(newQty == 0) newQty = "";
1209        qtyElement.val(newQty);
1210        checkBuyMembershipVoucher();
1211	});
1212    
1213    // Edit Buy Membership Voucher Qty
1214    $("#divBuyMembershipVoucher").on("change", "input[id^='buyMembershipVoucher']", function() {
1215        var qty = ($(this).val()*1);
1216        var minQty = $(this).attr("min") ? parseInt($(this).attr("min")) : 0;
1217        var maxQty = $(this).attr("max") ? parseInt($(this).attr("max")) : 999;
1218        
1219        if(isNaN(parseFloat(qty))) qty = "";
1220        
1221        if(qty == 0) {
1222            qty = "";
1223        } else if(qty < minQty) {
1224            qty = minQty;
1225        } else if(qty > maxQty) {
1226            qty = maxQty;
1227        }
1228        
1229        $(this).val(qty);
1230        checkBuyMembershipVoucher();
1231	});
1232});
1233
1234function selectVoucherExtra(obj) {
1235    var extraid = $(obj).data('extraid');    
1236    $('#voucherExtraId').val(extraid);
1237
1238    $('[data-type="voucherextraimage"]').removeClass('selected-voucher-extra');
1239    $('[data-extraid="'+extraid+'"]').find('img').addClass('selected-voucher-extra');
1240}
1241
1242function checkProductsTotal(memberProduct = false) {
1243    if(memberProduct) {
1244        var loggedInUserId = $("#userId").val();
1245        var categoryId = $("#categoryId").val();
1246        var locationId = $("#locationId").val();
1247        
1248        var products = new Array();
1249        var num = 0;
1250        var totalProducts = 0;
1251        
1252        $("#divMemberProducts input[id^='productQty_']").each(function() {
1253            var count = parseInt($(this).data("count"));
1254            
1255            var productId = $("#productId_"+count).val();
1256            var qty = 0;
1257            var price = 0;
1258            var userId = 0;
1259            var membershipId = 0;
1260            var membershipProductId = 0;
1261            
1262            if($(this).is(":checkbox")) {
1263                if($(this).is(":checked")) qty = 1;
1264                price = $("#memberPrice_"+count).val();
1265                userId = parseInt($("#userId_"+count).val());
1266                membershipId = parseInt($("#membershipId_"+count).val());
1267                membershipProductId = parseInt($("#membershipProductId_"+count).val());
1268                
1269                products[num] = productId+"_"+qty+"_"+price+"_"+userId+"_"+membershipId+"_"+membershipProductId;
1270                num++
1271                
1272                totalProducts += (qty*1);
1273            }
1274        });
1275            
1276        if(totalProducts > 0) {
1277            $.ajax({
1278                url: "/shop/ajax.php",
1279                type: "POST",
1280                async: false,
1281                data: { "getGroupedProductsTotal":1, "userId":loggedInUserId, "categoryId":categoryId, "locationId":locationId, "products":products },
1282                dataType: "json",
1283                success: function(data) {
1284                    // Check for Guest Product Prices
1285                    if(data.isNewGuestProducts == 1) {
1286                        $.each(data.products, function(key, value) {
1287                            var membershipActivityId = value.membershipActivityId;
1288                            
1289                            if(data.guestProducts == null || typeof data.guestProducts[membershipActivityId] == "undefined") return;
1290                            
1291                            $.each(data.guestProducts[membershipActivityId], function(productId, product) {
1292                                if(product.creditBasedPayment) {
1293                                    $("#spanPrice_"+productId).hide().html(parseInt(product.minCredits)+" credit(s)").fadeIn(500);
1294                                } else {
1295                                    $("#spanPrice_"+productId).hide().html(showprice(product.minPrice)).fadeIn(500);
1296                                }
1297                            });
1298                        });
1299                    } else {
1300                        $.each(data.guestProducts, function(productId, product) {
1301                            $("#price_"+productId).val(product.minPrice);
1302                            $("#spanPrice_"+productId).hide().html(showprice(product.minPrice)).fadeIn(500);
1303                        });
1304                    }
1305                }
1306            });
1307        } else {
1308            // Reset Additional Product Prices
1309            $("#divAdditionalProducts input[id^='productQty_']").each(function() {
1310                var productId = parseInt($(this).data("productid"));
1311                var price = $("#standardPrice_"+productId).val();
1312                
1313                $("#price_"+productId).val(price);
1314                $("#spanPrice_"+productId).html(showprice(price));
1315            });
1316        }
1317    }
1318    
1319    var totalProducts = 0;
1320    $("#divMemberProducts input[id^='productQty_'], #divAdditionalProducts input[id^='productQty_']").each(function() {
1321        var qty = 0;
1322        
1323        if($(this).is(":checkbox")) {
1324            if($(this).is(":checked")) qty = 1;
1325        } else {
1326            qty = $(this).val();
1327        }
1328        
1329        if(qty > 0) totalProducts += (qty*1);
1330    });
1331    
1332    if(totalProducts > 0) {
1333        $("#btnBookNow").show();
1334    } else {
1335        $("#btnBookNow").hide();
1336    }
1337}
1338
1339function getGroupedProductsTotal(memberProduct = false, newAvailabilityCheck = 0) {
1340    // SD bespoke js for rileys
1341    if(typeof handleRileysTables === "function") handleRileysTables();
1342    
1343    if(newAvailabilityCheck == 1) $("#divGroupedProductsError, .divGroupedProductsError").html("").slideUp();
1344    
1345    $("#divGroupedProductsList, .divGroupedProductsList").html('<div class="d-flex justify-content-center"><div class="spinner-grow" role="status"><span class="sr-only">Loading...</span></div></div>');
1346    
1347    var loggedInUserId = $("#userId").val();
1348    var categoryId = $("#categoryId").val();
1349    var locationId = $("#locationId").val();
1350    var showPrices = $("#showPrices").val();
1351	
1352    var products = new Array();
1353    arrSelectedProducts = {};
1354    var key = 0;
1355    var html = "";
1356    var totalProducts = 0;
1357    var totalMemberProducts = 0;
1358    var totalPrice = 0;
1359    var productsError = "";
1360    var mandatoryProds = 0;
1361    var mandatoryProdsSelected = 0;
1362    
1363    $("#divGroupedProducts input[id^='productQty_']").each(function() {
1364        var productName = $(this).data("productname");
1365        var count = parseInt($(this).data("count"));
1366        var mandatory = parseInt($(this).data("mandatory"));
1367        
1368        var productId = $("#productId_"+count).val();
1369        var qty = 0;
1370        var price = 0;
1371        var userId = 0;
1372        var membershipId = 0;
1373        var membershipProductId = 0;
1374        
1375        if($(this).is(":checkbox")) {
1376            if($(this).is(":checked")) qty = 1;
1377            
1378            if($("#productId_"+count)[0].tagName === "SELECT") {
1379                price = $("#productId_"+count).find(":selected").data("price");
1380                membershipProductId = parseInt($("#productId_"+count).find(":selected").data("membershipproductid"));
1381            } else {
1382                price = $("#memberPrice_"+count).val();
1383                membershipProductId = parseInt($("#membershipProductId_"+count).val());
1384            }
1385            
1386            userId = parseInt($("#userId_"+count).val());
1387            membershipId = parseInt($("#membershipId_"+count).val());
1388        } else {
1389            qty = $(this).val();
1390            price = $("#price_"+productId).val();
1391        }
1392        if(qty > 0) {
1393            products[key] = productId+"_"+qty+"_"+price+"_"+userId+"_"+membershipId+"_"+membershipProductId+"_"+isVouchersOnlyCategory;
1394            
1395            arrSelectedProducts[key] = {};
1396			arrSelectedProducts[key]["productId"] = productId;
1397            arrSelectedProducts[key]["qty"] = qty;
1398            arrSelectedProducts[key]["price"] = price;
1399            arrSelectedProducts[key]["userId"] = userId;
1400            arrSelectedProducts[key]["membershipId"] = membershipId;
1401            arrSelectedProducts[key]["membershipProductId"] = membershipProductId;
1402            arrSelectedProducts[key]["isVoucher"] = isVouchersOnlyCategory;
1403
1404            if (USE_V2_JOURNEY){
1405                html+= "<div class=\"d-flex align-items-start\">";
1406                html+= "<div class=\"flex-grow-1\">"+qty+" x "+productName+"</div>";
1407                if(showPrices == 1) html+= "<div class=\"flex-nowrap\">From "+showprice(price * qty)+"</div>";
1408                html+= "</div>";
1409            }else{
1410                html+= "<div>";
1411                html+= qty+" x "+productName;
1412                if(showPrices == 1) html+= " <small>From "+showprice(price * qty)+"</small>";
1413                html+= "</div>";
1414            }
1415            
1416            totalPrice+= (price * qty);
1417            
1418            key++;
1419            totalProducts+= (qty * 1);
1420            if(membershipId > 0) totalMemberProducts+= (qty * 1);
1421        }
1422       
1423        if(mandatory == 1) {
1424            mandatoryProds++;
1425            if($(".chkProduct_"+productId).is(":checked") || $(".product_"+productId).val() > 0 || $("#product_"+count).val() == productId) {
1426                mandatoryProdsSelected++;
1427            }
1428        }
1429    });
1430    
1431    if(totalProducts > 0) {
1432        if(newAvailabilityCheck == 1 && totalMemberProducts == 0) {
1433            if (WS_USER == "developer"){
1434                $.ajax({
1435                    url: "/booking/ajax.php",
1436                    type: "POST",
1437                    async: false,
1438                    data: { getBookingFee:1, userId:loggedInUserId, locationId:locationId, products:products },
1439                    dataType: "json",
1440                    success: function(data) {
1441                        if (data.hasOwnProperty("bookingfee")) {
1442                            var name = "Booking fee";
1443                            if (data.hasOwnProperty("bookingfeeName")) name = data.bookingfeeName;
1444                            if (USE_V2_JOURNEY){
1445                                html+= "<div class=\"d-flex align-items-start\">";
1446                                html+= "<div class=\"flex-grow-1\">"+name+"</div>";
1447                                if(showPrices == 1 || devmode) html+= "<div class=\"flex-nowrap\">"+showprice(data.bookingfee)+"</div>";
1448                                html+= "</div>";
1449                            }else{
1450                                html+= "<div>";
1451                                html+= "Booking fee";
1452                                if(showPrices == 1) html+= " <small>"+showprice(data.bookingfee)+"</small>";
1453                                html+= "</div>";
1454                            }
1455                            totalPrice= totalPrice+ +data.bookingfee;
1456                        }
1457                    },
1458                });
1459            }
1460        
1461            $("#divGroupedProductsList, .divGroupedProductsList").hide().html(html).fadeIn(1000);
1462            $("#incBasketHeading").removeClass("d-none");
1463            
1464            $("#spanGroupedProductsTotalPrice, .spanGroupedProductsTotalPrice").hide().html(showprice(totalPrice)).fadeIn(1000);
1465            $("#divGroupedProductsTotal").show();
1466        } else {
1467            // Rileys want to hide additional guests area if no members are selected
1468            if(WS_USER == "rileys") $(".divAdditionalGuests").show();
1469            
1470            if(mandatoryProds > 0 && mandatoryProdsSelected == 0) {
1471                productsError = "Your booking must contain at least one mandatory product.";
1472            }
1473            
1474            $.ajax({
1475                url: "/shop/ajax.php",
1476                type: "POST",
1477                async: false,
1478                data: { getGroupedProductsTotal:1, userId:loggedInUserId, categoryId:categoryId, locationId:locationId, products:products },
1479                dataType: "json",
1480                success: function(data) {
1481                    if(showPrices != 1) $("#totalPriceWrap").addClass("d-none");
1482                    
1483                    // Check for Guest Product Prices
1484                    if(memberProduct) {
1485                        if(data.isNewGuestProducts == 1) {
1486                            $.each(data.products, function(key, value) {
1487                                var membershipActivityId = value.membershipActivityId;
1488                                
1489                                if(data.guestProducts == null || typeof data.guestProducts[membershipActivityId] == "undefined") return;
1490                                
1491                                $.each(data.guestProducts[membershipActivityId], function(productId, product) {
1492                                    if(product.creditBasedPayment) {
1493                                        $("#spanPrice_"+productId).hide().html(parseInt(product.minCredits)+" credit(s)").fadeIn(500);
1494                                    } else {
1495                                        $("#spanPrice_"+productId).hide().html(showprice(product.minPrice)).fadeIn(500);
1496                                    }
1497                                });
1498                            });
1499                        } else {
1500                            $.each(data.guestProducts, function(productId, product) {
1501                                $("#price_"+productId).val(product.minPrice);
1502                                $("#spanPrice_"+productId).hide().html(showprice(product.minPrice)).fadeIn(500);
1503                            });
1504                        }
1505                    }
1506                    
1507                    // Build Total Products HTML
1508                    html = "";
1509                    $.each(data.products, function(key, product) {
1510                        if(USE_V2_JOURNEY) {
1511                            html+= "<div class=\"d-flex align-items-start\">";
1512                            html+= "<div class=\"flex-grow-1\">"+product.qty+" x "+product.name+"</div>";
1513                            if(showPrices == 1) {
1514                                if(product.creditBasedPayment) {
1515                                    html+= "<div class=\"text-nowrap\">"+(product.qty * product.minCredits)+" credits</div>";
1516                                } else {
1517                                    html+= "<div class=\"text-nowrap\">"+showprice(product.totalPrice)+"</div>";
1518                                }
1519                            }
1520                            html+= "</div>";
1521                        } else {
1522                            html+= "<div>";
1523                            if(showPrices == 1) {
1524                                html+= product.qty+" x "+product.name+" <small>From "+showprice(product.totalPrice)+"</small>";
1525                            } else {
1526                                html+= product.qty+" x "+product.name;
1527                            }
1528                            html+= "</div>";
1529                        }
1530                    });
1531
1532                    if (data.hasOwnProperty("bookingfee")) {
1533                        var name = "Booking fee";
1534                        if (data.hasOwnProperty("bookingfeeName")) name = data.bookingfeeName;
1535                        if (USE_V2_JOURNEY){
1536                            if (!data.basketContainsBookingFee){
1537                                html+= "<div class=\"d-flex align-items-start\">";
1538                                html+= "<div class=\"flex-grow-1\">"+name+"</div>";
1539                                if(showPrices == 1 || devmode) html+= "<div class=\"flex-nowrap\">"+showprice(data.bookingfee)+"</div>";
1540                                html+= "</div>";
1541                            }
1542                            
1543                        }else{
1544                            html+= "<div>";
1545                            html+= name;
1546                            if(showPrices == 1) html+= " <small>"+showprice(data.bookingfee)+"</small>";
1547                            html+= "</div>";
1548                        }
1549                        data.totalPrice = (parseFloat(data.totalPrice) || 0) + (parseFloat(data.bookingfee) || 0);
1550                        
1551                    }
1552                    
1553                    $("#divGroupedProductsList, .divGroupedProductsList").hide().html(html).fadeIn(1000);
1554                    $("#incBasketHeading").removeClass("d-none");
1555                    if (USE_V2_JOURNEY){
1556                        if (showPrices){
1557                            /* ADD BASKET TOTAL TO SELECT TICKETS TOTAL */
1558                            data.totalPrice+= $("#totalPrice").data("price");
1559                        }else{
1560                            data.totalPrice = $("#totalPrice").data("price");
1561                        }
1562                    }
1563
1564                    $("#spanGroupedProductsTotalPrice, .spanGroupedProductsTotalPrice").hide().html(showprice(data.totalPrice)).fadeIn(1000);
1565                    
1566                    //OD added 2021-09-08 ticket #035910
1567                    if(data.WS_USER == "continuum"){
1568                        $.each(data.products, function(key, product){
1569                            setTimeout(function(){
1570                                $('#qtyInc_'+product.productId).html('+');
1571                                $('#qtyDec_'+product.productId).html('-');
1572                            }, 500);
1573                        });
1574                    }
1575                    
1576                    if(USE_V2_JOURNEY) {
1577                        if (!showPrices && $("#totalPrice").data("basketitemcount") == 0){
1578                            $("#basketTotalPriceWrap").addClass("d-none").removeClass("d-flex");
1579                        }else{
1580                            $("#basketTotalPriceWrap").removeClass("d-none").addClass("d-flex");
1581                        }
1582                        $("#basketContentEmpty").addClass("d-none");
1583                        $("#basketContent").removeClass("d-none");
1584                    } else {
1585                        $("#divGroupedProductsTotal").show();
1586                    }
1587                    
1588                    if(newAvailabilityCheck == 1) {
1589                        $("#btnBookNow").slideDown();
1590                    } else {
1591                        var minimumBookingQty = ($("#minimumBookingQty").val()*1);
1592                        var maximumBookingQty = ($("#maximumBookingQty").val()*1);
1593                        
1594                        if(minimumBookingQty > 0 && totalProducts < minimumBookingQty) {
1595                            productsError = "You must select at least <b>"+minimumBookingQty+"</b> tickets.";
1596                        } else if(maximumBookingQty > 0 && totalProducts > maximumBookingQty) {
1597                            productsError = "You can only select up to <b>"+maximumBookingQty+"</b> tickets.";
1598                        } else if(data.bookingConditionError != "") {
1599                            productsError = data.bookingConditionError;
1600                        }
1601
1602                        if(productsError == "") {
1603                            $("#divGroupedProductsError, .divGroupedProductsError").slideUp();
1604                            
1605                            if(USE_V2_JOURNEY) {
1606                                $("#V2_journey_continue").removeClass("disabled").attr("aria-disabled","false").attr('onClick', '$("#frmGroupedProducts").submit();');
1607                                $("#footerHiddenSpacing").remove();
1608                                var bottomBarHeight = $("#V2_journeyButtonWrapper").height();
1609                                $("#footer").append("<div id=\"footerHiddenSpacing\" style='height:"+bottomBarHeight+"px'></div>");
1610                            } else {
1611                                $("#btnBookNow").show();
1612                            }
1613                        } else {
1614                            $("#divGroupedProductsError, .divGroupedProductsError").html(productsError);
1615                            $("#divGroupedProductsError, .divGroupedProductsError").slideDown();
1616                            
1617                            if(USE_V2_JOURNEY) {
1618                                $("#V2_journey_continue").addClass("disabled").attr("aria-disabled","true");  
1619                                $("#footerHiddenSpacing").remove();
1620                                var bottomBarHeight = $("#V2_journeyButtonWrapper").height();
1621                                $("#footer").append("<div id=\"footerHiddenSpacing\" style='height:"+bottomBarHeight+"px'></div>");
1622                            } else {
1623                                $("#btnBookNow").hide();
1624                            }
1625                        }
1626                    }
1627                }
1628            });
1629        }
1630    } else {
1631        // Reset Guest Product Prices
1632        $("#divGroupedProducts input[id^='productQty_']").each(function() {
1633            var productId = parseInt($(this).data("productid"));
1634            var price = $("#standardPrice_"+productId).val();
1635            
1636            $("#price_"+productId).val(price);
1637            $("#spanPrice_"+productId).html(showprice(price));
1638            
1639            // OD added 2021-09-08 ticket #035910
1640            if(WS_USER == "continuum") {
1641                setTimeout(function(){
1642                    $('#qtyDec_'+productId).html('-');
1643                }, 500);
1644            }
1645            
1646            // Rileys want to hide additional guests area if no members are selected
1647            if(WS_USER == "rileys") $(".divAdditionalGuests").slideUp();
1648        });
1649        
1650        $("#divGroupedProductsTotal").hide();
1651        $("#incBasketHeading").addClass("d-none");
1652
1653        if(USE_V2_JOURNEY) {
1654            $("#V2_journey_continue").addClass("disabled").attr("aria-disabled","true");   
1655            $("#basketContentEmpty").removeClass("d-none");
1656            $("#basketContent").addClass("d-none");
1657            var bottomBarHeight = $("#V2_journeyButtonWrapper").height();
1658            $("#footer").append("<div style='height:"+bottomBarHeight+"px'></div>");
1659        }
1660    }
1661}
1662
1663function bookInGroupedProducts() {
1664    var userId = $("#userId").val();
1665    var categoryId = $("#categoryId").val();
1666    var locationId = $("#locationId").val();
1667    
1668    $("#divGroupedProductsError, .divGroupedProductsError").html("").slideUp();
1669    
1670    $.ajax({
1671        url: "/shop/ajax.php",
1672        method: "POST",
1673        async: false,
1674        data: { checkBookingRestrictions:1, userId:userId, categoryId:categoryId, locationId:locationId, products:arrSelectedProducts },
1675        dataType: "json",
1676    }).done(function(result) {
1677        if(result.error == 1 && result.restrictionError != "") {
1678            $("#divGroupedProductsError, .divGroupedProductsError").html(result.restrictionError).slideDown();
1679        } else {
1680            $("#frmGroupedProducts").submit();
1681        }
1682    });
1683}
1684
1685$(document).on('click', '[data-action="bookInGroupedProducts"]', function (e) {
1686    e.preventDefault(); // replaces the old "return false;" — stops the # navigation
1687    bookInGroupedProducts();
1688});
1689
1690function checkProductUpsells() {
1691    var categoryId = $("#categoryId").val();
1692    var locationId = $("#locationId").val();
1693    
1694    $.ajax({
1695        url: "/shop/ajax.php",
1696        method: "POST",
1697        async: false,
1698        data: { checkProductUpsells:1, categoryId:categoryId, locationId:locationId, products:arrSelectedProducts },
1699        dataType: "json",
1700    }).done(function(result) {
1701        if(result.categoryCount > 0) {
1702            var html = "<div class=\"row justify-content-start justify-content-md-center\">";
1703            
1704            $.each(result.categories, function(key, value) {
1705                html+= "<div class=\"col-12 "+(result.categories.length > 1 ? "col-sm-6" : "")+" mb-4\">";
1706                    html+= "<div class=\"prodItem card h-100 postition-relative\">";
1707                        html+= "<div class=\"card-image\">";
1708                            html+= "<img class=\"card-img-top\" src=\""+value.imageURL+"\" alt=\""+value.name+"\">";
1709                        html+= "</div>";
1710                        html+= "<div class=\"card-body\">";
1711                            html+= "<h2 class=\"h4\">"+value.name+"</h2>";
1712                            if(value.description != "") {
1713                                html+= "<div class=\"product-description mb-2\">";
1714                                    html+= "<small>"+value.description+"</small>";
1715                                html+= "</div>";
1716                            }
1717                            if(typeof value.totalUpsellMinPriceDiff != "undefined" && value.totalUpsellMinPriceDiff > 0) {
1718                                html+= "<p class=\"mb-0\">";
1719                                if(value.totalUpsellMinPriceDiff != value.totalUpsellMaxPriceDiff) {
1720                                    html+= "Upgrade from";
1721                                } else {
1722                                    html+= "Upgrade for only";
1723                                }
1724                                html+= " <b>"+showprice(value.totalUpsellMinPriceDiff)+"</b> extra.";
1725                                html+= "</p>";
1726                            }
1727                        html+= "</div>";
1728                        html+= "<div class=\"card-footer\">";
1729                            $.each(value.productUpsells, function(key2, value2) {
1730                                html+= "<input type=\"hidden\" name=\"productUpsell["+value.categoryId+"]["+value2.productId+"]\" value=\""+value2.upsellProductId+"\">";
1731                            }); 
1732                            html+= "<button type=\"button\" class=\"btn btn-primary w-100\" onclick=\"$('#upsellCategoryId').val("+value.categoryId+"); $('#frmGroupedProducts').submit(); return false;\">"+lblProductUpsellsUpgrade+"</a>";
1733                        html+= "</div>";
1734                    html+= "</div>";
1735                html+= "</div>";
1736            });
1737            
1738            html+= "</div>";
1739            html+= "<button type=\"submit\" class=\"btn btn-secondary\">No Thanks</button>";
1740            
1741            $("#divUpgradeTickets").html(html);
1742            $("#modalUpgradeTickets").modal("show");
1743        } else {
1744            $("#frmGroupedProducts").submit();
1745        }
1746    });
1747}
1748$(document).on('click', '[data-action="checkProductUpsells"]', function (e) {
1749    e.preventDefault(); // replaces the old "return false;" — stops the # navigation
1750    checkProductUpsells();
1751});
1752function checkBuyVoucher() {
1753    var qty = ($("#buyVoucherQty").val()*1);
1754    var pricingTypeId = ($("#buyVoucherPricingTypeId").val()*1);
1755    
1756    if(qty > 0 && pricingTypeId > 0) {
1757        $("#btnAddVoucher").show();
1758    } else {
1759        $("#btnAddVoucher").hide();
1760    }
1761}
1762
1763function checkBuyMembershipVoucher() {
1764    var maximumUsers = parseInt($("#buyMembershipVoucherMaximumUsers").val());
1765    var voucherOption = $("#buyMembershipVoucherOption").val();
1766    var adults = parseInt($("#buyMembershipVoucherAdults").val()) || 0;
1767    var children = parseInt($("#buyMembershipVoucherChildren").val()) || 0;
1768    var seniors = parseInt($("#buyMembershipVoucherSeniors").val()) || 0;
1769    var students = parseInt($("#buyMembershipVoucherStudents").val()) || 0;
1770    var disabled = parseInt($("#buyMembershipVoucherDisabled").val()) || 0;
1771    var carers = parseInt($("#buyMembershipVoucherCarers").val()) || 0;
1772    var childminders = parseInt($("#buyMembershipVoucherChildminders").val()) || 0;
1773    
1774    var totalUsers = adults + children + seniors + students + disabled + carers + childminders;
1775    
1776    if(maximumUsers > 0 && totalUsers > maximumUsers) {
1777        $("#divBuyMembershipVoucherError").html("This membership allows a maximum <b>"+maximumUsers+"</b> users to proceed.").slideDown();
1778        $("#btnAddMembershipVoucher").hide();
1779        return;
1780    } else {
1781        $("#divBuyMembershipVoucherError").html("").slideUp();
1782    }
1783    
1784    if(totalUsers > 0) {
1785        if(voucherOption == "E-voucher" || voucherOption == "Posted" || voucherOption == "Both") {
1786            $("#btnAddMembershipVoucher").html("Continue").fadeIn("slow");
1787        } else {
1788            $("#btnAddMembershipVoucher").html("Add to basket").fadeIn("slow");
1789        }
1790    } else {
1791        $("#btnAddMembershipVoucher").hide();
1792    }
1793}
1794
1795function addVoucher() {    
1796    var basketId = parseInt($("#basketId").val());
1797    var secret = $("#secret").val();
1798    var productId = parseInt($("#buyVoucherProductId").val());
1799    var qty = parseInt($("#buyVoucherQty").val());
1800    var pricingTypeId = parseInt($("#buyVoucherPricingTypeId").val());
1801    var locationId = parseInt($("#buyVoucherLocationId").val());
1802    var voucherExtraId = 0;
1803    var voucherType = 'digital';
1804    var addAsIndividualItems = 0;
1805    if(WS_USER == 'silverstone') {
1806        addAsIndividualItems = 1;
1807    }
1808    if($('#vouchertypePosted').prop('checked')) {
1809        voucherType = 'posted';
1810    }
1811    if($('#voucherExtraId').val() > 0) voucherExtraId = $('#voucherExtraId').val();
1812    
1813    $.ajax({
1814        url: "/booking/ajax.php",
1815        type: "POST",
1816        async: false,
1817        data: { "buy_voucher":1, "basketid":basketId, "secret":secret, "productId":productId, "qty":qty, "pricingtype":pricingTypeId, "locationId":locationId, "voucherExtraId":voucherExtraId, "voucherType": voucherType, "addAsIndividualItems": addAsIndividualItems },
1818        dataType: "json",
1819        success: function(data) {
1820            console.log("here");
1821            console.log(data);
1822            if(data.success == "true") {
1823				dataLayer.push({ ecommerce: null });  // Clear the previous ecommerce object.
1824				/*
1825				dataLayer.push({
1826					event: "add_to_cart",
1827					ecommerce: {
1828						currency: "{$currencycode}",
1829						value: totalPrice,
1830						items: [
1831							{
1832								item_id: "{$productData.code}",
1833								item_name: "{$productData.name|escape:'htmlall'}",
1834								affiliation: "{$booking_locationName|escape:'htmlall'}",
1835								coupon: "",
1836								discount: 0,
1837								index: 0,
1838								item_brand: "",
1839								item_category: "{$productData.analysiscategoryname|escape:'htmlall'}",
1840								item_category2: "",
1841								item_category3: "",
1842								item_category4: "",
1843								item_category5: "",
1844								item_list_id: "",
1845								item_list_name: "",
1846								item_variant: "",
1847								location_id: "",
1848								price: 0,
1849								quantity: {$qty|intval}
1850							}
1851						]
1852					}
1853				});
1854				*/
1855                if(false || WS_USER == 'silverstone'){ //WS_USER == "continuum"  {*Continuum asked to have the normal modal flow |2024-01-03| -HC- (##052887 )*}
1856                    var lastBasketKey = -1;
1857                    $.each(data.newBasket.products, function(key, value) {
1858                        lastBasketKey = key;
1859                    });
1860
1861                    var newKeysString = data.keyString;
1862
1863                    if(lastBasketKey > -1) {
1864                        if(WS_USER == 'silverstone') {
1865                            window.location.href = "/booking/extras?key="+lastBasketKey+'&newkeys='+newKeysString;
1866                        } else {
1867                            window.location.href = "/booking/extras?key="+lastBasketKey;
1868                        }
1869                    } else {
1870                        var url = window.location.href;
1871                        $("#modalBuyVoucherSuccess").modal("show");
1872                        $("#modalBuyVoucher").modal("hide");
1873                    }
1874                } else {
1875					var lastBasketKey = -1;
1876                    $.each(data.newBasket.products, function(key, value) {
1877                        lastBasketKey = key;
1878                    });
1879					
1880					if(lastBasketKey > -1) {
1881						console.log("Basket Key = "+lastBasketKey+ " go to extras");
1882						$("#modalSuccessCTAButton").attr("href", "/booking/extras?key="+lastBasketKey);
1883					} else{
1884						console.log("Basket Key -1 go to basket instead");
1885						$("#modalSuccessCTAButton").attr("href", "/shop/basket");
1886					}
1887					
1888                    var url = window.location.href;
1889                    $("#modalBuyVoucherSuccess").modal("show");
1890                    $("#modalBuyVoucher").modal("hide");
1891                }
1892            }
1893        }, 
1894        fail: function(data) {
1895            console.log("fail");
1896            console.log(data);
1897        },
1898        complete: function(data) {
1899            console.log("complete");
1900            console.log(data);
1901        },
1902    });
1903}
1904
1905function addMembershipVoucher() {
1906    var locationId = parseInt($("#buyMembershipVoucherLocationId").val());
1907    var productId = parseInt($("#buyMembershipVoucherProductId").val());
1908    var voucherOption = $("#buyMembershipVoucherOption").val();
1909    var adultsQty = parseInt($("#buyMembershipVoucherAdults").val());
1910    var childrenQty = parseInt($("#buyMembershipVoucherChildren").val());
1911    var seniorsQty = parseInt($("#buyMembershipVoucherSeniors").val());
1912    var studentsQty = parseInt($("#buyMembershipVoucherStudents").val());
1913    var disabledQty = parseInt($("#buyMembershipVoucherDisabled").val());
1914    var carersQty = parseInt($("#buyMembershipVoucherCarers").val());
1915    var childmindersQty = parseInt($("#buyMembershipVoucherChildminders").val());
1916    
1917    if(voucherOption == "E-voucher" || voucherOption == "Posted" || voucherOption == "Both") {
1918        $("#frmBuyMembershipVoucher").attr("action", "/booking/buildvoucher.php");
1919        $("#frmBuyMembershipVoucher").submit();
1920    } else {
1921        $.ajax({
1922            url: "/booking/ajax.php",
1923            type: "POST",
1924            async: false,
1925            data: { "buyMembershipVoucher":1, "locationId":locationId, "productId":productId, "adultsQty":adultsQty, "childrenQty":childrenQty, "seniorsQty":seniorsQty, "studentsQty":studentsQty, "disabledQty":disabledQty, "carersQty":carersQty, "childmindersQty":childmindersQty },
1926            dataType: "json",
1927            success: function(data) {
1928                if(data.success == "true") {
1929                    var url = window.location.href;
1930                    $("#modalBuyVoucherSuccess").modal("show");
1931                    $("#divBuyMembershipVoucher").modal("hide");
1932                }
1933            },
1934            complete: function(data) {
1935            }        
1936        });
1937    }
1938}
1939
1940function searchFriendMemberships() {
1941    if(!$("#frmAddFriendsMembership")[0].checkValidity()) {
1942		$("#frmAddFriendsMembership").find('input[type="submit"]').click();
1943		return false;
1944	}
1945    
1946    $("#divAddFriendsMembership").html('<div class="d-flex justify-content-center"><div class="spinner-grow" role="status"><span class="sr-only">Loading...</span></div></div>');
1947    $("#btnAddFriendsMembership").hide("slow");
1948    
1949    var cardNumber = $("#addFriendCardNumber").val();
1950	var surname = $("#addFriendSurname").val();
1951    
1952    $.ajax({
1953        url: "/shop/ajax.php",
1954        type: "POST",
1955        async: false,
1956        data: { "searchMemberships":1, "cardNumber":cardNumber, "surname":surname },
1957        dataType: "json",
1958        success: function(data) {
1959            if(data.membershipId > 0 && data.membershipError == "") {
1960                console.log(data);
1961                var html = '<div class="alert alert-success mt-3" role="alert">Membership Found</div>';
1962                html += '<h3>Members</h3>';
1963                html += '<div class="list-group">';
1964                $.each(data.users, function(key, user) {
1965                    var memberName = user.name;
1966                    if(user.type == "Adult") {
1967                        memberName = '<i class="fas fa-male mr-2 me-2"></i>'+memberName;
1968                    } else {
1969                        memberName = '<i class="fas fa-child mr-2 me-2"></i>'+memberName;
1970                    }
1971                    html += '<li class="list-group-item p-2">'+memberName+'</li>';
1972                });
1973                html += '</div>';
1974                 $("#linkMembershipSurname").val(surname);
1975                $("#linkMembershipId").val(data.membershipId);
1976                $("#divAddFriendsMembership").html(html);
1977                $("#btnAddFriendsMembership").show("slow");
1978            } else {
1979                $("#divAddFriendsMembership").html('<div class="alert alert-danger text-center" role="alert">'+data.membershipError+'</div>');
1980            }
1981        }
1982    });
1983}
1984/*
1985--------------------------------------------------
1986END - CATEGORY & GROUP PRODUCTS
1987--------------------------------------------------
1988*/
1989
1990
1991/*
1992--------------------------------------------------
1993START - CATEGORY DATE SELECTION PRODUCTS
1994--------------------------------------------------
1995*/
1996var selectedCategoryId = 0;
1997var selectedProductId = 0;
1998var timer;
1999var delActivities = [];
2000var timeSelected = "";
2001
2002document.addEventListener("visibilitychange", function() {
2003    if(document.visibilityState === "hidden") {
2004        $("#modalAvailableProductsSummary").modal("hide");
2005    }
2006});
2007
2008$(function() {
2009	var $datepicker = $("#availableProductsDatepicker");
2010    let categoryId = $("#categoryId").val();
2011	if($datepicker.length) {
2012		if($datepicker.data('startdate')) {
2013			startDate = $datepicker.data('startdate');
2014			startDateArr = startDate.split('-');
2015            
2016			$datepicker.datepicker({ 
2017				dateFormat: "dd/mm/yy",
2018				minDate: new Date(startDateArr[0], startDateArr[1] - startDateArr[2], 1),
2019				firstDay: 1,
2020				nextText: "Later",
2021				beforeShow: function(input, inst) {
2022					$("#ui-datepicker-div").addClass("category-ui-picker ll-skin-melon");
2023					setTimeout(function () {
2024						inst.dpDiv.css({
2025							top: $("#availableProductsDatepicker").offset().top + 35 + "px",
2026							left: "50%",    
2027							transform:"translate(-50%, -50%)",
2028							boxShadow: "rgba(0, 0, 0, 0.56) 1px 0px 0px 7000px"
2029						});
2030					}, 0);
2031				},
2032          
2033                
2034			});
2035		} else {
2036            
2037			$datepicker.datepicker({ 
2038				dateFormat: "dd/mm/yy",
2039				minDate: 0,
2040				firstDay: 1,
2041				nextText: "Later",
2042				beforeShow: function(input, inst) {
2043					$("#ui-datepicker-div").addClass("category-ui-picker ll-skin-melon");
2044					setTimeout(function () {
2045						inst.dpDiv.css({
2046							top: $("#availableProductsDatepicker").offset().top + 35 + "px",
2047							left: "50%",    
2048							transform:"translate(-50%, -50%)",
2049							boxShadow: "rgba(0, 0, 0, 0.56) 1px 0px 0px 7000px"
2050						});
2051					}, 0);
2052				},
2053                // {*If user already selected a date and decide to change the date this will automatically 
2054                // re-submit the form without the need of clicking Check Availability |2024-09-20| -HC- (#)*}
2055                onSelect: function (i, e) {
2056                    var selectedDate = $("#selectedDate")
2057                    if(selectedDate.val()){
2058                        selectedDate.val(i)
2059                        $("#categoryDateSelector .btn").addClass("disabled")
2060                        $("#calendarForm").submit()
2061
2062                    }
2063                }
2064			});
2065		}
2066	}
2067    
2068    $('a[data-toggle="pill"]').on("shown.bs.tab", function(e) {
2069        var categoryId = $(e.target).data("categoryid");
2070        checkSelectedGroupProducts(categoryId);
2071    });
2072    
2073    // Book Now
2074    $("#divAvailableProducts").on("click", ".bookNow", function() {
2075        var categoryId = parseInt($(this).data("categoryid"));
2076        var productId = parseInt($(this).data("productid"));
2077        
2078        if(!$("#frmBookNow_"+categoryId+"_"+productId)[0].checkValidity()) {
2079            $("#frmBookNow_"+categoryId+"_"+productId).find('input[type="submit"]').click();
2080            return false;
2081        }
2082        
2083        checkSelectedProduct(categoryId, productId);
2084    });
2085    
2086    // Qty +/-
2087    $("#divAvailableProducts").on("click", ".qtyIncrement", function() {
2088        var count = parseInt($(this).data("count"));
2089		var add = parseInt($(this).data("add"));
2090        var productId = $("#productId_"+count).val();
2091		var qty = ($("#productQty_"+count).val()*1);
2092        var categoryId = parseInt($("#productQty_"+count).data("categoryid"));
2093        var minQty = parseInt($("#productQty_"+count).data("minqty")) || 1;
2094        var maxQty = parseInt($("#productQty_"+count).data("maxqty")) || 999;
2095        var newQty = qty + add;
2096        
2097        if(add == 1) {
2098            if(newQty < minQty) {
2099                newQty = minQty;
2100            } else if(newQty > maxQty) {
2101                newQty = maxQty;
2102            }
2103        } else if(add == -1) {
2104            if(qty == 0 || newQty == 0) {
2105                newQty = "";
2106            } else if(newQty < minQty) {
2107                newQty = minQty;
2108            }
2109        }
2110        
2111        $("#productQty_"+count).val(newQty);
2112        
2113        checkSelectedGroupProducts(categoryId);
2114	});
2115    
2116    // Edit Qty
2117    $("#divAvailableProducts").on("change", "[id^='productQty_'], [id^='productId_']", function() {
2118        if($(this).is(":checkbox") || $(this).is("select")) {
2119            var memberProduct = true;
2120            var categoryId = parseInt($(this).data("categoryid"));
2121        } else {
2122            var memberProduct = false;
2123            var qty = ($(this).val()*1);
2124            var categoryId = parseInt($(this).data("categoryid"));
2125            var minQty = parseInt($(this).data("minqty"));
2126            var maxQty = parseInt($(this).data("maxqty"));
2127            
2128            if(qty == 0) {
2129                qty = "";
2130            } else if(qty < minQty) {
2131                qty = minQty;
2132            } else if(qty > maxQty) {
2133                qty = maxQty;
2134            }
2135            
2136            $(this).val(qty);
2137        }
2138        
2139        checkSelectedGroupProducts(categoryId);
2140	});
2141    
2142    $("#modalAvailableProductsSummary").on("hidden.bs.modal", function(e) {
2143        $.each(delActivities, function(key, manifestid){
2144			delSelectedAct(key, manifestid);
2145		});
2146        
2147        if(selectedProductId > 0) {
2148            checkSelectedProduct(selectedCategoryId, selectedProductId);
2149        } else if(selectedCategoryId > 0) {
2150            checkSelectedGroupProducts(selectedCategoryId);
2151        }
2152        
2153        $("#secsRem").html("00");
2154        $("#minsRem").html("05");
2155        $("#timeRem").css("color", "black");
2156        clearInterval(countdown);
2157	});
2158});
2159
2160function checkSelectedProduct(categoryId, productId) {
2161    var qty = ($("#productQty_"+categoryId+"_"+productId).val()*1);
2162    var averageAge = ($("#averageAge_"+categoryId+"_"+productId).val()*1);
2163    var products = new Array();
2164    var extra = new Array();
2165    
2166    if(categoryId > 0 && productId > 0 && qty > 0) {
2167        $("#divAvailableProducts .list-group-item").removeClass("list-group-item-success").removeClass("list-group-item-light");
2168        $("#divAvailableProducts .list-group-item").not("#divListGroup_"+categoryId+"_"+productId).addClass("list-group-item-light");
2169        $("#divListGroup_"+categoryId+"_"+productId).addClass("list-group-item-success");
2170        
2171        selectedCategoryId = categoryId;
2172        selectedProductId = productId;
2173        products[0] = productId+"_"+qty;
2174        extra[0] = averageAge;
2175        
2176        $("#divAvailableProductsError_"+categoryId).html("").slideUp();
2177        $("#divAvailableProductsList_"+categoryId).html('<div class="d-flex justify-content-center"><div class="spinner-grow" style="width:3rem; height:3rem;" role="status"><span class="sr-only">Loading...</span></div></div>').fadeIn("slow");
2178        $("#divAvailableTimes_"+categoryId).html('<div class="d-flex justify-content-center"><div class="spinner-grow" style="width:3rem; height:3rem;" role="status"><span class="sr-only">Loading...</span></div></div>').fadeIn("slow");
2179        
2180        clearTimeout(timer);
2181        timer = setTimeout(function () {
2182            getAvailableProductsTimes(categoryId, products, extra);
2183        }, 1000);
2184        
2185        $("#divAvailableProductsSummary_"+categoryId).slideDown();
2186        
2187        $("html, body").animate({
2188            scrollTop: ($("#divAvailableProductsSummary_"+categoryId).offset().top)
2189        }, 500);
2190        
2191    } else {
2192        $("#divAvailableProductsSummary_"+categoryId).slideUp();
2193    }
2194}
2195
2196function checkSelectedGroupProducts(categoryId) {
2197    selectedCategoryId = categoryId;
2198    
2199    var minimumBookingQty = ($("#minimumBookingQty_"+categoryId).val()*1);
2200    var maximumBookingQty = ($("#maximumBookingQty_"+categoryId).val()*1);
2201    
2202    var products = new Array();
2203    var key = 0;
2204    var selectedProducts = 0;
2205    var mandatoryProds = 0;
2206    var mandatoryProdsSelected = 0;
2207    let extra = [];
2208    var availableProducts = "";
2209    
2210    $("#divAvailableProductsCategory_"+categoryId+" input[id^='productQty_']").each(function() {
2211        var count = parseInt($(this).data("count"));
2212        var mandatory = parseInt($(this).data("mandatory"));
2213        
2214        var productId = $("#productId_"+count).val();
2215        var qty = 0;
2216        var price = 0;
2217        var userId = 0;
2218        var membershipId = 0;
2219        var membershipProductId = 0;
2220        
2221        if($(this).is(":checkbox")) {
2222            if($(this).is(":checked")) qty = 1;
2223            userId = parseInt($("#userId_"+count).val());
2224            membershipId = parseInt($("#membershipId_"+count).val());
2225            membershipProductId = parseInt($("#membershipProductId_"+count).val());
2226        } else {
2227            var qty = $(this).val();
2228        }
2229        
2230        if(qty > 0) {
2231            products[key] = productId+"_"+qty+"_"+price+"_"+userId+"_"+membershipId+"_"+membershipProductId;
2232            key++
2233            selectedProducts+= (qty*1);
2234            
2235            if(mandatory == 1) {
2236                mandatoryProdsSelected++;
2237            }
2238        }
2239        
2240        if(mandatory == 1) {
2241            mandatoryProds++;
2242            extra.push("isMandatory_"+productId);
2243        }
2244        
2245        if(availableProducts != "") availableProducts+= ",";
2246        availableProducts+= productId;
2247    });
2248    
2249    if(selectedProducts > 0) {
2250        var productsError = "";
2251        if(mandatoryProds > 0 && mandatoryProdsSelected == 0) {
2252            productsError = "Your booking must contain at least one mandatory product.";
2253        } else if(minimumBookingQty > 0 && selectedProducts < minimumBookingQty) {
2254            productsError = "You must select at least <b>"+minimumBookingQty+"</b> tickets.";
2255        } else if(maximumBookingQty > 0 && selectedProducts > maximumBookingQty) {
2256            productsError = "You can only select up to <b>"+maximumBookingQty+"</b> tickets.";
2257        }
2258        
2259        if(productsError == "") {
2260            $("#divAvailableProductsError_"+categoryId).html("").slideUp();
2261            $("#divAvailableProductsList_"+categoryId).html('<div class="d-flex justify-content-center"><div class="spinner-grow" style="width:3rem; height:3rem;" role="status"><span class="sr-only">Loading...</span></div></div>').fadeIn("slow");
2262            $("#divAvailableTimes_"+categoryId).html('<div class="d-flex justify-content-center"><div class="spinner-grow" style="width:3rem; height:3rem;" role="status"><span class="sr-only">Loading...</span></div></div>').fadeIn("slow");
2263            
2264            clearTimeout(timer);
2265            timer = setTimeout(function () {
2266                getAvailableProductsTimes(categoryId, products, extra, false, availableProducts);
2267            }, 1500);
2268        } else {
2269            $("#divAvailableTimes_"+categoryId).slideUp();
2270            $("#divAvailableProductsError_"+categoryId).html(productsError).slideDown();
2271        }
2272        
2273        $("#divAvailableProductsSummary_"+categoryId).slideDown();
2274        
2275    } else {
2276        $("#divAvailableProductsSummary_"+categoryId).slideUp();
2277    }
2278}
2279
2280function getAvailableProductsTimes(categoryId, products, extra, getnextbundleitem = false, availableProducts = "") {
2281    var locationId = $("#locationId").val();
2282    var selectedDate = $("#selectedDate").val();
2283    var showPricesOnProducts = $("#showPrices").val();
2284    var showPricesOnTimeSlots = $("#showPricesOnTimeSlots").val();
2285    var selectedProducts = parseInt(products.length);
2286	var productsError = "";
2287    var averageAge = 0;
2288    var allPricingTypes = [];
2289
2290    tmpCatetoryId = categoryId;
2291    tmpProducts = products;
2292    
2293    var now = new Date();
2294    
2295    if(selectedProducts > 0 || getnextbundleitem == true) {
2296        var getAvailProdSetting = (getnextbundleitem == 1) ? 2 : 1;
2297        
2298        $.ajax({
2299            url: "/booking/ajaxGrouped.php",
2300            method: "POST",
2301            async: true,
2302            data: { getAvailableProductsTimes:getAvailProdSetting, selectedDate:selectedDate, categoryId:categoryId, locationId:locationId, products:products, availableProducts:availableProducts, extra:extra, getnextbundleitem:getnextbundleitem},
2303            dataType: "json",
2304            success: function(data) {
2305                productsError = "";
2306                if(data.bookingConditionError != "") productsError = data.bookingConditionError;
2307                
2308                // Build Products List HTML
2309                var html = "";
2310                console.log("#productExtraInfoDescriptionWrapper_"+categoryId);
2311                $("#productExtraInfoDescriptionWrapper_"+categoryId+", .productExtraInfoDescription").addClass("d-none");
2312                $.each(data.currentBookings, function(key, product) {
2313                    //console.log(product);
2314                    //console.log(product.productId);
2315                    $("#productExtraInfoDescriptionWrapper_"+categoryId).find('[data-'+product.prodid+'=true]').removeClass('d-none').parent().removeClass("d-none");
2316                    html += "<div>";
2317                    if(showPricesOnProducts == 1) {
2318                        html += product.qty+" x "+product.name+" <small>From "+showprice(product.totalPrice)+"</small>";
2319                    } else {
2320                        html += product.qty+" x "+product.name;
2321                    }
2322                    html += "</div>";
2323                });
2324                html += "<div class=\"mb-2\"></div>";
2325                $("#divAvailableProductsList_"+categoryId).html(html).fadeIn(1000);
2326                
2327
2328                if(data.times != "" && data.times != null) {
2329					
2330					console.log("Times:");
2331					console.log(data.times);
2332                    if(productsError == "") {
2333                        // Build Times List HTML
2334                        var html = "<div class=\"row\">";
2335                        var size = Object.keys(data.times).length;
2336						
2337                        
2338                        $.each(data.times, function(index, value) {
2339                            let btnText = (typeof value.timelabel != "undefined" && value.timelabel != null && value.timelabel != "") ? value.timelabel : index;
2340                            
2341                            if (showPricesOnTimeSlots){
2342                                price = "<div class=\"time-slot-price\"><small>"+showprice(value.totalOverallPrice)+"</small></div>";
2343                            }else{
2344                                price = "";
2345                            }
2346                           
2347                            //Collect all available pricing types into allPricingTypes array
2348                            if(usePricingTypeColors){
2349                                if(allPricingTypes.some(e => e.type == value.type)){
2350
2351                                }else {
2352                                    allPricingTypes.push({ type:value.type , colour:value.typeColour, price:value.totalOverallPrice})
2353                                }
2354                            }
2355
2356                            //let allDayText = index;
2357                            //if(size == 1 && WS_USER == "webadventure") btnText = "All Day";
2358							if(categoryId == 31 && WS_USER == "peakwildlifepark" && index == "10:00" && size < 3) btnText = "All Day";
2359							if(categoryId == 31 && WS_USER == "peakwildlifepark" && index == "14:30" && size < 3) btnText = "Afternoon";
2360							if(categoryId == 31 && WS_USER == "peakwildlifepark" && index == "14:30" && size < 3) allDayText = index;
2361                            
2362                            
2363                            averageAge = 0;
2364                            if(typeof value.averageAge != "undefined" && value.averageAge > 0) averageAge = value.averageAge;
2365                            
2366                            // usePricingTypeColors === website/bespoke/common.php > DEFINE("USE_PICING_TYPE_COLORS")
2367							pricingTypeBackground = usePricingTypeColors ? value.typeColour : null;
2368                            
2369                            var thisDateTime = selectedDate+" "+index+":00";
2370                            var timeSlotDate = new Date(thisDateTime.replace(/-/g,"/"));
2371                            
2372                            // {* Show spaces free on time slots -  |2024-12-05| -HC- (#059018) *}
2373                            const spacesFreeElement = showSpacesFree ? "<small class='d-block mt-1 timeslot-spaces'>"+value.qtyavailable+" Spaces</small>" : "";
2374                            
2375                            
2376
2377                            if((timeSlotDate.getTime() < now.getTime()) && btnText != "All Day" && value.available == 0) { // Time slot has passed
2378                                html += "<div class=\"col-6 col-sm-4 col-md-2 mb-3\"><button class=\"btn btn-primary w-100 test2\" style=\"cursor: default; opacity:0.2; background:#"+pricingTypeBackground+"; border-color:#"+pricingTypeBackground+";\"><s>"+btnText+"</s>"+price+"</button></div>";
2379                            } else if(value.available == 1) {
2380                                html += "<div class=\"col-6 col-sm-4 col-md-2 mb-3\"><button class=\"btn btn-primary w-100 date-select-time-slots test1\" onclick=\"setSelectedTime('"+index+"', '"+value.price+"', '"+btnText+"', '"+averageAge+"'); return false;\" style=\"background:#"+pricingTypeBackground+"; border-color:#"+pricingTypeBackground+";\" >"+btnText+price+spacesFreeElement+"</button></div>";
2381                            } else {
2382                                html += "<div class=\"col-6 col-sm-4 col-md-2 mb-3 text-center\"><button class='btn btn-primary disabled w-100' disabled style=\"background:#"+pricingTypeBackground+"; border-color:#"+pricingTypeBackground+";\"><s>"+btnText+"</s></button><div class=\"badge badge-secondary\">"+noAvailabilityWording+"</div></div>";
2383                            }
2384                        });
2385                        html += "</div>";
2386                        
2387                        $("#divAvailableTimes_"+categoryId).html(html).fadeIn("slow");
2388                    } else {
2389                        $("#divAvailableTimes_"+categoryId).slideUp();
2390                        $("#divAvailableProductsError_"+categoryId).html(productsError).slideDown();
2391                    }
2392
2393                    // make sure this "<div id="pricing-types"></div>" is placed under .divAvailableTimes eg Dev/templates/category-date-select.tpl
2394                    if(showPricingTypes){
2395                        const pricing_types_div = $("#pricing-types");
2396                        pricing_types_div.empty();
2397                        pricing_types_div && allPricingTypes.map(function(e){
2398                      	    if(e.price!="0.00" || e.price !=0){
2399                      	    	pricing_types_div.append('<div class="col-6 mb-3"><div class="time-slot" style="cursor:default; background:#'+e.colour+'">'+e.type+' '+currency+e.price+'</div></div>')
2400                      	    }
2401                        }) 
2402                        pricing_types_div.fadeIn()
2403                    }
2404
2405                    
2406                } else {
2407                    $("#divAvailableTimes_"+categoryId).html("Sorry, there is no availability on your chosen date - please select another date.").fadeIn("slow");
2408                }
2409            }
2410        });
2411    } else {
2412        $("#divAvailableProductsSummary_"+categoryId).hide("slow");
2413    }
2414}
2415
2416function setSelectedTime(time, price = 0, allDayText = false, averageAge = 0) {
2417
2418    console.log("running.....");
2419    //  Disable all the time slot buttons, now that one has been clicked. Stops clicking of another one, before the popup appears
2420    $('.date-select-time-slots').prop('disabled', true);
2421
2422    var selectedDate = $("#selectedDate").val();
2423    
2424    var qty = 1;
2425    var slotTxt = time;
2426    if(allDayText) slotTxt = allDayText;
2427    if(typeof averageAge == "undefined") averageAge = 0;
2428    
2429   
2430    // $("#availSummaryDate").html($("#availableProductsDatepicker").val()); {*Causing modal to display the wrong date to user.|2024-04-19| -HC- (#)*}
2431    const formatedDate = new Date(selectedDate).toLocaleDateString();
2432    $("#availSummaryDate").html(formatedDate);
2433    
2434    $("#availSummaryTime").html(slotTxt);
2435
2436    if(WS_USER == 'peakwildlifepark') {
2437        var dateArray = selectedDate.split('-');
2438        var timeArray = time.split(':');
2439        var dateDescription = new Date(dateArray[0], (dateArray[1]-1), dateArray[2], timeArray[0], timeArray[1]).toLocaleStr
2439ing('en-gb', {dateStyle: 'full', timeStyle: 'short'});
2440        $('#availSummaryDateText').html('You\'re booking for: <b>'+dateDescription+'</b>');
2441    }
2442	//console.log("calling ajax for setTime");
2443    $.ajax({
2444        url: "/booking/ajaxGrouped.php",
2445        method: "GET",
2446        async: true,
2447        data: { "setTime":1, "time":time, "date":selectedDate, "qty":qty, "averageAge":averageAge },
2448        dataType: "json",
2449        success: function(data) {
2450			console.log("setTime results");
2451			console.log(data);
2452            if(data != "" && data != null && data.error != 1) {
2453                if (displaySessionAlreadyStartedWarning){
2454                    var now = new Date();
2455                    var hour = now.getHours();
2456                    var day = now.getDay();
2457                    var minutes = now.getMinutes();
2458                    var timeSlot = time.split(":");
2459                    var timeSlotHasPassed = false;
2460                    if (selectedDate == todaysDate){
2461                        if (hour > timeSlot[0] ){
2462                            timeSlotHasPassed = true;
2463                        } else if (hour == timeSlot[0]){
2464                            if (minutes > timeSlot[1]){
2465                                timeSlotHasPassed = true;
2466                            }
2467                        }
2468                    }
2469                    if (timeSlotHasPassed){
2470                        $("#sessionAlreadyStartedWarning").removeClass("d-none");
2471                    }else{
2472                        $("#sessionAlreadyStartedWarning").addClass("d-none");
2473                    }
2474                }
2475
2476                if(data.hasOwnProperty("ga4data")) ga4AddToCartProducts = data.ga4data;
2477				addToCartTrackingEvents();
2478                    
2479                if(data.redirect != "" && data.redirect != undefined) {
2480                    window.location.href = data.redirect;
2481                } else if(data.booknextitem != "" && data.booknextitem != undefined) {
2482                	var categoryId = data.categoryId;
2483                	var products = new Array();
2484                	products[0] = "0_0";
2485                	var extras = new Array();
2486
2487			        $("#divAvailableProductsError_"+categoryId).html("").slideUp();
2488			        $("#divAvailableProductsList_"+categoryId).html('<div class="d-flex justify-content-center"><div class="spinner-grow" style="width:3rem; height:3rem;" role="status"><span class="sr-only">Loading...</span></div></div>').fadeIn("slow");
2489			        $("#divAvailableTimes_"+categoryId).html('<div class="d-flex justify-content-center"><div class="spinner-grow" style="width:3rem; height:3rem;" role="status"><span class="sr-only">Loading...</span></div></div>').fadeIn("slow");
2490        
2491                	getAvailableProductsTimes(categoryId, products, extras, 1);
2492                } else {
2493                    checkNextItem();
2494                    initCountdown();
2495                }
2496            } else {
2497                // Not Available
2498                alert("Sorry, this time slot is no longer available. Please select another time.");
2499                getAvailableProductsTimes(tmpCatetoryId, tmpProducts);
2500            }
2501        },
2502        fail: function() {
2503            
2504        }
2505    });
2506}
2507
2508function checkNextItem() {
2509    $.ajax({
2510        url: "/booking/ajaxGrouped.php",
2511        method: "GET",
2512        async: true,
2513        data: { "checkNextItem":1 },
2514        dataType: "json",
2515        success: function(data) {
2516            getCurrentActivities();
2517        }
2518    });
2519}
2520
2521function initCountdown() {
2522    startTime = 5 * 60 * 1000;
2523    countdown = setInterval(function(){
2524        startCountDown();
2525        startTime -= 1000;
2526    }, 1000);
2527}
2528
2529function startCountDown(){
2530    min = Math.floor(startTime / (60 * 1000));
2531    sec = Math.floor((startTime - (min * 60 * 1000)) / 1000);
2532    
2533    sec < 10 ? sec = "0"+sec : sec = sec;
2534    $("#minsRem").html("0"+min);
2535    $("#secsRem").html(sec);
2536    
2537    if(min < 2) $("#timeRem").css("color", "red");
2538    
2539    if(startTime < 0) {
2540        $(".divAvailableTimes").fadeOut();
2541        $("#secsRem").html("00");
2542        $("#minsRem").html("00");
2543        $("#timeRem").css("color", "black");
2544        clearInterval(countdown);
2545    }
2546}
2547
2548function getCurrentActivities() {
2549    $.ajax({
2550        url: "/booking/ajaxGrouped.php",
2551        method: "GET",
2552        async: true,
2553        data: { "getCurrentActivities":1 },
2554        dataType: "json",
2555        success: function(data) {
2556            if(data != "" && data != null) {
2557                if(data.allDone) {
2558                    var activities = "";
2559                    
2560                    $.each(data.info.done, function(key, dataArr) {
2561						console.log(dataArr);
2562                        var activityName = dataArr.name;
2563                        if(activityName == "") activityName = dataArr.data.name;
2564						
2565						
2566                        activities += "<div class=\"d-flex\">";
2567						activities += "		<div class=\"flex-grow-1\">"+dataArr.qty+" x "+activityName+"</div>";
2568						if (showActivityPricingBreakdown){
2569							activities += "		<div class=\"text-right text-end\">"+showprice(dataArr.sessionprice)+"</div>";
2570						}
2571						activities += "</div>";
2572						
2573                        
2574                        $.each(dataArr.activity.timedate.allocated, function(manifestId, vals){
2575                            delActivities[key] = manifestId;
2576                        });
2577                    });
2578                    
2579                    $("#availSummaryActivities").html(activities);
2580                    $("#availSummaryTotalPrice").html(showprice(data.totalPrice));
2581                     
2582                    $("#modalAvailableProductsSummary").modal("show");
2583                } else {
2584                    $("#modalAvailableProductsSummary").modal("hide");
2585                }
2586            }
2587        }
2588    });
2589}
2590
2591function delSelectedAct(key, manid) {
2592    $.ajax({
2593        url: "/booking/ajaxGrouped.php",
2594        method: "GET",
2595        async: true,
2596        data: { "delTime":1, "key":key, "manid":manid },
2597        dataType: "json",
2598        success: function(data) {
2599            checkNextItem();
2600        }
2601    });
2602}
2603
2604    function addToCartTrackingEvents(){
2605		//console.log("fbt");
2606		var productQty;
2607		//console.log("GA4Products");
2608		//console.log(ga4AddToCartProducts);
2609		if (ga4AddToCartProducts != "") {
2610			waitForFbq(function() {
2611				//console.log("send FB");
2612				$.each(ga4AddToCartProducts, function(key, item) {
2613					fbq('track', 'AddToCart', {
2614						event: 'AddToCart',
2615						eventID: FB_event_id,
2616						external_id: userId,
2617						content_category: item.analysiscategoryname,
2618						content_ids: item.code,
2619						content_name: item.name,
2620						content_type: 'product',
2621						contents: [{
2622							"id": item.code, 
2623							"quantity": item.qty,
2624							"item_price": item.price,
2625						}],
2626						currency: currency,
2627						value: item.price,
2628					});  
2629				});
2630			});
2631			$.each(ga4AddToCartProducts, function(key, item) {
2632				dataLayer.push({ ecommerce: null }); // Clear the previous ecommerce object.
2633				dataLayer.push({
2634					event: "add_to_cart",
2635					ecommerce: {
2636						currency: currency,
2637						value: item.price,
2638						items: [{
2639							item_id: item.code,
2640							item_name: item.name,
2641							affiliation: "{$booking_locationName|escape:'htmlall'}",
2642							coupon: "",
2643							discount: 0,
2644							index: item.index,
2645							item_brand: "",
2646							item_category: item.analysiscategoryname,
2647							item_category2: "",
2648							item_category3: "",
2649							item_category4: "",
2650							item_category5: "",
2651							item_list_id: "",
2652							item_list_name: "",
2653							item_variant: "",
2654							item_location: "{$booking_locationName|escape:'htmlall'}",
2655							location_id: item.gmb_locationid,
2656							price: item.price,
2657							quantity: item.qty,
2658						}]
2659					}
2660				});
2661			});
2662			if (typeof gtag != 'undefined'){
2663				//console.log("send gtag");
2664				/*
2665				$.each(ga4AddToCartProducts, function(key, item) {
2666					gtag("event", "add_to_cart", { 
2667						currency: {},
2668						value: item.price,
2669						items: [
2670							{
2671							item_id: item.code,
2672							item_name: item.name,
2673							affiliation: data.ga4data.transactionAffiliation,
2674							coupon: "",
2675							discount: 0,
2676							index: item.index,
2677							item_brand: "",
2678							item_category: item.analysiscategoryname,
2679							item_category2: "",
2680							item_category3: "",
2681							item_category4: "",
2682							item_category5: "",
2683							item_list_id: "",
2684							item_list_name: "",
2685							item_variant: "",
2686							location_id: item.gmb_locationid,
2687							price: item.price,
2688							quantity: item.qty,
2689							}
2690						]
2691					});
2692				});
2693				*/
2694			}
2695		}
2696	}
2697	
2698    function waitForFbq(callback){
2699		if(typeof fbq !== 'undefined'){
2700			callback()
2701		} else {
2702			setTimeout(function () {
2703				waitForFbq(callback)
2704			}, 100)
2705		}
2706	};
2707/*
2708--------------------------------------------------
2709END - CATEGORY DATE SELECTION PRODUCTS
2710--------------------------------------------------
2711*/
2712
2713
2714
2715/*
2716--------------------------------------------------
2717SIMONS NEW ADD TO CART FUNCTIONS
2718--------------------------------------------------
2719*/
2720
2721const reFactorBasket = basket => {
2722    //once an item is removed from basket, keys change and it comes back as an object, fun times.
2723    //if basket is an object convert it to an array
2724    //re-build products array as keys change from 0
2725
2726    let removeKeys = []
2727    typeof basket === 'object' ? basket = Object.values(basket) : null
2728
2729    basket.forEach(product => {
2730        removeKeys.push(product)
2731    })
2732    
2733    //console.log(removeKeys)
2734    return removeKeys
2735}
2736
2737const updateMiniCart = (totalProducts, product, image, basketgrosstotal) => {
2738    //console.log(product)
2739    document.querySelector('.basket-badge').innerHTML = totalProducts
2740    document.querySelector('#miniCartTotal').innerHTML = showprice(basketgrosstotal)
2741
2742    let productRow = document.createElement('div');
2743    productRow.classList.add('row', 'py-3')
2744
2745    let imageCol = document.createElement('div')
2746    imageCol.classList.add('col-3', 'pr-0')
2747    imageCol.innerHTML = `<img height='100' src='${image}' />`
2748
2749    let infoCol = document.createElement('div')
2750    infoCol.classList.add('col-9', 'd-flex', 'flex-column', 'justify-content-center')
2751    infoCol.innerHTML = '<h6>'+product.qty+' x '+product.name+'<br />'+showprice(basketgrosstotal)+'</h6>';
2752
2753    productRow.appendChild(imageCol)
2754    productRow.appendChild(infoCol)
2755
2756    document.querySelector('#miniCartProducts').appendChild(productRow)
2757}
2758
2759const addProductToCart = (productid, qty, prodname, categoryId, image) => {
2760	origText =  $(".addButton_" + productid).html();
2761	
2762    $(".addButton_" + productid).html("Loading...");
2763
2764    $.post("/shop/ajax.php", { "addProductToBasket": 1, "productid": productid, "qty": qty, "ajax": 1 }, function (data) {
2765        console.log(data);
2766        hide ? clearTimeout(hide) : null
2767        if (data.basketgrosstotal != "0") {
2768            let products = reFactorBasket(data.products)
2769
2770            let addedProduct = products[products.length - 1]
2771            console.log(addedProduct)
2772
2773            if (addedProduct.name) {
2774                $('#basketUpdateProductName').html(addedProduct.name.replace("Â","")) //fix unwanted character in product name
2775            }
2776            $('#basketUpdateProductPrice').html(showprice(addedProduct.grossprice))
2777            $('#basketUpdateProductQty').html(addedProduct.qty)
2778            // update the badge beside the basket icon
2779            $('#basketproductcount').html(products.length)
2780			$("#basketUpdateProductImage").attr("src", image);
2781
2782            $('#basketUpdateAlert').fadeIn()
2783
2784            var hide = setTimeout(() => {
2785                $('#basketUpdateAlert').fadeOut()
2786            }, 5000)
2787			
2788			if (document.getElementById('basket')) {
2789				location.reload();
2790			}else{
2791				$(".addButton_" + productid).html(origText);
2792			}
2793            //if site uses simons mini-cart component
2794            if (document.getElementById('basketDrop')) {
2795                updateMiniCart(products.length, addedProduct, image, data.basketgrosstotal)
2796            }
2797        }
2798    }, 'json');
2799}
2800
2801$(document).on('click', '[data-action="addProductToCart"]', function (e) {
2802    e.preventDefault();
2803    addProductToCart($(this).data('productid'), $(this).data('qty'), $(this).data('prodname'), $(this).data('categoryId'), $(this).data('image'));
2804});
2805
2806$(document).ready(function() {
2807    $('.cashVoucherSelector').on('change', function() {
2808        console.log($(this).val());
2809    
2810        if ($(this).val() == "Custom") {
2811            $('.cashVoucherCustomWrapper').removeClass("d-none");
2812            $('.cashVoucherCustomField').val("");
2813            $('.cashVoucherCustomWrapper').focus();
2814        } else {
2815            $('.cashVoucherCustomWrapper').addClass("d-none");
2816            $('.cashVoucherCustomField').val($(this).val());
2817        }
2818    });
2819    
2820    $('#giftVoucherSelector').on('change', function() {
2821        console.log($(this).val());
2822            
2823        if ($(this).val() == "Custom") {
2824            $('#giftVoucherCustomWrapper').removeClass("d-none");
2825            $('#giftVoucherCustomField').val("");
2826            $('#giftVoucherCustomWrapper').focus();
2827        } else {
2828            $('#giftVoucherCustomWrapper').addClass("d-none");
2829            $('#giftVoucherCustomField').val($(this).val());
2830        }
2831    });
2832
2833    
2834    // make sure only numbers can be entered into the gift voucher or cash voucher custom field
2835    if( $('#giftVoucherCustomField').length ){ 
2836        setInputFilter(document.getElementById("giftVoucherCustomField"), function(value) {
2837            return /^\d*$/.test(value); 
2838        }, "Must be a number");
2839
2840    }else{
2841       //console.log("giftVoucherCustomField doesn't exist");
2842    }
2843    
2844    if( $('#cashVoucherCustomField').length ){
2845        setInputFilter(document.getElementById("cashVoucherCustomField"), function(value) {
2846            return /^\d*$/.test(value); 
2847        }, "Must be an unsigned integer");
2848    }
2849
2850    
2851});
2852
2853// Restricts input for the given textbox to the given inputFilter.
2854function setInputFilter(textbox, inputFilter, errMsg) {
2855    ["input", "keydown", "keyup", "mousedown", "mouseup", "select", "contextmenu", "drop", "focusout"].forEach(function(event) {
2856        textbox.addEventListener(event, function(e) {
2857            if (inputFilter(this.value)) {
2858                // Accepted value
2859                if (["keydown","mousedown","focusout"].indexOf(e.type) >= 0){
2860                    this.classList.remove("input-error");
2861                    this.setCustomValidity("");
2862                }
2863                this.oldValue = this.value;
2864                this.oldSelectionStart = this.selectionStart;
2865                this.oldSelectionEnd = this.selectionEnd;
2866            } else if (this.hasOwnProperty("oldValue")) {
2867                // Rejected value - restore the previous one
2868                this.classList.add("input-error");
2869                this.setCustomValidity(errMsg);
2870                this.reportValidity();
2871                this.value = this.oldValue;
2872                this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
2873            } else {
2874                // Rejected value - nothing to restore
2875                this.value = "";
2876            }
2877        });
2878    });
2879}
2880
2881function addAccessCard(addingAnother = false, categoryId = 0) {
2882    $("#essentialCompanionCategoryId").val(categoryId);
2883    $("#modalAccessCardFirstName").val("");
2884    $("#modalAccessCardLastName").val("");
2885    $("#modalAccessCardID").val("");
2886    
2887    $("#divModalAccessCardSuccess").hide("slow");
2888    
2889    if(addingAnother) {
2890        $("#divModalAccessCardSuccess").hide("slow");
2891        $("#btnAddAnotherAccessCard").hide();
2892        $("#btnCheckModalAccessCard").show("slow");
2893    } else {
2894        $("#btnAddAnotherAccessCard").hide();
2895    }
2896    
2897    $("#modalEssentialCompanionTicket").modal("show");
2898}
2899
2900$(document).on('click', '[data-action="addAccessCard"]', function (e) {
2901    e.preventDefault(); // replaces the old "return false;" — stops the # navigation
2902    addAccessCard($(this).data('addinganother'), $(this).data('categoryid'));
2903});
2904
2905function checkModalAccessCard() {
2906    if(!$("#frmModalAccessCard")[0].checkValidity()) {
2907        $("#frmModalAccessCard").find('input[type="submit"]').click();
2908        return false;
2909    }
2910    
2911    var essentialCompanionCategoryId = parseInt($("#essentialCompanionCategoryId").val()) || 0;
2912    var accessCardFirstName = $("#modalAccessCardFirstName").val();
2913    var accessCardLastName = $("#modalAccessCardLastName").val();
2914    var accessCardID = $("#modalAccessCardID").val();
2915    
2916    $("#divModalAccessCardError, #divModalAccessCardSuccess").hide();
2917    
2918    var divEssentialCompanionTicketSelect = "divEssentialCompanionTicketSelect";
2919    if(essentialCompanionCategoryId > 0) divEssentialCompanionTicketSelect+= "_"+essentialCompanionCategoryId;
2920    
2921    var divEssentialCompanionTicketCheck = "divEssentialCompanionTicketCheck";
2922    if(essentialCompanionCategoryId > 0) divEssentialCompanionTicketCheck+= "_"+essentialCompanionCategoryId;
2923    
2924    $.ajax({
2925        method: "POST",
2926        url: "/shop/ajax.php",
2927        data: { checkAccessCard: 1, accessCardFirstName: accessCardFirstName, accessCardLastName: accessCardLastName, accessCardID: accessCardID },
2928        dataType: "json",
2929    }).done(function(result) {
2930        if(result.error != 1) {
2931            if(result.cardHasPlusOneCount > 0 || result.cardHasPlusTwoCount > 0) {
2932                var qty = (result.cardHasPlusTwoCount > 0) ? (result.cardHasPlusTwoCount * 2) : result.cardHasPlusOneCount;
2933                
2934                $("#"+divEssentialCompanionTicketSelect+" .qtyInput").data("maxqty", qty);
2935                $("#"+divEssentialCompanionTicketSelect+" .bookNowBtn").data("maxqty", qty);
2936                $("#"+divEssentialCompanionTicketSelect+" .bookNow").data("maxqty", qty);
2937                
2938                $("#"+divEssentialCompanionTicketSelect+" select").html("");
2939                for(var i = 1; i <= qty; i++) {
2940                    $("#"+divEssentialCompanionTicketSelect+" select").append('<option value="'+i+'">'+i+'</option>');
2941                }
2942                
2943                $("#"+divEssentialCompanionTicketCheck).hide();
2944                $("#"+divEssentialCompanionTicketSelect+"").show("slow");
2945            } else {
2946                $("#"+divEssentialCompanionTicketSelect+"").hide();
2947                $("#"+divEssentialCompanionTicketCheck).show("slow");
2948            }
2949            
2950            if(result.cardHasPlusOneCount > 0 || result.cardHasPlusTwoCount > 0) {
2951                $("#divModalAccessCardSuccess").show("slow");
2952            } else {
2953                $("#divModalAccessCardWarning").html("This card does not grant you access to an Essential Companion Ticket").show("slow");
2954            }
2955            $("#btnCheckModalAccessCard").hide();
2956            $("#btnAddAnotherAccessCard").show("slow");
2957        } else {
2958            if(result.errorMessage != "") {
2959                $("#divModalAccessCardError").html(result.errorMessage).show("slow");
2960            } else if(result.cardHasPlusOneCount == 0 && result.cardHasPlusTwoCount == 0) {
2961                $("#divModalAccessCardError").html("Your access card does not permit you to an Essential Companion ticket.").show("slow");
2962            }
2963        }
2964    });
2965}
2966
2967$(document).on('click', '[data-action="checkModalAccessCard"]', function (e) {
2968    e.preventDefault(); // replaces the old "return false;" — stops the # navigation
2969    checkModalAccessCard();
2970});
2971
2972if(displayVerifyMembershipDetails) {
2973    $(document).ready(function() {
2974        $("#btnUpdateBasketUsingMembership").hide();
2975        $("#modalVerifyMembershipDetails").modal("show");
2976    });
2977}
2978
2979function verifyMembershipDetails() {
2980    if(!$("#btnVerifyMembershipDetails")[0].checkValidity()) {
2981        $("#btnVerifyMembershipDetails").find('input[type="submit"]').click();
2982        return false;
2983    }
2984    
2985    var cardNumber = $("#verifyMembershipCardNumber").val();
2986    var firstName = $("#verifyMembershipFirstName").val();
2987    var lastName = $("#verifyMembershipLastName").val();
2988    var emailAddress = $("#verifyMembershipEmailAddress").val();
2989    
2990    $("#divModalVerifyMembershipError").hide();
2991    $("#btnUpdateBasketUsingMembership").hide();
2992    
2993    $.ajax({
2994        method: "POST",
2995        url: "/shop/ajax.php",
2996        data: { verifyMembershipDetails:1, cardNumber:cardNumber, firstName:firstName, lastName:lastName, emailAddress:emailAddress },
2997        dataType: "json",
2998    }).done(function(result) {
2999        if(result.error != 1) {
3000            $("#btnVerifyMembershipDetails").hide();
3001            
3002            var html = "<input type=\"hidden\" id=\"verifyMembershipId\" value=\""+result.mainMembershipId+"\">";
3003            html+= "<div class=\"alert alert-success text-center\" id=\"divModalVerifyMembershipSuccess\" role=\"alert\">Your membership details have been verified.</div>";
3004            html+= "<p class=\"card-text\">Please select which of your members are attending below.</p>";
3005            
3006            html+= "<div id=\"divMemberProducts\">";
3007                html+= "<div class=\"list-group\">";
3008                
3009                $.each(result.memberProducts, function(key, memberProduct) {
3010                    if(memberProduct.incorrectLocation == 1) {
3011                        html+= '<input type="checkbox">';
3012                        html+= '<label class="list-group-item disabled" aria-disabled="true">'+memberProduct.name+' ('+memberProduct.membershipName+') - This membership is only valid for</label>';
3013                    } else if(memberProduct.bookingLimitReached == 1) {
3014                        html+= '<input type="checkbox">';
3015                        html+= '<label class="list-group-item disabled" aria-disabled="true">'+memberProduct.name+' ('+memberProduct.membershipName+') - Booking Limit Reached</label>';
3016                    } else if(memberProduct.productId > 0) {
3017                        html+= '<input type="checkbox" name="memberProducts['+key+'][key]" id="productKey_'+key+'" value="'+key+'">';
3018                        html+= '<label class="list-group-item list-group-item-action font-weight-bold d-flex align-items-center" for="productKey_'+key+'"><span class="me-3 mr-3">'+memberProduct.name+' ('+memberProduct.membershipName+')</span><span class="btn btn-primary btn-add-member ml-auto ms-auto"></span></label>';
3019                    } else {
3020                        html+= '<input type="checkbox">';
3021                        html+= '<label class="list-group-item disabled" aria-disabled="true">'+memberProduct.name+' ('+memberProduct.membershipName+') - No Products Available</label>';
3022                    }
3023                });
3024                
3025                html+= "</div";
3026            html+= "</div";
3027            
3028            $("#divVerifyMembershipDetails").html(html);
3029        } else {
3030            $("#divModalVerifyMembershipError").html(result.errorMessage).show("slow");
3031        }
3032    });
3033}
3034
3035$(document).on("click", "#divMemberProducts input[type=checkbox][id^='productKey_']", function(event) {
3036    var totalProducts = 0;
3037    $("#divMemberProducts input[type=checkbox][id^='productKey_']:checked").each(function() {
3038        totalProducts++;
3039    });
3040    
3041    if(totalProducts > 0) {
3042        $("#btnUpdateBasketUsingMembership").slideDown();
3043    } else {
3044        $("#btnUpdateBasketUsingMembership").slideUp();
3045    }
3046});
3047
3048function updateBasketUsingMembership() {
3049    var membershipId = $("#verifyMembershipId").val();
3050    
3051    //var memberProducts = {};
3052    //var key = 0;
3053    var memberProducts = "";
3054    $("#divMemberProducts input[type=checkbox][id^='productKey_']:checked").each(function() {
3055        //memberProducts[key] = {};
3056        //memberProducts[key]["key"] = $(this).val();
3057        //key++;
3058        
3059        if(memberProducts != "") memberProducts+= ",";
3060        memberProducts+= $(this).val();
3061    });
3062    
3063    $.ajax({
3064        method: "POST",
3065        url: "/shop/ajax.php",
3066        data: { updateBasketUsingMembership:1, membershipId:membershipId, memberProducts:memberProducts },
3067        dataType: "json",
3068    }).done(function(result) {
3069        window.location.href = "/shop/basket";
3070    });
3071}

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.