Skip to content

Commit 3a582ff

Browse files
15 - Local storage and event delegation (#2)
* First form event listener * Logal storage setup * Added function comment blocks * Added check/uncheck all, plus clear items buttons * Check/uncheck functionality improvements * Amends
1 parent 267c37e commit 3a582ff

1 file changed

Lines changed: 176 additions & 2 deletions

File tree

15 - LocalStorage/index-START.html

Lines changed: 176 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,190 @@ <h2>LOCAL TAPAS</h2>
2424
<input type="text" name="item" placeholder="Item Name" required>
2525
<input type="submit" value="+ Add Item">
2626
</form>
27+
<button class="check-items">Check All</button>
28+
<button class="clear">Clear Items</button>
2729
</div>
2830

2931
<script>
3032
const addItems = document.querySelector('.add-items');
3133
const itemsList = document.querySelector('.plates');
32-
const items = [];
3334

35+
// Try to get the 'items' from localStorage and parse it as JSON. If it doesn't exist, use an empty array.
36+
const items = JSON.parse( localStorage.getItem( 'items' ) ) || [];
37+
38+
const checkItemsButton = document.querySelector('.check-items');
39+
const clearButton = document.querySelector('.clear');
40+
41+
/**
42+
* This function is called when the form is submitted to add a new item to the list.
43+
* It prevents the default form submission behavior, gets the value from the input field,
44+
* creates a new item object, adds it to the items array, updates the displayed list,
45+
* saves the updated items array to localStorage, and resets the form.
46+
*
47+
* @param {Event} e - The event object from the form submission.
48+
* @returns {void}
49+
*/
50+
function addItem( e ) {
51+
// Prevent the form from refreshing the page when it is submitted
52+
e.preventDefault();
53+
54+
// Get the value of the input field with name 'item' from the form
55+
// We can use 'this' to refer to the form element that triggered the event
56+
// We use the first parentheses to get the input element first and then we access its value
57+
const text = ( this.querySelector( '[name=item]' ) ).value;
58+
59+
// Create an item object with the name from the input and a done property set to false
60+
const item = {
61+
text,
62+
done: false
63+
};
64+
65+
// Add the new item to the items array
66+
items.push( item );
67+
68+
// Call the populateList function to update the displayed list of items
69+
populateList( items, itemsList );
70+
71+
// Save the updated items array to localStorage as a JSON string
72+
localStorage.setItem( 'items', JSON.stringify( items ) );
73+
74+
// Reset the form to clear the input field after adding the item
75+
this.reset();
76+
77+
// Revert button text to 'Check All' if any item is unchecked, otherwise set it to 'Uncheck All'
78+
updateCheckItemsButton();
79+
}
80+
81+
/**
82+
* This function populates the list of plates in the DOM.
83+
* It takes an array of plate objects and a DOM element to display the list.
84+
* Each plate object should have a 'text' property and a 'done' property.
85+
*
86+
* @param {Array} plates - The array of plate objects to display.
87+
* @param {HTMLElement} platesList - The DOM element to display the list of plates.
88+
* @returns {void}
89+
*/
90+
function populateList( plates = [], platesList ) {
91+
// Clear the existing content of the platesList element before populating it with new items
92+
platesList.innerHTML = '';
93+
94+
// Iterate over the array of plates and create a list item for each plate
95+
plates.forEach( ( plate, i ) => {
96+
const li = document.createElement( 'li' );
97+
98+
const checkbox = document.createElement( 'input' );
99+
checkbox.type = 'checkbox';
100+
checkbox.dataset.index = i;
101+
checkbox.id = `item${i}`;
102+
checkbox.checked = plate.done;
103+
104+
const label = document.createElement( 'label' );
105+
label.htmlFor = `item${i}`;
106+
label.textContent = plate.text;
107+
108+
li.append( checkbox, label );
109+
platesList.append( li );
110+
} );
111+
}
112+
113+
/**
114+
* This function toggles the 'done' property of an item when its checkbox is clicked.
115+
* It updates the items array and saves the updated array to localStorage.
116+
*
117+
* @param {Event} e - The event object from the click event.
118+
* @returns {void}
119+
*/
120+
function toggleDone( e ) {
121+
// Check if the clicked element is not a checkbox, if so, return early and do nothing
122+
if ( !e.target.matches( 'input' ) ) {
123+
return;
124+
}
125+
126+
// Get the clicked element, which should be the checkbox input
127+
const clickedElement = e.target;
128+
129+
// Get the index of the clicked checkbox from the data attribute
130+
const index = clickedElement.dataset.index;
131+
132+
// Toggle the done property of the corresponding item in the items array
133+
items[ index ].done = !items[ index ].done;
134+
135+
// Save the updated items array to localStorage as a JSON string
136+
localStorage.setItem( 'items', JSON.stringify( items ) );
137+
138+
// Revert button text to 'Check All' if any item is unchecked, otherwise set it to 'Uncheck All'
139+
updateCheckItemsButton();
140+
}
141+
142+
/**
143+
* This function updates the state of the checkItemsButton based on the current items in the list.
144+
* It checks if there are any items and if all items are marked as done to determine whether to enable or disable the button
145+
* and to set the appropriate text for the button.
146+
*
147+
* @returns {void}
148+
*/
149+
function updateCheckItemsButton() {
150+
const hasItems = items.length > 0;
151+
const allDone = hasItems && items.every( item => item.done );
152+
checkItemsButton.disabled = !hasItems;
153+
checkItemsButton.textContent = allDone ? 'Uncheck All' : 'Check All';
154+
}
155+
156+
/**
157+
* This function sets the 'done' property of all items in the list to the specified state (true or false).
158+
* It updates the items array, saves the updated array to localStorage, repopulates the list in the DOM,
159+
* and updates the state of the checkItemsButton.
160+
*
161+
* @param {boolean} state - The state to set for all items (true for done, false for not done).
162+
* @returns {void}
163+
*/
164+
function setAllDone( state ) {
165+
items.forEach( item => item.done = state );
166+
localStorage.setItem( 'items', JSON.stringify( items ) );
167+
populateList( items, itemsList );
168+
updateCheckItemsButton();
169+
}
170+
171+
/**
172+
* This function clears all items from the list by emptying the items array.
173+
* It updates localStorage and repopulates the list in the DOM to reflect the changes.
174+
*
175+
* @returns {void}
176+
*/
177+
function clearItems() {
178+
items.length = 0;
179+
localStorage.setItem( 'items', JSON.stringify( items ) );
180+
populateList( items, itemsList );
181+
updateCheckItemsButton();
182+
}
183+
184+
// Add an event listener to the form to handle the submit event and call the addItem function
185+
// That will add the new item to the list when the form is submitted
186+
addItems.addEventListener( 'submit', addItem );
187+
188+
// Add an event listener to the items list to handle click events and call the toggleDone function
189+
// Listen for a click on the list and then the toggleDone function will check if the click was on a checkbox
190+
// and toggle the done property of the corresponding item
191+
itemsList.addEventListener( 'click', toggleDone );
192+
193+
// When the page loads, call the populateList function to display any items that are already in localStorage
194+
// This will ensure that the list is populated with the saved items when the user revisits the page
195+
// If there are no items in localStorage, it will just display an empty list until the user adds new items
196+
// Also update the checkItemsButton state based on the loaded items - this will ensure the button is correctly enabled/disabled and has the correct text when the page loads
197+
populateList( items, itemsList );
198+
updateCheckItemsButton();
199+
200+
// Add an event listener to the checkItemsButton to handle click events
201+
// and call a function that checks or unchecks all items
202+
checkItemsButton.addEventListener( 'click', () => {
203+
const allDone = items.every( item => item.done );
204+
setAllDone( !allDone );
205+
} );
206+
207+
// Add an event listener to the clearButton to handle click events and call the clearItems function
208+
clearButton.addEventListener( 'click', clearItems );
34209
</script>
35210

36211

37212
</body>
38213
</html>
39-

0 commit comments

Comments
 (0)