PageSourceSearch

https://www.junipersardinia.com/wp-content/themes/juniper-club/assets/js/ticket-modal.js?ver=3

js junipersardinia.com collected 2026-10-09 23:14:19 UTC 5,707 bytes, 172 lines download raw bytes

1(function($) {
2	let selectedTickets = {}; // Memory to store selected ticket IDs and quantities
3
4	function updateSubtotal() {
5		let subtotal = 0;
6		let enableContinue = false;
7
8		$('#ticketSelectionForm .ticket-item').each(function() {
9			const $item = $(this);
10			const $input = $item.find('input[type="number"]');
11
12			if ($input.is(':disabled')) return;
13
14			const price = parseFloat($item.data('price')) || 0;
15			const quantity = parseInt($input.val(), 10) || 0;
16			const minPerOrder = parseInt($input.data('min-per-order'), 10) || 1;
17
18			subtotal += quantity * price;
19
20			if (quantity >= minPerOrder) {
21				enableContinue = true;
22			}
23		});
24
25		$('#subtotal-amount').text('€' + subtotal.toFixed(2));
26		$('#continue-to-step-2').prop('disabled', !enableContinue);
27	}
28
29	// Trigger initial update when modal opens
30	$('#ticketModal').on('shown.bs.modal', function () {
31		updateSubtotal();
32		attachQuantityListeners(); // Rebind in case modal content was updated
33	});
34
35	function updateButtonStates($input) {
36		const $parent = $input.closest('.quantity-selector');
37		const $plus = $parent.find('.plus');
38		const $minus = $parent.find('.minus');
39		const max = parseInt($input.attr('max')) || 999;
40		const quantity = parseInt($input.val(), 10) || 0;
41
42		$minus.prop('disabled', quantity <= 0);
43		$plus.prop('disabled', quantity >= max);
44	}
45
46	function attachQuantityListeners() {
47		// Always unbind to avoid duplicates
48		$('#ticketSelectionForm').off('click', '.plus');
49		$('#ticketSelectionForm').off('click', '.minus');
50		$('#ticketSelectionForm').off('change', 'input[type="number"]');
51
52		$('#ticketSelectionForm').on('click', '.plus', function () {
53			const $input = $(this).closest('.quantity-selector').find('input[type="number"]');
54			let value = parseInt($input.val(), 10) || 0;
55			const max = parseInt($input.attr('max')) || 999;
56			const minPerOrder = parseInt($input.data('min-per-order'), 10) || 1;
57
58			if (value === 0) {
59				value = minPerOrder;
60			} else if (value < max) {
61				value++;
62			}
63
64			$input.val(value).trigger('change');
65		});
66
67		$('#ticketSelectionForm').on('click', '.minus', function () {
68			const $input = $(this).closest('.quantity-selector').find('input[type="number"]');
69			let value = parseInt($input.val(), 10) || 0;
70			const minPerOrder = parseInt($input.data('min-per-order'), 10) || 1;
71
72			value = (value <= minPerOrder) ? 0 : value - 1;
73			$input.val(value).trigger('change');
74		});
75
76		$('#ticketSelectionForm').on('change', 'input[type="number"]', function () {
77			const $input = $(this);
78			const ticketId = $input.data('ticket-id');
79			let value = parseInt($input.val(), 10) || 0;
80			const minPerOrder = parseInt($input.data('min-per-order'), 10) || 1;
81			const max = parseInt($input.attr('max')) || 999;
82
83			if (value > 0 && value < minPerOrder) value = minPerOrder;
84			if (value > max) value = max;
85
86			$input.val(value);
87
88			if (value > 0) {
89				selectedTickets[ticketId] = value;
90			} else {
91				delete selectedTickets[ticketId];
92			}
93
94			updateButtonStates($input);
95			updateSubtotal();
96		});
97	}
98
99	// ---------------------------------------------------------------
100	// Ticket Tailor — Tickets button
101	// Uses data attributes + delegated handler instead of inline onclick.
102	// iOS Safari does not reliably honour "return false" in inline onclick
103	// handlers on anchor tags, causing the browser to follow the href
104	// and redirect to the event page instead of opening the TT widget.
105	// ---------------------------------------------------------------
106	$(document).on('click', '.jnp-tt-ticket-btn', function(e) {
107		if (window.TTWidget && typeof TTWidget.loadEventOccurrence === 'function') {
108			e.preventDefault();
109			TTWidget.loadEventOccurrence(
110				$(this).data('boxoffice'),
111				$(this).data('tt-id')
112			);
113		}
114		// If TTWidget is not loaded, fall through to href (fallback URL)
115	});
116
117	// ---------------------------------------------------------------
118	// Ticket Tailor — Tavoli (tables) button
119	// Same fix: data attributes instead of inline onclick.
120	// ---------------------------------------------------------------
121	$(document).on('click', '.jnp-tt-tables-btn', function(e) {
122		if (window.TTWidget && typeof TTWidget.loadEventOccurrence === 'function') {
123			e.preventDefault();
124			TTWidget.loadEventOccurrence(
125				$(this).data('boxoffice'),
126				$(this).data('tt-id')
127			);
128		}
129	});
130
131	// ---------------------------------------------------------------
132	// Internal ticket modal trigger (non-TT events)
133	// ---------------------------------------------------------------
134	$(document).on('click', '.open-ticket-modal', function(e) {
135		e.preventDefault();
136
137		const eventId = $(this).data('event-id');
138		const occurrence = $(this).data('occurrence');
139
140		if (!eventId || !occurrence) return;
141
142		const baseUrl = window.location.href.split('?')[0];
143		window.location.href = `${baseUrl}?modal=tickets&occurrence=${occurrence}`;
144	});
145
146	$('#continue-to-step-2').on('click', function() {
147		if ($.isEmptyObject(selectedTickets)) {
148			alert('Please select at least one ticket.');
149			return;
150		}
151
152		const eventId = $('#ticketSelectionForm').data('event-id');
153		const occurrenceTs = $('#ticketSelectionForm').data('occurrence-ts');
154
155		if (!eventId || !occurrenceTs) {
156			alert('Event information missing. Please refresh the page.');
157			return;
158		}
159
160		const referer = encodeURIComponent(window.location.href);
161		let query = `?event_id=${eventId}&occurrence_ts=${occurrenceTs}&product_type=event_ticket&referer=${referer}`;
162		$.each(selectedTickets, function(ticketId, quantity) {
163			query += `&selected_tickets[${ticketId}]=${quantity}`;
164		});
165
166		window.location.href = '/checkout/' + query;
167	});
168
169	// Initialize
170	attachQuantityListeners();
171	updateSubtotal();
172})(jQuery);

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.