PageSourceSearch

https://marli.de/javascript/main.js

js marli.de collected 2026-10-04 13:32:06 UTC 30,718 bytes, 1,242 lines download raw bytes

1
2
3
4function MainNavigation()
5{
6	var navigation = this;
7
8	this.$navigation = $('.mainnavigation').first();								// jQuery object of the navigation
9	this.$flyoutOverlay = $('.flyout-overlay').first();							// jQuery object of the flyout overlay (a seperate div outside of the navigation)
10	this.$backgroundOverlay = $('body > .overlay').first();						// jQuery object of the background overlay
11
12	this.$navigationToggle = $('.mainnavigation-toggle').first();					// jQuery object of the navgation toggle button
13
14	this.breakpoint = '980px';
15
16	// states for the flyout
17	//this.flyout_opening_counter = 0;
18	this.flyout_menu_mouseover = false;													// Boolean
19	this.flyout_overlay_mouseover = false;												// Boolean
20
21
22	/*
23	 * This method will initialise the navigation.
24	 * It will add markup to the dom and register event handlers.
25
26	 * Note that this method is called at the end of the class.
27	 */
28
29	this.init = function()
30	{
31		// start the navigation at the correct depth for tablets
32
33		this.$navigation.find('.active > .subnavigation').addClass('tablet-expanded');
34
35		// event handling for tablets
36
37		this.$navigationToggle.on('click', function(event)
38		{
39			navigation.handleNavigationToggleClick(event, $(this));
40		});
41
42		this.$navigation.find('.more-link').on('click', function(event)
43		{
44			navigation.handleMoreLinkClick(event, $(this));
45		});
46
47		this.$navigation.find('.back-link').on('click', function(event)
48		{
49			navigation.handleBackLinkClick(event, $(this));
50		});
51
52		$(window).on('resize', function(event)
53		{
54			navigation.updateNavigationHeights();
55		});
56		this.updateNavigationHeights();
57
58		// event handling for flyout
59
60		this.$navigation.find('.expandable').on('mouseenter', function(event) // old selector: '> .expandable'
61		{
62			navigation.handleExpandableItemMouseenter(event, $(this));
63		});
64		this.$navigation.find('.expandable > a').on('focus', function(event) // focus mapped to mouseenter handling
65		{
66			navigation.handleExpandableItemMouseenter(event, $(this).parent());
67		});
68
69		this.$navigation.find('.expandable').on('mouseleave', function(event) // old selector: '> .expandable'
70		{
71			navigation.handleExpandableItemMouseleave(event, $(this));
72		});
73		this.$navigation.find('.expandable > a').on('blur', function(event) // blur mapped to its own handler
74		{
75			navigation.handleExpandableItemBlur(event, $(this).parent());
76		});
77
78		this.$flyoutOverlay.on('mouseenter', function(event)
79		{
80			navigation.handleFlyoutOverlayMouseenter(event, $(this));
81		});
82
83		this.$flyoutOverlay.on('mouseleave', function(event)
84		{
85			navigation.handleFlyoutOverlayMouseleave(event, $(this));
86		});
87	};
88
89	this.handleNavigationToggleClick = function(event, $navigationToggle)
90	{
91		var mq = window.matchMedia('(max-width: ' + this.breakpoint + ')');
92		if(!mq.matches)
93		{
94			return;
95		}
96
97		if(!this.$navigation.hasClass('tablet-expanded'))
98		{
99			$navigationToggle.addClass('active');
100
101			this.$navigation
102			 .addClass('tablet-expanded')
103			 .css('opacity', 0.5)
104			 .stop()
105			 .animate({
106				  'opacity': 1.0
107			  },
108			  200,
109			  function()
110			  {
111				  // Animation complete.
112				  navigation.$navigation.css('opacity', '');
113			  });
114
115			$('body').addClass('tablet-overlayed');
116			this.$backgroundOverlay
117			 .css('opacity', 0.5)
118			 .stop()
119			 .animate({
120				  'opacity': 1.0
121			  },
122			  200,
123			  function()
124			  {
125				  // Animation complete.
126				  //navigation.$backgroundOverlay.css('opacity', '');
127			  });
128		}
129		else
130		{
131			$navigationToggle.removeClass('active');
132
133			this.$navigation
134			 .css('opacity', 1.0)
135			 .stop()
136			 .animate({
137				  'opacity': 0.5
138			  },
139			  200,
140			  function()
141			  {
142				  // Animation complete.
143				  navigation.$navigation
144					.removeClass('tablet-expanded')
145					.css('opacity', '');
146			  });
147
148			this.$backgroundOverlay
149			 .css('opacity', 1.0)
150			 .stop()
151			 .animate({
152				  'opacity': 0.5
153			  },
154			  200,
155			  function()
156			  {
157				  // Animation complete.
158				  $('body').removeClass('tablet-overlayed');
159				  navigation.$backgroundOverlay.css('opacity', '');
160			  });
161		}
162	};
163
164	this.handleMoreLinkClick = function(event, $moreLink)
165	{
166		var mq = window.matchMedia('(max-width: ' + this.breakpoint + ')');
167		if(!mq.matches)
168		{
169			return;
170		}
171
172		event.preventDefault(); // moreLink is inside the a-tag
173
174		var $subnavigation = $moreLink.parent().next();
175		$subnavigation.addClass('tablet-expanded');
176	};
177
178	this.handleBackLinkClick = function(event, $backLink)
179	{
180		var mq = window.matchMedia('(max-width: ' + this.breakpoint + ')');
181		if(!mq.matches)
182		{
183			return;
184		}
185
186		var $subnavigation = $backLink.parent();
187		$subnavigation.removeClass('tablet-expanded');
188	};
189
190	/*
191	 * This method set the height of the mainnavigation and all subnavigations to the highest of them.
192	 * If the window size is above the breakpoint the style declarations will be removed.
193	 */
194
195	this.updateNavigationHeights = function()
196	{
197		var mq = window.matchMedia('(max-width: ' + this.breakpoint + ')');
198		if(!mq.matches)
199		{
200			this.$navigation.css('height', '');
201			this.$navigation.find('.subnavigation').css('height', '');
202			return;
203		}
204
205		this.$navigation.css('display', 'block');
206		this.$navigation.css('height', '');
207		//alert(this.$navigation.height());
208		var largest_height = this.$navigation.height();
209
210		this.$navigation.find('.subnavigation').each(function()
211		{
212			$navigation = $(this);
213			$navigation.css('height', '');
214			//alert($navigation.height());
215			if($navigation.height() > largest_height)
216			{
217				largest_height = $navigation.height();
218			}
219		});
220
221		this.$navigation.css('display', '');
222		this.$navigation.css('height', largest_height + 'px');
223		this.$navigation.find('.subnavigation').css('height', largest_height + 'px');
224	};
225
226	this.handleExpandableItemMouseenter = function(event, $expandableItem)
227	{
228		var mq = window.matchMedia('(max-width: ' + this.breakpoint + ')');
229		if(mq.matches)
230		{
231			return;
232		}
233
234		//console.log('handleExpandableItemMouseenter');
235
236		// checking for depth to handle everything but the first layer
237		if($expandableItem.parents('li').length != 0)
238		{
239			if(!$expandableItem.hasClass('expanded'))
240			{
241				$expandableItem.addClass('expanded');
242			}
243			return;
244		}
245
246		this.flyout_menu_mouseover = true;
247
248		// do not animate when hovering back from the overlay
249		if($expandableItem.hasClass('expanded') && $(event.relatedTarget).hasClass('flyout-overlay'))
250		{
251			return;
252		}
253
254		//this.flyout_opening_counter++;
255
256		this.closeAllFlyoutMenus();
257		this.openFlyout($expandableItem);
258	};
259
260	this.handleExpandableItemMouseleave = function(event, $expandableItem)
261	{
262		var mq = window.matchMedia('(max-width: ' + this.breakpoint + ')');
263		if(mq.matches)
264		{
265			return;
266		}
267
268		//console.log('handleExpandableItemMouseleave');
269
270		// checking for depth to handle everything but the first layer
271		if($expandableItem.parents('li').length != 0)
272		{
273			$expandableItem.removeClass('expanded');
274			return;
275		}
276
277		this.flyout_menu_mouseover = false;
278
279		//navigation.closeFlyoutMenu($expandableItem);
280
281		setTimeout(function()
282		 {
283			 if(!navigation.flyout_overlay_mouseover && !navigation.flyout_menu_mouseover)
284			 {
285				 //navigation.closeFlyout($expandableItem);
286				 //navigation.closeFlyoutMenu($expandableItem);
287				 navigation.closeFlyoutOverlay();
288				 navigation.closeAllFlyoutMenus();
289			 }
290		 },
291		 10);
292	};
293
294	this.handleExpandableItemBlur = function(event, $expandableItem)
295	{
296		var mq = window.matchMedia('(max-width: ' + this.breakpoint + ')');
297		if(mq.matches)
298		{
299			return;
300		}
301
302		// wait for links to actually have focus
303		setTimeout(function()
304		{
305			// expandable item has to stay open if there is a link with focus inside
306			if($expandableItem.find('.subnavigation a:focus').length > 0)
307			{
308				return;
309			}
310
311			// checking for depth to handle everything but the first layer
312			if($expandableItem.parents('li').length != 0)
313			{
314				$expandableItem.removeClass('expanded');
315				return;
316			}
317
318			this.flyout_menu_mouseover = false;
319
320			setTimeout(function()
321			{
322				if(!navigation.flyout_overlay_mouseover && !navigation.flyout_menu_mouseover)
323				{
324					navigation.closeFlyoutOverlay();
325					navigation.closeAllFlyoutMenus();
326				}
327			},
328			10);
329		},
330		50);
331	};
332
333	this.handleFlyoutOverlayMouseenter = function(event)
334	{
335		var mq = window.matchMedia('(max-width: ' + this.breakpoint + ')');
336		if(mq.matches)
337		{
338			return;
339		}
340
341		//console.log('handleFlyoutOverlayMouseenter');
342
343		this.flyout_overlay_mouseover = true;
344	};
345
346	this.handleFlyoutOverlayMouseleave = function(event)
347	{
348		var mq = window.matchMedia('(max-width: ' + this.breakpoint + ')');
349		if(mq.matches)
350		{
351			return;
352		}
353
354		//console.log('handleFlyoutOverlayMouseleave');
355
356		this.flyout_overlay_mouseover = false;
357
358		setTimeout(function()
359		 {
360			 if(/*!navigation.flyout_overlay_mouseover &&*/ !navigation.flyout_menu_mouseover)
361			 {
362				 //navigation.closeFlyout(navigation.$navigation.find('> .expanded').first());
363				 navigation.closeAllFlyoutMenus();
364				 navigation.closeFlyoutOverlay();
365			 }
366		 },
367		 10);
368	};
369
370	/*
371	 * This method will show the menu, the overlay of the flyout and the background overlay.
372	 */
373
374	this.openFlyout = function($expandableItem)
375	{
376		if(!$expandableItem.hasClass('expanded'))
377		{
378			$expandableItem.addClass('expanded');
379		}
380
381		var $subnavigationWrapper = $expandableItem.find('.subnavigation').first();
382
383		if (this.$flyoutOverlay.css('height') == '0px') {
384			this.$flyoutOverlay.css('height', $subnavigationWrapper.outerHeight() + 'px');
385		}
386
387		this.$flyoutOverlay
388		 .stop(true)
389		 //.css('opacity', 0.5)
390		 .css('padding-top', this.$flyoutOverlay.css('padding-top'))
391		 .animate({
392			  'opacity': 1.0,
393			  'padding-top': '15px',
394			  'height': $subnavigationWrapper.outerHeight() + 'px'
395		  },
396		  100,
397		  function()
398		  {
399			  // Animation complete.
400		  });
401
402		$subnavigationWrapper
403		 .stop()
404		 .css('opacity', 0.5)
405		 .css('padding-top', 0)
406		 .animate({
407			  'opacity': 1.0,
408			  'padding-top': '15px'
409		  },
410		  100,
411		  function()
412		  {
413			  // Animation complete.
414		  });
415
416		//window.setTimeout(function() {
417		$('body').addClass('overlayed navigation-overlayed');
418		navigation.$backgroundOverlay
419		 .stop()
420		 //.css('opacity', 0.5)
421		 .animate({
422			  'opacity': 1.0
423		  },
424		  0,
425		  function()
426		  {
427			  // Animation complete.
428		  });
429		//}, 0);
430
431	};
432
433	this.closeAllFlyoutMenus = function(opts) {
434
435		//console.log('closeAllFlyoutMenus');
436
437		var $allFlyoutMenus = navigation.$navigation.find('> .expanded');
438
439		$allFlyoutMenus.each(function() {
440			var $expandedItem = $(this);
441			navigation.closeFlyoutMenu($expandedItem);
442		});
443	};
444
445	/*
446	 * This method will hide the menu, the overlay of the flyout and the background overlay.
447	 */
448
449	this.closeFlyoutMenu = function($expandedItem) {
450		var $subnavigationWrapper = $expandedItem.find('.subnavigation').first();
451
452
453		//window.setTimeout(function() {
454		$subnavigationWrapper
455		 .stop()
456		 .animate(
457		  {
458			  'opacity': 0.5,
459			  'padding-top': 0
460		  },
461		  100,
462		  function () {
463			  // Animation complete.
464			  $expandedItem.removeClass('expanded');
465		  });
466		//}, 100);
467
468	};
469
470	this.closeFlyoutOverlay = function()
471	{
472		window.setTimeout(function() {
473			if(!navigation.flyout_overlay_mouseover && !navigation.flyout_menu_mouseover) {
474				navigation.$flyoutOverlay
475				 .stop()
476				 .animate(
477				  {
478					  //'opacity': 0.5,
479					  'padding-top': 0,
480					  height: 0
481				  },
482				  200,
483				  function()
484				  {
485					  // Animation complete.
486					  navigation.$flyoutOverlay.css('height', '');
487				  });
488			}
489		}, 200);
490
491		this.$backgroundOverlay
492		 .stop()
493		 .css('opacity', 1.0)
494		 .animate({
495			  'opacity': 0.5
496		  },
497		  200,
498		  function()
499		  {
500			  // Animation complete.
501			  $('body').removeClass('overlayed navigation-overlayed');
502			  //navigation.$backgroundOverlay.css('opacity', '');
503			  navigation.$backgroundOverlay.css('opacity', 0);
504		  });
505	};
506
507	// Initialising the navigation
508	this.init();
509}
510
511$(document).ready(function(event)
512{
513	/* BEGIN Main navigation */
514
515	var mainNavigation = new MainNavigation();
516
517	/* END Main navigation */
518
519	/* BEGIN main navigation event handling (mainly for navigation via tab-key) */
520
521	/* OLD:
522
523	$('#navigation > li').each(function(index)
524	{
525		var $navItem = $(this);
526		var $flyoutPanel = $navItem.find('.flyout');
527
528		if($flyoutPanel.length > 0)
529		{
530			var $flyoutToggle = $navItem.find('.flyout_toggle');
531
532			$flyoutToggle.focus(function(event)
533			{
534				var $navItem = $(this).parent('li');
535				if(!$navItem.hasClass('flyout_expanded'))
536				{
537					$navItem.addClass('flyout_expanded');
538				}
539			});
540
541			$flyoutToggle.blur(function(event)
542			{
543				var $navItem = $(this).parent('li');
544
545				setTimeout(function()
546				{
547					if($navItem.find('.flyout a:focus').length == 0)
548					{
549						$navItem.removeClass('flyout_expanded');
550					}
551				},
552				50);
553			});
554
555			$flyoutPanel.find('a').blur(function(event)
556			{
557				var $flyoutPanel = $(this).parents('.flyout');
558
559				setTimeout(function()
560				{
561					if($flyoutPanel.find('a:focus').length == 0)
562					{
563						$flyoutPanel.parent('li').removeClass('flyout_expanded');
564					}
565				},
566				50);
567			});
568
569			$navItem.mouseover(function(event)
570			{
571				var $navItem = $(this);
572				if(!$navItem.hasClass('flyout_expanded'))
573				{
574					$navItem.addClass('flyout_expanded');
575				}
576			});
577
578			$navItem.mouseout(function(event)
579			{
580				var $navItem = $(this);
581				$navItem.removeClass('flyout_expanded');
582			});
583		}
584	});
585
586	 */
587
588	/* END main navigation event handling */
589
590	/* BEGIN slider event handling */
591
592	if($('#slider_items li').length > 1)
593	{
594		function animateSlides($current_active_item, $next_active_item, current_active_item_index, next_active_item_index)
595		{
596			//alert('current:' + $current_active_item.index() + ', next:' + $next_active_item.index());
597			if(next_active_item_index > current_active_item_index) // old: $next_active_item.index() > $current_active_item.index()
598			{
599				/* detach "next" item from dom and insert after(!) current one */
600				$current_active_item.after($next_active_item.detach());
601
602				/* move both items to the right */
603				$current_active_item
604				.css('left', 0)
605				.animate(
606				{
607					'left': '-100%'
608				},
609				slider_animation_duration,
610				function()
611				{
612					// Animation complete.
613				});
614
615				$next_active_item
616				.css('left', '100%')
617				.animate(
618				{
619					'left': 0
620				},
621				slider_animation_duration,
622				function()
623				{
624					// Animation complete.
625				});
626			}
627			else
628			{
629				/* detach "next" item from dom and insert before(!) current one */
630				$current_active_item.before($next_active_item.detach());
631
632				/* move both items to the left */
633				$current_active_item
634				.css('left', 0)
635				.animate(
636				{
637					'left': '100%'
638				},
639				slider_animation_duration,
640				function()
641				{
642					// Animation complete.
643				});
644
645				$next_active_item
646				.css('left', '-100%')
647				.animate(
648				{
649					'left': 0
650				},
651				slider_animation_duration,
652				function()
653				{
654					// Animation complete.
655				});
656			}
657		}
658
659		var slider_animation_duration = 480; // time in ms
660		var $slider = $('#slider');
661		var $slider_items = $('#slider_items li');
662		var $slider_navigation = $('<ul id="slider_navigation"></ul>');
663			$slider_navigation.attr('role', 'menu');
664			$slider_navigation.attr('aria-controls', 'slider_items');
665
666		/* create slider navigation links */
667		for(var i = 0; i < $slider_items.length; i++)
668		{
669			var $slider_nav_item = $('<li></li>');
670
671			$slider_nav_item.html('Seite ' + (i + 1));
672			$slider_nav_item.attr('tabindex', 0);
673			$slider_nav_item.attr('role', 'menuitemradio');
674			$slider_nav_item.attr('aria-checked', 'false');
675			$slider_nav_item.attr('title', 'Seite ' + (i + 1) + ' ansehen');
676
677			/* first item will be active by default */
678			if(i == 0)
679			{
680				$slider_nav_item.attr('aria-checked', 'true');
681				$slider_nav_item.addClass('active');
682				$slider_nav_item.attr('title', 'Seite ' + (i + 1));
683			}
684
685			/* prepend it to the list */
686			$slider_navigation.append($slider_nav_item);
687
688			/* (!!) slider items - set positions and aria attributes  */
689			$slider_items.eq(i).css('left', (100 * i) + '%');
690			$slider_items.eq(i).attr('aria-hidden', 'true');
691			if(i == 0)
692			{
693				$slider_items.eq(i).attr('aria-hidden', 'false');
694			}
695		}
696		$slider.prepend($slider_navigation);
697
698		/* navigation click handler */
699		$slider_navigation.find('li').click(function(event)
700		{
701			var $slider_nav_item = $(this);
702
703			if($(this).hasClass('active'))
704			{
705				return;
706			}
707
708			/* set classes and html attributes to indicate next active element */
709			var current_active_item_index = $slider_navigation.find('.active').index();
709 // index needed for animation
710
711			/* reset old ones */
712			$slider_navigation.find('li').each(function(index)
713			{
714				$(this).removeClass('active');
715				$(this).attr('aria-checked', 'false');
716				$(this).attr('title', 'Seite ' + (index + 1) + ' ansehen');
717			});
718
719			/* set new ones */
720			$slider_nav_item.attr('aria-checked', 'true');
721			$slider_nav_item.addClass('active');
722			$slider_nav_item.attr('title', 'Seite ' + ($slider_nav_item.index() + 1));
723
724			/* update aria attributes and call the animate function */
725			var $current_slider_item = $slider_items.eq(current_active_item_index);
726			var $next_slider_item = $slider_items.eq($slider_nav_item.index());
727
728			$current_slider_item.attr('aria-hidden', 'true');
729			$next_slider_item.attr('aria-hidden', 'false');
730
731			animateSlides($current_slider_item, $next_slider_item, current_active_item_index, $slider_nav_item.index());
732		});
733
734		/* navigation key handler */
735		$('#slider_navigation li').keydown(function(event)
736		{
737			if(
738				event.keyCode == 13 ||	/* enter */
739				event.keyCode == 32		/* space */
740			)
741			{
742				event.preventDefault(); // prevents scrolling in chrome (and maybe others)
743				$(this).click(); // mapped to the click event handling
744			}
745		});
746
747		/* create arrow navigation and add it to the dom (after the slider navigation) */
748		var $slider_arrow_navigation = $('<div id="slider_arrow_navigation"></div>');
749		var $slider_arrow_previous = $('<a tabindex="0" class="previous" title="Zurück">Zurück</a>');
750		var $slider_arrow_next = $('<a tabindex="0" class="next" title="Weiter">Weiter</a>');
751		$slider_arrow_navigation.prepend($slider_arrow_previous);
752		$slider_arrow_navigation.append($slider_arrow_next);
753		$slider_navigation.after($slider_arrow_navigation);
754
755		/* add event handlers for the links */
756		$slider_arrow_navigation.find('a').click(function(event)
757		{
758			var $slider_nav_items = $slider_navigation.find('li');
759
760			/* set classes and html attributes to indicate next active element */
761
762			var current_active_item_index = $slider_navigation.find('.active').index(); // index needed for animation
763
764			/* set indizes for previous link (default) */
765			var next_active_item_index = current_active_item_index - 1;
766			if(current_active_item_index == 0)
767			{
768				next_active_item_index = $slider_nav_items.length - 1;
769			}
770
771			/* set indizes for next link */
772			if($(this).hasClass('next'))
773			{
774				next_active_item_index = current_active_item_index + 1;
775				if(current_active_item_index == $slider_nav_items.length - 1)
776				{
777					next_active_item_index = 0;
778				}
779			}
780
781			/* reset old ones */
782			$slider_nav_items.each(function(index)
783			{
784				$(this).removeClass('active');
785				$(this).attr('aria-checked', 'false');
786				$(this).attr('title', 'Seite ' + (index + 1) + ' ansehen');
787			});
788
789			/* set new ones */
790			var $slider_nav_next_active_item = $slider_nav_items.eq(next_active_item_index);
791			$slider_nav_next_active_item.attr('aria-checked', 'true');
792			$slider_nav_next_active_item.addClass('active');
793			$slider_nav_next_active_item.attr('title', 'Seite ' + ($slider_nav_next_active_item.index() + 1));
794
795			/* update aria attributes and call the animate function */
796			var $current_slider_item = $slider_items.eq(current_active_item_index);
797			var $next_slider_item = $slider_items.eq(next_active_item_index);
798
799			$current_slider_item.attr('aria-hidden', 'true');
800			$next_slider_item.attr('aria-hidden', 'false');
801
802			animateSlides($current_slider_item, $next_slider_item, current_active_item_index, next_active_item_index);
803		});
804
805		/* arrow navigation key handler */
806		$('#slider_arrow_navigation a').keyup(function(event)
807		{
808			if(
809				event.keyCode == 13 ||	/* enter */
810				event.keyCode == 32		/* space */
811			)
812			{
813				$(this).click(); // mapped to the click event handling
814			}
815		});
816		$('#slider_arrow_navigation a').keydown(function(event)
817		{
818			if(
819				event.keyCode == 13 ||	/* enter */
820				event.keyCode == 32		/* space */
821			)
822			{
823				event.preventDefault(); // prevents scrolling
824			}
825		});
826	}
827
828	/* END slider event handling */
829
830	/* BEGIN fontsize switch event handling */
831
832	$('#fontsize-switch button').click(function(event)
833	{
834		var default_browser_fontsize = 16;
835		var current_fontsize = parseFloat($('body').css('font-size').replace('px', ''));
836
837		if($(this).hasClass('larger'))
838		{
839			current_fontsize += 1;
840		}
841		else if($(this).hasClass('smaller'))
842		{
843			current_fontsize -= 1;
844		}
845		else // reset
846		{
847			current_fontsize = 15;
848		}
849		$('body').css('font-size', (current_fontsize / default_browser_fontsize) + 'em');
850	});
851	$('#fontsize-switch button').keyup(function(event) // up because down triggers way too fast
852	{
853		if(event.keyCode == 32) /* space */
854		{
855			event.preventDefault(); // prevents scrolling
856			$(this).click(); // mapped to the click event handling
857		}
858	});
859
860	/* END fontsize switch event handling */
861
862	/* BEGIN topsearch event handling */
863
864	$('.topsearch input[type=text]').on('keyup paste', function(event)
865	{
866		$('.topsearch input[type=text]').val($(this).val());
867	});
868	$('.topsearch input[type=text]').focus(function(event)
869	{
870		var $words = $(this);
871		if($words.val() == 'Suchbegriff eingeben')
872		{
873			$('.topsearch input[type=text]').val('').removeClass('text_empty');;
874		}
875	});
876	$('.topsearch input[type=text]').blur(function(event)
877	{
878		var $words = $(this);
879		if($words.val() == '')
880		{
881			$('.topsearch input[type=text]').val('Suchbegriff eingeben').addClass('text_empty');;
882		}
883	});
884
885	/* END topsearch event handling */
886
887	/* BEGIN quickselect event handling */
888
889	$('#quickselect button').click(function(event)
890	{
891		var $button = $(this);
892		var $list = $button.next();
893		var $container = $button.parent();
894
895		if($container.hasClass('expanded')) // collapse
896		{
897			$container.removeClass('expanded');
898			$button.attr('aria-pressed', 'false');
899			$list.attr('aria-hidden', 'true');
900		}
901		else // expand
902		{
903			$container.addClass('expanded');
904			$button.attr('aria-pressed', 'true');
905			$list.attr('aria-hidden', 'false');
906		}
907	});
908	$('#quickselect button').keyup(function(event)
909	{
910		if(event.keyCode == 32) /* space */
911		{
912			event.preventDefault(); // prevents scrolling
913			$(this).click(); // mapped to the click event handling
914		}
915	});
916	$('#quickselect button').blur(function(event)
917	{
918		var $button = $(this);
919		var $list = $button.next();
920		var $container = $button.parent();
921
922		setTimeout(function()
923		{
924			if($container.hasClass('expanded') && $list.find('li a:focus').length == 0)
925			{
926				$button.click();
927			}
928		},
929		50);
930	});
931	$('#quickselect li a').blur(function(event)
932	{
933		var $list = $(this).parents('ul');
934		var $button = $list.prev();
935
936		setTimeout(function()
937		{
938			if($list.find('li a:focus').length == 0)
939			{
940				$button.click();
941			}
942		},
943		50);
944	});
945
946	/* END quickselect event handling */
947
948	/* BEGIN contrast switch */
949
950	activeStylesheetTitle = getActiveStyleSheet(); // activeStylesheetTitle is a global variable
951	var userStylesheetOverwritten = false;
952	var userStylesheetSaved = false;
953
954	//alert(activeStylesheetTitle);
955
956	$(window).resize(function(event)
957	{
958		var mq = window.matchMedia('(max-width: 640px)');
959		if(mq.matches)
960		{
961			userStylesheetOverwritten = true;
962
963			$('link[title]').each(function(index)
964			{
965				var $link = $(this);
966
967				if($link[0].disabled == false)
968				{
969					if(!userStylesheetSaved)
970					{
971						activeStylesheetTitle = $link.attr('title');
972						userStylesheetSaved = true;
973					}
974
975					console.log('saved title: ' + activeStylesheetTitle);
976				}
977				$link[0].disabled = true;
978
979				if($link.attr('title') == 'Standard')
980				{
981					$link[0].disabled = false;
982				}
983			});
984		}
985		else
986		{
987			if(userStylesheetOverwritten)
988			{
989				userStylesheetOverwritten = false;
990
991				$('link[title]').each(function(index)
992				{
993					var $link = $(this);
994
995					$link[0].disabled = true;
996
997					if($link.attr('title') == activeStylesheetTitle)
998					{
999						$link[0].disabled = false;
1000					}
1001				});
1002			}
1003		}
1004	});
1005
1006	$('#contrast-switch .contrast').each(function(index)
1007	{
1008		var $buttons = $('#contrast-switch .contrast');
1009		var $button = $(this);
1010
1011		$buttons.removeClass('active');
1012
1013		if(activeStylesheetTitle == 'Standard')
1014		{
1015			$buttons.filter('.normal').first().addClass('active');
1016		}
1017		else if(activeStylesheetTitle == 'Schwarz-Weiß')
1018		{
1019			$buttons.filter('.black-white').first().addClass('active');
1020		}
1021		else if(activeStylesheetTitle == 'Schwarz-Gelb')
1022		{
1023			$buttons.filter('.black-yellow').first().addClass('active');
1024		}
1025		else if(activeStylesheetTitle == 'Blau-Gelb')
1026		{
1027			$buttons.filter('.blue-yellow').first().addClass('active');
1028		}
1029	});
1030
1031	$('#contrast-switch .contrast').click(function(event)
1032	{
1033		var $button = $(this);
1034
1035		if($button.hasClass('active')) return;
1036
1037		$('#contrast-switch .contrast').removeClass('active');
1038		$button.addClass('active');
1039
1040		var linktitle = 'Standard';
1041
1042		if($button.hasClass('black-white'))
1043		{
1044			linktitle = 'Schwarz-Weiß';
1045		}
1046		else if($button.hasClass('black-yellow'))
1047		{
1048			linktitle = 'Schwarz-Gelb';
1049		}
1050		else if($button.hasClass('blue-yellow'))
1051		{
1052			linktitle = 'Blau-Gelb';
1053		}
1054
1055		//alert(linktitle);
1056		setActiveStyleSheet(linktitle);
1057	});
1058
1059	/* END contrast switch */
1060
1061	/* BEGIN hide contact person images */
1062
1063	$('.ansprechpartner img').each(function(index)
1064	{
1065		var $image = $(this);
1066		var $imageWrapper = $('<div class="ansprechpartner-portrait"></div>');
1067		$image.before($imageWrapper);
1068		$imageWrapper.append($image.detach());
1069		$imageWrapper.css('background-image', 'url(' + $image.attr('src') + ')');
1070		$imageWrapper.attr('title', $image.attr('title'));
1071		$image.attr('src', '/images/cm/ueber_uns/ansprechpartner-portrait-dummy.jpg');
1072	});
1073
1074	/* END hide contact person images */
1075
1076	/* BEGIN team list setup and event handling (new) */
1077
1078	// https://www.labnol.org/code/19616-detect-touch-screen-javascript
1079	function isTouchDevice()
1080	{
1081		return (('ontouchstart' in window) || (navigator.MaxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0));
1082	}
1083
1084	if (!isTouchDevice())
1085	{
1086		// console.log('no touch');
1087
1088		$('.list-team .team-member .image-wrapper').each(function()
1089		{
1090			var $teamMemberImageWrapper = $(this);
1091			var $image = $teamMemberImageWrapper.find('img');
1092			if(!$image.length)
1093			{
1094				return;
1095			}
1096			$teamMemberImageWrapper.css('background-image', 'url(' + $image.attr('src') + ')');
1097			$image.remove();
1098		});
1099		$('.list-team .team-member').on('focus', function(event)
1100		{
1101			var $teamMember = $(this);
1102			$teamMember.addClass('focus');
1103		});
1104		$('.list-team .team-member').on('blur', function(event)
1105		{
1106			var $teamMember = $(this);
1107			var $relatedTarget = $(event.relatedTarget);
1108			if($relatedTarget.closest($teamMember).length)
1109			{
1110				return;
1111			}
1112			$teamMember.removeClass('focus');
1113		});
1114		$('.list-team .team-member a').on('focus', function(event)
1115		{
1116			var $teamMember = $(this).parents('.team-member');
1117			$teamMember.addClass('focus');
1118		});
1119		$('.list-team .team-member a').on('blur', function(event)
1120		{
1121			var $teamMember = $(this).parents('.team-member');
1122			var $relatedTarget = $(event.relatedTarget);
1123			if($relatedTarget.closest($teamMember).length)
1124			{
1125				return;
1126			}
1127			$teamMember.removeClass('focus');
1128		});
1129	}
1130
1131	/* END team list setup and event handling (new) */
1132});
1133
1134/* BEGIN cookies for fontsize AND contrast stylesheets */
1135
1136function setActiveStyleSheet(title) {
1137	var i, a, main;
1138	for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
1139		if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")) {
1140			a.disabled = true;
1141			if(a.getAttribute("title") == title) a.disabled = false; // disabled is an official property
1142		}
1143	}
1144}
1145
1146function getActiveStyleSheet() {
1147	var i, a;
1148	for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
1149		if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title") && !a.disabled) return a.getAttribute("title");
1150	}
1151	return null;
1152}
1153
1154function getPreferredStyleSheet() {
1155	var i, a;
1156	for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
1157		if(a.getAttribute("rel").indexOf("style") != -1
1158		 && a.getAttribute("rel").indexOf("alt") == -1
1159		 && a.getAttribute("title")
1160		) return a.getAttribute("title");
1161	}
1162	return null;
1163}
1164
1165function createCookie(name,value,days)
1166{
1167	if (days)
1168	{
1169		var date = new Date();
1170		date.setTime(date.getTime()+(days*24*60*60*1000));
1171		var expires = "; expires="+date.toGMTString();
1172	}
1173	else expires = "";
1174	document.cookie = name+"="+value+expires+"; path=/";
1175}
1176
1177function readCookie(name)
1178{
1179	var nameEQ = name + "=";
1180	var ca = document.cookie.split(';');
1181	for(var i=0;i < ca.length;i++)
1182	{
1183		var c = ca[i];
1184		while (c.charAt(0)==' ') c = c.substring(1,c.length);
1185		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
1186	}
1187	return null;
1188}
1189
1190window.onload = function(e)
1191{
1192	var activeStylesheetTitle = getActiveStyleSheet();
1193	
1194	// read fontsize cookie
1195	var fontsizeCookie = readCookie("fontsize");
1196	var fontsize = fontsizeCookie ? fontsizeCookie : parseFloat($('body').css('font-size').replace('px', ''));
1197	$('body').css('font-size', (fontsize / 16) + 'em');
1198
1199	// read style cookie
1200	var styleCookie = readCookie("style");
1201	if (styleCookie && styleCookie == 'null') styleCookie = null;
1202	var title = styleCookie ? styleCookie : getPreferredStyleSheet();
1203	setActiveStyleSheet(title);
1204
1205	$(window).resize(); // resize triggered for stylesheet overwrite on small breakpoints
1206
1207
1208
1209	'use strict';
1210    var he = document.getElementById('logo');
1211    var startShrink = 50;
1212    window.addEventListener('scroll',
1213       function() {
1214          if( window.pageYOffset > startShrink ) {
1215              he.classList.add( 'shrink' );           
1216           }
1217          else {
1218              he.classList.remove( 'shrink' );                
1219           }
1220        },false);
1221}
1222
1223window.onunload = function(e)
1224{
1225	// create fontsize cookie
1226	var fontsize = parseFloat($('body').css('font-size').replace('px', ''));
1227	createCookie("fontsize", fontsize, 365);
1228
1229	// create style cookie
1230	var title = getActiveStyleSheet();
1231
1232	var mq = window.matchMedia('(max-width: 640px)');
1233	if(mq.matches)
1234	{
1235		title = activeStylesheetTitle; // activeStylesheetTitle is global
1236	}
1237
1238	createCookie("style", title, 365);
1239}
1240
1241/* END cookies for fontsize AND contrast stylesheets */
1242

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.