إنشاء تطبيق ملاحظات باستخدام HTML، CSS، وJavaScript

Example Image

في هذا الموضوع، سنتناول كيفية إنشاء تطبيق ملاحظات بسيط وفعّال باستخدام HTML, CSS, وJavaScript. سيتمكن المستخدمون من خلال هذا التطبيق من إضافة ملاحظاتهم الخاصة، تعديلها، وحتى حذفها. هذا التطبيق مثالي لتنظيم الأفكار والمهام اليومية.

كيف يعمل تطبيق الملاحظات؟

1.  واجهة المستخدم : يحتوي التطبيق على واجهة بسيطة وسهلة الاستخدام، حيث يمكن للمستخدمين إضافة ملاحظات جديدة بالضغط على أيقونة الإضافة. يظهر نموذج لإدخال عنوان الملاحظة ووصفها.
2.  إضافة ملاحظة : عند تعبئة النموذج والضغط على زر الإضافة، يتم حفظ الملاحظة في التخزين المحلي للمتصفح (LocalStorage)، مما يسمح بالحفاظ على البيانات حتى بعد إغلاق المتصفح.
3.  عرض الملاحظات : يتم عرض الملاحظات المحفوظة تلقائيًا على الصفحة، مع إمكانية تحديثها أو حذفها.

 شرح الكود:

-  HTML : يحتوي على هيكل الصفحة الأساسي، بما في ذلك النموذج لإدخال الملاحظات والقائمة لعرضها.
-  CSS : يعرف أسلوب الواجهة، مثل تنسيق النموذج والملاحظات.
-  JavaScript : يتعامل مع الوظائف الديناميكية للتطبيق، مثل إضافة، تعديل، وحذف الملاحظات، وكذلك حفظها واسترجاعها من التخزين المحلي.

كيفية تضمين الكود في صفحات بلوجر:

لإضافة هذا التطبيق إلى مدونة بلوجر، اتبع الخطوات التالية:
1.  إنشاء صفحة جديدة : من لوحة تحكم بلوجر، اذهب إلى "الصفحات" ثم اختر "صفحة جديدة".
2.  تضمين الكود : في محرر الصفحة، قم بالتبديل إلى وضع HTML بالضغط على زر "HTML"، ثم الصق كود HTML, CSS, وJavaScript لتطبيق الملاحظات.
3.  تخصيص وحفظ : يمكنك تخصيص الكود حسب حاجتك قبل الحفظ. بعد التخصيص، احفظ الصفحة.

الكود المستخدم في الدرس :

HTML - CSS - JavaScript
<!-- Coding By alicomputer7 -->
    <link rel="stylesheet" href="style.css">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- Iconscout Link For Icons -->
    <link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.0/css/line.css">
     <div class="popup-box">
      <div class="popup">
        <div class="content">
          <header>
            <p></p>
            <i class="uil uil-times"></i>
          </header>
          <form action="#">
            <div class="row title">
              <label>عنوان</label>
              <input type="text" spellcheck="false">
            </div>
            <div class="row description">
              <label>وصف</label>
              <textarea spellcheck="false"></textarea>
            </div>
            <button></button>
          </form>
        </div>
      </div>
    </div>
  <div class="wrapper">
     <li class="add-box">
      <div class="icon"><i class="uil uil-plus"></i></div>
      <p>أضف ملاحظة جديدة</p>
   </li>
</div>

