feat: Add initial mess
This commit is contained in:
		
							parent
							
								
									1988edaafe
								
							
						
					
					
						commit
						59fa42e6c0
					
				
							
								
								
									
										
											BIN
										
									
								
								icons/folder.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								icons/folder.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 1.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								icons/notepad.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								icons/notepad.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 843 B | 
							
								
								
									
										
											BIN
										
									
								
								icons/trash.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								icons/trash.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 671 B | 
							
								
								
									
										15
									
								
								index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								index.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | |||||||
|  | <!DOCTYPE html> | ||||||
|  | <html lang="en"> | ||||||
|  | <head> | ||||||
|  | 	<meta charset="UTF-8" /> | ||||||
|  | 	<meta name="viewport" content="width=device-width, initial-scale=1" /> | ||||||
|  | 	<link rel="stylesheet" href="styles.css" /> | ||||||
|  | 	<title>My Desktop Page</title> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  | 	<div class="desktop"> | ||||||
|  | 	</div> | ||||||
|  | 	<script src="script.js"></script> | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
|  | 
 | ||||||
							
								
								
									
										259
									
								
								script.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										259
									
								
								script.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,259 @@ | |||||||
|  | let highestZIndex = 100; | ||||||
|  | 
 | ||||||
|  | function init() { | ||||||
|  | 	const desktop = document.querySelector(".desktop"); | ||||||
|  | 
 | ||||||
|  | 	const shortcutData = [ | ||||||
|  | 		{ | ||||||
|  | 			label: "My Files", | ||||||
|  | 			icon: "icons/folder.png", | ||||||
|  | 			width: 500, | ||||||
|  | 			height: 400, | ||||||
|  | 			action: () => | ||||||
|  | 			openNewWindow( | ||||||
|  | 				"My Files", | ||||||
|  | 				`<iframe src="https://98.js.org"></iframe>`, | ||||||
|  | 				true, | ||||||
|  | 				500, | ||||||
|  | 				400 | ||||||
|  | 			) | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			label: "Notes", | ||||||
|  | 			icon: "icons/notepad.png", | ||||||
|  | 			width: 400, | ||||||
|  | 			height: 300, | ||||||
|  | 			action: () => | ||||||
|  | 			openNewWindow( | ||||||
|  | 				"Notes", | ||||||
|  | 				`<textarea>hello...</textarea>`, | ||||||
|  | 				true, | ||||||
|  | 				400, | ||||||
|  | 				300 | ||||||
|  | 			) | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			label: "Recycle Bin", | ||||||
|  | 			icon: "icons/trash.png", | ||||||
|  | 			width: 300, | ||||||
|  | 			height: 200, | ||||||
|  | 			action: () => | ||||||
|  | 			openNewWindow( | ||||||
|  | 				"Recycle Bin", | ||||||
|  | 				`<p>Your trash goes here.</p>`, | ||||||
|  | 				false, | ||||||
|  | 				300, | ||||||
|  | 				200 | ||||||
|  | 			) | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			label: "CSS Art", | ||||||
|  | 			icon: "icons/folder.png", | ||||||
|  | 			width: 600, | ||||||
|  | 			height: 500, | ||||||
|  | 			action: () => | ||||||
|  | 			openNewWindow( | ||||||
|  | 				"CSS Art", | ||||||
|  | 				`<iframe src="https://tilde.town/~dozens/cssart/quarters.html"></iframe>`, | ||||||
|  | 				true, | ||||||
|  | 				600, | ||||||
|  | 				600 | ||||||
|  | 			) | ||||||
|  | 		} | ||||||
|  | 	]; | ||||||
|  | 
 | ||||||
|  | 	shortcutData.forEach(({ label, icon, action }) => { | ||||||
|  | 		const shortcut = document.createElement("div"); | ||||||
|  | 		shortcut.className = "shortcut"; | ||||||
|  | 
 | ||||||
|  | 		shortcut.innerHTML = ` | ||||||
|  | 			<img src="${icon}" alt="${label}" /> | ||||||
|  | 			<span>${label}</span> | ||||||
|  | 		`;
 | ||||||
|  | 
 | ||||||
|  | 		shortcut.addEventListener("dblclick", action); | ||||||
|  | 		document.querySelector(".desktop").appendChild(shortcut); | ||||||
|  | 	}); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | init(); | ||||||
|  | 
 | ||||||
|  | function openNewWindow(title, contentHTML, fullSizeContent = false, width = 300, height = 200) { | ||||||
|  | 	const newWin = document.createElement("div"); | ||||||
|  | 	newWin.className = "window"; | ||||||
|  | 
 | ||||||
|  | 	const viewportWidth = window.innerWidth; | ||||||
|  | 	const viewportHeight = window.innerHeight; | ||||||
|  | 	const randomLeft = Math.floor(Math.random() * (viewportWidth - 320)); | ||||||
|  | 	const randomTop = Math.floor(Math.random() * (viewportHeight - 200)); | ||||||
|  | 	newWin.style.left = `${randomLeft}px`; | ||||||
|  | 	newWin.style.top = `${randomTop}px`; | ||||||
|  | 
 | ||||||
|  | 	newWin.innerHTML = ` | ||||||
|  | 	  <div class="titlebar"> | ||||||
|  | 		<div class="title">${title}</div> | ||||||
|  | 		<button class="close-btn" aria-label="Close window">×</button> | ||||||
|  | 	  </div> | ||||||
|  | 	  <div class="content">${contentHTML}</div> | ||||||
|  | 	`;
 | ||||||
|  | 
 | ||||||
|  | 	const resizers = ['nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w']; | ||||||
|  | 	resizers.forEach(pos => { | ||||||
|  | 		const resizer = document.createElement("div"); | ||||||
|  | 		resizer.className = `resizer ${pos}`; | ||||||
|  | 		newWin.appendChild(resizer); | ||||||
|  | 	}); | ||||||
|  | 
 | ||||||
|  | 	document.body.appendChild(newWin); | ||||||
|  | 
 | ||||||
|  | 	bringToFront(newWin); | ||||||
|  | 
 | ||||||
|  | 	const content = newWin.querySelector(".content"); | ||||||
|  | 	content.style.width = `${width}px`; | ||||||
|  | 	content.style.height = `${height}px`; | ||||||
|  | 
 | ||||||
|  | 	if (fullSizeContent) { | ||||||
|  | 		content.style.padding = "0"; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Bring window to front when clicked
 | ||||||
|  | 	newWin.addEventListener("mousedown", () => { | ||||||
|  | 		bringToFront(newWin); | ||||||
|  | 	}); | ||||||
|  | 
 | ||||||
|  | 	// Dragging logic
 | ||||||
|  | 	const titlebar = newWin.querySelector(".titlebar"); | ||||||
|  | 	let isDragging = false; | ||||||
|  | 	let offsetX = 0; | ||||||
|  | 	let offsetY = 0; | ||||||
|  | 
 | ||||||
|  | 	titlebar.addEventListener("mousedown", (e) => { | ||||||
|  | 		if (e.target.classList.contains("close-btn")) return; | ||||||
|  | 		isDragging = true; | ||||||
|  | 		const rect = newWin.getBoundingClientRect(); | ||||||
|  | 		offsetX = e.clientX - rect.left; | ||||||
|  | 		offsetY = e.clientY - rect.top; | ||||||
|  | 		document.body.style.userSelect = 'none'; | ||||||
|  | 	}); | ||||||
|  | 
 | ||||||
|  | 	document.addEventListener("mousemove", (e) => { | ||||||
|  | 		if (!isDragging) return; | ||||||
|  | 		newWin.style.left = `${e.clientX - offsetX}px`; | ||||||
|  | 		newWin.style.top = `${e.clientY - offsetY}px`; | ||||||
|  | 	}); | ||||||
|  | 
 | ||||||
|  | 	document.addEventListener("mouseup", () => { | ||||||
|  | 		if (isDragging) { | ||||||
|  | 			isDragging = false; | ||||||
|  | 			document.body.style.userSelect = ''; | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  | 
 | ||||||
|  | 	// Close button logic
 | ||||||
|  | 	const closeBtn = newWin.querySelector(".close-btn"); | ||||||
|  | 	closeBtn.addEventListener("click", () => { | ||||||
|  | 		newWin.remove(); | ||||||
|  | 	}); | ||||||
|  | 
 | ||||||
|  | 	let isResizing = false; | ||||||
|  | 	let currentResizer = null; | ||||||
|  | 
 | ||||||
|  | 	const minWidth = 200; | ||||||
|  | 	const minHeight = 150; | ||||||
|  | 
 | ||||||
|  | 	const startResize = (e, resizer) => { | ||||||
|  | 		e.preventDefault(); | ||||||
|  | 		isResizing = true; | ||||||
|  | 		currentResizer = resizer; | ||||||
|  | 
 | ||||||
|  | 		const rect = newWin.getBoundingClientRect(); | ||||||
|  | 		newWin.dataset.startX = e.clientX; | ||||||
|  | 		newWin.dataset.startY = e.clientY; | ||||||
|  | 		newWin.dataset.startWidth = rect.width; | ||||||
|  | 		newWin.dataset.startHeight = rect.height; | ||||||
|  | 		newWin.dataset.startLeft = rect.left; | ||||||
|  | 		newWin.dataset.startTop = rect.top; | ||||||
|  | 
 | ||||||
|  | 		document.body.style.userSelect = "none"; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	const onMouseMove = (e) => { | ||||||
|  | 		if (!isResizing || !currentResizer) return; | ||||||
|  | 
 | ||||||
|  | 		const dx = e.clientX - newWin.dataset.startX; | ||||||
|  | 		const dy = e.clientY - newWin.dataset.startY; | ||||||
|  | 
 | ||||||
|  | 		let newWidth = parseFloat(newWin.dataset.startWidth); | ||||||
|  | 		let newHeight = parseFloat(newWin.dataset.startHeight); | ||||||
|  | 		let newLeft = parseFloat(newWin.dataset.startLeft); | ||||||
|  | 		let newTop = parseFloat(newWin.dataset.startTop); | ||||||
|  | 
 | ||||||
|  | 		switch (currentResizer) { | ||||||
|  | 			case 'e': | ||||||
|  | 				newWidth += dx; | ||||||
|  | 				break; | ||||||
|  | 			case 's': | ||||||
|  | 				newHeight += dy; | ||||||
|  | 				break; | ||||||
|  | 			case 'se': | ||||||
|  | 				newWidth += dx; | ||||||
|  | 				newHeight += dy; | ||||||
|  | 				break; | ||||||
|  | 			case 'w': | ||||||
|  | 				newWidth -= dx; | ||||||
|  | 				newLeft += dx; | ||||||
|  | 				break; | ||||||
|  | 			case 'n': | ||||||
|  | 				newHeight -= dy; | ||||||
|  | 				newTop += dy; | ||||||
|  | 				break; | ||||||
|  | 			case 'nw': | ||||||
|  | 				newWidth -= dx; | ||||||
|  | 				newLeft += dx; | ||||||
|  | 				newHeight -= dy; | ||||||
|  | 				newTop += dy; | ||||||
|  | 				break; | ||||||
|  | 			case 'ne': | ||||||
|  | 				newWidth += dx; | ||||||
|  | 				newHeight -= dy; | ||||||
|  | 				newTop += dy; | ||||||
|  | 				break; | ||||||
|  | 			case 'sw': | ||||||
|  | 				newWidth -= dx; | ||||||
|  | 				newLeft += dx; | ||||||
|  | 				newHeight += dy; | ||||||
|  | 				break; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (newWidth >= minWidth) { | ||||||
|  | 			newWin.style.width = `${newWidth}px`; | ||||||
|  | 			newWin.style.left = `${newLeft}px`; | ||||||
|  | 			content.style.width = `${newWidth}px`; | ||||||
|  | 		} | ||||||
|  | 		if (newHeight >= minHeight) { | ||||||
|  | 			newWin.style.height = `${newHeight}px`; | ||||||
|  | 			newWin.style.top = `${newTop}px`; | ||||||
|  | 			content.style.height = `${newHeight - titlebar.offsetHeight}px`; | ||||||
|  | 		} | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	const stopResize = () => { | ||||||
|  | 		isResizing = false; | ||||||
|  | 		currentResizer = null; | ||||||
|  | 		document.body.style.userSelect = ""; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	resizers.forEach(pos => { | ||||||
|  | 		const el = newWin.querySelector(`.resizer.${pos}`); | ||||||
|  | 		el.addEventListener("mousedown", (e) => startResize(e, pos)); | ||||||
|  | 	}); | ||||||
|  | 
 | ||||||
|  | 	document.addEventListener("mousemove", onMouseMove); | ||||||
|  | 	document.addEventListener("mouseup", stopResize); | ||||||
|  | 
 | ||||||
|  | 	function bringToFront(win) { | ||||||
|  | 		highestZIndex++; | ||||||
|  | 		win.style.zIndex = highestZIndex; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
							
								
								
									
										156
									
								
								styles.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								styles.css
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,156 @@ | |||||||
|  | body { | ||||||
|  | 	font-family: Tahoma, sans-serif; | ||||||
|  | 	margin: 2rem; | ||||||
|  | 	background-color: #e0b0ff; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .window { | ||||||
|  | 	position: absolute; | ||||||
|  | 	border: 1px solid #555; | ||||||
|  | 	border-radius: 10px; | ||||||
|  | 	box-shadow:  | ||||||
|  | 		0 4px 8px rgba(0, 0, 0, 0.3),   /* Soft outer shadow */ | ||||||
|  | 		inset 0 0 5px rgba(255, 255, 255, 0.1); /* Inner highlight for 3D */ | ||||||
|  | 	overflow: hidden; | ||||||
|  | 	background-color: #f0f0f0; | ||||||
|  | 	font-family: sans-serif; | ||||||
|  | 	cursor: default; | ||||||
|  | 	display: flex; | ||||||
|  | 	flex-direction: column; | ||||||
|  | 	height: auto; /* allow flexible height */ | ||||||
|  | 	box-sizing: border-box; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .titlebar .title { | ||||||
|  |   flex: 1; | ||||||
|  |   white-space: nowrap; | ||||||
|  |   overflow: hidden; | ||||||
|  |   text-overflow: ellipsis; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .titlebar { | ||||||
|  | 	width: 100%; | ||||||
|  | 	height: 30px; | ||||||
|  | 	background: linear-gradient(to bottom, #8a2be2, #6a1dbf); | ||||||
|  | 	color: white; | ||||||
|  | 	display: flex; | ||||||
|  | 	justify-content: space-between; | ||||||
|  | 	align-items: center; | ||||||
|  | 	padding-left: 10px; | ||||||
|  | 	box-sizing: border-box; | ||||||
|  | 	cursor: move; | ||||||
|  | 	border-top-left-radius: 10px; | ||||||
|  | 	border-top-right-radius: 10px; | ||||||
|  | 	box-shadow: inset 0 -1px 1px rgba(255, 255, 255, 0.3); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .content { | ||||||
|  |   padding: 10px; | ||||||
|  |   background: #C0C0C0; | ||||||
|  |   overflow: auto; | ||||||
|  |   box-sizing: border-box; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .close-btn { | ||||||
|  | 	background: transparent; | ||||||
|  | 	border: none; | ||||||
|  | 	color: white; | ||||||
|  | 	font-size: 20px; | ||||||
|  | 	margin-right: 8px; | ||||||
|  | 	cursor: pointer; | ||||||
|  | 	transition: color 0.2s ease; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .close-btn:hover { | ||||||
|  | 	color: #ffaaaa; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .desktop { | ||||||
|  | 	display: grid; | ||||||
|  | 	grid-template-columns: repeat(auto-fill, 80px); | ||||||
|  | 	grid-auto-rows: 100px; | ||||||
|  | 	gap: 20px; | ||||||
|  | 	padding: 20px; | ||||||
|  | 	position: absolute; | ||||||
|  | 	top: 0; | ||||||
|  | 	left: 0; | ||||||
|  | 	z-index: 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .shortcut { | ||||||
|  | 	width: 80px; | ||||||
|  | 	text-align: center; | ||||||
|  | 	color: black; | ||||||
|  | 	font-size: 12px; | ||||||
|  | 	font-family: sans-serif; | ||||||
|  | 	margin: 10px; | ||||||
|  | 	cursor: pointer; | ||||||
|  | 	user-select: none; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .shortcut img { | ||||||
|  | 	width: 32px; | ||||||
|  | 	height: 32px; | ||||||
|  | 	display: block; | ||||||
|  | 	margin: 0 auto 5px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .shortcut span { | ||||||
|  | 	display: block; | ||||||
|  | 	text-shadow: 1px 1px 2px white; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .content textarea { | ||||||
|  | 	font-family: monospace; | ||||||
|  | 	padding: 8px; | ||||||
|  | 	resize: none; | ||||||
|  | 	outline: none; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .content iframe, | ||||||
|  | .content textarea { | ||||||
|  | 	width: 100%; | ||||||
|  | 	height: 100%; | ||||||
|  | 	border-radius: 6px; | ||||||
|  | 	border: none; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .window .resizer { | ||||||
|  | 	position: absolute; | ||||||
|  | 	background: transparent; | ||||||
|  | 	z-index: 10; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* Corners */ | ||||||
|  | .window .resizer.nw, .window .resizer.ne, | ||||||
|  | .window .resizer.sw, .window .resizer.se { | ||||||
|  | 	width: 10px; | ||||||
|  | 	height: 10px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .window .resizer.nw { top: 0; left: 0; cursor: nw-resize; } | ||||||
|  | .window .resizer.ne { top: 0; right: 0; cursor: ne-resize; } | ||||||
|  | .window .resizer.sw { bottom: 0; left: 0; cursor: sw-resize; } | ||||||
|  | .window .resizer.se { bottom: 0; right: 0; cursor: se-resize; } | ||||||
|  | 
 | ||||||
|  | /* Sides */ | ||||||
|  | .window .resizer.n, .window .resizer.s { | ||||||
|  | 	height: 6px; | ||||||
|  | 	left: 0; | ||||||
|  | 	right: 0; | ||||||
|  | 	cursor: ns-resize; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .window .resizer.n { top: 0; } | ||||||
|  | .window .resizer.s { bottom: 0; } | ||||||
|  | 
 | ||||||
|  | .window .resizer.e, .window .resizer.w { | ||||||
|  | 	width: 6px; | ||||||
|  | 	top: 0; | ||||||
|  | 	bottom: 0; | ||||||
|  | 	cursor: ew-resize; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .window .resizer.e { right: 0; } | ||||||
|  | .window .resizer.w { left: 0; } | ||||||
|  | 
 | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user