/
WebAppWindowInlineDialog.js
146 lines (133 loc) · 4.04 KB
/
WebAppWindowInlineDialog.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*!
* Copyright (c) 2022 Digital Bazaar, Inc. All rights reserved.
*/
import {WebAppWindowDialog} from './WebAppWindowDialog.js';
export class WebAppWindowInlineDialog extends WebAppWindowDialog {
constructor({url, handle, className}) {
super();
this.url = url;
this.handle = handle;
// create a top-level dialog overlay
this.dialog = document.createElement('dialog');
applyStyle(this.dialog, {
position: 'fixed',
top: 0,
left: 0,
width: '100%',
height: '100%',
'max-width': '100%',
'max-height': '100%',
display: 'none',
margin: 0,
padding: 0,
border: 'none',
background: 'transparent',
color: 'black',
'box-sizing': 'border-box',
overflow: 'hidden',
// prevent focus bug in chrome
'user-select': 'none',
'z-index': 1000000
});
this.dialog.className = 'web-app-window';
if(typeof className === 'string') {
this.dialog.className = this.dialog.className + ' ' + className;
}
// ensure backdrop is transparent by default
const style = document.createElement('style');
style.appendChild(
document.createTextNode(`dialog.web-app-window::backdrop {
background-color: transparent;
}`));
// create flex container for iframe
this.container = document.createElement('div');
applyStyle(this.container, {
position: 'relative',
width: '100%',
height: '100%',
margin: 0,
padding: 0,
display: 'flex',
'flex-direction': 'column'
});
this.container.className = 'web-app-window-backdrop';
// create iframe
this.iframe = document.createElement('iframe');
this.iframe.src = url;
this.iframe.scrolling = 'auto';
applyStyle(this.iframe, {
position: 'fixed',
top: 0,
left: 0,
width: '100%',
height: '100%',
border: 'none',
background: 'transparent',
overflow: 'hidden',
margin: 0,
padding: 0,
'flex-grow': 1,
// prevent focus bug in chrome
'user-select': 'none'
});
// assemble dialog
this.dialog.appendChild(style);
this.container.appendChild(this.iframe);
this.dialog.appendChild(this.container);
// a.document.appendChild(this.iframe);
// handle cancel (user pressed escape)
this.dialog.addEventListener('cancel', e => {
e.preventDefault();
this.hide();
});
// attach to DOM
document.body.appendChild(this.dialog);
this.handle = this.iframe.contentWindow;
}
show() {
this.dialog.style.display = 'block';
if(this.dialog.showModal) {
this.dialog.showModal();
}
/* Note: Hack to solve chromium bug that sometimes (race condition) causes
mouse events to go to the underlying page instead of the iframe. This bug
generally manifests by showing a very quick flash of unstyled content /
background followed by a "not-allowed" mouse cursor over the page and over
the dialog and iframe, preventing interaction with the page until
the user right-clicks or causes some other render event in the page (a
render event inside the iframe does not seem to help resolve the bug).
Could be related to bug: tinyurl.com/2p9c66z9
Or could be related to the "Paint Holding" chromium feature.
We have found experimentally, that resetting accepting pointer events on
the dialog and allowing enough frames for rendering (16 ms is insufficient
but 32 ms seems to work), the bug resolves. */
try {
this.dialog.style.pointerEvents = 'none';
} catch(e) {}
setTimeout(() => {
try {
this.dialog.style.pointerEvents = '';
} catch(e) {}
}, 32);
}
close() {
this.dialog.style.display = 'none';
if(this.dialog.close) {
try {
this.dialog.close();
} catch(e) {
console.error(e);
}
}
super.close();
}
destroy() {
this.dialog.parentNode.removeChild(this.dialog);
super.destroy();
}
}
function applyStyle(element, style) {
for(const name in style) {
element.style[name] = style[name];
}
}