Spaces:
Sleeping
Sleeping
File size: 8,920 Bytes
6d38145 7248bd4 6d38145 a40fdda 7248bd4 ccdc167 9c580f0 7248bd4 6d38145 7248bd4 46a6164 7248bd4 ccdc167 6d38145 7248bd4 ccdc167 7248bd4 46a6164 7248bd4 0659a19 7248bd4 0659a19 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JavaRunner — Learn Java Online</title>
<meta name="description" content="JavaRunner: Interactive Java IDE to write, run, and manage Java files locally. Perfect for learners.">
<meta name="author" content="JavaRunner Team">
<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">
<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:#0f1720; --glass:rgba(255,255,255,0.05); --glass-dark:rgba(0,0,0,0.35);
--accent:#6c8cff; --accent-light:#8be5d0; --muted:#9aa4b2;
--card-shadow:0 8px 30px rgba(2,6,23,0.6); --radius:16px;
}
*{box-sizing:border-box;}
html, body{margin:0;padding:0;font-family:Inter,sans-serif;background:linear-gradient(180deg,#071227 0%,#0d1a2b 100%);color:#e6eef8;}
body{min-height:100vh;display:flex;flex-direction:column;align-items:center;padding:12px;}
h1,h2,h3,h4,h5,h6{margin:0;}
.app{display:grid;grid-template-columns:280px 1fr;gap:16px;width:100%;max-width:1200px;margin:0 auto;flex:1 1 auto;}
.panel{background:var(--glass);backdrop-filter:blur(10px) saturate(1.05);border-radius:var(--radius);
border:1px solid rgba(255,255,255,0.08);padding:14px;display:flex;flex-direction:column;gap:12px;box-shadow:var(--card-shadow);
transition:all 0.2s ease;}
.panel:hover{transform:translateY(-4px);box-shadow:0 16px 40px rgba(8,14,40,0.6);}
.files{display:flex;flex-direction:column;gap:12px;min-height:200px;}
.files .top{display:flex;justify-content:space-between;align-items:center;gap:8px;}
.brand{font-size:18px;font-weight:700;color:var(--accent);display:flex;align-items:center;gap:8px;}
.brand i{font-size:20px;transform:translateY(-1px);}
.file-list{display:flex;flex-direction:column;gap:6px;overflow:auto;max-height:calc(100vh - 220px);}
.file-item{padding:8px;border-radius:12px;display:flex;justify-content:space-between;align-items:center;cursor:pointer;background:rgba(255,255,255,0.02);transition:all .14s ease;}
.file-item:hover{background:rgba(108,140,255,0.1);}
.file-item.active{background:rgba(108,140,255,0.12);color:#fff;}
.editor-area{display:flex;flex-direction:column;gap:10px;}
.topbar{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;}
.title{font-size:14px;color:var(--muted);}
.controls{display:flex;gap:6px;flex-wrap:wrap;margin-top:6px;}
.btn{padding:8px 10px;border-radius:12px;border:none;cursor:pointer;font-weight:600;display:inline-flex;align-items:center;gap:6px;
transition:all 0.15s ease;background:linear-gradient(180deg, rgba(255,255,255,0.02), rgba(255,255,255,0.01)); color:var(--muted);}
.btn:hover{transform:translateY(-2px);color:#fff;box-shadow:0 6px 16px rgba(0,0,0,0.35);}
.primary{background:linear-gradient(90deg,var(--accent), var(--accent-light)); color:#04253b; font-weight:700;}
.secondary{background:transparent; border:1px solid rgba(255,255,255,0.05); color:var(--muted);}
.cm-wrap{border-radius:14px; overflow:hidden; border:1px solid rgba(255,255,255,0.02);}
.CodeMirror{height:calc(100vh - 400px); background: var(--glass-dark); color:#e8f1ff; font-size:13px;}
.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);}
footer{text-align:center;font-size:13px;color:var(--muted);margin-top:14px;}
.note{color:#c7d7ff;font-weight:600;}
@media(max-width:1000px){.app{grid-template-columns:1fr;}}
@media(max-width:600px){.CodeMirror{height:calc(100vh - 380px); font-size:12px;}}
@media(max-width:400px){.topbar{flex-direction:column;align-items:flex-start;} .controls{flex-wrap:wrap;}}
</style>
</head>
<body>
<div class="app">
<div class="panel files" id="sidebar">
<div class="top">
<div class="brand"><i class="fa-solid fa-rocket"></i> JavaRunner</div>
<div>
<button class="btn" id="newBtn" title="New file"><i class="fa-solid fa-file-circle-plus"></i></button>
</div>
</div>
<div class="file-list" id="fileList"></div>
</div>
<div class="panel editor-area">
<div class="topbar">
<div class="title">Interactive Java IDE </div>
<div class="controls">
<button class="btn primary" id="runBtn"><i class="fa-solid fa-play"></i> Run</button>
<button class="btn secondary" id="saveBtn"><i class="fa-solid fa-floppy-disk"></i> Save</button>
<button class="btn secondary" id="downloadBtn"><i class="fa-solid fa-download"></i> Download</button>
<button class="btn secondary" id="formatBtn"><i class="fa-solid fa-align-left"></i> Format</button>
<button class="btn secondary" id="deleteBtn"><i class="fa-solid fa-trash"></i> Delete</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 care for <span class="note">Ragini Didi</span> — Happy Java Learning!
</footer>
<script>
const editor = CodeMirror(document.getElementById('editor'), {
mode:"text/x-java", lineNumbers:true, tabSize:4, indentUnit:4,
autoCloseBrackets:true, matchBrackets:true, theme:"default",
value:`class Main {
public static void main(String[] args) {
System.out.println("Hello Ragini Didi! Welcome to JavaRunner");
}
}`
});
function resizeEditor(){ editor.setSize('100%', window.innerHeight-400); }
window.addEventListener('resize',resizeEditor);
setTimeout(resizeEditor,200);
let files = JSON.parse(localStorage.getItem('java_runner_files')||'{}');
let active = localStorage.getItem('java_runner_active') || null;
const fileListEl = document.getElementById('fileList');
const consoleEl = document.getElementById('console');
function saveToStorage(){ localStorage.setItem('java_runner_files',JSON.stringify(files)); }
function setActive(name){ active=name; localStorage.setItem('java_runner_active',active); renderFiles(); editor.setValue(files[active]); }
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);
});
}
function newFile(){
const name=prompt('Enter new file name (with .java):','NewFile.java');
if(!name) return;
if(files[name]){ alert('File already exists!'); return;}
files[name]=`class ${name.replace('.java','')} {\n public static void main(String[] args) {\n System.out.println("Hello Ragini Didi!");\n }\n}`;
saveToStorage();
setActive(name);
}
function saveFile(){ if(!active)return; files[active]=editor.getValue(); saveToStorage(); consoleEl.innerText='Saved locally ✔';}
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);}
function deleteFile(){ if(!active) return; if(confirm(`Delete ${active}?`)){ delete files[active]; saveToStorage(); active=null; editor.setValue(''); renderFiles(); }}
document.getElementById('newBtn').onclick=newFile;
document.getElementById('saveBtn').onclick=saveFile;
document.getElementById('downloadBtn').onclick=downloadFile;
document.getElementById('deleteBtn').onclick=deleteFile;
document.getElementById('formatBtn').onclick=()=>{ editor.execCommand('selectAll'); editor.execCommand('indentAuto'); editor.execCommand('singleSelection');};
document.getElementById('runBtn').onclick=async()=>{
if(!active) return; saveFile(); consoleEl.innerText='Running...';
try{
const resp=await fetch('/run-java',{method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({code: editor.getValue(), filename: active})});
const data=await resp.json();
consoleEl.innerText=data.output||data.error||'No output';
}catch(e){ consoleEl.innerText='Error: '+e.message; }
};
if(Object.keys(files).length===0) newFile(); else setActive(Object.keys(files)[0]);
</script>
</body>
</html> |