Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>JavaRunner — Learn & Run Java Online</title> | |
| <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."> | |
| <meta name="keywords" content="Java IDE, Online Java compiler, JavaRunner, Learn Java, Java code editor, mobile-friendly IDE, Ragini Didi"> | |
| <meta name="author" content="Saksham Pathak"> | |
| <meta name="robots" content="index, follow"> | |
| <!-- Open Graph for SEO & social --> | |
| <meta property="og:title" content="JavaRunner — Learn & Run Java Online"> | |
| <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."> | |
| <meta property="og:type" content="website"> | |
| <!-- Fonts & Icons --> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&display=swap" rel="stylesheet"> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"> | |
| <!-- CodeMirror --> | |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/codemirror.min.css"> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/codemirror.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/mode/clike/clike.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/addon/edit/closebrackets.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/addon/edit/matchbrackets.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.13/addon/edit/indentation.min.js"></script> | |
| <style> | |
| :root { | |
| --bg:#0b1b2b; | |
| --glass: rgba(255,255,255,0.06); | |
| --glass-hover: rgba(255,255,255,0.1); | |
| --accent:#6c8cff; | |
| --accent-light:#8be5d0; | |
| --text:#e6eef8; | |
| --muted:#9aa4b2; | |
| --radius:14px; | |
| --shadow:0 8px 30px rgba(2,6,23,0.6); | |
| } | |
| *{box-sizing:border-box;margin:0;padding:0;} | |
| body{ | |
| font-family:'Inter',sans-serif; | |
| background:linear-gradient(180deg, #071227, #0d1a2b); | |
| color:var(--text); | |
| display:flex; | |
| flex-direction:column; | |
| min-height:100vh; | |
| padding:10px; | |
| } | |
| /* Header */ | |
| header{ | |
| display:flex; | |
| justify-content:center; | |
| align-items:center; | |
| margin-bottom:12px; | |
| } | |
| .brand{ | |
| font-weight:700; | |
| font-size:24px; | |
| color:var(--accent); | |
| display:flex; | |
| align-items:center; | |
| gap:10px; | |
| text-shadow: 1px 1px 4px rgba(0,0,0,0.5); | |
| } | |
| .brand i{font-size:28px;} | |
| /* App container */ | |
| .app{ | |
| display:flex; | |
| flex:1; | |
| gap:12px; | |
| max-width:1200px; | |
| width:100%; | |
| } | |
| .panel{ | |
| background: var(--glass); | |
| backdrop-filter: blur(12px) saturate(1.1); | |
| border-radius: var(--radius); | |
| border:1px solid rgba(255,255,255,0.08); | |
| padding:12px; | |
| box-shadow: var(--shadow); | |
| transition: transform .2s ease, box-shadow .2s ease; | |
| } | |
| .panel:hover{transform:translateY(-3px);box-shadow:0 16px 40px rgba(8,14,40,0.5);} | |
| /* Sidebar */ | |
| .sidebar{ | |
| flex:0 0 260px; | |
| display:flex; | |
| flex-direction:column; | |
| gap:10px; | |
| height:calc(100vh - 60px); | |
| } | |
| .sidebar-header{ | |
| display:flex; | |
| justify-content:space-between; | |
| align-items:center; | |
| } | |
| .file-list{ | |
| flex:1; | |
| overflow-y:auto; | |
| display:flex; | |
| flex-direction:column; | |
| gap:6px; | |
| } | |
| .file-item{ | |
| display:flex; | |
| justify-content:space-between; | |
| align-items:center; | |
| padding:8px; | |
| border-radius:10px; | |
| cursor:pointer; | |
| background: rgba(255,255,255,0.02); | |
| transition:0.2s; | |
| } | |
| .file-item:hover{background:var(--glass-hover);} | |
| .file-item.active{background:rgba(108,140,255,0.12);color:#fff;} | |
| .file-actions{display:flex;gap:6px;align-items:center;} | |
| /* Editor */ | |
| .editor-area{ | |
| flex:1; | |
| display:flex; | |
| flex-direction:column; | |
| gap:8px; | |
| min-height:400px; | |
| } | |
| .cm-wrap{ | |
| border-radius:12px; | |
| overflow:hidden; | |
| border:1px solid rgba(255,255,255,0.04); | |
| } | |
| .CodeMirror{ | |
| height:calc(100vh - 300px); | |
| background: rgba(2,6,23,0.7); | |
| color:#e8f1ff; | |
| font-size:14px; | |
| } | |
| /* Buttons */ | |
| .btn{ | |
| background: rgba(255,255,255,0.03); | |
| border:1px solid rgba(255,255,255,0.08); | |
| color:var(--muted); | |
| padding:6px 10px; | |
| border-radius:10px; | |
| cursor:pointer; | |
| display:inline-flex; | |
| align-items:center; | |
| gap:6px; | |
| transition: all .15s ease; | |
| } | |
| .btn:hover{color:#fff;transform:translateY(-2px);background:var(--glass-hover);} | |
| .btn-primary{ | |
| background: linear-gradient(90deg,var(--accent),var(--accent-light)); | |
| color:#04253b; | |
| padding:10px 14px; | |
| font-weight:700; | |
| border:none; | |
| } | |
| /* Console */ | |
| .console{ | |
| margin-top:6px; | |
| background: rgba(0,0,0,0.5); | |
| border-radius:10px; | |
| padding:12px; | |
| font-family:monospace; | |
| color:#cfe7ff; | |
| min-height:120px; | |
| overflow:auto; | |
| } | |
| /* Footer */ | |
| footer{ | |
| text-align:center; | |
| color:var(--muted); | |
| font-size:14px; | |
| padding:12px 0 6px 0; | |
| } | |
| footer .note{ | |
| color:#c7d7ff; | |
| font-weight:600; | |
| } | |
| /* Responsive */ | |
| @media(max-width:900px){ | |
| .app{flex-direction:column;} | |
| .sidebar{width:100%;height:auto;order:2;} | |
| .editor-area{order:1;} | |
| .CodeMirror{height:300px;} | |
| } | |
| @media(max-width:480px){ | |
| body{padding:6px;} | |
| .brand{font-size:20px;} | |
| .btn{padding:5px 8px;font-size:13px;} | |
| .btn-primary{padding:8px 10px;font-size:14px;} | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <header> | |
| <div class="brand"><i class="fa-solid fa-rocket"></i> JavaRunner</div> | |
| </header> | |
| <div class="app"> | |
| <!-- Sidebar --> | |
| <div class="panel sidebar"> | |
| <div class="sidebar-header"> | |
| <button class="btn" id="newBtn"><i class="fa-solid fa-file-circle-plus"></i> New</button> | |
| <button class="btn" id="importBtn"><i class="fa-solid fa-file-import"></i> Import</button> | |
| </div> | |
| <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;"> | |
| <div class="file-list" id="fileList"></div> | |
| </div> | |
| <!-- Editor --> | |
| <div class="panel editor-area"> | |
| <div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;"> | |
| <div>Active File: <span id="activeFile">—</span></div> | |
| <div style="display:flex;gap:6px;flex-wrap:wrap;"> | |
| <button class="btn-primary" id="runBtn"><i class="fa-solid fa-play"></i> Run</button> | |
| <button class="btn" id="saveBtn"><i class="fa-solid fa-floppy-disk"></i> Save</button> | |
| <button class="btn" id="downloadBtn"><i class="fa-solid fa-download"></i> Download</button> | |
| <button class="btn" id="formatBtn"><i class="fa-solid fa-align-left"></i> Format</button> | |
| <button class="btn" id="cutBtn"><i class="fa-solid fa-cut"></i></button> | |
| <button class="btn" id="copyBtn"><i class="fa-solid fa-copy"></i></button> | |
| <button class="btn" id="pasteBtn"><i class="fa-solid fa-clipboard"></i></button> | |
| <button class="btn" id="deleteBtn"><i class="fa-solid fa-trash"></i></button> | |
| </div> | |
| </div> | |
| <div class="cm-wrap" id="cmWrap"><div id="editor"></div></div> | |
| <div class="console" id="console">Console output will appear here.</div> | |
| </div> | |
| </div> | |
| <footer> | |
| Made with ❤️ for <span class="note">Ragini Didi</span> | |
| </footer> | |
| <input type="file" id="fileInput" accept=".java" style="display:none"> | |
| <script> | |
| // ---------- Editor setup ---------- | |
| const editor = CodeMirror(document.getElementById('editor'),{ | |
| mode:"text/x-java", | |
| lineNumbers:true, | |
| tabSize:4, | |
| indentUnit:4, | |
| autoCloseBrackets:true, | |
| matchBrackets:true, | |
| value:`class Main { | |
| public static void main(String[] args) { | |
| System.out.println("Hello Ragini Didi!"); | |
| } | |
| }` | |
| }); | |
| // Resize editor dynamically | |
| function resizeEditor(){ | |
| const wrap=document.querySelector('.CodeMirror'); | |
| if(!wrap) return; | |
| let vh=window.innerHeight; | |
| wrap.style.height=(vh - 280)+'px'; | |
| editor.refresh(); | |
| } | |
| window.addEventListener('resize',resizeEditor); | |
| setTimeout(resizeEditor,200); | |
| // ---------- Local storage & file management ---------- | |
| let files=JSON.parse(localStorage.getItem('javaRunner_files')||'{}'); | |
| let active=localStorage.getItem('javaRunner_active')||null; | |
| const fileListEl=document.getElementById('fileList'); | |
| const activeFileEl=document.getElementById('activeFile'); | |
| const consoleEl=document.getElementById('console'); | |
| function saveToStorage(){localStorage.setItem('javaRunner_files',JSON.stringify(files));} | |
| function setActive(name){ | |
| active=name; | |
| localStorage.setItem('javaRunner_active',active); | |
| activeFileEl.innerText=name||'—'; | |
| renderFiles(); | |
| if(active && files[active]) editor.setValue(files[active]); | |
| } | |
| function renderFiles(filter=''){ | |
| fileListEl.innerHTML=''; | |
| const names=Object.keys(files).filter(n=>n.toLowerCase().includes(filter.toLowerCase())).sort(); | |
| if(names.length===0){fileListEl.innerHTML='<div style="color:'+ 'var(--muted)' +';padding:10px;font-size:13px">No files yet.</div>';return;} | |
| names.forEach(name=>{ | |
| const div=document.createElement('div'); | |
| div.className='file-item'+(name===active?' active':''); | |
| div.innerHTML=`<div>${name}</div><div style="display:flex;gap:6px;"> | |
| <button class="btn" onclick="openFile('${name}')"><i class="fa-solid fa-folder-open"></i></button></div>`; | |
| fileListEl.appendChild(div); | |
| }); | |
| } | |
| // File actions | |
| function newFile(){ | |
| let name=prompt('Filename (end with .java)','Main.java'); | |
| if(!name) return;if(!name.endsWith('.java')){alert('Filename must end with .java');return;} | |
| if(files[name]){alert('File exists');return;} | |
| const classname=name.replace('.java','').replace(/[^A-Za-z0-9_]/g,'')||'Main'; | |
| files[name]=`class ${classname} {\n public static void main(String[] args) {\n System.out.println("Hello Ragini Didi!");\n }\n}`; | |
| saveToStorage(); | |
| setActive(name); | |
| } | |
| function openFile(name){setActive(name);} | |
| function deleteFile(name){if(confirm(`Delete file ${name}?`)){delete files[name]; if(active===name) active=null; saveToStorage(); setActive(active);}} | |
| function saveFile(){if(!active){alert('No active file'); return;} files[active]=editor.getValue(); saveToStorage(); consoleEl.innerText='Saved successfully!';} | |
| 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);} | |
| function formatCode(){const value=editor.getValue(); editor.setValue(value.split('\n').map(l=>l.trimStart()).join('\n'));} | |
| function cutText(){editor.execCommand('cut');} | |
| function copyText(){editor.execCommand('copy');} | |
| function pasteText(){editor.execCommand('paste');} | |
| // Run code (connect to backend /run API) | |
| async function runCode(){ | |
| if(!active){alert('No active file'); return;} | |
| consoleEl.innerText='Running...'; | |
| const code=editor.getValue(); | |
| try{ | |
| const res=await fetch('/run', {method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({code})}); | |
| const data=await res.json(); | |
| consoleEl.innerText=data.output||data.error||'No output'; | |
| }catch(e){consoleEl.innerText='Error running code: '+e.message;} | |
| } | |
| // Search files | |
| document.getElementById('searchFile').addEventListener('input',e=>renderFiles(e.target.value)); | |
| // Button events | |
| document.getElementById('newBtn').addEventListener('click',newFile); | |
| document.getElementById('saveBtn').addEventListener('click',saveFile); | |
| document.getElementById('downloadBtn').addEventListener('click',downloadFile); | |
| document.getElementById('formatBtn').addEventListener('click',formatCode); | |
| document.getElementById('cutBtn').addEventListener('click',cutText); | |
| document.getElementById('copyBtn').addEventListener('click',copyText); | |
| document.getElementById('pasteBtn').addEventListener('click',pasteText); | |
| document.getElementById('runBtn').addEventListener('click',runCode); | |
| // Import files | |
| const fileInput=document.getElementById('fileInput'); | |
| document.getElementById('importBtn').addEventListener('click',()=>fileInput.click()); | |
| fileInput.addEventListener('change',e=>{ | |
| const file=e.target.files[0]; | |
| if(!file) return; | |
| const reader=new FileReader(); | |
| reader.onload=()=>{files[file.name]=reader.result; saveToStorage(); setActive(file.name);} | |
| reader.readAsText(file); | |
| }); | |
| // Initialize | |
| setActive(active); | |
| renderFiles(); | |
| </script> | |
| </body> | |
| </html> |