|
115 | 115 | </div> |
116 | 116 | </div> |
117 | 117 | <script> |
118 | | - const container = document.getElementById('container'); |
119 | | - const toggle = document.getElementById('toggle'); |
120 | | - const iframe = document.getElementById('preview'); |
121 | | - const iframeDoc = iframe.contentDocument || iframe.contentWindow.document; |
| 118 | +const container = document.getElementById('container'); |
| 119 | +const toggle = document.getElementById('toggle'); |
| 120 | +const iframe = document.getElementById('preview'); |
| 121 | + |
| 122 | +function compressAndBase64Encode(str) { |
| 123 | + return btoa(String.fromCharCode.apply(null, pako.deflate(str))).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); |
| 124 | +} |
| 125 | + |
| 126 | +function base64DecodeAndDecompress(base64EncodedData) { |
| 127 | + const adjustedData = base64EncodedData.replace(/-/g, '+').replace(/_/g, '/'); |
| 128 | + const decodedData = atob(adjustedData); |
| 129 | + const charData = decodedData.split('').map(c => c.charCodeAt(0)); |
| 130 | + const binData = new Uint8Array(charData); |
| 131 | + return pako.inflate(binData, { to: 'string' }); |
| 132 | +} |
| 133 | + |
| 134 | +function updateURL() { |
| 135 | + console.log('url updated'); |
| 136 | + const html = compressAndBase64Encode(document.getElementById('htmlCode').value); |
| 137 | + const css = compressAndBase64Encode(document.getElementById('cssCode').value); |
| 138 | + const js = compressAndBase64Encode(document.getElementById('jsCode').value); |
| 139 | + history.replaceState(null, '', `?html=${html}&css=${css}&js=${js}`); |
| 140 | + updatePreview(); |
| 141 | +} |
| 142 | + |
| 143 | +function updatePreview() { |
| 144 | + const html = document.getElementById('htmlCode').value; |
| 145 | + const css = document.getElementById('cssCode').value; |
| 146 | + const js = document.getElementById('jsCode').value; |
122 | 147 |
|
123 | | - function compressAndBase64Encode(str) { |
124 | | - return btoa(String.fromCharCode.apply(null, pako.deflate(str))).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); |
125 | | - } |
126 | | - |
127 | | - function base64DecodeAndDecompress(base64EncodedData) { |
128 | | - const adjustedData = base64EncodedData.replace(/-/g, '+').replace(/_/g, '/'); |
129 | | - const decodedData = atob(adjustedData); |
130 | | - const charData = decodedData.split('').map(c => c.charCodeAt(0)); |
131 | | - const binData = new Uint8Array(charData); |
132 | | - return pako.inflate(binData, { to: 'string' }); |
133 | | - } |
| 148 | + // Create a new iframe to avoid variable redeclaration issues |
| 149 | + const oldIframe = document.getElementById('preview'); |
| 150 | + const newIframe = document.createElement('iframe'); |
| 151 | + newIframe.id = 'preview'; |
| 152 | + newIframe.style = 'width: 100%; height: 100%; border: none; flex: 1 1 0%;'; |
| 153 | + oldIframe.parentNode.replaceChild(newIframe, oldIframe); |
134 | 154 |
|
135 | | - function updateURL() { |
136 | | - console.log('url updated'); |
137 | | - const html = compressAndBase64Encode(document.getElementById('htmlCode').value); |
138 | | - const css = compressAndBase64Encode(document.getElementById('cssCode').value); |
139 | | - const js = compressAndBase64Encode(document.getElementById('jsCode').value); |
140 | | - history.replaceState(null, '', `?html=${html}&css=${css}&js=${js}`); |
141 | | - decompressAndInject(); |
142 | | - } |
| 155 | + // Get the new iframe's document |
| 156 | + const iframeDoc = newIframe.contentDocument || newIframe.contentWindow.document; |
143 | 157 |
|
144 | | - function decompressAndInject() { |
145 | | - let urlParams = new URLSearchParams(window.location.search); |
146 | | - let html = urlParams.get('html') ? sanitizeEncodedValue(urlParams.get('html')) : ''; |
147 | | - let css = urlParams.get('css') ? sanitizeEncodedValue(urlParams.get('css')) : ''; |
148 | | - let js = urlParams.get('js') ? sanitizeEncodedValue(urlParams.get('js')) : ''; |
| 158 | + // Write content to the new iframe |
| 159 | + iframeDoc.open(); |
| 160 | + iframeDoc.write(` |
| 161 | + <!DOCTYPE html> |
| 162 | + <html> |
| 163 | + <head> |
| 164 | + <style>${css}</style> |
| 165 | + </head> |
| 166 | + <body>${html} |
| 167 | + <script>${js}<\/script> |
| 168 | + <script> |
| 169 | + (function() { |
| 170 | + function handleInputChange(e) { |
| 171 | + if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.tagName === 'SELECT') { |
| 172 | + window.parent.postMessage({ |
| 173 | + type: 'inputChanged', |
| 174 | + html: document.body.innerHTML |
| 175 | + }, '*'); |
| 176 | + } |
| 177 | + } |
| 178 | + |
| 179 | + document.addEventListener('input', handleInputChange); |
| 180 | + document.addEventListener('change', handleInputChange); |
| 181 | + })(); |
| 182 | + <\/script> |
| 183 | + </body> |
| 184 | + </html> |
| 185 | + `); |
| 186 | + iframeDoc.close(); |
| 187 | +} |
| 188 | + |
| 189 | +function sanitizeEncodedValue(encodedValue) { |
| 190 | + return encodedValue.replace(/[\s'"]+$/g, ''); |
| 191 | +} |
| 192 | + |
| 193 | +function loadFromURL() { |
| 194 | + let urlParams = new URLSearchParams(window.location.search); |
| 195 | + let html = urlParams.get('html') ? sanitizeEncodedValue(urlParams.get('html')) : ''; |
| 196 | + let css = urlParams.get('css') ? sanitizeEncodedValue(urlParams.get('css')) : ''; |
| 197 | + let js = urlParams.get('js') ? sanitizeEncodedValue(urlParams.get('js')) : ''; |
| 198 | + |
| 199 | + html = html ? base64DecodeAndDecompress(html) : ''; |
| 200 | + css = css ? base64DecodeAndDecompress(css) : ''; |
| 201 | + js = js ? base64DecodeAndDecompress(js) : ''; |
| 202 | + |
| 203 | + if (html) document.getElementById('htmlCode').value = html; |
| 204 | + if (css) document.getElementById('cssCode').value = css; |
| 205 | + if (js) document.getElementById('jsCode').value = js; |
149 | 206 |
|
150 | | - html = html ? base64DecodeAndDecompress(html) : ''; |
151 | | - css = css ? base64DecodeAndDecompress(css) : ''; |
152 | | - js = js ? base64DecodeAndDecompress(js) : ''; |
153 | | - |
154 | | - if (html) document.getElementById('htmlCode').value = html; |
155 | | - if (css) document.getElementById('cssCode').value = css; |
156 | | - if (js) document.getElementById('jsCode').value = js; |
157 | | - |
158 | | - iframeDoc.open(); |
159 | | - iframeDoc.write(` |
160 | | - <html> |
161 | | - <head> |
162 | | - <style>${css}</style> |
163 | | - </head> |
164 | | - <body>${html}<script>${js}<\/script> |
165 | | - <script> |
166 | | - document.addEventListener('input', function(e) { |
167 | | - if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.tagName === 'SELECT') { |
168 | | - window.parent.postMessage({ |
169 | | - type: 'inputChanged', |
170 | | - html: document.body.innerHTML |
171 | | - }, '*'); |
172 | | - } |
173 | | - }); |
174 | | - document.addEventListener('change', function(e) { |
175 | | - if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.tagName === 'SELECT') { |
176 | | - window.parent.postMessage({ |
177 | | - type: 'inputChanged', |
178 | | - html: document.body.innerHTML |
179 | | - }, '*'); |
180 | | - } |
181 | | - }); |
182 | | - <\/script> |
183 | | - </body> |
184 | | - </html> |
185 | | - `); |
186 | | - iframeDoc.close(); |
| 207 | + updatePreview(); |
| 208 | +} |
| 209 | + |
| 210 | +document.getElementById('htmlCode').addEventListener('input', updateURL); |
| 211 | +document.getElementById('cssCode').addEventListener('input', updateURL); |
| 212 | +document.getElementById('jsCode').addEventListener('input', updateURL); |
| 213 | + |
| 214 | +window.addEventListener('message', function(event) { |
| 215 | + if (event.data && event.data.type === 'inputChanged') { |
| 216 | + document.getElementById('htmlCode').value = event.data.html; |
| 217 | + updateURL(); |
187 | 218 | } |
188 | | - |
189 | | - function sanitizeEncodedValue(encodedValue) { |
190 | | - return encodedValue.replace(/[\s'"]+$/g, ''); |
| 219 | +}); |
| 220 | + |
| 221 | +loadFromURL(); |
| 222 | + |
| 223 | +toggle.addEventListener('click', () => { |
| 224 | + const codeEditor = document.getElementById('codeEditor'); |
| 225 | + const preview = document.getElementById('preview'); |
| 226 | + if (codeEditor.style.display === 'none' || !codeEditor.style.display) { |
| 227 | + codeEditor.style.display = 'flex'; |
| 228 | + preview.style.flex = '1'; |
| 229 | + container.classList.remove('collapsed'); |
| 230 | + } else { |
| 231 | + codeEditor.style.display = 'none'; |
| 232 | + preview.style.flex = '0 0 100%'; |
| 233 | + container.classList.add('collapsed'); |
191 | 234 | } |
192 | | - |
193 | | - document.getElementById('htmlCode').addEventListener('input', updateURL); |
194 | | - document.getElementById('cssCode').addEventListener('input', updateURL); |
195 | | - document.getElementById('jsCode').addEventListener('input', updateURL); |
196 | | - |
197 | | - window.addEventListener('message', function(event) { |
198 | | - if (event.data && event.data.type === 'inputChanged') { |
199 | | - document.getElementById('htmlCode').value = event.data.html; |
200 | | - updateURL(); |
201 | | - } |
202 | | - }); |
203 | | - |
204 | | - decompressAndInject(); |
205 | | - |
206 | | - toggle.addEventListener('click', () => { |
207 | | - const codeEditor = document.getElementById('codeEditor'); |
208 | | - const preview = document.getElementById('preview'); |
209 | | - if (codeEditor.style.display === 'none' || !codeEditor.style.display) { |
210 | | - codeEditor.style.display = 'flex'; |
211 | | - preview.style.flex = '1'; |
212 | | - container.classList.remove('collapsed'); |
213 | | - } else { |
214 | | - codeEditor.style.display = 'none'; |
215 | | - preview.style.flex = '0 0 100%'; |
216 | | - container.classList.add('collapsed'); |
217 | | - } |
218 | | - }); |
| 235 | +}); |
219 | 236 | </script> |
220 | 237 | <script src="../logo.js"></script> |
221 | 238 | </body> |
|
0 commit comments