MikaFil commited on
Commit
47bb610
Β·
verified Β·
1 Parent(s): 96e6a0e

Create interface.js

Browse files
Files changed (1) hide show
  1. interface.js +213 -0
interface.js ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // fullscreen.js
2
+ (function () {
3
+ // ─── 1. Localiser la balise <script> ────────────────────────────────────────
4
+ const scriptTag = document.currentScript || (function () {
5
+ const all = document.getElementsByTagName('script');
6
+ for (let i = all.length - 1; i >= 0; i--) {
7
+ if (all[i].src && all[i].src.includes('fullscreen.js')) return all[i];
8
+ }
9
+ return all[all.length - 1];
10
+ })();
11
+
12
+ const playcanvasUrl = scriptTag.getAttribute('data-src');
13
+ if (!playcanvasUrl) return;
14
+
15
+ const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
16
+ const id = Math.random().toString(36).substr(2, 8);
17
+
18
+ // ─── 4. Calcul des ratios (Desktop & Mobile Portrait) ────────────────────────
19
+ function computeAspectPadding(aspectStr) {
20
+ if (!aspectStr) return null;
21
+ if (aspectStr.includes(':')) {
22
+ const [w, h] = aspectStr.split(':').map(Number);
23
+ return (w > 0 && h > 0) ? (h / w) * 100 + '%' : null;
24
+ }
25
+ const v = parseFloat(aspectStr);
26
+ return (v > 0) ? (100 / v) + '%' : null;
27
+ }
28
+
29
+ const desktopPadding = computeAspectPadding(scriptTag.getAttribute('data-aspect')) || '56.25%';
30
+ const mobilePadding = computeAspectPadding(scriptTag.getAttribute('data-aspect-mobile')) || desktopPadding;
31
+
32
+ // ─── 5. Injection du CSS avec Media Queries ──────────────────────────────────
33
+ const style = document.createElement('style');
34
+ style.textContent = `
35
+ .pc-embed-wrapper-${id} {
36
+ position: relative;
37
+ width: 100%;
38
+ height: 0;
39
+ overflow: hidden;
40
+ background: #000;
41
+ box-sizing: border-box;
42
+ /* Ratio par dΓ©faut (Paysage / Desktop) */
43
+ padding-bottom: ${desktopPadding};
44
+ }
45
+
46
+ /* Ratio Mobile Portrait : appliquΓ© uniquement si l'Γ©cran est plus haut que large */
47
+ @media (orientation: portrait) and (max-width: 768px) {
48
+ .pc-embed-wrapper-${id} {
49
+ padding-bottom: ${mobilePadding};
50
+ }
51
+ }
52
+
53
+ .pc-embed-wrapper-${id}.fake-fullscreen {
54
+ position: fixed !important;
55
+ top: 0 !important;
56
+ left: 0 !important;
57
+ width: 100vw !important;
58
+ height: 100vh !important;
59
+ height: 100dvh !important;
60
+ max-width: 100vw !important;
61
+ max-height: 100dvh !important;
62
+ padding-bottom: 0 !important;
63
+ margin: 0 !important;
64
+ z-index: 99999;
65
+ }
66
+ .pc-embed-inner-${id} {
67
+ position: absolute;
68
+ top: 0; left: 0;
69
+ width: 100%; height: 100%;
70
+ }
71
+ .pc-embed-inner-${id} iframe {
72
+ width: 100%; height: 100%;
73
+ border: none;
74
+ display: block;
75
+ }
76
+ .pc-fs-btn-${id} {
77
+ position: absolute;
78
+ top: 10px;
79
+ right: 10px;
80
+ z-index: 10;
81
+ width: 36px;
82
+ height: 36px;
83
+ border-radius: 50%;
84
+ border: none;
85
+ background: #2E2E2EB3;
86
+ color: #fff;
87
+ font-size: 18px;
88
+ line-height: 36px;
89
+ text-align: center;
90
+ cursor: pointer;
91
+ user-select: none;
92
+ }
93
+ `;
94
+ document.head.appendChild(style);
95
+
96
+ // ─── 6. Construction du DOM ──────────────────────────────────────────────────
97
+ const wrapper = document.createElement('div');
98
+ wrapper.className = `pc-embed-wrapper-${id}`;
99
+
100
+ const inner = document.createElement('div');
101
+ inner.className = `pc-embed-inner-${id}`;
102
+
103
+ const iframe = document.createElement('iframe');
104
+ const urlObj = new URL(playcanvasUrl);
105
+ urlObj.searchParams.set('overlay', 'false');
106
+ iframe.src = urlObj.href;
107
+ iframe.setAttribute('allowfullscreen', '');
108
+ iframe.setAttribute('allow', 'autoplay; fullscreen');
109
+ iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-pointer-lock allow-popups allow-forms');
110
+
111
+ const fsBtn = document.createElement('button');
112
+ fsBtn.className = `pc-fs-btn-${id}`;
113
+ fsBtn.textContent = '⇱';
114
+
115
+ inner.appendChild(iframe);
116
+ wrapper.appendChild(inner);
117
+ wrapper.appendChild(fsBtn);
118
+ scriptTag.parentNode.insertBefore(wrapper, scriptTag.nextSibling);
119
+
120
+ // ─── 7. Γ‰tat & Helper ────────────────────────────────────────────────────────
121
+ let isFullscreen = false;
122
+ let savedParent = null;
123
+ let savedNextSibling = null;
124
+
125
+ function getHeightUnit() {
126
+ return (CSS && CSS.supports && CSS.supports('height', '100dvh')) ? '100dvh' : '100vh';
127
+ }
128
+
129
+ // ─── 8. Styles Plein Γ‰cran ───────────────────────────────────────────────────
130
+ function applyFullscreenStyles() {
131
+ const h = isIOS ? getHeightUnit() : '100vh';
132
+ wrapper.style.position = 'fixed';
133
+ wrapper.style.top = '0';
134
+ wrapper.style.left = '0';
135
+ wrapper.style.width = '100vw';
136
+ wrapper.style.height = h;
137
+ wrapper.style.maxHeight = h;
138
+ wrapper.style.paddingBottom = '0';
139
+ wrapper.style.margin = '0';
140
+ wrapper.style.zIndex = '99999';
141
+ wrapper.classList.add('fake-fullscreen');
142
+ fsBtn.textContent = '⇲';
143
+ isFullscreen = true;
144
+ }
145
+
146
+ function applyFakeFullscreenStyles() {
147
+ savedParent = wrapper.parentNode;
148
+ savedNextSibling = wrapper.nextSibling;
149
+ document.body.appendChild(wrapper);
150
+ applyFullscreenStyles();
151
+ }
152
+
153
+ function restoreStyles() {
154
+ wrapper.style.cssText = '';
155
+ // Le CSS via les Media Queries reprendra le dessus automatiquement ici
156
+ wrapper.classList.remove('fake-fullscreen');
157
+ fsBtn.textContent = '⇱';
158
+ isFullscreen = false;
159
+
160
+ if (savedParent) {
161
+ savedParent.insertBefore(wrapper, savedNextSibling);
162
+ savedParent = null;
163
+ savedNextSibling = null;
164
+ }
165
+ }
166
+
167
+ // ─── 9. Gestionnaires d'Γ©vΓ©nements ───────────────────────────────────────────
168
+ function enterFullscreen() {
169
+ if (isIOS) {
170
+ applyFakeFullscreenStyles();
171
+ document.body.style.overflow = 'hidden';
172
+ } else {
173
+ const el = wrapper;
174
+ const req = el.requestFullscreen || el.webkitRequestFullscreen || el.mozRequestFullScreen || el.msRequestFullscreen;
175
+ if (req) {
176
+ req.call(el).catch(() => {
177
+ applyFakeFullscreenStyles();
178
+ document.body.style.overflow = 'hidden';
179
+ });
180
+ } else {
181
+ applyFakeFullscreenStyles();
182
+ document.body.style.overflow = 'hidden';
183
+ }
184
+ }
185
+ }
186
+
187
+ function exitFullscreen() {
188
+ if (document.fullscreenElement || document.webkitFullscreenElement) {
189
+ (document.exitFullscreen || document.webkitExitFullscreen || function(){}).call(document);
190
+ }
191
+ restoreStyles();
192
+ document.body.style.overflow = '';
193
+ }
194
+
195
+ fsBtn.addEventListener('click', (e) => {
196
+ e.stopPropagation();
197
+ isFullscreen ? exitFullscreen() : enterFullscreen();
198
+ });
199
+
200
+ document.addEventListener('fullscreenchange', () => {
201
+ const fsEl = document.fullscreenElement || document.webkitFullscreenElement;
202
+ if (!fsEl && isFullscreen) exitFullscreen();
203
+ else if (fsEl === wrapper && !isFullscreen) applyFullscreenStyles();
204
+ });
205
+
206
+ window.addEventListener('resize', () => {
207
+ if (isFullscreen) {
208
+ const h = isIOS ? getHeightUnit() : '100vh';
209
+ wrapper.style.height = h;
210
+ wrapper.style.maxHeight = h;
211
+ }
212
+ });
213
+ })();