Hi @Yuliya, here is a javascript script allowing you to open a popup from a button click:
if (typeof modal === 'undefined') {
var modal = null;
}
if (typeof modalDiv === 'undefined') {
var modalDiv = null;
}
if (typeof jSuites === 'undefined') {
var jSuites = {};
}
jSuites.loading = (function() {
var obj = {};
var loading = null;
obj.show = function(timeout) {
if (! loading) {
loading = document.createElement('div');
loading.className = 'jloading';
}
document.body.appendChild(loading);
// Max timeout in seconds
if (timeout > 0) {
setTimeout(function() {
obj.hide();
}, timeout * 1000)
}
}
obj.hide = function() {
if (loading && loading.parentNode) {
document.body.removeChild(loading);
}
}
return obj;
})();
jSuites.modal = (function(el, options) {
var obj = {};
obj.options = {};
// Default configuration
var defaults = {
url: null,
onopen: null,
onclose: null,
onload: null,
closed: false,
width: null,
height: null,
maxWidth: null,
maxHeight: null,
title: null,
padding: null,
backdrop: true,
icon: null,
};
// Loop through our object
for (var property in defaults) {
if (options && options.hasOwnProperty(property)) {
obj.options[property] = options[property];
} else {
obj.options[property] = defaults[property];
}
}
// Title
if (! obj.options.title && el.getAttribute('title')) {
obj.options.title = el.getAttribute('title');
}
var temp = document.createElement('div');
while (el.children[0]) {
temp.appendChild(el.children[0]);
}
obj.title = document.createElement('div');
obj.title.className = 'jmodal_title';
if (obj.options.icon) {
obj.title.setAttribute('data-icon', obj.options.icon);
}
obj.content = document.createElement('div');
obj.content.className = 'jmodal_content';
obj.content.innerHTML = el.innerHTML;
while (temp.children[0]) {
obj.content.appendChild(temp.children[0]);
}
obj.container = document.createElement('div');
obj.container.className = 'jmodal';
obj.container.appendChild(obj.title);
obj.container.appendChild(obj.content);
if (obj.options.padding) {
obj.content.style.padding = obj.options.padding;
}
if (obj.options.width) {
obj.container.style.width = obj.options.width;
}
if (obj.options.height) {
obj.container.style.height = obj.options.height;
}
if (obj.options.maxWidth) {
obj.container.style.maxWidth = obj.options.maxWidth;
}
if (obj.options.maxHeight) {
obj.container.style.maxHeight = obj.options.maxHeight;
}
if (obj.options.title) {
var title = document.createElement('h4');
title.innerText = obj.options.title;
obj.title.appendChild(title);
}
el.innerHTML = '';
el.style.display = 'none';
el.appendChild(obj.container);
// Backdrop
if (obj.options.backdrop) {
var backdrop = document.createElement('div');
backdrop.className = 'jmodal_backdrop';
backdrop.onclick = function () {
obj.close();
}
el.appendChild(backdrop);
}
obj.open = function() {
el.style.display = 'block';
// Fullscreen
var rect = obj.container.getBoundingClientRect();
if (jSuites.getWindowWidth() < rect.width) {
obj.container.style.top = '';
obj.container.style.left = '';
obj.container.classList.add('jmodal_fullscreen');
jSuites.animation.slideBottom(obj.container, 1);
} else {
if (obj.options.backdrop) {
backdrop.style.display = 'block';
}
}
// Event
if (typeof(obj.options.onopen) == 'function') {
obj.options.onopen(el, obj);
}
}
obj.resetPosition = function() {
obj.container.style.top = '';
obj.container.style.left = '';
}
obj.isOpen = function() {
return el.style.display != 'none' ? true : false;
}
obj.close = function() {
if (obj.isOpen()) {
el.style.display = 'none';
if (obj.options.backdrop) {
// Backdrop
backdrop.style.display = '';
}
// Remove fullscreen class
obj.container.classList.remove('jmodal_fullscreen');
// Event
if (typeof(obj.options.onclose) == 'function') {
obj.options.onclose(el, obj);
}
}
}
if (! jSuites.modal.hasEvents) {
// Position
var tracker = null;
document.addEventListener('keydown', function(e) {
if (e.which == 27) {
var modals = document.querySelectorAll('.jmodal');
for (var i = 0; i < modals.length; i++) {
modals[i].parentNode.modal.close();
}
}
});
document.addEventListener('mouseup', function(e) {
var item = jSuites.findElement(e.target, 'jmodal');
if (item) {
// Get target info
var rect = item.getBoundingClientRect();
if (e.changedTouches && e.changedTouches[0]) {
var x = e.changedTouches[0].clientX;
var y = e.changedTouches[0].clientY;
} else {
var x = e.clientX;
var y = e.clientY;
}
if (rect.width - (x - rect.left) < 50 && (y - rect.top) < 50) {
item.parentNode.modal.close();
}
}
if (tracker) {
tracker.element.style.cursor = 'auto';
tracker = null;
}
});
document.addEventListener('mousedown', function(e) {
var item = jSuites.findElement(e.target, 'jmodal');
if (item) {
// Get target info
var rect = item.getBoundingClientRect();
if (e.changedTouches && e.changedTouches[0]) {
var x = e.changedTouches[0].clientX;
var y = e.changedTouches[0].clientY;
} else {
var x = e.clientX;
var y = e.clientY;
}
if (rect.width - (x - rect.left) < 50 && (y - rect.top) < 50) {
// Do nothing
} else {
if (y - rect.top < 50) {
if (document.selection) {
document.selection.empty();
} else if ( window.getSelection ) {
window.getSelection().removeAllRanges();
}
tracker = {
left: rect.left,
top: rect.top,
x: e.clientX,
y: e.clientY,
width: rect.width,
height: rect.height,
element: item,
}
}
}
}
});
document.addEventListener('mousemove', function(e) {
if (tracker) {
e = e || window.event;
if (e.buttons) {
var mouseButton = e.buttons;
} else if (e.button) {
var mouseButton = e.button;
} else {
var mouseButton = e.which;
}
if (mouseButton) {
tracker.element.style.top = (tracker.top + (e.clientY - tracker.y) + (tracker.height / 2)) + 'px';
tracker.element.style.left = (tracker.left + (e.clientX - tracker.x) + (tracker.width / 2)) + 'px';
tracker.element.style.cursor = 'move';
} else {
tracker.element.style.cursor = 'auto';
}
}
});
jSuites.modal.hasEvents = true;
}
if (obj.options.url) {
jSuites.ajax({
url: obj.options.url,
method: 'GET',
dataType: 'text/html',
success: function(data) {
obj.content.innerHTML = data;
if (! obj.options.closed) {
obj.open();
}
if (typeof(obj.options.onload) === 'function') {
obj.options.onload(obj);
}
}
});
} else {
if (! obj.options.closed) {
obj.open();
}
if (typeof(obj.options.onload) === 'function') {
obj.options.onload(obj);
}
}
// Keep object available from the node
el.modal = obj;
return obj;
});
jSuites.findElement = function(element, condition) {
var foundElement = false;
function path (element) {
if (element && ! foundElement) {
if (typeof(condition) == 'function') {
foundElement = condition(element)
} else if (typeof(condition) == 'string') {
if (element.classList && element.classList.contains(condition)) {
foundElement = element;
}
}
}
if (element.parentNode && ! foundElement) {
path(element.parentNode);
}
}
path(element);
return foundElement;
}
jSuites.getWindowWidth = function() {
var w = window,
d = document,
e = d.documentElement,
g = d.getElementsByTagName('body')[0],
x = w.innerWidth || e.clientWidth || g.clientWidth;
return x;
}
var styles = `
.jmodal .jcolor-content {
position: fixed;
}
.jmodal {
position:fixed;
top:50%;
left:50%;
width:60%;
height:60%;
-webkit-box-shadow: 0 2px 12px rgba(0,0,0,.2);
-moz-box-shadow: 0 2px 12px rgba(0,0,0,.2);
border:1px solid #ccc;
background-color:#fff;
transform: translate(-50%, -50%);
box-sizing: border-box;
z-index:9002;
border-radius: 4px;
display: flex;
flex-direction: column;
}
.jmodal_title {
padding: 20px;
height: 70px;
box-sizing: border-box;
font-size: 1.4em;
background-color: #fff;
border-radius: 8px 8px 0px 0px;
pointer-events: none;
display: flex;
-webkit-align-items: center;
-webkit-box-align: center;
align-items: center;
border-bottom: 1px solid #eee;
}
.jmodal_title > div {
font-size: 1.4em;
}
.jmodal_title[data-icon]:before {
content: attr(data-icon);
font-family: 'Material Icons' !important;
width: 24px;
height: 24px;
font-size: 24px;
margin-right: 10px;
line-height: 24px;
}
.jmodal_content {
padding: 20px;
overflow-y: auto;
height: 100%;
box-sizing: border-box;
scrollbar-width: thin;
scrollbar-color: #333 transparent;
}
.jmodal_title:empty {
display: none;
}
.jmodal_title:empty + .jmodal_content {
height: 100%;
}
.jmodal_content::-webkit-scrollbar {
height: 12px;
}
.jmodal_content::-webkit-scrollbar {
width: 12px;
}
.jmodal_content::-webkit-scrollbar-track {
border: 1px solid #fff;
background: #eee;
}
.jmodal_content::-webkit-scrollbar-thumb {
border: 1px solid #fff;
background: #888;
}
.jmodal:after {
content: '';
background-image: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2724%27 height=%2724%27 viewBox=%270 0 24 24%27%3E%3Cpath d=%27M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z%27/%3E%3Cpath d=%27M0 0h24v24H0z%27 fill=%27none%27/%3E%3C/svg%3E");
position: absolute;
top: 0;
right: 0;
margin: 25px;
font-size: 24px;
width: 24px;
height: 24px;
cursor: pointer;
text-shadow: 0px 0px 5px #fff;
}
.jmodal_fullscreen {
width: 100% !important;
height: 100% !important;
top: 0px;
left: 0px;
transform: none;
border: 0px;
border-radius: 0px;
}
.jmodal_backdrop {
position: fixed;
top: 0px;
left: 0px;
min-width: 100%;
min-height: 100%;
background-color: rgba(0,0,0,0.2);
border: 0px;
padding: 0px;
z-index: 8000;
display: none;
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none; /* Non-prefixed version, currently
supported by Chrome and Opera */
}
.jmodal_content .jcalendar .jcalendar-content,
.jmodal_content .jdropdown-container {
position: fixed;
}
`
if(document.getElementById('myCSS')==null){
var styleSheet = document.createElement("style")
styleSheet.id = 'myCSS';
styleSheet.textContent = styles;
document.head.appendChild(styleSheet);
}
modalDiv = document.getElementById('basic-modal');
if (modalDiv==null) {
modalDiv = document.createElement("div");
modalDiv.id = "basic-modal";
}
modalDiv.innerHTML="";
const node = document.createTextNode("This is new.");
modalDiv.appendChild(node);
const element = document.getElementById('tables');
element.appendChild(modalDiv);
modal = jSuites.modal(document.getElementById('basic-modal'), {
closed: true,
width: 600,
height: 480
});
modal.open();
It is based on the great Jsuites library and its modal component. I embedded all the JS code needed and the CSS style in the script, which is definitely NOT the cleanest way, but at least it’s working!
Unfortunately I don’t have time to test it farther for now (you’ll see that it just opens a popup containing the “This is new.” TextNode defined on l.494 of the script), but I had two ideas for your needs from that starting point:
- Defining in the script a custom HTML display using
base.context.currentRow
to display the values of the current row (the one that triggered the modal opening).
- Create a universal app with one single ‘Single record’ page and format it as you want (don’t forget to hide tool bar to ensure it won’t be possible to navigate through records) . Allow anonymous access to this app and embed it in an iframe in the modal: your universal app page URL should look something like
https://MYSERVER/apps/custom/CUSTOMAPPURL/?page_id=PAGEID&record_id=RECORDID
so you can make this URL dynamic in the script to embed the current record with something like src="https://MYSERVER/apps/custom/CUSTOMAPPURL/?page_id=PAGEID&record_id="+base.context.currentRow._id
(Please note that I DIDN’T TEST the embedding in an iframe, so I’m not sure it will actually work).
Hope this could help you…
Bests,
Benjamin
I love spending time gathering information and explaining solutions to help you solve your problems. I spend… quite a bit of time on it
.If you feel grateful for the help I’ve given you, please don’t hesitate to support me. I am also available for paid services (scripts, database architecture, custom development, etc.).