PageSourceSearch

https://marli.de/javascript/cookie_consent/frontend/src/cookiebanner.js?r=1682074266

js marli.de collected 2026-10-04 13:32:07 UTC 27,685 bytes, 871 lines download raw bytes

1/**
2 ▄█       ▄██   ▄    ▄████████  ▄██████▄   ▄██████▄     ▄█   ▄█▄  ▄█     ▄████████
3███       ███   ██▄ ███    ███ ███    ███ ███    ███   ███ ▄███▀ ███    ███    ███
4███       ███▄▄▄███ ███    █▀  ███    ███ ███    ███   ███▐██▀   ███▌   ███    █▀
5███       ▀▀▀▀▀▀███ ███        ███    ███ ███    ███  ▄█████▀    ███▌  ▄███▄▄▄
6███       ▄██   ███ ███        ███    ███ ███    ███ ▀▀█████▄    ███▌ ▀▀███▀▀▀
7███       ███   ███ ███    █▄  ███    ███ ███    ███   ███▐██▄   ███    ███    █▄
8███▌    ▄ ███   ███ ███    ███ ███    ███ ███    ███   ███ ▀███▄ ███    ███    ███
9█████▄▄██  ▀█████▀  ████████▀   ▀██████▀   ▀██████▀    ███   ▀█▀ █▀     ██████████
10▀                                                      ▀
11
12Copyright 2020 - LYNET Kommunikation AG
13lharm, nkaut, mgrabau
14*/
15
16/**
17┌─┐┌─┐┌┬┐┬ ┬┌─┐
18└─┐├┤  │ │ │├─┘
19└─┘└─┘ ┴ └─┘┴
20*/
21
22// globals
23var settings = null;
24var translations = null;
25
26// determine document root path
27var script = document.getElementById("lycookie_script").src.split("?").shift();
28var scriptPath = script.replace("/cookiebanner.min.js", "");
29var scriptPath = scriptPath.replace("/cookiebanner.js", "");
30var scriptPath = scriptPath.replace("/src", "");
31var documentRoot = scriptPath.replace("/frontend", "");
32
33// utility paths
34var frontendRoot = documentRoot + "/frontend/";
35var backendRoot = documentRoot + "/backend/";
36var resourceRoot = documentRoot + "/resources/";
37
38loadJSON(resourceRoot + "config.json", function (response) {
39	loadConfig(response);
40	loadJSON(resourceRoot + "translations.json", function (response) {
41		loadTranslations(response);
42		loadJQuery();
43	})
44});
45
46function loadConfig(settingsData) {
47	settings = JSON.parse(settingsData);
48}
49
50function loadTranslations(translationData) {
51	translations = JSON.parse(translationData);
52}
53
54function loadJQuery() {
55	if (settings.initOptions.loadJQuery) {
56		var jquery_script = document.createElement('script');
57		document.head.appendChild(jquery_script);
58		jquery_script.type = 'text/javascript';
59		jquery_script.src = documentRoot + settings.paths.jQuery;
60		jquery_script.onload = init;
61	} else {
62		init();
63	}
64}
65
66/**
67┌─┐┬ ┬┌┐┌┌─┐┌┬┐┬┌─┐┌┐┌┌─┐
68├┤ │ │││││   │ ││ ││││└─┐
69└  └─┘┘└┘└─┘ ┴ ┴└─┘┘└┘└─┘
70*/
71
72function init() {
73	if (!settings.misc.forceLocal) {
74		// detect user local
75		userLocal = detectLanguage();
76
77		// check if local has translations
78		if (checkLanguageAvailable(userLocal)) {
79			settings.misc.local = userLocal
80		}
81	}
82
83	// set jQuery to no conflict
84	lyQuery = $.noConflict(true);
85
86	// build DOM
87	buildCookieBanner();
88
89	// visibility check
90	if (getCookie('lycookie')) {
91		// if lycookie is set and shown is set, hide banner
92		var lycookie = JSON.parse(getCookie('lycookie'));
93		if (typeof lycookie.shown !== 'undefined') {
94			hideBanner();
95			sectionHandler();
96		}
97	} else if (isUrlIgnored()) {
98		// if url contains ignored word, hide banner
99		hideBanner();
100		sectionHandler();
101	}
102}
103
104// create html markup for cookiebanner
105function buildCookieBanner() {
106	// create overlay element and appends to body
107	var overlay = lyQuery('<div></div>');
108	lyQuery(overlay).addClass('lynet_cookie_overlay lynet_cookie_is_open')
109		.appendTo(lyQuery('body'));
110
111	// create overlay toggle
112	if (settings.visual.overlayToggle) {
113		var overlayToggle = lyQuery('<button></button>');
114		lyQuery(overlayToggle).addClass('lynet_cookie_overlay_toggle lynet_cookie_banner_hide')
115			.text(translate('overlay_button'))
116			.click(function () {
117				showBanner();
118			})
119			.appendTo(lyQuery('body'));
120	}
121
122	lyQuery('.lynet_cookie_trigger').click(
123		function () {
124			showBanner();
125		});
126
127	// add class to body
128	lyQuery('body').addClass('lynet_cookie_overlayed');
129
130	// create container element and appends to overlay
131	var container = lyQuery('<div></div>');
132	lyQuery(container).addClass('lynet_cookie_container')
133		.appendTo(lyQuery(overlay));
134
135	var banner = lyQuery('<div></div>');
136	lyQuery(banner).addClass('lynet_cookie_wrapper')
137		.appendTo(lyQuery(container));
138
139	// create bannerHead
140	var bannerHead = lyQuery('<div></div>');
141	lyQuery(bannerHead).addClass('lynet_cookie_banner_head')
142		.appendTo(lyQuery(banner));
143
144	var headline = lyQuery('<h2></h2>');
145	lyQuery(headline).text(translate('headline'))
146		.appendTo(lyQuery(bannerHead));
147
148	// remove logo from headline if set
149	if (!settings.visual.logo) {
150		lyQuery(headline).css("background", "unset");
151	}
152
153	var headlineText = lyQuery('<p></p>');
154	lyQuery(headlineText).text(translate('headline_text'))
155		.appendTo(lyQuery(bannerHead));
156
157	var bannerHeadLinks = lyQuery('<div></div>');
158	lyQuery(bannerHeadLinks).addClass('lynet_cookie_banner_head_links')
159		.appendTo(lyQuery(bannerHead));
160
161	var bannerHeadLink1 = lyQuery('<a></a>');
162	lyQuery(bannerHeadLink1).text(translate('headline_link_1_text'))
163		.attr('href', translate('headline_link_1_link'))
164		.appendTo(lyQuery(bannerHeadLinks));
165
166	var bannerHeadLink2 = lyQuery('<a></a>');
167	lyQuery(bannerHeadLink2).text(translate('headline_link_2_text'))
168		.attr('href', translate('headline_link_2_link'))
169		.appendTo(lyQuery(bannerHeadLinks));
170
171	var bannerHeadLink3 = lyQuery('<a></a>');
172	lyQuery(bannerHeadLink3).text(translate('headline_link_3_text'))
173		.attr('href', translate('headline_link_3_link'))
174		.appendTo(lyQuery(bannerHeadLinks));
175
176	// create bannerBody
177	var bannerBody = lyQuery('<div></div>');
178	lyQuery(bannerBody).addClass('lynet_cookie_banner_body')
179		.addClass('parent')
180		.appendTo(lyQuery(banner));
181
182	var list = lyQuery('<ul></ul>');
183	lyQuery(list).addClass('lynet_cookie_banner_list')
184		.appendTo(lyQuery(bannerBody));
185
186	// Essential Dropdown
187	if (settings.cookies.essential) {
188		var dropdown = generateDropdown("essential", 'list_essential', 'infotext_essential', 'link_1_text_essential', 'link_1_link_essential', true);
189		lyQuery(dropdown).appendTo(list);
190	}
191
192	// Analytics Dropdown
193	if (settings.cookies.analytics) {
194		var dropdown = generateDropdown("analytics", 'list_analytics', 'infotext_analytics', 'link_1_text_analytics', 'link_1_link_analytics', false);
195		lyQuery(dropdown).appendTo(list);
196	}
197
198	// Marketing Dropdown
199	if (settings.cookies.marketing) {
200		var dropdown = generateDropdown("marketing", "list_marketing", "infotext_marketing", "link_1_text_marketing", "link_1_link_marketing", false);
201		lyQuery(dropdown).appendTo(list);
202	}
203
204	// Embeds Dropdown
205	var embeds = settings.cookies.embeds.split(",")
206	if (embeds[0] !== "") {
207
208		var listItemEmbeds = lyQuery('<li></li>');
209		lyQuery(listItemEmbeds).addClass('lynet_cookie_banner_list_item')
210			.addClass('lynet_cookie_banner_list_item_collapsed')
211			.appendTo(lyQuery(list));
212
213		var EmbedsCheckbox = lyQuery('<input>');
214		lyQuery(EmbedsCheckbox)
215			.addClass('embeds-checkbox lynet-checkbox')
216			.attr('type', 'checkbox')
217			.attr('id', 'embeds_checkbox')
218			.attr('indeterminate', 'false')
219			.change(function () {
220				updateEmbedToggles(embeds, lyQuery(EmbedsCheckbox.prop("checked")));
221			})
222			.appendTo(lyQuery(listItemEmbeds));
223
224		var EmbedsCheckboxLabel = lyQuery('<label></label>');
225		lyQuery(EmbedsCheckboxLabel).addClass('lynet_cookie_banner_checkbox_label')
226			.text(translate('list_embeds'))
227			.attr('for', 'embeds_checkbox')
228			.appendTo(lyQuery(listItemEmbeds));
229
230		var EmbedsExpandableTrigger = lyQuery('<button></button>');
231		lyQuery(EmbedsExpandableTrigger).addClass('lynet_cookie_banner_list_item_expandable_trigger')
232			.appendTo(lyQuery(listItemEmbeds));
233
234		var EmbedsExpandableWrapper = lyQuery('<div></div>');
235		lyQuery(EmbedsExpandableWrapper).addClass('lynet_cookie_banner_list_item_expandable_wrapper embed_wrapper')
236			.appendTo(lyQuery(listItemEmbeds));
237
238		// Embed Table
239		var EmbedsTable = lyQuery('<table></table>')
240			.attr('class', 'lynet_cookie_banner_table');
241
242		embeds.forEach(function (embed) {
243			var newRow = lyQuery('<tr></tr>');
244
245			var toggleCell = lyQuery('<td></td>') // table cell for toggle switch
246				.addClass("toggle-cell");
247			var switchLabel = lyQuery("<label></label>") // switch wrapper
248				.addClass("switch")
249				.appendTo(toggleCell);
250			var switchInput = lyQuery("<input>") // switch control
251				.attr("type", "checkbox")
252				.attr("id", embed + "-toggle")
253				.change(function () {
254					updateEmbedCheckbox();
255				})
256				.appendTo(switchLabel);
257			// append styed switch based on settings
258			if (settings.visual.roundToggles) {
259				switchLabel.append('<span class="slider round"></span>');
260			} else {
261				switchLabel.append('<span class="slider"></span>');
262			}
263
264			newRow.append(toggleCell);
265			var descriptionCell = lyQuery('<td></td>') // table cell for descriptive content
266				.append('<div><span class="embed-title">' + translations[settings['misc']['local']]['embeds'][embed]['name'] + '</span><span class="embed-description"> - ' + translations[settings['misc']['local']]['embeds'][embed]['description'] + '</span></div>')
267				.append('<div class="lynet_cookie_banner_list_item_links"><a href=' + translations[settings['misc']['local']]['embeds'][embed]['policy'] + '>
267' + translate("link_embeds_policy") + '<img src="/images/cm/embeds/icon-external-link.svg"></a></div>')
268				.appendTo(newRow);
269			newRow.appendTo(EmbedsTable);
270		})
271		EmbedsTable.appendTo(EmbedsExpandableWrapper);
272
273	}
274
275	// expandable trigger
276	lyQuery('.lynet_cookie_banner_list_item_collapsed .lynet_cookie_banner_list_item_expandable_wrapper').hide();
277	lyQuery('.lynet_cookie_banner_list_item_expandable_trigger').on('click', function (event) {
278		var $trigger = lyQuery(this);
279		var $item = $trigger.parent();
280		var $wrapper = $item.find('.lynet_cookie_banner_list_item_expandable_wrapper').first();
281		if (!$wrapper.length) {
282			return;
283		}
284		var current_item_index = $item.index();
285
286		// collapse last expanded
287		lyQuery('.lynet_cookie_banner_list_item:not(.lynet_cookie_banner_list_item_collapsed)').each(function (index) {
288			var $item = lyQuery(this);
289			if ($item.index() == current_item_index) {
290				return;
291			}
292			var $wrapper = $item.find('.lynet_cookie_banner_list_item_expandable_wrapper').first();
293			if (!$wrapper.length) {
294				return;
295			}
296			$item.addClass('lynet_cookie_banner_list_item_collapsed');
297			$wrapper.stop().slideUp(240, function () {
298				$wrapper.css('height', '').css('margin', '').css('padding', '');
299				$wrapper.get(0).scrollIntoView({behavior: "smooth"});
300
301			});
302		});
303
304		// toggle current
305		$item.toggleClass('lynet_cookie_banner_list_item_collapsed');
306		$wrapper.stop().slideToggle(240, function () {
307			$wrapper.css('height', '').css('margin', '').css('padding', '');
308			$wrapper.get(0).scrollIntoView({behavior: "smooth"});
309
310		});
311	});
312
313	// buttons
314	var buttonWrapper = lyQuery('<div></div>');
315	lyQuery(buttonWrapper).addClass('lynet_cookie_button_wrapper')
316		.appendTo(lyQuery(container));
317
318	var saveAllButton = lyQuery('<button></button>');
319	lyQuery(saveAllButton).addClass('lynet_cookie_button')
320		.addClass('lynet_cookie_button_save_all')
321		.text(translate('save_all_button'))
322		.click(function () {
323			onCookieSettingsSaveAll(bannerBody);
324		})
325		.appendTo(lyQuery(buttonWrapper));
326
327	var saveButton = lyQuery('<button></button>');
328	lyQuery(saveButton).addClass('lynet_cookie_button')
329		.text(translate('save_button'))
330		.click(function () {
331			onCookieSettingsSave();
332		})
333		.appendTo(lyQuery(buttonWrapper));
334
335	lyQuery(".lycookie_embed_unlock").each(function () {
336		var parent = lyQuery(this).parents(".lycookie_placeholder");
337		lyQuery(this).click(function () {
338			onEmbedUnlock(parent);
339		})
340	})
341} // END buildCookieBanner()
342
343/**
344 * Generiert Markup zu einem Dropdown, wie er auf dem Cookie-Banner verwendet wird
345 * @param {*} name Bezeichnung des Dropdowns
346 * @param {*} labelTag Übersetzungs-Tag für angezeigten Namen des Dropdowns
347 * @param {*} infoTextTag Übersetzungs-Tag für Inhalt des Infotextes
348 * @param {*} linkTextTag Übersetzungs-Tag für Inhalt des Links
349 * @param {*} linkTag  Übersetzungs-Tag für Ziel des Links
350 * @param {*} isEssential soll die Checkbox automatisch aktiviert und gesperrt werden?
351 */
352function generateDropdown(name, labelTag, infoTextTag, linkTextTag, linkTag, isEssential) {
353	var listItem = lyQuery('<li></li>');
354	lyQuery(listItem).addClass('lynet_cookie_banner_list_item')
355		.addClass('lynet_cookie_banner_list_item_collapsed');
356
357	var checkbox = lyQuery('<input>');
358	lyQuery(checkbox)
359		.addClass(name + '-checkbox lynet-checkbox')
360		.attr('type', 'checkbox')
361		.attr('id', name + '_checkbox')
362		.appendTo(lyQuery(listItem));
363
364	if (isEssential) {
365		lyQuery(checkbox).attr('disabled', 'true')
366			.attr('checked', 'true')
367	}
368
369	var checkboxLabel = lyQuery('<label></label>');
370	lyQuery(checkboxLabel).addClass('lynet_cookie_banner_checkbox_label')
371		.text(translate(labelTag))
372		.attr('for', name + '_checkbox')
373		.appendTo(lyQuery(listItem));
374
375	var expandableTrigger = lyQuery('<button></button>');
376	lyQuery(expandableTrigger).addClass('lynet_cookie_banner_list_item_expandable_trigger')
377		.appendTo(lyQuery(listItem));
378
379	var expandableWrapper = lyQuery('<div></div>');
380	lyQuery(expandableWrapper).addClass('lynet_cookie_banner_list_item_expandable_wrapper')
381		.appendTo(lyQuery(listItem));
382
383	var infoText = lyQuery('<p></p>');
384	lyQuery(infoText).text(translate(infoTextTag))
385		.appendTo(lyQuery(expandableWrapper));
386
387	var links = lyQuery('<div></div>');
388	lyQuery(links).addClass('lynet_cookie_banner_list_item_links')
389		.appendTo(lyQuery(expandableWrapper));
390
391	var link1 = lyQuery('<a></a>');
392	lyQuery(link1).text(translate(linkTextTag))
393		.attr('href', translate(linkTag))
394		.appendTo(lyQuery(links));
395
396	return listItem;
397}
398
399/**
400 * wird ausgeführt, wenn der Nutzer den Button "Auswahl bestätigen" betätigt
401 */
402function onCookieSettingsSave() {
403	cookieHandler();
404	hideBanner();
405	location.reload();
406}
407
408/**
409 * wird ausgeführt, wenn der Nutzer den Button "Alle akzeptieren" betätigt
410 * @param {*} context Banner-Element als Referenz, um auf Children zugreifen zu können
411 */
412function onCookieSettingsSaveAll(context) {
413	var checkboxes = lyQuery(context).find('.lynet-checkbox');
414	lyQuery(checkboxes).each(function (index, checkbox) {
415		lyQuery(checkbox).prop("checked", true);
416		if (lyQuery(checkbox).attr("indeterminate") === true) {
417			lyQuery(checkbox).attr("indeterminate", false);
418		}
419	});
420
421	var embeds = settings.cookies.embeds.split(",");
422	embeds.forEach(function (key) {
423		var toggleId = "#" + key + "-toggle";
424		lyQuery(toggleId).prop("checked", true);
425	});
426
427	onCookieSettingsSave();
428}
429
430/**
431 * wird ausgeführt, wenn der Nutzer den Button "Inhalt freigeben" eines Platzhalters betätigt
432 * @param parent Platzhalter-Element
433 */
434function onEmbedUnlock(parent) {
435	var checkbox = lyQuery(parent).find("input[type=checkbox]")[0];
436	var key = lyQuery(parent).attr("data-provider-name");
437
438	if (lyQuery(checkbox).prop("checked")) {
439		// unlock all embeds for provider
440		var elements = lyQuery("[data-provider-name='" + key + "']").toArray();
441		var toggleId = "#" + key + "-toggle";
442		lyQuery(toggleId).prop("checked", true);
443		unlockAllEmbeds(elements);
444		cookieHandler();
445	} else {
446		// unlock clicked embed
447		unlockEmbed(parent)
448	}
449}
450
451/**
452 * Ersetzt den angegebenen Parent durch seinen assoziierten Embed aus dem Cache
453 * @param {*} parent zu ersetzendes Platzhalter-Element
454 */
455async function unlockEmbed(parent) {
456	return new Promise((resolve, reject) => {
457		var id = lyQuery(parent).attr("data-content-id");
458		var key = lyQuery(parent).attr("data-provider-name");
459		var error = null;
460
461		if (id) {
462			lyQuery.when(
463				lyQuery.get("/cache/embeds/" + id + ".html"),
464				lyQuery.get(resourceRoot + "/embeds/" + key + ".json")
465			).fail(function() {
466				error = `LyCookie: Error loading embed from provider "${key}" with id "${id}". Is the cache directory readable and not being rerouted?`
467				console.error(error)
468			}).then(async function (cachedElement, embedConfig) {
469				cachedElement = cachedElement[0] // extract response content for readability
470				embedConfig = embedConfig[0]
471				// replace placeholder with element from cache
472				lyQuery(parent).replaceWith(cachedElement);
473				// if an additional script is defined in provider config, load it
474				if (embedConfig.additional_script) {
475					await loadEmbedScript(key, embedConfig.additional_script, embedConfig.unlock_function);
476				}
477			})
478		} else {
479			error = `LyCookie: Error loading embed from provider "${key}". Placeholder element has no id.`
480			console.error(error)
481		}
482		// resolve Promise
483		if (error === null) {
484			resolve();
485		}
486		reject(error);
487	})
488}
489
490/**
491 * Ersetze alle gegebenen Platzhalter durch ihren assoziierten Embed aus dem Cache
492 * @param {*} parents Array aller freizuschaltenden Platzhalter
493 */
494async function unlockAllEmbeds(parents) {
495	for (parent of parents) {
496		await unlockEmbed(parent);
497	}
498}
499
500/**
501 * Lade das dem Key zugeordnete Script an den Anfang des Bodys
502 * @param {*} key Name des Providers, dessen Script geladen werden soll
503 * @param scriptUrl src-Attribut des einzusetzenden Scripts
504 * @param unlockFunction Funktion, die zum Neuladen der Einbettungen aufgerufen werden soll, falls Script bereits existiert
505 */
506function loadEmbedScript(key, scriptUrl, unlockFunction) {
507	return new Promise(resolve => {
508		var existingScript = lyQuery("script[src='" + scriptUrl + "']")[0];
509		if (scriptUrl && !existingScript) {
510			var body = lyQuery("body");
511			var script = lyQuery("<script></script>")
512				.attr("src", scriptUrl)
513				.prop("async", true)
514				.attr("id", key + "_embed_script");
515			script.prependTo(body);
516			resolve()
517		} else {
518			if (unlockFunction) {
519				executeFunctionByName(unlockFunction, window)
520				resolve()
521			}
522		}
523	})
524}
525
526function detectLanguage() {
527	// get browser local like de-DE
528	var userLang = navigator.language || navigator.userLanguage;
529
530	// break local de-DE to de
531	userLang = userLang.split('-');
532
533	// break ie
534	//userLang = userLang.split(',');
535
536	return userLang[0];
537}
538
539function checkLanguageAvailable(lang) {
540	if (typeof translations[lang] === 'undefined') {
541		return false;
542	} else {
543		return true;
544	}
545}
546
547function translate(key) {
548	var translation = "";
549	if (typeof translations[settings.misc.local][key] !== "undefined") {
550		translation = translations[settings.misc.local][key]
551	} else {
552		translation = "no translation : " + settings.misc.local + " - " + key;
553	}
554
555	return translation;
556}
557
558function capitalize(string) {
559	return string.charAt(0).toUpperCase() + string.slice(1);
560}
561
562// Banner helper functions
563
564function showBanner() {
565	lyQuery('.lynet_cookie_overlay').removeClass('lynet_cookie_banner_hide');
566
567	// add class to body
568	lyQuery('body').addClass('lynet_cookie_overlayed');
569
570	// hide overlay-toggle
571	lyQuery('.lynet_cookie_overlay_toggle').addClass('lynet_cookie_banner_hide');
572}
573
574function hideBanner() {
575	lyQuery('.lynet_cookie_overlay').addClass('lynet_cookie_banner_hide');
576
577	// remove class from body
578	lyQuery('.lynet_cookie_overlayed').removeClass('lynet_cookie_overlayed');
579
580	// show overlay-toggle
581	lyQuery('.lynet_cookie_overlay_toggle').removeClass('lynet_cookie_banner_hide');
582}
583
584// Cookie helper functions
585
586function setCookie(name, value, daysToLive, domain) {
587	domain = typeof domain === 'undefined' ? false : domain;
588	// Encode value in order to escape semicolons, commas, and whitespace
589	var cookie = name + "=" + encodeURIComponent(value);
590
591	var path = ';path=/';
592
593	if (typeof daysToLive === "number") {
594		/** Sets the max-age attribute so that the cookie expires
595		after the specified number of days */
596		cookie += "; max-age=" + (daysToLive * 24 * 60 * 60) + path + (domain !== false ? ';domain=' + domain : '');
597
598		document.cookie = cookie;
599	}
600}
601
602function getCookie(name) {
603	// Split cookie string and get all individual name=value pairs in an array
604	var cookieArr = document.cookie.split(";");
605
606	// Loop through the array elements
607	for (var i = 0; i < cookieArr.length; i++) {
608		var cookiePair = cookieArr[i].split("=");
609
610		/** Removing whitespace at the beginning of the cookie name
611		and compare it with the given string */
612		if (name == cookiePair[0].trim()) {
613			// Decode the cookie value and return
614			return decodeURIComponent(cookiePair[1]);
615		}
616	}
617
618	// Return null if not found
619	return null;
620}
621
622// deletes cookie by name
623function delete_cookie(name) {
624	document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
625}
626
627// logic
628
629// sets cookies with permission
630function cookieHandler() {
631	/**
632	 * structure of the lycookie cookie
633	 *
634	 * lycookie: Object
635	 * ├── shown: boolean
636	 * ├── analytics: boolean
637	 * └── embeds: Object
638	 *     ├── facebook: boolean
639	 *     ├── youtube: boolean
640	 *     ├── instagram: boolean
641	 *     ├── vimeo: boolean
642	 *     └── twitter: boolean
643	 */
644
645	var lycookie = new Object();
646	lycookie.shown = true;
647	lycookie.embeds = {};
648
649	// check for analytics cookie
650	if (lyQuery('.analytics-checkbox').prop('checked')) {
651		lycookie.analytics = true;
652	}
653
654	// check for marketing cookie
655	if (lyQuery('.marketing-checkbox').prop('checked')) {
656		lycookie.marketing = true;
657	}
658
659	// check for embeds checkbox
660	if (lyQuery('.embeds-checkbox').prop('checked') && (lyQuery('.embeds-checkbox').attr('indeterminate') == false)) {
661		// set all embeds to true
662		var embeds = settings.cookies.embeds.split(",")
663		embeds.forEach(function (embed) {
664			lycookie["embeds"][embed] = true;
665		});
666	} else {
667		// set only specified embeds to true
668		var embeds = settings.cookies.embeds.split(",")
669		embeds.forEach(function (embed) {
670			var embedToggle = lyQuery("#" + embed + "-toggle");
671			var state = embedToggle.prop("checked");
672			if (state) {
673				// only set value if true
674				lycookie["embeds"][embed] = state;
675			}
676		});
677	}
678
679	if(typeof(settings.forceCookieCreationdateToConfigDate) === 'undefined')
680	{
681		/*
682		var set =  new Date();
683		// add creation date
684		lycookie.creationDate = set.getDate() + "." + (set.getMonth()+1) + "." + set.getFullYear() + " " + set.getHours() + ":" + set.getMinutes() + ":" + set.getSeconds();
685		 */
686		lycookie.creationDate = settings.misc.lastChanged;
687
688
689	}
690	else
691	{
692		lycookie.creationDate = settings.misc.lastChanged;
693	}
694
695	setCookie("lycookie", JSON.stringify(lycookie), 365);
696	sectionHandler();
697}
698
699// read cookies permissions and executes scripts
700function sectionHandler() {
701	// check analytics cookie
702	var lycookie = JSON.parse(getCookie('lycookie'));
703
704	// check if cookie is set
705	if (typeof lycookie.analytics !== 'undefined') {
706		// toggle checkbox on overlay
707		lyQuery('.analytics-checkbox').prop("checked", true);
708		appendAnalyticsScript();
709	}
710
711	// check if cookie is set
712	if (typeof lycookie.marketing !== 'undefined') {
713		lyQuery('.marketing-checkbox').prop("checked", true);
714		appendMarketingScript();
715	}
716
717	// check all registered keys and update corresponding toggles
718	var registeredEmbedKeys = Object.keys(lycookie.embeds);
719	registeredEmbedKeys.forEach(function (key) {
720		var toggleId = "#" + key + "-toggle";
721		var state = lycookie["embeds"][key];
722		lyQuery(toggleId).prop("checked", state);
723		if (state) {
724			var elements = lyQuery('.' + key).toArray();
725			unlockAllEmbeds(elements);
726		}
727	})
728
729	// if all keys are registered, check embed main toggle
730	var localEmbedKeys = settings.cookies.embeds.split(",");
731	if (registeredEmbedKeys.length > 0) {
732		lyQuery('.embeds-checkbox').prop("checked", true);
733	}
734	if (localEmbedKeys.length === registeredEmbedKeys.length) {
735		lyQuery('.embeds-checkbox').attr("indeterminate", false);
736	} else {
737		lyQuery('.embeds-checkbox').attr("indeterminate", true);
738	}
739
740	if(typeof(lycookie.creationDate) !== 'undefined')
741	{
742		if(lycookie.creationDate != settings.misc.lastChanged)
743		{
744			settings.forceCookieCreationdateToConfigDate = true;
745			showBanner();
746		}
747
748	}
749	else
750	{
751		// delete cookie and reload
752	}
753
754}
755
756/**
757 * überprüft, ob die aktuelle URL ein zu ignorierendes Keyword beinhaltet
758 * @returns {boolean} ob das Keyword gefunden wurde
759 */
760function isUrlIgnored() {
761	var currentUrl = window.location.href;
762	var urlSegments = settings.disallow.urlKeywords.split(',');
763	for (var i = 0; i <= urlSegments.length - 1; i++) {
764		if (currentUrl.indexOf(urlSegments[i]) !== -1) {
765			return true;
766		}
767	}
768	return false;
769}
770
771/**
772 * Wird beim Schalten der Haupt-Checkbox des Dropdowns "Externe Inhalte" ausgeführt
773 * sorgt dafür, dass alle Embed-Toggles den selben Wert wie die Checkbox erhalten
774 */
775function updateEmbedToggles() {
776	var EmbedsCheckbox = lyQuery("#embeds_checkbox");
777	var embeds = settings.cookies.embeds.split(",");
778	var state = lyQuery("#embeds_checkbox").prop("checked");
779
780	// if all elements are checked, toggle all elements
781	if (EmbedsCheckbox.attr("indeterminate", "false")) {
782		embeds.forEach(function (embed) {
783			var embedId = "#" + embed + "-toggle";
784			lyQuery(embedId).prop("checked", state);
785		})
786	} else {
787		EmbedsCheckbox.attr("indeterminate", false);
788		EmbedsCheckbox.prop("checked", false);
789	}
790
791}
792
793/**
794 * Wird beim Schalten eines Embed-Toggles ausgeführt
795 * sorgt dafür, dass die Haupt-Checkbox den entsprechenden Status übernimmt
796 */
797function updateEmbedCheckbox() {
798	var embeds = settings.cookies.embeds.split(",");
799	var embedCheckbox = lyQuery("#embeds_checkbox");
800	var checked = 0;
801	embeds.forEach(function (embed) {
802		// if one of all sub toggles is disabled, disable main toggle
803		var embedId = "#" + embed + "-toggle";
804		if (lyQuery(embedId).prop("checked")) {
805			checked++;
806		}
807	})
808
809	if (checked === 0) {
810		// if no embeds are checked, uncheck main toggle
811		embedCheckbox.prop("checked", false);
812	} else {
813		embedCheckbox.prop("checked", true);
814	}
815
816	if (embeds.length === checked) {
817		// if all embeds are checked, remove indeterminate status
818		embedCheckbox.attr('indeterminate', false);
819	} else {
820		embedCheckbox.attr('indeterminate', true);
821	}
822}
823
824function appendAnalyticsScript() {
825	lyQuery.get(documentRoot + settings.paths.analyticsScript, function (data) {
826		if (data.length > 0) {
827			lyQuery('head').append(data);
828		}
829	})
830}
831
832function appendMarketingScript() {
833	lyQuery.get(documentRoot + settings.paths.marketingScript, function (data) {
834		if (data.length > 0) {
835			lyQuery('head').append(data);
836		}
837	})
838}
839
840/**
841 * Lädt eine JSON-Datei vom gegebenen Pfad und führt ein Callback mit dem Ergebnis aus
842 * @param {*} file Pfad der gewünschten Datei
843 * @param {*} callback auszuführende Callback-Funktion
844 */
845function loadJSON(file, callback) {
846	var xobj = new XMLHttpRequest();
847	xobj.overrideMimeType('application/json');
848	xobj.open("GET", file, true);
849	xobj.onreadystatechange = function () {
850		if (xobj.readyState == 4 && xobj.status == 200) {
851			callback(xobj.responseText);
852		}
853	};
854	xobj.send(null);
855}
856
857/**
858 * https://stackoverflow.com/a/4351575
859 * @param functionName
860 * @param context
861 * @returns {*}
862 */
863function executeFunctionByName(functionName, context /*, args */) {
864	var args = Array.prototype.slice.call(arguments, 2);
865	var namespaces = functionName.split(".");
866	var func = namespaces.pop();
867	for (var i = 0; i < namespaces.length; i++) {
868		context = context[namespaces[i]];
869	}
870	return context[func].apply(context, args);
871}

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.