Initial commit

This commit is contained in:
Brendan
2024-09-21 16:54:43 +00:00
commit 30f209480b
8 changed files with 788 additions and 0 deletions

206
static/css/style.css Normal file
View File

@@ -0,0 +1,206 @@
body {
font-family: 'Segoe UI', Arial, sans-serif;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
height: 100vh;
background-color: #1e1e1e;
color: #ffffff;
}
.menu-bar {
background-color: #2d2d2d;
padding: 10px;
border-bottom: 1px solid #3a3a3a;
display: flex;
align-items: center;
flex-wrap: wrap;
}
.menu-item {
display: inline-flex;
align-items: center;
margin-right: 20px;
cursor: pointer;
color: #ffffff;
font-size: 14px;
text-decoration: none;
}
.menu-item:hover {
color: #0078d4;
}
.notepad-icon {
margin-right: 5px;
}
.notepad-icon.logo {
width: 24px;
height: 24px;
}
#brendanLink {
margin-right: 20px;
}
#brendanLink:hover {
color: #0078d4;
}
#encodingSelect, #fontSelect {
background-color: #3c3c3c;
color: #ffffff;
border: 1px solid #555555;
padding: 5px 10px;
font-size: 14px;
cursor: pointer;
outline: none;
transition: background-color 0.3s, border-color 0.3s;
}
#encodingSelect:hover, #encodingSelect:focus,
#fontSelect:hover, #fontSelect:focus {
background-color: #4c4c4c;
border-color: #0078d4;
}
#encodingSelect option, #fontSelect option {
background-color: #3c3c3c;
color: #ffffff;
}
#editor {
flex-grow: 1;
width: 100%;
padding: 20px;
box-sizing: border-box;
border: none;
resize: none;
font-size: 14px;
line-height: 1.6;
background-color: #252526;
color: #d4d4d4;
white-space: pre;
overflow-wrap: normal;
overflow-x: auto;
font-family: Consolas, 'Courier New', Monaco, 'Roboto Mono', Arial, Verdana, 'Times New Roman', Georgia, Palatino, Wingdings, monospace;
}
#editor.wrap {
white-space: pre-wrap;
overflow-wrap: break-word;
overflow-x: hidden;
}
#editor:focus {
outline: none;
}
.modal {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.6);
}
.modal-content {
background-color: #2d2d2d;
margin: 15% auto;
padding: 20px;
border: 1px solid #3a3a3a;
width: 80%;
max-width: 500px;
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
.close {
color: #999999;
float: right;
font-size: 28px;
font-weight: bold;
cursor: pointer;
}
.close:hover,
.close:focus {
color: #ffffff;
text-decoration: none;
}
#findInput {
width: 100%;
padding: 10px;
margin-bottom: 10px;
background-color: #3c3c3c;
border: 1px solid #555555;
color: #ffffff;
font-size: 14px;
}
#findButton {
padding: 10px 20px;
background-color: #0078d4;
border: none;
color: #ffffff;
cursor: pointer;
font-size: 14px;
transition: background-color 0.3s;
}
#findButton:hover {
background-color: #2b90d9;
}
#printBtn {
transition: color 0.3s;
}
#printBtn:hover {
color: #0078d4;
}
#wrapText {
margin-right: 5px;
}
/* Brendan Modal Styles */
#brendanModal .modal-content {
text-align: center;
}
.brendan-logo {
width: 48px;
height: 48px;
margin-bottom: 15px;
}
.brendan-description {
font-size: 16px;
margin-bottom: 10px;
}
.brendan-byline {
font-style: italic;
margin-bottom: 15px;
}
.brendan-link {
display: inline-block;
padding: 10px 20px;
background-color: #0078d4;
color: #ffffff;
text-decoration: none;
border-radius: 4px;
transition: background-color 0.3s;
}
.brendan-link:hover {
background-color: #2b90d9;
}

216
static/js/editor.js Normal file
View File

