PageSourceSearch

https://www.movietimetv.ca/wp-content/plugins/corus-wpp-adobe-anal…/frontend/adobe_analytics.js?ver=0.0.1

js movietimetv.ca collected 2026-10-02 13:11:28 UTC 14,643 bytes, 415 lines download raw bytes

1window.codexData = window.codexData || {};
2let headerNavigation = false;
3let headerNavigationFragment = '';
4const oldViewName = window.codexData.view.name;
5
6function satelliteTrack(scrollViewTrack = false) {
7	// eslint-disable-next-line no-underscore-dangle
8	if (typeof window._satellite !== 'undefined') {
9		// eslint-disable-next-line no-underscore-dangle
10		let copyCodexData = Object.assign({}, codexData);
11		if( scrollViewTrack ) {
12			copyCodexData.content = {};
13		}
14		const data = window._satellite.track('track', copyCodexData);
15	}
16}
17
18/**
19 * Does the element `el` have at least one of the CSS classnames in `classNames`?
20 * @param {Element} el Element to test for the presence of at least one of the CSS classnames in `classList`.
21 * @param {Array<string>} [classNames=[]] CSS classnames to test against.
22 * @returns {boolean} `false` if `classNames` is empty; otherwise whether or not `el` contains one of `classNames` in its `classList`.
23 */
24function elementHasSomeClassName(el, classNames = []) {
25	return classNames.some(className => el.classList.contains(className));
26}
27
28/**
29 * Handle carousel button click event.
30 * @param {HTMLElement} [slickElement=null]
31 */
32function carouselClickEvent(slickElement = null) {
33	if (window.codexData) {
34		let slickIdentify = '';
35		let slickArrowParentId = '';
36		let slickArrowParentIdName = '';
37		let pageName = '';
38
39		if (window.location.pathname === '/') {
40			pageName = 'home';
41		}
42
43		if (slickElement) {
44			delete codexData.flow;
45	
46			const { flowComplete, flowStep, login, ...restEvents } = codexData.events;
47
48			codexData.events = restEvents;
49
50			const slickArrowElementClass = slickElement.className.split(' ');
51
52			slickArrowParentId = slickElement.closest('section');
53
54			if (slickArrowParentId) {
55				const { name = '' }  = slickArrowParentId.dataset.analytics ? JSON.parse(slickArrowParentId.dataset.analytics) : {};
56				slickArrowParentIdName = name != '' ? ':' + name : '';
57			}
58
59			if (
60				slickElement.dataset?.carouselArrow?.toLowerCase() === 'next'
61				|| elementHasSomeClassName(slickElement, ['slick-next', 'rotator-next-btn'])
62			) {
63				slickIdentify = 'next';
64			} else if (
65				slickElement.dataset?.carouselArrow?.toLowerCase() === 'prev'
66				|| elementHasSomeClassName(slickElement, ['slick-prev', 'rotator-prev-btn'])
67			) {
68				slickIdentify = 'previous';
69			}
70		}
71
72		window.codexData.content = {};
73		window.codexData.events.interaction = true;
74		window.codexData.events.view = false;
75
76		pageOrViewName = pageName ? ':' + pageName : ':' + oldViewName;
77
78		window.codexData.interaction = {
79			name: (`${window.codexData.app.name}${pageOrViewName}${slickArrowParentIdName}:carousel-${slickIdentify}`),
80		};
81
82		delete window.codexData.view;
83
84		satelliteTrack();
85	}
86}
87
88function getRandomAlphanumericAsciiCharacter() {
89	const CHARACTER_RANGE = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
90
91	const randomIndex = Math.floor(Math.random() * CHARACTER_RANGE.length);
92
93	return CHARACTER_RANGE[randomIndex];
94}
95
96function getRandomAlphanumericAsciiId(length) {
97	if (!(length > 0)) {
98		throw new Error('getRandomAlphanumericAsciiId must be called with a non-zero positive length');
99	}
100
101	const id = Array(length)
102		.fill('')
103		.map(() => getRandomAlphanumericAsciiCharacter());
104
105	return id.join('');
106}
107
108function createSerializationId(idPrefix, id, timeMs) {
109	return `${idPrefix}${id}${timeMs}`;
110}
111
112/**
113 * @summary Use this function as a hook for successful newsletter signups.
114 * Call this function where you know the signup is successful, and it will take care of the analytics fields.
115 * @param {string} [flowName] Optionally override `flow.name`; otherwise will use default of `${app.name}-newsletter-signup`
116 * @returns {void}
117 */
118function handleSuccessMessageAnalytics(flowName = null) {
119	if (window.codexData) {
120		// Get the app name from the codexData object, otherwise use `'corus'` as a default.
121		const namePrefix = window?.codexData?.app?.name ?? 'corus';
122
123		// Get the 2-letter app ID from the codexData object, otherwise use `'CE'` as a default.
124		const idPrefix = window?.codexData?.misc?.serializationIdPrefix ?? 'CE';
125
126		const oldCodexData = window.codexData;
127
128		const flowNameText = flowName ? flowName : `${namePrefix}-newsletter-signup`;
129
130		const newCodexData = {
131			...oldCodexData,
132			events: {
133				flowComplete: true,
134				flowStep: true,
135				newsletterSignup: true,
136				view: false, // newsletter signup is not a page view
137			},
138			flow: {
139				name: flowNameText,
140				serializationid: createSerializationId(
141					idPrefix,
142					getRandomAlphanumericAsciiId(4),
143					Date.now(),
144				),
145				stepName: 'complete',
146			},
147		};
148
149		window.codexData = newCodexData;
150
151		satelliteTrack();
152	}
153}
154
155if (window.codexData) {
156	// Trigger analytics for anchor links, buttons, or input or option elements when they have a 'data-analytics' attribute
157	const navOrBtnItems = document.querySelectorAll('a[data-analytics], button[data-analytics], input[data-analytics], option[data-analytics]');
158	let navOrBtnItemName = '';
159
160	navOrBtnItems.forEach((navOrBtnItem) => {
161		const { position = '', name = '', module = '', destination = '' } = JSON.parse(navOrBtnItem.dataset.analytics);
162
163		// By default first click should expand accordion
164		let expand = true;
165
166		navOrBtnItem.addEventListener('click', () => {
167			const { href: url = '' } = navOrBtnItem;
168			const [, fragmentUrl] = url.split('#');
169			if (fragmentUrl) {
170				headerNavigation = true;
171				headerNavigationFragment = fragmentUrl;
172			}
173			window.codexData.events = window.codexData.events || {};
174			window.codexData.content = {};
175			window.codexData.events.interaction = true;
176			window.codexData.events.view = false;
177			let pageName = '';
178			if (window.location.pathname === '/') {
179				pageName = 'home';
180			}
181			
182			sectionNavOrBtnItem = navOrBtnItem.closest('section');
183			if (sectionNavOrBtnItem) {
184				const { name = '' }  = sectionNavOrBtnItem.dataset.analytics ? JSON.parse(sectionNavOrBtnItem.dataset.analytics) : {};
185				navOrBtnItemName = name != '' ? ':' + name : '';
186			}
187
188			pageOrViewName = pageName ? ':' + pageName : ':' + oldViewName;
189
190			if (module) {
191				if (module == 'share') {
192					window.codexData.content = {};
193					window.codexData.events.share = true;
194					window.codexData.share = {type : name};
195					window.codexData.interaction = {
196						name: (`${window.codexData.app.name}:${pageOrViewName}${navOrBtnItemName}:${module}`).replace(/(\W)\W*/g, '$1'),
197					};
198					delete window.codexData.view;
199				}
200
201				if (module == 'faq') {
202					window.codexData.content = {};
203					let expandOrCollapse = expand ? 'expand' : 'collapse';
204					if(expandOrCollapse == 'expand') {
205						window.codexData.interaction = {
206							name: (`${window.codexData.app.name}:${pageOrViewName}${navOrBtnItemName}:${module}:${name}:${expandOrCollapse}`).replace(/(\W)\W*/g, '$1'),
207						};
208
209						// after expand, next on click event should collapse the accordion
210						expand = false;
211					} else {
212						delete window.codexData.events.interaction;
213						delete window.codexData.interaction;
214
215						expand = true;
216						return;
217					}
218
219					delete window.codexData.view;
220				}
221
222				/**
223				 * Set data layer fields for items that direct users to external sites and applications.
224				 * Use the `destination` property to indicate where the user is going using a slug.
225				 * For example, `apple-podcasts`, `spotify`, etc.
226				 */
227				if (module === 'exit-link' && destination) {
228					window.codexData.content = {};
229
230					const interactionName = (
231						`${window.codexData.app.name}:${pageOrViewName}${navOrBtnItemName}:${module}:${destination}`
232					).replace(/(\W)\W*/g, '$1');
233
234					window.codexData.interaction = {
235						name: interactionName,
236					};
237
238					delete window.codexData.view;
239				}
240			} else {
241				const positionName = position ? ':' + position : ':';
242				window.codexData.content = {};
243				window.codexData.interaction = {
244					name: (`${window.codexData.app.name}:${pageOrViewName}${navOrBtnItemName}${positionName}:${name}`).replace(/(\W)\W*/g, '$1'),
245				};
246				delete window.codexData.view;
247			}
248
249			satelliteTrack();
250		});
251	});
252
253	//==================================================================================================================//
254	// NEWSLETTER PAGE FORM INITIAL FLOW SERIALIZATION ID                                                               //
255	//==================================================================================================================//
256
257	// If this is the Newsletter Page
258	if (window.codexData.content.type === 'page' && window.codexData.content.title.toLowerCase().includes('newsletter')) {
259		/** @type {NodeListOf<HTMLFormElement>} */
260		const newsletterForms = document.querySelectorAll('form.newsletter-form');
261
262		/**
263		 * Create the initial newsletter flow serialization ID.
264		 */
265		if (newsletterForms.length > 0) {
266			// Get the 2-letter app ID from the codexData object, otherwise use `'CE'` as a default.
267			const idPrefix = window?.codexData?.misc?.serializationIdPrefix ?? 'CE';
268
269			// Ensure codexData.flow is defined.
270			window.codexData.flow = window.codexData.flow || {};
271
272			// Set the flow serialization ID, using the user's current client-side time in ms.
273			window.codexData.flow.serializationid = createSerializationId(
274				idPrefix,
275				getRandomAlphanumericAsciiId(4),
276				Date.now()
277			);
278		}
279	}
280
281	//==================================================================================================================//
282	// END NEWSLETTER PAGE FORM INITIAL FLOW SERIALIZATION ID                                                           //
283	//==================================================================================================================//
284
285	// Trigger page views on scroll when section has
286	// 'data-analytics' and 'data-analytics-view' attributes
287	(() => {
288		let ticking = false;
289		function triggerAnalytics() {
290			ticking = false;
291			const elements = document.querySelectorAll('section[data-analytics][data-analytics-view=false]');
292
293			elements.forEach((element) => {
294				const elementTop = element.getBoundingClientRect().top;
295				const elementBottom = element.getBoundingClientRect().bottom;
296				const windowHeight = window.innerHeight;
297
298				if (elementTop < windowHeight && windowHeight < elementBottom) {
299					const sectionID = element.getAttribute('id');
300
301					if (sectionID && headerNavigation) {
302						if (sectionID === headerNavigationFragment) {
303							headerNavigation = false;
304						} else {
305							return;
306						}
307					}
308
309					window.codexData = window.codexData || {};
310					window.codexData.view.type = 'section';
311
312					const dataAnalytics = JSON.parse(element.dataset.analytics);
313
314					window.codexData.view.name = dataAnalytics.name;
315					
316					window.codexData.events.view = true;
317					window.codexData.events.interaction = false;
318
319					if( typeof(window.overrideCodexDataConfig) === 'function' ) {
320						window.codexData = window.overrideCodexDataConfig(window.codexData);
321					}
322
323					satelliteTrack(true);
324					element.setAttribute('data-analytics-view', true);
325				}
326			});
327		}
328
329		/**
330		 * For Slick Slider ( Carousel ) arrow button click ( Next / Previous )
331		 *
332		 * The arrow buttons should have one of the following to indicate it is a next / previous button:
333		 * - a `data-carousel-arrow` attribute. Direction then depends on attribute value being `next` or `prev`.
334		 * - a classlist including `slick-arrow`. Direction then depends on including a `slick-(next/prev)` class.
335		 * - a classlist including `rotator-arrow`. Direction then depends on including a `rotator-(next/prev)-btn` class.
336		 *
337		 * Additionally, the buttons should NOT have a classlist including `fullSchedule-arrow` or `gallery-next`.
338		 *
339		 * @param {MouseEvent} event
340		 */
341		function handleCarouselClick(event) {
342			const slickArrowElement = event.target;
343
344			const hasCarouselArrowDatasetOrClassNames = (
345				slickArrowElement.dataset?.carouselArrow /* data-carousel-arrrow */
346				|| elementHasSomeClassName(slickArrowElement, ['slick-arrow', 'rotator-arrow'])
347			);
348
349			if (
350				hasCarouselArrowDatasetOrClassNames
351				&& !slickArrowElement.classList.contains('fullSchedule-arrow')
352			) {
353				if (!slickArrowElement.classList.contains('gallery-next')) {
354					carouselClickEvent(slickArrowElement, true);
355				}
356			}
357		}
358
359		document.addEventListener('click', handleCarouselClick);
360
361		function loadRequest() {
362			// eslint-disable-next-line no-underscore-dangle
363			if (window._satellite !== 'undefined') {
364				ticking = ticking || requestAnimationFrame(triggerAnalytics);
365			}
366		}
367
368		window.addEventListener('scroll', loadRequest, false);
369	})();
370
371	//==================================================================================================================//
372	// LIGHT / DARK MODE THEME TOGGLE                                                                                   //
373	//==================================================================================================================//
374	// Set data layer field for the state of the dark / light mode theme toggle,
375	// otherwise the browser / device theme preference.
376	// Field is of the form `{dark|light}:{system|user}`
377
378	/**
379	 * Get the value of the `user_chosen_theme` cookie and verify it is either `'dark'` or `'light'`.
380	 * Returns `undefined` if cookie does not exist or does not contain `'dark'` or `'light'`.
381	 * @returns {'dark' | 'light' | undefined}
382	 */
383	const getUserChosenThemeCookieValue = () => {
384		// Adapated from MDN example.
385		const cookieValue = document.cookie
386			.split('; ')
387			.find((row) => row.startsWith('user_chosen_theme='))
388			?.split('=')[1];
389	
390		// Guard against unknown values
391		if (['dark', 'light'].includes(cookieValue)) {
392			return cookieValue;
393		}
394
395		return undefined;
396	};
397
398	// Just in case
399	window.codexData.view = window.codexData.view || {};
400
401	const userChosenThemeCookieValue = getUserChosenThemeCookieValue();
402
403	if (userChosenThemeCookieValue) {
404		window.codexData.view.appearance = `${userChosenThemeCookieValue}:user`;
405	} else {
406		// Note that `light` could also indicate no preference / use browser or device settings
407		const isBrowserOrSystemDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
408
409		window.codexData.view.appearance = `${isBrowserOrSystemDarkMode ? 'dark' : 'light'}:system`;
410	}
411
412	//==================================================================================================================//
413	// END LIGHT / DARK MODE THEME TOGGLE                                                                               //
414	//==================================================================================================================//
415}

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.