PageSourceSearch

https://www.lidocinemas.com.au/js/layout.js?v=5iStmC-NL3lOK9YqagmrJFVy6kFnbSkDaaujDSbZmDE

js lidocinemas.com.au collected 2026-10-03 21:18:38 UTC 14,371 bytes, 639 lines download raw bytes

1// Layout
2window.layout = {
3
4	// Load
5	load: function (url, data, callback) {
6
7		// Variables
8		var response = null,
9			ready = null,
10			complete = function () {
11				if (ready && response) {
12					$('html').removeClass('ToggleLoading');
13					if (callback) {
14						callback(response);
15					}
16				}
17			};
18
19		// Class
20		$('html').addClass('ToggleLoading');
21
22		// Ajax
23		$.ajax({
24			type: 'POST',
25			url: url,
26			data: data,
27			cache: false,
28			contentType: false,
29			processData: false,
30			timeout: 20000,
31			success: function (data) {
32				response = data;
33				complete();
34			},
35			error: function () {
36				$('html').addClass('ToggleError');
37			}
38		});
39
40		// Timeout
41		setTimeout(function () {
42			ready = true;
43			complete();
44		}, 500);
45
46	},
47
48	// Modals
49	modals: function () {
50
51		// Variables
52		var $modal = $('.Modal'),
53			$foreground = $modal.find('.Foreground');
54
55		// Close
56		$modal.on('click', '.Close, .Background', function (event) {
57			event.preventDefault();
58			$modal.hide();
59			$foreground.empty();
60		});
61
62		// Open
63		$(document).on('click', '.TriggerModal', function (event) {
64
65			if ($('html').hasClass('App')) return;
66
67			// Variables
68			var breakpoint = $(this).attr('data-disable-below') ? layout.widths[$(this).attr('data-disable-below').toLowerCase()] : 0,
69				callback = $(this).attr('data-callback');
70
71			// Check
72			if ($(window).width() > breakpoint) {
73
74				// Stop
75				event.preventDefault();
76
77				// Load
78				layout.load($(this).attr('data-href'), null, function (data) {
79					$foreground.html(data);
80					$modal.show();
81					if (callback) {
82						window.layout[callback]();
83					}
84				});
85
86			}
87
88		});
89
90	},
91
92	// Toggles
93	toggles: function () {
94
95		// Toggle
96		$(document).on('click', '.Toggle', function (event) {
97
98			// Variables
99			var $parent = $(this).attr('data-parent') ? $(this).parents($(this).attr('data-parent')) : $(this).parent(),
100				name = $(this).attr('data-class') ? 'Toggle' + $(this).attr('data-class') : 'Toggled',
101				callback = $(this).attr('data-callback');
102
103			// Stop
104			event.preventDefault();
105
106			// Toggle
107			$(this).toggleClass('Toggled');
108			$parent.toggleClass(name);
109			if (callback) {
110				window.layout[callback]();
111			}
112
113		});
114
115	},
116
117	// Search
118	search: function () {
119
120		// Variables
121		var loading = null,
122			timeout = null,
123			keyword = null,
124			$form = $('.Header > .Search'),
125			$input = $form.find('input'),
126			startTimeout = function () {
127				timeout = setTimeout(function () {
128					request();
129					timeout = null;
130				}, 500);
131			},
132			stopTimeout = function () {
133				clearTimeout(timeout);
134				timeout = null;
135			},
136			request = function () {
137				if (!loading && keyword !== $.trim($input.val())) {
138					loading = true;
139					keyword = $.trim($input.val());
140					$.ajax({
141						type: 'POST',
142						url: $form.attr('data-action'),
143						data: { 'keyword': keyword },
144						success: function (data) {
145							$form.find('.Wrapper').replaceWith($(data).filter('.Wrapper'));
146							if (timeout === null && keyword !== $.trim($input.val())) {
147								startTimeout();
148							}
149							loading = false;
150						}
151					});
152				}
153			};
154
155		// Submit
156		$form.on('submit', function (event) {
157			event.preventDefault();
158		});
159
160		// Key Up
161		$input.on('keyup', function (event) {
162			stopTimeout();
163			if (event.which === 13 || event.which === 32) {
164				request();
165			} else {
166				startTimeout();
167			}
168		});
169
170	},
171
172	// Sub Menu
173	subMenu: function () {
174
175		// Variables
176		var $subMenu = $('.Header .SubMenu'), swiper;
177
178		// Swiper
179		if ($subMenu.length) {
180			swiper = new Swiper($('.Header .SubMenu .swiper-container'), {
181				slidesPerView: 'auto',
182				watchOverflow: true,
183				freeMode: true
184			});
185		}
186
187	},
188
189	loggedInStatus: function () {
190			const signOutLink = document.getElementById("signOutLink");
191			const memberKey = "movingstory.member";
192
193			if (signOutLink) {
194				signOutLink.addEventListener("click", function (event) {
195					event.preventDefault(); // Prevent immediate navigation
196					sessionStorage.removeItem(memberKey); // Remove sessionStorage key
197
198					// After removing, navigate to the logout page
199					window.location.href = "/logout";
200				});
201			}
202
203			function isLoggedIn() {
204				const memberData = sessionStorage.getItem(memberKey);
205				return memberData && memberData !== "{}";
206			}
207			async function fetchMemberData() {
208				try {
209					const response = await fetch("/api/member");
210					const data = await response.json();
211					sessionStorage.setItem(memberKey, JSON.stringify(data));
212					return data;
213				} catch (error) {
214					console.error("Error fetching member data:", error);
215				}
216			}
217			function toggleHeader() {
218				if (isLoggedIn()) {
219					document.querySelector('.Header .Buttons')?.classList.add('authenticated');
220					const signInElement = document.querySelector('.Drawer .SignIn');
221					if (signInElement) {
222						signInElement.textContent = 'My Account';
223					}
224				} else {
225					document.querySelector('.Header .Buttons')?.classList.remove('authenticated');
226					const signInElement = document.querySelector('.Drawer .SignIn');
227					if (signInElement) {
228						signInElement.textContent = 'Club Sign In';
229					}
230				}
231			}
232			async function init() {
233				let memberData = sessionStorage.getItem(memberKey);
234				if (!memberData) {
235					await fetchMemberData();
236				}
237				toggleHeader();
238			}
239			init();
240	},
241
242	// Homepage Featured Video 
243	features: function () {
244
245		// Variables
246		var $features = $('.Features'),
247			$videos = $features.find('video'),
248			swiper,
249			activeIndex = 0;
250
251		// Function to load video by index
252		var loadVideo = function (index) {
253
254			// Variables
255			var $this = $videos.eq(index),
256				request = new XMLHttpRequest();
257
258			// Check if the video element exists and isn't already loaded
259			if ($this.length && !$this.hasClass('Loaded')) {
260
261				// Load the video
262				request.onload = function () {
263					if (this.status === 200) {
264						$this.attr('src', URL.createObjectURL(this.response));
265						setTimeout(function () {
266							$this.addClass('Loaded'); // Mark as loaded
267							if (index === activeIndex) {  // Play only the current active video
268								$this.get(0).play();
269							}
270						}, 2000);
271					}
272				};
273
274				request.open('GET', $this.attr('data-src'), true);
275				request.responseType = 'blob';
276				request.send();
277			}
278		};
279
280		if ($features.length) {
281			chook.lazyloader($features, function () {
282				// Initialize Swiper
283				swiper = new Swiper($features.find('.swiper-container'), {
284					navigation: {
285						nextEl: $features.find('.swiper-button-next'),
286						prevEl: $features.find('.swiper-button-prev'),
287					},
288					pagination: {
289						el: $features.find('.swiper-pagination'),
290						clickable: true
291					},
292					on: {
293						slideChange: function () {
294							// Pause the currently active video when the slide changes
295							$features.find('.swiper-slide-active video').get(0).pause();
296						},
297						slideChangeTransitionEnd: function () {
298							// Update activeIndex
299							activeIndex = swiper.activeIndex;
300
301							// Load and play the current active slide's video
302							$features.find('.swiper-slide-active video').get(0).play();
303
304							// Load the current slide's video and preload the next slide's video
305							loadVideo(activeIndex);
306							loadVideo(activeIndex + 1);
307						}
308					},
309					autoplay: {
310						delay: 20000,
311					},
312					speed: 500,
313					watchOverflow: true,
314					roundLengths: true
315				});
316
317			}, function () {
318				loadVideo(0);
319				window.setTimeout(function () {
320					loadVideo(1);
321				}, 4000);
322			});
323		}
324
325	},
326
327	// Swipers
328	swipers: function () {
329
330		function sizeFilters($filters, slides) {
331
332			$filters.removeClass('scrollable').css('width', '');
333
334			var available = $filters.parent().width();
335
336			//get total width of all slides
337			var totalWidth = 100;
338			slides.each(function () {
339				totalWidth += $(this).outerWidth();
340			});
341
342			if (totalWidth < 1440) {
343				$filters.width(Math.min(totalWidth, available));
344			} else {
345				$filters.addClass('scrollable');
346			}
347		}
348
349		function filterSlides($swiper) {
350			return $swiper.children('.swiper-container').children('.swiper-wrapper').children('.swiper-slide');
351		}
352
353		function intialiseSwiper() {
354			$('.Filters > .swiper').each(function () {
355
356				// Variables
357				var $swiper = $(this),
358					breakpoints = {},
359					swiper;
360
361				// Breakpoint
362				breakpoints[layout.widths.tablet + layout.widths.scrollbar] = {
363					slidesPerGroup: 2
364				};
365
366				sizeFilters($swiper.closest('.Filters'), filterSlides($swiper));
367
368				// Swiper
369				swiper = new Swiper($swiper.children('.swiper-container'), {
370					pagination: {
371						el: $swiper.children('.swiper-pagination'),
372						clickable: true
373					},
374					slidesPerView: 'auto',
375					slidesPerGroup: 3,
376					watchOverflow: true,
377					roundLengths: true,
378					freeMode: true,
379					navigation: {
380						nextEl: $swiper.children('.swiper-button-next'),
381						prevEl: $swiper.children('.swiper-button-prev'),
382					},
383					breakpoints: breakpoints
384				});
385
386			});
387		}
388
389		function debounce(func, wait) {
390			let timeout;
391			return function () {
392				const context = this, args = arguments;
393				clearTimeout(timeout);
394				timeout = setTimeout(() => func.apply(context, args), wait);
395			};
396		}
397
398		intialiseSwiper();
399
400		$(window).resize(debounce(function () {
401			$('.Filters > .swiper').each(function () {
402				var $swiper = $(this),
403					container = $swiper.children('.swiper-container')[0],
404					swiper = container && container.swiper;
405
406				sizeFilters($swiper.closest('.Filters'), filterSlides($swiper));
407
408				if (swiper && !swiper.destroyed) {
409					swiper.update();
410					swiper.navigation.update();
411				}
412			});
413		}, 250));
414
415		// Loop
416		$('.Widget > .Boundary > .swiper').each(function () {
417
418			// Variables
419			var breakpoints = {},
420				swiper;
421
422			// Breakpoint
423			breakpoints[layout.widths.tablet + layout.widths.scrollbar] = {
424				slidesPerGroup: 2
425			};
426
427			// Swiper
428			swiper = new Swiper($(this).children('.swiper-container'), {
429				pagination: {
430					el: $(this).children('.swiper-pagination'),
431					clickable: true
432				},
433				slidesPerView: 'auto',
434				slidesPerGroup: 3,
435				watchOverflow: true,
436				roundLengths: true,
437				freeMode: true,
438				breakpoints: breakpoints
439			});
440
441		});
442
443	},
444
445	// Feeds
446	feeds: function () {
447
448		// Load
449		WebFont.load({
450			custom: {
451				families: [layout.fonts.bold, layout.fonts.regular]
452			},
453			classes: false
454		});
455
456	},
457
458	// https://stackoverflow.com/questions/27078285/simple-throttle-in-js/27078401
459	// Returns a function, that, when invoked, will only be triggered at most once
460	// during a given window of time. Normally, the throttled function will run
461	// as much as it can, without ever going more than once per `wait` duration;
462	// but if you'd like to disable the execution on the leading edge, pass
463	// `{leading: false}`. To disable execution on the trailing edge, ditto.
464	throttle: function (func, wait, options) {
465		var context, args, result;
466		var timeout = null;
467		var previous = 0;
468		if (!options) options = {};
469		var later = function () {
470			previous = options.leading === false ? 0 : Date.now();
471			timeout = null;
472			result = func.apply(context, args);
473			if (!timeout) context = args = null;
474		};
475		return function () {
476			var now = Date.now();
477			if (!previous && options.leading === false) previous = now;
478			var remaining = wait - (now - previous);
479			context = this;
480			args = arguments;
481			if (remaining <= 0 || remaining > wait) {
482				if (timeout) {
483					clearTimeout(timeout);
484					timeout = null;
485				}
486				previous = now;
487				result = func.apply(context, args);
488				if (!timeout) context = args = null;
489			} else if (!timeout && options.trailing !== false) {
490				timeout = setTimeout(later, remaining);
491			}
492			return result;
493		};
494	},
495
496	// Tickets
497	tickets: function () {
498
499		// Tickets
500		$('.Tickets').each(function () {
501
502			// Variables
503			var $this = $(this),
504				$days = $this.find('.swiper a'),
505				$sessions = $this.find('.Sessions'),
506				swiper;
507
508			// Days
509			$days.click(function (event) {
510				event.preventDefault();
511				$sessions.addClass('Hidden').eq($days.index($(this))).removeClass('Hidden');
512				$days.removeClass('Selected');
513				$(this).addClass('Selected');
514			});
515
516			// Swiper
517			swiper = new Swiper($this.find('.swiper-container'), {
518				navigation: {
519					nextEl: $this.find('.swiper-button-next'),
520					prevEl: $this.find('.swiper-button-prev'),
521				},
522				slidesPerView: 'auto',
523				watchOverflow: true,
524				freeMode: true
525			});
526
527			// Resize
528			$(window).resize(function () {
529				try {
530					swiper.update();
531				}
532				catch (e) {
533				}
534			});
535
536		});
537
538	},
539
540	// Filters
541	filters: function () {
542
543		// Variables
544		var $filters = $('.Filters'),
545			$links = $filters.find('a'),
546			swiper;
547
548		// Links
549		$links.click(function (event) {
550			event.preventDefault();
551			$links.removeClass('Selected');
552			$(this).addClass('Selected');
553			$.ajax({
554				type: 'GET',
555				url: $(this).attr('href'),
556				success: function (data) {
557					$('.Movies').replaceWith($(data).find('.Movies'));
558
559					// if in app via iframe trigger resize
560					if (window.top !== window.self) {
561						if (app && app.watchImages) app.watchImages();
562						$(window).trigger('resize');
563					}
564				}
565			});
566		});
567	},
568
569	// Gallery
570	gallery: function () {
571
572		// Variables
573		var swiper;
574
575		// Swiper
576		swiper = new Swiper($('.Gallery .swiper-container'), {
577			slidesPerView: 'auto',
578			watchOverflow: true,
579			freeMode: true
580		});
581
582	},
583
584	// Media
585	media: function () {
586
587		// Variables
588		var $media = $('.Modal .Media'),
589			$trigger = $('.TriggerModal[data-id="' + $media.attr('data-id') + '"]'),
590			$triggers = $trigger.parents('.Gallery').find('.TriggerModal');
591
592		// Check
593		if ($triggers.length) {
594			$media.find('.Arrow').removeClass('Hidden');
595		}
596
597		// Click
598		$media.find('.Arrow').click(function (event) {
599			var index = $triggers.index($trigger);
600			event.preventDefault();
601			if ($(this).hasClass('Previous')) {
602				index = index - 1 >= 0 ? index - 1 : $triggers.length - 1;
603			} else {
604				index = index + 1 < $triggers.length ? index + 1 : 0;
605			}
606			$media.find('.Close').click();
607			$triggers.eq(index).click();
608		});
609
610	},
611
612	shop: function () {
613		// Show Cart
614		$('.Header .Shop .Trigger').click(function (event) {
615			event.preventDefault();
616		});
617	},
618
619	// Master
620	master: function () {
621
622		// Modals
623		layout.modals();
624
625		// Toggles
626		layout.toggles();
627
628		// Header logged in status
629		layout.loggedInStatus();
630
631		// Search
632		layout.search();
633
634		// Sub Menu
635		layout.subMenu();
636
637	}
638
639};

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.