<style>
.wrapper{display: grid;gap: 20px;grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));}.wrapper li{height: 250px;list-style: none;border-radius: 7px;padding: 15px;background: #fff;}.add-box, .icon, .bottom-content, .popup, header, .settings .menu li{display: flex;align-items: center;justify-content: space-between;}.add-box{cursor: pointer;flex-direction: column;justify-content: center;}.add-box .icon{height: 78px;width: 78px;color: var(--themeLink);font-size: 40px;border-radius: 50%;justify-content: center;border: 2px dashed var(--themeLink);margin-top: 20px;}.add-box p{color: var(--themeLink);font-weight: 500;margin-top: 20px;margin-block: 0.9em !important;}.note{display: flex;flex-direction: column;justify-content: space-between;}.note .details{max-height: 165px;overflow-y: hidden;}.note .details::-webkit-scrollbar, .popup textarea::-webkit-scrollbar{width: 0;}.note .details:hover::-webkit-scrollbar, .popup textarea:hover::-webkit-scrollbar{width: 5px;}.note .details:hover::-webkit-scrollbar-track, .popup textarea:hover::-webkit-scrollbar-track{background: #f1f1f1;border-radius: 25px;}.note .details:hover::-webkit-scrollbar-thumb, .popup textarea:hover::-webkit-scrollbar-thumb{background: #e6e6e6;border-radius: 25px;}.note p{font-size: 22px;font-weight: 500;position: relative;top: -7px;}.note > .details > span{display: block;color: #575757;font-size: 14px;}.note .bottom-content{top: 20px;border-block-start: var(--footerBd-line) solid var(--footerBd-color);margin: 0 -20px;position: relative;padding: 20px;}.bottom-content span{color: #6D6D6D;font-size: 14px;}.bottom-content .settings{position: relative;}.bottom-content .settings i{color: #6D6D6D;cursor: pointer;font-size: 15px;}.settings .menu{z-index: 1;bottom: 0;left: 0;padding: 5px 0;background: var(--headerBg);position: absolute;border-radius: 4px;transform: scale(0);transform-origin: bottom left;border: var(--buttonBd-line) solid var(--buttonBd-color);transition: transform 0.2s ease;}.settings.show .menu{transform: scale(1);}.settings .menu li{height: 25px;font-size: 16px;margin-bottom: 2px;padding: 17px 15px;cursor: pointer;box-shadow: none;border-radius: 0;justify-content: flex-start;border: none;}.menu li:last-child{margin-bottom: 0;}.menu li:hover{background: #f5f5f5;}.menu li i{padding-left: 8px;}.popup-box{position: fixed;top: 0;left: 0;z-index: 2;height: 100%;width: 100%;background: rgba(0,0,0,0.4);}.popup-box .popup{position: absolute;top: 50%;left: 50%;z-index: 3;width: 100%;max-width: 400px;justify-content: center;transform: translate(-50%, -50%) scale(0.95);}.popup-box, .popup{opacity: 0;pointer-events: none;transition: all 0.25s ease;}.popup-box.show, .popup-box.show .popup{opacity: 1;pointer-events: auto;}.popup-box.show .popup{transform: translate(-50%, -50%) scale(1);}.popup .content{border-radius: 5px;background: #fff;width: calc(100% - 15px);box-shadow: 0 0 15px rgba(0,0,0,0.1);}.content header{padding: 15px 25px;border-bottom: 1px solid #ccc;}.content header p{font-size: 20px;font-weight: 500;}.content header i{color: #8b8989;cursor: pointer;font-size: 23px;right: 5px;position: relative;}.content form{margin: 15px 25px 35px;}.content form .row{margin-bottom: 20px;}form .row label{font-size: 18px;display: block;margin-bottom: 6px;}form :where(input, textarea){height: 50px;width: 100%;outline: none;font-size: 17px;padding: 0 15px;border-radius: 4px;border: 1px solid #999;}form :where(input, textarea):focus{box-shadow: 0 2px 4px rgba(0,0,0,0.11);}form .row textarea{height: 150px;resize: none;padding: 8px 15px;}form button{width: 100%;height: 50px;color: #fff;outline: none;border: none;cursor: pointer;font-size: 17px;border-radius: 4px;color: var(--themeBg);background-color: var(--buttonBg);}.widget .title::after {display: none;}.popup .content {border-radius: 5px;background: #fff;width: calc(100% - 15px);border: var(--buttonBd-line) solid var(--buttonBd-color) !important;background-color: var(--headerBg) !important;}.content header {padding: 15px 25px;border-bottom: var(--headerBd-line) solid var(--headerBd-color);height: 60px;}form :where(input, textarea) {height: 50px;width: 100%;outline: none;font-size: 17px;padding: 0 15px !important;border-radius: 4px;border: 1px solid #999;border: var(--buttonBd-line) solid var(--buttonBd-color) !important;}form .row textarea {min-height: 150px;resize: none;padding: 15px 15px !important;border: var(--buttonBd-line) solid var(--buttonBd-color);box-shadow: none;}.wrapper li {height: 250px;list-style: none;border-radius: 7px;padding: 20px;background: #fff;background-color: var(--headerBg) !important;border: var(--buttonBd-line) solid var(--buttonBd-color);}.note {color: inherit;}form input:is([type="text"], [type="email"]), form textarea {box-shadow: none;}.pE p {margin-block: 0;}</style>

<script>
const addBox=document.querySelector(".add-box"),popupBox=document.querySelector(".popup-box"),popupTitle=popupBox.querySelector("header p"),closeIcon=popupBox.querySelector("header i"),titleTag=popupBox.querySelector("input"),descTag=popupBox.querySelector("textarea"),addBtn=popupBox.querySelector("button"),notes=JSON.parse(localStorage.getItem("notes")||"[]");let updateId,isUpdate=!1;function showNotes(){document.querySelectorAll(".note").forEach((e=>e.remove())),notes.forEach(((e,t)=>{let o=e.description.replaceAll("\n","<br>"),n=`<li class="note">\n                        <div class="details">\n                            <p>${e.title}</p>\n                            <span>${o}</span>\n                        </div>\n                        <div class="bottom-content">\n                            <span>${e.date}</span>\n                            <div class="settings">\n                                <i onclick="showMenu(this)" class="uil uil-ellipsis-h"></i>\n                                <ul class="menu">\n                                    <li onclick="updateNote(${t}, '${e.title}', '${e.description}')"><i class="uil uil-pen"></i>تحرير</li>\n                                    <li onclick="deleteNote(${t})"><i class="uil uil-trash"></i>حذف</li>\n                                </ul>\n                            </div>\n                        </div>\n                    </li>`;addBox.insertAdjacentHTML("afterend",n)}))}function showMenu(e){e.parentElement.classList.add("show"),document.addEventListener("click",(t=>{"I"==t.target.tagName&&t.target==e||e.parentElement.classList.remove("show")}))}function deleteNote(e){const t=document.createElement("div");t.style.position="fixed",t.style.top="0",t.style.left="0",t.style.width="100%",t.style.height="100vh",t.style.backgroundColor="rgba(0, 0, 0, 0.7)",t.style.display="flex",t.style.justifyContent="center",t.style.alignItems="center",t.style.zIndex="9999";const o=document.createElement("div");o.style.background="#fff",o.style.padding="30px",o.style.borderRadius="10px",o.style.boxShadow="0 4px 8px rgba(0, 0, 0, 0.2)",o.style.textAlign="center",o.style.maxWidth="400px",o.style.margin="0 20px",o.innerHTML='\n        <h2 style="color: #333; margin-bottom: 20px;">تأكيد الحذف</h2>\n        <p style="color: #555; margin-bottom: 30px;">هل أنت متأكد من أنك تريد حذف هذه الملاحظة؟</p>\n        <button id="confirmDelete" style="background-color: #e74c3c; color: #fff; border: none; border-radius: 5px; padding: 10px 20px; margin-left: 10px; cursor: pointer;">تأكيد الحذف</button>\n        <button id="cancelDelete" style="background-color: #3498db; color: #fff; border: none; border-radius: 5px; padding: 10px 20px; cursor: pointer;">إلغاء</button>\n    ',t.appendChild(o),document.body.appendChild(t);const n=document.getElementById("confirmDelete"),l=document.getElementById("cancelDelete");[n,l].forEach((e=>{e.onmouseover=()=>e.style.opacity="0.8",e.onmouseout=()=>e.style.opacity="1"})),l.addEventListener("click",(function(){document.body.removeChild(t)})),n.addEventListener("click",(function(){notes.splice(e,1),localStorage.setItem("notes",JSON.stringify(notes)),showNotes(),document.body.removeChild(t)}))}function updateNote(e,t,o){updateId=e,isUpdate=!0,addBox.click(),titleTag.value=t,descTag.value=o,popupTitle.innerText="تحديث ملاحظة",addBtn.innerText="تحديث ملاحظة"}addBox.addEventListener("click",(()=>{popupTitle.innerText="أضف ملاحظة جديدة",addBtn.innerText="اضف ملاحظة",popupBox.classList.add("show"),window.innerWidth>660&&titleTag.focus()})),closeIcon.addEventListener("click",(()=>{isUpdate=!1,titleTag.value=descTag.value="",popupBox.classList.remove("show")})),showNotes(),addBtn.addEventListener("click",(e=>{e.preventDefault();let t=titleTag.value.trim(),o=descTag.value.trim(),n=new Date,l=n.getDate(),i=n.getFullYear(),s={title:t,description:o,date:`${l} ${n.toLocaleString("ar-EG",{month:"long"})} ${i}`};isUpdate?(isUpdate=!1,notes[updateId]=s):notes.push(s),localStorage.setItem("notes",JSON.stringify(notes)),showNotes(),closeIcon.click()}));
</script>

باتباع هذه الخطوات، ستكون قد أضفت تطبيق الملاحظات إلى صفحة في مدونتك على بلوجر. يمكن لزوار مدونتك الآن استخدام هذه الأداة لتدوين ملاحظاتهم بكل سهولة ويسر.

هذا الشرح يوفر نظرة عامة حول كيفية إنشاء وتضمين تطبيق ملاحظات باستخدام الأكواد البرمجية في صفحات بلوجر، مما يجعله إضافة قيمة لأي مدونة أو موقع إلكتروني.