UNPKG

toloframework

Version:

Javascript/HTML/CSS compiler for Firefox OS or nodewebkit apps using modules in the nodejs style.

276 lines (253 loc) 7.32 kB
/** * @module wdg.modal * * @class * @param {boolean} scroll - Default true. * * * @example * var mod = require('wdg.modal'); */ const $ = require("dom"), DB = require("tfw.data-binding"), Flex = require("wdg.flex"), Button = require("wdg.button"); /** @exports {class} @param {object} opts.content - */ function Modal(opts) { var that = this; var body = $.div(); body.addEventListener("scroll", onScroll.bind(this, body)); const laterScroll = function() { window.setTimeout(function() { onScroll(body); }); }, header = $.tag('header', 'thm-fg', 'thm-ele8', 'thm-bgPD'), footer = $.tag('footer', "thm-bg0"), cell = $.div('cell', 'thm-ele24', 'thm-bg1', [header, body, footer]), elem = $.elem(this, 'div', 'wdg-modal', [$.div([cell])]); $.on(elem, function(evt) { if (evt.target.parentElement !== elem) return; that.visible = false; }); DB.prop(this, 'content')(function(v) { $.clear(body); if (Array.isArray(v)) { v.forEach(function(itm) { $.add(body, itm); }); } else if (typeof v !== 'undefined' && v !== null) { $.add(body, v); } laterScroll(); }); DB.prop(this, 'header')(function(v) { if (!v || (typeof v === 'string' && v.trim().length === 0)) { $.addClass(header, "hide"); return; } $.removeClass(header, "hide"); $.clear(header); if (Array.isArray(v)) { v.forEach(function(itm) { $.add(header, itm); }); } else if (typeof v !== 'undefined' && v !== null) { $.add(header, v); } laterScroll(); }); DB.prop(this, 'footer')(function(v) { if (!v || (typeof v === 'string' && v.trim().length === 0)) { $.addClass(footer, "hide"); return; } $.removeClass(footer, "hide"); $.clear(footer); if (Array.isArray(v)) { v.forEach(function(itm) { $.add(footer, itm); }); } else { $.add(footer, v); } laterScroll(); }); DB.propString(this, 'width')(function(v) { $.css(body, { 'max-width': v }); laterScroll(); }); DB.propAddClass(this, 'fullscreen'); DB.propAddClass(this, 'padding'); DB.propAddClass(this, 'scroll'); DB.propAddClass(this, 'wide'); DB.propBoolean(this, 'visible')(function(v) { if (v) { that.attach(); } else { that.detach(); } }); opts = DB.extend({ visible: false, header: null, content: [], footer: null, padding: true, scroll: true, wide: false, fullscreen: false, width: 'auto' }, opts, this); } /** * @member Modal.refresh * Refresh the content. */ Modal.prototype.refresh = function() { DB.fire(this, 'content'); return this; }; /** * @member Modal.attach * Append element to body. */ Modal.prototype.attach = function() { var that = this; if (this._timeoutDetach) { window.clearTimeout(this._timeoutDetach); delete this._timeoutDetach; } document.body.appendChild(this.element); DB.set(this, 'visible', true); $.addClass(this, 'fadeout'); window.setTimeout(function() { $.removeClass(that, 'fadeout'); }); }; /** * @member Modal.detach * Remove element from body. */ Modal.prototype.detach = function() { var that = this; window.setTimeout(function() { $.addClass(that, 'fadeout'); }); this._timeoutDetach = window.setTimeout(function() { delete this._timeoutDetach; DB.set(that, 'visible', false); $.detach(that.element); }, 250); }; /** * @function Modal.comfirm * @param {array|object|string} args.content - Content to display. * @param {string} args.title - Modal title. * @param {string} args.yes - Text of the confirmation button. Default is `OK`. * @param {string} args.no - Text of the cancellation button. Default is `Cancel`. * @param {function} args.onYes - Callback for confirmation. * @param {function} args.onNo - Callback for cancel. */ Modal.confirm = function(args, onYes, onNo) { if (typeof onYes === 'function') { // This is the old calling way, with multiple arguments. args = { content: args, onYes: onYes, onNo: onNo }; } if (typeof args.title === 'undefined') args.title = _('confirm'); if (typeof args.yes === 'undefined') args.yes = _('ok'); if (typeof args.no === 'undefined') args.no = _('cancel'); if (typeof args.onYes === 'undefined') args.onYes = function() {}; if (typeof args.onNo === 'undefined') args.onNo = function() {}; onYes = args.onYes; onNo = args.onNo; var btnYes = new Button({ text: args.yes, flat: true }); var btnNo = new Button({ text: args.no, flat: true }); if (Array.isArray(args.content)) { // Arrays must be wrapped in a DIV. args.content = $.div(args.content); } if (typeof args.content === 'string' && args.content.substr(0, 6) == '<html>') { // This is HTML code. var html = args.content.substr(6); args.content = $.div(); args.content.innerHTML = html; } var modal = new Modal({ header: args.title, footer: [btnNo, btnYes], content: args.content }); modal.attach(); btnNo.on(function() { modal.detach(); if (typeof onNo === 'function') { onNo(); } }); btnYes.on(function() { if (typeof onYes === 'function') { var caption = onYes(); if (typeof caption !== 'string') modal.detach(); else { btnNo.visible = false; btnYes.waitOn(caption); } } else { modal.detach(); } }); return modal; }; /** * Display a message with an OK button. */ Modal.alert = function(content, onOK) { var btnOK = new Button({ text: _('close'), flat: true }); if (typeof content === 'string' && content.substr(0, 6) == '<html>') { // This is HTML code. var html = content.substr(6); content = $.div(); content.innerHTML = html; } var modal = new Modal({ footer: btnOK, content: content }); modal.attach(); btnOK.on(function() { modal.detach(); if (typeof onOK === 'function') onOK(); }); return modal; }; /** * Help the user to understand that the `body` can or cannot scroll to * the top or to the bottom, or both. * If the user can scroll up, a thin top inset shadow is displayed. * If the user can scroll down, a thin bottom inset shadow is displayed. */ function onScroll(body, evt) { if (body.scrollTop > 0) { $.addClass(body, "top"); } else { $.removeClass(body, "top"); } if (body.scrollHeight - body.scrollTop > body.clientHeight) { $.addClass(body, "bottom"); } else { $.removeClass(body, "bottom"); } } module.exports = Modal;