Unify modals
This commit is contained in:
+146
@@ -0,0 +1,146 @@
|
||||
(function () {
|
||||
var backdrop = null;
|
||||
var modal = null;
|
||||
var titleEl = null;
|
||||
var bodyEl = null;
|
||||
var cancelBtn = null;
|
||||
var confirmBtn = null;
|
||||
var footerEl = null;
|
||||
var prevFocus = null;
|
||||
var currentOpts = null;
|
||||
var onKeydown = null;
|
||||
|
||||
function build() {
|
||||
backdrop = document.createElement('div');
|
||||
backdrop.className = 'modal-backdrop';
|
||||
|
||||
modal = document.createElement('div');
|
||||
modal.className = 'modal';
|
||||
modal.setAttribute('role', 'dialog');
|
||||
modal.setAttribute('aria-modal', 'true');
|
||||
|
||||
var header = document.createElement('div');
|
||||
header.className = 'modal-header';
|
||||
titleEl = document.createElement('span');
|
||||
header.appendChild(titleEl);
|
||||
|
||||
bodyEl = document.createElement('div');
|
||||
bodyEl.className = 'modal-body';
|
||||
|
||||
footerEl = document.createElement('div');
|
||||
footerEl.className = 'modal-footer';
|
||||
|
||||
cancelBtn = document.createElement('button');
|
||||
cancelBtn.type = 'button';
|
||||
confirmBtn = document.createElement('button');
|
||||
confirmBtn.type = 'button';
|
||||
|
||||
modal.appendChild(header);
|
||||
modal.appendChild(bodyEl);
|
||||
modal.appendChild(footerEl);
|
||||
backdrop.appendChild(modal);
|
||||
|
||||
backdrop.addEventListener('mousedown', function (e) {
|
||||
if (e.target === backdrop) close();
|
||||
});
|
||||
cancelBtn.addEventListener('click', close);
|
||||
confirmBtn.addEventListener('click', function () {
|
||||
if (confirmBtn.disabled) return;
|
||||
if (currentOpts && currentOpts.confirm && currentOpts.confirm.onConfirm) {
|
||||
currentOpts.confirm.onConfirm();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function open(opts) {
|
||||
if (backdrop && backdrop.parentNode) close();
|
||||
if (!backdrop) build();
|
||||
|
||||
currentOpts = opts;
|
||||
prevFocus = document.activeElement;
|
||||
|
||||
titleEl.textContent = opts.title || '';
|
||||
|
||||
bodyEl.textContent = '';
|
||||
if (opts.body instanceof Node) {
|
||||
bodyEl.appendChild(opts.body);
|
||||
} else if (typeof opts.body === 'string') {
|
||||
bodyEl.textContent = opts.body;
|
||||
}
|
||||
|
||||
var confirmOpts = opts.confirm || {};
|
||||
var cancelOpts = opts.cancel || {};
|
||||
|
||||
confirmBtn.textContent = confirmOpts.label || 'OK';
|
||||
confirmBtn.className = 'btn' + (confirmOpts.danger ? ' danger' : '');
|
||||
confirmBtn.disabled = !!confirmOpts.initiallyDisabled;
|
||||
|
||||
cancelBtn.textContent = cancelOpts.label || 'CANCEL';
|
||||
cancelBtn.className = 'btn';
|
||||
|
||||
footerEl.textContent = '';
|
||||
if (opts.swapButtons) {
|
||||
footerEl.appendChild(confirmBtn);
|
||||
footerEl.appendChild(cancelBtn);
|
||||
} else {
|
||||
footerEl.appendChild(cancelBtn);
|
||||
footerEl.appendChild(confirmBtn);
|
||||
}
|
||||
|
||||
document.body.appendChild(backdrop);
|
||||
|
||||
setTimeout(function () {
|
||||
if (cancelOpts.autofocus) {
|
||||
cancelBtn.focus();
|
||||
return;
|
||||
}
|
||||
var firstInput = bodyEl.querySelector('input, textarea, select');
|
||||
if (firstInput) {
|
||||
firstInput.focus();
|
||||
if (firstInput.select) firstInput.select();
|
||||
} else {
|
||||
confirmBtn.focus();
|
||||
}
|
||||
}, 0);
|
||||
|
||||
var enterConfirms = confirmOpts.enterConfirms !== false;
|
||||
onKeydown = function (e) {
|
||||
if (e.key === 'Escape') {
|
||||
e.preventDefault();
|
||||
close();
|
||||
return;
|
||||
}
|
||||
if (e.key === 'Enter' && enterConfirms) {
|
||||
var tag = (e.target && e.target.tagName) || '';
|
||||
if (tag === 'TEXTAREA') return;
|
||||
e.preventDefault();
|
||||
if (!confirmBtn.disabled) confirmBtn.click();
|
||||
}
|
||||
};
|
||||
document.addEventListener('keydown', onKeydown);
|
||||
|
||||
return {
|
||||
close: close,
|
||||
setConfirmDisabled: function (d) { confirmBtn.disabled = !!d; },
|
||||
confirmButton: confirmBtn
|
||||
};
|
||||
}
|
||||
|
||||
function close() {
|
||||
if (!backdrop || !backdrop.parentNode) return;
|
||||
if (onKeydown) {
|
||||
document.removeEventListener('keydown', onKeydown);
|
||||
onKeydown = null;
|
||||
}
|
||||
backdrop.parentNode.removeChild(backdrop);
|
||||
currentOpts = null;
|
||||
var toRestore = prevFocus;
|
||||
prevFocus = null;
|
||||
if (toRestore && toRestore.focus) {
|
||||
try { toRestore.focus(); } catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
window.openModal = open;
|
||||
window.closeModal = close;
|
||||
})();
|
||||
Reference in New Issue
Block a user