basti1012.bplaced.net

Du siehst gerade eine vereinfachte Darstellung unserer Inhalte. Normale Ansicht mit richtiger Formatierung.
    Viele To-do Liste speichern ihre Daten im Localstorage. Diese Version nutzt den indexedDB Speicher

    Code

                                        
                                    <!DOCTYPE html>
    <!-- saved from url=(0055)https://mdn.github.io/dom-examples/to-do-notifications/ -->
    <html lang="en-US" data-lt-installed="true"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    	
    	<meta name="viewport" content="width=380">
        <script>
            window.onload = () => {
      const MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
    
      // Hold an instance of a db object for us to store the IndexedDB data in
      let db;
    
      // Create a reference to the notifications list in the bottom of the app; we will write database messages into this list by
      // appending list items as children of this element
      const note = document.getElementById('notifications');
    
      // All other UI elements we need for the app
      const taskList = document.getElementById('task-list');
      const taskForm = document.getElementById('task-form');
      const title = document.getElementById('title');
      const hours = document.getElementById('deadline-hours');
      const minutes = document.getElementById('deadline-minutes');
      const day = document.getElementById('deadline-day');
      const month = document.getElementById('deadline-month');
      const year = document.getElementById('deadline-year');
      const notificationBtn = document.getElementById('enable');
    
      // Do an initial check to see what the notification permission state is
      if (Notification.permission === 'denied' || Notification.permission === 'default') {
        notificationBtn.style.display = 'block';
      } else {
        notificationBtn.style.display = 'none';
      }
    
      note.appendChild(createListItem('App initialised.'));
    
      // Let us open our database
      const DBOpenRequest = window.indexedDB.open('toDoList', 4);
    
      // Register two event handlers to act on the database being opened successfully, or not
      DBOpenRequest.onerror = (event) => {
        note.appendChild(createListItem('Error loading database.'));
      };
    
      DBOpenRequest.onsuccess = (event) => {
        note.appendChild(createListItem('Database initialised.'));
    
        // Store the result of opening the database in the db variable. This is used a lot below
        db = DBOpenRequest.result;
    
        // Run the displayData() function to populate the task list with all the to-do list data already in the IndexedDB
        displayData();
      };
    
      // This event handles the event whereby a new version of the database needs to be created
      // Either one has not been created before, or a new version number has been submitted via the
      // window.indexedDB.open line above
      //it is only implemented in recent browsers
      DBOpenRequest.onupgradeneeded = (event) => {
        db = event.target.result;
    
        db.onerror = (event) => {
          note.appendChild(createListItem('Error loading database.'));
        };
    
        // Create an objectStore for this database
        const objectStore = db.createObjectStore('toDoList', { keyPath: 'taskTitle' });
    
        // Define what data items the objectStore will contain
        objectStore.createIndex('hours', 'hours', { unique: false });
        objectStore.createIndex('minutes', 'minutes', { unique: false });
        objectStore.createIndex('day', 'day', { unique: false });
        objectStore.createIndex('month', 'month', { unique: false });
        objectStore.createIndex('year', 'year', { unique: false });
    
        objectStore.createIndex('notified', 'notified', { unique: false });
    
        note.appendChild(createListItem('Object store created.'));
      };
    
      function displayData() {
        // First clear the content of the task list so that you don't get a huge long list of duplicate stuff each time
        // the display is updated.
        while (taskList.firstChild) {
          taskList.removeChild(taskList.lastChild);
        }
    
        // Open our object store and then get a cursor list of all the different data items in the IDB to iterate through
        const objectStore = db.transaction('toDoList').objectStore('toDoList');
        objectStore.openCursor().onsuccess = (event) => {
          const cursor = event.target.result;
          // Check if there are no (more) cursor items to iterate through
          if (!cursor) {
            // No more items to iterate through, we quit.
            note.appendChild(createListItem('Entries all displayed.'));
            return;
          }
          
          // Check which suffix the deadline day of the month needs
          const { hours, minutes, day, month, year, notified, taskTitle } = cursor.value;
          const ordDay = ordinal(day);
    
          // Build the to-do list entry and put it into the list item.
          const toDoText = `${taskTitle} — ${hours}:${minutes}, ${month} ${ordDay} ${year}.`;
          const listItem = createListItem(toDoText);
    
          if (notified === 'yes') {
            listItem.style.textDecoration = 'line-through';
            listItem.style.color = 'rgba(255, 0, 0, 0.5)';
          }
    
          // Put the item item inside the task list
          taskList.appendChild(listItem);
    
          // Create a delete button inside each list item,
          const deleteButton = document.createElement('button');
          listItem.appendChild(deleteButton);
          deleteButton.textContent = 'X';
          
          // Set a data attribute on our delete button to associate the task it relates to.
          deleteButton.setAttribute('data-task', taskTitle);
          
          // Associate action (deletion) when clicked
          deleteButton.onclick = (event) => {
            deleteItem(event);
          };
    
          // continue on to the next item in the cursor
          cursor.continue();
        };
      };
    
      // Add listener for clicking the submit button
      taskForm.addEventListener('submit', addData, false);
    
      function addData(e) {
        // Prevent default, as we don't want the form to submit in the conventional way
        e.preventDefault();
    
        // Stop the form submitting if any values are left empty.
        // This should never happen as there is the required attribute
        if (title.value === '' || hours.value === null || minutes.value === null || day.value === '' || month.value === '' || year.value === null) {
          note.appendChild(createListItem('Data not submitted — form incomplete.'));
          return;
        }
        
        // Grab the values entered into the form fields and store them in an object ready for being inserted into the IndexedDB
        const newItem = [
          { taskTitle: title.value, hours: hours.value, minutes: minutes.value, day: day.value, month: month.value, year: year.value, notified: 'no' },
        ];
    
        // Open a read/write DB transaction, ready for adding the data
        const transaction = db.transaction(['toDoList'], 'readwrite');
    
        // Report on the success of the transaction completing, when everything is done
        transaction.oncomplete = () => {
          note.appendChild(createListItem('Transaction completed: database modification finished.'));
    
          // Update the display of data to show the newly added item, by running displayData() again.
          displayData();
        };
    
        // Handler for any unexpected error
        transaction.onerror = () => {
          note.appendChild(createListItem(`Transaction not opened due to error: ${transaction.error}`));
        };
    
        // Call an object store that's already been added to the database
        const objectStore = transaction.objectStore('toDoList');
        console.log(objectStore.indexNames);
        console.log(objectStore.keyPath);
        console.log(objectStore.name);
        console.log(objectStore.transaction);
        console.log(objectStore.autoIncrement);
    
        // Make a request to add our newItem object to the object store
        const objectStoreRequest = objectStore.add(newItem[0]);
        objectStoreRequest.onsuccess = (event) => {
    
          // Report the success of our request
          // (to detect whether it has been succesfully
          // added to the database, you'd look at transaction.oncomplete)
          note.appendChild(createListItem('Request successful.'));
    
          // Clear the form, ready for adding the next entry
          title.value = '';
          hours.value = null;
          minutes.value = null;
          day.value = 01;
          month.value = 'January';
          year.value = 2020;
        };
      };
    
      function deleteItem(event) {
        // Retrieve the name of the task we want to delete
        const dataTask = event.target.getAttribute('data-task');
    
        // Open a database transaction and delete the task, finding it by the name we retrieved above
        const transaction = db.transaction(['toDoList'], 'readwrite');
        transaction.objectStore('toDoList').delete(dataTask);
    
        // Report that the data item has been deleted
        transaction.oncomplete = () => {
          // Delete the parent of the button, which is the list item, so it is no longer displayed
          event.target.parentNode.parentNode.removeChild(event.target.parentNode);
          note.appendChild(createListItem(`Task "${dataTask}" deleted.`));
        };
      };
    
      // Check whether the deadline for each task is up or not, and responds appropriately
      function checkDeadlines() {
        // First of all check whether notifications are enabled or denied
        if (Notification.permission === 'denied' || Notification.permission === 'default') {
          notificationBtn.style.display = 'block';
        } else {
          notificationBtn.style.display = 'none';
        }
    
        // Grab the current time and date
        const now = new Date();
    
        // From the now variable, store the current minutes, hours, day of the month, month, year and seconds
        const minuteCheck = now.getMinutes();
        const hourCheck = now.getHours();
        const dayCheck = now.getDate(); // Do not use getDay() that returns the day of the week, 1 to 7
        const monthCheck = now.getMonth();
        const yearCheck = now.getFullYear(); // Do not use getYear() that is deprecated.
    
        // Open a new transaction
        const objectStore = db.transaction(['toDoList'], 'readwrite').objectStore('toDoList');
        
        // Open a cursor to iterate through all the data items in the IndexedDB
        objectStore.openCursor().onsuccess = (event) => {
          const cursor = event.target.result;
          if (!cursor) return;
          const { hours, minutes, day, month, year, notified, taskTitle } = cursor.value;
    
          // convert the month names we have installed in the IDB into a month number that JavaScript will understand.
          // The JavaScript date object creates month values as a number between 0 and 11.
          const monthNumber = MONTHS.indexOf(month);
          if (monthNumber === -1) throw new Error('Incorrect month entered in database.');
    
          // Check if the current hours, minutes, day, month and year values match the stored values for each task.
          // The parseInt() function transforms the value from a string to a number for comparison
          // (taking care of leading zeros, and removing spaces and underscores from the string).
          let matched = parseInt(hours) === hourCheck;
          matched &&= parseInt(minutes) === minuteCheck;
          matched &&= parseInt(day) === dayCheck;
          matched &&= parseInt(monthNumber) === monthCheck;
          matched &&= parseInt(year) === yearCheck;
          if (matched && notified === 'no') {
            // If the numbers all do match, run the createNotification() function to create a system notification
            // but only if the permission is set
            if (Notification.permission === 'granted') {
              createNotification(taskTitle);
            }
          }
    
          // Move on to the next cursor item
          cursor.continue();
        };
      };
    
      // Ask for permission when the 'Enable notifications' button is clicked
      function askNotificationPermission() {
        // Function to actually ask the permissions
        function handlePermission(permission) {
          // Whatever the user answers, we make sure Chrome stores the information
          if (!Reflect.has(Notification, 'permission')) {
            Notification.permission = permission;
          }
    
          // Set the button to shown or hidden, depending on what the user answers
          if (Notification.permission === 'denied' || Notification.permission === 'default') {
            notificationBtn.style.display = 'block';
          } else {
            notificationBtn.style.display = 'none';
          }
        };
    
        // Check if the browser supports notifications
        if (!Reflect.has(window, 'Notification')) {
          console.log('This browser does not support notifications.');
        } else {
          if (checkNotificationPromise()) {
            Notification.requestPermission().then(handlePermission);
          } else {
            Notification.requestPermission(handlePermission);
          }
        }
      };
    
      // Check whether browser supports the promise version of requestPermission()
      // Safari only supports the old callback-based version
      function checkNotificationPromise() {
        try {
          Notification.requestPermission().then();
        } catch(e) {
          return false;
        }
    
        return true;
      };
    
      // Wire up notification permission functionality to 'Enable notifications' button
      notificationBtn.addEventListener('click', askNotificationPermission);
    
      function createListItem(contents) {
        const listItem = document.createElement('li');
        listItem.textContent = contents;
        return listItem;
      };
    
      // Create a notification with the given title
      function createNotification(title) {
        // Create and show the notification
        const img = '/to-do-notifications/img/icon-128.png';
        const text = `HEY! Your task "${title}" is now overdue.`;
        const notification = new Notification('To do list', { body: text, icon: img });
    
        // We need to update the value of notified to 'yes' in this particular data object, so the
        // notification won't be set off on it again
    
        // First open up a transaction
        const objectStore = db.transaction(['toDoList'], 'readwrite').objectStore('toDoList');
    
        // Get the to-do list object that has this title as its title
        const objectStoreTitleRequest = objectStore.get(title);
    
        objectStoreTitleRequest.onsuccess = () => {
          // Grab the data object returned as the result
          const data = objectStoreTitleRequest.result;
    
          // Update the notified value in the object to 'yes'
          data.notified = 'yes';
    
          // Create another request that inserts the item back into the database
          const updateTitleRequest = objectStore.put(data);
    
          // When this new request succeeds, run the displayData() function again to update the display
          updateTitleRequest.onsuccess = () => {
            displayData();
          };
        };
      };
    
      // Using a setInterval to run the checkDeadlines() function every second
      setInterval(checkDeadlines, 1000);
    }
    
    // Helper function returning the day of the month followed by an ordinal (st, nd, or rd)
    function ordinal(day) {
      const n = day.toString();
      const last = n.slice(-1);
      if (last === '1' && n !== '11') return `${n}st`;
      if (last === '2' && n !== '12') return `${n}nd`;
      if (last === '3' && n !== '13') return `${n}rd`;
      return `${n}th`;
    };
        </script>
    	<title>To-do list with Notifications</title>
    	<!-- Icon originated from design by Sabine Wollender: http://thenounproject.com/wosamo/ -->
    	<link rel="icon" type="image/png" href="https://mdn.github.io/dom-examples/to-do-notifications/img/icon-128.png">
     
    <style>
        /* Basic set up + sizing for containers */
    
    html,
    body {
      margin: 0;
    }
    
    html {
      width: 100%;
      height: 100%;
      font-size: 10px;
      font-family: Georgia, "Times New Roman", Times, serif;
      background: #111;
    }
    
    body {
      width: 50rem;
      position: relative;
      background: #d88;
      margin: 0 auto;
      border-left: 2px solid #d33;
      border-right: 2px solid #d33;
    }
    
    h1,
    h2 {
      text-align: center;
      background: #d88;
      font-family: Arial, Helvetica, sans-serif;
    }
    
    h1 {
      font-size: 6rem;
      margin: 0;
      background: #d66;
    }
    
    h2 {
      font-size: 2.4rem;
    }
    
    /* Bottom toolbar styling  */
    
    #toolbar {
      position: relative;
      height: 6rem;
      width: 100%;
      background: #d66;
      border-top: 2px solid #d33;
      border-bottom: 2px solid #d33;
    }
    
    #enable,
    input[type="submit"] {
      line-height: 1.8;
      font-size: 1.3rem;
      border-radius: 5px;
      border: 1px solid black;
      color: black;
      text-shadow: 1px 1px 1px black;
      border: 1px solid rgba(0, 0, 0, 0.1);
      box-shadow: inset 0px 5px 3px rgba(255, 255, 255, 0.2),
        inset 0px -5px 3px rgba(0, 0, 0, 0.2);
    }
    
    #enable {
      position: absolute;
      bottom: 0.3rem;
      right: 0.3rem;
    }
    
    #notifications {
      margin: 0;
      position: relative;
      padding: 0.3rem;
      background: #ddd;
      position: absolute;
      top: 0rem;
      left: 0rem;
      height: 5.4rem;
      width: 50%;
      overflow: auto;
      line-height: 1.2;
    }
    
    #notifications li {
      margin-left: 1.5rem;
    }
    
    /* New item form styling */
    
    .form-box {
      background: #d66;
      width: 85%;
      padding: 1rem;
      margin: 2rem auto;
      box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.7);
    }
    
    form div {
      margin-bottom: 1rem;
    }
    
    form .full-width {
      margin: 1rem auto 2rem;
      width: 100%;
    }
    
    form .half-width {
      width: 50%;
      float: left;
    }
    
    form .third-width {
      width: 33%;
      float: left;
    }
    
    form div label {
      width: 10rem;
      float: left;
      padding-right: 1rem;
      font-size: 1.6rem;
      line-height: 1.6;
    }
    
    form .full-width input {
      width: 30rem;
    }
    
    form .half-width input {
      width: 8.75rem;
    }
    
    form .third-width select {
      width: 13.5rem;
    }
    
    form div input[type="submit"] {
      clear: both;
      width: 20rem;
      display: block;
      height: 3rem;
      margin: 0 auto;
      position: relative;
      top: 0.5rem;
    }
    
    /* || tasks box */
    
    .task-box {
      width: 85%;
      padding: 1rem;
      margin: 2rem auto;
      font-size: 1.8rem;
    }
    
    .task-box ul {
      margin: 0;
      padding: 0;
    }
    
    .task-box li {
      list-style-type: none;
      padding: 1rem;
      border-bottom: 2px solid #d33;
    }
    
    .task-box li:last-child {
      border-bottom: none;
    }
    
    .task-box li:last-child {
      margin-bottom: 0rem;
    }
    
    .task-box button {
      margin-left: 2rem;
      font-size: 1.6rem;
      border: 1px solid #eee;
      border-radius: 5px;
      box-shadow: inset 0 -2px 5px rgba(0, 0, 0, 0.5) 1px 1px 1px black;
    }
    
    /* setting cursor for interactive controls */
    
    button,
    input[type="submit"],
    select {
      cursor: pointer;
    }
    
    /* media query for small screens */
    
    @media (max-width: 32rem) {
      body {
        width: 100%;
        border-left: none;
        border-right: none;
      }
    
      form div {
        clear: both;
      }
    
      form .full-width {
        margin: 1rem auto;
      }
    
      form .half-width {
        width: 100%;
        float: none;
      }
    
      form .third-width {
        width: 100%;
        float: none;
      }
    
      form div label {
        width: 36%;
        padding-left: 1rem;
      }
    
      form input,
      form select,
      form label {
        line-height: 2.5rem;
        font-size: 2rem;
      }
    
      form .full-width input {
        width: 50%;
      }
    
      form .half-width input {
        width: 50%;
      }
    
      form .third-width select {
        width: 50%;
      }
    
      #enable {
        right: 1rem;
      }
    }
    
        
    </style>
    </head>
    <body>
    
    <h1>To-do list</h1>
    
    <div class="task-box">
    
    <ul id="task-list"><li>rrrr — 12:00, June 09th 2023.<button data-task="rrrr">X</button></li></ul>
    
    </div>
    
    <div class="form-box">
    <h2>Add new to-do item.</h2>
    
    <form id="task-form" action="https://mdn.github.io/dom-examples/to-do-notifications/index.html">
      <div class="full-width"><label for="title">Task title:</label><input type="text" id="title" required=""></div>
      <div class="half-width"><label for="deadline-hours">Hours (hh):</label><input type="number" id="deadline-hours" required=""></div>
      <div class="half-width"><label for="deadline-minutes">Mins (mm):</label><input type="number" id="deadline-minutes" required=""></div>
      <div class="third-width"><label for="deadline-day">Day:</label>
            <select id="deadline-day" required="">
              <option value="01">01</option>
              <option value="02">02</option>
              <option value="03">03</option>
              <option value="04">04</option>
              <option value="05">05</option>
              <option value="06">06</option>
              <option value="07">07</option>
              <option value="08">08</option>
              <option value="09">09</option>
              <option value="10">10</option>
              <option value="11">11</option>
              <option value="12">12</option>
              <option value="13">13</option>
              <option value="14">14</option>
              <option value="15">15</option>
              <option value="16">16</option>
              <option value="17">17</option>
              <option value="18">18</option>
              <option value="19">19</option>
              <option value="20">20</option>
              <option value="21">21</option>
              <option value="22">22</option>
              <option value="23">23</option>
              <option value="24">24</option>
              <option value="25">25</option>
              <option value="26">26</option>
              <option value="27">27</option>
              <option value="28">28</option>
              <option value="29">29</option>
              <option value="30">30</option>
              <option value="31">31</option>
            </select></div>
    
      <div class="third-width"><label for="deadline-month">Month:</label>
           <select id="deadline-month" required="">
             <option value="January">January</option>
             <option value="February">February</option>
             <option value="March">March</option>
             <option value="April">April</option>
             <option value="May">May</option>
             <option value="June">June</option>
             <option value="July">July</option>
             <option value="August">August</option>
             <option value="September">September</option>
             <option value="October">October</option>
             <option value="November">November</option>
             <option value="December">December</option>
           </select></div>
    
      <div class="third-width"><label for="deadline-year">Year:</label>
           <select id="deadline-year" required="">
    	 <option value="2025">2025</option>
             <option value="2024">2024</option>
             <option value="2023">2023</option>
             <option value="2022">2022</option>
             <option value="2021">2021</option>
             <option value="2020">2020</option>
             <option value="2019">2019</option>
             <option value="2018">2018</option>
           </select></div>
    
      <div><input type="submit" id="submit" value="Add Task"></div>
      <div></div>
    </form>
    </div>
    
    <div id="toolbar">
      <ul id="notifications">
    
      <li>App initialised.</li><li>Object store created.</li><li>Database initialised.</li><li>Entries all displayed.</li><li>Request successful.</li><li>Transaction completed: database modification finished.</li><li>Entries all displayed.</li></ul>
    
      <button id="enable" style="display: block;">
        Enable notifications
      </button>
    </div>
    
    
    
    </body></html>