/* Source common/js/lib/02_device.js */ // DEVICE // ------------------------------------------------------------------------------------------------- (function(document, navigator, window) { var $html = document.querySelector('html'); function _find(needle) { return navigator.userAgent.toLowerCase().indexOf(needle) !== -1; } window.device = {}; device.iphone = _find('iphone'); device.ipod = _find('ipod'); device.ipad = _find('ipad'); device.ios = device.iphone || device.ipod || device.ipad; device.android = _find('android'); device.android_phone = device.android && _find('mobile'); device.android_tablet = device.android && !_find('mobile'); device.windows = _find('windows'); device.windows_phone = device.windows && _find('phone'); device.windows_tablet = device.windows && _find('touch'); device.mobile = device.android_phone || device.iphone || device.ipod || device.windows_phone; device.tablet = device.ipad || device.android_tablet || device.windows_tablet; if (device.ios) { if (device.ipad) { $html.classList.add('ios', 'ipad', 'tablet'); } else if (device.iphone || device.ipod) { $html.classList.add('ios', 'iphone', 'mobile'); } } else if (device.android) { if (device.android_tablet) { $html.classList.add('android', 'tablet'); } else { $html.classList.add('android', 'mobile'); } } else if (device.windows) { if (device.windows_tablet) { $html.classList.add('windows', 'tablet'); } else if (device.windows_phone) { $html.classList.add('windows', 'mobile'); } else { $html.classList.add('desktop'); } } else { $html.classList.add('desktop'); } }(document, navigator, window)); /* Source common/js/lib/03_support.js */ // BROWSER SUPPORT // ------------------------------------------------------------------------------------------------- (function(document, navigator, window) { var $html = document.querySelector('html'), $div = document.createElement('div'); // Überprüft die Browser-Unterstützung für CSS-Attribute wie z. B. transition function _has_css_property(property) { var css_property_found = false, prefixes = ['Moz', 'Webkit']; if (property in $div.style) { css_property_found = true; } else { property = property.charAt(0).toUpperCase() + property.substr(1); for (var i = 0, len = prefixes.length; i < len; i++) { if (typeof $div.style[prefixes[i] + property] !== 'undefined') { css_property_found = true; break; } } } return css_property_found; } window.support = { touch : window.navigator.msMaxTouchPoints || 'ontouchstart' in document.documentElement, transition : _has_css_property('transition') && 'TransitionEvent' in window }; // Setzt Klassen auf den HTML-Tag $html.classList.remove('no_js'); $html.classList.add(support.touch ? 'touch' : 'no_touch'); }(document, navigator, window)); /* Source common/js/lib/04_performance.js */ // PREFETCH // ------------------------------------------------------------------------------------------------- (function(document) { var Prefetch = function($prefetch_link) { var _this = this; _this._$prefetch_link = $prefetch_link; _this._$options = _this._$prefetch_link.getAttribute('data-performance'); }; Prefetch.prototype = { init: function() { var _this = this; if (_this._$options.indexOf('prefetch') > -1) { _this._prefetch(); } if (_this._$options.indexOf('prerender') > -1) { _this._prerender(); } }, _prefetch: function() { var _this = this, $link = document.createElement('link'); $link.setAttribute('rel', 'prefetch'); $link.setAttribute('href', _this._$prefetch_link.getAttribute('href')); document.querySelector('head').appendChild($link); }, _prerender: function() { var _this = this, $link = document.createElement('link'); $link.setAttribute('rel', 'prerender'); $link.setAttribute('href', _this._$prefetch_link.getAttribute('href')); document.querySelector('head').appendChild($link); } }; var $prefetch_links = document.querySelectorAll('[data-performance]'); for (var i = 0, len = $prefetch_links.length; i < len; i++) { new Prefetch($prefetch_links[i]).init(); } })(document); /* Source common/js/lib/05_accessibility.js */ // BARRIEREFREIHEIT // Wird gebraucht für alle Projekte // EXTERNER LINK // ------------------------------------------------------------------------------------------------- (function(document) { var $links = document.querySelectorAll('[href*=http]'); for (var i = 0, $link; $link = $links[i]; i++) { var target = $link.getAttribute('target'), title = $link.getAttribute('title'); if (title && target === '_blank') { $link.setAttribute('title', title + ' (Neues Fenster)'); } } })(document); // TASTATURSTEUERUNG FÜR ELEMENTE MIT ROLE BUTTON // ------------------------------------------------------------------------------------------------- (function(document) { var $buttons = document.querySelectorAll('[role="button"]'); for (var i = 0, $button; $button = $buttons[i]; i++) { $button.addEventListener('keyup', function(event) { if (event.keyCode === 13 && this.tagName !== 'A' || event.keyCode === 32) { this.click(); } }); } })(document); // ERKENNUNG DER FOKUSMETHODE FÜR LINKS // Wird verwendet für verbesserten Fokus auf Links (siehe default.less) // ------------------------------------------------------------------------------------------------- (function(document) { var FocusMethod = function($link) { var _this = this; _this.$link = $link; _this.focus_method = false; _this.last_focus_method = false; }; FocusMethod.prototype = { init: function() { var _this = this; _this.$link.addEventListener('keydown', _this._on_key_down.bind(this), { 'passive' : true } ); _this.$link.addEventListener('mousedown', _this._on_mouse_down.bind(this), { 'passive' : true } ); _this.$link.addEventListener('touchstart', _this._on_touch_start.bind(this), { 'passive' : true } ); _this.$link.addEventListener('focus', _this._on_focus.bind(this)); _this.$link.addEventListener('blur', _this._on_blur.bind(this)); window.addEventListener('blur', this._on_window_blur.bind(this)); }, _on_key_down: function() { var _this = this; _this.focus_method = 'key'; }, _on_mouse_down: function() { var _this = this; if (_this.focus_method === 'touch') { return; } _this.focus_method = 'mouse'; }, _on_touch_start: function() { var _this = this; _this.focus_method = 'touch'; }, _on_focus: function() { var _this = this; if (!_this.focus_method) { _this.focus_method = _this.last_focus_method; } _this.$link.setAttribute('data-focus-method', _this.focus_method); this.last_focus_method = this.focus_method; this.focus_method = false; }, _on_blur: function() { var _this = this; _this.$link.removeAttribute('data-focus-method'); }, _on_window_blur: function() { var _this = this; _this.focus_method = false; } }; var $links = document.querySelectorAll('a, [tabindex="0"]'); for (var i = 0, $link; $link = $links[i]; i++) { new FocusMethod($link).init(); } })(document); /* Source common/js/lib/07_smooth_scroll.js */ // SANFTES SCROLLEN // ------------------------------------------------------------------------------------------------- (function (document, window) { var SmoothScroll = function ($link) { var _this = this; _this.$link = $link; _this.has_animationend_event = false; }, offset_top = 170; function _get_offset_top($target) { var $obj = $target, top_position = $obj.offsetTop; while ($obj = $obj.offsetParent) { top_position += $obj.offsetTop; } return top_position; } function _remove_highlight_class($highlighted_target) { if ($highlighted_target.has_animationend_event) { return; } $highlighted_target.addEventListener('animationend', function (event) { if (event.target !== this) { return; } $highlighted_target.has_animationend_event = true; $highlighted_target.classList.remove('highlighted'); }); } function _scroll_to($target, offset, $callback) { var top_position = _get_offset_top($target) - offset, duration = 300, $highlighted_target, interval; if ($target.getAttribute('name')) { $highlighted_target = $target.parentElement; } else { $highlighted_target = $target; } interval = setInterval(function () { var diff = top_position - window.pageYOffset, step = diff / duration * 10; if (Math.abs(diff) <= Math.abs(step)) { clearInterval(interval); $highlighted_target.classList.add('highlighted'); if (typeof $callback === 'function') { $callback(); } } window.scrollBy(0, step); duration -= 10; }, 10); _remove_highlight_class($highlighted_target); } function _auto_scroll() { var hash = location.hash, parameter = location.search, $target; if (hash.length <= 1) { return; } $target = document.querySelector(hash) || document.querySelector('a[name="' + hash.slice(1) + '"]'); if (!$target || $target.classList.contains('no_smooth_scroll')) { return; } location.hash = ''; // IE und Edge Bug - Scroll beginnt nicht am Seitenanfang window.history.replaceState(null, document.title, location.pathname + parameter); setTimeout(function () { // Firefox Bug - Scroll beginnt nicht am Seitenanfang window.scrollTo(0, 0); _scroll_to($target, offset_top, function () { $target.focus(); window.history.replaceState(null, document.title, parameter + hash); }); }, 10); } SmoothScroll.prototype = { init: function () { var _this = this; if (_this.$link.classList.contains('no_smooth_scroll')) { return; } if (_this.$link.tagName === 'A') { _this._click_link(); } else { _this._change_select(); } }, _click_link: function () { var _this = this; _this.$link.addEventListener('click', function (event) { var hash = this.getAttribute('href'), parameter, $parameter, $hash, $target; if (hash.length === 1) { return; } $hash = hash.split('#'); $parameter = $hash[0].split('?'); parameter = $parameter.length === 2 ? '?' + $parameter[1] : ''; hash = $hash[1]; $target = document.querySelector('#' + hash) || document.querySelector('a[name="' + hash + '"]'); if (!$target) { return; } event.preventDefault(); _scroll_to($target, offset_top, function () { $target.focus(); window.history.replaceState(null, document.title, parameter + '#' + hash); }); }); }, _change_select: function () { var _this = this; _this.$link.addEventListener('change', function (event) { var hash = this.options[this.selectedIndex].value, $target; if (hash.length === 1) { return; } hash = hash.split('#')[1]; $target = document.querySelector('#' + hash) || document.querySelector('a[name="' + hash + '"]'); if (!$target) { return; } event.preventDefault(); _scroll_to($target, offset_top, function () { $target.focus(); window.history.replaceState(null, document.title, hash); }); }); } }; var $links = document.querySelectorAll('a, select'); for (var i = 0, len = $links.length; i < len; i++) { new SmoothScroll($links[i]).init(); } window.addEventListener('load', function () { _auto_scroll(); }) })(document, window); /* Source common/js/lib/20_form_helpers.js */ // FORMULARE // ------------------------------------------------------------------------------------------------- (function() { var FormHelpers = function($element) { var _this = this; _this.$el = $element; }; FormHelpers.prototype = { init: function() { var _this = this; _this._file_upload(); _this._select(); }, _file_upload: function() { var _this = this; if (_this.$el.getAttribute('type') !== 'file') { return; } var $parent_node = _this.$el.parentNode, $file_name = $parent_node.querySelector('.file_name'), $file_button = $parent_node.querySelector('.file_button'); _this.$el.addEventListener('focus', function() { $file_button.classList.add('focus'); }); _this.$el.addEventListener('blur', function() { $file_button.classList.remove('focus'); }); _this.$el.addEventListener('change', function() { $file_name.innerHTML = _this.$el.files[0].name; }); }, _select: function() { var _this = this; if (_this.$el.tagName !== 'SELECT') { return; } // parent must have class 'select' _this.$el.addEventListener('focus', function() { _this.$el.parentNode.classList.add('focus'); }); // parent must have class 'select' _this.$el.addEventListener('blur', function() { _this.$el.parentNode.classList.remove('focus'); }); } }; var $form_elements = document.querySelectorAll('input, select, textarea'); for (var i = 0, len = $form_elements.length; i < len; i++) { new FormHelpers($form_elements[i]).init(); } })(); /* Source common/js/lib/21_form_validation.js */ // FORM VALIDIERUNG // ------------------------------------------------------------------------------------------------- (function(document, window) { var FormValidation = function($form) { var _this = this; _this._$form = $form; _this._$inputs = _this._$form.querySelectorAll('input.validate, textarea.validate'); _this._$inputs_checkbox = _this._$form.querySelectorAll('input[type=checkbox][required]'); _this._$inputs_checkbox_wrapper = _this._$form.querySelectorAll('.checkbox_wrapper.required'); _this._$selects = _this._$form.querySelectorAll('select[required]'); _this._$button = _this._$form.querySelector('[type="submit"]'); _this._$error_msg_button = _this._$form.querySelector('.error_msg_button'); }; FormValidation.prototype = { init: function() { var _this = this; _this._$form.noValidate = true; for (var j = 0, inputs_len = _this._$inputs.length; j < inputs_len; j++) { var $input = this._$inputs[j]; $input.addEventListener('keyup', _this._input_keyup.bind(_this, $input)); $input.addEventListener('blur', _this._input_blur.bind(_this, $input)); } for (var i = 0, inputs_checkbox_len = _this._$inputs_checkbox.length; i < inputs_checkbox_len; i++) { var $input_checkbox = this._$inputs_checkbox[i]; $input_checkbox.addEventListener('click', _this._input_checkbox_click.bind(_this, $input_checkbox)); $input_checkbox.addEventListener('keyup', _this._input_checkbox_keyup.bind(_this, $input_checkbox)); $input_checkbox.addEventListener('blur', _this._input_checkbox_blur.bind(_this, $input_checkbox)); } for (var k = 0, inputs_checkbox_wrapper_len = _this._$inputs_checkbox_wrapper.length; k < inputs_checkbox_wrapper_len; k++) { var $inputs_checkbox_wrapper = _this._$inputs_checkbox_wrapper[k]; var $wrapped_checkboxes = $inputs_checkbox_wrapper.querySelectorAll('input[type=checkbox]'); for (var l = 0, wrapped_checkboxes_len = $wrapped_checkboxes.length; l < wrapped_checkboxes_len; l++) { var $wrapped_checkbox = $wrapped_checkboxes[l]; $wrapped_checkbox.addEventListener('click', _this._input_wrapped_checkbox_click.bind(_this, $wrapped_checkbox, $inputs_checkbox_wrapper)); $wrapped_checkbox.addEventListener('keyup', _this._input_wrapped_checkbox_keyup.bind(_this, $wrapped_checkbox, $inputs_checkbox_wrapper)); } } for (var x = 0, selects_len = _this._$selects.length; x < selects_len; x++) { var $select = this._$selects[x]; $select.addEventListener('change', _this._select_change.bind(_this, $select)); $select.addEventListener('blur', _this._select_blur.bind(_this, $select)); } _this._$form.addEventListener('submit', _this._submit.bind(_this)); _this._check_submit_status(); }, _input_keyup: function($input, event) { if (event.keyCode === 9 || event.keyCode === 27) { // No validation on TAB or ESC return; } this._validate_input($input, event); }, _input_blur: function($input, event) { this._validate_input($input, event); }, _validate_input: function($input, event) { var _this = this, id = $input.getAttribute('id'), $error_warning = document.querySelector('[for="' + id + '"] .error_warning'), min = parseInt($input.getAttribute('min')), pattern = $input.getAttribute('pattern'), regexp = new RegExp(pattern), value = $input.value; if ($input.type === 'file') { _this._validate_input_file($input); } else if (value) { if (pattern && value.match(regexp) || value >= min || !pattern && $input.required) { $input.setAttribute('aria-invalid', 'false'); if (!event || event.type === 'blur') { $input.classList.remove('error'); if ($error_warning) { $error_warning.classList.remove('show'); } } } else { $input.setAttribute('aria-invalid', 'true'); if (!event || event.type === 'blur') { $input.classList.add('error'); if ($error_warning) { $error_warning.classList.add('show'); } } } } else if ($input.required) { $input.setAttribute('aria-invalid', 'true'); if (!event || event.type === 'blur') { $input.classList.add('error'); if ($error_warning) { $error_warning.classList.add('show'); } } } else { $input.setAttribute('aria-invalid', 'false'); if (!event || event.type === 'blur') { $input.classList.remove('error'); if ($error_warning) { $error_warning.classList.remove('show'); } } } _this._check_submit_status(); }, _validate_input_file: function($input) { var _this = this, id = $input.getAttribute('id'), $error_warning = document.querySelector('[for="' + id + '"] .error_warning'), value = $input.value; while ($input && $input.nodeType !== 9) { $input = $input.parentNode; if ($input.classList.contains('file')) { break; } } if (value) { $input.classList.remove('error'); if ($error_warning) { $error_warning.classList.remove('show'); } } else { $input.classList.add('error'); if ($error_warning) { $error_warning.classList.add('show'); } } _this._check_submit_status(); }, _input_checkbox_click: function($input_checkbox, event) { this._validate_input_checkbox($input_checkbox, event); }, _input_checkbox_keyup: function($input_checkbox, event) { if (event.keyCode === 32) { // SPACE this._validate_input_checkbox($input_checkbox, event); } }, _input_checkbox_blur: function($input_checkbox, event) { this._validate_input_checkbox($input_checkbox, event); }, _validate_input_checkbox: function($input_checkbox, event) { var _this = this, id = $input_checkbox.getAttribute('id'), $error_warning = document.querySelector('#label_' + id + ' .error_warning'); if ($input_checkbox.checked && !event || $input_checkbox.checked && event && event.type !== 'keyup' || !$input_checkbox.checked && event && event.type === 'keyup') { $input_checkbox.setAttribute('aria-invalid', 'false'); $input_checkbox.classList.remove('error'); $error_warning.classList.remove('show'); } else { $input_checkbox.setAttribute('aria-invalid', 'true'); $input_checkbox.classList.add('error'); $error_warning.classList.add('show'); } _this._check_submit_status(); }, _input_wrapped_checkbox_click: function($wrapped_checkbox, $parent, event) { this._validate_input_checkbox_wrapper($parent, event); }, _input_wrapped_checkbox_keyup: function($wrapped_checkbox, $parent, event) { if (event.keyCode === 32) { // SPACE this._validate_input_checkbox($parent, event); } }, _input_wrapped_checkbox_blur: function($wrapped_checkbox, $parent, event) { this._validate_input_checkbox($parent, event); }, _validate_input_checkbox_wrapper: function($inputs_checkbox_wrapper) { var _this = this, id = $inputs_checkbox_wrapper.getAttribute('id'), $error_warning = document.querySelector('#label_' + id + ' .error_warning'), $checked_checkboxes = $inputs_checkbox_wrapper.querySelectorAll('input[type=checkbox]:checked'); if ($checked_checkboxes.length >= 1) { $inputs_checkbox_wrapper.setAttribute('aria-invalid', 'false'); $inputs_checkbox_wrapper.classList.remove('error'); $error_warning.classList.remove('show'); } else { $inputs_checkbox_wrapper.setAttribute('aria-invalid', 'true'); $inputs_checkbox_wrapper.classList.add('error'); $error_warning.classList.add('show'); } _this._check_submit_status(); }, _select_change: function($select, event) { this._validate_select($select, event); }, _select_blur: function($select, event) { this._validate_select($select, event); }, _validate_select: function($select, event) { var _this = this, id = $select.getAttribute('id'), $wrapper = $select, $error_warning = document.querySelector('#label_' + id + ' .error_warning'), value = $select.value; while ($wrapper && $wrapper.nodeType !== 9) { $wrapper = $wrapper.parentNode; if ($wrapper.classList.contains('select')) { break; } } if (value) { $select.setAttribute('aria-invalid', 'false'); if (!event || event.type === 'blur') { $wrapper.classList.remove('error'); $error_warning.classList.remove('show'); } } else { $select.setAttribute('aria-invalid', 'true'); if (!event || event.type === 'blur') { $wrapper.classList.add('error'); $error_warning.classList.add('show'); } } _this._check_submit_status(); }, _check_submit_status: function() { var _this = this, error_msg_button_id = _this._$error_msg_button.getAttribute('id'), enable_submit_button = true; for (var j = 0, inputs_len = _this._$inputs.length; j < inputs_len; j++) { if (_this._$inputs[j].getAttribute('aria-invalid') === 'true' || _this._$inputs[j].required && !_this._$inputs[j].value) { enable_submit_button = false; break; } } for (var k = 0, inputs_checkbox_wrapper_len = _this._$inputs_checkbox_wrapper.length; k < inputs_checkbox_wrapper_len; k++) { if (_this._$inputs_checkbox_wrapper[k].getAttribute('aria-invalid') === 'true') { enable_submit_button = false; break; } } for (var i = 0, inputs_checkbox_len = _this._$inputs_checkbox.length; i < inputs_checkbox_len; i++) { if (!_this._$inputs_checkbox[i].checked) { enable_submit_button = false; break; } } for (var x = 0, selects_len = _this._$selects.length; x < selects_len; x++) { if (!_this._$selects[x].value) { enable_submit_button = false; break; } } if (enable_submit_button) { _this._$button.classList.remove('disabled'); _this._$button.removeAttribute('aria-describedby'); } else { _this._$button.classList.add('disabled'); _this._$button.setAttribute('aria-describedby', error_msg_button_id); } }, _show_first_error: function() { var _this = this, $first_input_error = _this._$form.querySelector('[aria-invalid="true"]'), top_position = 0, offset_top = 60, duration = 300, interval, $obj; if ($first_input_error) { $obj = $first_input_error; top_position = $obj.offsetTop - offset_top; while ($obj = $obj.offsetParent) { top_position += $obj.offsetTop; } if (window.pageYOffset < top_position) { $first_input_error.focus(); return; } interval = setInterval(function() { var diff = top_position - window.pageYOffset, step = diff / duration * 10; if (Math.abs(diff) <= Math.abs(step)) { $first_input_error.focus(); clearInterval(interval); } window.scrollBy(0, step); duration -= 10; }, 10); } }, _submit: function(event) { var _this = this; _this._check_submit_status(); if (_this._$button.classList.contains('disabled')) { event.preventDefault(); for (var j = 0, inputs_len = _this._$inputs.length; j < inputs_len; j++) { _this._validate_input(this._$inputs[j]); } for (var i = 0, inputs_checkbox_len = _this._$inputs_checkbox.length; i < inputs_checkbox_len; i++) { _this._validate_input_checkbox(this._$inputs_checkbox[i]); } for (var k = 0, inputs_checkbox_wrapper_len = _this._$inputs_checkbox_wrapper.length; k < inputs_checkbox_wrapper_len; k++) { _this._validate_input_checkbox_wrapper(this._$inputs_checkbox_wrapper[k]); } for (var x = 0, selects_len = _this._$selects.length; x < selects_len; x++) { _this._validate_select(this._$selects[x]); } _this._show_first_error(); } } }; var $forms = document.querySelectorAll('[data-form*="validate"]'); for (var i = 0, len = $forms.length; i < len; i++) { new FormValidation($forms[i]).init(); } })(document, window); /* Source common/js/lib/22_form_cache.js */ // FORMULARE: EINGABE ZWISCHENSPEICHERN // Wird verwendet für: formular // ------------------------------------------------------------------------------------------------- (function(document) { var FormCache = function($form) { var _this = this; _this._$form = $form; _this._form_name = _this._$form.getAttribute('data-form-cache'); _this._$inputs = _this._$form.querySelectorAll('input, select, textarea'); _this._$cache = {}; }; FormCache.prototype = { init: function() { var _this = this; _this._init_events(); _this._restore_cache(); }, _init_events: function() { var _this = this, $input, type, event_listener; for (var i = 0, len = _this._$inputs.length; i < len; i++) { $input = _this._$inputs[i]; type = $input.type; if (type === 'checkbox') { event_listener = 'click'; } else if (type === 'select-one') { event_listener = 'change'; } else { event_listener = 'input'; } $input.addEventListener(event_listener, _this._save_cache.bind(_this, $input), false); } _this._$form.addEventListener('submit', _this._reset_cache.bind(_this), false); }, _save_cache: function($input) { var _this = this, name = $input.getAttribute('name'), type = $input.type; if (type === 'checkbox') { _this._$cache[name] = $input.checked; } else if (type === 'select-one') { _this._$cache[name] = $input.selectedIndex; } else if (type !== 'file') { // files/filepaths should not be cached _this._$cache[name] = $input.value; } localStorage.setItem(domain + '_form_cache_' + _this._form_name, JSON.stringify(_this._$cache)); }, _restore_cache: function() { var _this = this, $cache = localStorage.getItem(domain + '_form_cache_' + _this._form_name), $input, type; if (!$cache) { return; } _this._$cache = JSON.parse($cache); for (var key in _this._$cache) { if (_this._$cache.hasOwnProperty(key)) { $input = _this._$form.querySelector('[name="' + key + '"]'); type = $input.type; if (type === 'checkbox') { $input.checked = _this._$cache[key]; } else if (type === 'select-one') { $input.selectedIndex = _this._$cache[key]; } else { $input.value = _this._$cache[key]; } } } }, _reset_cache: function() { var _this = this, is_valid = true; for (var i = 0, len = _this._$inputs.length; i < len; i++) { if (_this._$inputs[i].getAttribute('aria-invalid') === 'true') { is_valid = false; break; } } if (is_valid) { localStorage.removeItem(domain + '_form_cache_' + _this._form_name); } } }; var $forms = document.querySelectorAll('[data-form-cache]'); for (var i = 0, len = $forms.length; i < len; i++) { new FormCache($forms[i]).init(); } })(document); /* Source common/js/lib/23_form_textarea_autogrow.js */ // FORMULARE: TEXTAREA AUTOGROW // Wird gebraucht für alle