parent
4033547358
commit
d2e8c3978e
@ -1,114 +0,0 @@ |
|||||||
var modal = require('./modaldialog.js') |
|
||||||
var yo = require('yo-yo') |
|
||||||
var css = require('./styles/modal-dialog-custom-styles') |
|
||||||
|
|
||||||
module.exports = { |
|
||||||
alert: function (title, text) { |
|
||||||
if (text) return modal(title, yo`<div>${text}</div>`, null, { label: null }) |
|
||||||
return modal('Alert', yo`<div>${title}</div>`, null, { label: null }) |
|
||||||
}, |
|
||||||
prompt: function (title, text, inputValue, ok, cancel, focus) { |
|
||||||
return prompt(title, text, false, inputValue, ok, cancel, focus) |
|
||||||
}, |
|
||||||
promptPassphrase: function (title, text, inputValue, ok, cancel) { |
|
||||||
return prompt(title, text, true, inputValue, ok, cancel) |
|
||||||
}, |
|
||||||
promptPassphraseCreation: function (ok, cancel) { |
|
||||||
var text = 'Please provide a Passphrase for the account creation' |
|
||||||
var input = yo` |
|
||||||
<div> |
|
||||||
<input id="prompt1" type="password" name='prompt_text' class="${css.prompt_text}" oninput="${(e) => validateInput(e)}"> |
|
||||||
<br> |
|
||||||
<br> |
|
||||||
<input id="prompt2" type="password" name='prompt_text' class="${css.prompt_text}" oninput="${(e) => validateInput(e)}"> |
|
||||||
</div> |
|
||||||
` |
|
||||||
return modal(null, yo`<div>${text}<div>${input}</div></div>`, |
|
||||||
{ |
|
||||||
fn: () => { |
|
||||||
if (typeof ok === 'function') { |
|
||||||
if (input.querySelector('#prompt1').value === input.querySelector('#prompt2').value) { |
|
||||||
ok(null, input.querySelector('#prompt1').value) |
|
||||||
} else { |
|
||||||
ok('Passphase does not match') |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
}, |
|
||||||
{ |
|
||||||
fn: () => { |
|
||||||
if (typeof cancel === 'function') cancel() |
|
||||||
} |
|
||||||
} |
|
||||||
) |
|
||||||
}, |
|
||||||
promptMulti: function ({ title, text, inputValue }, ok, cancel) { |
|
||||||
if (!inputValue) inputValue = '' |
|
||||||
const input = yo` |
|
||||||
<textarea |
|
||||||
id="prompt_text" |
|
||||||
data-id="modalDialogCustomPromptText" |
|
||||||
class=${css.prompt_text} |
|
||||||
rows="4" |
|
||||||
cols="50" |
|
||||||
oninput="${(e) => validateInput(e)}" |
|
||||||
></textarea> |
|
||||||
` |
|
||||||
return modal(title, yo`<div>${text}<div>${input}</div></div>`, |
|
||||||
{ |
|
||||||
fn: () => { if (typeof ok === 'function') ok(document.getElementById('prompt_text').value) } |
|
||||||
}, |
|
||||||
{ |
|
||||||
fn: () => { if (typeof cancel === 'function') cancel() } |
|
||||||
} |
|
||||||
) |
|
||||||
}, |
|
||||||
confirm: function (title, text, ok, cancel) { |
|
||||||
return modal(title, yo`<div>${text}</div>`, |
|
||||||
{ |
|
||||||
fn: () => { if (typeof ok === 'function') ok() } |
|
||||||
}, |
|
||||||
{ |
|
||||||
fn: () => { if (typeof cancel === 'function') cancel() } |
|
||||||
} |
|
||||||
) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
const validateInput = (e) => { |
|
||||||
if (!document.getElementById('modal-footer-ok')) return |
|
||||||
|
|
||||||
if (e.target.value === '') { |
|
||||||
document.getElementById('modal-footer-ok').classList.add('disabled') |
|
||||||
document.getElementById('modal-footer-ok').style.pointerEvents = 'none' |
|
||||||
} else { |
|
||||||
document.getElementById('modal-footer-ok').classList.remove('disabled') |
|
||||||
document.getElementById('modal-footer-ok').style.pointerEvents = 'auto' |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
function prompt (title, text, hidden, inputValue, ok, cancel, focus) { |
|
||||||
if (!inputValue) inputValue = '' |
|
||||||
var type = hidden ? 'password' : 'text' |
|
||||||
var input = yo` |
|
||||||
<input |
|
||||||
type=${type} |
|
||||||
name='prompt_text' |
|
||||||
id='prompt_text' |
|
||||||
class="${css.prompt_text} form-control" |
|
||||||
value='${inputValue}' |
|
||||||
data-id="modalDialogCustomPromptText" |
|
||||||
oninput="${(e) => validateInput(e)}" |
|
||||||
> |
|
||||||
` |
|
||||||
|
|
||||||
modal(title, yo`<div>${text}<div>${input}</div></div>`, |
|
||||||
{ |
|
||||||
fn: () => { if (typeof ok === 'function') ok(document.getElementById('prompt_text').value) } |
|
||||||
}, |
|
||||||
{ |
|
||||||
fn: () => { if (typeof cancel === 'function') cancel() } |
|
||||||
}, |
|
||||||
focus ? '#prompt_text' : undefined |
|
||||||
) |
|
||||||
} |
|
@ -1,150 +0,0 @@ |
|||||||
var yo = require('yo-yo') |
|
||||||
var css = require('./styles/modaldialog-styles') |
|
||||||
|
|
||||||
let incomingModal = false // in case modals are queued, ensure we are not hiding the last one.
|
|
||||||
module.exports = (title, content, ok, cancel, focusSelector, opts) => { |
|
||||||
let agreed = true |
|
||||||
let footerIsActive = false |
|
||||||
opts = opts || {} |
|
||||||
var container = document.getElementById('modal-dialog') |
|
||||||
if (!container) { |
|
||||||
document.querySelector('body').appendChild(html(opts)) |
|
||||||
container = document.getElementById('modal-dialog') |
|
||||||
incomingModal = false |
|
||||||
} else incomingModal = true |
|
||||||
|
|
||||||
var closeDiv = document.getElementById('modal-close') |
|
||||||
if (opts.hideClose) closeDiv.style.display = 'none' |
|
||||||
|
|
||||||
var okDiv = document.getElementById('modal-footer-ok') |
|
||||||
okDiv.innerHTML = (ok && ok.label !== undefined) ? ok.label : 'OK' |
|
||||||
okDiv.style.display = okDiv.innerHTML === '' ? 'none' : 'inline-block' |
|
||||||
|
|
||||||
var cancelDiv = document.getElementById('modal-footer-cancel') |
|
||||||
cancelDiv.innerHTML = (cancel && cancel.label !== undefined) ? cancel.label : 'Cancel' |
|
||||||
cancelDiv.style.display = cancelDiv.innerHTML === '' ? 'none' : 'inline-block' |
|
||||||
|
|
||||||
var modal = document.getElementById('modal-body-id') |
|
||||||
var modalTitle = document.getElementById('modal-title-h6') |
|
||||||
|
|
||||||
modalTitle.innerHTML = '' |
|
||||||
if (title) modalTitle.innerText = title |
|
||||||
|
|
||||||
modal.innerHTML = '' |
|
||||||
if (content) modal.appendChild(content) |
|
||||||
|
|
||||||
setFocusOn('ok') |
|
||||||
|
|
||||||
show() |
|
||||||
|
|
||||||
function setFocusOn (btn) { |
|
||||||
var okDiv = document.getElementById('modal-footer-ok') |
|
||||||
var cancelDiv = document.getElementById('modal-footer-cancel') |
|
||||||
if (btn === 'ok') { |
|
||||||
okDiv.className = okDiv.className.replace(/\bbtn-light\b/g, 'btn-dark') |
|
||||||
cancelDiv.className = cancelDiv.className.replace(/\bbtn-dark\b/g, 'btn-light') |
|
||||||
} else { |
|
||||||
cancelDiv.className = cancelDiv.className.replace(/\bbtn-light\b/g, 'btn-dark') |
|
||||||
okDiv.className = okDiv.className.replace(/\bbtn-dark\b/g, 'btn-light') |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
function okListener () { |
|
||||||
removeEventListener() |
|
||||||
if (ok && ok.fn && agreed) ok.fn() |
|
||||||
if (!incomingModal) hide() |
|
||||||
incomingModal = false |
|
||||||
} |
|
||||||
|
|
||||||
function cancelListener () { |
|
||||||
removeEventListener() |
|
||||||
if (cancel && cancel.fn) cancel.fn() |
|
||||||
if (!incomingModal) hide() |
|
||||||
incomingModal = false |
|
||||||
} |
|
||||||
|
|
||||||
function modalKeyEvent (e) { |
|
||||||
if (e.keyCode === 27) { // Esc
|
|
||||||
cancelListener() |
|
||||||
} else if (e.keyCode === 13) { // Enter
|
|
||||||
e.preventDefault() |
|
||||||
okListener() |
|
||||||
} else if (e.keyCode === 37 && footerIsActive) { // Arrow Left
|
|
||||||
e.preventDefault() |
|
||||||
agreed = true |
|
||||||
setFocusOn('ok') |
|
||||||
} else if (e.keyCode === 39 && footerIsActive) { // Arrow Right
|
|
||||||
e.preventDefault() |
|
||||||
agreed = false |
|
||||||
setFocusOn('cancel') |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
function hide () { |
|
||||||
if (!container) return |
|
||||||
container.style.display = 'none' |
|
||||||
if (container.parentElement) container.parentElement.removeChild(container) |
|
||||||
container = null |
|
||||||
incomingModal = false |
|
||||||
} |
|
||||||
|
|
||||||
function show () { |
|
||||||
if (!container) return |
|
||||||
container.style.display = 'block' |
|
||||||
if (focusSelector) { |
|
||||||
const focusTarget = document.querySelector(`.modal ${focusSelector}`) |
|
||||||
if (focusTarget) { |
|
||||||
focusTarget.focus() |
|
||||||
if (typeof focusTarget.setSelectionRange === 'function') { |
|
||||||
focusTarget.setSelectionRange(0, focusTarget.value.length) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
function removeEventListener () { |
|
||||||
okDiv.removeEventListener('click', okListener) |
|
||||||
cancelDiv.removeEventListener('click', cancelListener) |
|
||||||
closeDiv.removeEventListener('click', cancelListener) |
|
||||||
document.removeEventListener('keydown', modalKeyEvent) |
|
||||||
if (document.getElementById('modal-background')) { |
|
||||||
document.getElementById('modal-background').removeEventListener('click', cancelListener) |
|
||||||
} |
|
||||||
} |
|
||||||
okDiv.addEventListener('click', okListener) |
|
||||||
cancelDiv.addEventListener('click', cancelListener) |
|
||||||
closeDiv.addEventListener('click', cancelListener) |
|
||||||
document.addEventListener('keydown', modalKeyEvent) |
|
||||||
|
|
||||||
const modalDialog = document.getElementById('modal-dialog') |
|
||||||
if (modalDialog) { |
|
||||||
modalDialog.addEventListener('click', (e) => { |
|
||||||
footerIsActive = document.activeElement === modalDialog |
|
||||||
if (e.toElement === modalDialog) { |
|
||||||
cancelListener() // click is outside of modal-content
|
|
||||||
} |
|
||||||
}) |
|
||||||
} |
|
||||||
return { container, okListener, cancelListener, hide } |
|
||||||
} |
|
||||||
|
|
||||||
function html (opts) { |
|
||||||
return yo` |
|
||||||
<div id="modal-dialog" data-id="modalDialogContainer" data-backdrop="static" data-keyboard="false" class="modal" tabindex="-1" role="dialog"> |
|
||||||
<div id="modal-background" class="modal-dialog" role="document"> |
|
||||||
<div class="modal-content ${css.modalContent} ${opts.class}"> |
|
||||||
<div class="modal-header"> |
|
||||||
<h6 id="modal-title-h6" class="modal-title" data-id="modalDialogModalTitle"></h6> |
|
||||||
<span class="modal-close"> |
|
||||||
<i id="modal-close" title="Close" class="fas fa-times" aria-hidden="true"></i> |
|
||||||
</span> |
|
||||||
</div> |
|
||||||
<div id="modal-body-id" class="modal-body ${css.modalBody}" data-id="modalDialogModalBody"> - </div> |
|
||||||
<div class="modal-footer" data-id="modalDialogModalFooter" autofocus> |
|
||||||
<span id="modal-footer-ok" class="${css.modalFooterOk} modal-ok btn btn-sm btn-light" tabindex='5'>OK</span> |
|
||||||
<span id="modal-footer-cancel" class="${css.modalFooterCancel} modal-cancel btn btn-sm btn-light" tabindex='10' data-dismiss="modal">Cancel</span> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div>` |
|
||||||
} |
|
@ -1,110 +0,0 @@ |
|||||||
/* global Element */ |
|
||||||
var yo = require('yo-yo') |
|
||||||
var css = require('./styles/tooltip-styles') |
|
||||||
var modal = require('./modal-dialog-custom') |
|
||||||
|
|
||||||
/** |
|
||||||
* Open a tooltip |
|
||||||
* @param {string} tooltipText The text shown by the tooltip |
|
||||||
* @param {function} [action] Returns An HTMLElement to display for action |
|
||||||
*/ |
|
||||||
module.exports = function addTooltip (tooltipText, action, opts) { |
|
||||||
action = action || function () { return yo`<div></div>` } |
|
||||||
const t = new Toaster() |
|
||||||
return t.render(tooltipText, action(t), opts) |
|
||||||
} |
|
||||||
|
|
||||||
class Toaster { |
|
||||||
hide () { |
|
||||||
if (this.id) clearTimeout(this.id) |
|
||||||
setTimeout(() => { |
|
||||||
// remove from body after the animation is finished
|
|
||||||
if (this.tooltip.parentElement) this.tooltip.parentElement.removeChild(this.tooltip) |
|
||||||
}, 2000) |
|
||||||
animation(this.tooltip, css.animateTop.className) |
|
||||||
} |
|
||||||
|
|
||||||
render (tooltipText, actionElement, opts) { |
|
||||||
opts = defaultOptions(opts) |
|
||||||
let canShorten = true |
|
||||||
if (tooltipText instanceof Element) { |
|
||||||
canShorten = false |
|
||||||
} else { |
|
||||||
if (typeof tooltipText === 'object') { |
|
||||||
if (tooltipText.message) { |
|
||||||
tooltipText = tooltipText.message |
|
||||||
} else { |
|
||||||
try { |
|
||||||
tooltipText = JSON.stringify(tooltipText) |
|
||||||
} catch (e) { |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return new Promise((resolve, reject) => { |
|
||||||
const shortTooltipText = (canShorten && tooltipText.length > 201) ? tooltipText.substring(0, 200) + '...' : tooltipText |
|
||||||
this.resolveFn = resolve |
|
||||||
|
|
||||||
function showFullMessage () { |
|
||||||
modal.alert(tooltipText) |
|
||||||
} |
|
||||||
|
|
||||||
function closeTheToaster (self) { |
|
||||||
self.hide() |
|
||||||
over() |
|
||||||
resolve() |
|
||||||
} |
|
||||||
const button = tooltipText.length > 201 ? yo` |
|
||||||
<button class="btn btn-secondary btn-sm mx-3" style="white-space: nowrap;" onclick=${() => showFullMessage()}>Show full message</button> |
|
||||||
` : ''
|
|
||||||
|
|
||||||
this.tooltip = yo` |
|
||||||
<div data-shared="tooltipPopup" class="${css.tooltip} alert alert-info p-2" onmouseenter=${() => { over() }} onmouseleave=${() => { out() }}> |
|
||||||
<span class="px-2"> |
|
||||||
${shortTooltipText} |
|
||||||
${button} |
|
||||||
${actionElement} |
|
||||||
</span> |
|
||||||
<span style="align-self: baseline;"> |
|
||||||
<button data-id="tooltipCloseButton" class="fas fa-times btn-info mx-1 p-0" onclick=${() => closeTheToaster(this)}></button> |
|
||||||
</span> |
|
||||||
</div>` |
|
||||||
const timeOut = () => { |
|
||||||
return setTimeout(() => { |
|
||||||
if (this.id) { |
|
||||||
this.hide() |
|
||||||
resolve() |
|
||||||
} |
|
||||||
}, opts.time) |
|
||||||
} |
|
||||||
const over = () => { |
|
||||||
if (this.id) { |
|
||||||
clearTimeout(this.id) |
|
||||||
this.id = null |
|
||||||
} |
|
||||||
} |
|
||||||
const out = () => { |
|
||||||
if (!this.id) this.id = timeOut() |
|
||||||
} |
|
||||||
this.id = timeOut() |
|
||||||
document.body.appendChild(this.tooltip) |
|
||||||
animation(this.tooltip, css.animateBottom.className) |
|
||||||
}) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
const defaultOptions = (opts) => { |
|
||||||
opts = opts || {} |
|
||||||
return { |
|
||||||
time: opts.time || 7000 |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
const animation = (tooltip, anim) => { |
|
||||||
tooltip.classList.remove(css.animateTop.className) |
|
||||||
tooltip.classList.remove(css.animateBottom.className) |
|
||||||
// eslint-disable-next-line
|
|
||||||
void tooltip.offsetWidth // trick for restarting the animation
|
|
||||||
tooltip.classList.add(anim) |
|
||||||
} |
|
Loading…
Reference in new issue