PageSourceSearch

https://shop.zoo.dk/assets/event-shop/scripts/freeAdmissionVoucher-52c146160584477c8f802837cfec5997.js

js zoo.dk collected 2026-09-24 20:53:30 UTC 8,895 bytes, 314 lines download raw bytes

1/* global common, modal */
2/* exported freeAdmissionVoucher */
3
4/**
5 * Methods related to adding a free admission voucher on the event page.
6 */
7const freeAdmissionVoucher = {
8
9	/**
10	 * The current event category ID.
11	 * @type Number
12	 */
13	categoryId: null,
14
15	/**
16	 * Data of the added free admission vouchers.
17	 * @type Object
18	 */
19	voucherData: null,
20
21	/**
22	 * Initialize the free admission voucher on event page.
23	 * @param {Number} categoryId	The event category ID
24	 */
25	init: function(categoryId) {
26		this.categoryId = categoryId;
27
28		// Do we have any voucher code we want to preadd?
29		let voucherCode = '0';
30		if (location.hash.length > 1) {
31			const hash = location.hash.substr(1).split('=');
32			if (hash.length === 2 && hash[0] === 'voucher_code') {
33				voucherCode = hash[1];
34				location.hash = '';
35			}
36		}
37
38		// Load the voucher data
39		common.ajaxLoader({
40			url: '/voucher/addFreeAdmission',
41			method: 'POST',
42			data: {
43				voucherCode: voucherCode,
44				categoryId: this.categoryId,
45				cleanup: 1
46			},
47			success: function(response) {
48				if (voucherCode !== '0') {
49					// We have added a voucher code, so we need to reload the page to find the correct sections
50					window.location.reload();
51
52					return;
53				}
54
55				freeAdmissionVoucher.voucherData = response.data.vouchers === undefined ? [] : response.data.vouchers;
56				$('#num-tickets').prop('disabled', false);
57
58				// Make sure that a refreshed page displays the correct number of tickets
59				freeAdmissionVoucher.loadEventSelections();
60
61				// Render the voucher list (if the modal is ready)
62				freeAdmissionVoucher.populateList();
63			}
64		});
65	}, // End freeAdmission.init()
66
67	/**
68	 * Show the free admission voucher modal.
69	 */
70	show: function() {
71		// Use existing modal if any
72		const $modal = $('#free_admission_voucher_modal');
73		if ($modal.length > 0) {
74			$modal.modal('show');
75
76			return;
77		}
78
79		// Create a new modal and show it
80		modal.create('free_admission_voucher_modal', {
81			title: common.getResource('free_admission_voucher.modal.title'),
82			body: common.getResource('free_admission_voucher.modal.body'),
83			buttons: ['buttons.close'],
84			focus: 'voucher_code',
85			keyboard: false
86		});
87
88		// Render the voucher list (if the data is ready)
89		this.populateList();
90	}, // End freeAdmission.show()
91
92	/**
93	 * Render the list of active free admission vouchers.
94	 * Will only render if the data has been received from the server and the modal is created.
95	 * Will not do anything if the list has already been rendered.
96	 */
97	populateList: function() {
98		if (this.voucherData === null) {
99			// The data is not ready yet
100			return;
101		}
102		const $placeholder = $('#free_admission_voucher_list_placeholder');
103		if ($placeholder.length === 0) {
104			// The modal is not ready, or the list has already been rendered
105			return;
106		}
107		if (this.voucherData.length === 0) {
108			// No vouchers to list
109			$placeholder.remove();
110
111			return;
112		}
113		const listTemplate = common.getResource('free_admission_voucher.list');
114		const rowTemplate = common.getResource('free_admission_voucher.row');
115		const rows = [];
116		for (let voucherCodeId in this.voucherData) {
117			rows.push(
118				rowTemplate
119					.replace('{id}', voucherCodeId)
120					.replace('{code}', this.voucherData[voucherCodeId].code)
121					.replace('{status}', common.getResource('free_admission_voucher.status.' + this.voucherData[voucherCodeId].status))
122			);
123		}
124		const $list = $(listTemplate.replace('{rows}', rows.join('')));
125		$placeholder.replaceWith($list);
126		common.initScope($list);
127	}, // End freeAdmission.populateList()
128
129	/**
130	 * Shows modal for entering voucher code.
131	 */
132	showVoucherModal: function() {
133		modal.create(
134			'voucher_modal',
135			{
136				title: common.getResource('multihall.voucher_modal.title'),
137				body: common.getResource('multihall.voucher_modal.body'),
138				buttons: ['button.close', 'multihall.voucher_modal.submit_button'],
139				reload: true,
140				show: true
141			}
142		);
143
144	}, // End showVoucherModal()
145
146	/**
147	 * Handle submit of the add free admission voucher form.
148	 * @param {HTMLFormElement} form
149	 */
150	submit: function(form) {
151		const $form = $(form);
152		const $errorFeedback = $('#free_admission_voucher_feedback').hide();
153		const voucherCode = $form.find('input[name="voucher_code"]').val();
154		if (voucherCode === '') {
155
156			return;
157		}
158
159		const $loader = $form.closest('.loader_container');
160		common.ajaxLoader({
161			loader: $loader,
162			url: '/voucher/addFreeAdmission',
163			method: 'POST',
164			data: {
165				voucherCode: voucherCode,
166				categoryId: this.categoryId
167			},
168			success: function(response) {
169				if (response.data.voucherValid) {
170					// Save the current selections and reload the page
171					freeAdmissionVoucher.saveEventSelections();
172					location.reload();
173				}
174				else {
175					$errorFeedback.text(response.data.voucherErrorMessage);
176					$errorFeedback.show();
177				}
178			}
179		});
180	}, // End freeAdmission.submit()
181
182	/**
183	 * Remove all added free admission vouchers
184	 */
185	removeAll: function() {
186		$('#free_admission_voucher_modal .loader_container').addClass('loader');
187		common.ajaxLoader({
188			url: '/voucher/deleteAllFreeAdmission',
189			method: 'POST',
190			success: function(response) {
191				freeAdmissionVoucher.saveEventSelections();
192				location.reload();
193			}
194		});
195	}, // End freeAdmission.removeAll()
196
197	/**
198	 * Remove a specific added free admission voucher.
199	 * @param {Number} voucherCodeId
200	 */
201	remove: function(voucherCodeId) {
202		$('#free_admission_voucher_modal .loader_container').addClass('loader');
203		common.ajaxLoader({
204			url: '/voucher/deleteFreeAdmission',
205			method: 'POST',
206			data: {
207				voucherCodeId: voucherCodeId
208			},
209			success: function(response) {
210				freeAdmissionVoucher.saveEventSelections();
211				location.reload();
212			}
213		});
214	}, // End freeAdmission.remove()
215
216	/**
217	 * Save the event selections in the sessionStorage.
218	 * Typically done before a reload.
219	 */
220	saveEventSelections: function() {
221		if (window.sessionStorage === undefined) {
222			return;
223		}
224		sessionStorage.setItem('num-tickets', $('#num-tickets').val());
225	}, // End freeAdmission.saveEventSelections()
226
227	/**
228	 * Load the saved event selections from the sessionStorage.
229	 * Typically done on page load.
230	 * @return {Boolean}	Returns True if any event data where loaded, and the DOM updated.
231	 */
232	loadEventSelections: function() {
233		if (window.sessionStorage === undefined) {
234			return false;
235		}
236		const numTickets = sessionStorage.getItem('num-tickets');
237		if (numTickets) {
238			sessionStorage.removeItem('num-tickets');
239
240			// Set the ticket number and trigger its change event
241			$('#num-tickets').val(numTickets).change();
242
243			// We do not select ticket types as we expect the customer to want to use the newly added free admission voucher tickets
244			return true;
245		}
246
247		return false;
248	}, // End freeAdmission.loadEventSelections()
249
250	/**
251	 * Get a list of available voucher products.
252	 * This is called in context of MultiHallSeatmap, meaning *this* refers to MultiHallSeatmap!
253	 * We expect all vouchers to be usable in all possible sections. Other scenarios are usually not possible in practice.
254	 * @returns {Array}	Array of products in a regular array, meaning NOT indexed by their ID.
255	 */
256	getVoucherProducts: function() {
257		if (freeAdmissionVoucher.voucherData === null) {
258			// Wow, we're not ready yet!
259			return null;
260		}
261
262		// Find a product for each voucher code.
263		// It is actually the same product for all voucher codes,
264		//  but the presentation varies.
265		const result = [];
266		for (let voucherCodeId in freeAdmissionVoucher.voucherData) {
267			const voucherCode = freeAdmissionVoucher.voucherData[voucherCodeId];
268			if (voucherCode.status !== 'available') {
269				continue;
270			}
271
272			// There is only one possible product for a free admission voucher.
273			// But the product is stored for each possible section.
274			// Therefor, find the first product of the first section and use that.
275			let productFound = false;
276			for (let sectionId in voucherCode.sections) {
277				if (productFound) {
278					break;
279				}
280				const section = voucherCode.sections[sectionId];
281				for (let productId in section.products) {
282					const product = section.products[productId];
283					product.id = productId;
284					result.push(product);
285					productFound = true;
286					break;
287				}
288			}
289		}
290
291		return result;
292	}, // End freeAdmission.getVoucherProducts()
293
294	/**
295	 * Set the status of the given voucher codes as "in cart".
296	 * This is called in context of MultiHallSeatmap, meaning *this* refers to MultiHallSeatmap!
297	 *
298	 * @param {Array} voucherCodeIds
299	 */
300	setAsInCart: function(voucherCodeIds) {
301		if (freeAdmissionVoucher.voucherData === null) {
302			return;
303		}
304
305		for (let i in voucherCodeIds) {
306			const voucherCodeId = voucherCodeIds[i];
307			if (freeAdmissionVoucher.voucherData[voucherCodeId] === undefined) {
308				continue;
309			}
310			freeAdmissionVoucher.voucherData[voucherCodeId].status = 'in_cart';
311		}
312	} // End setAsInCart()
313
314};

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.