Web-Based Fake Operating System Project

Table of Contents

  1. Introduction
  2. Project Structure
  3. Key Features
  4. HTML Structure
  5. CSS Styling
  6. JavaScript Functionality
  7. Application Management
  8. Error Handling and Debugging
  9. Conclusion

Introduction

This project aims to create an extensive fake operating system (OS) within a web browser. It includes features such as draggable and resizable application windows, a taskbar with a clock, and basic window management (minimize, maximize, and close). The purpose of this project is to simulate the look and feel of a real OS using web technologies like HTML, CSS, and JavaScript.

Project Structure

The project is organized into several folders and files:

project-root/
├── apps/
│   ├── terminal/
│   │   ├── index.html
│   │   ├── terminal.js
│   │   └── styles.css
│   └── file-explorer/
│       ├── index.html
│       ├── file-explorer.js
│       └── styles.css
├── scripts/
│   ├── taskbar.js
│   ├── windowManagement.js
│   └── appsConfig.js
├── styles/
│   └── main.css
└── index.html

Key Features

  • Draggable and Resizable Windows: Users can drag and resize application windows.
  • Taskbar: Contains app icons and a clock.
  • Dynamic Window Initialization: Windows are dynamically created and initialized.
  • Focus Management: Clicking on a window brings it to the front.

HTML Structure

The main index.html file serves as the entry point for the fake OS:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Fake Operating System</title>
    <link rel="stylesheet" href="styles/main.css">
</head>
<body>
    <div id="taskbar"></div>
    <script type="module" src="scripts/taskbar.js"></script>
</body>
</html>

CSS Styling

Main Styles (main.css)

The main CSS file styles the overall layout, taskbar, and basic window appearance:

body {
    margin: 0;
    font-family: Arial, sans-serif;
}

#taskbar {
    position: fixed;
    bottom: 0;
    width: 100%;
    background-color: #333;
    color: #fff;
    display: flex;
    justify-content: space-between;
    padding: 5px 10px;
}

/* ... additional styles ... */

JavaScript Functionality

Taskbar Initialization

The taskbar.js file manages the taskbar and initializes application icons and the clock:

// taskbar.js

import { appsConfig } from './appsConfig.js';
import { initializeWindow, focusWindow } from './windowManagement.js';

document.addEventListener("DOMContentLoaded", function() {
    const taskbar = document.getElementById('taskbar');

    appsConfig.forEach(app => {
        const button = document.createElement('button');
        button.classList.add('taskbar-app');
        button.id = `${app.id}-icon`;
        button.innerHTML = `<img src="${app.icon}" alt="${app.name}">`;
        button.addEventListener('click', () => toggleAppWindow(app));
        taskbar.appendChild(button);
    });

    const clock = document.createElement('div');
    clock.classList.add('taskbar-clock');
    taskbar.appendChild(clock);
    updateClock(clock);
    setInterval(() => updateClock(clock), 1000);
});

/* ... additional functions ... */

Window Management

The windowManagement.js file includes functions to initialize, drag, resize, and focus windows:

// windowManagement.js

export function initializeWindow(appId, appName) {
    const appWindow = document.createElement('div');
    appWindow.id = `${appId}-window`;
    appWindow.classList.add('window');
    
    const titleBar = document.createElement('div');
    titleBar.classList.add('window-titlebar');
    titleBar.innerHTML = `
        <span>${appName}</span>
        <div class="window-controls">
            <button class="minimize-btn" onclick="minimizeWindow('${appId}-window')">-</button>
            <button class="close-btn" onclick="closeWindow('${appId}-window', '${appId}-icon')">x</button>
        </div>
    `;
    
    appWindow.appendChild(titleBar);
    document.body.appendChild(appWindow);
    
    makeWindowDraggableAndResizable(appWindow);
    centerWindow(appWindow);
    focusWindow(appWindow);
}

export function makeWindowDraggableAndResizable(windowElement) {
    let isDragging = false;
    let isResizing = false;
    let startX, startY, startWidth, startHeight;

    const titleBar = windowElement.querySelector('.window-titlebar');
    const resizeHandle = document.createElement('div');
    resizeHandle.classList.add('resize-handle', 'resize-bottom-right');
    windowElement.appendChild(resizeHandle);

    titleBar.addEventListener('mousedown', startDrag);
    windowElement.addEventListener('mousedown', () => focusWindow(windowElement));
    resizeHandle.addEventListener('mousedown', startResize);

    function startDrag(e) {
        isDragging = true;
        startX = e.clientX;
        startY = e.clientY;
        
        document.addEventListener('mousemove', drag);
        document.addEventListener('mouseup', stopDrag);
    }

    function drag(e) {
        if (!isDragging) return;
        windowElement.style.left = `${windowElement.offsetLeft + e.clientX - startX}px`;
        windowElement.style.top = `${windowElement.offsetTop + e.clientY - startY}px`;
        startX = e.clientX;
        startY = e.clientY;
    }

    function stopDrag() {
        isDragging = false;
        document.removeEventListener('mousemove', drag);
        document.removeEventListener('mouseup', stopDrag);
    }

    function startResize(e) {
        isResizing = true;
        startX = e.clientX;
        startY = e.clientY;
        startWidth = windowElement.clientWidth;
        startHeight = windowElement.clientHeight;
        
        document.addEventListener('mousemove', resize);
        document.addEventListener('mouseup', stopResize);
    }

    function resize(e) {
        if (!isResizing) return;
        
        windowElement.style.width = `${startWidth + e.clientX - startX}px`;
        windowElement.style.height = `${startHeight + e.clientY - startY}px`;
    }

    function stopResize() {
        isResizing = false;
        document.removeEventListener('mousemove', resize);
        document.removeEventListener('mouseup', stopResize);
    }
}

export function centerWindow(windowElement) {
    const rect = windowElement.getBoundingClientRect();
    const winWidth = window.innerWidth;
    const winHeight = window.innerHeight;
    
    windowElement.style.left = `${(winWidth - rect.width) / 2}px`;
    windowElement.style.top = `${(winHeight - rect.height) / 2}px`;
}

export function focusWindow(windowElement) {
    windowElement.style.zIndex = ++zIndexCounter;
}

Clock and Taskbar

The taskbar.js file also manages the taskbar clock and updates it every second:

function updateClock(clock) {
    const now = new Date();
    const time = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
    const date = now.toLocaleDateString();
    clock.innerHTML = `<time>${time}</time><date>${date}</date>`;
}

Application Management

The appsConfig.js file contains the configuration for different applications available in the fake OS:

// appsConfig.js

export const appsConfig = [
    {
        id: 'terminal',
        name: 'Terminal',
        icon: 'icons/terminal.png',
        html: 'apps/terminal/index.html'
    },
    {
        id: 'file-explorer',
        name: 'File Explorer',
        icon: 'icons/file-explorer.png',
        html: 'apps/file-explorer/index.html'
    }
];

Error Handling and Debugging

When creating and managing dynamic content, errors can occur. Ensure to add proper error handling mechanisms:

// windowManagement.js

fetch(`apps/${appId}/index.html`)
    .then(response => response.text())
    .then(data => {
        appWindow.innerHTML = data;
        initializeWindow(appId, appName);
    })
    .catch(error => {
        console.error(`Error loading HTML for ${appName}:`, error);
        appWindow.innerHTML = `<p>Error loading ${appName}. Please try again later.</p>`;
    });

Conclusion

This project demonstrates how to create a dynamic, web-based fake operating system with features such as draggable and resizable windows,