cybrkyd

My quiet writing area: Version 2

 Tue, 08 Jul 2025 07:53 UTC
My quiet writing area: Version 2
Image: CC BY 4.0 by cybrkyd

Welcome to version 2.0 of The Quiet Writing Area. This version is capable of importing and exporting text files, with the option to save files with a custom name and extension. Since the default export file name is quiet-writing.txt, a customised file name can be entered via a small form text field if preferred.

Given that Chrome/Edge and derivatives are the only browsers which support File System Access API, I have provided the import/export functionality via traditional methods, which enjoy support in all browsers, including Firefox and Safari.

To open the files, I employ the <input type="file"> element, and the file is read using the FileReader API, another well-supported alternative to the File System Access API.

For saving files, instead of using showSaveFilePicker() from the File System Access API, the code creates a download link using URL.createObjectURL() and a dynamically created <a> element.

Make your own space

Version 2 works in all browsers and can be run locally from your machine. Make a new empty file and name it quiet.html or your own preferred name, then copy and paste the code below into it.

Enjoy the serenity, now with import, export and custom save-as file names.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>The Quiet Writing Area</title>
<style>
body {
    font-family: 'sans-serif';
    text-align: center;
    background-color: #fff1e5;
}
h1 {
    font-size: 1.6rem;
    color: #807973
}
textarea {
    font-family: 'sans-serif';
    font-size: 1.1rem;
    border: 1px solid #aaa;
    padding: 8px;
    box-sizing: border-box;
    background-color: #fff1e5;
}
textarea:focus {
    outline: none;
    border: 1px solid #aaa;
    box-shadow: 0 0 4px rgba(0,0,0,0.05);
}
#countContainer {
    margin-top: 10px;
    font-size: 0.9rem;
    color: #0f8e99;
    display: flex;
    justify-content: center;
    gap: 10px;
}
input[type="text"] {
    padding: 5px;
    font-size: 0.9rem;
    border: 1px solid #aaa;
    width: 200px;
    text-align: center;
    background-color: #fff1e5;
}
.clearing, .clearing a {
    font-size: 0.9rem;
    color: #0f8e99;
    text-decoration: none;
    margin: 15px 0;
}
</style>
</head>
<body>

<h1>The quiet writing area</h1>

<form>
    <textarea id="textbox" name="quiet" rows="25" cols="100"></textarea>
    <div id="countContainer">
        <div id="wordCount">0 words</div> |
        <div id="charCount">0 characters</div>
    </div>
    <div class="clearing">
        <a href="#" id="openBtn">Import</a> |
        <a href="#" id="saveBtn">Export</a> |
        <a href="#" id="clearLink">Clear Form</a>
    </div>
    <div>
        <input type="text" id="filenameInput" placeholder="Save-as filename (optional)">
    </div>
    <input type="file" id="fileInput" style="display:none" />
</form>

<script>
const textarea = document.getElementById('textbox');
const charCount = document.getElementById('charCount');
const wordCount = document.getElementById('wordCount');
const openBtn = document.getElementById('openBtn');
const saveBtn = document.getElementById('saveBtn');
const fileInput = document.getElementById('fileInput');
const filenameInput = document.getElementById('filenameInput');

function updateCounts(text) {
  const characters = text.length;
  const words = text.trim().split(/\s+/).filter(Boolean).length;
  charCount.textContent = `${characters} character${characters !== 1 ? 's' : ''}`;
  wordCount.textContent = `${words} word${words !== 1 ? 's' : ''}`;
}

textarea.addEventListener('input', () => {
  updateCounts(textarea.value);
});

openBtn.addEventListener('click', () => {
    fileInput.click();
});

fileInput.addEventListener('change', async () => {
    const file = fileInput.files[0];
    if (file) {
        const reader = new FileReader();
        reader.onload = () => {
            textarea.value = reader.result;
            updateCounts(reader.result);
        };
        reader.readAsText(file);
    }
});

saveBtn.addEventListener('click', () => {
    const filename = filenameInput.value.trim() || 'quiet-writing.txt';
    const blob = new Blob([textarea.value], { type: 'text/plain' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = filename;
    a.click();
    URL.revokeObjectURL(url);
});

document.getElementById('clearLink').addEventListener('click', function(event) {
  event.preventDefault();
  textarea.value = '';
  charCount.textContent = '0 characters';
  wordCount.textContent = '0 words';
});
</script>

</body>
</html>
»
Tagged in:

Visitors: Loading...