├── test.html
├── style.css
└── main.js
/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Multiple windows view
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
Drag the resizers to change width and height of the windows.
15 |
😊😉
16 |
17 |
18 |
19 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |

34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | html,
2 | body {
3 | width: 100vw;
4 | height: 100vh;
5 | margin: 0;
6 | border: 0;
7 | padding: 0;
8 | -webkit-box-sizing: border-box;
9 | -moz-box-sizing: border-box;
10 | box-sizing: border-box;
11 | }
12 |
13 | *,
14 | *::before,
15 | *::after {
16 | -webkit-box-sizing: inherit;
17 | -moz-box-sizing: inherit;
18 | box-sizing: inherit;
19 | }
20 |
21 | #app {
22 | width: 100%;
23 | height: 100%;
24 |
25 | font-family: Arial, Helvetica, sans-serif;
26 | }
27 |
28 | .resizable-x,
29 | .resizable-y {
30 | display: flex;
31 | overflow: hidden;
32 | }
33 |
34 | .resizable-x {
35 | height: 100%;
36 | }
37 |
38 | .resizable-y {
39 | flex-direction: column;
40 | }
41 |
42 | .resizer-x,
43 | .resizer-y {
44 | position: relative;
45 | display: flex;
46 | justify-content: center;
47 | align-items: center;
48 | background: black;
49 | padding: 4px;
50 | }
51 |
52 | .resizer-x {
53 | z-index: 2;
54 | cursor: col-resize;
55 | }
56 | .resizer-x::before,
57 | .resizer-x::after {
58 | content: '';
59 | width: 1px;
60 | height: 16px;
61 | margin: 2px;
62 | background: lightgray;
63 | }
64 |
65 | .resizer-y {
66 | z-index: 1;
67 | cursor: row-resize;
68 | flex-direction: column;
69 | }
70 | .resizer-y::before,
71 | .resizer-y::after {
72 | content: '';
73 | width: 16px;
74 | height: 1px;
75 | margin: 2px;
76 | background: lightgray;
77 | }
78 |
79 | .img-container {
80 | overflow: hidden;
81 | height: 100%;
82 | width: 100%;
83 | display: flex;
84 | justify-content: center;
85 | align-items: center;
86 | }
87 | .img-container img {
88 | overflow: hidden;
89 | height: 100%;
90 | width: 100%;
91 | }
92 | .img-container iframe {
93 | overflow: hidden;
94 | height: 100%;
95 | width: 100%;
96 | /* z-index: -1; */
97 | }
98 |
--------------------------------------------------------------------------------
/main.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | // horizontal direction
3 | (function resizableX() {
4 | const resizers = document.querySelectorAll('.resizer-x');
5 | resizers.forEach((resizer) => {
6 | resizer.addEventListener('mousedown', onmousedown);
7 | resizer.addEventListener('touchstart', ontouchstart);
8 |
9 | // for mobile
10 | function ontouchstart(e) {
11 | e.preventDefault();
12 | document.querySelectorAll('iframe').forEach((item) => (item.style.zIndex = -1));
13 | resizer.addEventListener('touchmove', ontouchmove);
14 | resizer.addEventListener('touchend', ontouchend);
15 | }
16 | function ontouchmove(e) {
17 | e.preventDefault();
18 | const clientX = e.touches[0].clientX;
19 | const deltaX = clientX - (resizer._clientX || clientX);
20 | resizer._clientX = clientX;
21 | const l = resizer.previousElementSibling;
22 | const r = resizer.nextElementSibling;
23 | // LEFT
24 | if (deltaX < 0) {
25 | const w = Math.round(parseInt(getComputedStyle(l).width) + deltaX);
26 | l.style.flex = `0 ${w < 10 ? 0 : w}px`;
27 | r.style.flex = '1 0';
28 | }
29 | // RIGHT
30 | if (deltaX > 0) {
31 | const w = Math.round(parseInt(getComputedStyle(r).width) - deltaX);
32 | r.style.flex = `0 ${w < 10 ? 0 : w}px`;
33 | l.style.flex = '1 0';
34 | }
35 | }
36 | function ontouchend(e) {
37 | e.preventDefault();
38 | document.querySelectorAll('iframe').forEach((item) => (item.style.zIndex = 1));
39 | resizer.removeEventListener('touchmove', ontouchmove);
40 | resizer.removeEventListener('touchend', ontouchend);
41 | delete e._clientX;
42 | }
43 |
44 | // for desktop
45 | function onmousedown(e) {
46 | e.preventDefault();
47 | document.querySelectorAll('iframe').forEach((item) => (item.style.zIndex = -1));
48 | document.addEventListener('mousemove', onmousemove);
49 | document.addEventListener('mouseup', onmouseup);
50 | }
51 | function onmousemove(e) {
52 | e.preventDefault();
53 | const clientX = e.clientX;
54 | const deltaX = clientX - (resizer._clientX || clientX);
55 | resizer._clientX = clientX;
56 | const l = resizer.previousElementSibling;
57 | const r = resizer.nextElementSibling;
58 | // LEFT
59 | if (deltaX < 0) {
60 | const w = Math.round(parseInt(getComputedStyle(l).width) + deltaX);
61 | l.style.flex = `0 ${w < 10 ? 0 : w}px`;
62 | r.style.flex = '1 0';
63 | }
64 | // RIGHT
65 | if (deltaX > 0) {
66 | const w = Math.round(parseInt(getComputedStyle(r).width) - deltaX);
67 | r.style.flex = `0 ${w < 10 ? 0 : w}px`;
68 | l.style.flex = '1 0';
69 | }
70 | }
71 | function onmouseup(e) {
72 | e.preventDefault();
73 | document.querySelectorAll('iframe').forEach((item) => (item.style.zIndex = 1));
74 | document.removeEventListener('mousemove', onmousemove);
75 | document.removeEventListener('mouseup', onmouseup);
76 | delete e._clientX;
77 | }
78 | });
79 | })();
80 |
81 | // vertical direction
82 | (function resizableY() {
83 | const resizers = document.querySelectorAll('.resizer-y');
84 | resizers.forEach((resizer) => {
85 | resizer.addEventListener('mousedown', onmousedown);
86 | resizer.addEventListener('touchstart', ontouchstart);
87 |
88 | // for mobile
89 | function ontouchstart(e) {
90 | e.preventDefault();
91 | document.querySelectorAll('iframe').forEach((item) => (item.style.zIndex = -1));
92 | resizer.addEventListener('touchmove', ontouchmove);
93 | resizer.addEventListener('touchend', ontouchend);
94 | }
95 | function ontouchmove(e) {
96 | e.preventDefault();
97 | const clientY = e.touches[0].clientY;
98 | const deltaY = clientY - (resizer._clientY || clientY);
99 | resizer._clientY = clientY;
100 | const t = resizer.previousElementSibling;
101 | const b = resizer.nextElementSibling;
102 | // UP
103 | if (deltaY < 0) {
104 | const h = Math.round(parseInt(getComputedStyle(t).height) + deltaY);
105 | t.style.flex = `0 ${h < 10 ? 0 : h}px`;
106 | b.style.flex = '1 0';
107 | }
108 | // DOWN
109 | if (deltaY > 0) {
110 | const h = Math.round(parseInt(getComputedStyle(b).height) - deltaY);
111 | b.style.flex = `0 ${h < 10 ? 0 : h}px`;
112 | t.style.flex = '1 0';
113 | }
114 | }
115 | function ontouchend(e) {
116 | e.preventDefault();
117 | document.querySelectorAll('iframe').forEach((item) => (item.style.zIndex = 1));
118 | resizer.removeEventListener('touchmove', ontouchmove);
119 | resizer.removeEventListener('touchend', ontouchend);
120 | delete e._clientY;
121 | }
122 |
123 | // for desktop
124 | function onmousedown(e) {
125 | e.preventDefault();
126 | document.querySelectorAll('iframe').forEach((item) => (item.style.zIndex = -1));
127 | document.addEventListener('mousemove', onmousemove);
128 | document.addEventListener('mouseup', onmouseup);
129 | }
130 | function onmousemove(e) {
131 | e.preventDefault();
132 | const clientY = e.clientY;
133 | const deltaY = clientY - (resizer._clientY || clientY);
134 | resizer._clientY = clientY;
135 | const t = resizer.previousElementSibling;
136 | const b = resizer.nextElementSibling;
137 | // UP
138 | if (deltaY < 0) {
139 | const h = Math.round(parseInt(getComputedStyle(t).height) + deltaY);
140 | t.style.flex = `0 ${h < 10 ? 0 : h}px`;
141 | b.style.flex = '1 0';
142 | }
143 | // DOWN
144 | if (deltaY > 0) {
145 | const h = Math.round(parseInt(getComputedStyle(b).height) - deltaY);
146 | b.style.flex = `0 ${h < 10 ? 0 : h}px`;
147 | t.style.flex = '1 0';
148 | }
149 | }
150 | function onmouseup(e) {
151 | e.preventDefault();
152 | document.querySelectorAll('iframe').forEach((item) => (item.style.zIndex = 1));
153 | document.removeEventListener('mousemove', onmousemove);
154 | document.removeEventListener('mouseup', onmouseup);
155 | delete e._clientY;
156 | }
157 | });
158 | })();
159 | })();
160 |
--------------------------------------------------------------------------------