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