/** * BSDialog4 * @version v0.1.4.031 (2023/11/03 22:42) */ var BSDialog = { Show: async function (options) { const a = this; const _options = Object.assign(a.Options.ShowModal, options); a.id = _options.ID; a.pfx = "bsdia4_"; a.body = document.getElementsByTagName("body")[0]; a.addBackdrop(); a.addModal(_options.ID, _options.Title, _options.Size, _options.ShowFooter, _options.EasyClose, _options.Colour); if (_options.URL == null) { await a.Update({ ID: _options.ID, Body: _options.Message }); } else { if (a.isNullOrWhitespace(_options.URL)) { await a.Update({ ID: _options.ID, Body: _options.URL }); } else { if (_options.URL.startsWith("http://") || _options.URL.startsWith("https://") || _options.URL.startsWith("/")) { let response = await a.retrieveURL(_options.URL); await a.Update({ ID: _options.ID, Body: response }); } else { await a.Update({ ID: _options.ID, Body: _options.URL }); } } } }, Prompt: async function (options) { const a = this; let id = Math.floor(Math.random() * 10000) + 1000; const _options = Object.assign(a.Options.ShowPrompt, options); switch (_options.Type) { case "textbox": return await a.showTextboxPrompt(id, _options); case "button": default: return await a.showButtonPrompt(id, _options); } }, Clear: function () { this.body.querySelectorAll(".modal").forEach(function(e) { e.parentNode.removeChild(e); }); this.removeBackdrop(); }, Close: function (id) { let modal = this.Find(id); if (modal === null) { return; } modal.Modal.parentNode.removeChild(modal.Modal); modal = this.Find(id); if (modal !== null) { return; } this.removeBackdrop(); }, Update: async function (options) { const a = this; let _options = Object.assign(a.Options.UpdateModal, options); const modal = a.Find(_options.ID); if (modal === null) { return; } if (!this.isNullOrWhitespace(_options.Title)) { modal.Title.innerHTML = _options.Title; } if (!this.isNullOrWhitespace(_options.Body)) { a.html(modal.Body, _options.Body); } if (!this.isNullOrWhitespace(_options.BodyURL)) { if (_options.BodyURL.startsWith("http://") || _options.BodyURL.startsWith("https://") || _options.BodyURL.startsWith("/")) { // ok } else { _options.BodyURL = null; } } if (!this.isNullOrWhitespace(_options.BodyURL)) { let response = await a.retrieveURL(_options.BodyURL); await a.Update({ ID: _options.ID, Body: response }); } if (!this.isNullOrWhitespace(_options.Footer)) { a.html(modal.Footer, _options.Footer); } if (!this.isNullOrWhitespace(_options.Size)) { modal.Modal.querySelectorAll(".modal-dialog").forEach(function(e) { e.classList.forEach(function(e2) { if (e2 == "modal-dialog") { return; } if (e2.startsWith("modal-")) { e.classList.remove(e2); } }); e.classList.add("modal-" + _options.Size); }); } }, Exists: function (id) { return (this.Find(id) !== null); }, Find: function (id) { const a = this; const modal = a.body.querySelectorAll("#" + a.pfx + id + ".modal"); if (!modal) { return null; } if (modal.length <= 0) { return null; } return { Title: modal[0].querySelectorAll(".modal-title")[0], Header: modal[0].querySelectorAll(".modal-header")[0], Body: modal[0].querySelectorAll(".modal-body")[0], Footer: modal[0].querySelectorAll(".modal-footer")[0], Close: modal[0].querySelectorAll("[data-dismiss='modal']"), Modal: modal[0] }; }, Options: { ShowModal: { ID: null, Title: "", Message: "", URL: null, Size: "md", Colour: "secondary", ShowFooter: true, EasyClose: true }, ShowPrompt: { Type: "button", Title: "", Message: "", Size: "md", EasyClose: true, Buttons: [ { Label: "Yes", Value: "Yes", Colour: "primary" }, { Label: "No", Value: "No", Colour: "secondary" }, { Label: "Cancel", Value: "Cancel", Colour: "secondary" } ], Textbox: { Label: "", LabelSize: 4, Placeholder: "", Value: "", BoxSize: 8 } }, UpdateModal: { ID: null, Title: null, Body: null, BodyURL: null, Footer: null, Size: null }, ShowToast: { ID: null, Title: "", Message: "", Size: "md" } }, addBackdrop: function () { const a = this; // don't allow duplicates if (a.body.querySelectorAll(".modal-backdrop").length > 0) { return; } a.appendHtml(a.body, ''); // lock background a.body.classList.add("modal-open"); a.body.style.overflow = "hidden"; }, addModal: function (id, title, size, showFooter, easyClose, closeColour) { const a = this; // don't allow duplicates let modal = a.Find(id); if (modal !== null) { return; } let html = ""; html += ''; a.appendHtml(a.body, html); modal = a.Find(id); if (modal === null) { return; } // Close on backdrp if (easyClose === true) { modal.Modal.addEventListener("click", function(e){ e.stopPropagation(); e.preventDefault(); a.Close(id); }); const modalContent = modal.Modal.querySelectorAll(".modal-content")[0]; modalContent.addEventListener("click", function(e){ e.stopPropagation(); e.preventDefault(); }); } modal.Close.forEach(function(e){ e.addEventListener("click", function(e){ e.stopPropagation(); e.preventDefault(); a.Close(id); }); }); modal.Title.addEventListener("dblclick", function(e){ e.stopPropagation(); e.preventDefault(); a.toggleSize(); }); }, showButtonPrompt: async function (id, options) { const a = this; return await new Promise(async (resolve, reject) => { await a.Show({ ID: id, Title: options.Title, Message: options.Message, Size: options.Size, EasyClose: options.EasyClose }); let html = ''; options.Buttons.forEach(function(e) { html += ''; }); a.Update({ ID: id, Footer: html }); const modal = a.Find(id); modal.Footer.querySelectorAll("button").forEach(function(button) { button.addEventListener("click", function(e){ e.stopPropagation(); e.preventDefault(); const value = button.getAttribute("data-prompt-value"); a.Close(id); resolve(value); }); }); modal.Close.forEach(function(sender) { sender.addEventListener("click", function(e){ e.stopPropagation(); e.preventDefault(); a.Close(id); resolve(""); }); }); }); }, showTextboxPrompt: async function (id, options) { const a = this; return await new Promise(async (resolve, reject) => { options.Buttons = [ { Label: "OK", Value: "", Colour: "primary" }, { Label: "Cancel", Value: "", Colour: "secondary" } ]; await a.Show({ ID: id, Title: options.Title, Message: options.Message, Size: options.Size, EasyClose: options.EasyClose }); let body = ''; if (!a.isNullOrWhitespace(options.Message)) { body += '

' + options.Message + '

'; } body += '
'; if (a.isNullOrWhitespace(options.Textbox.Label) || (options.Textbox.LabelSize <= 0)) { body += '
'; body += ''; body += '
'; } else { body += ''; body += '
'; body += ''; body += '
'; } body += '
'; let footer = ''; options.Buttons.forEach(function(e) { footer += ''; }); a.Update({ ID: id, Body: body, Footer: footer }); const modal = a.Find(id); const buttons = modal.Footer.querySelectorAll("button"); buttons[0].addEventListener("click", function(e){ e.stopPropagation(); e.preventDefault(); const value = modal.Body.querySelectorAll("input")[0].value; a.Close(id); resolve(value); }); buttons[1].addEventListener("click", function(e){ e.stopPropagation(); e.preventDefault(); a.Close(id); resolve(""); }); modal.Close.forEach(function(sender) { sender.addEventListener("click", function(e){ e.stopPropagation(); e.preventDefault(); a.Close(id); resolve(""); }); }); }); }, appendHtml: function (el, html) { let node = document.createElement('template'); node.innerHTML = html; node = node.content.firstChild; el.appendChild(node); }, html: function (el, newHtml) { /// todo: replace with pure JS if (jQuery) { jQuery(el).html(newHtml); } else { el.innerHTML = newHtml; } }, isNullOrWhitespace: function(e) { if (typeof (e) == "undefined") { return true; } if (e == null) { return true; } if (e == false) { return true; } return (e.trim().length <= 0); }, removeBackdrop: function () { if (this.body.querySelectorAll(".modal-backdrop").length <= 0) { return; } if (this.body.querySelectorAll(".modal").length > 0) { return; } let backdrop = this.body.querySelectorAll(".modal-backdrop")[0]; backdrop.parentNode.removeChild(backdrop); // unlock background this.body.classList.remove("modal-open"); this.body.style.overflow = null; }, retrieveURL: async function (url) { return await new Promise(async (resolve) => { await fetch(url, { cache: 'no-cache', credentials: 'same-origin' }).then(data => data.text()).then(data => { resolve(data); }).catch((error) => { resolve("Error: " + error); }); }); }, toggleSize: function () { const a = this; let modal = a.Find(a.id); if (modal === null) { return; } let modalDialog = modal.Modal.querySelectorAll(".modal-dialog")[0]; if (modalDialog.classList.contains('modal-sm')) { a.Update({ ID: a.id, Size: "md" }); } else if (modalDialog.classList.contains('modal-md')) { a.Update({ ID: a.id, Size: "lg" }); } else if (modalDialog.classList.contains('modal-lg')) { a.Update({ ID: a.id, Size: "xl" }); } else if (modalDialog.classList.contains('modal-xl')) { a.Update({ ID: a.id, Size: "xxl" }); } else if (modalDialog.classList.contains('modal-xxl')) { a.Update({ ID: a.id, Size: "sm" }); } else { a.Update({ ID: a.id, Size: "md" }); } }, // // // deprecated/legacy-support Create: async function (id, title, url, size) { await this.Show({ ID: id, Title: title, Message: url, URL: url, Size: size, Colour: "secondary" }); }, UpdateTitle: function (id, title) { this.Update({ ID: id, Title: title }); }, UpdateSize: function (id, size) { this.Update({ ID: id, Size: size }); }, UpdateBody: function (id, content) { this.Update({ ID: id, Body: content }); }, UpdateFooter: function (id, content) { this.Update({ ID: id, Footer: content }); }, Toast: async function (options) { const a = this; const _options = Object.assign(a.Options.ShowToast, options); await this.Show({ ID: _options.ID, Title: _options.Title, Message: _options.Message, URL: null, Size: _options.Size, Colour: "secondary", ShowFooter: false }); }, ShowToast: function (id, title, message, size) { this.Toast({ ID: id, Title: title, Message: message, Size: size }); } };