@@ -0,0 +1,216 @@
document.addEventListener('DOMContentLoaded', function() {
console.log("DOM content loaded");
const editor = document.getElementById('editor');
const openBtn = document.getElementById('openBtn');
const saveBtn = document.getElementById('saveBtn');
const findBtn = document.getElementById('findBtn');
const printBtn = document.getElementById('printBtn');
const modal = document.getElementById('modal');
const closeModal = document.getElementsByClassName('close')[0];
const findInput = document.getElementById('findInput');
const findButton = document.getElementById('findButton');
const encodingSelect = document.getElementById('encodingSelect');
const fontSelect = document.getElementById('fontSelect');
const wrapTextCheckbox = document.getElementById('wrapText');
const fileInput = document.getElementById('fileInput');
// Brendan Modal elements
const brendanLink = document.getElementById('brendanLink');
const brendanModal = document.getElementById('brendanModal');
const closeBrendanModal = brendanModal.getElementsByClassName('close')[0];
console.log("All elements selected");
let currentFileName = 'untitled.txt';
let currentEncoding = 'utf-8';
// Set file input to accept only .txt files
fileInput.setAttribute('accept', '.txt');
openBtn.addEventListener('click', function() {
console.log("Open button clicked");
fileInput.click();
});
fileInput.addEventListener('change', function(e) {
console.log("File input changed");
const file = e.target.files[0];
if (file) {
if (file.name.toLowerCase().endsWith('.txt')) {
currentFileName = file.name;
const reader = new FileReader();
reader.onload = function(e) {
const content = e.target.result;
detectEncoding(content);
editor.value = content;
console.log("File loaded successfully");
};
reader.onerror = function(e) {
console.error("Error reading file:", e);
alert("An error occurred while reading the file. Please try again.");
};
reader.readAsText(file);
} else {
alert("Please select a .txt file.");
fileInput.value = ''; // Clear the file input
}
}
});
saveBtn.addEventListener('click', function() {
console.log("Save button clicked");
const content = editor.value;
fetch('/download', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ content: content, filename: currentFileName, encoding: currentEncoding }),
})
.then(response => response.json())
.then(data => {
const blob = new Blob([data.content], { type: 'text/plain' });
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = data.filename;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
console.log("File saved successfully");
})
.catch((error) => {
console.error('Error:', error);
alert("An error occurred while saving the file. Please try again.");
});
});
findBtn.addEventListener('click', function() {
console.log("Find button clicked");
modal.style.display = "block";
});
closeModal.addEventListener('click', function() {
modal.style.display = "none";
});
window.addEventListener('click', function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
});
findButton.addEventListener('click', function() {
console.log("Find text button clicked");
const searchText = findInput.value;
if (searchText) {
const content = editor.value;
const startIndex = content.indexOf(searchText);
if (startIndex !== -1) {
editor.setSelectionRange(startIndex, startIndex + searchText.length);
editor.focus();
console.log("Text found and highlighted");
} else {
alert("Text not found!");
}
}
});
encodingSelect.addEventListener('change', function() {
console.log("Encoding changed to:", this.value);
currentEncoding = this.value;
});
function detectEncoding(content) {
console.log("Detecting encoding");
fetch('/detect_encoding', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ content: content }),
})
.then(response => response.json())
.then(data => {
currentEncoding = data.encoding;
encodingSelect.value = currentEncoding;
console.log("Encoding detected:", currentEncoding);
})
.catch((error) => {
console.error('Error:', error);
alert("An error occurred while detecting the file encoding. Using default encoding.");
});
}
// Print functionality
printBtn.addEventListener('click', function() {
console.log("Print button clicked");
const content = editor.value;
const printWindow = window.open('', '_blank');
printWindow.document.write('<html><head><title>Print</title>');
printWindow.document.write('<style>body { font-family: ' + editor.style.fontFamily + '; white-space: pre-wrap; }</style>');
printWindow.document.write('</head><body>');
printWindow.document.write(content);
printWindow.document.write('</body></html>');
printWindow.document.close();
printWindow.print();
});
// Basic text editing features
document.addEventListener('keydown', function(e) {
if (e.ctrlKey || e.metaKey) {
switch (e.key.toLowerCase()) {
case 'x':
document.execCommand('cut');
break;
case 'c':
document.execCommand('copy');
break;
case 'v':
document.execCommand('paste');
break;
}
}
});
// Font selection
fontSelect.addEventListener('change', function() {
console.log("Font changed to:", this.value);
editor.style.fontFamily = this.value + ', monospace';
});
// Text wrapping
wrapTextCheckbox.addEventListener('change', function() {
console.log("Text wrap changed to:", this.checked);
if (this.checked) {
editor.classList.add('wrap');
} else {
editor.classList.remove('wrap');
}
});
// Set initial font
editor.style.fontFamily = fontSelect.value + ', monospace';
// Brendan Modal functionality
brendanLink.addEventListener('click', function(e) {
console.log("Brendan link clicked");
e.preventDefault();
brendanModal.style.display = "block";
});
closeBrendanModal.addEventListener('click', function() {
brendanModal.style.display = "none";
});
window.addEventListener('click', function(event) {
if (event.target == brendanModal) {
brendanModal.style.display = "none";
}
});
console.log("All event listeners set up");
});
console.log("editor.js loaded");