PageSourceSearch

https://www.lebenshilfe-erh.de/frontend/assets/scripts/core.js?1788167348

js lebenshilfe-erh.de collected 2026-10-07 02:57:41 UTC 105,099 bytes, 3,562 lines download raw bytes

1// Every file in scripts/ acts as an entry-point and gets tranformed to build/.
2// Feel free to create as much as you want.
3// Files in subdirectories will be ignored but you can require them in entry-point-files.
4// Add an _ to a file and it will just be ignored(good for tests).
5// Add your entry-point-files to templates/layout/yourlayout.html
6
7// ===============================================================================
8// CORE
9// ===============================================================================
10
11// ATOMS
12
13/**
14 *
15 * Detect current input method and add a class to the body
16 * so things can be styled accordingly, e.g. tab-key focussed focus styles
17 *
18 */
19
20// Add body class if user is tabbing
21function handleFirstTab(e) {
22    if (e.keyCode === 9) {
23        document.body.classList.add('user-is-tabbing');
24        window.removeEventListener('keydown', handleFirstTab);
25
26        // Start listening for mouse usage
27        window.addEventListener('mousedown', handleMouseDownOnce);
28    }
29}
30
31// Remove body class if user is using a mouse
32function handleMouseDownOnce() {
33    document.body.classList.remove('user-is-tabbing');
34    window.removeEventListener('mousedown', handleMouseDownOnce);
35    window.addEventListener('keydown', handleFirstTab);
36}
37
38// Start listening for tab usage
39window.addEventListener('keydown', handleFirstTab);
40
41$(document).ready(function () {
42    var $button;
43
44    uploadInit();
45
46    function bindMultipleDelete() {
47        $('.multiple__delete').on('click', function (event) {
48            $button = $(this);
49
50            event.preventDefault();
51
52            if ($button.attr('data-multi-argument')) {
53                $template_path =
54                    $button.attr('data-multi-path') +
55                    '&' +
56                    $button.attr('data-multi-argument') +
57                    '=' +
58                    $button.attr('data-multi-id');
59
60                $.ajax({
61                    url: $template_path,
62                }).done(function (html) {});
63            } else {
64                //
65            }
66
67            $button.parents('.multiple__wrap').remove();
68        });
69    }
70
71    function uploadInit() {
72        $('.upload input[type=file]:not(.upload-initialised)').each(
73            function () {
74                var eventNamespace = '.upload';
75                var labelInputValueAttr = 'data-input-value';
76                var $input = $(this);
77                $input.removeClass('empty');
78                var $inputClone = $input.clone(true, true);
79                var $label = $input.next('label');
80
81                var setLabelInputValue = function () {
82                    var $input = $(this);
83
84                    if ($input.val() && $input.val() !== '') {
85                        $input.removeClass('empty');
86                        $label.attr(
87                            labelInputValueAttr,
88                            $input.val().split('\\').pop()
89                        );
90                    } else {
91                        $label.attr(labelInputValueAttr, '');
92                        $input.addClass('empty');
93                    }
94                };
95
96                if (!$input.val() || $input.val() === '') {
97                    $input.addClass('empty');
98                }
99
100                $label.attr(labelInputValueAttr, '');
101                $input.on('change' + eventNamespace, setLabelInputValue);
102                $label.on('click' + eventNamespace, function (event) {
103                    if (
104                        $input.val() &&
105                        $input.val() !== '' &&
106                        $input.is(':valid')
107                    ) {
108                        event.preventDefault();
109                        $input.remove();
110                        $label.before($inputClone); // cant just empty val because of ie
111                        $input = $inputClone;
112
113                        if (!$input.val() || $input.val() === '') {
114                            $input.addClass('empty');
115                        }
116
117                        $inputClone = $input.clone(true, true);
118                        $inputClone.removeClass('empty');
119                        $input.off('change' + eventNamespace);
120                        $input.on(
121                            'change' + eventNamespace,
122                            setLabelInputValue
123                        );
124
125                        $label.attr(labelInputValueAttr, '');
126                    }
127                });
128
129                $input.addClass('upload-initialised');
130            }
131        );
132    }
133
134    (function () {
135        bindMultipleDelete();
136
137        $('div[data-multi-btn]').on('click', function (event) {
138            $button = $(this);
139            event.preventDefault();
140
141            if ($(this).attr('data-multi-argument')) {
142                $template_path =
143                    $(this).attr('data-multi-path') +
144                    '&' +
145                    $(this).attr('data-multi-argument') +
146                    '=' +
147                    $(this).attr('data-multi-iteration');
148            } else {
149                $template_path = $(this).attr('data-multi-path');
150            }
151
152            $container = $('#' + $(this).attr('data-multi-cont'));
153
154            $.ajax({
155                url: $template_path,
156            }).done(function (html) {
157                $container.append(html);
158                bindMultipleDelete();
159
160                $button.attr(
161                    'data-multi-iteration',
162                    parseInt($button.attr('data-multi-iteration')) + 1
163                );
164                uploadInit();
165            });
166        });
167    })();
168});
169
170// //=require jquery.sumoselect.js
171
172$(document).ready(function () {
173
174  var lang = {
175    de: {
176      'PLEASE_CHOOSE': 'Bitte wählen',
177      'CHOOSE': 'auswählen',
178      'CHOOSE_ALL': 'Alle auswählen',
179      'CHOOSED': 'ausgewählt',
180      'ALL': 'Alle',
181      'SEARCH': 'Suche',
182      'NO_RESULTS_FOR': 'Keine Ergebnisse für ',
183      'OK': 'OK',
184      'CANCEL': 'Abbrechen'
185    },
186    en: {
187      'PLEASE_CHOOSE': 'Please choose',
188      'CHOOSE': 'choose',
189      'CHOOSE_ALL': 'Choose all',
190      'CHOOSED': 'choosed',
191      'ALL': 'All',
192      'SEARCH': 'Search',
193      'NO_RESULTS_FOR': 'No results for ',
194      'OK': 'OK',
195      'CANCEL': 'Cancel'
196    }
197  }
198
199  lang = lang[$('html').attr('lang') || 'de'];
200
201
202  $('select.form-control, .js__sumoselect').each(function () {
203    var $this = $(this);
204
205    $this.SumoSelect({
206      placeholder: $this.attr('placeholder') || lang['PLEASE_CHOOSE'],
207      floatWidth: 0,
208	  forceCustomRendering: false,
209      nativeOnDevice: ['Android', 'BlackBerry', 'iPhone', 'iPad', 'iPod', 'Opera Mini', 'IEMobile', 'Silk'],
210      captionFormat: '{0} ' + lang['CHOOSED'],
211      captionFormatAllSelected: $this.attr('data-choose-all') || lang['CHOOSE_ALL'],
212      // selectAll: $this.attr('data-select-all') || true,
213      selectAll: false,
214      // okCancelInMulti: true,
215      search: $this.attr('data-search') || false,
216      searchText: lang['SEARCH'],
217      noMatch: lang['NO_RESULTS_FOR'] + ' "{0}"',
218      locale: [
219      	lang['OK'],
220      	lang['CANCEL'],
221      	$this.attr('data-choose-all') || lang['CHOOSE_ALL']
222      ],
223      triggerChangeCombined: true
224    });
225  });
226
227});
228
229
230$(document).ready(function(){
231
232
233	$("select.select--submit-onchange, .js__select-submit-onchange").on("change", function(){
234		$(this).parents("form").submit();
235	});
236	
237	$("select.select--jump-onchange, .js__select-jump-onchange").on("change", function(){
238		jumpMenu( 'parent',this,0);
239	});
240
241});
242
243
244function jumpMenu(targ,selObj,restore) {
245	window.location='http://'+window.location.hostname+'/'+selObj.options[selObj.selectedIndex].value;
246	if (restore) selObj.selectedIndex = 0;
247}
248
249/*!
250 * jQuery Validation Plugin v1.16.1-pre
251 *
252 * http://jqueryvalidation.org/
253 *
254 * Copyright (c) 2017 Jörn Zaefferer
255 * Released under the MIT license
256 */
257(function( factory ) {
258	if ( typeof define === "function" && define.amd ) {
259		define( ["jquery"], factory );
260	} else if (typeof module === "object" && module.exports) {
261		module.exports = factory( require( "jquery" ) );
262	} else {
263		factory( jQuery );
264	}
265}(function( $ ) {
266
267$.extend( $.fn, {
268
269	// http://jqueryvalidation.org/validate/
270	validate: function( options ) {
271
272		// If nothing is selected, return nothing; can't chain anyway
273		if ( !this.length ) {
274			if ( options && options.debug && window.console ) {
275				console.warn( "Nothing selected, can't validate, returning nothing." );
276			}
277			return;
278		}
279
280		// Check if a validator for this form was already created
281		var validator = $.data( this[ 0 ], "validator" );
282		if ( validator ) {
283			return validator;
284		}
285
286		// Add novalidate tag if HTML5.
287		this.attr( "novalidate", "novalidate" );
288
289		validator = new $.validator( options, this[ 0 ] );
290		$.data( this[ 0 ], "validator", validator );
291
292		if ( validator.settings.onsubmit ) {
293
294			this.on( "click.validate", ":submit", function( event ) {
295				if ( validator.settings.submitHandler ) {
296					validator.submitButton = event.currentTarget;
297				}
298
299				// Allow suppressing validation by adding a cancel class to the submit button
300				if ( $( this ).hasClass( "cancel" ) ) {
301					validator.cancelSubmit = true;
302				}
303
304				// Allow suppressing validation by adding the html5 formnovalidate attribute to the submit button
305				if ( $( this ).attr( "formnovalidate" ) !== undefined ) {
306					validator.cancelSubmit = true;
307				}
308			} );
309
310			// Validate the form on submit
311			this.on( "submit.validate", function( event ) {
312				if ( validator.settings.debug ) {
313
314					// Prevent form submit to be able to see console output
315					event.preventDefault();
316				}
317				function handle() {
318					var hidden, result;
319					if ( validator.settings.submitHandler ) {
320						if ( validator.submitButton ) {
321
322							// Insert a hidden input as a replacement for the missing submit button
323							hidden = $( "<input type='hidden'/>" )
324								.attr( "name", validator.submitButton.name )
325								.val( $( validator.submitButton ).val() )
326								.appendTo( validator.currentForm );
327						}
328						result = validator.settings.submitHandler.call( validator, validator.currentForm, event );
329						if ( validator.submitButton ) {
330
331							// And clean up afterwards; thanks to no-block-scope, hidden can be referenced
332							hidden.remove();
333						}
334						if ( result !== undefined ) {
335							return result;
336						}
337						return false;
338					}
339					return true;
340				}
341
342				// Prevent submit for invalid forms or custom submit handlers
343				if ( validator.cancelSubmit ) {
344					validator.cancelSubmit = false;
345					return handle();
346				}
347				if ( validator.form() ) {
348					if ( validator.pendingRequest ) {
349						validator.formSubmitted = true;
350						return false;
351					}
352					return handle();
353				} else {
354					validator.focusInvalid();
355					return false;
356				}
357			} );
358		}
359
360		return validator;
361	},
362
363	// http://jqueryvalidation.org/valid/
364	valid: function() {
365		var valid, validator, errorList;
366
367		if ( $( this[ 0 ] ).is( "form" ) ) {
368			valid = this.validate().form();
369		} else {
370			errorList = [];
371			valid = true;
372			validator = $( this[ 0 ].form ).validate();
373			this.each( function() {
374				valid = validator.element( this ) && valid;
375				if ( !valid ) {
376					errorList = errorList.concat( validator.errorList );
377				}
378			} );
379			validator.errorList = errorList;
380		}
381		return valid;
382	},
383
384	// http://jqueryvalidation.org/rules/
385	rules: function( command, argument ) {
386		var element = this[ 0 ],
387			settings, staticRules, existingRules, data, param, filtered;
388
389		// If nothing is selected, return empty object; can't chain anyway
390		if ( element == null ) {
391			return;
392		}
393
394		if ( !element.form && element.hasAttribute( "contenteditable" ) ) {
395			element.form = this.closest( "form" )[ 0 ];
396			element.name = this.attr( "name" );
397		}
398
399		if ( element.form == null ) {
400			return;
401		}
402
403		if ( command ) {
404			settings = $.data( element.form, "validator" ).settings;
405			staticRules = settings.rules;
406			existingRules = $.validator.staticRules( element );
407			switch ( command ) {
408			case "add":
409				$.extend( existingRules, $.validator.normalizeRule( argument ) );
410
411				// Remove messages from rules, but allow them to be set separately
412				delete existingRules.messages;
413				staticRules[ element.name ] = existingRules;
414				if ( argument.messages ) {
415					settings.messages[ element.name ] = $.extend( settings.messages[ element.name ], argument.messages );
416				}
417				break;
418			case "remove":
419				if ( !argument ) {
420					delete staticRules[ element.name ];
421					return existingRules;
422				}
423				filtered = {};
424				$.each( argument.split( /\s/ ), function( index, method ) {
425					filtered[ method ] = existingRules[ method ];
426					delete existingRules[ method ];
427					if ( method === "required" ) {
428						$( element ).removeAttr( "aria-required" );
429					}
430				} );
431				return filtered;
432			}
433		}
434
435		data = $.validator.normalizeRules(
436		$.extend(
437			{},
438			$.validator.classRules( element ),
439			$.validator.attributeRules( element ),
440			$.validator.dataRules( element ),
441			$.validator.staticRules( element )
442		), element );
443
444		// Make sure required is at front
445		if ( data.required ) {
446			param = data.required;
447			delete data.required;
448			data = $.extend( { required: param }, data );
449			$( element ).attr( "aria-required", "true" );
450		}
451
452		// Make sure remote is at back
453		if ( data.remote ) {
454			param = data.remote;
455			delete data.remote;
456			data = $.extend( data, { remote: param } );
457		}
458
459		return data;
460	}
461} );
462
463// Custom selectors
464$.extend( $.expr.pseudos || $.expr[ ":" ], {		// '|| $.expr[ ":" ]' here enables backwards compatibility to jQuery 1.7. Can be removed when dropping jQ 1.7.x support
465
466	// http://jqueryvalidation.org/blank-selector/
467	blank: function( a ) {
468		return !$.trim( "" + $( a ).val() );
469	},
470
471	// http://jqueryvalidation.org/filled-selector/
472	filled: function( a ) {
473		var val = $( a ).val();
474		return val !== null && !!$.trim( "" + val );
475	},
476
477	// http://jqueryvalidation.org/unchecked-selector/
478	unchecked: function( a ) {
479		return !$( a ).prop( "checked" );
480	}
481} );
482
483// Constructor for validator
484$.validator = function( options, form ) {
485	this.settings = $.extend( true, {}, $.validator.defaults, options );
486	this.currentForm = form;
487	this.init();
488};
489
490// http://jqueryvalidation.org/jQuery.validator.format/
491$.validator.format = function( source, params ) {
492	if ( arguments.length === 1 ) {
493		return function() {
494			var args = $.makeArray( arguments );
495			args.unshift( source );
496			return $.validator.format.apply( this, args );
497		};
498	}
499	if ( params === undefined ) {
500		return source;
501	}
vendor: 10,001 bytes, lines 502-813
502	if ( arguments.length > 2 && params.constructor !== Array  ) {
503		params = $.makeArray( arguments ).slice( 1 );
504	}
505	if ( params.constructor !== Array ) {
506		params = [ params ];
507	}
508	$.each( params, function( i, n ) {
509		source = source.replace( new RegExp( "\\{" + i + "\\}", "g" ), function() {
510			return n;
511		} );
512	} );
513	return source;
514};
515
516$.extend( $.validator, {
517
518	defaults: {
519		messages: {},
520		groups: {},
521		rules: {},
522		errorClass: "error",
523		pendingClass: "pending",
524		validClass: "valid",
525		errorElement: "label",
526		focusCleanup: false,
527		focusInvalid: true,
528		errorContainer: $( [] ),
529		errorLabelContainer: $( [] ),
530		onsubmit: true,
531		ignore: ":hidden",
532		ignoreTitle: false,
533		onfocusin: function( element ) {
534			this.lastActive = element;
535
536			// Hide error label and remove error class on focus if enabled
537			if ( this.settings.focusCleanup ) {
538				if ( this.settings.unhighlight ) {
539					this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
540				}
541				this.hideThese( this.errorsFor( element ) );
542			}
543		},
544		onfocusout: function( element ) {
545			if ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) {
546				this.element( element );
547			}
548		},
549		onkeyup: function( element, event ) {
550
551			// Avoid revalidate the field when pressing one of the following keys
552			// Shift       => 16
553			// Ctrl        => 17
554			// Alt         => 18
555			// Caps lock   => 20
556			// End         => 35
557			// Home        => 36
558			// Left arrow  => 37
559			// Up arrow    => 38
560			// Right arrow => 39
561			// Down arrow  => 40
562			// Insert      => 45
563			// Num lock    => 144
564			// AltGr key   => 225
565			var excludedKeys = [
566				16, 17, 18, 20, 35, 36, 37,
567				38, 39, 40, 45, 144, 225
568			];
569
570			if ( event.which === 9 && this.elementValue( element ) === "" || $.inArray( event.keyCode, excludedKeys ) !== -1 ) {
571				return;
572			} else if ( element.name in this.submitted || element.name in this.invalid ) {
573				this.element( element );
574			}
575		},
576		onclick: function( element ) {
577
578			// Click on selects, radiobuttons and checkboxes
579			if ( element.name in this.submitted ) {
580				this.element( element );
581
582			// Or option elements, check parent select in that case
583			} else if ( element.parentNode.name in this.submitted ) {
584				this.element( element.parentNode );
585			}
586		},
587		highlight: function( element, errorClass, validClass ) {
588			if ( element.type === "radio" ) {
589				this.findByName( element.name ).addClass( errorClass ).removeClass( validClass );
590			} else {
591				$( element ).addClass( errorClass ).removeClass( validClass );
592			}
593		},
594		unhighlight: function( element, errorClass, validClass ) {
595			if ( element.type === "radio" ) {
596				this.findByName( element.name ).removeClass( errorClass ).addClass( validClass );
597			} else {
598				$( element ).removeClass( errorClass ).addClass( validClass );
599			}
600		}
601	},
602
603	// http://jqueryvalidation.org/jQuery.validator.setDefaults/
604	setDefaults: function( settings ) {
605		$.extend( $.validator.defaults, settings );
606	},
607
608	messages: {
609		required: "This field is required.",
610		remote: "Please fix this field.",
611		email: "Please enter a valid email address.",
612		url: "Please enter a valid URL.",
613		date: "Please enter a valid date.",
614		dateISO: "Please enter a valid date (ISO).",
615		number: "Please enter a valid number.",
616		digits: "Please enter only digits.",
617		equalTo: "Please enter the same value again.",
618		maxlength: $.validator.format( "Please enter no more than {0} characters." ),
619		minlength: $.validator.format( "Please enter at least {0} characters." ),
620		rangelength: $.validator.format( "Please enter a value between {0} and {1} characters long." ),
621		range: $.validator.format( "Please enter a value between {0} and {1}." ),
622		max: $.validator.format( "Please enter a value less than or equal to {0}." ),
623		min: $.validator.format( "Please enter a value greater than or equal to {0}." ),
624		step: $.validator.format( "Please enter a multiple of {0}." )
625	},
626
627	autoCreateRanges: false,
628
629	prototype: {
630
631		init: function() {
632			this.labelContainer = $( this.settings.errorLabelContainer );
633			this.errorContext = this.labelContainer.length && this.labelContainer || $( this.currentForm );
634			this.containers = $( this.settings.errorContainer ).add( this.settings.errorLabelContainer );
635			this.submitted = {};
636			this.valueCache = {};
637			this.pendingRequest = 0;
638			this.pending = {};
639			this.invalid = {};
640			this.reset();
641
642			var groups = ( this.groups = {} ),
643				rules;
644			$.each( this.settings.groups, function( key, value ) {
645				if ( typeof value === "string" ) {
646					value = value.split( /\s/ );
647				}
648				$.each( value, function( index, name ) {
649					groups[ name ] = key;
650				} );
651			} );
652			rules = this.settings.rules;
653			$.each( rules, function( key, value ) {
654				rules[ key ] = $.validator.normalizeRule( value );
655			} );
656
657			function delegate( event ) {
658
659				// Set form expando on contenteditable
660				if ( !this.form && this.hasAttribute( "contenteditable" ) ) {
661					this.form = $( this ).closest( "form" )[ 0 ];
662					this.name = $( this ).attr( "name" );
663				}
664
665				var validator = $.data( this.form, "validator" ),
666					eventType = "on" + event.type.replace( /^validate/, "" ),
667					settings = validator.settings;
668				if ( settings[ eventType ] && !$( this ).is( settings.ignore ) ) {
669					settings[ eventType ].call( validator, this, event );
670				}
671			}
672
673			$( this.currentForm )
674				.on( "focusin.validate focusout.validate keyup.validate",
675					":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], " +
676					"[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], " +
677					"[type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], " +
678					"[type='radio'], [type='checkbox'], [contenteditable], [type='button']", delegate )
679
680				// Support: Chrome, oldIE
681				// "select" is provided as event.target when clicking a option
682				.on( "click.validate", "select, option, [type='radio'], [type='checkbox']", delegate );
683
684			if ( this.settings.invalidHandler ) {
685				$( this.currentForm ).on( "invalid-form.validate", this.settings.invalidHandler );
686			}
687
688			// Add aria-required to any Static/Data/Class required fields before first validation
689			// Screen readers require this attribute to be present before the initial submission http://www.w3.org/TR/WCAG-TECHS/ARIA2.html
690			$( this.currentForm ).find( "[required], [data-rule-required], .required" ).attr( "aria-required", "true" );
691		},
692
693		// http://jqueryvalidation.org/Validator.form/
694		form: function() {
695			this.checkForm();
696			$.extend( this.submitted, this.errorMap );
697			this.invalid = $.extend( {}, this.errorMap );
698			if ( !this.valid() ) {
699				$( this.currentForm ).triggerHandler( "invalid-form", [ this ] );
700			}
701			this.showErrors();
702			return this.valid();
703		},
704
705		checkForm: function() {
706			this.prepareForm();
707			for ( var i = 0, elements = ( this.currentElements = this.elements() ); elements[ i ]; i++ ) {
708				this.check( elements[ i ] );
709			}
710			return this.valid();
711		},
712
713		// http://jqueryvalidation.org/Validator.element/
714		element: function( element ) {
715			var cleanElement = this.clean( element ),
716				checkElement = this.validationTargetFor( cleanElement ),
717				v = this,
718				result = true,
719				rs, group;
720
721			if ( checkElement === undefined ) {
722				delete this.invalid[ cleanElement.name ];
723			} else {
724				this.prepareElement( checkElement );
725				this.currentElements = $( checkElement );
726
727				// If this element is grouped, then validate all group elements already
728				// containing a value
729				group = this.groups[ checkElement.name ];
730				if ( group ) {
731					$.each( this.groups, function( name, testgroup ) {
732						if ( testgroup === group && name !== checkElement.name ) {
733							cleanElement = v.validationTargetFor( v.clean( v.findByName( name ) ) );
734							if ( cleanElement && cleanElement.name in v.invalid ) {
735								v.currentElements.push( cleanElement );
736								result = v.check( cleanElement ) && result;
737							}
738						}
739					} );
740				}
741
742				rs = this.check( checkElement ) !== false;
743				result = result && rs;
744				if ( rs ) {
745					this.invalid[ checkElement.name ] = false;
746				} else {
747					this.invalid[ checkElement.name ] = true;
748				}
749
750				if ( !this.numberOfInvalids() ) {
751
752					// Hide error containers on last error
753					this.toHide = this.toHide.add( this.containers );
754				}
755				this.showErrors();
756
757				// Add aria-invalid status for screen readers
758				$( element ).attr( "aria-invalid", !rs );
759			}
760
761			return result;
762		},
763
764		// http://jqueryvalidation.org/Validator.showErrors/
765		showErrors: function( errors ) {
766			if ( errors ) {
767				var validator = this;
768
769				// Add items to error list and map
770				$.extend( this.errorMap, errors );
771				this.errorList = $.map( this.errorMap, function( message, name ) {
772					return {
773						message: message,
774						element: validator.findByName( name )[ 0 ]
775					};
776				} );
777
778				// Remove items from success list
779				this.successList = $.grep( this.successList, function( element ) {
780					return !( element.name in errors );
781				} );
782			}
783			if ( this.settings.showErrors ) {
784				this.settings.showErrors.call( this, this.errorMap, this.errorList );
785			} else {
786				this.defaultShowErrors();
787			}
788		},
789
790		// http://jqueryvalidation.org/Validator.resetForm/
791		resetForm: function() {
792			if ( $.fn.resetForm ) {
793				$( this.currentForm ).resetForm();
794			}
795			this.invalid = {};
796			this.submitted = {};
797			this.prepareForm();
798			this.hideErrors();
799			var elements = this.elements()
800				.removeData( "previousValue" )
801				.removeAttr( "aria-invalid" );
802
803			this.resetElements( elements );
804		},
805
806		resetElements: function( elements ) {
807			var i;
808
809			if ( this.settings.unhighlight ) {
810				for ( i = 0; elements[ i ]; i++ ) {
811					this.settings.unhighlight.call( this, elements[ i ],
812						this.settings.errorClass, "" );
813					this.findByName( elements[ i ].name ).removeClass( this.settings.val
813idClass );
814				}
815			} else {
816				elements
817					.removeClass( this.settings.errorClass )
818					.removeClass( this.settings.validClass );
819			}
820		},
821
822		numberOfInvalids: function() {
823			return this.objectLength( this.invalid );
824		},
825
826		objectLength: function( obj ) {
827			/* jshint unused: false */
828			var count = 0,
829				i;
830			for ( i in obj ) {
831
832				// This check allows counting elements with empty error
833				// message as invalid elements
834				if ( obj[ i ] !== undefined && obj[ i ] !== null && obj[ i ] !== false ) {
835					count++;
836				}
837			}
838			return count;
839		},
840
841		hideErrors: function() {
842			this.hideThese( this.toHide );
843		},
844
845		hideThese: function( errors ) {
846			errors.not( this.containers ).text( "" );
847			this.addWrapper( errors ).hide();
848		},
849
850		valid: function() {
851			return this.size() === 0;
852		},
853
854		size: function() {
855			return this.errorList.length;
856		},
857
858		focusInvalid: function() {
859			if ( this.settings.focusInvalid ) {
860				try {
861					$( this.findLastActive() || this.errorList.length && this.errorList[ 0 ].element || [] )
862					.filter( ":visible" )
863					.focus()
864
865					// Manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
866					.trigger( "focusin" );
867				} catch ( e ) {
868
869					// Ignore IE throwing errors when focusing hidden elements
870				}
871			}
872		},
873
874		findLastActive: function() {
875			var lastActive = this.lastActive;
876			return lastActive && $.grep( this.errorList, function( n ) {
877				return n.element.name === lastActive.name;
878			} ).length === 1 && lastActive;
879		},
880
881		elements: function() {
882			var validator = this,
883				rulesCache = {};
884
885			// Select all valid inputs inside the form (no submit or reset buttons)
886			return $( this.currentForm )
887			.find( "input, select, textarea, [contenteditable]" )
888			.not( ":submit, :reset, :image, :disabled" )
889			.not( this.settings.ignore )
890			.filter( function() {
891				var name = this.name || $( this ).attr( "name" ); // For contenteditable
892				if ( !name && validator.settings.debug && window.console ) {
893					console.error( "%o has no name assigned", this );
894				}
895
896				// Set form expando on contenteditable
897				if ( this.hasAttribute( "contenteditable" ) ) {
898					this.form = $( this ).closest( "form" )[ 0 ];
899					this.name = name;
900				}
901
902				// Select only the first element for each name, and only those with rules specified
903				if ( name in rulesCache || !validator.objectLength( $( this ).rules() ) ) {
904					return false;
905				}
906
907				rulesCache[ name ] = true;
908				return true;
909			} );
910		},
911
912		clean: function( selector ) {
913			return $( selector )[ 0 ];
914		},
915
916		errors: function() {
917			var errorClass = this.settings.errorClass.split( " " ).join( "." );
918			return $( this.settings.errorElement + "." + errorClass, this.errorContext );
919		},
920
921		resetInternals: function() {
922			this.successList = [];
923			this.errorList = [];
924			this.errorMap = {};
925			this.toShow = $( [] );
926			this.toHide = $( [] );
927		},
928
929		reset: function() {
930			this.resetInternals();
931			this.currentElements = $( [] );
932		},
933
934		prepareForm: function() {
935			this.reset();
936			this.toHide = this.errors().add( this.containers );
937		},
938
939		prepareElement: function( element ) {
940			this.reset();
941			this.toHide = this.errorsFor( element );
942		},
943
944		elementValue: function( element ) {
945			var $element = $( element ),
946				type = element.type,
947				val, idx;
948
949			if ( type === "radio" || type === "checkbox" ) {
950				return this.findByName( element.name ).filter( ":checked" ).val();
951			} else if ( type === "number" && typeof element.validity !== "undefined" ) {
952				return element.validity.badInput ? "NaN" : $element.val();
953			}
954
955			if ( element.hasAttribute( "contenteditable" ) ) {
956				val = $element.text();
957			} else {
958				val = $element.val();
959			}
960
961			if ( type === "file" ) {
962
963				// Modern browser (chrome & safari)
964				if ( val.substr( 0, 12 ) === "C:\\fakepath\\" ) {
965					return val.substr( 12 );
966				}
967
968				// Legacy browsers
969				// Unix-based path
970				idx = val.lastIndexOf( "/" );
971				if ( idx >= 0 ) {
972					return val.substr( idx + 1 );
973				}
974
975				// Windows-based path
976				idx = val.lastIndexOf( "\\" );
977				if ( idx >= 0 ) {
978					return val.substr( idx + 1 );
979				}
980
981				// Just the file name
982				return val;
983			}
984
985			if ( typeof val === "string" ) {
986				return val.replace( /\r/g, "" );
987			}
988			return val;
989		},
990
991		check: function( element ) {
992			element = this.validationTargetFor( this.clean( element ) );
993
994			var rules = $( element ).rules(),
995				rulesCount = $.map( rules, function( n, i ) {
996					return i;
997				} ).length,
998				dependencyMismatch = false,
999				val = this.elementValue( element ),
1000				result, method, rule, normalizer;
1001
1002			// Prioritize the local normalizer defined for this element over the global one
1003			// if the former exists, otherwise user the global one in case it exists.
1004			if ( typeof rules.normalizer === "function" ) {
1005				normalizer = rules.normalizer;
1006			} else if (	typeof this.settings.normalizer === "function" ) {
1007				normalizer = this.settings.normalizer;
1008			}
1009
1010			// If normalizer is defined, then call it to retreive the changed value instead
1011			// of using the real one.
1012			// Note that `this` in the normalizer is `element`.
1013			if ( normalizer ) {
1014				val = normalizer.call( element, val );
1015
1016				if ( typeof val !== "string" ) {
1017					throw new TypeError( "The normalizer should return a string value." );
1018				}
1019
1020				// Delete the normalizer from rules to avoid treating it as a pre-defined method.
1021				delete rules.normalizer;
1022			}
1023
1024			for ( method in rules ) {
1025				rule = { method: method, parameters: rules[ method ] };
vendor: 4,525 bytes, lines 1026-1162
1026				try {
1027					result = $.validator.methods[ method ].call( this, val, element, rule.parameters );
1028
1029					// If a method indicates that the field is optional and therefore valid,
1030					// don't mark it as valid when there are no other rules
1031					if ( result === "dependency-mismatch" && rulesCount === 1 ) {
1032						dependencyMismatch = true;
1033						continue;
1034					}
1035					dependencyMismatch = false;
1036
1037					if ( result === "pending" ) {
1038						this.toHide = this.toHide.not( this.errorsFor( element ) );
1039						return;
1040					}
1041
1042					if ( !result ) {
1043						this.formatAndAdd( element, rule );
1044						return false;
1045					}
1046				} catch ( e ) {
1047					if ( this.settings.debug && window.console ) {
1048						console.log( "Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.", e );
1049					}
1050					if ( e instanceof TypeError ) {
1051						e.message += ".  Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.";
1052					}
1053
1054					throw e;
1055				}
1056			}
1057			if ( dependencyMismatch ) {
1058				return;
1059			}
1060			if ( this.objectLength( rules ) ) {
1061				this.successList.push( element );
1062			}
1063			return true;
1064		},
1065
1066		// Return the custom message for the given element and validation method
1067		// specified in the element's HTML5 data attribute
1068		// return the generic message if present and no method specific message is present
1069		customDataMessage: function( element, method ) {
1070			return $( element ).data( "msg" + method.charAt( 0 ).toUpperCase() +
1071				method.substring( 1 ).toLowerCase() ) || $( element ).data( "msg" );
1072		},
1073
1074		// Return the custom message for the given element name and validation method
1075		customMessage: function( name, method ) {
1076			var m = this.settings.messages[ name ];
1077			return m && ( m.constructor === String ? m : m[ method ] );
1078		},
1079
1080		// Return the first defined argument, allowing empty strings
1081		findDefined: function() {
1082			for ( var i = 0; i < arguments.length; i++ ) {
1083				if ( arguments[ i ] !== undefined ) {
1084					return arguments[ i ];
1085				}
1086			}
1087			return undefined;
1088		},
1089
1090		// The second parameter 'rule' used to be a string, and extended to an object literal
1091		// of the following form:
1092		// rule = {
1093		//     method: "method name",
1094		//     parameters: "the given method parameters"
1095		// }
1096		//
1097		// The old behavior still supported, kept to maintain backward compatibility with
1098		// old code, and will be removed in the next major release.
1099		defaultMessage: function( element, rule ) {
1100			if ( typeof rule === "string" ) {
1101				rule = { method: rule };
1102			}
1103
1104			var message = this.findDefined(
1105					this.customMessage( element.name, rule.method ),
1106					this.customDataMessage( element, rule.method ),
1107
1108					// 'title' is never undefined, so handle empty string as undefined
1109					!this.settings.ignoreTitle && element.title || undefined,
1110					$.validator.messages[ rule.method ],
1111					"<strong>Warning: No message defined for " + element.name + "</strong>"
1112				),
1113				theregex = /\$?\{(\d+)\}/g;
1114			if ( typeof message === "function" ) {
1115				message = message.call( this, rule.parameters, element );
1116			} else if ( theregex.test( message ) ) {
1117				message = $.validator.format( message.replace( theregex, "{$1}" ), rule.parameters );
1118			}
1119
1120			return message;
1121		},
1122
1123		formatAndAdd: function( element, rule ) {
1124			var message = this.defaultMessage( element, rule );
1125
1126			this.errorList.push( {
1127				message: message,
1128				element: element,
1129				method: rule.method
1130			} );
1131
1132			this.errorMap[ element.name ] = message;
1133			this.submitted[ element.name ] = message;
1134		},
1135
1136		addWrapper: function( toToggle ) {
1137			if ( this.settings.wrapper ) {
1138				toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
1139			}
1140			return toToggle;
1141		},
1142
1143		defaultShowErrors: function() {
1144			var i, elements, error;
1145			for ( i = 0; this.errorList[ i ]; i++ ) {
1146				error = this.errorList[ i ];
1147				if ( this.settings.highlight ) {
1148					this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
1149				}
1150				this.showLabel( error.element, error.message );
1151			}
1152			if ( this.errorList.length ) {
1153				this.toShow = this.toShow.add( this.containers );
1154			}
1155			if ( this.settings.success ) {
1156				for ( i = 0; this.successList[ i ]; i++ ) {
1157					this.showLabel( this.successList[ i ] );
1158				}
1159			}
1160			if ( this.settings.unhighlight ) {
1161				for ( i = 0, elements = this.validElements(); elements[ i ]; i++ ) {
1162					this.settings.unhighlight.call( this, elements[ i ], this.settings.errorClass, this.settings.val
1162idClass );
1163				}
1164			}
1165			this.toHide = this.toHide.not( this.toShow );
1166			this.hideErrors();
1167			this.addWrapper( this.toShow ).show();
1168		},
1169
1170		validElements: function() {
1171			return this.currentElements.not( this.invalidElements() );
1172		},
1173
1174		invalidElements: function() {
1175			return $( this.errorList ).map( function() {
1176				return this.element;
1177			} );
1178		},
1179
1180		showLabel: function( element, message ) {
1181			var place, group, errorID, v,
1182				error = this.errorsFor( element ),
1183				elementID = this.idOrName( element ),
1184				describedBy = $( element ).attr( "aria-describedby" );
1185
1186			if ( error.length ) {
1187
1188				// Refresh error/success class
1189				error.removeClass( this.settings.validClass ).addClass( this.settings.errorClass );
1190
1191				// Replace message on existing label
1192				error.html( message );
1193			} else {
1194
1195				// Create error element
1196				error = $( "<" + this.settings.errorElement + ">" )
1197					.attr( "id", elementID + "-error" )
1198					.addClass( this.settings.errorClass )
1199					.html( message || "" );
1200
1201				// Maintain reference to the element to be placed into the DOM
1202				place = error;
1203				if ( this.settings.wrapper ) {
1204
1205					// Make sure the element is visible, even in IE
1206					// actually showing the wrapped element is handled elsewhere
1207					place = error.hide().show().wrap( "<" + this.settings.wrapper + "/>" ).parent();
1208				}
1209				if ( this.labelContainer.length ) {
1210					this.labelContainer.append( place );
1211				} else if ( this.settings.errorPlacement ) {
1212					this.settings.errorPlacement.call( this, place, $( element ) );
1213				} else {
1214					place.insertAfter( element );
1215				}
1216
1217				// Link error back to the element
1218				if ( error.is( "label" ) ) {
1219
1220					// If the error is a label, then associate using 'for'
1221					error.attr( "for", elementID );
1222
1223					// If the element is not a child of an associated label, then it's necessary
1224					// to explicitly apply aria-describedby
1225				} else if ( error.parents( "label[for='" + this.escapeCssMeta( elementID ) + "']" ).length === 0 ) {
1226					errorID = error.attr( "id" );
1227
1228					// Respect existing non-error aria-describedby
1229					if ( !describedBy ) {
1230						describedBy = errorID;
1231					} else if ( !describedBy.match( new RegExp( "\\b" + this.escapeCssMeta( errorID ) + "\\b" ) ) ) {
1232
1233						// Add to end of list if not already present
1234						describedBy += " " + errorID;
1235					}
1236					$( element ).attr( "aria-describedby", describedBy );
1237
1238					// If this element is grouped, then assign to all elements in the same group
1239					group = this.groups[ element.name ];
1240					if ( group ) {
1241						v = this;
1242						$.each( v.groups, function( name, testgroup ) {
1243							if ( testgroup === group ) {
1244								$( "[name='" + v.escapeCssMeta( name ) + "']", v.currentForm )
1245									.attr( "aria-describedby", error.attr( "id" ) );
1246							}
1247						} );
1248					}
1249				}
1250			}
1251			if ( !message && this.settings.success ) {
1252				error.text( "" );
1253				if ( typeof this.settings.success === "string" ) {
1254					error.addClass( this.settings.success );
1255				} else {
1256					this.settings.success( error, element );
1257				}
1258			}
1259			this.toShow = this.toShow.add( error );
1260		},
1261
1262		errorsFor: function( element ) {
1263			var name = this.escapeCssMeta( this.idOrName( element ) ),
1264				describer = $( element ).attr( "aria-describedby" ),
1265				selector = "label[for='" + name + "'], label[for='" + name + "'] *";
1266
1267			// 'aria-describedby' should directly reference the error element
1268			if ( describer ) {
1269				selector = selector + ", #" + this.escapeCssMeta( describer )
1270					.replace( /\s+/g, ", #" );
1271			}
1272
1273			return this
1274				.errors()
1275				.filter( selector );
1276		},
1277
1278		// See https://api.jquery.com/category/selectors/, for CSS
1279		// meta-characters that should be escaped in order to be used with JQuery
1280		// as a literal part of a name/id or any selector.
1281		escapeCssMeta: function( string ) {
1282			return string.replace( /([\\!"#$%&'()*+,./:;<=>?@\[\]^`{|}~])/g, "\\$1" );
1283		},
1284
1285		idOrName: function( element ) {
1286			return this.groups[ element.name ] || ( this.checkable( element ) ? element.name : element.id || element.name );
1287		},
1288
1289		validationTargetFor: function( element ) {
1290
1291			// If radio/checkbox, validate first element in group instead
1292			if ( this.checkable( element ) ) {
1293				element = this.findByName( element.name );
1294			}
1295
1296			// Always apply ignore filter
1297			return $( element ).not( this.settings.ignore )[ 0 ];
1298		},
1299
1300		checkable: function( element ) {
1301			return ( /radio|checkbox/i ).test( element.type );
1302		},
1303
1304		findByName: function( name ) {
1305			return $( this.currentForm ).find( "[name='" + this.escapeCssMeta( name ) + "']" );
1306		},
1307
1308		getLength: function( value, element ) {
1309			switch ( element.nodeName.toLowerCase() ) {
1310			case "select":
1311				return $( "option:selected", element ).length;
1312			case "input":
1313				if ( this.checkable( element ) ) {
1314					return this.findByName( element.name ).filter( ":checked" ).length;
1315				}
1316			}
1317			return value.length;
1318		},
1319
1320		depend: function( param, element ) {
1321			return this.dependTypes[ typeof param ] ? this.dependTypes[ typeof param ]( param, element ) : true;
1322		},
1323
1324		dependTypes: {
1325			"boolean": function( param ) {
1326				return param;
1327			},
1328			"string": function( param, element ) {
1329				return !!$( param, element.form ).length;
1330			},
1331			"function": function( param, element ) {
1332				return param( element );
1333			}
1334		},
1335
1336		optional: function( element ) {
1337			var val = this.elementValue( element );
1338			return !$.validator.methods.required.call( this, val, element ) && "dependency-mismatch";
1339		},
1340
1341		startRequest: function( element ) {
1342			if ( !this.pending[ element.name ] ) {
1343				this.pendingRequest++;
1344				$( element ).addClass( this.settings.pendingClass );
1345				this.pending[ element.name ] = true;
1346			}
1347		},
1348
1349		stopRequest: function( element, valid ) {
1350			this.pendingRequest--;
1351
1352			// Sometimes synchronization fails, make sure pendingRequest is never < 0
1353			if ( this.pendingRequest < 0 ) {
1354				this.pendingRequest = 0;
1355			}
1356			delete this.pending[ element.name ];
1357			$( element ).removeClass( this.settings.pendingClass );
1358			if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) {
1359				$( this.currentForm ).submit();
1360				this.formSubmitted = false;
vendor: 13,084 bytes, lines 1361-1766
1361			} else if ( !valid && this.pendingRequest === 0 && this.formSubmitted ) {
1362				$( this.currentForm ).triggerHandler( "invalid-form", [ this ] );
1363				this.formSubmitted = false;
1364			}
1365		},
1366
1367		previousValue: function( element, method ) {
1368			method = typeof method === "string" && method || "remote";
1369
1370			return $.data( element, "previousValue" ) || $.data( element, "previousValue", {
1371				old: null,
1372				valid: true,
1373				message: this.defaultMessage( element, { method: method } )
1374			} );
1375		},
1376
1377		// Cleans up all forms and elements, removes validator-specific events
1378		destroy: function() {
1379			this.resetForm();
1380
1381			$( this.currentForm )
1382				.off( ".validate" )
1383				.removeData( "validator" )
1384				.find( ".validate-equalTo-blur" )
1385					.off( ".validate-equalTo" )
1386					.removeClass( "validate-equalTo-blur" );
1387		}
1388
1389	},
1390
1391	classRuleSettings: {
1392		required: { required: true },
1393		email: { email: true },
1394		url: { url: true },
1395		date: { date: true },
1396		dateISO: { dateISO: true },
1397		number: { number: true },
1398		digits: { digits: true },
1399		creditcard: { creditcard: true }
1400	},
1401
1402	addClassRules: function( className, rules ) {
1403		if ( className.constructor === String ) {
1404			this.classRuleSettings[ className ] = rules;
1405		} else {
1406			$.extend( this.classRuleSettings, className );
1407		}
1408	},
1409
1410	classRules: function( element ) {
1411		var rules = {},
1412			classes = $( element ).attr( "class" );
1413
1414		if ( classes ) {
1415			$.each( classes.split( " " ), function() {
1416				if ( this in $.validator.classRuleSettings ) {
1417					$.extend( rules, $.validator.classRuleSettings[ this ] );
1418				}
1419			} );
1420		}
1421		return rules;
1422	},
1423
1424	normalizeAttributeRule: function( rules, type, method, value ) {
1425
1426		// Convert the value to a number for number inputs, and for text for backwards compability
1427		// allows type="date" and others to be compared as strings
1428		if ( /min|max|step/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) {
1429			value = Number( value );
1430
1431			// Support Opera Mini, which returns NaN for undefined minlength
1432			if ( isNaN( value ) ) {
1433				value = undefined;
1434			}
1435		}
1436
1437		if ( value || value === 0 ) {
1438			rules[ method ] = value;
1439		} else if ( type === method && type !== "range" ) {
1440
1441			// Exception: the jquery validate 'range' method
1442			// does not test for the html5 'range' type
1443			rules[ method ] = true;
1444		}
1445	},
1446
1447	attributeRules: function( element ) {
1448		var rules = {},
1449			$element = $( element ),
1450			type = element.getAttribute( "type" ),
1451			method, value;
1452
1453		for ( method in $.validator.methods ) {
1454
1455			// Support for <input required> in both html5 and older browsers
1456			if ( method === "required" ) {
1457				value = element.getAttribute( method );
1458
1459				// Some browsers return an empty string for the required attribute
1460				// and non-HTML5 browsers might have required="" markup
1461				if ( value === "" ) {
1462					value = true;
1463				}
1464
1465				// Force non-HTML5 browsers to return bool
1466				value = !!value;
1467			} else {
1468				value = $element.attr( method );
1469			}
1470
1471			this.normalizeAttributeRule( rules, type, method, value );
1472		}
1473
1474		// 'maxlength' may be returned as -1, 2147483647 ( IE ) and 524288 ( safari ) for text inputs
1475		if ( rules.maxlength && /-1|2147483647|524288/.test( rules.maxlength ) ) {
1476			delete rules.maxlength;
1477		}
1478
1479		return rules;
1480	},
1481
1482	dataRules: function( element ) {
1483		var rules = {},
1484			$element = $( element ),
1485			type = element.getAttribute( "type" ),
1486			method, value;
1487
1488		for ( method in $.validator.methods ) {
1489			value = $element.data( "rule" + method.charAt( 0 ).toUpperCase() + method.substring( 1 ).toLowerCase() );
1490			this.normalizeAttributeRule( rules, type, method, value );
1491		}
1492		return rules;
1493	},
1494
1495	staticRules: function( element ) {
1496		var rules = {},
1497			validator = $.data( element.form, "validator" );
1498
1499		if ( validator.settings.rules ) {
1500			rules = $.validator.normalizeRule( validator.settings.rules[ element.name ] ) || {};
1501		}
1502		return rules;
1503	},
1504
1505	normalizeRules: function( rules, element ) {
1506
1507		// Handle dependency check
1508		$.each( rules, function( prop, val ) {
1509
1510			// Ignore rule when param is explicitly false, eg. required:false
1511			if ( val === false ) {
1512				delete rules[ prop ];
1513				return;
1514			}
1515			if ( val.param || val.depends ) {
1516				var keepRule = true;
1517				switch ( typeof val.depends ) {
1518				case "string":
1519					keepRule = !!$( val.depends, element.form ).length;
1520					break;
1521				case "function":
1522					keepRule = val.depends.call( element, element );
1523					break;
1524				}
1525				if ( keepRule ) {
1526					rules[ prop ] = val.param !== undefined ? val.param : true;
1527				} else {
1528					$.data( element.form, "validator" ).resetElements( $( element ) );
1529					delete rules[ prop ];
1530				}
1531			}
1532		} );
1533
1534		// Evaluate parameters
1535		$.each( rules, function( rule, parameter ) {
1536			rules[ rule ] = $.isFunction( parameter ) && rule !== "normalizer" ? parameter( element ) : parameter;
1537		} );
1538
1539		// Clean number parameters
1540		$.each( [ "minlength", "maxlength" ], function() {
1541			if ( rules[ this ] ) {
1542				rules[ this ] = Number( rules[ this ] );
1543			}
1544		} );
1545		$.each( [ "rangelength", "range" ], function() {
1546			var parts;
1547			if ( rules[ this ] ) {
1548				if ( $.isArray( rules[ this ] ) ) {
1549					rules[ this ] = [ Number( rules[ this ][ 0 ] ), Number( rules[ this ][ 1 ] ) ];
1550				} else if ( typeof rules[ this ] === "string" ) {
1551					parts = rules[ this ].replace( /[\[\]]/g, "" ).split( /[\s,]+/ );
1552					rules[ this ] = [ Number( parts[ 0 ] ), Number( parts[ 1 ] ) ];
1553				}
1554			}
1555		} );
1556
1557		if ( $.validator.autoCreateRanges ) {
1558
1559			// Auto-create ranges
1560			if ( rules.min != null && rules.max != null ) {
1561				rules.range = [ rules.min, rules.max ];
1562				delete rules.min;
1563				delete rules.max;
1564			}
1565			if ( rules.minlength != null && rules.maxlength != null ) {
1566				rules.rangelength = [ rules.minlength, rules.maxlength ];
1567				delete rules.minlength;
1568				delete rules.maxlength;
1569			}
1570		}
1571
1572		return rules;
1573	},
1574
1575	// Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
1576	normalizeRule: function( data ) {
1577		if ( typeof data === "string" ) {
1578			var transformed = {};
1579			$.each( data.split( /\s/ ), function() {
1580				transformed[ this ] = true;
1581			} );
1582			data = transformed;
1583		}
1584		return data;
1585	},
1586
1587	// http://jqueryvalidation.org/jQuery.validator.addMethod/
1588	addMethod: function( name, method, message ) {
1589		$.validator.methods[ name ] = method;
1590		$.validator.messages[ name ] = message !== undefined ? message : $.validator.messages[ name ];
1591		if ( method.length < 3 ) {
1592			$.validator.addClassRules( name, $.validator.normalizeRule( name ) );
1593		}
1594	},
1595
1596	// http://jqueryvalidation.org/jQuery.validator.methods/
1597	methods: {
1598
1599		// http://jqueryvalidation.org/required-method/
1600		required: function( value, element, param ) {
1601
1602			// Check if dependency is met
1603			if ( !this.depend( param, element ) ) {
1604				return "dependency-mismatch";
1605			}
1606			if ( element.nodeName.toLowerCase() === "select" ) {
1607
1608				// Could be an array for select-multiple or a string, both are fine this way
1609				var val = $( element ).val();
1610				return val && val.length > 0;
1611			}
1612			if ( this.checkable( element ) ) {
1613				return this.getLength( value, element ) > 0;
1614			}
1615			return value.length > 0;
1616		},
1617
1618		// http://jqueryvalidation.org/email-method/
1619		email: function( value, element ) {
1620
1621			// From https://html.spec.whatwg.org/multipage/forms.html#valid-e-mail-address
1622			// Retrieved 2014-01-14
1623			// If you have a problem with this implementation, report a bug against the above spec
1624			// Or use custom methods to implement your own email validation
1625			return this.optional( element ) || /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test( value );
1626		},
1627
1628		// http://jqueryvalidation.org/url-method/
1629		url: function( value, element ) {
1630
1631			// Copyright (c) 2010-2013 Diego Perini, MIT licensed
1632			// https://gist.github.com/dperini/729294
1633			// see also https://mathiasbynens.be/demo/url-regex
1634			// modified to allow protocol-relative URLs
1635			return this.optional( element ) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( value );
1636		},
1637
1638		// http://jqueryvalidation.org/date-method/
1639		date: function( value, element ) {
1640			return this.optional( element ) || !/Invalid|NaN/.test( new Date( value ).toString() );
1641		},
1642
1643		// http://jqueryvalidation.org/dateISO-method/
1644		dateISO: function( value, element ) {
1645			return this.optional( element ) || /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test( value );
1646		},
1647
1648		// http://jqueryvalidation.org/number-method/
1649		number: function( value, element ) {
1650			return this.optional( element ) || /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test( value );
1651		},
1652
1653		// http://jqueryvalidation.org/digits-method/
1654		digits: function( value, element ) {
1655			return this.optional( element ) || /^\d+$/.test( value );
1656		},
1657
1658		// http://jqueryvalidation.org/minlength-method/
1659		minlength: function( value, element, param ) {
1660			var length = $.isArray( value ) ? value.length : this.getLength( value, element );
1661			return this.optional( element ) || length >= param;
1662		},
1663
1664		// http://jqueryvalidation.org/maxlength-method/
1665		maxlength: function( value, element, param ) {
1666			var length = $.isArray( value ) ? value.length : this.getLength( value, element );
1667			return this.optional( element ) || length <= param;
1668		},
1669
1670		// http://jqueryvalidation.org/rangelength-method/
1671		rangelength: function( value, element, param ) {
1672			var length = $.isArray( value ) ? value.length : this.getLength( value, element );
1673			return this.optional( element ) || ( length >= param[ 0 ] && length <= param[ 1 ] );
1674		},
1675
1676		// http://jqueryvalidation.org/min-method/
1677		min: function( value, element, param ) {
1678			return this.optional( element ) || value >= param;
1679		},
1680
1681		// http://jqueryvalidation.org/max-method/
1682		max: function( value, element, param ) {
1683			return this.optional( element ) || value <= param;
1684		},
1685
1686		// http://jqueryvalidation.org/range-method/
1687		range: function( value, element, param ) {
1688			return this.optional( element ) || ( value >= param[ 0 ] && value <= param[ 1 ] );
1689		},
1690
1691		// http://jqueryvalidation.org/step-method/
1692		step: function( value, element, param ) {
1693			var type = $( element ).attr( "type" ),
1694				errorMessage = "Step attribute on input type " + type + " is not supported.",
1695				supportedTypes = [ "text", "number", "range" ],
1696				re = new RegExp( "\\b" + type + "\\b" ),
1697				notSupported = type && !re.test( supportedTypes.join() ),
1698				decimalPlaces = function( num ) {
1699					var match = ( "" + num ).match( /(?:\.(\d+))?$/ );
1700					if ( !match ) {
1701						return 0;
1702					}
1703
1704					// Number of digits right of decimal point.
1705					return match[ 1 ] ? match[ 1 ].length : 0;
1706				},
1707				toInt = function( num ) {
1708					return Math.round( num * Math.pow( 10, decimals ) );
1709				},
1710				valid = true,
1711				decimals;
1712
1713			// Works only for text, number and range input types
1714			// TODO find a way to support input types date, datetime, datetime-local, month, time and week
1715			if ( notSupported ) {
1716				throw new Error( errorMessage );
1717			}
1718
1719			decimals = decimalPlaces( param );
1720
1721			// Value can't have too many decimals
1722			if ( decimalPlaces( value ) > decimals || toInt( value ) % toInt( param ) !== 0 ) {
1723				valid = false;
1724			}
1725
1726			return this.optional( element ) || valid;
1727		},
1728
1729		// http://jqueryvalidation.org/equalTo-method/
1730		equalTo: function( value, element, param ) {
1731
1732			// Bind to the blur event of the target in order to revalidate whenever the target field is updated
1733			var target = $( param );
1734			if ( this.settings.onfocusout && target.not( ".validate-equalTo-blur" ).length ) {
1735				target.addClass( "validate-equalTo-blur" ).on( "blur.validate-equalTo", function() {
1736					$( element ).valid();
1737				} );
1738			}
1739			return value === target.val();
1740		},
1741
1742		// http://jqueryvalidation.org/remote-method/
1743		remote: function( value, element, param, method ) {
1744			if ( this.optional( element ) ) {
1745				return "dependency-mismatch";
1746			}
1747
1748			method = typeof method === "string" && method || "remote";
1749
1750			var previous = this.previousValue( element, method ),
1751				validator, data, optionDataString;
1752
1753			if ( !this.settings.messages[ element.name ] ) {
1754				this.settings.messages[ element.name ] = {};
1755			}
1756			previous.originalMessage = previous.originalMessage || this.settings.messages[ element.name ][ method ];
1757			this.settings.messages[ element.name ][ method ] = previous.message;
1758
1759			param = typeof param === "string" && { url: param } || param;
1760			optionDataString = $.param( $.extend( { data: value }, param.data ) );
1761			if ( previous.old === optionDataString ) {
1762				return previous.valid;
1763			}
1764
1765			previous.old = optionDataString;
1766			validator = this;
1767			this.startRequest( element );
1768			data = {};
1769			data[ element.name ] = value;
1770			$.ajax( $.extend( true, {
1771				mode: "abort",
1772				port: "validate" + element.name,
1773				dataType: "json",
1774				data: data,
1775				context: validator.currentForm,
1776				success: function( response ) {
1777					var valid = response === true || response === "true",
1778						errors, message, submitted;
1779
1780					validator.settings.messages[ element.name ][ method ] = previous.originalMessage;
1781					if ( valid ) {
1782						submitted = validator.formSubmitted;
1783						validator.resetInternals();
1784						validator.toHide = validator.errorsFor( element );
1785						validator.formSubmitted = submitted;
1786						validator.successList.push( element );
1787						validator.invalid[ element.name ] = false;
1788						validator.showErrors();
1789					} else {
1790						errors = {};
1791						message = response || validator.defaultMessage( element, { method: method, parameters: value } );
1792						errors[ element.name ] = previous.message = message;
1793						validator.invalid[ element.name ] = true;
1794						validator.showErrors( errors );
1795					}
1796					previous.valid = valid;
1797					validator.stopRequest( element, valid );
1798				}
1799			}, param ) );
1800			return "pending";
1801		}
1802	}
1803
1804} );
1805
1806// Ajax mode: abort
1807// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
1808// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
1809
1810var pendingRequests = {},
1811	ajax;
1812
1813// Use a prefilter if available (1.5+)
1814if ( $.ajaxPrefilter ) {
1815	$.ajaxPrefilter( function( settings, _, xhr ) {
1816		var port = settings.port;
1817		if ( settings.mode === "abort" ) {
1818			if ( pendingRequests[ port ] ) {
1819				pendingRequests[ port ].abort();
1820			}
1821			pendingRequests[ port ] = xhr;
1822		}
1823	} );
1824} else {
1825
1826	// Proxy ajax
1827	ajax = $.ajax;
1828	$.ajax = function( settings ) {
1829		var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
1830			port = ( "port" in settings ? settings : $.ajaxSettings ).port;
1831		if ( mode === "abort" ) {
1832			if ( pendingRequests[ port ] ) {
1833				pendingRequests[ port ].abort();
1834			}
1835			pendingRequests[ port ] = ajax.apply( this, arguments );
1836			return pendingRequests[ port ];
1837		}
1838		return ajax.apply( this, arguments );
1839	};
1840}
1841return $;
1842}));
1843(function( factory ) {
1844	if ( typeof define === "function" && define.amd ) {
1845		define( ["jquery", "../jquery.validate"], factory );
1846	} else if (typeof module === "object" && module.exports) {
1847		module.exports = factory( require( "jquery" ) );
1848	} else {
1849		factory( jQuery );
1850	}
1851}(function( $ ) {
1852
1853/*
1854 * Translated default messages for the jQuery validation plugin.
1855 * Locale: DE (German, Deutsch)
1856 */
1857$.extend( $.validator.messages, {
1858	required: "Dieses Feld ist ein Pflichtfeld.",
1859	maxlength: $.validator.format( "Geben Sie bitte maximal {0} Zeichen ein." ),
1860	minlength: $.validator.format( "Geben Sie bitte mindestens {0} Zeichen ein." ),
1861	rangelength: $.validator.format( "Geben Sie bitte mindestens {0} und maximal {1} Zeichen ein." ),
1862	email: "Geben Sie bitte eine gültige E-Mail Adresse ein.",
1863	url: "Geben Sie bitte eine gültige URL ein.",
1864	date: "Bitte geben Sie ein gültiges Datum ein.",
1865	number: "Geben Sie bitte eine Nummer ein.",
1866	digits: "Geben Sie bitte nur Ziffern ein.",
1867	equalTo: "Bitte denselben Wert wiederholen.",
1868	range: $.validator.format( "Geben Sie bitte einen Wert zwischen {0} und {1} ein." ),
1869	max: $.validator.format( "Geben Sie bitte einen Wert kleiner oder gleich {0} ein." ),
1870	min: $.validator.format( "Geben Sie bitte einen Wert größer oder gleich {0} ein." ),
1871	creditcard: "Geben Sie bitte eine gültige Kreditkarten-Nummer ein."
1872} );
1873return $;
1874}));
1875
1876$(document).ready(function () {
1877
1878    // validation
1879    $('form').each(function () {
1880
1881        // console.log( $(this).attr("id") + " _ " + $(this).attr("class") );
1882        var $thisForm = $(this);
1883
1884        $thisForm.validate({
1885            invalidHandler: function (event, validator) {
1886                // remove waiting spinner form submit button
1887                $thisForm.removeClass("submitting");
1888				/*
1889				// 'this' refers to the form
1890				var errors = validator.numberOfInvalids();
1891				if (errors) {
1892					var message = errors == 1
1893					? 'You missed 1 field. It has been highlighted'
1894					: 'You missed ' + errors + ' fields. They have been highlighted';
1895					$("div.error span").html(message);
1896					$("div.error").show();
1897				} else {
1898					$("div.error").hide();
1899				}
1900				*/
1901            },
1902            errorPlacement: function (error, element) {
1903                if (element.attr("type") == "checkbox") {
1904                    if ($(element).parents('.checkbox__error-container')) {
1905                        error.appendTo($(element).parents('.checkbox__error-container'));
1906                    } else {
1907                        error.appendTo($(element).closest('.form-group'));
1908                    }
1909                } else if (element.attr("type") == "radio") {
1910                    if ($(element).parents('.radio__error-container')) {
1911                        error.appendTo($(element).parents('.radio__error-container'));
1912                    } else {
1913                        error.appendTo($(element).closest('.form-group'));
1914                    }
1915                } else {
1916                    // something else if it's not a checkbox or radio
1917                    error.appendTo($(element).closest('.form-group'));
1918                }
1919            }
1920        });
1921
1922		// Require numbers for fields with data-field-type="number"
1923        $('[data-field-type="number"]', $thisForm).rules('add', {
1924			number: true
1925		});
1926
1927    });
1928
1929    // Require .TLD in email adresses
1930	/*
1931	$.validator.addMethod(
1932		'email',
1933			function(value, element){
1934			return this.optional(element) || /(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*")@((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}
1934\.?|[A-Z0-9-]{2,}\.?)$)|\[(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\]$/i.test(value);
1935	});
1936	*/
1937
1938    // TODO: Is this better than "validator.addMethod"?
1939    $.validator.methods.email = function (value, element) {
1940        return this.optional(element) || /(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*")@((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)$)|\[(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\]$/i.test(value);
1941    }
1942});
1943
1944
1945// MOLECULES
1946
1947// navigation-main: hover intent
1948
1949$(document).ready(function () {
1950    var $navLis = $(".first-level__item");
1951
1952    function over() {
1953        $(this).addClass("hoverIntent");
1954    }
1955
1956    function out() {
1957        $(this).removeClass("hoverIntent");
1958    }
1959
1960    $navLis.addClass("nohover");
1961
1962    $navLis.hoverIntent({
1963        over: over,
1964        out: out,
1965        timeout: 250,
1966    });
1967});
1968
1969// Accessible toggle for second level of main nav
1970
1971$(document).ready(function () {
1972    $(".sub-toggle").on("click", function (e) {
1973        if ($(this).parent("a").attr("aria-expanded") === "false") {
1974            $(this).parent("a").attr("aria-expanded", "true");
1975            $(this)
1976                .parent()
1977                .parent(".first-level__item")
1978                .addClass("hoverIntent");
1979            $(this).children().children("span").text("Menü schließen");
1980        } else {
1981            $(this).parent("a").attr("aria-expanded", "false");
1982            $(this).parent().parent().removeClass("hoverIntent");
1983            $(this).children().children("span").text("Menü öffnen");
1984        }
1985
1986        e.preventDefault();
1987        return false;
1988    });
1989});
1990
1991// Accessible toggle for mobile nav
1992
1993$(document).ready(function () {
1994    var $slideNavCheckbox = $("#slide-nav-checkbox-root");
1995    var $slideNavToggle = $("#slide-nav-trigger");
1996
1997    // uncheckAll();
1998
1999    $slideNavToggle.on("click", function (e) {
2000        if ($slideNavCheckbox.prop("checked") === false) {
2001            $slideNavCheckbox.prop("checked", true);
2002            $slideNavToggle.children("span").text("Menü"); // schließen
2003
2004            // console.log('new toggle is clicked to open');
2005            // console.log('root checkbox is ' + $slideNavCheckbox.prop( 'checked' ) );
2006        } else {
2007            $slideNavCheckbox.prop("checked", false);
2008            $slideNavToggle.children("span").text("Menü"); // öffnen
2009
2010            // console.log('new toggle is clicked to close');
2011            // console.log('root checkbox is ' + $slideNavCheckbox.prop( 'checked' ) );
2012        }
2013
2014        e.preventDefault();
2015        return false;
2016    });
2017});
2018
2019// navigation-mobile: close all sub-navs on close
2020
2021$(document).ready(function () {
2022    var $body = $("body");
2023    var $nav = $(".slide-nav-root");
2024    var $navCheckboxes = $nav.find(".slide-nav-checkbox");
2025    var $rootCheckbox = $("#slide-nav-checkbox-root");
2026
2027    $rootCheckbox.on("change", function (event) {
2028        if ($rootCheckbox.prop("checked") === true) {
2029            $body.addClass("slide-nav-open");
2030            console.log("root checkbox is checked");
2031        } else {
2032            $body.removeClass("slide-nav-open");
2033            $navCheckboxes.prop("checked", false);
2034            console.log("root checkbox is not checked");
2035        }
2036    });
2037});
2038
2039// navigation-mobile: scroll up on checkbox change
2040
2041$(document).ready(function () {
2042    var $navCheckboxes = $(".slide-nav-checkbox");
2043
2044    $navCheckboxes.on("change", function () {
2045        $(".slide-nav-root, .slide-nav-root *").scrollTop(0);
2046    });
2047});
2048
2049/*
2050
2051
2052$(document).ready(function() {
2053
2054	var labelId;
2055
2056	$('.pseudo-label').on('click', function(e) {
2057
2058		console.log('pseudo label was clicked');
2059       labelId = $(this).children('label').attr('for');
2060
2061       	$('#'+labelId).trigger('click');
2062
2063	   	e.preventDefault();
2064		return false
2065
2066	});
2067
2068});
2069*/
2070
2071/*
2072
2073$(document).ready(function() {
2074
2075	$('.slide-nav-checkbox').focus(function() {
2076
2077		$checkboxId = $(this).attr('id');
2078
2079		$('label[for="' + $checkboxId + '"]').addClass('has-focus');
2080
2081	}).blur(function() {
2082		$('label[for="' + $checkboxId + '"]').removeClass('has-focus');
2083	});
2084
2085});
2086*/
2087
2088// .parent('a')
2089
2090/*
2091$(document).ready(function () {
2092    var $navServiceClone = $('nav.service').find('li').clone();
2093    var $navSocialsClone = $('nav.socials').find('a').clone()
2094    var $navMobile = $('.slide-nav-root');
2095
2096    $navServiceClone.addClass('slide-nav-service');
2097    $navServiceClone.eq(0).addClass('slide-nav-service-first');
2098    $navServiceClone.eq($navServiceClone.length - 1).addClass('slide-nav-service-last');
2099
2100    $navSocialsClone.wrapAll('<li class="slide-nav-socials"></li>');
2101
2102    $navServiceClone.appendTo($navMobile.find('> ul'));
2103    $navSocialsClone.parent('li').appendTo($navMobile.find('> ul'));
2104});
2105*/
2106
2107/*
2108
2109$("#demo6").hoverIntent({
2110	over: makeTall,
2111	out: makeShort,
2112	selector: 'li'
2113});
2114*/
2115
2116$(document).ready(function () {
2117    $(".accordion__button button").each(function () {
2118        const $button = $(this);
2119        const $item = $button.parent().parent(".accordion__item");
2120        const $panel = $item.children(".accordion__panel");
2121        let isExpanded;
2122
2123        if (!$item || !$panel) return;
2124
2125        function init() {
2126            isExpanded = $item.hasClass("isExpanded");
2127            isExpanded ? openAccordion() : closeAccordion();
2128        }
2129
2130        function openAccordion() {
2131            $item.addClass("isExpanded");
2132            $button.attr("aria-expanded", "true");
2133            $panel.prop("hidden", false);
2134            isExpanded = true;
2135        }
2136
2137        function closeAccordion() {
2138            $item.removeClass("isExpanded");
2139            $button.attr("aria-expanded", "false");
2140            $panel.prop("hidden", true);
2141            isExpanded = false;
2142        }
2143
2144        function toggleAccordion() {
2145            if (isExpanded) {
2146                closeAccordion();
2147            } else {
2148                openAccordion();
2149            }
2150        }
2151
2152        $button.on("click", function (evt) {
2153            evt.preventDefault();
2154            toggleAccordion();
2155            return false;
2156        });
2157
2158        init();
2159    });
2160});
2161
2162$(document).ready(function () {
2163    var $carousel = $('.carousel__wrap');
2164    var $carousel_status = $('.carousel__status');
2165
2166    var $carousel_SlidesToShow = 3;
2167    var $carousel_SlidesToShow_Tablet = 2;
2168    var $carousel_SlidesToShow_Mobile = 1;
2169
2170    var $carousel_variableWidth = false;
2171    var $carousel_adaptiveHeight = false;
2172    var $carousel_centerMode = false;
2173
2174    // Getting current slide and total number of slides
2175    // for a compact replacement of the dot nav on mobile
2176    $('.carousel__wrap').on(
2177        'onLoad init reInit afterChange',
2178        function (event, slick, currentSlide, nextSlide) {
2179            // currentSlide is undefined on init
2180            // set it to 0 in this case (currentSlide is 0 based)
2181            var i = (currentSlide ? currentSlide : 0) + 1;
2182
2183            $carousel_status.html(
2184                '<span>' +
2185                    i +
2186                    '</span>' +
2187                    '/' +
2188                    '<span>' +
2189                    slick.slideCount +
2190                    '</span>'
2191            );
2192        }
2193    );
2194
2195    $('.carousel').each(function () {
2196        // Setting the max numbers of slides shown
2197        $carousel = $(this);
2198
2199        if ($(this).hasClass('carousel--col-1')) {
2200            $carousel_SlidesToShow = 1;
2201            $carousel_SlidesToShow_Tablet = 1;
2202            $carousel_SlidesToShow_Mobile = 1;
2203        }
2204
2205        if ($(this).hasClass('carousel--col-2')) {
2206            $carousel_SlidesToShow = 2;
2207            $carousel_SlidesToShow_Tablet = 2;
2208            $carousel_SlidesToShow_Mobile = 1;
2209        }
2210
2211        if ($(this).hasClass('carousel--col-4')) {
2212            $carousel_SlidesToShow = 4;
2213            $carousel_SlidesToShow_Tablet = 3;
2214            $carousel_SlidesToShow_Mobile = 2;
2215        }
2216
2217        if ($(this).hasClass('carousel--col-5')) {
2218            $carousel_SlidesToShow = 5;
2219            $carousel_SlidesToShow_Tablet = 3;
2220            $carousel_SlidesToShow_Mobile = 2;
2221        }
2222
2223        // Setting the handling of differently sized images
2224        if ($(this).hasClass('carousel--variable-width')) {
2225            $carousel_variableWidth = true;
2226        }
2227
2228        if ($(this).hasClass('carousel--center-mode')) {
2229            $carousel_centerMode = true;
2230        }
2231
2232        if ($(this).hasClass('carousel--adaptive-height')) {
2233            $carousel_adaptiveHeight = true;
2234            $carousel_SlidesToShow = 1;
2235            $carousel_SlidesToShow_Tablet = 1;
2236            $carousel_SlidesToShow_Mobile = 1;
2237        }
2238
2239        $('.carousel__wrap', this).slick({
2240            prevArrow:
2241                '<button type="button" class="slick-prev"><span class="sr-only">Vorheriges</span></button>',
2242            nextArrow:
2243                '<button type="button" class="slick-next"><span class="sr-only">Nächstes</span></button>',
2244            slidesToShow: $carousel_SlidesToShow,
2245            slidesToScroll: $carousel_SlidesToShow,
2246            arrows: true,
2247            prevArrow: $carousel.find('.carousel__prev'),
2248            nextArrow: $carousel.find('.carousel__next'),
2249            dots: true,
2250            appendDots: $carousel.find('.carousel__dots'),
2251            slide: '.carousel__item',
2252            fade: false,
2253            speed: 500,
2254            autoplay: false,
2255            autoplaySpeed: 5000,
2256            variableWidth: $carousel_variableWidth,
2257            centerMode: $carousel_centerMode,
2258            adaptiveHeight: $carousel_adaptiveHeight,
2259
2260            responsive: [
2261                {
2262                    breakpoint: 992,
2263                    settings: {
2264                        slidesToShow: $carousel_SlidesToShow_Tablet,
2265                        slidesToScroll: $carousel_SlidesToShow_Tablet,
2266                    },
2267                },
2268                {
2269                    breakpoint: 720,
2270                    settings: {
2271                        slidesToShow: $carousel_SlidesToShow_Mobile,
2272                        slidesToScroll: $carousel_SlidesToShow_Mobile,
2273                        dots: false,
2274                        variableWidth: false,
2275                        // adaptiveHeight: false,
2276                    },
2277                },
2278                {
2279                    breakpoint: 480,
2280                    settings: {
2281                        slidesToShow: 1,
2282                        slidesToScroll: 1,
2283                        dots: false,
2284                        variableWidth: false,
2285                        // adaptiveHeight: false,
2286                    },
2287                },
2288            ],
2289        });
2290
2291        $carousel_SlidesToShow = 3;
2292        $carousel_SlidesToShow_Tablet = 2;
2293        $carousel_SlidesToShow_Mobile = 1;
2294        $carousel_variableWidth = false;
2295        $carousel_adaptiveHeight = false;
2296        $carousel_centerMode = false;
2297    });
2298});
2299
2300(() => {
2301    const consentOpener = document.querySelector(".js-consent-dialog-opener");
2302
2303    if (!consentOpener) return;
2304
2305    consentOpener.addEventListener("click", (event) => {
2306        window.DPCookieConsent.popup.revoke();
2307    });
2308})();
2309
2310/**
2311 *
2312 * JavaScript 'polyfill' for HTML5's <details> and <summary> elements
2313 * and 'shim' to add accessiblity enhancements for all browsers
2314 *
2315 * http://caniuse.com/#feat=details
2316 */
2317
2318// import '../../vendor/polyfills/Function/prototype/bind'
2319// import '../../vendor/polyfills/Event' // addEventListener and event.target normaliziation
2320// import { generateUniqueID } from '../../common.js'
2321
2322var KEY_ENTER = 13;
2323var KEY_SPACE = 32;
2324
2325function Details($module) {
2326    this.$module = $module;
2327}
2328
2329Details.prototype.init = function () {
2330    if (!this.$module) {
2331        return;
2332    }
2333
2334    // If there is native details support, we want to avoid
2335    // running code to polyfill native behaviour.
2336    var hasNativeDetails = typeof this.$module.open === 'boolean';
2337
2338    if (hasNativeDetails) {
2339        return;
2340    }
2341
2342    this.polyfillDetails();
2343};
2344
2345Details.prototype.polyfillDetails = function () {
2346    var $module = this.$module;
2347
2348    // Save shortcuts to the inner summary and content elements
2349    var $summary = (this.$summary = $module
2350        .getElementsByTagName('summary')
2351        .item(0));
2352    var $content = (this.$content = $module
2353        .getElementsByTagName('div')
2354        .item(0));
2355
2356    // If <details> doesn't have a <summary> and a <div> representing the content
2357    // it means the required HTML structure is not met so the script will stop
2358    if (!$summary || !$content) {
2359        return;
2360    }
2361
2362    // If the content doesn't have an ID, assign it one now
2363    // which we'll need for the summary's aria-controls assignment
2364    if (!$content.id) {
2365        $content.id = 'details-content-' + generateUniqueID();
2366    }
2367
2368    // Add ARIA role="group" to details
2369    $module.setAttribute('role', 'group');
2370
2371    // Add role=button to summary
2372    $summary.setAttribute('role', 'button');
2373
2374    // Add aria-controls
2375    $summary.setAttribute('aria-controls', $content.id);
2376
2377    // Set tabIndex so the summary is keyboard accessible
2378    // for non-native elements
2379    //
2380    // We have to use the camelcase `tabIndex` property as there is a bug
2381    // in IE6/IE7 when we set the correct attribute lowercase:
2382    // See http://web.archive.org/web/20170120194036/http://www.saliences.com/browserBugs/tabIndex.html
2383    $summary.tabIndex = 0;
2384
2385    // Detect initial open state
2386    var openAttr = $module.getAttribute('open') !== null;
2387    if (openAttr === true) {
2388        $summary.setAttribute('aria-expanded', 'true');
2389        $content.setAttribute('aria-hidden', 'false');
2390    } else {
2391        $summary.setAttribute('aria-expanded', 'false');
2392        $content.setAttribute('aria-hidden', 'true');
2393        $content.style.display = 'none';
2394    }
2395
2396    // Bind an event to handle summary elements
2397    this.polyfillHandleInputs($summary, this.polyfillSetAttributes.bind(this));
2398};
2399
2400/**
2401 * Define a statechange function that updates aria-expanded and style.display
2402 * @param {object} summary element
2403 */
2404Details.prototype.polyfillSetAttributes = function () {
2405    var $module = this.$module;
2406    var $summary = this.$summary;
2407    var $content = this.$content;
2408
2409    var expanded = $summary.getAttribute('aria-expanded') === 'true';
2410    var hidden = $content.getAttribute('aria-hidden') === 'true';
2411
2412    $summary.setAttribute('aria-expanded', expanded ? 'false' : 'true');
2413    $content.setAttribute('aria-hidden', hidden ? 'false' : 'true');
2414
2415    $content.style.display = expanded ? 'none' : '';
2416
2417    var hasOpenAttr = $module.getAttribute('open') !== null;
2418    if (!hasOpenAttr) {
2419        $module.setAttribute('open', 'open');
2420    } else {
2421        $module.removeAttribute('open');
2422    }
2423
2424    return true;
2425};
2426
2427/**
2428 * Handle cross-modal click events
2429 * @param {object} node element
2430 * @param {function} callback function
2431 */
2432Details.prototype.polyfillHandleInputs = function (node, callback) {
2433    node.addEventListener('keypress', function (event) {
2434        var target = event.target;
2435        // When the key gets pressed - check if it is enter or space
2436        if (event.keyCode === KEY_ENTER || event.keyCode === KEY_SPACE) {
2437            if (target.nodeName.toLowerCase() === 'summary') {
2438                // Prevent space from scrolling the page
2439                // and enter from submitting a form
2440                event.preventDefault();
2441                // Click to let the click event do all the necessary action
2442                if (target.click) {
2443                    target.click();
2444                } else {
2445                    // except Safari 5.1 and under don't support .click() here
2446                    callback(event);
2447                }
2448            }
2449        }
2450    });
2451
2452    // Prevent keyup to prevent clicking twice in Firefox when using space key
2453    node.addEventListener('keyup', function (event) {
2454        var target = event.target;
2455        if (event.keyCode === KEY_SPACE) {
2456            if (target.nodeName.toLowerCase() === 'summary') {
2457                event.preventDefault();
2458            }
2459        }
2460    });
2461
2462    node.addEventListener('click', callback);
2463};
2464
2465$(document).ready(function () {
2466    if ($(".donationBar").length > 0) {
2467        $("body").addClass("has-donationBar");
2468    }
2469});
2470
2471$(document).ready(function () {
2472    $(".donationQuickSearch__input input").change(function () {
2473        $(".donationQuickSearch__btn-group .btn")
2474            .removeClass("btn-primary")
2475            .addClass("btn-secondary");
2476        $(this).addClass("is-active");
2477        $(".donationQuickSearch__amount").val($(this).val());
2478    });
2479
2480    $(".donationQuickSearch__btn-1").click(function () {
2481        $(".donationQuickSearch__input input").val("").removeClass("is-active");
2482        $(".donationQuickSearch__btn-group .btn")
2483            .removeClass("btn-primary")
2484            .addClass("btn-secondary");
2485        $(this).addClass("btn-primary").removeClass("btn-secondary");
2486        $(".donationQuickSearch__amount").val($(this).data("value"));
2487    });
2488
2489    $(".donationQuickSearch__btn-2").click(function () {
2490        $(".donationQuickSearch__input input").val("").removeClass("is-active");
2491        $(".donationQuickSearch__btn-group .btn")
2492            .removeClass("btn-primary")
2493            .addClass("btn-secondary");
2494        $(this).addClass("btn-primary").removeClass("btn-secondary");
2495        $(".donationQuickSearch__amount").val($(this).data("value"));
2496    });
2497
2498    $(".donationQuickSearch__btn-3").click(function () {
2499        $(".donationQuickSearch__input input").val("").removeClass("is-active");
2500        $(".donationQuickSearch__btn-group .btn")
2501            .removeClass("btn-primary")
2502            .addClass("btn-secondary");
2503        $(this).addClass("btn-primary").removeClass("btn-secondary");
2504        $(".donationQuickSearch__amount").val($(this).data("value"));
2505    });
2506
2507    $(".donationQuickSearch__btn-group .btn")
2508        .removeClass("btn-primary")
2509        .addClass("btn-secondary");
2510    if ($(".donationQuickSearch__amount").val() == 20) {
2511        $(".donationQuickSearch__btn-1")
2512            .removeClass("btn-secondary")
2513            .addClass("btn-primary");
2514    } else if ($(".donationQuickSearch__amount").val() == 50) {
2515        $(".donationQuickSearch__btn-2")
2516            .removeClass("btn-secondary")
2517            .addClass("btn-primary");
2518    } else if ($(".donationQuickSearch__amount").val() == 100) {
2519        $(".donationQuickSearch__btn-3")
2520            .removeClass("btn-secondary")
2521            .addClass("btn-primary");
2522    } else if ($(".donationQuickSearch__amount").val()) {
2523        $(".donationQuickSearch__input input")
2524            .val($(".donationQuickSearch__amount").val())
2525            .addClass("is-active");
2526    }
2527});
2528
2529$(document).ready(function () {
2530    $('.js-filter-reset').on('click', function (event) {
2531        event.preventDefault();
2532
2533        $('.filter input[type="text"], .filter input[type="search"]').val('');
2534
2535        $('.filter select').each(function () {
2536            if ($(this).attr('multiple')) {
2537                $('option', this).removeAttr('selected');
2538                $(this)
2539                    .parent()
2540                    .find('.optWrapper.multiple .options .selected')
2541                    .click();
2542            } else {
2543                $('option', this).removeAttr('selected');
2544                $(this).parent().find('.optWrapper .options li').eq(0).click();
2545            }
2546        });
2547    });
2548});
2549
2550$(document).ready(function () {
2551    var $heroSlideshow = $('.hero.hero--stage');
2552    var $slideshowPause = $('.js-hero__play');
2553
2554    $heroSlideshow.slick({
2555        prevArrow:
2556            '<button type="button" class="slick-prev"><span class="sr-only">Vorheriges</span></button>',
2557        nextArrow:
2558            '<button type="button" class="slick-next"><span class="sr-only">Nächstes</span></button>',
2559        slidesToShow: 1,
2560        slidesToScroll: 1,
2561        arrows: false,
2562        dots: true,
2563        slide: '.hero__item',
2564        adaptiveHeight: false,
2565        fade: false,
2566        speed: 500,
2567        autoplay: true,
2568        autoplaySpeed: 5000,
2569    });
2570
2571    $slideshowPause.on('click', function () {
2572        var $this = $(this);
2573
2574        $this.toggleClass('hero__play--is-paused');
2575
2576        if ($this.hasClass('hero__play--is-paused')) {
2577            $heroSlideshow.slick('slickPause');
2578            $this.text('Play');
2579        } else {
2580            $heroSlideshow.slick('slickPlay');
2581            $this.text('Pause');
2582            $heroSlideshow.slick('slickNext');
2583        }
2584    });
2585});
2586
2587/*
2588function copyToClipboard() {
2589    var copyText = document.getElementById("iban").textContent;
2590    navigator.clipboard.writeText(copyText).then(() => {
2591        // Alert the user that the action took place.
2592        // Nobody likes hidden stuff being done under the hood!
2593        document.getElementById("ibanButton").blur();
2594        document.getElementById("ibanTooltip").style.display = "block";
2595
2596        setTimeout(function () {
2597            document.getElementById("ibanTooltip").style.display = "none";
2598        }, 3000);
2599    });
2600}
2601*/
2602
2603$(document).ready(function(){
2604
2605
2606	$("a.lightbox").attr('rel','image-in-lightbox');
2607	$(".slideshow a.lightbox").attr('rel','slide-in-lightbox');
2608	$(".carousel a.lightbox").attr('rel','carousel-in-lightbox');
2609
2610
2611	// initialize fancybox
2612	$("a.lightbox").fancybox({
2613		margin: 0,
2614		padding: 80,
2615		autoSize: true,
2616		fitToView: true,
2617		fixed: false,
2618		openEffect: 'fade',
2619		closeEffect: 'fade',
2620		nextEffect: 'fade',
2621		prevEffect: 'fade',
2622		openSpeed: 250,
2623		closeSpeed: 250,
2624		nextSpeed: 250,
2625		prevSpeed: 250,
2626		arrows: true,
2627		closeBtn: true,
2628		loop: true,
2629		wrapCSS: 'gal-fancy',
2630		helpers:
2631		{
2632			title: {
2633				type: 'inside'
2634			},
2635			buttons: {
2636				position: 'bottom'
2637			}
2638		},
2639		beforeLoad: function(){
2640
2641			var obj = $(this.element);
2642			var caption = obj.attr('data-caption');
2643			var credits = obj.attr('data-credits');
2644			var download = obj.attr('data-download');
2645
2646			if ( obj.parent().hasClass("media") ) {
2647				if ( !caption ) caption = obj.parent().next().html();
2648				if ( !credits ) credits = obj.next().html();
2649			} else {
2650				if ( !caption ) caption = obj.parent().find(".caption").html();
2651				if ( !credits ) credits = obj.parent().find(".credits").html();
2652			}
2653
2654			var text = '';
2655			text += '<div class="text">';
2656			if(credits) text += '<p class="credits">' + credits + '</p>';
2657
2658			if(download) text += '<a href="' + download + '" title="Download starten" class="download" target="_blank">Download</a>';
2659
2660			if(caption) text += '<p class="caption">' + caption + '</p>';
2661
2662			text += '</div>';
2663
2664			this.title = (caption || credits || download) ? text : "";
2665
2666		},
2667		beforeShow: function(){
2668			// Disable right click
2669			$.fancybox.inner.bind("contextmenu", function(e){ return false; });
2670		}
2671
2672	});
2673});
2674
2675// Fade in sticky newsletter teaser
2676
2677$(document).ready(function(){
2678
2679	var $window = $(window);
2680	var $newsletterlSticky = $('.newsletter-sticky');
2681
2682	$window.bind("scroll", function() {
2683
2684	    if ($(this).scrollTop() > 400) {
2685	        $newsletterlSticky.addClass('is-visible');
2686	    } else {
2687	        $newsletterlSticky.removeClass('is-visible');
2688	    }
2689
2690	});
2691
2692});
2693
2694$(document).ready(function(){
2695	
2696	
2697		
2698});
2699
2700$(document).ready(function(){
2701	
2702	$(".footer__zip-search form").on("submit", function( event ){ 
2703		
2704		event.preventDefault();
2705		
2706		window.location = $(this).attr("action") + "#/search?url&plz=" + $("#inline-search__input").val();
2707		
2708	});
2709	
2710});
2711$(document).ready(function(){
2712	
2713	if( $(".share").length > 0 ){
2714	
2715		var currentLocation = encodeURIComponent( $("meta[property='og:url']").attr("content") );
2716		var currentTitle= encodeURIComponent( $("meta[property='og:title']").attr("content") );			
2717		var currentSiteName= encodeURIComponent( $("meta[property='og:site_name']").attr("content") );
2718		var currentDesc= encodeURIComponent( $("meta[property='og:description']").attr("content") );
2719		
2720		if(currentDesc == 'undefined') {
2721			currentDesc = '';
2722		}
2723		if (currentSiteName == 'undefined') {
2724			currentSiteName = '';
2725		}
2726	
2727		$(".share .share__icon--email").attr(
2728			"href",
2729			//'mailto:?subject=Empfehlung:' + mailURI
2730			'mailto:?subject=Empfehlung: ' + currentTitle + ' von ' + currentSiteName + '&body=' + currentTitle + '%0D%0A'+ currentDesc + '%0D%0A%0D%0A' + currentLocation
2731		);
2732	}
2733});
2734
2735// Set tabindex -1 on skip link target
2736
2737// Prevent Safari on iOS to jump back to skip link
2738// on subsequent "tab" when using voice over
2739
2740$(document).ready(function(){
2741
2742	$('.skip-link--content').click(function(e) {
2743
2744		e.preventDefault();
2745
2746		$('#content').attr('tabindex', '-1').focus();
2747	});
2748
2749});
2750
2751// show "reload cart button" if quantity in cart was changed
2752
2753$(document).ready(function() {
2754    $('.shop__item--input').on('change keyup paste', function() {
2755
2756        $('.btn--reload').addClass('shop__item--input-change');
2757        $('.shop__cart .icon-enabled').addClass('disabled');
2758    });
2759});
2760
2761class ElementHasLink {
2762    constructor($module) {
2763        this.$teaser = $module;
2764        this.$mainLink = this.$teaser.querySelector(".js-element-link");
2765
2766        // bind `this` to methods where needed
2767        this.addClickListener = this.addClickListener.bind(this);
2768        this.handleTeaserClick = this.handleTeaserClick.bind(this);
2769    }
2770    init() {
2771        if (!this.$teaser || !this.$mainLink) {
2772            return;
2773        }
2774        window.addEventListener("DOMContentLoaded", this.addClickListener);
2775    }
2776    addClickListener() {
2777        window.removeEventListener("DOMContentLoaded", this.addClickListener);
2778        const $clickables = this.$teaser.querySelectorAll("a, button");
2779
2780        // Listen for clicks on teaser
2781        this.$teaser.addEventListener("click", this.handleTeaserClick);
2782
2783        // Listen for clicks on clickable elements inside teaser
2784        $clickables.forEach(function ($clickable) {
2785            $clickable.addEventListener("click", function (event) {
2786                // Don’t bubble up and trigger main link when a button or link is clicked
2787                event.stopPropagation();
2788            });
2789        });
2790    }
2791    // Trigger main link when teaser is clicked, unless text
2792    // is being selected
2793    // TODO: handle clicks on modal buttons
2794    handleTeaserClick(event) {
2795        const noTextSelected = !window.getSelection().toString();
2796        // const isNotFancyBox = !event.target.hasAttribute('data-fancybox');
2797        // if (noTextSelected && isNotFancyBox) {
2798        if (noTextSelected) {
2799            this.$mainLink.click();
2800        }
2801    }
2802}
2803
2804// export default TeaserHasLink;
2805
2806const $elementsHasLink = document.getElementsByClassName("js-element-has-link");
2807for (const $elementHasLink of $elementsHasLink) {
2808    new ElementHasLink($elementHasLink).init();
2809}
2810
2811$(document).ready(function () {
2812    $(".teaser--masonary").imagesLoaded(function () {
2813        $(".teaser--masonary").isotope({
2814            itemSelector: ".teaser__item",
2815            percentPosition: true,
2816            stamp: ".stamp",
2817            masonry: {
2818                // use outer width of grid-sizer for columnWidth
2819                // columnWidth: 33.333333%
2820                columnWidth: ".grid-sizer",
2821            },
2822        });
2823    });
2824
2825    /*
2826	$(".teaser--fit-in-row").isotope(
2827		{
2828			itemSelector: '.teaser-item',
2829			layoutMode: 'fitRows'
2830		}
2831	);
2832	*/
2833
2834    // Teaser Slideshow - 2 columns
2835
2836    var $teaserSlideshow = $(".teaser--slideshow.teaser--col-2");
2837
2838    $teaserSlideshow.slick({
2839        prevArrow:
2840            '<button type="button" class="slick-prev"><span class="sr-only">Vorheriges</span></button>',
2841        nextArrow:
2842            '<button type="button" class="slick-next"><span class="sr-only">Nächstes</span></button>',
2843        slidesToShow: 1,
2844        slidesToScroll: 1,
2845        arrows: false,
2846        dots: true,
2847        slide: ".teaser__item",
2848        adaptiveHeight: false,
2849        fade: false,
2850        speed: 500,
2851        autoplay: false,
2852        autoplaySpeed: 5000,
2853        mobileFirst: true,
2854        responsive: [
2855            {
2856                breakpoint: 960,
2857                settings: {
2858                    slidesToShow: 2,
2859                    slidesToScroll: 2,
2860                    arrows: true,
2861                },
2862            },
2863        ],
2864    });
2865
2866    // Teaser Slideshow - 3 columns
2867
2868    var $teaserSlideshow = $(".teaser--slideshow.teaser--col-3");
2869
2870    $teaserSlideshow.slick({
2871        prevArrow:
2872            '<button type="button" class="slick-prev"><span class="sr-only">Vorheriges</span></button>',
2873        nextArrow:
2874            '<button type="button" class="slick-next"><span class="sr-only">Nächstes</span></button>',
2875        slidesToShow: 1,
2876        slidesToScroll: 1,
2877        arrows: false,
2878        dots: true,
2879        slide: ".teaser__item",
2880        adaptiveHeight: false,
2881        fade: false,
2882        speed: 500,
2883        autoplay: false,
2884        autoplaySpeed: 5000,
2885        mobileFirst: true,
2886        responsive: [
2887            {
2888                breakpoint: 640,
2889                settings: {
2890                    slidesToShow: 2,
2891                    slidesToScroll: 2,
2892                },
2893            },
2894            {
2895                breakpoint: 960,
2896                settings: {
2897                    slidesToShow: 3,
2898                    slidesToScroll: 3,
2899                    arrows: true,
2900                },
2901            },
2902        ],
2903    });
2904
2905    // Teaser Slideshow - 4 columns
2906
2907    var $teaserSlideshow = $(".teaser--slideshow.teaser--col-4");
2908
2909    $teaserSlideshow.slick({
2910        prevArrow:
2911            '<button type="button" class="slick-prev"><span class="sr-only">Vorheriges</span></button>',
2912        nextArrow:
2913            '<button type="button" class="slick-next"><span class="sr-only">Nächstes</span></button>',
2914        slidesToShow: 1,
2915        slidesToScroll: 1,
2916        arrows: false,
2917        dots: true,
2918        slide: ".teaser__item",
2919        adaptiveHeight: false,
2920        fade: false,
2921        speed: 500,
2922        autoplay: false,
2923        autoplaySpeed: 5000,
2924        mobileFirst: true,
2925        responsive: [
2926            {
2927                breakpoint: 480,
2928                settings: {
2929                    slidesToShow: 2,
2930                    slidesToScroll: 2,
2931                },
2932            },
2933            {
2934                breakpoint: 720,
2935                settings: {
2936                    slidesToShow: 3,
2937                    slidesToScroll: 3,
2938                },
2939            },
2940            {
2941                breakpoint: 960,
2942                settings: {
2943                    slidesToShow: 4,
2944                    slidesToScroll: 4,
2945                },
2946            },
2947        ],
2948    });
2949
2950    // Teaser Slideshow - 5 columns
2951
2952    var $teaserSlideshow = $(".teaser--slideshow.teaser--col-5");
2953
2954    $teaserSlideshow.slick({
2955        prevArrow:
2956            '<button type="button" class="slick-prev"><span class="sr-only">Vorheriges</span></button>',
2957        nextArrow:
2958            '<button type="button" class="slick-next"><span class="sr-only">Nächstes</span></button>',
2959        slidesToShow: 1,
2960        slidesToScroll: 1,
2961        arrows: false,
2962        dots: true,
2963        slide: ".teaser__item",
2964        adaptiveHeight: false,
2965        fade: false,
2966        speed: 500,
2967        autoplay: false,
2968        autoplaySpeed: 5000,
2969        mobileFirst: true,
2970        responsive: [
2971            {
2972                breakpoint: 480,
2973                settings: {
2974                    slidesToShow: 2,
2975                    slidesToScroll: 2,
2976                },
2977            },
2978            {
2979                breakpoint: 720,
2980                settings: {
2981                    slidesToShow: 3,
2982                    slidesToScroll: 3,
2983                },
2984            },
2985            {
2986                breakpoint: 960,
2987                settings: {
2988                    slidesToShow: 4,
2989                    slidesToScroll: 4,
2990                },
2991            },
2992            {
2993                breakpoint: 1200,
2994                settings: {
2995                    slidesToShow: 5,
2996                    slidesToScroll: 5,
2997                },
2998            },
2999        ],
3000    });
3001
3002    // Teaser Slideshow - Speaker
3003
3004    var $teaserSlideshowSpeaker = $(".teaser--slideshow.teaser--speaker");
3005
3006    $teaserSlideshowSpeaker.slick({
3007        prevArrow:
3008            '<button type="button" class="slick-prev"><span class="sr-only">Vorheriges</span></button>',
3009        nextArrow:
3010            '<button type="button" class="slick-next"><span class="sr-only">Nächstes</span></button>',
3011        slidesToShow: 1,
3012        slidesToScroll: 1,
3013        arrows: false,
3014        dots: true,
3015        slide: ".teaser__item",
3016        adaptiveHeight: false,
3017        fade: false,
3018        speed: 500,
3019        autoplay: false,
3020        autoplaySpeed: 5000,
3021        mobileFirst: true,
3022        responsive: [
3023            {
3024                breakpoint: 960,
3025                settings: {
3026                    slidesToShow: 2,
3027                    slidesToScroll: 2,
3028                },
3029            },
3030        ],
3031    });
3032});
3033
3034$(document).ready(function () {
3035    /*
3036	$(".media-group.top").isotope(
3037		{
3038			itemSelector: '.media',
3039			layoutMode: 'fitRows'
3040		}
3041	);
3042
3043	$(".media-group.above").isotope(
3044		{
3045			itemSelector: '.media',
3046			layoutMode: 'fitRows'
3047		}
3048	);
3049
3050	$(".media-group.bottom").isotope(
3051		{
3052			itemSelector: '.media',
3053			layoutMode: 'fitRows'
3054		}
3055	);
3056	*/
3057
3058    $(".textrow table").each(function () {
3059        $(this).wrap(
3060            '<div class="tableWrapOuter"><div class="tableWrapInner"></div></div>'
3061        );
3062    });
3063});
3064
3065/**
3066 * Table of Contents
3067 *
3068 * Automatically generate a table of contents from the headings on the page.
3069 *
3070 * @param  {String} content A selector for the element that the content is in
3071 * @param  {String} target  The selector for the container to render the table of contents into
3072 * @param  {Object} options An object of user options [optional]
3073 */
3074
3075var tableOfContents = function (content, target, options) {
3076	// Where to look for the headings to generate a table of contens from
3077	var contentWrap = document.querySelector(content);
3078
3079	// Where to append the generated table of contens
3080	var toc = document.querySelector(target);
3081
3082	if (!contentWrap || !toc) return;
3083
3084	// Settings & Defaults
3085	var defaults = {
3086		tocId: 'toc',
3087		tocClass: 'toc',
3088		toclistClass: 'toc__list', // Class name of the outer list
3089		tocListType: 'ol',
3090		levels: 'h2, h3', // The heading levels to generate a TOC from
3091		backToToc: false,
3092		backToTocClass: 'back-to-toc',
3093		backToTocText: 'Inhaltsverzeichnis',
3094		backToTopSelector: '.top-scroll__fixed ',
3095	};
3096
3097	var settings = {};
3098	var headings;
3099
3100	/**
3101	 * Merge user options into defaults.
3102	 *
3103	 * @param  {Object} obj The user options
3104	 */
3105
3106	var merge = function (obj) {
3107		for (var key in defaults) {
3108			if (Object.prototype.hasOwnProperty.call(defaults, key)) {
3109				settings[key] = Object.prototype.hasOwnProperty.call(obj, key)
3110					? obj[key]
3111					: defaults[key];
3112			}
3113		}
3114	};
3115
3116	/**
3117	 * Create an ID for a heading if one does not exist
3118	 *
3119	 * @param  {Node} heading The heading element
3120	 * @todo Handle umlauts instead of just dropping them
3121	 */
3122
3123	var createID = function (heading) {
3124		if (heading.id.length) return;
3125		heading.id = heading.innerText.toLowerCase().replace(/[^A-Za-z0-9]/g, '-');
3126	};
3127
3128	/**
3129	 * Get the HTML to indent a list a specific number of levels
3130	 *
3131	 * @param  {Integer} count The number of times to indent the list
3132	 * @return {String} The HTML
3133	 */
3134
3135	var getIndent = function (count) {
3136		var html = '';
3137		for (var i = 0; i < count; i++) {
3138			html += '<' + settings.tocListType + '>';
3139		}
3140		return html;
3141	};
3142
3143	/**
3144	 * Get the HTML to close an indented list a specific number of levels
3145	 *
3146	 * @param  {Integer} count The number of times to "outdent" the list
3147	 * @return {String} The HTML
3148	 */
3149
3150	var getOutdent = function (count) {
3151		var html = '';
3152		for (var i = 0; i < count; i++) {
3153			html += '</' + settings.tocListType + '></li>';
3154		}
3155		return html;
3156	};
3157
3158	/**
3159	 * Get the HTML string to start a new list of headings
3160	 *
3161	 * @param  {Integer} diff  The number of levels in or out from the current level the list is
3162	 * @param  {Integer} index The index of the heading in the "headings" NodeList
3163	 * @return {String} The HTML
3164	 */
3165
3166	var getStartingHTML = function (diff, index) {
3167		// If indenting
3168		if (diff > 0) {
3169			return getIndent(diff);
3170		}
3171
3172		// If outdenting
3173		if (diff < 0) {
3174			return getOutdent(Math.abs(diff));
3175		}
3176
3177		// If it's not the first item and there's no difference
3178		if (index && !diff) {
3179			return '</li>';
3180		}
3181
3182		return '';
3183	};
3184
3185	/**
3186	 * Inject the back-to-top link’s HTML into the DOM
3187	 */
3188
3189	var injectBackToToc = function () {
3190		// Get the current URL without any possible hash
3191		var currentURL = window.location.href.split('#')[0];
3192
3193		// Create the HTML
3194		var backToTocHTML = document.createElement('a');
3195
3196		backToTocHTML.classList.add(settings.backToTocClass);
3197		backToTocHTML.setAttribute('href', currentURL + '#' + settings.tocId);
3198		backToTocHTML.textContent += settings.backToTocText;
3199
3200		// Inject the HTML
3201		document.body.appendChild(backToTocHTML);
3202	};
3203
3204	/**
3205	 * Inject the toc’s HTML into the DOM
3206	 */
3207
3208	var injectToc = function () {
3209		// Get the current URL without any possible hash
3210		var currentURL = window.location.href.split('#')[0];
3211
3212		// Get the current heading level
3213		var level = headings[0].tagName.slice(1);
3214		var startingLevel = level;
3215
3216		// Cache the number of headings
3217		var len = headings.length - 1;
3218
3219		// Create the HTML
3220		var tocHTML =
3221			'<' +
3222			settings.tocListType +
3223			' class="' +
3224			settings.toclistClass +
3225			// '" id="' +
3226			// settings.tocId +
3227			'">' +
3228			Array.prototype.map
3229				.call(headings, function (heading, index) {
3230					// Add an ID if none is present
3231					createID(heading);
3232
3233					// Check the heading level vs. the current list
3234					var currentLevel = heading.tagName.slice(1);
3235					var levelDifference = currentLevel - level;
3236
3237					level = currentLevel;
3238
3239					var HTML = getStartingHTML(levelDifference, index);
3240
3241					// Generate the list HTML
3242					HTML +=
3243						'<li>' +
3244						'<a href="' +
3245						currentURL +
3246						'#' +
3247						heading.id +
3248						'">' +
3249						heading.innerText.trim() +
3250						'</a>';
3251
3252					// If the last item, close it
3253					if (index === len) {
3254						HTML += getOutdent(Math.abs(startingLevel - currentLevel));
3255					}
3256
3257					return HTML;
3258				})
3259				.join('') +
3260			'</' +
3261			settings.tocListType +
3262			'>';
3263
3264		// Inject the HTML into the DOM
3265		toc.innerHTML = tocHTML;
3266	};
3267
3268	/**
3269	 * Initialize the TOC
3270	 */
3271
3272	var init = function () {
3273		// Merge user settings into the defaults
3274		merge(options || {});
3275
3276		// Get all heading candidates
3277		headings = contentWrap.querySelectorAll(settings.levels);
3278		if (!headings.length) return;
3279
3280		// Inject the TOC
3281		injectToc();
3282
3283		// Inject the back-to-toc link
3284		if (settings.backToToc) injectBackToToc();
3285	};
3286
3287	init();
3288};
3289
3290tableOfContents('.article', '.js-toc', {
3291	levels: 'h2, h3',
3292	backToToc: true,
3293});
3294
3295$(document).ready(function () {
3296    // Top Button Fixed
3297    var $window = $(window);
3298    var offsetTop = $window.height() / 4;
3299
3300    var $donate = $(".donationBar");
3301    var $toc = $(".back-to-toc");
3302    var $top = $(
3303        '<div class="top-scroll__fixed"><span class="sr-only">Zum Seitenanfang</span></div>'
3304    ).appendTo("body");
3305
3306    $top.on("click", function (event) {
3307        // Disable native smooth scroll before scrolling with velocity
3308        // Scroll easing is buggy when native smooth scroll is set
3309        $("html").css("scroll-behavior", "auto");
3310
3311        $("body").velocity("scroll", {
3312            duration: 800,
3313        });
3314
3315        // Reenable native smooth scroll
3316        setTimeout(function () {
3317            $("html").css("scroll-behavior", "smooth");
3318        }, 1000);
3319    });
3320
3321    function topVisible(event) {
3322        var windowScrollTop = $window.scrollTop();
3323
3324        if (windowScrollTop > offsetTop && topVisible.state !== true) {
3325            topVisible.state = true;
3326
3327            $top.addClass("is-visible");
3328            $toc.addClass("is-visible");
3329            $donate.addClass("is-visible");
3330        } else if (windowScrollTop <= offsetTop && topVisible.state !== false) {
3331            topVisible.state = false;
3332
3333            $top.removeClass("is-visible");
3334            $toc.removeClass("is-visible");
3335            $donate.removeClass("is-visible");
3336        }
3337    }
3338
3339    topVisible.state = undefined;
3340
3341    $window.on("scroll.top", topVisible);
3342
3343    topVisible();
3344});
3345
3346
3347// ORGANISMS
3348
3349$(document).ready(function(){
3350
3351	var $fbslide = $('.js-facebookstream__slider');
3352
3353	$fbslide.slick({
3354
3355		prevArrow: '<button type="button" class="slick-prev"><span class="sr-only">Vorheriges</span></button>',
3356		nextArrow: '<button type="button" class="slick-next"><span class="sr-only">Nächstes</span></button>',
3357		arrows : false,
3358		dots: true,
3359		slide : '.js-facebookstream__item',
3360		adaptiveHeight: false,
3361		fade: false,
3362		speed: 500,
3363		autoplay : true,
3364		autoplaySpeed : 5000,
3365		variableWidth : false,
3366		slidesToShow:3,
3367		slidesToScroll:3,
3368		responsive : [
3369			{
3370			breakpoint: 960,
3371				settings: {
3372					slidesToShow: 2,
3373					slidesToScroll: 2
3374				}
3375			},{
3376			breakpoint: 640,
3377				settings: {
3378					adaptiveHeight: true,
3379					autoplay : false,
3380					slidesToShow: 1,
3381					slidesToScroll: 1
3382				}
3383			}
3384		]
3385
3386	});
3387
3388});
3389$(document).ready(function() {
3390
3391	if ($('.header').length > 0) {
3392
3393	    var $window = $(window);
3394
3395	    function checkWidth() {
3396
3397	        var windowsize = $window.width();
3398
3399	        if (windowsize > 960) {
3400
3401	            var $header = $('.header');
3402				var $headerSticky = $('.header__bottom')
3403
3404			    $headerSticky.elementDirectionAndOffsetByScroll('init', {
3405			        offsetSmall : $header.outerHeight() - $headerSticky.outerHeight(), // Best practice: header-height - header-small-height
3406			        offsetOut : $header.outerHeight() * 1 // Best practice: header-height,
3407
3408			    });
3409
3410	        } else {
3411
3412		        var $header = $('.header');
3413				var $headerSticky = $('.header__middle')
3414
3415			    $headerSticky.elementDirectionAndOffsetByScroll('init', {
3416			        offsetSmall : $header.outerHeight() - $headerSticky.outerHeight(), // Best practice: header-height - header-small-height
3417			        offsetOut : $header.outerHeight() * 1 // Best practice: header-height,
3418
3419			    });
3420	        }
3421	    }
3422
3423	    checkWidth();
3424
3425	    $(window).resize(checkWidth);
3426
3427    }
3428});
3429
3430// Get Publication Shop Item's Width and set it's Height Accordingly
3431
3432$(document).ready(pubHeight);
3433$(window).on('resize',pubHeight);
3434
3435function pubHeight() {
3436     $('.shop-detail .publication-wrap').each(function() {
3437        $(this).height($(this).outerWidth());
3438    });
3439}
3440
3441
3442
3443// showing/hiding additional form fields during checkout
3444
3445$(document).ready(function() {
3446
3447	if ($("#alt-shipping-toggle").prop("checked") === true) {
3448
3449		// showing additional form fields
3450		$(".alt-shipping").show();
3451
3452		// setting shown form fields to required
3453		$("input.alt-shipping__required").prop("required", true);
3454	}
3455
3456	$("#alt-shipping-toggle").click(function() {
3457		if ($(this).prop("checked") === true) {
3458
3459			// showing additional form fields
3460			$(".alt-shipping").show();
3461
3462			// setting shown form fields to required
3463			$("input.alt-shipping__required").prop("required", true);
3464		} else {
3465
3466			// removing focus and clearing content of hidden form fields
3467			$(".alt-shipping input")
3468				.blur()
3469				.val("");
3470
3471			// hiding additional form fields again
3472			$(".alt-shipping").hide();
3473
3474			// setting hidden form fields to not required
3475			$("input.alt-shipping__required").prop("required", false);
3476		}
3477	});
3478});
3479
3480
3481$(document).ready(function() {
3482
3483	if ($("#alt-billing-toggle").prop("checked") === true) {
3484
3485		// showing additional form fields
3486		$(".alt-billing").show();
3487
3488		// setting shown form fields to required
3489		$("input.alt-billing__required").prop("required", true);
3490	}
3491
3492	$("#alt-billing-toggle").click(function() {
3493		if ($(this).prop("checked") === true) {
3494
3495			// showing additional form fields
3496			$(".alt-billing").show();
3497
3498			// setting shown form fields to required
3499			$("input.alt-billing__required").prop("required", true);
3500		} else {
3501
3502			// removing focus and clearing content of hidden form fields
3503			$(".alt-billing input")
3504				.blur()
3505				.val("");
3506
3507			// hiding additional form fields again
3508			$(".alt-billing").hide();
3509
3510			// setting hidden form fields to not required
3511			$("input.alt-billing__required").prop("required", false);
3512		}
3513	});
3514});
3515
3516
3517
3518
3519
3520// show "reload cart button" if quantity in cart was changed
3521
3522$(document).ready(function() {
3523
3524	$('.item__quantity__input').on('change keyup paste', function () {
3525
3526		$('.reload-cart').addClass('cart-has-changed');
3527
3528	});
3529});
3530
3531$(document).ready(function() {
3532
3533	if (!$("#form-termine-register")) return;
3534
3535	$(".company").hide();
3536	$(".email-organization").hide();
3537	$("#company").prop('required', false);
3538	$("#email2").prop('required', false);
3539	
3540	$('input[name="tx_lfseminars_registration[newRegistration][addressType]"]').on("change", function() {
3541
3542		if (this.value == 'company') {
3543			$(".company").show();
3544			$("#company").attr("required", true);
3545			$(".email-organization").show();
3546			$("#email2").attr("required", true);
3547			$('.note-company').show()
3548			$('.note-company').siblings().hide()
3549		} else {
3550			$(".company").hide();
3551			$(".email-organization").hide();
3552			$("#company").prop('required', false);
3553			$("#email2").prop('required',false);
3554			$("#company").val("");
3555			$("#email2").val("");
3556			$('.note-company').hide();
3557			$('.note-company').siblings().show();
3558		}
3559	})
3560});
3561
3562

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.