Created
February 5, 2025 13:41
-
-
Save primaprashant/4b14f25eb66c48de97e5974a8bc79cef to your computer and use it in GitHub Desktop.
A browser-based text drafting space that saves to localStorage, offering consistent behavior across devices and platforms while avoiding the quirks of various text input tools.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> | |
| <title>Full-Page Notes</title> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet"> | |
| <style> | |
| html, body { | |
| height: 100%; | |
| margin: 0; | |
| padding: 0; | |
| font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif; | |
| background-color: #f5f5f5; | |
| overflow-x: hidden; | |
| } | |
| body { | |
| display: flex; | |
| flex-direction: column; | |
| line-height: 1.6; | |
| } | |
| .container { | |
| max-width: 800px; | |
| width: 100%; | |
| margin: 20px auto; | |
| padding: 20px; | |
| box-sizing: border-box; | |
| display: flex; | |
| flex-direction: column; | |
| flex-grow: 1; | |
| background-color: #ffffff; | |
| border-radius: 8px; | |
| box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); | |
| } | |
| .header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| margin-bottom: 20px; | |
| flex-wrap: wrap; | |
| } | |
| h1 { | |
| margin: 0; | |
| padding: 0; | |
| font-size: 24px; | |
| color: #333; | |
| font-weight: 700; | |
| } | |
| .button-group { | |
| display: flex; | |
| gap: 10px; | |
| } | |
| button { | |
| padding: 5px 10px; | |
| font-size: 14px; | |
| background-color: #f0f0f0; | |
| border: 1px solid #ddd; | |
| border-radius: 4px; | |
| cursor: pointer; | |
| transition: background-color 0.3s; | |
| white-space: nowrap; | |
| } | |
| button:hover { | |
| background-color: #e0e0e0; | |
| } | |
| #notesArea { | |
| flex-grow: 1; | |
| border: 1px solid #e0e0e0; | |
| border-radius: 4px; | |
| outline: none; | |
| font-size: 16px; | |
| font-family: inherit; | |
| resize: none; | |
| overflow-y: auto; | |
| padding: 10px; | |
| box-sizing: border-box; | |
| line-height: inherit; | |
| width: 100%; | |
| min-height: 300px; | |
| } | |
| #statusBar { | |
| margin-top: 10px; | |
| font-size: 14px; | |
| color: #666; | |
| display: flex; | |
| justify-content: space-between; | |
| flex-wrap: wrap; | |
| } | |
| @media (max-width: 600px) { | |
| .container { | |
| margin: 0; | |
| padding: 10px; | |
| border-radius: 0; | |
| box-shadow: none; | |
| } | |
| .header { | |
| flex-direction: column; | |
| align-items: flex-start; | |
| gap: 10px; | |
| } | |
| h1 { | |
| font-size: 20px; | |
| } | |
| #notesArea { | |
| font-size: 16px; | |
| min-height: 200px; | |
| } | |
| #statusBar { | |
| font-size: 12px; | |
| flex-direction: column; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <div class="header"> | |
| <h1>Start Writing...</h1> | |
| <div class="button-group"> | |
| <button id="selectAllBtn">Select All</button> | |
| <button id="copyAllBtn">Copy All</button> | |
| </div> | |
| </div> | |
| <textarea id="notesArea" autofocus></textarea> | |
| <div id="statusBar"> | |
| <span id="charCount">Characters: 0</span> | |
| <span id="wordCount">Words: 0</span> | |
| <span id="lineCount">Lines: 0</span> | |
| </div> | |
| </div> | |
| <script> | |
| const notesArea = document.getElementById('notesArea'); | |
| const charCountElement = document.getElementById('charCount'); | |
| const wordCountElement = document.getElementById('wordCount'); | |
| const lineCountElement = document.getElementById('lineCount'); | |
| const selectAllBtn = document.getElementById('selectAllBtn'); | |
| const copyAllBtn = document.getElementById('copyAllBtn'); | |
| function updateCounts() { | |
| const text = notesArea.value; | |
| const charCount = text.length; | |
| const wordCount = text.trim().split(/\s+/).filter(word => word.length > 0).length; | |
| const lineCount = text.split('\n').length; | |
| charCountElement.textContent = `Characters: ${charCount}`; | |
| wordCountElement.textContent = `Words: ${wordCount}`; | |
| lineCountElement.textContent = `Lines: ${lineCount}`; | |
| } | |
| // Load saved content on page load | |
| notesArea.value = localStorage.getItem('fullPageNotes') || ''; | |
| updateCounts(); | |
| // Save content and update counts whenever it changes | |
| notesArea.addEventListener('input', () => { | |
| localStorage.setItem('fullPageNotes', notesArea.value); | |
| updateCounts(); | |
| }); | |
| // Select All button functionality | |
| selectAllBtn.addEventListener('click', () => { | |
| notesArea.select(); | |
| notesArea.focus(); | |
| }); | |
| // Copy All button functionality | |
| copyAllBtn.addEventListener('click', () => { | |
| notesArea.select(); | |
| document.execCommand('copy'); | |
| // Optional: Provide visual feedback | |
| copyAllBtn.textContent = 'Copied!'; | |
| setTimeout(() => { | |
| copyAllBtn.textContent = 'Copy All'; | |
| }, 2000); | |
| }); | |
| // Set cursor position after the last character | |
| notesArea.setSelectionRange(notesArea.value.length, notesArea.value.length); | |
| // Ensure textarea is focused | |
| notesArea.focus(); | |
| // Prevent zooming on mobile devices | |
| document.addEventListener('touchmove', function (event) { | |
| if (event.scale !== 1) { | |
| event.preventDefault(); | |
| } | |
| }, { passive: false }); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment