File size: 9,359 Bytes
8196597
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// Create needed constants
const list = document.querySelector('ul');
const titleInput = document.querySelector('#title');
const dateInput = document.querySelector('#date');
const contentInput = document.querySelector('#content');
const form = document.querySelector('form');
const newBtn = document.querySelector('#newBtn');
// Create an instance of a db object for us to store the open database in
let db;
// Open our database; it is created if it doesn't already exist
// (see the upgradeneeded handler below)
const openRequest = window.indexedDB.open("notes_db", 1);
// error handler signifies that the database didn't open successfully
openRequest.addEventListener("error", () => console.error("Database failed to open"));
// Create a submit event handler so that when the form is submitted the addData() function is run
form.addEventListener("submit", addData);
// success handler signifies that the database opened successfully
openRequest.addEventListener("success", () => {
    console.log("Database opened successfully");
    // Store the opened database object in the db variable. 
    // This is used a lot below.
    db = openRequest.result;
    // Run the displayData() function to display the notes already in the IDB
    displayData();
});
// Finally for this section, we'll add probably the most important event 
// handler for setting up the database: upgradeneeded. This handler runs if the 
// database has not already been set up, or if the database is opened with a 
// bigger version number than the existing stored database (when performing an 
// upgrade). Add the following code, below your previous handler: 
// Set up the database tables if this has not already been done.
// Here we first grab a reference to the existing database from the result 
// property of the event's target (e.target.result), which is the request 
// object. This is equivalent to the line db = openRequest.result; inside the 
// success event handler, but we need to do this separately here because the 
// upgradeneeded event handler (if needed) will run before the success event 
// handler, meaning that the db value wouldn't be available if we didn't do 
// this.
openRequest.addEventListener("upgradeneeded", (e) => {
    // Grab a reference to the opened database
    db = e.target.result;
    // Create an objectStore in our database to store notes and an 
    // auto-incrementing key
    // An objectStore is similar to a 'table' in a relational database
    const objectStore = db.createObjectStore("notes_os", {
        keyPath: "id",
        autoIncrement: true,
    });
    // Define what data items the objectStore will contain
    objectStore.createIndex("title", "title", { unique: false });
    objectStore.createIndex("content", "content", { unique: false });
    objectStore.createIndex("date", "date", { unique: false });
    // Print the outcome of the setup
    console.log("Database setup completed.");
});
// Define the addData() function
function addData(e) {
    // prevent default - we don't want the form to submit in the conventional way
    e.preventDefault();
    // grab the values entered into the form fields and store them in an object ready for being inserted into the DB
    const newItem = {
        title: titleInput.value,
        content: contentInput.value,
        date: dateInput.value
    };
    // open a read/write db transaction, ready for adding the data,
    // name of the db: notes_os
    // IDBDatabase.transaction()
    const transaction = db.transaction(["notes_os"], "readwrite");
    // call an object store that's already been added to the database
    // IDBTransaction.objectStore()
    const objectStore = transaction.objectStore("notes_os");
    // Make a request to add our newItem object to the object store
    //  IDBObjectStore.add()
    const addRequest = objectStore.add(newItem);
    // If the transaction is successful
    addRequest.addEventListener("success", () => {
        // Clear the form, ready for adding the next entry
        titleInput.value = "";
        contentInput.value = "";
        dateInput.value = "";
    });
    // Report on the success of the transaction completing, when everything is done
    transaction.addEventListener("complete", () => {
        console.log("Transaction completed: database modification finished.");
        // update the display of data to show the newly added item, by running displayData() again.
        displayData();
    });
    // If there is error in the transaction
    transaction.addEventListener("error", () => console.log("Transaction not opened due to error"));
}
// Define the displayData() function
function displayData() {
    // Here we empty the contents of the list element each time the display is updated
    // If you didn't do this, you'd get duplicates listed each time a new note is added
    while (list.firstChild) {
        list.removeChild(list.firstChild);
    }
    // Open our object store and then get a cursor - which iterates through all the
    // different data items in the store
    const transaction = db.transaction("notes_os");
    const objectStore = transaction.objectStore("notes_os");
    // IDBObjectStore: openCursor(). Returns an IDBRequest object, and, in a 
    // separate thread, returns a new IDBCursorWithValue object. Used for 
    // iterating through an object store with a cursor. 
    objectStore.openCursor().addEventListener("success", (e) => {
        // Get a reference to the cursor
        const cursor = e.target.result;
        // If there is still another data item to iterate through, keep running this code,
        // In short:
        // if (cursor) {
        //     cursor.value contains the current record being iterated through
        //     this is where you'd do something with the result
        //     cursor.continue();
        //} 
        // else {
        //     no more results
        //}
        if (cursor) {
            // Create a list item, h3, and p to put each data item inside when displaying it
            // structure the HTML fragment, and append it inside the list
            const listItem = document.createElement("li");
            const h3 = document.createElement("h3");
            const para = document.createElement("p");
            listItem.appendChild(h3);
            listItem.appendChild(para);
            list.appendChild(listItem);
            // Put the data from the cursor inside the h3 and para
            h3.textContent = cursor.value.title;
            para.textContent = `${cursor.value.date}: ${cursor.value.content}`;
            // Store the ID of the data item inside an attribute on the listItem, so we know
            // which item it corresponds to. This will be useful later when we want to delete items
            listItem.setAttribute("data-note-id", cursor.value.id);
            // Create a button and place it inside each listItem
            const deleteBtn = document.createElement("button");
            listItem.appendChild(deleteBtn);
            deleteBtn.textContent = "Delete";
            // Set an event handler so that when the button is clicked, the deleteItem()
            // function is run
            deleteBtn.addEventListener("click", deleteItem);
            // Iterate to the next item in the cursor
            cursor.continue();
        }
        else {
            // Again, if list item is empty, display a 'No notes stored' message
            if (!list.firstChild) {
                const listItem = document.createElement("li");
                listItem.textContent = "No notes stored.";
                list.appendChild(listItem);
            }
            // if there are no more cursor items to iterate through, say so
            console.log("Notes all displayed");
        }
    });
}
// Define the deleteItem() function
function deleteItem(e) {
    // retrieve the name of the task we want to delete. We need
    // to convert it to a number before trying to use it with IDB; IDB key
    // values are type-sensitive.
    const ulNode = e.target.parentNode;
    // const noteId = Number(e.target.parentNode.getAttribute("data-note-id"));
    // We do however need to pass the attribute through the global built-in 
    // Number() object as it is of datatype string, and therefore wouldn't be 
    // recognized by the database, which expects a number.
    const noteId = Number(ulNode.getAttribute("data-note-id"));
    // open a database transaction and delete the task, finding it using the id we retrieved above
    const transaction = db.transaction(["notes_os"], "readwrite");
    const objectStore = transaction.objectStore("notes_os");
    const deleteRequest = objectStore.delete(noteId);
    // report that the data item has been deleted
    transaction.addEventListener("complete", () => {
        // delete the parent of the button
        // which is the list item, so it is no longer displayed
        //e.target.parentNode.parentNode.removeChild(e.target.parentNode);
        ulNode.parentNode.removeChild(ulNode);
        console.log(`Note ${noteId} deleted.`);
        // Again, if list item is empty, display a 'No notes stored' message
        if (!list.firstChild) {
            const listItem = document.createElement("li");
            listItem.textContent = "No notes stored.";
            list.appendChild(listItem);
        }
    });
}