initial commit

Hunter
Monday, July 7th, 2025 at 2:39 PM

index.htmlnew

index.html
  1 +<!DOCTYPE html>
  2 +<html lang="en">
  3 +<head>
  4 +    <meta charset="UTF-8">
  5 +    <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6 +    <title>HTML Laboratory</title>
  7 +    <style>
  8 +        :root {
  9 +            --bg-color: #2d2d2d;
 10 +            --text-color: #f8f8f2;
 11 +            --editor-bg: #1e1e1e;
 12 +            --border-color: #222;
 13 +            --header-bg: #333;
 14 +            --header-text: #ccc;
 15 +            --preview-bg: #2d2d2d;
 16 +        }
 17 +
 18 +        @media (prefers-color-scheme: light) {
 19 +            :root {
 20 +                --bg-color: #f0f0f0;
 21 +                --text-color: #333;
 22 +                --editor-bg: #fafafa;
 23 +                --border-color: #ccc;
 24 +                --header-bg: #ddd;
 25 +                --header-text: #666;
 26 +                --preview-bg: white;
 27 +            }
 28 +        }
 29 +
 30 +        * {
 31 +            margin: 0;
 32 +            padding: 0;
 33 +            box-sizing: border-box;
 34 +        }
 35 +
 36 +        body {
 37 +            font-family: monospace;
 38 +            background: var(--bg-color);
 39 +            color: var(--text-color);
 40 +            height: 100vh;
 41 +            display: flex;
 42 +            overflow: hidden;
 43 +        }
 44 +
 45 +        .editor-pane {
 46 +            width: 50%;
 47 +            height: 100vh;
 48 +            background: var(--preview-bg);
 49 +            border-right: 1px solid var(--border-color);
 50 +            position: relative;
 51 +        }
 52 +
 53 +        .preview-pane {
 54 +            width: 50%;
 55 +            height: 100vh;
 56 +            background: var(--preview-bg);
 57 +            position: relative;
 58 +        }
 59 +
 60 +        #editor {
 61 +            width: 100%;
 62 +            height: 100%;
 63 +            border: none;
 64 +            outline: none;
 65 +            font-family: monospace;
 66 +            font-size: 21px;
 67 +            padding: 15px;
 68 +            resize: none;
 69 +            overflow: auto;
 70 +            background: var(--editor-bg);
 71 +            color: var(--text-color);
 72 +            spellcheck: false;
 73 +            tab-size: 4;
 74 +        }
 75 +
 76 +        #preview {
 77 +            width: 100%;
 78 +            height: 100%;
 79 +            border: none;
 80 +            background: white;
 81 +            overflow: auto;
 82 +        }
 83 +
 84 +        #editor {
 85 +            padding-top: 15px;
 86 +        }
 87 +
 88 +        #preview {
 89 +            padding-top: 0;
 90 +        }
 91 +
 92 +        /* Hide scrollbars until needed */
 93 +        ::-webkit-scrollbar {
 94 +            width: 12px;
 95 +        }
 96 +
 97 +        ::-webkit-scrollbar-track {
 98 +            background: var(--editor-bg);
 99 +        }
100 +
101 +        ::-webkit-scrollbar-thumb {
102 +            background: var(--border-color);
103 +            border-radius: 6px;
104 +        }
105 +
106 +        ::-webkit-scrollbar-thumb:hover {
107 +            background: var(--header-text);
108 +        }
109 +    </style>
110 +</head>
111 +<body>
112 +    <div class="editor-pane">
113 +        <textarea id="editor" placeholder="Type your HTML, CSS, and JavaScript here..." spellcheck="false"></textarea>
114 +    </div>
115 +    
116 +    <div class="preview-pane">
117 +        <iframe id="preview" sandbox="allow-scripts"></iframe>
118 +    </div>
119 +
120 +    <script>
121 +        let updateTimer;
122 +        const editor = document.getElementById('editor');
123 +        const preview = document.getElementById('preview');
124 +        const storageKey = 'html-lab-content';
125 +
126 +        function updatePreview() {
127 +            const code = editor.value;
128 +            const blob = new Blob([code], { type: 'text/html' });
129 +            const url = URL.createObjectURL(blob);
130 +            preview.src = url;
131 +            
132 +            // Clean up the previous URL to prevent memory leaks
133 +            setTimeout(() => URL.revokeObjectURL(url), 1000);
134 +        }
135 +
136 +        function saveToStorage() {
137 +            try {
138 +                localStorage.setItem(storageKey, editor.value);
139 +            } catch (e) {
140 +                // Handle localStorage errors silently
141 +                console.warn('Could not save to localStorage:', e);
142 +            }
143 +        }
144 +
145 +        function loadFromStorage() {
146 +            try {
147 +                const saved = localStorage.getItem(storageKey);
148 +                if (saved !== null) {
149 +                    editor.value = saved;
150 +                    return true;
151 +                }
152 +            } catch (e) {
153 +                // Handle localStorage errors silently
154 +                console.warn('Could not load from localStorage:', e);
155 +            }
156 +            return false;
157 +        }
158 +
159 +
160 +        // Handle Tab key to insert tab character
161 +        editor.addEventListener('keydown', function(e) {
162 +            if (e.key === 'Tab') {
163 +                e.preventDefault();
164 +                
165 +                const start = this.selectionStart;
166 +                const end = this.selectionEnd;
167 +                
168 +                // Insert tab character at cursor position
169 +                this.value = this.value.substring(0, start) + '\t' + this.value.substring(end);
170 +                
171 +                // Move cursor to after the inserted tab
172 +                this.selectionStart = this.selectionEnd = start + 1;
173 +                
174 +                // Trigger input event to update preview
175 +                this.dispatchEvent(new Event('input'));
176 +            }
177 +        });
178 +
179 +        // Update preview after 0.5 seconds of no typing
180 +        editor.addEventListener('input', function() {
181 +            clearTimeout(updateTimer);
182 +            updateTimer = setTimeout(updatePreview, 500);
183 +            
184 +            // Save to localStorage on every change
185 +            saveToStorage();
186 +        });
187 +
188 +        // Save functionality with Cmd+S
189 +        document.addEventListener('keydown', function(e) {
190 +            if ((e.metaKey || e.ctrlKey) && e.key === 's') {
191 +                e.preventDefault();
192 +                saveFile();
193 +            }
194 +        });
195 +
196 +        function saveFile() {
197 +            const code = editor.value;
198 +            const blob = new Blob([code], { type: 'text/html' });
199 +            const url = URL.createObjectURL(blob);
200 +            
201 +            const a = document.createElement('a');
202 +            a.href = url;
203 +            a.download = 'index.html';
204 +            a.click();
205 +            
206 +            URL.revokeObjectURL(url);
207 +        }
208 +
209 +        // Initialize the editor content and render
210 +        function initialize() {
211 +            // Always try to load from localStorage regardless of refresh type
212 +            loadFromStorage();
213 +            
214 +            // Focus the editor
215 +            editor.focus();
216 +            
217 +            // Initial render
218 +            updatePreview();
219 +        }
220 +
221 +        // Initialize when page loads
222 +        initialize();
223 +    </script>
224 +</body>
225 +</html>