(function() { 'use strict'; window.utils = window.utils || {}; var JS_INITIALIZED_CLASS = 'js-initialized'; function isNotInitialized(element) { return !element.classList.contains(JS_INITIALIZED_CLASS); } window.utils.inputs = function(wrapper, options) { var utilInstances = []; // checkboxes var checkboxes = Array.from(wrapper.querySelectorAll('input[type="checkbox"]')); checkboxes.filter(isNotInitialized).forEach(function(checkbox) { utilInstances.push(window.utils.setup('checkbox', checkbox)); }); // radios var radios = Array.from(wrapper.querySelectorAll('input[type="radio"]')); radios.filter(isNotInitialized).forEach(function(radio) { utilInstances.push(window.utils.setup('radio', radio)); }); // file-uploads var fileUploads = Array.from(wrapper.querySelectorAll('input[type="file"]')); fileUploads.filter(isNotInitialized).forEach(function(input) { utilInstances.push(window.utils.setup('fileUpload', input, options)); }); // file-checkboxes var fileCheckboxes = Array.from(wrapper.querySelectorAll('.file-checkbox')); fileCheckboxes.filter(isNotInitialized).forEach(function(input) { utilInstances.push(window.utils.setup('fileCheckbox', input, options)); }); function destroyUtils() { utilInstances.filter(function(utilInstance) { return !!utilInstance; }).forEach(function(utilInstance) { utilInstance.destroy(); }); } return { scope: wrapper, destroy: destroyUtils, }; }; // (multiple) dynamic file uploads // expects i18n object with following strings: // »filesSelected«: label of multi-upload button after selection // example: "Dateien ausgewählt" (will be prepended by number of selected files) // »selectFile«: label of single-upload button before selection // example: "Datei auswählen" // »selectFiles«: label of multi-upload button before selection // example: "Datei(en) auswählen" var FILE_UPLOAD_INPUT_LIST_CLASS = 'file-input__list'; var FILE_UPLOAD_INPUT_UNPACK_CHECKBOX_CLASS = 'file-input__unpack'; var FILE_UPLOAD_INPUT_LABEL_CLASS = 'file-input__label'; var FILE_UPLOAD_INPUT_HIDDEN_CLASS = 'file-input__input--hidden'; window.utils.fileUpload = function(input, options) { var isMulti = input.hasAttribute('multiple'); var fileList = isMulti ? addFileList() : null; var label = addFileLabel(); var i18n = options.i18n; if (!i18n) { throw new Error('window.utils.fileUpload(input, options) needs to be passed i18n object via options'); } input.classList.add(JS_INITIALIZED_CLASS); function renderFileList(files) { fileList.innerHTML = ''; Array.from(files).forEach(function(file, index) { var fileDisplayEl = document.createElement('li'); fileDisplayEl.innerHTML = file.name; fileList.appendChild(fileDisplayEl); }); } function updateLabel(files) { if (files.length) { if (isMulti) { label.innerText = files.length + ' ' + i18n.filesSelected; } else { label.innerHTML = files[0].name; } } else { resetFileLabel(); } } function addFileList() { var list = document.createElement('ol'); list.classList.add(FILE_UPLOAD_INPUT_LIST_CLASS); var unpackEl = input.parentElement.querySelector('.' + FILE_UPLOAD_INPUT_UNPACK_CHECKBOX_CLASS); if (unpackEl) { input.parentElement.insertBefore(list, unpackEl); } else { input.parentElement.appendChild(list); } return list; } function addFileLabel() { var label = document.createElement('label'); label.classList.add(FILE_UPLOAD_INPUT_LABEL_CLASS); label.setAttribute('for', input.id); input.parentElement.insertBefore(label, input); return label; } function resetFileLabel() { if (isMulti) { label.innerText = i18n.selectFiles; } else { label.innerText = i18n.selectFile; } } // initial setup resetFileLabel(); input.classList.add(FILE_UPLOAD_INPUT_HIDDEN_CLASS); input.addEventListener('change', function() { input.dispatchEvent(new Event('input')); if (isMulti) { renderFileList(input.files); } updateLabel(input.files); }); return { scope: input, destroy: function() {}, }; } // to remove previously uploaded files var FILE_UPLOAD_CONTAINER_CLASS = 'file-container'; var FILE_UPLOAD_CONTAINER_CHECKED_CLASS = 'file-container--checked'; window.utils.fileCheckbox = function(input) { // adds eventlistener(s) function addListener(container) { input.addEventListener('change', function(event) { container.classList.toggle(FILE_UPLOAD_CONTAINER_CHECKED_CLASS, this.checked); }); } // initial setup function setup() { var cont = input.parentNode; while (cont !== document.body) { if (cont.matches('.' + FILE_UPLOAD_CONTAINER_CLASS)) { break; } cont = cont.parentNode; } addListener(cont); input.classList.add(JS_INITIALIZED_CLASS); cont.classList.add(JS_INITIALIZED_CLASS); } setup(); return { scope: input, destroy: function() {}, }; } // turns native checkboxes into custom ones window.utils.checkbox = function(input) { if (!input.parentElement.classList.contains('checkbox')) { var parentEl = input.parentElement; var siblingEl = input.nextElementSibling; var wrapperEl = document.createElement('div'); var labelEl = document.createElement('label'); wrapperEl.classList.add('checkbox'); labelEl.setAttribute('for', input.id); wrapperEl.appendChild(input); wrapperEl.appendChild(labelEl); input.classList.add(JS_INITIALIZED_CLASS); if (siblingEl) { parentEl.insertBefore(wrapperEl, siblingEl); } else { parentEl.appendChild(wrapperEl); } } return { scope: input, destroy: function() {}, }; } // turns native radio buttons into custom ones window.utils.radio = function(input) { if (!input.parentElement.classList.contains('radio')) { var parentEl = input.parentElement; var siblingEl = input.nextElementSibling; var wrapperEl = document.createElement('div'); wrapperEl.classList.add('radio'); wrapperEl.appendChild(input); if (siblingEl && siblingEl.matches('label')) { wrapperEl.appendChild(siblingEl); } input.classList.add(JS_INITIALIZED_CLASS); parentEl.appendChild(wrapperEl); } return { scope: input, destroy: function() {}, }; } // Override implicit submit (pressing enter) behaviour to trigger a specified submit button instead of the default window.utils.implicitSubmit = function(input, options) { var submit = options.submit; console.log('implicitSubmit', input, submit); if (!submit) { throw new Error('window.utils.implicitSubmit(input, options) needs to be passed a submit element via options'); } var doSubmit = function(event) { if (event.keyCode == 13) { event.preventDefault(); submit.click(); } }; input.addEventListener('keypress', doSubmit); return { scope: input, destroy: function() { input.removeEventListener('keypress', doSubmit); }, }; } })();