fradrive/static/js/utils/modal.js
2019-04-10 23:32:28 +02:00

197 lines
5.5 KiB
JavaScript

(function() {
'use strict';
/**
*
* Modal Utility
*
* Attribute: uw-modal
*
* Params:
* data-modal-trigger: string
* Selector for the element that toggles the modal.
* If trigger element has "href" attribute the modal will be dynamically loaded from the referenced page
* data-modal-closeable: boolean property
* If the param is present the modal will have a close-icon and can also be closed by clicking anywhere on the overlay
*
* Example usage:
* <div uw-modal data-modal-trigger='#trigger' data-modal-closeable>This is the modal content
* <div id='trigger'>Click me to open the modal
*/
var MODAL_UTIL_NAME = 'modal';
var MODAL_UTIL_SELECTOR = '[uw-modal]';
var MODAL_HEADERS = {
'Is-Modal': 'True',
};
var MODAL_INITIALIZED_CLASS = 'modal--initialized';
var MODAL_CLASS = 'modal';
var MODAL_OPEN_CLASS = 'modal--open';
var MODAL_TRIGGER_CLASS = 'modal__trigger';
var MODAL_CONTENT_CLASS = 'modal__content';
var MODAL_OVERLAY_CLASS = 'modal__overlay';
var MODAL_OVERLAY_OPEN_CLASS = 'modal__overlay--open';
var MODAL_CLOSER_CLASS = 'modal__closer';
var MAIN_CONTENT_CLASS = 'main__content-body'
var modalUtil = function(element) {
var overlayElement = document.createElement('div');
var modalUrl;
function _init() {
if (!element) {
throw new Error('Modal utility cannot be setup without an element!');
}
if (element.classList.contains(MODAL_INITIALIZED_CLASS)) {
return false;
}
// param modalTrigger
if (!element.dataset.modalTrigger) {
throw new Error('Modal utility cannot be setup without a trigger element!');
} else {
setupTrigger();
}
// param modalCloseable
if (element.dataset.modalCloseable !== undefined) {
setupCloser();
}
// setupForm();
// mark as initialized and add modal class for styling
element.classList.add(MODAL_INITIALIZED_CLASS, MODAL_CLASS);
return {
name: MODAL_UTIL_NAME,
element: element,
destroy: function() {}
};
}
function setupTrigger() {
var triggerSelector = element.dataset.modalTrigger;
if (!triggerSelector.startsWith('#')) {
triggerSelector = '#' + triggerSelector;
}
var triggerElement = document.querySelector(triggerSelector);
if (!triggerElement) {
throw new Error('Trigger element for Modal not found: "' + triggerSelector + '"');
}
triggerElement.classList.add(MODAL_TRIGGER_CLASS);
triggerElement.addEventListener('click', onTriggerClicked, false);
modalUrl = triggerElement.getAttribute('href');
}
function setupCloser() {
var closerElement = document.createElement('div');
element.insertBefore(closerElement, null);
closerElement.classList.add(MODAL_CLOSER_CLASS);
closerElement.addEventListener('click', onCloseClicked, false);
overlayElement.addEventListener('click', onCloseClicked, false);
}
function onTriggerClicked(event) {
event.preventDefault();
open();
}
function onCloseClicked(event) {
event.preventDefault();
close();
}
function onKeyUp(event) {
if (event.key === 'Escape') {
close();
}
}
function open() {
document.body.insertBefore(element, null);
element.classList.add(MODAL_OPEN_CLASS);
overlayElement.classList.add(MODAL_OVERLAY_CLASS);
document.body.insertBefore(overlayElement, element);
overlayElement.classList.add(MODAL_OVERLAY_OPEN_CLASS);
if (modalUrl) {
fillModal(modalUrl);
}
document.addEventListener('keyup', onKeyUp);
}
function close() {
overlayElement.classList.remove(MODAL_OVERLAY_OPEN_CLASS);
element.classList.remove(MODAL_OPEN_CLASS);
document.removeEventListener('keyup', onKeyUp);
};
function fillModal(url) {
if (!HttpClient) {
throw new Error('HttpClient not found! Can\'t fetch modal content from ' + url);
}
HttpClient.get(url, MODAL_HEADERS)
.then(function(response) {
response.text().then(processResponse);
});
}
function processResponse(responseBody) {
var responseElement = document.createElement('div');
responseElement.innerHTML = responseBody;
var modalContent = document.createElement('div');
modalContent.classList.add(MODAL_CONTENT_CLASS);
var contentBody = responseElement.querySelector('.' + MAIN_CONTENT_CLASS);
if (contentBody) {
modalContent.innerHTML = contentBody.innerHTML;
}
var previousModalContent = element.querySelector('.' + MODAL_CONTENT_CLASS);
if (previousModalContent) {
previousModalContent.remove();
}
modalContent = withPrefixedInputIDs(modalContent);
element.insertBefore(modalContent, null);
// setup any newly arrived utils
UtilRegistry.setupAll(element);
}
function withPrefixedInputIDs(modalContent) {
var idAttrs = ['id', 'for', 'data-conditional-input'];
idAttrs.forEach(function(attr) {
Array.from(modalContent.querySelectorAll('[' + attr + ']')).forEach(function(input) {
var value = element.id + '__' + input.getAttribute(attr);
input.setAttribute(attr, value);
});
});
return modalContent;
}
return _init();
};
if (UtilRegistry) {
UtilRegistry.register({
name: MODAL_UTIL_NAME,
selector: MODAL_UTIL_SELECTOR,
setup: modalUtil
});
}
})();