parthmax commited on
Commit
ccdc167
Β·
verified Β·
1 Parent(s): 0659a19

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +189 -340
index.html CHANGED
@@ -1,363 +1,212 @@
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>JavaRunner β€” Learn & Run Java Online</title>
7
- <meta name="description" content="JavaRunner is a mobile-friendly online Java IDE. Write, run, save, and download Java code. Perfect for beginners like Ragini Didi.">
8
- <meta name="keywords" content="Java IDE, Online Java compiler, JavaRunner, Learn Java, Java code editor, mobile-friendly IDE, Ragini Didi">
9
- <meta name="author" content="Saksham Pathak">
10
- <meta name="robots" content="index, follow">
11
-
12
- <!-- Open Graph for SEO & social -->
13
- <meta property="og:title" content="JavaRunner β€” Learn & Run Java Online">
14
- <meta property="og:description" content="JavaRunner is a mobile-friendly online Java IDE. Write, run, save, and download Java code. Perfect for beginners like Ragini Didi.">
15
- <meta property="og:type" content="website">
16
-
17
- <!-- Fonts & Icons -->
18
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&display=swap" rel="stylesheet">
19
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">
20
-
21
- <!-- CodeMirror -->
22
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/codemirror.min.css">
23
- <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/codemirror.min.js"></script>
24
- <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/mode/clike/clike.min.js"></script>
25
- <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/addon/edit/closebrackets.min.js"></script>
26
- <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/addon/edit/matchbrackets.min.js"></script>
27
- <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/addon/edit/indentation.min.js"></script>
28
-
29
- <style>
30
- :root {
31
- --bg:#0b1b2b;
32
- --glass: rgba(255,255,255,0.06);
33
- --glass-hover: rgba(255,255,255,0.1);
34
- --accent:#6c8cff;
35
- --accent-light:#8be5d0;
36
- --text:#e6eef8;
37
- --muted:#9aa4b2;
38
- --radius:14px;
39
- --shadow:0 8px 30px rgba(2,6,23,0.6);
40
- }
41
- *{box-sizing:border-box;margin:0;padding:0;}
42
- body{
43
- font-family:'Inter',sans-serif;
44
- background:linear-gradient(180deg, #071227, #0d1a2b);
45
- color:var(--text);
46
- display:flex;
47
- flex-direction:column;
48
- min-height:100vh;
49
- padding:10px;
50
- }
51
-
52
- /* Header */
53
- header{
54
- display:flex;
55
- justify-content:center;
56
- align-items:center;
57
- margin-bottom:12px;
58
- }
59
- .brand{
60
- font-weight:700;
61
- font-size:24px;
62
- color:var(--accent);
63
- display:flex;
64
- align-items:center;
65
- gap:10px;
66
- text-shadow: 1px 1px 4px rgba(0,0,0,0.5);
67
- }
68
- .brand i{font-size:28px;}
69
-
70
- /* App container */
71
- .app{
72
- display:flex;
73
- flex:1;
74
- gap:12px;
75
- max-width:1200px;
76
- width:100%;
77
- }
78
- .panel{
79
- background: var(--glass);
80
- backdrop-filter: blur(12px) saturate(1.1);
81
- border-radius: var(--radius);
82
- border:1px solid rgba(255,255,255,0.08);
83
- padding:12px;
84
- box-shadow: var(--shadow);
85
- transition: transform .2s ease, box-shadow .2s ease;
86
- }
87
- .panel:hover{transform:translateY(-3px);box-shadow:0 16px 40px rgba(8,14,40,0.5);}
88
-
89
- /* Sidebar */
90
- .sidebar{
91
- flex:0 0 260px;
92
- display:flex;
93
- flex-direction:column;
94
- gap:10px;
95
- height:calc(100vh - 60px);
96
- }
97
- .sidebar-header{
98
- display:flex;
99
- justify-content:space-between;
100
- align-items:center;
101
- }
102
- .file-list{
103
- flex:1;
104
- overflow-y:auto;
105
- display:flex;
106
- flex-direction:column;
107
- gap:6px;
108
- }
109
- .file-item{
110
- display:flex;
111
- justify-content:space-between;
112
- align-items:center;
113
- padding:8px;
114
- border-radius:10px;
115
- cursor:pointer;
116
- background: rgba(255,255,255,0.02);
117
- transition:0.2s;
118
- }
119
- .file-item:hover{background:var(--glass-hover);}
120
- .file-item.active{background:rgba(108,140,255,0.12);color:#fff;}
121
- .file-actions{display:flex;gap:6px;align-items:center;}
122
-
123
- /* Editor */
124
- .editor-area{
125
- flex:1;
126
- display:flex;
127
- flex-direction:column;
128
- gap:8px;
129
- min-height:400px;
130
- }
131
- .cm-wrap{
132
- border-radius:12px;
133
- overflow:hidden;
134
- border:1px solid rgba(255,255,255,0.04);
135
- }
136
- .CodeMirror{
137
- height:calc(100vh - 300px);
138
- background: rgba(2,6,23,0.7);
139
- color:#e8f1ff;
140
- font-size:14px;
141
- }
142
-
143
- /* Buttons */
144
- .btn{
145
- background: rgba(255,255,255,0.03);
146
- border:1px solid rgba(255,255,255,0.08);
147
- color:var(--muted);
148
- padding:6px 10px;
149
- border-radius:10px;
150
- cursor:pointer;
151
- display:inline-flex;
152
- align-items:center;
153
- gap:6px;
154
- transition: all .15s ease;
155
- }
156
- .btn:hover{color:#fff;transform:translateY(-2px);background:var(--glass-hover);}
157
- .btn-primary{
158
- background: linear-gradient(90deg,var(--accent),var(--accent-light));
159
- color:#04253b;
160
- padding:10px 14px;
161
- font-weight:700;
162
- border:none;
163
- }
164
-
165
- /* Console */
166
- .console{
167
- margin-top:6px;
168
- background: rgba(0,0,0,0.5);
169
- border-radius:10px;
170
- padding:12px;
171
- font-family:monospace;
172
- color:#cfe7ff;
173
- min-height:120px;
174
- overflow:auto;
175
- }
176
 
177
- /* Footer */
178
- footer{
179
- text-align:center;
180
- color:var(--muted);
181
- font-size:14px;
182
- padding:12px 0 6px 0;
183
- }
184
- footer .note{
185
- color:#c7d7ff;
186
- font-weight:600;
187
- }
 
 
 
 
188
 
189
- /* Responsive */
190
- @media(max-width:900px){
191
- .app{flex-direction:column;}
192
- .sidebar{width:100%;height:auto;order:2;}
193
- .editor-area{order:1;}
194
- .CodeMirror{height:300px;}
195
- }
196
- @media(max-width:480px){
197
- body{padding:6px;}
198
- .brand{font-size:20px;}
199
- .btn{padding:5px 8px;font-size:13px;}
200
- .btn-primary{padding:8px 10px;font-size:14px;}
201
- }
202
- </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
  </head>
204
  <body>
205
- <header>
206
- <div class="brand"><i class="fa-solid fa-rocket"></i> JavaRunner</div>
207
- </header>
208
 
209
- <div class="app">
210
- <!-- Sidebar -->
211
- <div class="panel sidebar">
212
- <div class="sidebar-header">
213
- <button class="btn" id="newBtn"><i class="fa-solid fa-file-circle-plus"></i> New</button>
214
- <button class="btn" id="importBtn"><i class="fa-solid fa-file-import"></i> Import</button>
 
215
  </div>
216
- <input type="text" placeholder="Search files..." id="searchFile" style="width:100%;padding:6px;border-radius:8px;background:rgba(255,255,255,0.03);border:1px solid rgba(255,255,255,0.08);color:var(--muted);margin-bottom:6px;">
217
- <div class="file-list" id="fileList"></div>
 
218
  </div>
219
 
220
- <!-- Editor -->
221
  <div class="panel editor-area">
222
- <div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;">
223
- <div>Active File: <span id="activeFile">β€”</span></div>
224
- <div style="display:flex;gap:6px;flex-wrap:wrap;">
225
- <button class="btn-primary" id="runBtn"><i class="fa-solid fa-play"></i> Run</button>
226
- <button class="btn" id="saveBtn"><i class="fa-solid fa-floppy-disk"></i> Save</button>
227
- <button class="btn" id="downloadBtn"><i class="fa-solid fa-download"></i> Download</button>
228
- <button class="btn" id="formatBtn"><i class="fa-solid fa-align-left"></i> Format</button>
229
- <button class="btn" id="cutBtn"><i class="fa-solid fa-cut"></i></button>
230
- <button class="btn" id="copyBtn"><i class="fa-solid fa-copy"></i></button>
231
- <button class="btn" id="pasteBtn"><i class="fa-solid fa-clipboard"></i></button>
232
- <button class="btn" id="deleteBtn"><i class="fa-solid fa-trash"></i></button>
233
- </div>
234
  </div>
235
- <div class="cm-wrap" id="cmWrap"><div id="editor"></div></div>
236
- <div class="console" id="console">Console output will appear here.</div>
 
 
 
237
  </div>
238
- </div>
239
-
240
- <footer>
241
- Made with ❀️ for <span class="note">Ragini Didi</span>
242
- </footer>
243
-
244
- <input type="file" id="fileInput" accept=".java" style="display:none">
245
-
246
- <script>
247
- // ---------- Editor setup ----------
248
- const editor = CodeMirror(document.getElementById('editor'),{
249
- mode:"text/x-java",
250
- lineNumbers:true,
251
- tabSize:4,
252
- indentUnit:4,
253
- autoCloseBrackets:true,
254
- matchBrackets:true,
255
- value:`class Main {
256
  public static void main(String[] args) {
257
- System.out.println("Hello Ragini Didi!");
258
  }
259
  }`
260
- });
261
-
262
- // Resize editor dynamically
263
- function resizeEditor(){
264
- const wrap=document.querySelector('.CodeMirror');
265
- if(!wrap) return;
266
- let vh=window.innerHeight;
267
- wrap.style.height=(vh - 280)+'px';
268
- editor.refresh();
269
- }
270
- window.addEventListener('resize',resizeEditor);
271
- setTimeout(resizeEditor,200);
272
-
273
- // ---------- Local storage & file management ----------
274
- let files=JSON.parse(localStorage.getItem('javaRunner_files')||'{}');
275
- let active=localStorage.getItem('javaRunner_active')||null;
276
- const fileListEl=document.getElementById('fileList');
277
- const activeFileEl=document.getElementById('activeFile');
278
- const consoleEl=document.getElementById('console');
279
-
280
- function saveToStorage(){localStorage.setItem('javaRunner_files',JSON.stringify(files));}
281
- function setActive(name){
282
- active=name;
283
- localStorage.setItem('javaRunner_active',active);
284
- activeFileEl.innerText=name||'β€”';
285
- renderFiles();
286
- if(active && files[active]) editor.setValue(files[active]);
287
- }
288
-
289
- function renderFiles(filter=''){
290
- fileListEl.innerHTML='';
291
- const names=Object.keys(files).filter(n=>n.toLowerCase().includes(filter.toLowerCase())).sort();
292
- if(names.length===0){fileListEl.innerHTML='<div style="color:'+ 'var(--muted)' +';padding:10px;font-size:13px">No files yet.</div>';return;}
293
- names.forEach(name=>{
294
- const div=document.createElement('div');
295
- div.className='file-item'+(name===active?' active':'');
296
- div.innerHTML=`<div>${name}</div><div style="display:flex;gap:6px;">
297
- <button class="btn" onclick="openFile('${name}')"><i class="fa-solid fa-folder-open"></i></button></div>`;
298
- fileListEl.appendChild(div);
299
  });
300
- }
301
-
302
- // File actions
303
- function newFile(){
304
- let name=prompt('Filename (end with .java)','Main.java');
305
- if(!name) return;if(!name.endsWith('.java')){alert('Filename must end with .java');return;}
306
- if(files[name]){alert('File exists');return;}
307
- const classname=name.replace('.java','').replace(/[^A-Za-z0-9_]/g,'')||'Main';
308
- files[name]=`class ${classname} {\n public static void main(String[] args) {\n System.out.println("Hello Ragini Didi!");\n }\n}`;
309
- saveToStorage();
310
- setActive(name);
311
- }
312
-
313
- function openFile(name){setActive(name);}
314
- function deleteFile(name){if(confirm(`Delete file ${name}?`)){delete files[name]; if(active===name) active=null; saveToStorage(); setActive(active);}}
315
- function saveFile(){if(!active){alert('No active file'); return;} files[active]=editor.getValue(); saveToStorage(); consoleEl.innerText='Saved successfully!';}
316
- function downloadFile(){if(!active){alert('No active file'); return;} const blob=new Blob([editor.getValue()],{type:'text/plain'}); const a=document.createElement('a'); a.href=URL.createObjectURL(blob); a.download=active; a.click(); URL.revokeObjectURL(a.href);}
317
- function formatCode(){const value=editor.getValue(); editor.setValue(value.split('\n').map(l=>l.trimStart()).join('\n'));}
318
- function cutText(){editor.execCommand('cut');}
319
- function copyText(){editor.execCommand('copy');}
320
- function pasteText(){editor.execCommand('paste');}
321
 
322
- // Run code (connect to backend /run API)
323
- async function runCode(){
324
- if(!active){alert('No active file'); return;}
325
- consoleEl.innerText='Running...';
326
- const code=editor.getValue();
327
- try{
328
- const res=await fetch('/run', {method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({code})});
329
- const data=await res.json();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
330
  consoleEl.innerText=data.output||data.error||'No output';
331
- }catch(e){consoleEl.innerText='Error running code: '+e.message;}
332
- }
333
-
334
- // Search files
335
- document.getElementById('searchFile').addEventListener('input',e=>renderFiles(e.target.value));
336
-
337
- // Button events
338
- document.getElementById('newBtn').addEventListener('click',newFile);
339
- document.getElementById('saveBtn').addEventListener('click',saveFile);
340
- document.getElementById('downloadBtn').addEventListener('click',downloadFile);
341
- document.getElementById('formatBtn').addEventListener('click',formatCode);
342
- document.getElementById('cutBtn').addEventListener('click',cutText);
343
- document.getElementById('copyBtn').addEventListener('click',copyText);
344
- document.getElementById('pasteBtn').addEventListener('click',pasteText);
345
- document.getElementById('runBtn').addEventListener('click',runCode);
346
-
347
- // Import files
348
- const fileInput=document.getElementById('fileInput');
349
- document.getElementById('importBtn').addEventListener('click',()=>fileInput.click());
350
- fileInput.addEventListener('change',e=>{
351
- const file=e.target.files[0];
352
- if(!file) return;
353
- const reader=new FileReader();
354
- reader.onload=()=>{files[file.name]=reader.result; saveToStorage(); setActive(file.name);}
355
- reader.readAsText(file);
356
- });
357
 
358
- // Initialize
359
- setActive(active);
360
- renderFiles();
361
- </script>
362
  </body>
363
  </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>JavaRunner β€” Learn Java Online for Mobile & Desktop</title>
7
+ <meta name="description" content="JavaRunner is a mobile and desktop-friendly interactive Java IDE for beginners. Learn Java safely on your device with auto-formatting, run code, and save files locally.">
8
+ <meta name="keywords" content="Java IDE, Learn Java, Online Java Compiler, JavaRunner, Coding for Beginners, Ragini Didi">
9
+ <meta name="author" content="JavaRunner Team">
10
+
11
+ <!-- OpenGraph / LLM friendly -->
12
+ <meta property="og:title" content="JavaRunner β€” Learn Java Online"/>
13
+ <meta property="og:description" content="Interactive Java IDE for mobile and desktop. Write, run, save Java code locally. Perfect for beginners and students."/>
14
+ <meta property="og:type" content="website"/>
15
+
16
+ <!-- Font -->
17
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&display=swap" rel="stylesheet">
18
+
19
+ <!-- FontAwesome Icons -->
20
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" integrity="sha512-t9f6b..." crossorigin="anonymous" referrerpolicy="no-referrer" />
21
+
22
+ <!-- CodeMirror -->
23
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/codemirror.min.css">
24
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/codemirror.min.js"></script>
25
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/mode/clike/clike.min.js"></script>
26
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/addon/edit/closebrackets.min.js"></script>
27
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/addon/edit/matchbrackets.min.js"></script>
28
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/addon/edit/indentation.min.js"></script>
29
+
30
+ <style>
31
+ :root{
32
+ --bg: #0f1720;
33
+ --glass: rgba(255,255,255,0.05);
34
+ --glass-dark: rgba(0,0,0,0.35);
35
+ --accent: #6c8cff;
36
+ --accent-light: #8be5d0;
37
+ --muted: #9aa4b2;
38
+ --card-shadow: 0 8px 30px rgba(2,6,23,0.6);
39
+ --radius: 16px;
40
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
+ *{box-sizing:border-box;}
43
+ html, body{margin:0;padding:0;font-family:Inter,sans-serif;background: linear-gradient(180deg,#071227 0%,#0d1a2b 100%); color:#e6eef8;}
44
+ body{min-height:100vh; display:flex; flex-direction:column; align-items:center; padding:12px;}
45
+
46
+ h1,h2,h3,h4,h5,h6{margin:0;}
47
+
48
+ .app {
49
+ display:grid;
50
+ grid-template-columns: 280px 1fr;
51
+ gap:16px;
52
+ width:100%;
53
+ max-width:1200px;
54
+ margin:0 auto;
55
+ flex:1 1 auto;
56
+ }
57
 
58
+ /* Glass morph panel */
59
+ .panel {
60
+ background: var(--glass);
61
+ backdrop-filter: blur(10px) saturate(1.05);
62
+ border-radius: var(--radius);
63
+ border:1px solid rgba(255,255,255,0.08);
64
+ padding:14px;
65
+ display:flex;
66
+ flex-direction:column;
67
+ gap:12px;
68
+ box-shadow: var(--card-shadow);
69
+ transition: all 0.2s ease;
70
+ }
71
+ .panel:hover { transform: translateY(-4px); box-shadow: 0 16px 40px rgba(8,14,40,0.6); }
72
+
73
+ /* File sidebar */
74
+ .files {
75
+ display:flex;
76
+ flex-direction:column;
77
+ gap:12px;
78
+ min-height:200px;
79
+ }
80
+ .files .top { display:flex; justify-content:space-between; align-items:center; gap:8px; }
81
+ .brand { font-size:18px; font-weight:700; color: var(--accent); display:flex; align-items:center; gap:8px; }
82
+ .brand i{font-size:20px; transform:translateY(-1px);}
83
+ .file-list { display:flex; flex-direction:column; gap:6px; overflow:auto; max-height:calc(100vh - 220px); }
84
+
85
+ .file-item {
86
+ padding:8px; border-radius:12px; display:flex; justify-content:space-between; align-items:center; cursor:pointer; background: rgba(255,255,255,0.02);
87
+ transition: all .14s ease;
88
+ }
89
+ .file-item:hover{background: rgba(108,140,255,0.1);}
90
+ .file-item.active{background: rgba(108,140,255,0.12); color:#fff;}
91
+
92
+ /* Editor area */
93
+ .editor-area{display:flex; flex-direction:column; gap:10px;}
94
+ .topbar{display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap;}
95
+ .title{font-size:14px;color:var(--muted);}
96
+ .controls{display:flex; gap:6px; flex-wrap:wrap; margin-top:6px;}
97
+
98
+ .btn{
99
+ padding:8px 10px; border-radius:12px; border:none; cursor:pointer; font-weight:600; display:inline-flex; align-items:center; gap:6px;
100
+ transition: all 0.15s ease; background: linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.01)); color:var(--muted);
101
+ }
102
+ .btn:hover{transform:translateY(-2px);color:#fff;box-shadow:0 6px 16px rgba(0,0,0,0.35);}
103
+ .primary{background: linear-gradient(90deg,var(--accent), var(--accent-light)); color:#04253b; font-weight:700;}
104
+ .secondary{background:transparent; border:1px solid rgba(255,255,255,0.05); color:var(--muted);}
105
+
106
+ .cm-wrap{border-radius:14px; overflow:hidden; border:1px solid rgba(255,255,255,0.02);}
107
+ .CodeMirror{height:calc(100vh - 400px); background: var(--glass-dark); color:#e8f1ff; font-size:13px;}
108
+ .console{background: rgba(0,0,0,0.4); border-radius:12px; padding:10px; font-family:monospace; color:#cfe7ff; max-height:160px; overflow:auto; border:1px solid rgba(255,255,255,0.04);}
109
+
110
+ footer{text-align:center; font-size:13px; color:var(--muted); margin-top:14px;}
111
+ .note{color:#c7d7ff; font-weight:600;}
112
+
113
+ /* Responsive */
114
+ @media(max-width:1000px){.app{grid-template-columns:1fr;}}
115
+ @media(max-width:600px){.CodeMirror{height:calc(100vh - 380px); font-size:12px;}}
116
+ @media(max-width:400px){.topbar{flex-direction:column; align-items:flex-start;} .controls{flex-wrap:wrap;}}
117
+ </style>
118
  </head>
119
  <body>
 
 
 
120
 
121
+ <div class="app">
122
+ <!-- File sidebar -->
123
+ <div class="panel files" id="sidebar">
124
+ <div class="top">
125
+ <div class="brand"><i class="fa-solid fa-rocket"></i> JavaRunner</div>
126
+ <div>
127
+ <button class="btn" id="newBtn" title="New file"><i class="fa-solid fa-file-circle-plus"></i></button>
128
  </div>
129
+ </div>
130
+
131
+ <div class="file-list" id="fileList"></div>
132
  </div>
133
 
134
+ <!-- Editor area -->
135
  <div class="panel editor-area">
136
+ <div class="topbar">
137
+ <div class="title">Interactive Java IDE β€” Mobile & Desktop Friendly</div>
138
+ <div class="controls">
139
+ <button class="btn primary" id="runBtn"><i class="fa-solid fa-play"></i> Run</button>
140
+ <button class="btn secondary" id="saveBtn"><i class="fa-solid fa-floppy-disk"></i> Save</button>
141
+ <button class="btn secondary" id="downloadBtn"><i class="fa-solid fa-download"></i> Download</button>
142
+ <button class="btn secondary" id="formatBtn"><i class="fa-solid fa-align-left"></i> Format</button>
143
+ <button class="btn secondary" id="deleteBtn"><i class="fa-solid fa-trash"></i> Delete</button>
 
 
 
 
144
  </div>
145
+ </div>
146
+ <div class="cm-wrap" id="cmWrap">
147
+ <div id="editor"></div>
148
+ </div>
149
+ <div class="console" id="console">Console output will appear here.</div>
150
  </div>
151
+ </div>
152
+
153
+ <footer>
154
+ Made with love for <span class="note">Ragini Didi πŸ’–</span> β€” Happy Java Learning!
155
+ </footer>
156
+
157
+ <script>
158
+ // ---------- CodeMirror ----------
159
+ const editor = CodeMirror(document.getElementById('editor'), {
160
+ mode:"text/x-java",
161
+ lineNumbers:true,
162
+ tabSize:4,
163
+ indentUnit:4,
164
+ autoCloseBrackets:true,
165
+ matchBrackets:true,
166
+ theme:"default",
167
+ value:`class Main {
 
168
  public static void main(String[] args) {
169
+ System.out.println("Hello Ragini Didi! Welcome to JavaRunner");
170
  }
171
  }`
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
 
174
+ function resizeEditor(){ editor.setSize('100%', window.innerHeight-400); }
175
+ window.addEventListener('resize',resizeEditor);
176
+ setTimeout(resizeEditor,200);
177
+
178
+ // Local file storage
179
+ let files = JSON.parse(localStorage.getItem('java_runner_files')||'{}');
180
+ let active = localStorage.getItem('java_runner_active') || null;
181
+ const fileListEl = document.getElementById('fileList');
182
+ const consoleEl = document.getElementById('console');
183
+
184
+ function saveToStorage(){ localStorage.setItem('java_runner_files',JSON.stringify(files)); }
185
+ function setActive(name){ active=name; localStorage.setItem('java_runner_active',active); renderFiles(); editor.setValue(files[active]); }
186
+ function renderFiles(){ fileListEl.innerHTML=''; Object.keys(files).forEach(f=>{const div=document.createElement('div');div.className='file-item'+(f===active?' active':''); div.innerText=f; div.onclick=()=>setActive(f); fileListEl.appendChild(div); }); }
187
+
188
+ function newFile(){ const name='Main.java'; if(files[name]) { alert('File exists'); return;} files[name]=editor.getValue(); saveToStorage(); setActive(name);}
189
+ function saveFile(){ if(!active)return; files[active]=editor.getValue(); saveToStorage(); consoleEl.innerText='Saved locally βœ”';}
190
+ function downloadFile(){ if(!active)return; const blob=new Blob([editor.getValue()],{type:'text/plain'}); const a=document.createElement('a'); a.href=URL.createObjectURL(blob); a.download=active; a.click(); URL.revokeObjectURL(a.href);}
191
+ function deleteFile(){ if(!active) return; if(confirm(`Delete ${active}?`)){ delete files[active]; saveToStorage(); active=null; editor.setValue(''); renderFiles(); }}
192
+
193
+ document.getElementById('newBtn').onclick=newFile;
194
+ document.getElementById('saveBtn').onclick=saveFile;
195
+ document.getElementById('downloadBtn').onclick=downloadFile;
196
+ document.getElementById('deleteBtn').onclick=deleteFile;
197
+
198
+ document.getElementById('formatBtn').onclick=()=>{ editor.execCommand('selectAll'); editor.execCommand('indentAuto'); editor.execCommand('singleSelection');};
199
+
200
+ document.getElementById('runBtn').onclick=async()=>{
201
+ if(!active) return; saveFile(); consoleEl.innerText='Running...';
202
+ try{
203
+ const resp=await fetch('/run-java',{method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({code: editor.getValue(), filename: active})});
204
+ const data=await resp.json();
205
  consoleEl.innerText=data.output||data.error||'No output';
206
+ }catch(e){ consoleEl.innerText='Error: '+e.message; }
207
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
 
209
+ if(Object.keys(files).length===0) newFile(); else setActive(Object.keys(files)[0]);
210
+ </script>
 
 
211
  </body>
212
  </html>