Spaces:
Sleeping
Sleeping
File size: 10,355 Bytes
6d38145 ccdc167 a40fdda ccdc167 a40fdda ccdc167 6d38145 a40fdda ccdc167 9c580f0 ccdc167 9c580f0 6d38145 ccdc167 9c580f0 ccdc167 9c580f0 ccdc167 6d38145 ccdc167 0659a19 ccdc167 0659a19 9c580f0 0659a19 ccdc167 0659a19 ccdc167 0659a19 ccdc167 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 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
<!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 for Mobile & Desktop</title>
<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.">
<meta name="keywords" content="Java IDE, Learn Java, Online Java Compiler, JavaRunner, Coding for Beginners, Ragini Didi">
<meta name="author" content="JavaRunner Team">
<!-- OpenGraph / LLM friendly -->
<meta property="og:title" content="JavaRunner β Learn Java Online"/>
<meta property="og:description" content="Interactive Java IDE for mobile and desktop. Write, run, save Java code locally. Perfect for beginners and students."/>
<meta property="og:type" content="website"/>
<!-- Font -->
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&display=swap" rel="stylesheet">
<!-- FontAwesome Icons -->
<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" />
<!-- 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: #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;
}
/* Glass morph panel */
.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); }
/* File sidebar */
.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 */
.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;}
/* Responsive */
@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">
<!-- File sidebar -->
<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>
<!-- Editor area -->
<div class="panel editor-area">
<div class="topbar">
<div class="title">Interactive Java IDE β Mobile & Desktop Friendly</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 love for <span class="note">Ragini Didi π</span> β Happy Java Learning!
</footer>
<script>
// ---------- CodeMirror ----------
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);
// Local file storage
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='Main.java'; if(files[name]) { alert('File exists'); return;} files[name]=editor.getValue(); 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> |