Загрузить файлы в «/»
This commit is contained in:
commit
4c09eb9710
BIN
TeletactileRus.ttf
Normal file
BIN
TeletactileRus.ttf
Normal file
Binary file not shown.
247
app.js
Normal file
247
app.js
Normal file
@ -0,0 +1,247 @@
|
||||
const textInput = document.querySelector(".textInput");
|
||||
const btnSave = document.querySelector(".btnSave");
|
||||
const notes = document.querySelector(".notes-container");
|
||||
|
||||
// Получаем кнопки
|
||||
const boldBtn = document.getElementById("boldBtn");
|
||||
const italicBtn = document.getElementById("italicBtn");
|
||||
const headerBtn = document.getElementById("headerBtn");
|
||||
const listBtn = document.getElementById("listBtn");
|
||||
const quoteBtn = document.getElementById("quoteBtn");
|
||||
const codeBtn = document.getElementById("codeBtn");
|
||||
const linkBtn = document.getElementById("linkBtn");
|
||||
|
||||
function getFormattedDateTime() {
|
||||
let now = new Date();
|
||||
let day = String(now.getDate()).padStart(2, "0");
|
||||
let month = String(now.getMonth() + 1).padStart(2, "0");
|
||||
let year = now.getFullYear();
|
||||
let hours = String(now.getHours()).padStart(2, "0");
|
||||
let minutes = String(now.getMinutes()).padStart(2, "0");
|
||||
|
||||
return {
|
||||
date: `${day}.${month}.${year}`,
|
||||
time: `${hours}:${minutes}`,
|
||||
};
|
||||
}
|
||||
|
||||
// Сохранить заметки в localStorage
|
||||
function saveNotesToLocalStorage(notesArr) {
|
||||
localStorage.setItem("notes", JSON.stringify(notesArr));
|
||||
}
|
||||
|
||||
// Получить заметки из localStorage
|
||||
function getNotesFromLocalStorage() {
|
||||
return JSON.parse(localStorage.getItem("notes")) || [];
|
||||
}
|
||||
|
||||
// Обновить функцию renderNotes
|
||||
function renderNotes() {
|
||||
const notesArr = getNotesFromLocalStorage();
|
||||
notes.innerHTML = ""; // Очищаем контейнер перед рендерингом
|
||||
|
||||
notesArr.forEach(function (content, index) {
|
||||
const noteHtml = `
|
||||
<div id="note" class="container">
|
||||
<div class="date">
|
||||
${content.date} ${content.time}
|
||||
<div id="editBtn" class="notesHeaderBtn" data-index="${index}">Редактировать</div>
|
||||
<div id="deleteBtn" class="notesHeaderBtn" data-index="${index}">Удалить</div>
|
||||
</div>
|
||||
<div class="textNote">${marked.parse(content.content)}</div>
|
||||
</div>
|
||||
`;
|
||||
notes.insertAdjacentHTML("afterbegin", noteHtml);
|
||||
});
|
||||
|
||||
deleteNote();
|
||||
editNote();
|
||||
}
|
||||
|
||||
// Обновить функцию saveNote
|
||||
function saveNote() {
|
||||
btnSave.addEventListener("click", function () {
|
||||
if (textInput.value.trim() !== "") {
|
||||
let { date, time } = getFormattedDateTime();
|
||||
|
||||
const note = {
|
||||
content: textInput.value,
|
||||
date: date,
|
||||
time: time,
|
||||
};
|
||||
|
||||
const notesArr = getNotesFromLocalStorage();
|
||||
notesArr.push(note);
|
||||
saveNotesToLocalStorage(notesArr);
|
||||
|
||||
textInput.value = "";
|
||||
textInput.style.height = "auto"; // Сбрасываем размер текстового поля
|
||||
renderNotes();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Обновить функцию deleteNote
|
||||
function deleteNote() {
|
||||
document.querySelectorAll("#deleteBtn").forEach((btn) => {
|
||||
btn.addEventListener("click", function (event) {
|
||||
let index = event.target.dataset.index;
|
||||
const notesArr = getNotesFromLocalStorage();
|
||||
notesArr.splice(index, 1);
|
||||
saveNotesToLocalStorage(notesArr);
|
||||
renderNotes();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Обновить функцию editNote
|
||||
function editNote() {
|
||||
document.querySelectorAll("#editBtn").forEach((btn) => {
|
||||
btn.addEventListener("click", function (event) {
|
||||
let index = event.target.dataset.index;
|
||||
let noteContainer = event.target.closest("#note");
|
||||
let noteContent = noteContainer.querySelector(".textNote");
|
||||
|
||||
// Создаем textarea с уже существующим классом textInput
|
||||
let textarea = document.createElement("textarea");
|
||||
textarea.classList.add("textInput");
|
||||
textarea.value = noteContent.textContent;
|
||||
|
||||
// Привязываем авторасширение к textarea для редактирования
|
||||
textarea.addEventListener("input", function () {
|
||||
autoExpandTextarea(textarea);
|
||||
});
|
||||
autoExpandTextarea(textarea);
|
||||
|
||||
// Кнопка сохранить
|
||||
let saveEditBtn = document.createElement("button");
|
||||
saveEditBtn.textContent = "Сохранить";
|
||||
saveEditBtn.classList.add("btnSave");
|
||||
|
||||
// Очищаем текущий контент и вставляем textarea и кнопку сохранить
|
||||
noteContent.innerHTML = "";
|
||||
noteContent.appendChild(textarea);
|
||||
noteContent.appendChild(saveEditBtn);
|
||||
|
||||
saveEditBtn.addEventListener("click", function () {
|
||||
if (textarea.value.trim() !== "") {
|
||||
let { date, time } = getFormattedDateTime();
|
||||
const notesArr = getNotesFromLocalStorage();
|
||||
notesArr[index] = {
|
||||
content: textarea.value,
|
||||
date: date,
|
||||
time: time,
|
||||
};
|
||||
saveNotesToLocalStorage(notesArr);
|
||||
renderNotes();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Функция для авторасширения текстового поля
|
||||
function autoExpandTextarea(textarea) {
|
||||
textarea.style.height = "auto";
|
||||
textarea.style.height = textarea.scrollHeight + "px";
|
||||
}
|
||||
|
||||
// Привязываем авторасширение к текстовому полю для создания заметки
|
||||
textInput.addEventListener("input", function () {
|
||||
autoExpandTextarea(textInput);
|
||||
});
|
||||
|
||||
// Изначально запускаем для установки правильной высоты
|
||||
autoExpandTextarea(textInput);
|
||||
|
||||
function insertMarkdown(tag) {
|
||||
const start = textInput.selectionStart;
|
||||
const end = textInput.selectionEnd;
|
||||
const text = textInput.value;
|
||||
|
||||
const before = text.substring(0, start);
|
||||
const selected = text.substring(start, end);
|
||||
const after = text.substring(end);
|
||||
|
||||
if (selected.startsWith(tag) && selected.endsWith(tag)) {
|
||||
// Если теги уже есть, удаляем их
|
||||
textInput.value = `${before}${selected.slice(
|
||||
tag.length,
|
||||
-tag.length
|
||||
)}${after}`;
|
||||
textInput.setSelectionRange(start, end - 2 * tag.length);
|
||||
} else if (selected.trim() === "") {
|
||||
// Если текст не выделен
|
||||
if (tag === "[Текст ссылки](URL)") {
|
||||
// Для ссылок создаем шаблон с двумя кавычками
|
||||
textInput.value = `${before}[Текст ссылки](URL)${after}`;
|
||||
const cursorPosition = start + 1; // Помещаем курсор внутрь текста ссылки
|
||||
textInput.setSelectionRange(cursorPosition, cursorPosition + 12);
|
||||
} else if (tag === "- " || tag === "> " || tag === "# ") {
|
||||
// Для списка, цитаты и заголовка помещаем курсор после `- `, `> ` или `# `
|
||||
textInput.value = `${before}${tag}${after}`;
|
||||
const cursorPosition = start + tag.length;
|
||||
textInput.setSelectionRange(cursorPosition, cursorPosition);
|
||||
} else {
|
||||
// Для остальных типов создаем два тега
|
||||
textInput.value = `${before}${tag}${tag}${after}`;
|
||||
const cursorPosition = start + tag.length;
|
||||
textInput.setSelectionRange(cursorPosition, cursorPosition);
|
||||
}
|
||||
} else {
|
||||
// Если текст выделен
|
||||
if (tag === "[Текст ссылки](URL)") {
|
||||
// Для ссылок используем выделенный текст вместо "Текст ссылки"
|
||||
textInput.value = `${before}[${selected}](URL)${after}`;
|
||||
const cursorPosition = start + selected.length + 3; // Помещаем курсор в URL
|
||||
textInput.setSelectionRange(cursorPosition, cursorPosition + 3);
|
||||
} else if (tag === "- " || tag === "> " || tag === "# ") {
|
||||
// Для списка, цитаты и заголовка добавляем `- `, `> ` или `# ` перед выделенным текстом
|
||||
textInput.value = `${before}${tag}${selected}${after}`;
|
||||
const cursorPosition = start + tag.length + selected.length;
|
||||
textInput.setSelectionRange(cursorPosition, cursorPosition);
|
||||
} else {
|
||||
// Для остальных типов оборачиваем выделенный текст
|
||||
textInput.value = `${before}${tag}${selected}${tag}${after}`;
|
||||
const cursorPosition = start + tag.length + selected.length + tag.length;
|
||||
textInput.setSelectionRange(cursorPosition, cursorPosition);
|
||||
}
|
||||
}
|
||||
|
||||
textInput.focus();
|
||||
}
|
||||
|
||||
// Обработчики для кнопок
|
||||
boldBtn.addEventListener("click", function () {
|
||||
insertMarkdown("**"); // Вставляем жирный текст
|
||||
});
|
||||
|
||||
italicBtn.addEventListener("click", function () {
|
||||
insertMarkdown("*"); // Вставляем курсив
|
||||
});
|
||||
|
||||
headerBtn.addEventListener("click", function () {
|
||||
insertMarkdown("# "); // Вставляем заголовок
|
||||
});
|
||||
|
||||
listBtn.addEventListener("click", function () {
|
||||
insertMarkdown("- "); // Вставляем элемент списка
|
||||
});
|
||||
|
||||
quoteBtn.addEventListener("click", function () {
|
||||
insertMarkdown("> "); // Вставляем цитату
|
||||
});
|
||||
|
||||
codeBtn.addEventListener("click", function () {
|
||||
insertMarkdown("`"); // Вставляем код
|
||||
});
|
||||
|
||||
linkBtn.addEventListener("click", function () {
|
||||
insertMarkdown("[Текст ссылки](URL)"); // Вставляем ссылку
|
||||
});
|
||||
|
||||
// Удалено дублирование добавления кнопок Markdown в окно сохранения заметки
|
||||
// Кнопки уже добавлены в HTML (index.html), поэтому их повторное создание не требуется
|
||||
|
||||
renderNotes();
|
||||
saveNote();
|
||||
72
index.html
Normal file
72
index.html
Normal file
@ -0,0 +1,72 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Document</title>
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>Заметки</header>
|
||||
<div class="main">
|
||||
<div class="markdown-buttons">
|
||||
<button class="btnMarkdown" id="boldBtn">
|
||||
<i class="fas fa-bold"></i>
|
||||
<!-- Иконка для жирного текста -->
|
||||
</button>
|
||||
<button class="btnMarkdown" id="italicBtn">
|
||||
<i class="fas fa-italic"></i>
|
||||
<!-- Иконка для курсива -->
|
||||
</button>
|
||||
<button class="btnMarkdown" id="headerBtn">
|
||||
<i class="fas fa-heading"></i>
|
||||
<!-- Иконка для заголовка -->
|
||||
</button>
|
||||
<button class="btnMarkdown" id="listBtn">
|
||||
<i class="fas fa-list-ul"></i>
|
||||
<!-- Иконка для списка -->
|
||||
</button>
|
||||
<button class="btnMarkdown" id="quoteBtn">
|
||||
<i class="fas fa-quote-right"></i>
|
||||
<!-- Иконка для цитаты -->
|
||||
</button>
|
||||
<button class="btnMarkdown" id="codeBtn">
|
||||
<i class="fas fa-code"></i>
|
||||
<!-- Иконка для кода -->
|
||||
</button>
|
||||
<button class="btnMarkdown" id="linkBtn">
|
||||
<i class="fas fa-link"></i>
|
||||
<!-- Иконка для ссылки -->
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<textarea
|
||||
class="textInput"
|
||||
name=""
|
||||
id=""
|
||||
placeholder="Ваша заметка..."
|
||||
></textarea>
|
||||
<button class="btnSave">Сохранить</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="notes-container">
|
||||
<div id="note" class="container">
|
||||
<div class="date">
|
||||
<div class="notesHeaderBtn"></div>
|
||||
<div class="notesHeaderBtn"></div>
|
||||
</div>
|
||||
<div class="textNote"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<p>Создатель: <span>Fovway</span></p>
|
||||
</div>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/11.1.0/marked.min.js"></script>
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
20
manifest.json
Normal file
20
manifest.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "Fov Notes",
|
||||
"short_name": "Notes",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#ffffff",
|
||||
"theme_color": "#000000",
|
||||
"icons": [
|
||||
{
|
||||
"src": "project.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "project.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
project.png
Normal file
BIN
project.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
Loading…
x
Reference in New Issue
Block a user