(function(global) { 'use strict'; if (typeof module !== 'undefined' && module.exports) module.exports = SmallTalk(); else global.smalltalk = SmallTalk(); function SmallTalk(callback) { if (!(this instanceof SmallTalk)) return new SmallTalk(callback); let remove = bind(removeEl, '.smalltalk'); const BUTTON_OK = ['OK']; const BUTTON_OK_CANCEL = ['OK', 'Cancel']; this.alert = (title, msg, options) => { return showDialog(title, msg, '', BUTTON_OK, options); }; this.prompt = (title, msg, value, options) => { let val = value || ''; let valueStr = ``; return showDialog(title, msg, valueStr, BUTTON_OK_CANCEL, options); }; this.confirm = (title, msg, options) => { return showDialog(title, msg, '', BUTTON_OK_CANCEL, options); }; function getTemplate(title, msg, value, buttons) { if (!Array.isArray(buttons)) throw Error('buttons should be array!'); return `
${ title }
${ msg } ${ value }
${ buttons.map((name, i) => `` ).join('') }
`; } function showDialog(title, msg, value, buttons, options) { let dialog = document.createElement('div'), closeButtons = [ 'cancel', 'close', 'ok' ], ok, cancel, promise = new Promise((resolve, reject) => { let noCancel = options && !options.cancel; let empty = () => {}; ok = resolve; cancel = reject; if (noCancel) cancel = empty; }), tmpl = getTemplate(title, msg, value, buttons); dialog.innerHTML = tmpl; dialog.className = 'smalltalk'; document.body.appendChild(dialog); find(dialog, ['ok', 'input']).forEach(el => el.focus() ); find(dialog, ['input']).forEach(el => { el.setSelectionRange(0, value.length); }); addListeterAll('click', dialog, closeButtons, event => closeDialog(event.target, dialog, ok, cancel) ); ['click', 'contextmenu'].forEach(event => dialog.addEventListener(event, () => find(dialog, ['ok', 'input']).forEach(el => el.focus() ) ) ); dialog.addEventListener('keydown', keyDown(dialog, ok, cancel)); return promise; } function keyDown(dialog, ok, cancel) { return event => { const KEY = { ENTER : 13, ESC : 27, TAB : 9, LEFT : 37, UP : 38, RIGHT : 39, DOWN : 40 }; let keyCode = event.keyCode, el = event.target; let namesAll = ['ok', 'cancel', 'input'], names = find(dialog, namesAll).map(el => getDataName(el) ); switch(keyCode) { case KEY.ENTER: closeDialog(el, dialog, ok, cancel); event.preventDefault(); break; case KEY.ESC: remove(); cancel(); break; case KEY.TAB: if (event.shiftKey) tab(dialog, names); tab(dialog, names); event.preventDefault(); break; default: let is = ['left', 'right', 'up', 'down'].some(name => keyCode === KEY[name.toUpperCase()] ); if (is) changeButtonFocus(dialog, names); break; } event.stopPropagation(); }; } function getDataName(el) { return el .getAttribute('data-name') .replace('js-', ''); } function changeButtonFocus(dialog, names) { let name = '', active = document.activeElement, activeName = getDataName(active), isButton = /ok|cancel/.test(activeName), count = names.length - 1; if (activeName !== 'input' && count && isButton) { if (activeName === 'cancel') name = 'ok'; else name = 'cancel'; find(dialog, [name]).forEach(el => el.focus() ); } } function tab(dialog, names) { let active = document.activeElement, activeName = getDataName(active), count = names.length - 1, index = names.indexOf(activeName); if (index === count) index = 0; else if (index < count) ++index; let name = names[index]; find(dialog, [name]).forEach(el => el.focus() ); } function closeDialog(el, dialog, ok, cancel) { let value, name = el .getAttribute('data-name') .replace('js-', ''); if (/close|cancel/.test(name)) { cancel(); } else { value = find(dialog, ['input']).reduce((value, el) => { return el.value; }, null); ok(value); } remove(); } function find(element, names) { let elements = names.map(name => element.querySelector(`[data-name="js-${ name }"]`) ).filter(el => el ); return elements; } function addListeterAll(event, parent, elements, fn) { find(parent, elements).forEach(el => el.addEventListener(event, fn) ); } function removeEl(name) { var el = document.querySelector(name); el.parentElement.removeChild(el); } function bind(fn) { var args = [].slice.call(arguments, 1); return fn.bind(null, args); } } })(typeof window !== 'undefined' && window);