1 // Copyright (C) 2005 Rod Roark <rod@sunsetsystems.com>
2 // Copyright (C) 2018-2020 Jerry Padgett <sjpadgett@gmail.com>
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
10 define(['jquery'], function ($, root) {
11 let opts_default = {};
15 root.confirm = confirm;
16 root.closeAjax = closeAjax;
23 buttons: data.buttons,
24 allowDrag: data.allowDrag,
25 allowResize: data.allowResize,
26 sizeHeight: data.sizeHeight,
28 resolvePromiseOn: data.resolvePromiseOn,
31 dataType: data.dataType // xml/json/text etc.
34 let title = data.title;
36 return dlgopen('', '', data.size, 0, '', title, opts);
39 function alert(data, title) {
40 title = title ? title : 'Alert';
41 let alertTitle = '<span class="text-danger bg-light"><i class="fa fa-exclamation-triangle"></i> ' + title + '</span>';
42 return dlgopen('', '', 675, 0, '', alertTitle, {
44 {text: '<i class="fa fa-thumbs-up mr-1"></i>OK', close: true, style: 'primary'}
48 html: '<p>' + data + '</p>'
52 function confirm(data, title) {
53 title = title ? title : 'Confirm';
54 let alertTitle = '<span class="text-info bg-light"><i class="fa fa-exclamation-triangle"></i> ' + title + '</span>';
55 return dlgopen('', '', "modal-md", 0, '', alertTitle, {
57 {text: '<i class="fa fa-thumbs-up mr-1"></i>Yes', close: true, id: 'confirmYes', style: 'primary'},
58 {text: '<i class="fa fa-thumbs-down mr-1"></i>No', close: true, id: 'confirmNo', style: 'primary'},
59 {text: 'Nevermind', close: true, style: 'secondary'}
62 resolvePromiseOn: 'confirm',
64 html: '<p>' + data + '</p>'
68 function closeAjax() {
77 if (typeof window.xl !== 'function') {
79 await includeScript(utilfn, 'script');
80 })(top.webroot_url + '/library/js/utility.js').then(() => {
81 console.log('Utilities Unavailable! loading:[ ' + utilfn + ' ] For: [ ' + location + ' ]');
84 }(typeof define == 'function' && define.amd ?
86 function (args, mName) {
87 this.dialog = typeof module != 'undefined' && module.exports ?
88 mName(require(args[0], {}), module.exports) :
93 // open a new cascaded window
94 function cascwin(url, winname, width, height, options) {
95 var mywin = window.parent ? window.parent : window;
96 var newx = 25, newy = 25;
97 if (!isNaN(mywin.screenX)) {
98 newx += mywin.screenX;
99 newy += mywin.screenY;
100 } else if (!isNaN(mywin.screenLeft)) {
101 newx += mywin.screenLeft;
102 newy += mywin.screenTop;
104 if ((newx + width) > screen.width || (newy + height) > screen.height) {
108 top.restoreSession();
110 // MS IE version detection taken from
111 // http://msdn2.microsoft.com/en-us/library/ms537509.aspx
112 // to adjust the height of this box for IE only -- JRM
113 if (navigator.appName == 'Microsoft Internet Explorer') {
114 var ua = navigator.userAgent;
115 var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
116 if (re.exec(ua) != null)
117 rv = parseFloat(RegExp.$1); // this holds the version number
118 height = height + 28;
121 retval = window.open(url, winname, options +
122 ",width=" + width + ",height=" + height +
123 ",left=" + newx + ",top=" + newy +
124 ",screenX=" + newx + ",screenY=" + newy);
129 // recursive window focus-event grabber
130 function grabfocus(w) {
131 for (var i = 0; i < w.frames.length; ++i) grabfocus(w.frames[i]);
132 w.onfocus = top.imfocused;
135 // Call this when a "modal" windowed dialog is desired.
136 // Note that the below function is free standing for either
137 // ui's.Use dlgopen() for responsive b.s modal dialogs.
138 // Can now use anywhere to cascade natives...12/1/17 sjp
140 function dlgOpenWindow(url, winname, width, height) {
141 if (top.modaldialog && !top.modaldialog.closed) {
142 if (window.focus) top.modaldialog.focus();
143 if (top.modaldialog.confirm(top.oemr_dialog_close_msg)) {
144 top.modaldialog.close();
145 top.modaldialog = null;
150 top.modaldialog = cascwin(url, winname, width, height,
151 "resizable=1,scrollbars=1,location=0,toolbar=0");
156 // This is called from del_related() which in turn is invoked by find_code_dynamic.php.
157 // Deletes the specified codetype:code from the indicated input text element.
158 function my_del_related(s, elem, usetitle) {
160 // Deleting everything.
167 // Convert the codes and their descriptions to arrays for easy manipulation.
168 var acodes = elem.value.split(';');
169 var i = acodes.indexOf(s);
171 return; // not found, should not happen
173 // Delete the indicated code and description and convert back to strings.
175 elem.value = acodes.join(';');
177 var atitles = elem.title.split(';');
178 atitles.splice(i, 1);
179 elem.title = atitles.join(';');
183 function dialogID() {
185 return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
188 return s4() + s4() + s4() + s4() + s4() + +s4() + s4() + s4();
191 // test for and/or remove dependency.
192 function inDom(dependency, type, remove) {
194 let attr = type === 'script' ? 'src' : type === 'link' ? 'href' : 'none';
195 let all = document.getElementsByTagName(el);
196 for (let i = all.length; i > -1; i--) {
197 if (all[i] && all[i].getAttribute(attr) !== null && all[i].getAttribute(attr).indexOf(dependency) !== -1) {
199 all[i].parentNode.removeChild(all[i]);
200 console.log("Removed from DOM: " + dependency);
210 // test to see if bootstrap theming is loaded (via standard or custom bootstrap library)
211 // Will check for the badge-secondary class
212 // - if exist, then assume bootstrap loaded
213 // - if not exist, then assume bootstrap not loaded
214 function isBootstrapCss() {
215 for (let i = 0; i < document.styleSheets.length; i++) {
216 let rules = document.styleSheets[i].rules || document.styleSheets[i].cssRules;
217 for (let x in rules) {
218 if (rules[x].selectorText == '.badge-secondary') {
226 // These functions may be called from scripts that may be out of scope with top so...
227 // if opener is tab then we need to be in tabs UI scope and while we're at it, let's bring webroot along...
229 if (typeof top.webroot_url === "undefined" && opener) {
230 if (typeof opener.top.webroot_url !== "undefined") {
231 top.webroot_url = opener.top.webroot_url;
234 // We'll need these if out of scope
236 if (typeof top.set_opener !== "function") {
237 var opener_list = [];
239 function set_opener(window, opener) {
240 top.opener_list[window] = opener;
243 function get_opener(window) {
244 return top.opener_list[window];
248 // universal alert popup message
249 if (typeof alertMsg !== "function") {
250 function alertMsg(message, timer = 5000, type = 'danger', size = '', persist = '') {
251 // this xl() is just so cool.
252 let gotIt = xl("Got It");
253 let title = xl("Alert");
254 let dismiss = xl("Dismiss");
255 $('#alert_box').remove();
257 oHidden = !persist ? "hidden" : '';
258 let oSize = (size == 'lg') ? 'left:10%;width:80%;' : 'left:25%;width:50%;';
259 let style = "position:fixed;top:25%;" + oSize + " bottom:0;z-index:9999;";
260 $("body").prepend("<div class='container text-center' id='alert_box' style='" + style + "'></div>");
261 let mHtml = '<div id="alertmsg" class="alert alert-' + type + ' alert-dismissable">' +
262 '<button type="button" class="btn btn-link ' + oHidden + '" id="dontShowAgain" data-dismiss="alert">' +
263 gotIt + ' <i class="fa fa-thumbs-up"></i></button>' +
264 '<h4 class="alert-heading text-center">' + title + '!</h4><hr>' + '<p style="color:#000;">' + message + '</p>' +
265 '<button type="button" class="pull-right btn btn-link" data-dismiss="alert">' + dismiss + '</button><br /></div>';
266 $('#alert_box').append(mHtml);
267 $('#alertmsg').on('closed.bs.alert', function () {
268 clearTimeout(AlertMsg);
269 $('#alert_box').remove();
272 $('#dontShowAgain').on('click', function (e) {
273 persistUserOption(persist, 1);
275 let AlertMsg = setTimeout(function () {
276 $('#alertmsg').fadeOut(800, function () {
277 $('#alert_box').remove();
282 const persistUserOption = function (option, value) {
284 url: top.webroot_url + "/library/ajax/user_settings.php",
286 contentType: 'application/x-www-form-urlencoded',
288 csrf_token_form: top.csrf_token_js,
292 beforeSend: function () {
293 top.restoreSession();
295 error: function (jqxhr, status, errorThrown) {
296 console.log(errorThrown);
303 // Test if supporting dialog callbacks and close dependencies are in scope.
304 // This is useful when opening and closing the dialog is in the same scope. Still use include_opener.js
305 // in script that will close a dialog that is not in the same scope dlgopen was used
306 // or use parent.dlgclose() if known decedent.
307 // dlgopen() will always have a name whether assigned by dev or created by function.
308 // Callback, onClosed and button clicks are still available either way.
309 // For a callback on close use: dlgclose(functionName, farg1, farg2 ...) which becomes: functionName(farg1,farg2, etc)
311 if (typeof dlgclose !== "function") {
316 function dlgclose(call, args) {
317 var frameName = window.name;
319 if (frameName === '') {
320 // try to find dialog. dialogModal is embedded dialog class
321 // It has to be here somewhere.
322 frameName = $(".dialogModal").attr('id');
324 frameName = parent.$(".dialogModal").attr('id');
326 console.log("Unable to find dialog.");
331 var dialogModal = top.$('div#' + frameName);
333 var removeFrame = dialogModal.find("iframe[name='" + frameName + "']");
334 if (removeFrame.length > 0) {
335 removeFrame.remove();
338 if (dialogModal.length > 0) {
340 wframe.setCallBack(call, args); // sets/creates callback function in dialogs scope.
342 dialogModal.modal('hide');
344 // no opener not iframe must be in here
345 $(this.document).find(".dialogModal").modal('hide');
351 * function dlgopen(url, winname, width, height, forceNewWindow, title, opts)
353 * @summary Stackable, resizable and draggable responsive ajax/iframe dialog modal.
355 * @param {url} string Content location.
356 * @param {String} winname If set becomes modal id and/or iframes name. Or, one is created/assigned(iframes).
357 * @param {Number| String} width|modalSize(modal-xl) For sizing: an number will be converted to a percentage of view port width.
358 * @param {Number} height Initial minimum height. For iframe auto resize starts at this height.
359 * @param {boolean} forceNewWindow Force using a native window.
360 * @param {String} title If exist then header with title is created otherwise no header and content only.
361 * @param {Object} opts Dialogs options.
362 * @returns {Object} dialog object reference.
364 function dlgopen(url, winname, width, height, forceNewWindow, title, opts) {
365 // First things first...
366 top.restoreSession();
367 // A matter of Legacy
368 if (forceNewWindow) {
369 return dlgOpenWindow(url, winname, width, height);
372 // wait for DOM then check dependencies needed to run this feature.
373 // dependency duration is while 'this' is in scope, temporary...
374 // seldom will this get used as more of U.I is moved to Bootstrap
375 // but better to continue than stop because of a dependency...
377 let jqurl = top.webroot_url + '/public/assets/jquery/dist/jquery.min.js';
378 if (typeof jQuery === 'undefined') {
380 await includeScript(utilfn, 'script');
384 // Check for dependencies we will need.
385 // webroot_url is a global defined in main_screen.php or main.php.
386 let bscss = top.webroot_url + '/public/assets/bootstrap/dist/css/bootstrap.min.css';
387 let bscssRtl = top.webroot_url + '/public/assets/bootstrap-v4-rtl/dist/css/bootstrap-rtl.min.css';
388 let bsurl = top.webroot_url + '/public/assets/bootstrap/dist/js/bootstrap.bundle.min.js';
390 let version = jQuery.fn.jquery.split(' ')[0].split('.');
391 if ((version[0] < 2 && version[1] < 9) || (version[0] === 1 && version[1] === 9 && version[2] < 1)) {
392 inDom('jquery-min', 'script', true);
394 await includeScript(utilfn, 'script');
395 })(jqurl).then(() => {
396 console.log('Replacing jQuery version:[ ' + version + ' ]');
399 if (!isBootstrapCss()) {
401 await includeScript(utilfn, 'link');
403 if (top.jsLanguageDirection == 'rtl') {
405 await includeScript(utilfn, 'link');
409 if (typeof jQuery.fn.modal === 'undefined') {
410 if (!inDom('bootstrap.bundle.min.js', 'script', false)) {
412 await includeScript(utilfn, 'script');
419 var opts_defaults = {
420 type: 'iframe', // POST, GET (ajax) or iframe
422 frameContent: "", // for iframe embedded content
423 html: "", // content for alerts, comfirm etc ajax
426 sizeHeight: 'auto', // 'full' will use as much height as allowed
427 // use is onClosed: fnName ... args not supported however, onClosed: 'reload' is auto defined and requires no function to be created.
429 callBack: false, // use {call: 'functionName, args: args, args} if known or use dlgclose.
430 resolvePromiseOn: '' // this may be useful values are init, shown, show, confirm, alert and closed which coincide with dialog events.
436 opts = jQuery.extend({}, opts_defaults, opts);
437 opts.type = opts.type ? opts.type.toLowerCase() : '';
438 opts.resolvePromiseOn = opts.resolvePromiseOn ?? 'init';
439 var mHeight, mWidth, mSize, msSize, dlgContainer, fullURL, where; // a growing list...
441 where = (opts.type === 'iframe') ? top : window;
443 // get url straight...
449 if (url[0] === "/") {
452 fullURL = window.location.href.substr(0, window.location.href.lastIndexOf("/") + 1) + url;
456 // what's a window without a name. important for stacking and opener.
457 winname = (winname === "_blank" || !winname) ? dialogID() : winname;
459 // for small screens or request width is larger than viewport.
460 if (where.innerWidth <= 768) {
463 // Convert dialog size to percentages and/or css class.
464 var sizeChoices = ['modal-sm', 'modal-md', 'modal-mlg', 'modal-lg', 'modal-xl', 'modal-full'];
465 if (Math.abs(width) > 0) {
466 width = Math.abs(width);
467 mWidth = (width / where.innerWidth * 100).toFixed(1) + '%';
468 msSize = '<style>.modal-custom-' + winname + ' {max-width:' + mWidth + ' !important;}</style>';
469 mSize = 'modal-custom' + winname;
470 } else if (jQuery.inArray(width, sizeChoices) !== -1) {
471 mSize = width; // is a modal class
473 msSize = '<style>.modal-custom-' + winname + ' {max-width:35% !important;}</style>'; // standard B.S. modal default (modal-md)
475 // leave below for legacy
476 if (mSize === 'modal-sm') {
477 msSize = '<style>.modal-custom-' + winname + ' {max-width:25% !important;}</style>';
478 } else if (mSize === 'modal-md') {
479 msSize = '<style>.modal-custom-' + winname + ' {max-width:40% !important;}</style>';
480 } else if (mSize === 'modal-mlg') {
481 msSize = '<style>.modal-custom-' + winname + ' {max-width:55% !important;}</style>';
482 } else if (mSize === 'modal-lg') {
483 msSize = '<style>.modal-custom-' + winname + ' {max-width:75% !important;}</style>';
484 } else if (mSize === 'modal-xl') {
485 msSize = '<style>.modal-custom-' + winname + ' {max-width:92% !important;}</style>';
486 } else if (mSize === 'modal-full') {
487 msSize = '<style>.modal-custom-' + winname + ' {max-width:97% !important;}</style>';
489 mSize = 'modal-custom-' + winname;
491 // Initial responsive height.
492 var vpht = where.innerHeight;
493 mHeight = height > 0 ? (height / vpht * 100).toFixed(1) + 'vh' : '';
495 // Build modal template. For now !title = !header and modal full height.
496 var mTitle = title > "" ? '<h5 class=modal-title>' + title + '</h5>' : '';
499 '<div class="loadProgress text-center">' +
500 '<span class="fa fa-circle-o-notch fa-spin fa-3x text-primary"></span>' +
504 ('<div class="modal-header">%title%<button type="button" class="close" data-dismiss="modal">' +
505 '×</button></div>').replace('%title%', mTitle);
508 ('<iframe id="modalframe" class="w-100 h-100 modalIframe" name="%winname%" %url% frameborder=0></iframe>').replace('%winname%', winname).replace('%url%', fullURL ? 'src=' + fullURL : '');
510 var contentStyles = ('style="height:%initHeight%; max-height: 94vh"').replace('%initHeight%', opts.sizeHeight !== 'full' ? mHeight : '85vh');
512 var altClose = '<div class="closeDlgIframe" data-dismiss="modal" ></div>';
515 ('<div id="%id%" class="modal fade dialogModal" tabindex="-1" role="dialog">%sizeStyle%' +
516 '<style>.drag-resize {touch-action:none;user-select:none;}</style>' +
517 '<div %dialogId% class="modal-dialog %drag-action% %sizeClass%" role="dialog">' +
518 '<div class="modal-content %resize-action%" %contentStyles%>' + '%head%' + '%altclose%' + '%wait%' +
519 '<div class="modal-body px-1">' + '%body%' + '</div></div></div></div>').replace('%id%', winname).replace('%sizeStyle%', msSize ? msSize : '').replace('%dialogId%', opts.dialogId ? ('id=' + opts.dialogId + '"') : '').replace('%sizeClass%', mSize ? mSize : '').replace('%head%', mTitle !== '' ? headerhtml : '').replace('%altclose%', mTitle === '' ? altClose : '').replace('%drag-action%', (opts.allowDrag) ? 'drag-action' : '').replace('%resize-action%', (opts.allowResize) ? 'resize-action' : '').replace('%wait%', '').replace('%contentStyles%', contentStyles).replace('%body%', opts.type === 'iframe' ? frameHtml : '');
521 // Write modal template.
522 dlgContainer = where.jQuery(mhtml);
523 dlgContainer.attr("name", winname);
525 // No url and just iframe content
526 if (opts.frameContent && opts.type === 'iframe') {
527 var ipath = 'data:text/html,' + encodeURIComponent(opts.frameContent);
528 dlgContainer.find("iframe[name='" + winname + "']").attr("src", ipath);
532 dlgContainer.find('.modal-content').append(buildFooter());
535 if (opts.type === 'alert') {
536 dlgContainer.find('.modal-body').html(opts.html);
538 if (opts.type === 'confirm') {
539 dlgContainer.find('.modal-body').html(opts.html);
541 if (opts.type !== 'iframe' && opts.type !== 'alert' && opts.type !== 'confirm') {
544 method: opts.type || '', // if empty and has data object, then post else get.
545 content: opts.data || opts.html, // ajax loads fetched content.
546 url: opts.url || fullURL,
547 dataType: opts.dataType || '' // xml/json/text etc.
550 dialogAjax(params, dlgContainer, opts);
553 // let opener array know about us.
554 top.set_opener(winname, window);
556 // Write the completed template to calling document or 'where' window.
557 where.jQuery("body").append(dlgContainer);
560 return new Promise((resolve, reject) => {
562 // DOM Ready. Handle events and cleanup.
563 if (opts.type === 'iframe') {
564 var modalwin = where.jQuery('body').find("[name='" + winname + "']");
565 jQuery('div.modal-dialog', modalwin).css({'margin': "0.75rem auto auto"});
566 modalwin.on('load', function (e) {
567 setTimeout(function () {
568 if (opts.sizeHeight === 'auto' && opts.type === 'iframe') {
569 SizeModaliFrame(e, height);
570 } else if (opts.sizeHeight === 'fixed') {
573 sizing(e, height); // must be full height of container
578 var modalwin = where.jQuery('body').find("[name='" + winname + "']");
579 jQuery('div.modal-dialog', modalwin).css({'margin': '15px auto auto'});
580 modalwin.on('show.bs.modal', function (e) {
581 setTimeout(function () {
586 if (opts.resolvePromiseOn === 'confirm') {
587 jQuery("#confirmYes").on('click', function (e) {
590 jQuery("#confirmNo").on('click', function (e) {
595 dlgContainer.on('show.bs.modal', function () {
596 if (opts.allowResize || opts.allowDrag) {
597 initDragResize(where.document, where.document);
600 if (opts.resolvePromiseOn === 'show') {
601 resolve(dlgContainer);
603 }).on('shown.bs.modal', function () {
604 // Remove waitHtml spinner/loader etc.
605 jQuery(this).parent().find('div.loadProgress').fadeOut(function () {
606 jQuery(this).remove();
608 dlgContainer.modal('handleUpdate'); // allow for scroll bar
610 if (opts.resolvePromiseOn === 'shown') {
611 resolve(dlgContainer);
613 }).on('hidden.bs.modal', function (e) {
615 e.target.style.cursor = "pointer";
617 jQuery(this).remove();
618 // now we can run functions in our window.
620 console.log('Doing onClosed:[' + opts.onClosed + ']');
621 if (opts.onClosed === 'reload') {
622 window.location.reload();
624 window[opts.onClosed]();
627 if (opts.callBack.call) {
628 console.log('Doing callBack:[' + opts.callBack.call + '|' + opts.callBack.args + ']');
629 if (opts.callBack.call === 'reload') {
630 window.location.reload();
632 window[opts.callBack.call](opts.callBack.args);
636 if (opts.resolvePromiseOn == 'close') {
637 resolve(dlgContainer);
641 // define local dialog close() function. openers scope
642 window.dlgCloseAjax = function (calling, args) {
644 opts.callBack = {call: calling, args: args};
646 dlgContainer.modal('hide'); // important to clean up in only one place, hide event....
650 // define local callback function. Set with opener or from opener, will exe on hide.
651 window.dlgSetCallBack = function (calling, args) {
652 opts.callBack = {call: calling, args: args};
656 // in residents dialog scope
657 where.setCallBack = function (calling, args) {
658 opts.callBack = {call: calling, args: args};
662 where.getOpener = function () {
665 // dialog is completely built and events set
666 // this is default returning our dialog container reference.
667 if (opts.resolvePromiseOn == 'init') {
668 resolve(dlgContainer);
670 // Finally Show Dialog after DOM settles
671 dlgContainer.modal({backdrop: 'static', keyboard: true}, 'show');
673 }); /* Returning Promise */
675 // Ajax call with promise via dialog
676 function dialogAjax(data, $dialog, opts) {
679 method: data.method || '',
682 dataType: data.dataType || 'html'
686 jQuery.extend(params, data);
689 jQuery.ajax(params).done(aOkay).fail(oops);
693 function aOkay(html) {
695 $dialog.find('.modal-body').html(data.success ? data.success(html) : html);
700 function oops(r, s) {
701 var msg = data.error ?
702 data.error(r, s, params) :
703 '<div class="alert alert-danger">' +
704 '<strong>XHR Failed:</strong> [ ' + params.url + '].' + '</div>';
706 $dialog.find('.modal-body').html(msg);
712 function buildFooter() {
713 if (opts.buttons === false) {
716 var oFoot = jQuery('<div>').addClass('modal-footer').prop('id', 'oefooter');
718 for (var i = 0, k = opts.buttons.length; i < k; i++) {
719 var btnOp = opts.buttons[i];
720 if (typeof btnOp.class !== 'undefined') {
721 btnOp.class = btnOp.class.replace(/default/gi, 'secondary');
722 var btn = jQuery('<button>').addClass('btn ' + (btnOp.class || 'btn-primary'));
724 btnOp.style = btnOp.style.replace(/default/gi, 'secondary');
725 var btn = jQuery('<button>').addClass('btn btn-' + (btnOp.style || 'primary'));
728 for (var index in btnOp) {
729 if (btnOp.hasOwnProperty(index)) {
734 btn.attr('data-dismiss', 'modal');
738 //binds button to click event of fn defined in calling document/form
739 var fn = btnOp.click.bind(dlgContainer.find('.modal-content'));
743 btn.html(btnOp[index]);
748 //all other possible HTML attributes to button element
750 btn.attr(index, btnOp[index]);
758 return oFoot; // jquery object of modal footer.
761 // dynamic sizing - special case for full height
762 function sizing(e, height) {
764 if (opts.sizeHeight === 'auto') {
765 dlgContainer.find('div.modal-body').css({'overflow-y': 'auto'});
766 // let BS determine height for alerts etc
769 let $idoc = jQuery(e.currentTarget);
770 viewPortHt = Math.max(window.document.documentElement.clientHeight, window.innerHeight || 0);
771 let frameContentHt = opts.sizeHeight === 'full' ? viewPortHt : height;
772 frameContentHt = frameContentHt >= viewPortHt ? viewPortHt : frameContentHt;
773 size = (frameContentHt / viewPortHt * 100).toFixed(2);
775 dlgContainer.find('div.modal-content').css({'height': size});
776 if (opts.type === 'iframe') {
777 dlgContainer.find('div.modal-body').css({'overflow-y': 'hidden'});
779 dlgContainer.find('div.modal-body').css({'overflow-y': 'auto'});
786 // sizing for modals with iframes
787 function SizeModaliFrame(e, minSize) {
789 let idoc = e.currentTarget.contentDocument ? e.currentTarget.contentDocument : e.currentTarget.contentWindow.document;
790 jQuery(e.currentTarget).parents('div.modal-content').css({'height': 0});
791 viewPortHt = where.window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
792 let frameContentHt = Math.max(jQuery(idoc).height(), idoc.body.offsetHeight) + 40;
793 frameContentHt = frameContentHt < minSize ? minSize : frameContentHt;
794 frameContentHt = frameContentHt >= viewPortHt ? viewPortHt : frameContentHt;
795 size = (frameContentHt / viewPortHt * 100).toFixed(1);
796 size = size + 'vh'; // will start the dialog as responsive. Any resize by user turns dialog to absolute positioning.
797 jQuery(e.currentTarget).parents('div.modal-content').css({'height': size});