5// Created by Stefan Ritt on 5/8/15.
16 Dialog boxes consists of normal HTML code defined on the current web page. By
17 using the class "dlgFrame" they are automatically hidden until the
18 dlgShow() function is called. The dialog has a title bar and can be moved
19 around by dragging the title bar. The dlgHide() function should be called
20 to close (hide) the dialog.
22 Following button shows the dialog dlgXXX:
24 <button type="button" onClick="dlgShow('dlgXXX')">XXX</button>
26 Following HTML code defines the dialog dlgXXX:
28 <div id="dlgXXX" class="dlgFrame">
29 <div class="dlgTitlebar">Title</div>
30 <div class="dlgPanel">
31 <div>Dialog Contents</div>
32 <button class="dlgButton" onClick="dlgHide('dlgXXX')">Close</button>
41 Replacement for alert() function showing a standard notification
43 dlgConfirm(message, callback, param)
44 Replacement of confirm() dialog. Shows a message dialog with a 'Cancel'
45 and 'Ok' button. The callback is called with the first parameter either
46 true (if Ok has been clicked) or false (if Cancel has been clicked) and
47 the second parameter a copy of 'param' passed to dlgConfirm().
49 dlgQuery(message, value, callback, param)
50 Replacement of prompt() dialog. Shows a dialog box ith a 'Cancel', 'Ok'
51 button and a field to enter a value. 'message' is shown before the
52 input filed and can contain a string like 'Please enter value:'. If
53 'cancel' is pressed, the 'callback' function is called with the first
54 parameter equal 'false'. If 'Ok' is pressed, 'callback' is called with
55 the first parameter being the value of the input field. 'param' is just
56 passed to the callback function as an optional second parameter. So a
57 typical callback function can look like
59 function cb(value, param) {
61 alert('Value is '+value+', param is '+param);
64 where 'param' can also be ommitted.
66 dlgMessage(title, message, modal, error, callback, param)
67 Similar to dlgAlert, but with the option to set a custom title which
68 gets a red background if error is true. After the 'Ok' button is pressed,
69 the callback function is called with an optional parameter passed to
70 dlgMessage. If modal equals true, the whole screen is greyed out and all
71 mouse events are captured until the 'Ok' button is pressed.
74 Shows a model dialog with a progress bar for 'time' seconds and 'string'
75 in the first line. After 'time' seconds the dialog closes automatically.
80 <button name="ctrlHSlider" type="button" class="ctrlHSlider" data-update="xxx()" id="yyy"></button>
82 <button name="ctrlVSlider" type="button" class="ctrlVSlider" data-update="xxx()" id="yyy"></button>
84 On each change of the slider, the function xxx(value, final) is called with
85 value ranging from 0 to 1. Dragging the slider will cause many updates with
86 final = false, and once the mouse button got released, the funciton is called
87 once with final = true.
89 To set the slider programmatically call
91 document.getElementById('yyy').set(0.5);
93 Valid range is again 0 to 1.
99 <div name="ctrlProgress" style="width:xxxpx;color:yyy;" id="zzz"></div>
101 document.getElementById('yyy').set(v); // v = 0...1
108 <button name="ctrlButton" data-draw="xxx" type="button" id="yyy" onClick="zzz()"></button>
112 // example for an up-arrow with 36x36 pixels
115 let ctx = cvs.getContext("2d");
116 ctx.fillStyle = "#E0E0E0";
117 ctx.fillRect(0, 0, 36, 36);
124 ctx.fillStyle = "#808080";
130// default styles for dialog boxes
131let controls_css = `<style>
133 font-family: verdana,tahoma,sans-serif;
134 border: 1px solid black;
135 box-shadow: 6px 6px 10px 4px rgba(0,0,0,0.2);
141 display: none; /* pre-hidden */
146 background-color: #C0C0C0;
147 border-top-left-radius: 6px;
148 border-top-right-radius: 6px;
159 background-color: #F8F8F8;
160 border: 1px solid #808080;
167 background-color: #4187F7;
169 border: 1px solid #808080;
175 background-color: #F0F0F0;
178 background-color: #F0F0F0;
181 border-bottom-left-radius: 6px;
182 border-bottom-right-radius: 6px;
185 background: rgba(0,0,0,.5);
206 border: 1px solid #A0A0A0;
210 background-color: #E0E0E0;
218 background-color: #419bf9;
223(function (window) { // anonymous global function
224 window.addEventListener("load", ctlInit, false);
228 let CTL = new Controls();
232function Controls() // constructor
236Controls.prototype.init = function () // scan DOM
239 document.head.insertAdjacentHTML("beforeend", controls_css);
241 // scan DOM for controls
242 this.ctrlButton = document.getElementsByName("ctrlButton");
243 this.ctrlVSlider = document.getElementsByName("ctrlVSlider");
244 this.ctrlHSlider = document.getElementsByName("ctrlHSlider");
245 this.ctrlProgress = document.getElementsByName("ctrlProgress");
248 for (let i = 0; i < this.ctrlButton.length; i++) {
249 let cvs = document.createElement("canvas");
250 this.ctrlButton[i].appendChild(cvs);
252 if (this.ctrlButton[i].dataset.draw !== undefined)
253 eval(this.ctrlButton[i].dataset.draw + "(cvs)");
257 for (let i = 0; i < this.ctrlVSlider.length; i++) {
258 let cvs = document.createElement("canvas");
259 let sl = this.ctrlVSlider[i];
260 cvs.width = sl.clientWidth;
261 cvs.height = sl.clientHeight;
265 sl.position = 0.5; // slider position 0...1
266 sl.addEventListener("click", this.ctrlVSliderHandler.bind(this));
267 sl.addEventListener("contextmenu", this.ctrlVSliderHandler.bind(this));
268 sl.addEventListener("mousemove", this.ctrlVSliderHandler.bind(this));
269 sl.addEventListener("touchmove", this.ctrlVSliderHandler.bind(this));
270 sl.draw = this.ctrlVSliderDraw;
272 sl.set = this.ctrlVSliderSet;
276 for (let i = 0; i < this.ctrlHSlider.length; i++) {
277 let cvs = document.createElement("canvas");
278 let sl = this.ctrlHSlider[i];
279 cvs.width = sl.clientWidth;
280 cvs.height = sl.clientHeight;
284 sl.position = 0.5; // slider position 0...1
285 sl.addEventListener("click", this.ctrlHSliderHandler.bind(this));
286 sl.addEventListener("contextmenu", this.ctrlHSliderHandler.bind(this));
287 sl.addEventListener("mousemove", this.ctrlHSliderHandler.bind(this));
288 sl.addEventListener("touchmove", this.ctrlHSliderHandler.bind(this));
289 sl.addEventListener("mouseup", this.ctrlHSliderHandler.bind(this));
290 sl.draw = this.ctrlHSliderDraw;
292 sl.set = this.ctrlHSliderSet;
296 for (let i = 0; i < this.ctrlProgress.length; i++) {
297 let p = this.ctrlProgress[i];
298 p.className = "ctrlProgress";
299 let ind = document.createElement("div");
300 ind.className = "ctrlProgressInd";
301 ind.style.height = p.style.height;
302 ind.style.backgroundColor = p.style.color;
304 p.set = this.ctrlProgressSet;
309Controls.prototype.ctrlVSliderDraw = function (b) {
312 let w = b.canvas.width;
313 let h = b.canvas.height;
316 let ctx = b.canvas.getContext("2d");
317 ctx.fillStyle = "#E0E0E0";
318 ctx.fillRect(0, 0, b.canvas.width, b.canvas.height);
320 let knob = b.sliderOfs + (1 - b.position) * (h - 2 * b.sliderOfs);
322 ctx.strokeStyle = "#A0A0A0";
325 ctx.moveTo(w / 2, b.sliderOfs);
326 ctx.lineTo(w / 2, knob);
329 ctx.strokeStyle = "#00A0FF";
331 ctx.moveTo(w / 2, knob);
332 ctx.lineTo(w / 2, h - b.sliderOfs);
335 ctx.fillStyle = "#E0E0E0";
336 ctx.strokeStyle = "#C0C0C0";
338 ctx.arc(w / 2, knob, 10, 0, 2 * Math.PI);
343Controls.prototype.ctrlVSliderSet = function (pos) {
352Controls.prototype.ctrlVSliderHandler = function (e) {
355 let b = e.currentTarget;
357 if (b.canvas === undefined) // we can get events from parent node
360 if ((e.buttons === 1 && e.type === "mousemove") || e.type === "click")
362 if (e.type === "touchmove")
363 y = e.changedTouches[e.changedTouches.length - 1].clientY - b.getBoundingClientRect().top;
365 if (e.type === "contextmenu") {
367 this.ctrlVSliderDraw(b);
368 let f = b.dataset.update;
370 f = f.substr(0, f.indexOf("("));
371 window[f](b.position);
373 if (y !== undefined) {
374 b.position = 1 - (y - b.sliderOfs) / (b.clientHeight - 2 * b.sliderOfs);
379 this.ctrlVSliderDraw(b);
380 let f = b.dataset.update;
382 f = f.substr(0, f.indexOf("("));
383 window[f](b.position);
388Controls.prototype.ctrlHSliderDraw = function (b) {
391 let w = b.canvas.width;
392 let h = b.canvas.height;
395 let ctx = b.canvas.getContext("2d");
396 ctx.fillStyle = "#E0E0E0";
397 ctx.fillRect(0, 0, b.canvas.width, b.canvas.height);
399 let knob = b.sliderOfs + (b.position) * (w - 2 * b.sliderOfs);
401 ctx.strokeStyle = "#A0A0A0";
404 ctx.moveTo(w - b.sliderOfs, h / 2);
405 ctx.lineTo(knob, h / 2);
408 ctx.strokeStyle = "#00A0FF";
410 ctx.moveTo(knob, h / 2);
411 ctx.lineTo(b.sliderOfs, h / 2);
414 ctx.fillStyle = "#E0E0E0";
415 ctx.strokeStyle = "#C0C0C0";
417 ctx.arc(knob, h / 2, 10, 0, 2 * Math.PI);
422Controls.prototype.ctrlHSliderSet = function (pos) {
431Controls.prototype.ctrlHSliderHandler = function (e) {
434 let b = e.currentTarget;
436 if (b.canvas === undefined) // we can get events from parent node
439 if ((e.buttons === 1 && e.type === "mousemove") || e.type === "click")
441 if (e.type === "touchmove")
442 x = e.changedTouches[e.changedTouches.length - 1].clientX - b.getBoundingClientRect().left;
444 if (e.type === "contextmenu") {
446 b.contextMenu = true;
447 this.ctrlHSliderDraw(b);
448 let f = b.dataset.update;
450 f = f.substr(0, f.indexOf("("));
451 window[f](b.position, true);
454 if (x !== undefined) {
455 b.contextMenu = false;
456 b.position = (x - b.sliderOfs) / (b.clientWidth - 2 * b.sliderOfs);
461 this.ctrlHSliderDraw(b);
462 let f = b.dataset.update;
464 f = f.substr(0, f.indexOf("("));
465 window[f](b.position, false);
468 if (e.type === "mouseup" && !b.contextMenu) {
469 console.log(e.buttons);
470 let f = b.dataset.update;
472 f = f.substr(0, f.indexOf("("));
473 window[f](b.position, true);
477Controls.prototype.ctrlProgressSet = function (value) {
482 this.firstChild.style.width = Math.round(parseInt(this.style.width) * value) + "px";
485//-------------------------------------------------------------------------------------------------
486var dlgLoadedDialogs = [];
488function dlgLoad(url) {
489 // check if dialog already laoded
490 if (dlgLoadedDialogs.includes(url))
493 dlgLoadedDialogs.push(url);
495 // load dialog via AJAX
496 return new Promise(function (resolve, reject) {
497 let xhr = new XMLHttpRequest();
498 xhr.onreadystatechange = function () {
499 if (xhr.readyState === 4) {
500 if (xhr.status === 200) {
501 let d = document.createElement("div");
502 d.innerHTML = xhr.responseText;
503 document.body.appendChild(d);
504 resolve(xhr.responseText);
506 dlgAlert("network error: see javascript console: dlgLoad() cannot load " + url + ", HTTP status: " + xhr.status);
507 reject(xhr.responseURL);
512 xhr.open("GET", url, true);
513 xhr.setRequestHeader('Content-type', 'text/html');
518function drawCloseButton(c, mark) {
521 let ctx = c.getContext("2d");
522 ctx.clearRect(0, 0, c.width, c.height);
525 ctx.arc(c.width/2, c.height/2, c.width/2-1, 0, 2*Math.PI);
526 ctx.fillStyle = '#FD5E59';
528 ctx.strokeStyle = '#DF2020';
531 ctx.strokeStyle = '#000000';
534 ctx.moveTo(c.width/2-3, c.height/2-3);
535 ctx.lineTo(c.width/2+3, c.height/2+3);
536 ctx.moveTo(c.width/2+3, c.height/2-3);
537 ctx.lineTo(c.width/2-3, c.height/2+3);
542function dlgCenter(dlg) {
544 if (typeof dlg === "string")
545 d = document.getElementById(dlg);
550 dlgAlert("Dialog '" + dlg + "' does not exist");
554 d.style.position = "fixed";
555 d.style.left = Math.round(document.documentElement.clientWidth / 2 - d.offsetWidth / 2) + "px";
556 if (document.documentElement.clientHeight / 2 - d.offsetHeight / 2 < 0)
559 d.style.top = Math.round(document.documentElement.clientHeight / 2 - d.offsetHeight / 2) + "px";
561 // allow for scrolling of very high dialog boxes
562 if (d.offsetHeight > document.documentElement.clientHeight)
563 d.style.position = "absolute";
566function dlgShow(dlg, modal, param) {
568 if (typeof dlg === "string")
569 d = document.getElementById(dlg);
574 dlgAlert("Dialog '" + dlg + "' does not exist");
578 if (d.childNodes === undefined) {
579 dlgAlert("Dialog '" + dlg + "' has no title bar");
583 // add optional parameter to dialog
586 // put "close" icon into title bar
588 if (d.childNodes[0].className === "dlgTitlebar")
590 if (d.childNodes[1] && d.childNodes[1].className === "dlgTitlebar")
592 if (t !== undefined) {
593 let ttext = t.innerHTML;
594 if (ttext.search('dlgHide') === -1) {
595 t.innerHTML = "<div style=\"position: absolute;left: 6px;top: 3px;\" " +
596 "onclick=\"dlgClose(this);\">" +
597 "<canvas id=\"cvsClose\" width=\"14px\" height=\"14px\"></canvas>" +
600 d.canvas = t.childNodes[0].childNodes[0];
601 drawCloseButton(d.canvas, false);
608 d.modal = (modal === true);
610 d.style.display = "block";
613 // put dialog on top of all other dialogs
614 let dlgs = document.getElementsByClassName("dlgFrame");
615 for (let i = 0; i < dlgs.length; i++)
616 dlgs[i].style.zIndex = "30"; // on top of blackout (20)
617 d.style.zIndex = "31";
619 // move dialog right-down if on top of previous one
620 if (dlgs.length > 1) {
621 d.style.left = (parseInt(dlgs[dlgs.length - 2].style.left) + 30).toString() + "px";
622 d.style.top = (parseInt(dlgs[dlgs.length - 2].style.top) + 30).toString() + "px";
625 // enable scrolling if dialog box goes beyond screen
626 d.oldScroll = window.getComputedStyle(document.body).overflow;
627 document.body.style.overflow = "scroll";
630 let b = document.getElementById("dlgBlackout");
631 if (b === undefined || b === null) {
632 b = document.createElement("div");
633 b.id = "dlgBlackout";
634 b.className = "dlgBlackout";
635 document.body.appendChild(b);
638 b.style.display = "block";
642 d.dlgMouseDown = function (e) {
643 if (d.style.display === "none")
646 // ignore right mouse clicks
650 if ((e.target === this || e.target.parentNode === this) &&
651 e.target.className === "dlgTitlebar") {
655 this.Dx = parseInt(this.style.left);
656 this.Dy = parseInt(this.style.top);
659 if (d.modal && e.target !== d && !d.contains(e.target)) {
660 // catch all mouse events outside the dialog
663 if (e.target === this || d.contains(e.target)) {
664 let dlgs = document.getElementsByClassName("dlgFrame");
665 for (let i = 0; i < dlgs.length; i++)
666 dlgs[i].style.zIndex = "30";
667 d.style.zIndex = "31";
672 d.dlgMouseMove = function (e) {
673 if (d.style.display === "none")
676 // draw close button with "x" if mouse cursor is inside
677 drawCloseButton(d.canvas, e.target === d.canvas);
679 if (this.Ax > 0 && this.Ay > 0) {
683 // stop dragging if leaving window
684 if (x < 0 || y < 0 ||
685 x > document.documentElement.clientWidth ||
686 y > document.documentElement.clientHeight ||
687 (this.Dy + (y - this.Ay)) < 0) {
691 this.style.left = (this.Dx + (x - this.Ax)) + "px";
692 this.style.top = (this.Dy + (y - this.Ay)) + "px";
697 d.dlgMouseUp = function () {
702 d.dlgTouchStart = function (e) {
703 if (d.style.display === "none")
706 if ((e.target === this || e.target.parentNode === this) &&
707 e.target.className === "dlgTitlebar") {
709 this.Ax = e.targetTouches[0].clientX;
710 this.Ay = e.targetTouches[0].clientY;
711 this.Dx = parseInt(this.style.left);
712 this.Dy = parseInt(this.style.top);
715 if (d.modal && e.target !== d && !d.contains(e.target)) {
716 // catch all mouse events
719 if (e.target === this || d.contains(e.target)) {
720 let dlgs = document.getElementsByClassName("dlgFrame");
721 for (let i = 0; i < dlgs.length; i++)
722 dlgs[i].style.zIndex = "30";
723 d.style.zIndex = "31";
728 d.dlgTouchMove = function (e) {
729 if (d.style.display === "none")
732 if (this.Ax > 0 && this.Ay > 0) {
734 let x = e.changedTouches[e.changedTouches.length - 1].clientX;
735 let y = e.changedTouches[e.changedTouches.length - 1].clientY;
736 this.style.left = (this.Dx + (x - this.Ax)) + "px";
737 this.style.top = (this.Dy + (y - this.Ay)) + "px";
741 d.dlgTouchEnd = function (e) {
742 if (d.style.display === "none")
745 if (this.Ax > 0 && this.Ay > 0) {
752 d.dlgTouchCancel = function (e) {
753 if (d.style.display === "none")
756 if (this.Ax > 0 && this.Ay > 0) {
763 d.dlgKeyDown = function (e) {
764 if (d.style.display === "none")
767 if (e.key === 'Escape') {
769 dlgClose(d.childNodes[1].childNodes[0]);
772 window.addEventListener("keydown", d.dlgKeyDown.bind(d), true);
774 window.addEventListener("mousedown", d.dlgMouseDown.bind(d), true);
775 window.addEventListener("mousemove", d.dlgMouseMove.bind(d), true);
776 window.addEventListener("mouseup", d.dlgMouseUp.bind(d), true);
777 window.addEventListener("touchstart", d.dlgTouchStart.bind(d), true);
778 window.addEventListener("touchmove", d.dlgTouchMove.bind(d), true);
779 window.addEventListener("touchend", d.dlgTouchEnd.bind(d), true);
780 window.addEventListener("touchcancel", d.dlgTouchCancel.bind(d), true);
783function dlgMove(d, x, y) {
784 d.style.position = "fixed";
785 d.style.left = x + "px";
786 d.style.top = y + "px";
789function dlgClose(div) {
791 while (!dlg.className.includes("dlgFrame"))
792 dlg = dlg.parentElement;
793 if (dlg.shouldDestroy)
794 dlgMessageDestroy(dlg);
795 else if (dlg.id !== undefined)
799function dlgHide(dlg) {
800 if (typeof dlg === "string")
801 dlg = document.getElementById(dlg);
802 else if (dlg.type === "button") {
804 dlg = dlg.parentElement;
805 } while (dlg.className !== 'dlgFrame');
809 // only remove blackout if we are the only modal dialog left
810 let dlgs = document.getElementsByClassName("dlgFrame");
812 for (let i = 0; i < dlgs.length; i++)
813 if (dlgs[i].style.display === "block" && dlgs[i].modal)
816 let d = document.getElementById("dlgBlackout");
817 if (d !== undefined && d !== null)
818 d.style.display = "none";
821 dlg.style.display = "none";
822 if (dlg.oldScroll !== "")
823 document.body.style.overflow = dlg.oldScroll;
826function dlgMessageDestroy(b) {
828 while (!dlg.className.includes("dlgFrame"))
829 dlg = dlg.parentElement;
831 // only remove blackout if we are the only modal dialog left
832 let dlgs = document.getElementsByClassName("dlgFrame");
834 for (let i = 0; i < dlgs.length; i++)
835 if (dlgs[i].style.display === "block" && dlgs[i].modal)
838 let d = document.getElementById("dlgBlackout");
839 if (d !== undefined && d !== null)
840 d.style.display = "none";
843 // dialog is not really removed from memory, event listerner is still active and
844 // grabs mousdown events, so mark its display "none" to prevent eating mouse events
845 // above in dlgMouseDown routine
846 dlg.style.display = "none";
847 document.body.removeChild(dlg);
850function dlgMessage(title, string, modal, error, callback, param) {
851 let d = document.createElement("div");
852 d.className = "dlgFrame";
853 d.style.zIndex = modal ? "31" : "30";
854 d.callback = callback;
855 d.callbackParam = param;
856 d.shouldDestroy = true;
858 d.innerHTML = "<div class=\"dlgTitlebar\" id=\"dlgMessageTitle\">" + title + "</div>" +
859 "<div class=\"dlgPanel\" style=\"padding: 30px;\">" +
860 "<div id=\"dlgMessageString\">" + string + "</div>" +
861 "<br /><br /><button class=\"dlgButton\" id=\"dlgMessageButton\" type=\"button\" " +
862 " onClick=\"let d=this.parentElement.parentElement;if(d.callback!==undefined)d.callback(d.callbackParam);dlgMessageDestroy(this)\">Close</button>" +
865 document.body.appendChild(d);
867 if (error === true) {
868 let t = document.getElementById("dlgMessageTitle");
869 t.style.backgroundColor = "#9E2A2A";
870 t.style.color = "white";
877function dlgAlert(s, callback) {
878 dlgMessage('Message', s, true, false, callback);
881function dlgConfirm(string, confirmCallback, param) {
882 let d = document.createElement("div");
883 d.className = "dlgFrame";
884 d.style.zIndex = "31";
885 d.callback = confirmCallback;
886 d.callbackParam = param;
887 d.shouldDestroy = true;
889 d.innerHTML = "<div class=\"dlgTitlebar\" id=\"dlgMessageTitle\">Please confirm</div>" +
890 "<div class=\"dlgPanel\" style=\"padding: 30px;\">" +
891 "<div id=\"dlgMessageString\">" + string + "</div>" +
893 "<button class=\"dlgButtonDefault\" id=\"dlgMessageButtonOk\" type=\"button\" " +
894 " onClick=\"let d=this.parentElement.parentElement;d.callback(true,d.callbackParam);dlgMessageDestroy(this);\">OK</button>" +
895 "<button class=\"dlgButton\" id=\"dlgMessageButtonCancel\" type=\"button\" " +
896 " onClick=\"let d=this.parentElement.parentElement;d.callback(false,d.callbackParam);dlgMessageDestroy(this);\">Cancel</button>" +
899 document.body.appendChild(d);
902 document.getElementById('dlgMessageButtonOk').focus();
906// Populate a modal with a general html
907function dlgGeneral(p) {
908 /* general dialog containing p.html code and other optional parameters
909 p.iddiv - the name of the dialog div (optional)
910 p.width/p.height - minimal width/height of dialog (optional)
911 p.minWidth/p.minHeight - minimal width/height of dialog (optional)
912 p.x/p.y - initial position of dialog (optional)
913 p.title - title of the dialog (optional)
916 // First make sure you removed existing iddiv
917 if (document.getElementById(p.iddiv)) document.getElementById(p.iddiv).remove();
918 let d = document.createElement("div");
919 d.className = "dlgFrame";
920 if (p.iddiv) d.id = p.iddiv;
921 d.style.zIndex = "30";
922 d.style.overflow = "hidden";
923 d.style.resize = "both";
924 d.style.width = p.width? p.width + "px" : "400px";
925 d.style.height = p.height ? p.height + "px" : "200px";
926 d.style.minWidth = p.minWidth ? p.minWidth + "px" : d.style.width;
927 d.style.minHeight = p.minHeight ? p.minHeight + "px" : d.style.height;
928 d.style.maxHeight = "90vh";
929 d.style.maxWidth = "60vw";
930 d.shouldDestroy = true;
932 const dlgTitle = document.createElement("div");
933 dlgTitle.className = "dlgTitlebar";
934 //dlgTitle.id = "dlgMessageTitle";
935 dlgTitle.innerText = p.title || (p.iddiv ? p.iddiv + " dialog" : "General dialog");
936 d.appendChild(dlgTitle);
938 const dlgPanel = document.createElement("div");
939 dlgPanel.className = "dlgPanel";
940 //dlgPanel.id = "dlgPanel";
941 d.appendChild(dlgPanel);
943 const content = document.createElement("div");
944 //content.id = "dlgHTML";
945 content.style.overflow = "auto";
946 content.innerHTML = p.html;
947 dlgPanel.appendChild(content);
949 document.body.appendChild(d);
952 if (p.x !== undefined && p.y !== undefined)
953 dlgMove(d, p.x, p.y);
955 // Initial size based on content
956 d.style.height = (content.scrollHeight + dlgTitle.offsetHeight + 5 ) + "px";
957 d.style.width = (content.scrollWidth + 5 ) + "px";
959 // Function to handle resize events
960 function handleResize() {
961 content.style.height = (d.offsetHeight - dlgTitle.offsetHeight - 5 ) + "px";
964 // Resize observer to watch for dialog resizing
965 const resizeObs = new ResizeObserver(handleResize);
966 resizeObs.observe(d);
971function dlgQueryKeyDown(event, inp) {
972 let keyCode = ('which' in event) ? event.which : event.keyCode;
974 if (keyCode === 27) {
976 let d = inp.parentElement.parentElement.parentElement;
977 d.callback(false, d.callbackParam);
978 dlgMessageDestroy(inp.parentElement);
982 if (keyCode === 13) {
984 let d = inp.parentElement.parentElement.parentElement;
985 d.callback(inp.value, d.callbackParam);
986 dlgMessageDestroy(inp.parentElement);
993function dlgQuery(string, value, queryCallback, param, size) {
994 let d = document.createElement("div");
995 d.className = "dlgFrame";
996 d.style.zIndex = "31";
997 d.callback = queryCallback;
998 d.callbackParam = param;
999 d.shouldDestroy = true;
1001 if (size === undefined)
1004 d.innerHTML = "<div class=\"dlgTitlebar\" id=\"dlgMessageTitle\"> </div>" +
1005 "<div class=\"dlgPanel\" style=\"padding: 20px;\">" +
1006 "<div id=\"dlgMessageString\">" + string + " <input type='text' size='"+size+"' id='dlgQueryInput' onkeydown='return dlgQueryKeyDown(event, this);' value='" + value + "'></input></div>" +
1008 "<button class=\"dlgButtonDefault\" id=\"dlgMessageButton\" type=\"button\" " +
1009 " onClick=\"let d=this.parentElement.parentElement;d.callback(document.getElementById('dlgQueryInput').value,d.callbackParam);dlgMessageDestroy(this);\">OK</button>" +
1010 "<button class=\"dlgButton\" id=\"dlgMessageButton\" type=\"button\" " +
1011 " onClick=\"let d=this.parentElement.parentElement;d.callback(false,d.callbackParam);dlgMessageDestroy(this);\">Cancel</button>" +
1014 document.body.appendChild(d);
1017 document.getElementById('dlgQueryInput').focus();
1018 document.getElementById('dlgQueryInput').select();
1027let dlgWaitFuncParam;
1029function dlgWait(time, string, func, param) {
1031 let d = document.createElement("div");
1032 d.className = "dlgFrame";
1033 d.style.zIndex = "31";
1034 d.shouldDestroy = true;
1036 <!-- wait dialog -->
1037 d.innerHTML = "<div class=\"dlgTitlebar\" id=\"dlgMessageTitle\">Please wait...</div>" +
1038 "<div class=\"dlgPanel\" style=\"padding: 20px;\">" +
1039 "<div id=\"dlgMessageString\">" + string + "</div>" +
1041 "<div name=\"ctrlProgress\" style=\"width:250px;\" id=\"dlgWaitProgress\"></div>" +
1044 document.body.appendChild(d);
1046 // init progress bar
1047 let p = document.getElementById('dlgWaitProgress');
1048 p.className = "ctrlProgress";
1049 let ind = document.createElement("div");
1050 ind.className = "ctrlProgressInd";
1051 ind.style.height = p.style.height;
1052 ind.style.backgroundColor = p.style.color;
1054 p.set = function (value) {
1055 this.firstChild.style.width = Math.round(parseInt(this.style.width) * value) + "px";
1061 dlgWaitProgress = 0;
1064 dlgWaitFuncParam = param;
1065 window.setTimeout(updateDlgWaitProgress, 100);
1068function updateDlgWaitProgress() {
1069 dlgWaitProgress += 0.1;
1070 let d = document.getElementById("dlgWaitProgress");
1071 d.set(dlgWaitProgress / dlgWaitTime);
1072 if (dlgWaitProgress >= dlgWaitTime) {
1073 dlgWaitDialog.style.display = "none";
1074 document.body.removeChild(dlgWaitDialog);
1075 let d = document.getElementById("dlgBlackout");
1076 if (d !== undefined && d !== null)
1077 d.style.display = "none";
1078 if (dlgWaitFunc !== undefined)
1079 dlgWaitFunc(dlgWaitFuncParam);
1081 window.setTimeout(updateDlgWaitProgress, 100);