fradrive/static/js/utils/inputs.js
2019-04-06 14:51:16 +02:00

279 lines
7.8 KiB
JavaScript

(function() {
'use strict';
var JS_INITIALIZED_CLASS = 'js-inputs-initialized';
window.utils.inputs = function(wrapper, options) {
options = options || {};
var utilInstances = [];
if (wrapper.classList.contains(JS_INITIALIZED_CLASS) && !options.force) {
return false;
}
// checkboxes
var checkboxes = Array.from(wrapper.querySelectorAll('input[type="checkbox"]'));
checkboxes.forEach(function(checkbox) {
utilInstances.push(window.utils.setup('checkbox', checkbox));
});
// radios
var radios = Array.from(wrapper.querySelectorAll('input[type="radio"]'));
radios.forEach(function(radio) {
utilInstances.push(window.utils.setup('radio', radio));
});
// file-uploads
var fileUploads = Array.from(wrapper.querySelectorAll('input[type="file"]'));
fileUploads.forEach(function(input) {
utilInstances.push(window.utils.setup('fileUpload', input, options));
});
// file-checkboxes
var fileCheckboxes = Array.from(wrapper.querySelectorAll('.file-checkbox'));
fileCheckboxes.forEach(function(input) {
utilInstances.push(window.utils.setup('fileCheckbox', input, options));
});
function destroyUtils() {
utilInstances.filter(function(utilInstance) {
return !!utilInstance;
}).forEach(function(utilInstance) {
utilInstance.destroy();
});
}
wrapper.classList.add(JS_INITIALIZED_CLASS);
return {
scope: wrapper,
destroy: destroyUtils,
};
};
/**
*
* FileUpload Utility
*
* Attribute: uw-file-upload
* (element must be an input of type='file')
*
* Example usage:
* <input type='file' uw-file-upload>
*
* Internationalization:
* This utility expects the following translations to be available:
* »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_UTIL_NAME = 'fileUpload';
var FILE_UPLOAD_UTIL_SELECTOR = 'input[type="file"][uw-file-upload]';
var FILE_UPLOAD_CLASS = 'file-input';
var FILE_UPLOAD_INITIALIZED_CLASS = 'file-input--initialized';
var FILE_UPLOAD_LIST_CLASS = 'file-input__list';
var FILE_UPLOAD_UNPACK_CHECKBOX_CLASS = 'file-input__unpack';
var FILE_UPLOAD_LABEL_CLASS = 'file-input__label';
var fileUploadUtil = function(element) {
var isMultiFileUpload = false;
var fileList;
var label;
function init() {
if (!element) {
throw new Error('FileUpload utility cannot be setup without an element!');
}
if (element.classList.contains(FILE_UPLOAD_INITIALIZED_CLASS)) {
throw new Error('FileUpload utility already initialized!');
}
// check if is multi-file upload
isMultiFileUpload = element.hasAttribute('multiple');
if (isMultiFileUpload) {
fileList = createFileList();
}
label = createFileLabel();
updateLabel();
// add change listener
element.addEventListener('change', function() {
updateLabel();
renderFileList();
});
// add util class for styling and mark as initialized
element.classList.add(FILE_UPLOAD_CLASS, FILE_UPLOAD_INITIALIZED_CLASS);
return {
name: FILE_UPLOAD_UTIL_NAME,
element: element,
destroy: function() {},
};
}
function renderFileList() {
if (!fileList) {
return;
}
var files = element.files;
fileList.innerHTML = '';
Array.from(files).forEach(function(file) {
var fileDisplayEl = document.createElement('li');
fileDisplayEl.innerHTML = file.name;
fileList.appendChild(fileDisplayEl);
});
}
function createFileList() {
var list = document.createElement('ol');
list.classList.add(FILE_UPLOAD_LIST_CLASS);
var unpackEl = element.parentElement.querySelector('.' + FILE_UPLOAD_UNPACK_CHECKBOX_CLASS);
if (unpackEl) {
element.parentElement.insertBefore(list, unpackEl);
} else {
element.parentElement.appendChild(list);
}
return list;
}
function createFileLabel() {
var label = document.createElement('label');
label.classList.add(FILE_UPLOAD_LABEL_CLASS);
label.setAttribute('for', element.id);
element.parentElement.insertBefore(label, element);
return label;
}
function updateLabel() {
var files = element.files;
if (files && files.length) {
label.innerText = isMultiFileUpload ? files.length + ' ' + I18n.get('filesSelected') : files[0].name;
} else {
label.innerText = isMultiFileUpload ? I18n.get('selectFiles') : I18n.get('selectFile');
}
}
return init();
}
if (UtilRegistry) {
UtilRegistry.register({
name: FILE_UPLOAD_UTIL_NAME,
selector: FILE_UPLOAD_UTIL_SELECTOR,
setup: fileUploadUtil,
});
}
// 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 init() {
var cont = input.parentNode;
while (cont !== document.body) {
if (cont.matches('.' + FILE_UPLOAD_CONTAINER_CLASS)) {
break;
}
cont = cont.parentNode;
}
addListener(cont);
}
return init();
}
// 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);
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);
}
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;
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);
},
};
}
})();