PageSourceSearch

https://www.eibsee-hotel.de/(cms)/module/static/default/content/libs/js/nst/frontend_edit.js

js eibsee-hotel.de collected 2026-09-26 07:03:52 UTC 28,125 bytes, 843 lines download raw bytes

1((w, d) => {
2	"use strict";
3	if (!w || !d) return;
4
5	if (w['_frontendEditDisabled']) return;
6
7	var storageElements = sessionStorage && sessionStorage.getItem('fe_edit');
8	var getElements;
9	if (storageElements === 'all') {
10		getElements = 'all';
11	} else if (storageElements) {
12		try {
13			getElements = JSON.parse(storageElements);
14		} catch (e) {
15			getElements = [];
16		}
17	} else {
18		getElements = [];
19	}
20	const allowedElements = getElements;
21	
22
23	let lgs = {
24		de: {
25			editContent: 'Inhalt bearbeiten',
26			edit20: 'Artikel bearbeiten',
27			edit29: 'Proxy bearbeiten',
28			edit54: 'Galerie bearbeiten',
29			edit57: 'CST Element bearbeiten',
30			edit87: 'Media Einzelelement bearbeiten',
31			edit94: 'Klon bearbeiten',
32			edit102: 'Social bearbeiten',
33			editmodules: 'Gruppe bearbeiten',
34			edit116: 'Karte bearbeiten',
35			editCst: 'CST bearbeiten',
36			editRoom: "Zimmer bearbeiten",
37			editOffer: "Angebot bearbeiten",
38			editProgram: "Zusatzleistung bearbeiten",
39			editHotel: "Hotel bearbeiten"
40		},
41		en: {
42			editContent: 'Edit content',
43			edit20: 'Edit article',
44			edit29: 'Edit proxy',
45			edit54: 'Edit gallery',
46			edit57: 'Edit CST element',
47			edit87: 'Edit media single element',
48			edit102: 'Edit social',
49			editmodules: 'Edit group',
50			edit116: 'Edit map',
51			editCst: 'Edit CST',
52			editRoom: "Edit room",
53			editOffer: "Edit offer",
54			editProgram: "Edit additional service",
55			editHotel: "Edit hotel"
56		}
57	}
58	lgs = lgs.de;
59
60	let currentTarget = null;
61	let editBtn = null;
62	let overlay = null;
63	let hideTimeout = null;
64
65	let currentTargetCst = null;
66	let editBtnCst = null;
67	let overlayCst = null;
68	let hideTimeoutCst = null;
69	let isSuspended = false;
70	let supportPickOverlay = null;
71	let persistentSupportOverlay = null;
72	let isSupportPickMode = false;
73	let _supportPickHandlers = null;
74	let _supportPickEligible = null;
75	let stylesElement = null;
76
77	const windowOpener = (cid) => {
78		if (!cid) return;
79		w.open('/condeon/frontend.php?type=in&page_content=' + cid, '_blank');
80	};
81
82	const windowOpenerCst = (cstid, hotelid, csttype) => {
83		if (!hotelid || !csttype) return;
84
85		let base = 'https://cst-pro.viomassl.com/hotel/' + hotelid + '/';
86		let addition = '';
87
88		if (cstid && csttype === 'room') {
89			addition = 'hotel_room_type?id=' + cstid;
90		}
91		else if (cstid && csttype === 'offer') {
92			addition = 'hotel_package?id=' + cstid;
93		}
94		else if (cstid && csttype === 'program') {
95			addition = 'hotel_program?id=' + cstid;
96		}
97		else if (cstid && csttype === 'job') {
98			addition = 'hotel_job?id=' + cstid;
99		}
100		w.open(base + addition, '_blank');
101	};
102
103	const isEditAllowed = (el) => {
104		if (!el || !el.dataset) return false;
105		if (allowedElements === 'all') return true;
106		if (Array.isArray(allowedElements) && allowedElements.length > 0) {
107			const pct = Number(el.dataset.pct);
108			return allowedElements.includes(pct);
109		}
110		return false;
111	};
112
113	const getEditableCidElements = () => {
114		return Array.from(d.querySelectorAll('[data-cid][data-pct]:not(.grp-single)')).filter(isEditAllowed);
115	};
116
117	const getSupportCidElements = () => {
118		return Array.from(d.querySelectorAll('[data-cid]:not(.grp-single):not(.frontend-edit__btn)'));
119	};
120
121	const suspendFrontendEdit = () => {
122		isSuspended = true;
123		if (hideTimeout) clearTimeout(hideTimeout);
124		if (hideTimeoutCst) clearTimeout(hideTimeoutCst);
125		hideTimeout = null;
126		hideTimeoutCst = null;
127		hideEditButton();
128		hideEditButtonCst();
129		d.documentElement.classList.add('frontend-edit--nooutline');
130	};
131
132	const resumeFrontendEdit = () => {
133		isSuspended = false;
134		d.documentElement.classList.remove('frontend-edit--nooutline');
135	};
136
137	const disableStyles = () => {
138		if (stylesElement) {
139			stylesElement.remove();
140			stylesElement = null;
141		}
142	};
143
144	const enableStyles = () => {
145		if (!stylesElement) {
146			styles();
147		}
148	};
149
150	const disable = () => {
151		isSuspended = true;
152		if (hideTimeout) clearTimeout(hideTimeout);
153		if (hideTimeoutCst) clearTimeout(hideTimeoutCst);
154		hideTimeout = null;
155		hideTimeoutCst = null;
156		hideEditButton();
157		hideEditButtonCst();
158		d.documentElement.classList.add('frontend-edit--nooutline');
159		disableStyles();
160		if (persistentSupportOverlay) {
161			persistentSupportOverlay.remove();
162			persistentSupportOverlay = null;
163		}
164		if (supportPickOverlay) {
165			supportPickOverlay.remove();
166			supportPickOverlay = null;
167		}
168		d.documentElement.classList.remove('fe-support-pick-mode');
169	};
170
171	const enable = () => {
172		isSuspended = false;
173		d.documentElement.classList.remove('frontend-edit--nooutline');
174		enableStyles();
175	};
176
177	const changeBtnText = (el) => {
178		var cls = el.classList;
179		switch (true) {
180			case cls.contains('grp-modules'):
181				editBtn.textContent = lgs.editmodules;
182				break;
183			case cls.contains('grp-mem-20'):
184				editBtn.textContent = lgs.edit20;
185				break;
186			case cls.contains('grp-mem-29'):
187				editBtn.textContent = lgs.edit29;
188				break;
189			case cls.contains('grp-mem-54'):
190				editBtn.textContent = lgs.edit54;
191				break;
192			case cls.contains('grp-mem-57'):
193				editBtn.textContent = lgs.edit57;
194				break;
195			case cls.contains('grp-mem-87'):
196				editBtn.textContent = lgs.edit87;
197				break;
198			case cls.contains('grp-mem-102'):
199				editBtn.textContent = lgs.edit102;
200				break;
201			case cls.contains('grp-mem-116'):
202				editBtn.textContent = lgs.edit116;
203				break;
204			default:
205				editBtn.textContent = lgs.editContent;
206		}
207	}
208
209	const changeBtnTextCst = (el, type) => {
210		switch (type) {
211			case 'room':
212				editBtnCst.textContent = lgs.editRoom;
213				break;
214			case 'offer':
215				editBtnCst.textContent = lgs.editOffer;
216				break;
217			case 'program':
218				editBtnCst.textContent = lgs.editProgram;
219				break;
220			case 'hotel':
221				editBtnCst.textContent = lgs.editHotel;
222				break;
223			default:
224				editBtnCst.textContent = lgs.editCst;
225		}
226	};
227
228	const createEditButton = () => {
229		const btn = d.createElement('button');
230		btn.className = 'frontend-edit__btn';
231		btn.textContent = lgs.editContent;
232		btn.addEventListener('click', () => {
233			if (currentTarget) windowOpener(currentTarget.dataset.cid);
234		});
235		return btn;
236	};
237
238	const createEditButtonCst = () => {
239		const btn = d.createElement('button');
240		btn.className = 'frontend-edit__btn frontend-edit__btn--cst';
241		btn.textContent = lgs.editCst;
242		btn.addEventListener('click', () => {
243			if (currentTargetCst) windowOpenerCst(currentTargetCst.dataset.cstid, currentTargetCst.dataset.csthotel, currentTargetCst.dataset.csttype);
244		});
245		return btn;
246	};
247
248	const createOverlay = () => {
249		const ov = d.createElement('div');
250		ov.className = 'frontend-edit__overlay';
251		editBtn = createEditButton();
252		ov.appendChild(editBtn);
253		d.body.appendChild(ov);
254		return ov;
255	};
256
257	const createOverlayCst = () => {
258		const ov = d.createElement('div');
259		ov.className = 'frontend-edit__overlay frontend-edit__overlay--cst';
260		editBtnCst = createEditButtonCst();
261		ov.appendChild(editBtnCst);
262		d.body.appendChild(ov);
263		return ov;
264	};
265
266	const showOverlay = (el) => {
267		if (isSuspended) return;
268		if (!overlay) overlay = createOverlay();
269		if (!isEditAllowed(el)) return;
270
271		const rect = el.getBoundingClientRect();
272		changeBtnText(el);
273		overlay.style.display = 'flex';
274		overlay.style.position = 'absolute';
275		overlay.style.left = (rect.left + window.scrollX - 3) + 'px';
276		overlay.style.top = (rect.top + window.scrollY - 3) + 'px';
277		overlay.style.width = (rect.width + 6) + 'px';
278		overlay.style.height = (rect.height + 6) + 'px';
279		overlay.style.zIndex = 2999;
280		editBtn.dataset.cid = el.dataset.cid;
281	};
282
283	const showOverlayCst = (el) => {
284		if (isSuspended) return;
285		if (!overlayCst) overlayCst = createOverlayCst();
286		const rect = el.getBoundingClientRect();
287		changeBtnTextCst(el, el.dataset.csttype);
288		overlayCst.style.display = 'flex';
289		overlayCst.style.position = 'absolute';
290		overlayCst.style.left = (rect.left + window.scrollX - 3) + 'px';
291		overlayCst.style.top = (rect.top + window.scrollY - 3) + 'px';
292		overlayCst.style.width = (rect.width + 6) + 'px';
293		overlayCst.style.height = (rect.height + 6) + 'px';
294		overlayCst.style.zIndex = 2999;
295		editBtnCst.dataset.cstid = el.dataset.cstid;
296		editBtnCst.dataset.csttype = el.dataset.csttype;
297	};
298
299	const hideOverlay = () => {
300		if (overlay) overlay.style.display = 'none';
301	};
302
303	const hideOverlayCst = () => {
304		if (overlayCst) overlayCst.style.display = 'none';
305	};
306
307	const showEditButton = (el) => {
308		if (isSuspended) return;
309		if (hideTimeout) {
310			clearTimeout(hideTimeout);
311			hideTimeout = null;
312		}
313		currentTarget = el;
314		showOverlay(el);
315	};
316
317	const showEditButtonCst = (el) => {
318		if (isSuspended) return;
319		if (hideTimeoutCst) {
320			clearTimeout(hideTimeoutCst);
321			hideTimeoutCst = null;
322		}
323		currentTargetCst = el;
324		showOverlayCst(el);
325	};
326
327	const hideEditButton = () => {
328		currentTarget = null;
329		hideOverlay();
330	};
331
332	const hideEditButtonCst = () => {
333		currentTargetCst = null;
334		hideOverlayCst();
335	};
336
337	const delayedHide = () => {
338		if (hideTimeout) clearTimeout(hideTimeout);
339		hideTimeout = setTimeout(() => {
340			hideEditButton();
341		}, 300);
342	};
343
344	const delayedHideCst = () => {
345		if (hideTimeoutCst) clearTimeout(hideTimeoutCst);
346		hideTimeoutCst = setTimeout(() => {
347			hideEditButtonCst();
348		}, 300);
349	};
350
351	const mouseMover = () => {
352		let timeout = null;
353		let timeouttime = 1500;
354		d.body.addEventListener('mousemove', e => {
355			if (isSuspended) {
356				if (timeout) {
357					clearTimeout(timeout);
358					timeout = null;
359				}
360				return;
361			}
362			// Outline hider logic
363			const isOverEditBtn = e.target.closest('.frontend-edit__btn');
364			if (timeout) {
365				clearTimeout(timeout);
366				timeout = null;
367			}
368			// Nur entfernen, wenn Maus nicht über einem Edit-Button ist
369			if (!isOverEditBtn) {
370				d.documentElement.classList.remove('frontend-edit--nooutline');
371				timeout = setTimeout(() => {
372					// Nur setzen, wenn Maus nicht über einem Edit-Button ist
373					if (!document.querySelector(':hover.frontend-edit__btn')) {
374						d.documentElement.classList.add('frontend-edit--nooutline');
375					}
376				}, timeouttime);
377			}
378
379			// Overlay hide logic
380			if (overlay && overlay.style.display !== 'none' && currentTarget) {
381				const rect = currentTarget.getBoundingClientRect();
382				const ovRect = overlay.getBoundingClientRect();
383				const x = e.clientX, y = e.clientY;
384				const inTarget = x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
385				const inOverlay = x >= ovRect.left && x <= ovRect.right && y >= ovRect.top && y <= ovRect.bottom;
386				if (!inTarget && !inOverlay) delayedHide();
387			}
388			if (overlayCst && overlayCst.style.display !== 'none' && currentTargetCst) {
389				const rect = currentTargetCst.getBoundingClientRect();
390				const ovRect = overlayCst.getBoundingClientRect();
391				const x = e.clientX, y = e.clientY;
392				const inTarget = x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom;
393				const inOverlay = x >= ovRect.left && x <= ovRect.right && y >= ovRect.top && y <= ovRect.bottom;
394				if (!inTarget && !inOverlay) delayedHideCst();
395			}
396		});
397	}
398
399	const styles = () => {
400		if (stylesElement) return; // Already added
401		const style = d.createElement('style');
402		style.textContent = `
403		:root {
404			--edit-icon: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="%23ffffff"><path d="M200-200h57l391-391-57-57-391 391v57Zm-80 80v-170l528-527q12-11 26.5-17t30.5-6q16 0 31 6t26 18l55 56q12 11 17.5 26t5.5 30q0 16-5.5 30.5T817-647L290-120H120Zm640-584-56-56 56 56Zm-141 85-28-29 57 57-29-28Z"/></svg>');
405			--edit-icon-cst: url('data:image/svg+xml,<path xmlns="http://www.w3.org/2000/svg" d="M42.964 4.697h-5.907V.385H53.33l-.009 4.313h-4.919v14.916h-5.439V4.697h0zm-27.581 8.544c-1.245 1.502-2.756 2.253-4.532 2.253-1.044 0-1.973-.229-2.788-.687s-1.447-1.103-1.896-1.937-.673-1.79-.673-2.87.224-2.037.673-2.87 1.081-1.479 1.896-1.937 1.744-.687 2.788-.687c1.776 0 3.287.751 4.532 2.253l2.203-4.426c-.669-.562-1.421-1.028-2.258-1.398C13.918.312 12.334 0 10.576 0 8.561 0 6.753.426 5.151 1.278S2.289 3.315 1.374 4.835 0 8.076 0 9.999s.457 3.644 1.374 5.164 2.174 2.705 3.777 3.557 3.411 1.278 5.425 1.278c1.758 0 3.342-.312 4.752-.934.836-.369 1.589-.835 2.258-1.397l-2.203-4.426zm7.746 6.18c-1.466-.384-2.656-.897-3.571-1.538l1.948-3.906c.861.568 1.696.921 2.831 1.269s2.253.522 3.351.522c2.088 0 3.132-.522 3.132-1.566 0-.549-.298-.957-.893-1.223s-1.552-.544-2.87-.838c-1.447-.311-2.656-.645-3.626-1.002s-1.804-.929-2.499-1.717-1.044-1.85-1.044-3.187a5.51 5.51 0 0 1 .962-3.173c.64-.943 1.597-1.689 2.87-2.239s2.834-.825 4.684-.825a16.51 16.51 0 0 1 3.736.426c1.226.284 2.307.7 3.242 1.25l-1.96 3.94c-1.831-.989-3.324-1.385-5.044-1.385-1.081 0-1.868.161-2.362.481s-.742.738-.742 1.25.293.897.879 1.154 1.529.522 2.83.797c1.465.312 2.678.645 3.64 1.003a6.29 6.29 0 0 1 2.5 1.703c.705.779 1.058 1.836 1.058 3.173 0 1.154-.321 2.198-.961 3.132s-1.603 1.68-2.884 2.239-2.839.838-4.67.838c-1.558-.002-3.069-.194-4.534-.578z"/>');
406			--editblue: #2196F3;
407			--editblue-hover: #136bb2;
408		}
409		[data-cid]:not(.frontend-edit__btn):not(.grp-single) {
410			outline: 2px dashed var(--editblue);
411			min-height: 36px;
412			transition: all .3s ease-out;
413		}
414		[data-cstid][data-csttype]:not(.frontend-edit__btn) {
415			outline: 2px dashed var(--editblue-hover);
416			min-height: 36px;
417		}
418		.frontend-edit__btn {
419			position: sticky;
420			top: 10px;
421			right: 10px;
422			margin-inline: auto 10px;
423			display: flex;
424			align-items: center;
425			width: 0px;
426			height: 36px;
427			box-sizing: border-box;
428			font-family: system-ui, sans-serif;
429			font-size: .875rem;
430			border: none;
431			background: var(--editblue);
432			color: #fff;
433			cursor: pointer;
434			font-weight: bold;
435			z-index: 100;
436			text-transform: uppercase;
437			pointer-events: auto;
438			padding: 0 0 0 36px;
439			white-space: nowrap;
440			transition: all .3s ease-out;
441			interpolate-size: allow-keywords;
442			line-height: 40px;
443			overflow: hidden;
444			border-radius: .25rem;
445		}
446
447		.frontend-edit__btn:hover {
448			width: auto;
449			padding-inline: 42px 16px;
450		}
451
452		.frontend-edit__btn::before {
453			content:'';
454			display: block;
455			width: 26px;
456			height: 26px;
457			background: var(--edit-icon) no-repeat center center;
458			background-size: contain;
459			position: absolute;
460			inset: 5px;
461		}
462		.frontend-edit__btn:hover, .frontend-edit__btn:focus {
463			background: var(--editblue-hover);
464			outline: none;
465		}
466		.frontend-edit__overlay {
467			display: none;
468			padding: 10px;
469			border: 3px solid var(--editblue);
470			background: rgba(33,150,243,0.1);
471			background: color-mix(in srgb, var(--editblue) 10%, transparent);
472			box-sizing: border-box;
473			z-index: 3000;
474			transition: all .25s;
475			position: absolute;
476			pointer-events: none;
477		}
478		.frontend-edit__overlay:has(~.frontend-edit__overlay[style*="display: flex"]) {
479			--editblue: transparent;
480			--editblue-hover: transparent;
481			opacity: 0;
482		}
483		.frontend-edit__overlay--cst {
484			--editblue: #83BB26;
485			--editblue-hover: #83BB26;
486			z-index: 3010;
487		}
488		.frontend-edit__btn--cst {
489			position: absolute;
490			--editblue: #fff;
491			--editblue-hover: #fff;
492			color: #000;
493			padding-left: 50px;
494		}
495
496		.frontend-edit__btn--cst::before {
497			background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" id="Ebene_1" viewBox="0 0 70.409 19.999"><defs><style>.cls-1{fill:%2383bb26;}.cls-2{fill:%237aae24;}</style></defs><path d="m42.964,4.697h-5.907V.385h16.273l-.009,4.313h-4.919v14.916h-5.439V4.697h0Z"/><path d="m15.383,13.241c-1.245,1.502-2.756,2.253-4.532,2.253-1.044,0-1.973-.229-2.788-.687-.815-.458-1.447-1.103-1.896-1.937-.449-.833-.673-1.79-.673-2.87s.224-2.037.673-2.87c.448-.833,1.081-1.479,1.896-1.937.815-.458,1.744-.687,2.788-.687,1.776,0,3.287.751,4.532,2.253l2.203-4.426c-.669-.562-1.421-1.028-2.258-1.398-1.41-.623-2.994-.935-4.752-.935-2.015,0-3.823.426-5.425,1.278-1.603.851-2.862,2.037-3.777,3.557-.916,1.52-1.374,3.241-1.374,5.164s.457,3.644,1.374,5.164c.915,1.52,2.174,2.705,3.777,3.557,1.602.851,3.411,1.278,5.425,1.278,1.758,0,3.342-.312,4.752-.934.836-.369,1.589-.835,2.258-1.397l-2.203-4.426Z"/><path d="m23.129,19.421c-1.466-.384-2.656-.897-3.571-1.538l1.948-3.906c.861.568,1.696.921,2.831,1.269,1.135.348,2.253.522,3.351.522,2.088,0,3.132-.522,3.132-1.566,0-.549-.298-.957-.893-1.223-.595-.265-1.552-.544-2.87-.838-1.447-.311-2.656-.645-3.626-1.002-.971-.357-1.804-.929-2.499-1.717-.697-.787-1.044-1.85-1.044-3.187,0-1.172.32-2.229.962-3.173.64-.943,1.597-1.689,2.87-2.239,1.272-.549,2.834-.825,4.684-.825,1.264,0,2.509.142,3.736.426,1.226.284,2.307.7,3.242,1.25l-1.96,3.94c-1.831-.989-3.324-1.385-5.044-1.385-1.081,0-1.868.161-2.362.481-.494.321-.742.738-.742,1.25s.293.897.879,1.154c.586.256,1.529.522,2.83.797,1.465.312,2.678.645,3.64,1.003.962.357,1.794.925,2.5,1.703.705.779,1.058,1.836,1.058,3.173,0,1.154-.321,2.198-.961,3.132-.641.934-1.603,1.68-2.884,2.239-1.283.558-2.839.838-4.67.838-1.558-.002-3.069-.194-4.534-.578Z"/><path class="cls-2" d="m66.304.385h4.105v4.094l-.397.516c-1.139,1.48-2.167,3.071-3.057,5.511-.89,2.448-1.411,4.902-1.545,7.292l-.102,1.807h-5.402l.031-1.945c.023-1.459.253-3.165.683-5.072.428-1.895,1.025-3.328,1.773-5.042.218-.501,1.148-2.385,1.378-2.846h-7.888V.385h10.421Z"/><path class="cls-1" d="m66.304.385c.822-.002,4.105,0,4.105,0v4.094l-.397.516c-1.139,1.48-2.167,3.071-3.057,5.511-.89,2.448-1.411,4.902-1.545,7.292l-.102,1.807h-5.402l.031-1.945c.023-1.459.253-3.165.683-5.072.428-1.895,1.025-3.328,1.773-5.042.218-.501.954-2.02,1.378-2.846.425-.826,1.704-2.906,2.533-4.314Z"/></svg>');
498			background-size: 40px auto;
499			width: 40px;
500			border-radius: .25em;
501		}
502		.frontend-edit__btn--cst:hover {
503			padding-left: 72px;
504		}
505
506		.frontend-edit__btn--cst:hover::after {
507			content: "";
508			position: absolute;
509			width: 1px;
510			height: 1em;
511			background: rgba(0, 0, 0, .16);
512			transform: translateX(-11px);
513		}
514
515		body #site :is([data-cstid][data-csttype]:not(.frontend-edit__btn), [data-cid]:not(.frontend-edit__btn)) {
516			transition: all .3s ease-out;
517		}
518
519		html:not(.frontend-edit--nooutline) #site :is([data-cstid][data-csttype]:not(.frontend-edit__btn), [data-cid]:not(.frontend-edit__btn)) {
520			border-radius: 0;
521		}
522
523		.frontend-edit__btn--cst:hover::before {
524			width: 50px;
525		}
526
527		@starting-style {
528			.frontend-edit__overlay,
529			.frontend-edit__overlay--cst {
530				opacity: 0;
531			}
532		}
533
534		.frontend-edit--nooutline .frontend-edit__overlay {
535			opacity: 0;
536			pointer-events: none;
537		}
538
539		.frontend-edit--nooutline :is(
540			[data-cstid][data-csttype]:not(.frontend-edit__btn), 
541			[data-cid]:not(.frontend-edit__btn)
542		) {
543			outline-color: transparent;
544		}
545
546		/* Support pick mode */
547		.frontend-edit__overlay--support {
548			border: 3px solid #e07b00 !important;
549			background: rgba(224,123,0,0.14) !important;
550			padding: 0;
551			box-shadow: 0 0 0 1px rgba(0, 0, 0, .08), 0 8px 24px rgba(0, 0, 0, .20);
552			pointer-events: none;
553		}
554		.frontend-edit__overlay--support::before {
555			content: 'Dieses Element markieren';
556			position: absolute;
557			top: -32px;
558			left: 0;
559			padding: 5px 10px;
560			border-radius: 4px;
561			background: #e07b00;
562			color: #fff;
563			font-size: 12px;
564			font-weight: 700;
565			line-height: 1.2;
566			white-space: nowrap;
567			letter-spacing: .01em;
568		}
569		#frontend-edit-support-bar {
570			position: fixed;
571			inset-inline: 0;
572			bottom: 0;
573			z-index: 9998;
574			display: flex;
575			align-items: center;
576			gap: 8px;
577			padding: 10px 16px;
578			background: #fff;
579			border-top: 2px solid #e07b00;
580			font-family: system-ui, sans-serif;
581			font-size: .875rem;
582			box-shadow: 0 -4px 16px rgba(0,0,0,.18);
583		}
584		#frontend-edit-support-bar > span {
585			flex: 1;
586			color: #444;
587			font-weight: 500;
588		}
589		#frontend-edit-support-bar button {
590			padding: 6px 14px;
591			border-radius: 4px;
592			border: none;
593			cursor: pointer;
594			font-size: .875rem;
595			font-weight: 600;
596			font-family: inherit;
597		}
598		#frontend-edit-support-bar .fe-support-btn-nocid { background: #f3f4f6; color: #333; }
599		#frontend-edit-support-bar .fe-support-btn-cancel { background: #fee2e2; color: #b91c1c; }
600		#frontend-edit-support-bar .fe-support-btn-nocid:hover { background: #e5e7eb; }
601		#frontend-edit-support-bar .fe-support-btn-cancel:hover { background: #fecaca; }
602		body.fe-support-pick-mode [data-cid]:not(.grp-single):not(.frontend-edit__btn) {
603			outline-style: dashed !important;
604			outline-width: 2px !important;
605			outline-color: #e07b00 !important;
606			cursor: crosshair !important;
607		}
608		body.fe-support-pick-mode .frontend-edit__overlay--support {
609			opacity: 1 !important;
610			pointer-events: none !important;
611		}
612		
613		`;
614		d.head.appendChild(style);
615		stylesElement = style;
616	};
617
618	const showSupportPickOverlay = (el) => {
619		if (!supportPickOverlay) {
620			supportPickOverlay = d.createElement('div');
621			supportPickOverlay.className = 'frontend-edit__overlay frontend-edit__overlay--support';
622			d.body.appendChild(supportPickOverlay);
623		}
624		const rect = el.getBoundingClientRect();
625		supportPickOverlay.style.display = 'block';
626		supportPickOverlay.style.position = 'fixed';
627		supportPickOverlay.style.left = (rect.left - 3) + 'px';
628		supportPickOverlay.style.top = (rect.top - 3) + 'px';
629		supportPickOverlay.style.width = (rect.width + 6) + 'px';
630		supportPickOverlay.style.height = (rect.height + 6) + 'px';
631		supportPickOverlay.style.zIndex = 4000;
632	};
633
634	const hideSupportPickOverlay = () => {
635		if (supportPickOverlay) supportPickOverlay.style.display = 'none';
636	};
637
638	const getEligibleSupportTarget = (startNode) => {
639		let node = startNode && startNode.nodeType === 1 ? startNode : null;
640		while (node) {
641			if (node.matches && node.matches('[data-cid]') && _supportPickEligible && _supportPickEligible.has(node)) {
642				return node;
643			}
644			node = node.parentElement;
645		}
646		return null;
647	};
648
649	const stopSupportPickMode = () => {
650		if (!isSupportPickMode) return;
651		isSupportPickMode = false;
652		_supportPickEligible = null;
653		if (_supportPickHandlers) {
654			d.removeEventListener('mousemove', _supportPickHandlers.onMouseMove, true);
655			d.removeEventListener('click', _supportPickHandlers.onClick, true);
656			d.removeEventListener('scroll', _supportPickHandlers.onScroll, true);
657			d.removeEventListener('keydown', _supportPickHandlers.onKeyDown, true);
658			_supportPickHandlers = null;
659		}
660		if (supportPickOverlay) { supportPickOverlay.remove(); supportPickOverlay = null; }
661		d.getElementById('frontend-edit-support-bar')?.remove();
662		d.body.classList.remove('fe-support-pick-mode');
663		resumeFrontendEdit();
664	};
665
666	const setPersistentSupportOverlay = (el) => {
667		if (!persistentSupportOverlay) {
668			persistentSupportOverlay = d.createElement('div');
669			persistentSupportOverlay.className = 'frontend-edit__overlay frontend-edit__overlay--support';
670			persistentSupportOverlay.setAttribute('data-persistent', 'true');
671			d.body.appendChild(persistentSupportOverlay);
672		}
673		const rect = el.getBoundingClientRect();
674		persistentSupportOverlay.style.display = 'block';
675		persistentSupportOverlay.style.position = 'absolute';
676		persistentSupportOverlay.style.left = (rect.left + window.scrollX - 3) + 'px';
677		persistentSupportOverlay.style.top = (rect.top + window.scrollY - 3) + 'px';
678		persistentSupportOverlay.style.width = (rect.width + 6) + 'px';
679		persistentSupportOverlay.style.height = (rect.height + 6) + 'px';
680		persistentSupportOverlay.style.zIndex = 3999;
681	};
682
683	const clearPersistentSupportOverlay = () => {
684		if (persistentSupportOverlay) { persistentSupportOverlay.remove(); persistentSupportOverlay = null; }
685	};
686
687	const startSupportPickMode = (onPicked, onNoCid, onCancelled, eligibleElements) => {
688		if (isSupportPickMode) stopSupportPickMode();
689		clearPersistentSupportOverlay();
690		suspendFrontendEdit();
691		isSupportPickMode = true;
692		_supportPickEligible = new Set(eligibleElements || getSupportCidElements());
693		d.body.classList.add('fe-support-pick-mode');
694
695		const bar = d.createElement('div');
696		bar.id = 'frontend-edit-support-bar';
697		bar.innerHTML =
698			'<span>Klicken Sie auf die Problemstelle auf der Seite</span>' +
699			'<button class="fe-support-btn-nocid" type="button">Ohne Element fortfahren</button>' +
700			'<button class="fe-support-btn-cancel" type="button">Abbrechen\u00a0(Esc)</button>';
701		d.body.appendChild(bar);
702
703		bar.querySelector('.fe-support-btn-nocid').addEventListener('click', () => {
704			stopSupportPickMode();
705			if (onNoCid) onNoCid();
706		});
707		bar.querySelector('.fe-support-btn-cancel').addEventListener('click', () => {
708			stopSupportPickMode();
709			if (onCancelled) onCancelled();
710		});
711
712		const onMouseMove = (e) => {
713			if (e.target.closest('#frontend-edit-support-bar')) { hideSupportPickOverlay(); return; }
714			const eligible = getEligibleSupportTarget(e.target);
715			if (eligible) showSupportPickOverlay(eligible);
716			else hideSupportPickOverlay();
717		};
718
719		const onClick = (e) => {
720			if (e.target.closest('#frontend-edit-support-bar')) return;
721			const eligible = getEligibleSupportTarget(e.target);
722			if (eligible) {
723				e.preventDefault();
724				e.stopPropagation();
725				setPersistentSupportOverlay(eligible);
726				const cb = onPicked;
727				stopSupportPickMode();
728				if (cb) cb(eligible);
729			}
730		};
731
732		const onScroll = () => { hideSupportPickOverlay(); };
733
734		const onKeyDown = (e) => {
735			if (e.key === 'Escape') {
736				stopSupportPickMode();
737				if (onCancelled) onCancelled();
738			}
739		};
740
741		d.addEventListener('mousemove', onMouseMove, true);
742		d.addEventListener('click', onClick, true);
743		d.addEventListener('scroll', onScroll, true);
744		d.addEventListener('keydown', onKeyDown, true);
745		_supportPickHandlers = { onMouseMove, onClick, onScroll, onKeyDown };
746	};
747
748	const autoscroll = () => {
749		if (location && location.hash && location.hash.startsWith('#cid-')) {
750			const cid = location.hash.replace('#cid-', '');
751			const el = d.querySelector('[data-cid="' + cid + '"]');
752			if (el) {
753				setTimeout(() => {
754					const rect = el.getBoundingClientRect();
755					const scrollTop = window.scrollY + rect.top - 200;
756					window.scrollTo({ top: scrollTop, behavior: 'smooth' });
757					showEditButton(el);
758				}, 500);
759			}
760		}
761	};
762
763	const init = () => {
764		const condeonElements = d.querySelectorAll('[data-cid][data-pct]:not(.grp-single)');
765		const cstElements = d.querySelectorAll('[data-cstid][data-csttype]');
766		if ((!condeonElements || condeonElements.length === 0) && (!cstElements || cstElements.length === 0)) return;
767		
768		condeonElements.forEach(el => {
769			el.addEventListener('mouseenter', () => showEditButton(el));
770			el.addEventListener('mouseleave', (e) => {
771				const related = e.relatedTarget;
772				let parentGroup = el.closest('.grp-modules');
773				if (parentGroup && parentGroup !== el && parentGroup.contains(related)) {
774					showEditButton(parentGroup);
775					return;
776				}
777				if (!overlay || (!overlay.contains(related))) {
778					delayedHide();
779				}
780			});
781		});
782		cstElements.forEach(el => {
783			el.addEventListener('mouseenter', () => showEditButtonCst(el));
784			el.addEventListener('mouseleave', (e) => {
785				const related = e.relatedTarget;
786				if (!overlayCst || (!overlayCst.contains(related))) {
787					delayedHideCst();
788				}
789			});
790		});
791		if (!overlay) overlay = createOverlay();
792		overlay.addEventListener('mouseleave', (e) => {
793			const related = e.relatedTarget;
794			let enteringCondeon = false;
795			condeonElements.forEach(el => {
796				if (el.contains(related)) enteringCondeon = true;
797			});
798			if (!enteringCondeon) {
799				delayedHide();
800			}
801		});
802		if (!overlayCst) overlayCst = createOverlayCst();
803		overlayCst.addEventListener('mouseleave', (e) => {
804			const related = e.relatedTarget;
805			let enteringCst = false;
806			cstElements.forEach(el => {
807				if (el.contains(related)) enteringCst = true;
808			});
809			if (!enteringCst) {
810				delayedHideCst();
811			}
812		});
813		mouseMover();
814		autoscroll();
815
816		w.__condeonAssist = w.__condeonAssist || {};
817		w.__condeonAssist.frontendEdit = {
818			isEditAllowed,
819			getEditableCidElements,
820			getSupportCidElements,
821			suspend: suspendFrontendEdit,
822			resume: resumeFrontendEdit,
823			startSupportPickMode,
824			stopSupportPickMode,
825			enableStyles,
826			disableStyles,
827			disable,
828			enable,
829		};
830
831		// Apply initial state from sessionStorage
832		if (sessionStorage.getItem('fe_edit_enabled') === 'false') {
833			disable();
834		} else {
835			enableStyles();
836		}
837
838
839	};
840
841	init();
842
843})(window, document);

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.