Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ Code examples that accompany various MDN DOM and Web API documentation pages.

- The "edit-context" directory contains examples demonstrating the [EditContext API](https://developer.mozilla.org/docs/Web/API/EditContext_API). See the [list of examples](https://github.com/mdn/dom-examples/tree/main/edit-context/).

- The "filesystemobserver" directory contains an example demonstrating usage of the [FileSystemObserver](https://developer.mozilla.org/docs/Web/API/FileSystemObserver) API ([run the example live](https://mdn.github.io/dom-examples/filesystemobserver/)). This example was originally published on Glitch as [File System Observer Demo](https://file-system-observer.glitch.me/) by [Thomas Steiner](https://front-end.social/@tomayac@toot.cafe).

- The "fullscreen-api" directory is for examples and demos of the [Fullscreen API](https://wiki.developer.mozilla.org/docs/Web/API/Fullscreen_API). Run the [example live](https://mdn.github.io/dom-examples/fullscreen-api/).

- The "history-api" directory contains an example that demonstrates the [History API](https://developer.mozilla.org/docs/Web/API/History_API). [View the demo live](https://mdn.github.io/dom-examples/history-api/).
Expand Down
27 changes: 27 additions & 0 deletions filesystemobserver/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script>
if (!isSecureContext) location.protocol = "https:";
</script>
<script src="random.js" type="module"></script>
<link rel="stylesheet" href="style.css" />

<link
rel="icon"
href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>📁</text></svg>" />
<title>File System Observer Demo</title>
</head>
<body>
<h1>File System Observer Demo</h1>
<h2>🎲 Random file operations log</h2>
<p>Log of randomly created, deleted, or modified files.</p>
<div id="log"></div>
<h2>👀 File system observer log</h2>
<p>Log of observed file system changes.</p>
<div id="observer"></div>
<pre></pre>
</body>
</html>
45 changes: 45 additions & 0 deletions filesystemobserver/observer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
function logMessage(message) {
const logContainer = document.getElementById("observer");
const logEntry = document.createElement("div");
logEntry.className = "log-entry";
logEntry.textContent = message;

logContainer.appendChild(logEntry);

// Ensure we only keep the last 10 log entries
while (logContainer.children.length > 10) {
logContainer.removeChild(logContainer.firstChild);
}

// Scroll to the bottom of the log
logContainer.scrollTop = logContainer.scrollHeight;
}

const callback = async (records, observer) => {
const icons = {
created: "✅",
appeared: "✅",
modified: "📝",
deleted: "🗑️",
disappeared: "🗑️",
};
for (const record of records) {
console.log(record);
if (record.changedHandle && record.changedHandle.name.endsWith(".crswap")) {
continue;
}
if (!record.changedHandle) {
continue;
}
logMessage(
`The ${record.changedHandle.kind} "${record.changedHandle.name}" ${
["modified", "deleted", "created"].includes(record.type) ? "was " : ""
}${icons[record.type]} ${record.type}`
);
}
};

(async () => {
const observer = new self.FileSystemObserver(callback);
await observer.observe(await navigator.storage.getDirectory());
})();
98 changes: 98 additions & 0 deletions filesystemobserver/random.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
(async () => {
const rootHandle = await navigator.storage.getDirectory();
await rootHandle.remove({ recursive: true });
await startObserver();

async function startObserver() {
if ("FileSystemObserver" in self) {
await import("./observer.js");
demoOPFS();
} else {
document.querySelector("pre").textContent =
"😕 Your browser does not support the File System Observer API";
}
}

async function demoOPFS() {
const loremIpsum =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.";

function logMessage(message) {
const logContainer = document.getElementById("log");
const logEntry = document.createElement("div");
logEntry.className = "log-entry";
logEntry.textContent = message;

logContainer.appendChild(logEntry);

// Ensure we only keep the last 10 log entries
while (logContainer.children.length > 10) {
logContainer.removeChild(logContainer.firstChild);
}

// Scroll to the bottom of the log
logContainer.scrollTop = logContainer.scrollHeight;
}

async function getRandomFileHandle() {
const files = [];
for await (const entry of rootHandle.values()) {
if (entry.kind === "file") {
files.push(entry);
}
}
if (files.length === 0) {
return null;
}
const randomIndex = Math.floor(Math.random() * files.length);
return files[randomIndex];
}

async function createFile() {
const fileName = `file_${Date.now()}.txt`;
const fileHandle = await rootHandle.getFileHandle(fileName, {
create: true,
});
const writable = await fileHandle.createWritable();
const text = loremIpsum.repeat(Math.floor(Math.random() * 20) + 1);
await writable.write(text);
await writable.close();
logMessage(`✅ Created file "${fileName}"`);
}

async function deleteFile() {
const fileHandle = await getRandomFileHandle();
if (!fileHandle) {
return;
}
await rootHandle.removeEntry(fileHandle.name);
logMessage(`🗑️ Deleted file "${fileHandle.name}"`);
}

async function modifyFile() {
const fileHandle = await getRandomFileHandle();
if (!fileHandle) {
return;
}
const writable = await fileHandle.createWritable();
const text = loremIpsum.repeat(Math.floor(Math.random() * 20) + 1);
await writable.write(text);
await writable.close();
logMessage(`📝 Modified file "${fileHandle.name}"`);
}

async function performRandomOperation() {
const operations = [createFile, deleteFile, modifyFile];
const randomOperation =
operations[Math.floor(Math.random() * operations.length)];
try {
await randomOperation();
} catch {
// No op
}
}

// Perform random operations in an interval
setInterval(performRandomOperation, 2000); // every 2 seconds
}
})();
22 changes: 22 additions & 0 deletions filesystemobserver/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
:root {
color-scheme: dark light;
}

html {
box-sizing: border-box;
}

*,
*:before,
*:after {
box-sizing: inherit;
}

body {
margin: 1rem;
font-family: system-ui, sans-serif;
}

pre {
color: red;
}