From 12779824496fd6056723e98aee74df1ef1ea00bc Mon Sep 17 00:00:00 2001 From: Felix Hamann Date: Sat, 16 Feb 2019 13:38:11 +0100 Subject: [PATCH] move js utils for inputs to static --- src/Foundation.hs | 1 + static/js/utils/inputs.js | 171 +++++++++++++++++++++++++++++ templates/multiFileField.hamlet | 2 +- templates/standalone/inputs.julius | 151 +------------------------ 4 files changed, 179 insertions(+), 146 deletions(-) create mode 100644 static/js/utils/inputs.js diff --git a/src/Foundation.hs b/src/Foundation.hs index b32fb3f66..fac4c3e0c 100644 --- a/src/Foundation.hs +++ b/src/Foundation.hs @@ -1004,6 +1004,7 @@ siteLayout' headingOverride widget = do addScript $ StaticR js_utils_tabber_js addScript $ StaticR js_utils_alerts_js addScript $ StaticR js_utils_asidenav_js + addScript $ StaticR js_utils_inputs_js addStylesheet $ StaticR css_utils_tabber_scss addStylesheet $ StaticR css_utils_alerts_scss addStylesheet $ StaticR css_utils_asidenav_scss diff --git a/static/js/utils/inputs.js b/static/js/utils/inputs.js new file mode 100644 index 000000000..68edee519 --- /dev/null +++ b/static/js/utils/inputs.js @@ -0,0 +1,171 @@ +(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) { + // checkboxes / radios + var checkboxes = Array.from(wrapper.querySelectorAll('input[type="checkbox"], input[type="radio"]')); + checkboxes.filter(isNotInitialized).forEach(window.utils.checkboxRadio); + + // file-uploads + var fileUploads = Array.from(wrapper.querySelectorAll('input[type="file"]')); + fileUploads.filter(isNotInitialized).forEach(function(input) { + window.utils.fileUpload(input, options); + }); + + // file-checkboxes + var fileCheckboxes = Array.from(wrapper.querySelectorAll('.file-checkbox')); + fileCheckboxes.filter(isNotInitialized).forEach(function(inp) { + window.utils.fileCheckbox(inp); + inp.classList.add(JS_INITIALIZED_CLASS); + }); + }; + + // (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); + }); + } + + // 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(); + } + + // turns native checkboxes and radio buttons into custom ones + window.utils.checkboxRadio = function(input) { + + var type = input.getAttribute('type'); + + if (!input.parentElement.classList.contains(type)) { + var parentEl = input.parentElement; + var siblingEl = input.nextElementSibling; + var wrapperEl = document.createElement('div'); + var labelEl = document.createElement('label'); + wrapperEl.classList.add(type); + 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); + } + } + } + +})(); diff --git a/templates/multiFileField.hamlet b/templates/multiFileField.hamlet index 649a9b47e..c8c501841 100644 --- a/templates/multiFileField.hamlet +++ b/templates/multiFileField.hamlet @@ -3,7 +3,7 @@ $forall FileUploadInfo{..} <- fileInfos