move js utils for inputs to static

This commit is contained in:
Felix Hamann 2019-02-16 13:38:11 +01:00
parent 9d6eb5ae4e
commit 1277982449
4 changed files with 179 additions and 146 deletions

View File

@ -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

171
static/js/utils/inputs.js Normal file
View File

@ -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);
}
}
}
})();

View File

@ -3,7 +3,7 @@ $forall FileUploadInfo{..} <- fileInfos
<div .file-container :fuiChecked:.file-container--checked>
<label .file-container__label.btn for=#{fuiHtmlId}>#{fuiTitle}
<div .checkbox>
<input .file-container__checkbox.js-file-checkbox id=#{fuiHtmlId} name=#{fieldName} :fuiChecked:checked value=#{toPathPiece fuiId} type="checkbox">
<input .file-container__checkbox.file-checkbox id=#{fuiHtmlId} name=#{fieldName} :fuiChecked:checked value=#{toPathPiece fuiId} type="checkbox">
<label for=#{fuiHtmlId}>
$# new files

View File

@ -1,147 +1,8 @@
(function() {
'use strict';
window.utils = window.utils || {};
// allows for multiple file uploads with separate inputs
window.utils.initializeFileUpload = function(input) {
var isMulti = input.hasAttribute('multiple');
var fileList = isMulti ? addFileList() : null;
var label = addFileLabel();
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 + ' Dateien ausgwählt';
} else {
label.innerHTML = files[0].name;
}
} else {
resetFileLabel();
}
}
function addFileList() {
var list = document.createElement('ol');
list.classList.add('file-input__list');
var unpackEl = input.parentElement.querySelector('.file-input__unpack');
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-input__label');
label.setAttribute('for', input.id);
input.parentElement.insertBefore(label, input);
return label;
}
function resetFileLabel() {
// interpolate translated String here
label.innerText = 'Datei' + (isMulti ? 'en' : '') + ' auswählen';
}
// initial setup
resetFileLabel();
input.classList.add('file-input__input--hidden');
input.addEventListener('change', function() {
input.dispatchEvent(new Event('input'));
if (isMulti) {
renderFileList(input.files);
}
updateLabel(input.files);
});
}
// to remove previously uploaded files
window.utils.reactiveFileCheckbox = function(input) {
// adds eventlistener(s)
function addListener(container) {
input.addEventListener('change', function(event) {
container.classList.toggle('file-container--checked', this.checked);
});
}
// initial setup
function setup() {
var cont = input.parentNode;
while (cont !== document.body) {
if (cont.matches('.file-container')) {
break;
}
cont = cont.parentNode;
}
addListener(cont);
}
setup();
}
window.utils.initializeCheckboxRadio = function(input, 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);
if (siblingEl) {
parentEl.insertBefore(wrapperEl, siblingEl);
} else {
parentEl.appendChild(wrapperEl);
}
}
}
})();
document.addEventListener('setup', function(e) {
if (e.detail.module && e.detail.module !== 'inputs')
return;
// initialize checkboxes
Array.from(e.detail.scope.querySelectorAll('input[type="checkbox"]:not(.js-initialized)')).forEach(function(inp) {
window.utils.initializeCheckboxRadio(inp, 'checkbox');
inp.classList.add("js-initialized");
});
// initialize radios
Array.from(e.detail.scope.querySelectorAll('input[type="radio"]:not(.js-initialized)')).forEach(function(inp) {
window.utils.initializeCheckboxRadio(inp, 'radio');
inp.classList.add("js-initialized");
});
// initialize file-upload-fields
Array.from(e.detail.scope.querySelectorAll('input[type="file"]:not(.js-initialized)')).forEach(function(inp) {
window.utils.initializeFileUpload(inp);
inp.classList.add("js-initialized");
});
// initialize file-checkbox-fields
Array.from(e.detail.scope.querySelectorAll('.js-file-checkbox:not(.js-initialized)')).forEach(function(inp) {
window.utils.reactiveFileCheckbox(inp);
inp.classList.add("js-initialized");
});
});
document.addEventListener('DOMContentLoaded', function() {
document.dispatchEvent(new CustomEvent('setup', { detail: { scope: document.body, module: 'inputs' }, bubbles: true, cancelable: true }));
var i18n = {
filesSelected: 'Dateien ausgewählt',
selectFile: 'Datei auswählen',
selectFiles: 'Datei(en) auswählen',
};
window.utils.setup('inputs', document.body, { i18n });
});