dev-ghpages/windows7.html

225 lines
14 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Windows 7 Apps Demo</title>
<style>
:root{--taskbar:56px;--text:#eaf2ff;--muted:#bed3f1;--bg1:#081626;--bg2:#0d2f50;--glass:rgba(255,255,255,.08)}
*{box-sizing:border-box}
html,body{height:100%;margin:0;font-family:"Segoe UI",Arial,sans-serif;color:var(--text);overflow:hidden;background:linear-gradient(135deg,var(--bg1),var(--bg2))}
.wallpaper{position:fixed;inset:0;display:grid;place-items:center;pointer-events:none}
.glow{width:700px;height:340px;opacity:.08;filter:blur(20px);transform:rotate(-8deg);border-radius:20px;background:linear-gradient(90deg,#0bb1ff,#2fbf54,#ffcb40,#ff4f4f)}
.desktop{position:fixed;inset:0 0 var(--taskbar) 0;padding:18px}
.desktop-icons{display:flex;gap:16px;flex-wrap:wrap;align-content:flex-start;width:360px}
.icon{width:92px;padding:10px;border-radius:10px;text-align:center;cursor:pointer;background:rgba(0,0,0,.15);border:1px solid rgba(255,255,255,.1)}
.icon:hover{background:rgba(255,255,255,.12)}
.icon .emoji{font-size:30px;display:block;margin-bottom:8px}
.icon .label{font-size:12px}
.window{position:absolute;width:min(960px,calc(100vw - 60px));height:min(620px,calc(100vh - 120px));top:50px;left:60px;border-radius:10px;overflow:hidden;background:rgba(7,15,30,.78);border:1px solid rgba(255,255,255,.16);box-shadow:0 20px 60px rgba(0,0,0,.55);display:none}
.window.visible{display:flex;flex-direction:column}
.titlebar{height:42px;display:flex;align-items:center;gap:10px;padding:8px 10px;background:linear-gradient(180deg,rgba(255,255,255,.11),rgba(255,255,255,.03));border-bottom:1px solid rgba(255,255,255,.13);cursor:move}
.title{font-size:14px;font-weight:700}
.controls{margin-left:auto;display:flex;gap:7px}
.controls button{width:42px;height:28px;border:0;border-radius:6px;cursor:pointer;font-weight:700}
.min{background:#dcecff}.max{background:#2a88d8;color:#fff}.close{background:#d55353;color:#fff}
.explorer-shell{display:grid;grid-template-columns:220px 1fr;height:100%}
.sidebar{border-right:1px solid rgba(255,255,255,.12);padding:10px;background:rgba(255,255,255,.03)}
.node{padding:7px;border-radius:6px;cursor:pointer;font-size:13px}.node:hover{background:rgba(255,255,255,.1)}
.explorer-main{display:flex;flex-direction:column}
.toolbar,.pathbar{padding:8px 10px;border-bottom:1px solid rgba(255,255,255,.12);display:flex;gap:8px;align-items:center}
.toolbar button,.pathbar button{padding:6px 10px;border-radius:6px;border:1px solid rgba(255,255,255,.2);background:rgba(255,255,255,.08);color:var(--text);cursor:pointer}
.crumb{background:none;border:none;color:#d8ebff;cursor:pointer}
.list{padding:10px;display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:10px;overflow:auto}
.item{padding:10px;border-radius:8px;border:1px solid rgba(255,255,255,.15);background:rgba(7,18,33,.66);cursor:pointer}
.item.sel{outline:2px solid #8ec4ff}
.meta{font-size:12px;color:var(--muted);margin-top:4px}
.status{padding:7px 10px;font-size:12px;color:var(--muted);border-top:1px solid rgba(255,255,255,.12)}
.browser-toolbar{display:flex;gap:8px;padding:10px;border-bottom:1px solid rgba(255,255,255,.12)}
.browser-toolbar input{flex:1;padding:8px;border-radius:6px;border:1px solid rgba(255,255,255,.2);background:rgba(0,0,0,.25);color:#fff}
.browser-toolbar button{padding:8px 10px;border-radius:6px;border:1px solid rgba(255,255,255,.2);background:rgba(255,255,255,.08);color:#fff;cursor:pointer}
iframe{width:100%;height:100%;border:0;background:#fff}
.editor-toolbar{display:flex;gap:8px;padding:10px;border-bottom:1px solid rgba(255,255,255,.12)}
.editor-toolbar input,.editor-toolbar button{padding:7px 10px;border-radius:6px;border:1px solid rgba(255,255,255,.2);background:rgba(255,255,255,.08);color:#fff}
#editor{flex:1;background:#071423;color:#d7ebff;border:0;padding:12px;font-family:Consolas,monospace;resize:none}
.taskbar{position:fixed;left:8px;right:8px;bottom:8px;height:calc(var(--taskbar) - 10px);border-radius:12px;display:flex;align-items:center;justify-content:space-between;padding:8px;background:linear-gradient(180deg,rgba(6,13,25,.65),rgba(3,7,14,.85));box-shadow:0 10px 30px rgba(0,0,0,.55)}
.task-left{display:flex;gap:8px;align-items:center}
.start{padding:8px 12px;border-radius:8px;background:rgba(255,255,255,.1);font-weight:700}
.task-app{width:44px;height:36px;border-radius:8px;border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.08);color:#fff;cursor:pointer}
#clock{font-size:13px;color:#d8ebff}
</style>
</head>
<body>
<div class="wallpaper"><div class="glow"></div></div>
<main class="desktop">
<section class="desktop-icons">
<div class="icon" data-open="explorer"><span class="emoji">📁</span><span class="label">Explorer</span></div>
<div class="icon" data-open="browser"><span class="emoji">🌐</span><span class="label">Browser</span></div>
<div class="icon" data-open="editor"><span class="emoji">📝</span><span class="label">Text Editor</span></div>
</section>
<section class="window visible" id="explorer-window" style="z-index:5">
<div class="titlebar"><span>📁</span><span class="title">Windows Explorer</span>
<div class="controls"><button class="min" data-min="explorer-window"></button><button class="max" data-max="explorer-window"></button><button class="close" data-close="explorer-window"></button></div>
</div>
<div class="explorer-shell">
<aside class="sidebar">
<div class="node" data-path="/">🖥️ Computer</div>
<div class="node" data-path="/Music">🎵 Music</div>
<div class="node" data-path="/Music/NewJeans">💿 NewJeans</div>
<div class="node" data-path="/Music/Blackpink">💿 Blackpink</div>
</aside>
<div class="explorer-main">
<div class="toolbar">
<button id="up-btn">Up</button>
<button id="new-folder-btn">New Folder</button>
<button id="new-file-btn">New Text File</button>
<button id="rename-btn">Rename</button>
<button id="delete-btn">Delete</button>
</div>
<div class="pathbar" id="pathbar"></div>
<div class="list" id="file-list"></div>
<div class="status" id="status">Ready</div>
</div>
</div>
</section>
<section class="window" id="browser-window" style="top:85px;left:110px;z-index:4">
<div class="titlebar"><span>🌐</span><span class="title">Browser</span>
<div class="controls"><button class="min" data-min="browser-window"></button><button class="max" data-max="browser-window"></button><button class="close" data-close="browser-window"></button></div>
</div>
<div class="browser-toolbar">
<input id="address" value="https://example.com" />
<button id="go-btn">Go</button>
</div>
<iframe id="browser-frame" src="https://example.com"></iframe>
</section>
<section class="window" id="editor-window" style="top:120px;left:160px;z-index:3;height:min(560px,calc(100vh - 150px))">
<div class="titlebar"><span>📝</span><span class="title">Text Editor</span>
<div class="controls"><button class="min" data-min="editor-window"></button><button class="max" data-max="editor-window"></button><button class="close" data-close="editor-window"></button></div>
</div>
<div class="editor-toolbar">
<input id="note-name" value="note.txt" />
<button id="save-note">Save</button>
<button id="load-note">Load</button>
</div>
<textarea id="editor">Write something here...</textarea>
</section>
</main>
<footer class="taskbar">
<div class="task-left">
<div class="start">Start</div>
<button class="task-app" data-open="explorer" title="Explorer">📁</button>
<button class="task-app" data-open="browser" title="Browser">🌐</button>
<button class="task-app" data-open="editor" title="Text Editor">📝</button>
</div>
<div id="clock"></div>
</footer>
<script>
const fs = { type:'folder', children:{ Music:{ type:'folder', children:{
NewJeans:{ type:'folder', children:{
'Attention.mp3':{type:'file',size:'7.0 MB'}, 'Hype Boy.mp3':{type:'file',size:'6.8 MB'}, 'Ditto.mp3':{type:'file',size:'7.2 MB'}, 'OMG.mp3':{type:'file',size:'6.5 MB'}, 'Super Shy.mp3':{type:'file',size:'6.2 MB'}
}},
Blackpink:{ type:'folder', children:{
'DDU-DU DDU-DU.mp3':{type:'file',size:'7.3 MB'}, 'How You Like That.mp3':{type:'file',size:'7.1 MB'}, 'Kill This Love.mp3':{type:'file',size:'7.0 MB'}, 'Pink Venom.mp3':{type:'file',size:'6.9 MB'}, 'Shut Down.mp3':{type:'file',size:'6.7 MB'}
}}
}}} };
const windows = {
explorer: document.getElementById('explorer-window'),
browser: document.getElementById('browser-window'),
editor: document.getElementById('editor-window')
};
let z = 10;
const bringFront = (el) => { el.style.zIndex = ++z; };
const showWindow = (name) => { const el = windows[name]; el.classList.add('visible'); bringFront(el); };
document.querySelectorAll('[data-open]').forEach(el => el.onclick = () => showWindow(el.dataset.open));
document.querySelectorAll('[data-close]').forEach(el => el.onclick = () => el.closest('.window').classList.remove('visible'));
document.querySelectorAll('[data-min]').forEach(el => el.onclick = () => el.closest('.window').classList.remove('visible'));
document.querySelectorAll('[data-max]').forEach(el => el.onclick = () => {
const w = el.closest('.window');
if (!w.dataset.maxed) { w.dataset.maxed='1'; w.dataset.prev=w.style.cssText; w.style.top='8px'; w.style.left='8px'; w.style.width='calc(100vw - 16px)'; w.style.height='calc(100vh - 74px)'; }
else { delete w.dataset.maxed; w.style.cssText = w.dataset.prev; w.classList.add('visible'); }
bringFront(w);
});
document.querySelectorAll('.window').forEach(w => w.addEventListener('mousedown', () => bringFront(w)));
// Browser app
const frame = document.getElementById('browser-frame');
const address = document.getElementById('address');
document.getElementById('go-btn').onclick = () => {
let url = address.value.trim();
if (!/^https?:\/\//i.test(url)) url = `https://${url}`;
address.value = url;
frame.src = url;
};
// Text editor app
const editor = document.getElementById('editor');
const noteName = document.getElementById('note-name');
document.getElementById('save-note').onclick = () => {
localStorage.setItem(`note:${noteName.value}`, editor.value);
alert('Saved.');
};
document.getElementById('load-note').onclick = () => {
const content = localStorage.getItem(`note:${noteName.value}`);
editor.value = content ?? '';
};
// Explorer app
const fileList = document.getElementById('file-list');
const pathBar = document.getElementById('pathbar');
const status = document.getElementById('status');
let currentPath=['/']; let selected=null;
const normalize = (path) => path === '/' ? ['/'] : ['/', ...path.split('/').filter(Boolean)];
function getNode(pathArr){ let node=fs; for(const part of pathArr.slice(1)){ if(!node.children?.[part]) return null; node=node.children[part]; } return node; }
function openPath(path){ const target=normalize(path); if(getNode(target)?.type!=='folder') return; currentPath=target; selected=null; render(); }
function renderPath(){ pathBar.innerHTML=''; let built=''; currentPath.forEach((part,i)=>{
built = i===0 ? '/' : `${built==='/'?'':built}/${part}`;
const b=document.createElement('button'); b.className='crumb'; b.textContent=i===0?'Computer':part; b.onclick=()=>openPath(built); pathBar.appendChild(b);
if(i<currentPath.length-1) pathBar.append('');
}); }
function renderList(){
const folder=getNode(currentPath); const entries=Object.entries(folder.children||{}).sort((a,b)=>a[0].localeCompare(b[0]));
fileList.innerHTML='';
for(const [name,node] of entries){
const el=document.createElement('article');
el.className=`item${selected===name?' sel':''}`;
el.innerHTML=`<div>${node.type==='folder'?'📁':'🎵'} ${name}</div><div class="meta">${node.type==='folder'?'File Folder':node.size}</div>`;
el.onclick=()=>{selected=name; renderList(); status.textContent=`${name} selected`;};
el.ondblclick=()=>{ if(node.type==='folder') openPath(`${currentPath.join('/').replace('//','/')}/${name}`); else status.textContent=`Now playing: ${name}`; };
fileList.appendChild(el);
}
status.textContent=`${entries.length} item(s)`;
}
document.getElementById('up-btn').onclick=()=>{ if(currentPath.length>1){ currentPath=currentPath.slice(0,-1); selected=null; render(); } };
document.getElementById('new-folder-btn').onclick=()=>{ const name=prompt('Folder name?'); if(!name) return; const n=getNode(currentPath); if(n.children[name]) return alert('Name already exists.'); n.children[name]={type:'folder',children:{}}; render(); };
document.getElementById('new-file-btn').onclick=()=>{ const name=prompt('File name?','New File.txt'); if(!name) return; const n=getNode(currentPath); if(n.children[name]) return alert('Name already exists.'); n.children[name]={type:'file',size:'1 KB'}; render(); };
document.getElementById('rename-btn').onclick=()=>{ if(!selected) return alert('Select an item first.'); const n=getNode(currentPath); const next=prompt('Rename to?',selected); if(!next||next===selected) return; if(n.children[next]) return alert('Name already exists.'); n.children[next]=n.children[selected]; delete n.children[selected]; selected=next; render(); };
document.getElementById('delete-btn').onclick=()=>{ if(!selected) return alert('Select an item first.'); const n=getNode(currentPath); delete n.children[selected]; selected=null; render(); };
document.querySelectorAll('.node').forEach(n=>n.onclick=()=>openPath(n.dataset.path));
function render(){ renderPath(); renderList(); }
render();
// clock
const clock = document.getElementById('clock');
const tick = () => clock.textContent = new Date().toLocaleString();
tick(); setInterval(tick, 1000);
</script>
</body>
</html>