לאחרונה נתקלתי בצורך (של עצמי..) לכתוב תזכורות לכל מיני מטלות קטנות שאסור לי לשכוח
'פתקים נדבקים' כמובן הם האופציה הכי מתאימה, אבל משום מה לי זה לא התאים, אז יצרתי {לא יפה לומר ככה. GEMINI יצר עבורי...} קוד לדף אינטרנט יפה ומעוצב שנותן לשמור תזכורות [ע"י עוגיות בדפדפן] ולמחוק, וגם להגדיר סיסמה
צילו"מ לדוגמה בספויילר
אז הנה אני משתף את זה איתכם, תהנו...
קישור לקוד בגיטהאב
הקוד המלא בספויילר, ניתן כמובן לשמור באופן מקומי על המחשב שלכם בקובץ בסיומת HTML ולפתוח בדפדפן. תהנו...
עריכה: א"א להשתמש בקוד הנוכחי באופן מקומי, מצורף כאן קובץ עם קוד אחר שלא משתמש בעוגיות אלא ב-localStorage ומיועד להרצה על מחשב מקומי תזכורות.txt (קליק ימני, שמירת קישור בשם. להחליף את הסיומת ל-html כמובן)
<!DOCTYPE html>
<html lang="he" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>מנהל התזכורות</title>
<style>
@keyframes subtleGradientShift {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
body {
color: #00ffcc;
font-family: 'Courier New', Courier, monospace;
margin: 0;
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
background: linear-gradient(270deg, #0a0f1f, #10152f, #0a0f1f);
background-size: 600% 600%;
animation: subtleGradientShift 30s ease infinite;
}
.container {
background-color: rgba(26, 31, 54, 0.85);
backdrop-filter: blur(5px);
padding: 30px;
border-radius: 15px;
box-shadow: 0 0 35px rgba(0, 255, 204, 0.4), 0 0 15px rgba(0, 255, 204, 0.2) inset;
border: 1px solid #00ffcc;
width: 90%;
max-width: 700px;
text-align: center;
margin-top: 20px;
}
h1 {
color: #ffffff;
text-shadow: 0 0 10px #00ffcc;
margin-bottom: 30px;
}
.input-area, .password-area {
margin-bottom: 25px;
display: flex;
gap: 10px;
flex-wrap: wrap;
}
input[type="text"], input[type="password"] {
flex-grow: 1;
padding: 12px 15px;
background-color: #0a0f1f;
color: #e0e0e0;
border: 1px solid #007766;
border-radius: 8px;
font-size: 16px;
outline: none;
min-width: 200px;
}
input[type="text"]::placeholder, input[type="password"]::placeholder {
color: #555f78;
}
input[type="text"]:focus, input[type="password"]:focus {
border-color: #00ffcc;
box-shadow: 0 0 10px rgba(0, 255, 204, 0.4);
}
button {
padding: 12px 20px;
background-color: #007766;
color: #ffffff;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s ease, box-shadow 0.3s ease;
text-shadow: 0 0 5px rgba(0,0,0,0.5);
flex-shrink: 0;
}
button:hover {
background-color: #00ffcc;
color: #0a0f1f;
box-shadow: 0 0 15px rgba(0, 255, 204, 0.6);
}
button.delete-btn {
background-color: #990033;
padding: 5px 10px;
font-size: 12px;
}
button.delete-btn:hover {
background-color: #ff3366;
}
button.cancel-btn {
background-color: #4a4f66;
}
button.cancel-btn:hover {
background-color: #6a6f86;
}
#deleteAllRemindersBtn {
background-color: #cc0000;
margin-top: 10px;
width: 100%;
font-size: 1em;
padding: 12px 20px;
}
#deleteAllRemindersBtn:hover {
background-color: #ff4d4d;
}
#remindersListArea {
margin-top: 20px;
background-color: rgba(10, 15, 31, 0.7);
padding: 20px;
border-radius: 10px;
border: 1px dashed #007766;
min-height: 100px;
text-align: right;
}
#remindersListArea h2 {
color: #ffffff;
text-align: center;
margin-top: 0;
margin-bottom: 15px;
border-bottom: 1px solid #007766;
padding-bottom: 10px;
}
.reminder-item {
background-color: #1a1f36;
border: 1px solid #00ffcc;
padding: 10px;
margin-bottom: 8px;
border-radius: 5px;
color: #e0e0e0;
font-size: 15px;
word-wrap: break-word;
display: flex;
justify-content: space-between;
align-items: center;
}
.reminder-item-text {
flex-grow: 1;
text-align: right;
}
.hidden { display: none !important; }
#toast-container {
position: fixed;
bottom: 20px;
left: 20px;
z-index: 10000;
display: flex;
flex-direction: column-reverse;
gap: 10px;
}
.toast-message {
background-color: #00ffcc;
color: #0a0f1f;
padding: 12px 18px;
border-radius: 8px;
box-shadow: 0 3px 12px rgba(0,0,0,0.25);
opacity: 0;
transform: translateX(-100%);
transition: opacity 0.4s ease-out, transform 0.4s ease-out;
min-width: 250px;
text-align: left;
}
.toast-message.show {
opacity: 0.95;
transform: translateX(0);
}
.toast-message.error {
background-color: #ff3366;
color: #ffffff;
}
.modal-overlay {
position: fixed;
top: 0; left: 0; width: 100%; height: 100%;
background-color: rgba(0,0,0,0.7);
display: flex;
justify-content: center;
align-items: center;
z-index: 9000;
opacity: 0;
transition: opacity 0.3s ease-in-out;
}
.modal-overlay.show {
opacity: 1;
}
.modal-content {
background-color: #1a1f36;
padding: 30px 40px;
border-radius: 12px;
border: 1px solid #00ffcc;
text-align: center;
box-shadow: 0 0 30px rgba(0, 255, 204, 0.5);
transform: scale(0.7);
transition: transform 0.3s ease-in-out;
}
.modal-overlay.show .modal-content {
transform: scale(1);
}
.modal-content p {
margin-bottom: 25px;
font-size: 1.1em;
color: #e0e0e0;
}
.modal-buttons button { margin: 0 12px; }
#confirm-no-btn { background-color: #4a4f66; }
#confirm-no-btn:hover { background-color: #6a6f86; }
#passwordManagementArea { margin-top: 20px; }
#passwordMgmtBtn { background-color: #3a3f56; }
#passwordMgmtBtn:hover { background-color: #555f78; }
</style>
</head>
<body>
<div class="container">
<h1>מנהל התזכורות</h1>
<div id="password-section" class="hidden">
<div id="password-setup-area" class="password-area hidden">
<p>הגדר סיסמה לגישה לתזכורות:</p>
<input type="password" id="newPassword" placeholder="הזן סיסמה חדשה (לפחות 4 תווים)">
<button id="setPasswordBtn">הגדר סיסמה</button>
<button id="cancelPasswordSetupBtn" class="cancel-btn">ביטול</button>
</div>
<div id="password-entry-area" class="password-area hidden">
<p>אנא הזן את הסיסמה שלך כדי לגשת לתזכורות:</p>
<input type="password" id="enteredPassword" placeholder="הזן סיסמה">
<button id="loginBtn">הכנס</button>
<button id="cancelLoginAttemptBtn" class="cancel-btn hidden">ביטול</button>
</div>
</div>
<div id="app-content-area">
<div class="input-area">
<input type="text" id="reminderText" placeholder="הזן תזכורת חדשה ולחץ Enter או על הכפתור...">
<button id="saveReminderBtn">שמור תזכורת</button>
</div>
<button id="toggleRemindersBtn">הצג את כל התזכורות</button>
<button id="deleteAllRemindersBtn">מחק את כל התזכורות</button>
<div id="remindersListArea" class="hidden">
<h2>רשימת תזכורות:</h2>
<div id="remindersList">
<p>עדיין לא נשמרו תזכורות, או שלא נלחץ על כפתור ההצגה.</p>
</div>
</div>
<div id="passwordManagementArea">
<button id="passwordMgmtBtn">הפעל הגנת סיסמה</button>
</div>
</div>
</div>
<div id="toast-container"></div>
<div id="confirmation-modal-overlay" class="modal-overlay hidden">
<div class="modal-content">
<p id="confirmation-message">האם אתה בטוח?</p>
<div class="modal-buttons">
<button id="confirm-yes-btn" class="confirm-action-btn">כן</button>
<button id="confirm-no-btn" class="confirm-action-btn">לא</button>
</div>
</div>
</div>
<script>
const APP_PASSWORD_COOKIE = 'app_access_password_v1';
const REMINDER_PREFIX = "reminder_item_";
const passwordSection = document.getElementById('password-section');
const passwordSetupArea = document.getElementById('password-setup-area');
const newPasswordInput = document.getElementById('newPassword');
const setPasswordBtn = document.getElementById('setPasswordBtn');
const cancelPasswordSetupBtn = document.getElementById('cancelPasswordSetupBtn');
const passwordEntryArea = document.getElementById('password-entry-area');
const enteredPasswordInput = document.getElementById('enteredPassword');
const loginBtn = document.getElementById('loginBtn');
const cancelLoginAttemptBtn = document.getElementById('cancelLoginAttemptBtn');
const appContentArea = document.getElementById('app-content-area');
const reminderTextElement = document.getElementById('reminderText');
const saveReminderBtn = document.getElementById('saveReminderBtn');
const toggleRemindersBtn = document.getElementById('toggleRemindersBtn');
const deleteAllRemindersBtn = document.getElementById('deleteAllRemindersBtn');
const remindersListArea = document.getElementById('remindersListArea');
const remindersListDiv = document.getElementById('remindersList');
const passwordMgmtBtn = document.getElementById('passwordMgmtBtn');
const toastContainer = document.getElementById('toast-container');
const confirmationModalOverlay = document.getElementById('confirmation-modal-overlay');
const confirmationMessageElement = document.getElementById('confirmation-message');
const confirmYesBtn = document.getElementById('confirm-yes-btn');
const confirmNoBtn = document.getElementById('confirm-no-btn');
let currentOnConfirmCallback = null;
function setCookie(name, value, days) {
let expires = "";
if (days) {
const date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + (encodeURIComponent(value) || "") + expires + "; path=/; SameSite=Lax";
}
function getCookie(name) {
const nameEQ = name + "=";
const ca = document.cookie.split(';');
for(let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) === ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) === 0) return decodeURIComponent(c.substring(nameEQ.length, c.length));
}
return null;
}
function eraseCookie(name) {
document.cookie = name+'=; Max-Age=-99999999; path=/; SameSite=Lax';
}
function getAllReminderCookies() {
const cookies = {};
if (document.cookie && document.cookie !== '') {
document.cookie.split(';').forEach(function(cookie) {
const parts = cookie.match(/^\s*([^=]+)=(.*)$/);
if(parts && parts.length === 3 && parts[1].startsWith(REMINDER_PREFIX)) {
cookies[parts[1]] = decodeURIComponent(parts[2]);
}
});
}
return cookies;
}
function showToast(message, type = 'success', duration = 2500) {
const toast = document.createElement('div');
toast.classList.add('toast-message');
if (type === 'error') toast.classList.add('error');
toast.textContent = message;
toastContainer.appendChild(toast);
setTimeout(() => toast.classList.add('show'), 10);
setTimeout(() => {
toast.classList.remove('show');
toast.addEventListener('transitionend', () => toast.remove(), { once: true });
}, duration);
}
function showConfirmation(message, onConfirm) {
confirmationMessageElement.textContent = message;
currentOnConfirmCallback = onConfirm;
confirmationModalOverlay.classList.remove('hidden');
setTimeout(() => confirmationModalOverlay.classList.add('show'), 10);
}
function hideConfirmation() {
confirmationModalOverlay.classList.remove('show');
confirmationModalOverlay.addEventListener('transitionend', () => {
confirmationModalOverlay.classList.add('hidden');
currentOnConfirmCallback = null;
}, { once: true });
}
confirmYesBtn.addEventListener('click', () => {
if (currentOnConfirmCallback) currentOnConfirmCallback();
hideConfirmation();
});
confirmNoBtn.addEventListener('click', hideConfirmation);
function updatePasswordMgmtButton() {
if (getCookie(APP_PASSWORD_COOKIE)) {
passwordMgmtBtn.textContent = "הסר הגנת סיסמה";
} else {
passwordMgmtBtn.textContent = "הפעל הגנת סיסמה";
}
}
passwordMgmtBtn.addEventListener('click', () => {
if (getCookie(APP_PASSWORD_COOKIE)) {
showConfirmation("האם אתה בטוח שברצונך להסיר את הגנת הסיסמה? התזכורות יהיו נגישות ללא סיסמה.", () => {
eraseCookie(APP_PASSWORD_COOKIE);
showToast("הגנת הסיסמה הוסרה.");
updatePasswordMgmtButton();
passwordSection.classList.add('hidden');
appContentArea.classList.remove('hidden');
});
} else {
passwordSection.classList.remove('hidden');
passwordSetupArea.classList.remove('hidden');
passwordEntryArea.classList.add('hidden');
appContentArea.classList.add('hidden');
}
});
setPasswordBtn.addEventListener('click', () => {
const newPassword = newPasswordInput.value;
if (newPassword.length < 4) {
showToast("הסיסמה חייבת להכיל לפחות 4 תווים.", 'error');
return;
}
setCookie(APP_PASSWORD_COOKIE, btoa(newPassword), 365);
showToast("הסיסמה הוגדרה בהצלחה!");
newPasswordInput.value = '';
passwordSetupArea.classList.add('hidden');
passwordSection.classList.add('hidden');
appContentArea.classList.remove('hidden');
updatePasswordMgmtButton();
});
cancelPasswordSetupBtn.addEventListener('click', () => {
passwordSetupArea.classList.add('hidden');
passwordSection.classList.add('hidden');
appContentArea.classList.remove('hidden');
newPasswordInput.value = '';
});
cancelLoginAttemptBtn.addEventListener('click', () => {
enteredPasswordInput.value = '';
showToast("הגישה מוגנת. עליך להזין סיסמה כדי להמשיך.", "error", 3000);
appContentArea.classList.add('hidden');
passwordSection.classList.remove('hidden');
passwordEntryArea.classList.remove('hidden');
});
loginBtn.addEventListener('click', () => {
const enteredPassword = enteredPasswordInput.value;
const storedEncodedPassword = getCookie(APP_PASSWORD_COOKIE);
if (!storedEncodedPassword) {
showToast("שגיאה: לא נמצאה סיסמה שמורה.", 'error');
passwordEntryArea.classList.add('hidden');
passwordSection.classList.add('hidden');
appContentArea.classList.remove('hidden');
updatePasswordMgmtButton();
return;
}
try {
if (btoa(enteredPassword) === storedEncodedPassword) {
showToast("התחברת בהצלחה!");
passwordEntryArea.classList.add('hidden');
passwordSection.classList.add('hidden');
appContentArea.classList.remove('hidden');
enteredPasswordInput.value = '';
cancelLoginAttemptBtn.classList.add('hidden');
updatePasswordMgmtButton();
} else {
showToast("סיסמה שגויה. נסה שוב.", 'error');
enteredPasswordInput.value = '';
}
} catch (e) {
showToast("שגיאה בעיבוד הסיסמה.", 'error');
}
});
function saveReminder() {
const reminderText = reminderTextElement.value.trim();
if (reminderText === "") {
showToast("אנא הזן תוכן לתזכורת.", 'error');
return;
}
const cookieName = REMINDER_PREFIX + Date.now();
setCookie(cookieName, reminderText, 365);
showToast("התזכורת נשמרה!");
reminderTextElement.value = "";
if (!remindersListArea.classList.contains('hidden')) {
displayReminders();
}
}
function displayReminders() {
remindersListDiv.innerHTML = "";
const allCookies = getAllReminderCookies();
let remindersFound = false;
const sortedCookieNames = Object.keys(allCookies).sort((a, b) => {
return parseInt(b.substring(REMINDER_PREFIX.length)) - parseInt(a.substring(REMINDER_PREFIX.length));
});
for (const cookieName of sortedCookieNames) {
remindersFound = true;
const reminderValue = allCookies[cookieName];
const reminderElement = document.createElement('div');
reminderElement.classList.add('reminder-item');
const textSpan = document.createElement('span');
textSpan.classList.add('reminder-item-text');
textSpan.textContent = reminderValue;
const deleteButton = document.createElement('button');
deleteButton.classList.add('delete-btn');
deleteButton.textContent = "מחק";
deleteButton.onclick = function() {
showConfirmation(`האם אתה בטוח שברצונך למחוק את התזכורת: "${reminderValue.substring(0,20)}..."?`, () => {
eraseCookie(cookieName);
showToast("התזכורת נמחקה.");
displayReminders();
});
};
reminderElement.appendChild(deleteButton);
reminderElement.appendChild(textSpan);
remindersListDiv.appendChild(reminderElement);
}
if (!remindersFound) {
remindersListDiv.innerHTML = "<p>לא נמצאו תזכורות שמורות.</p>";
}
}
function toggleRemindersDisplay() {
remindersListArea.classList.toggle('hidden');
if (remindersListArea.classList.contains('hidden')) {
toggleRemindersBtn.textContent = "הצג את כל התזכורות";
} else {
toggleRemindersBtn.textContent = "הסתר תזכורות";
displayReminders();
}
}
function deleteAllReminders() {
showConfirmation("האם אתה בטוח שברצונך למחוק את *כל* התזכורות? לא ניתן יהיה לשחזר פעולה זו.", () => {
const allReminderCookies = getAllReminderCookies();
let remindersWereDeleted = false;
for (const cookieName in allReminderCookies) {
eraseCookie(cookieName);
remindersWereDeleted = true;
}
if (remindersWereDeleted) {
showToast("כל התזכורות נמחקו בהצלחה!");
} else {
showToast("לא נמצאו תזכורות למחיקה.", "error");
}
displayReminders();
});
}
window.onload = function() {
const storedPassword = getCookie(APP_PASSWORD_COOKIE);
if (storedPassword) {
appContentArea.classList.add('hidden');
passwordSection.classList.remove('hidden');
passwordEntryArea.classList.remove('hidden');
passwordSetupArea.classList.add('hidden');
cancelLoginAttemptBtn.classList.remove('hidden');
} else {
appContentArea.classList.remove('hidden');
passwordSection.classList.add('hidden');
cancelLoginAttemptBtn.classList.add('hidden');
}
updatePasswordMgmtButton();
newPasswordInput.addEventListener('keypress', function(event) {
if (event.key === 'Enter' || event.keyCode === 13) { setPasswordBtn.click(); }
});
enteredPasswordInput.addEventListener('keypress', function(event) {
if (event.key === 'Enter' || event.keyCode === 13) { loginBtn.click(); }
});
saveReminderBtn.addEventListener('click', saveReminder);
reminderTextElement.addEventListener('keypress', function(event) {
if (event.key === 'Enter' || event.keyCode === 13) {
event.preventDefault();
saveReminder();
}
});
toggleRemindersBtn.addEventListener('click', toggleRemindersDisplay);
deleteAllRemindersBtn.addEventListener('click', deleteAllReminders);
};
</script>
</body>
</html>