Last active
February 5, 2022 12:56
-
-
Save iancover/b0b4337aad9f4373c4d361b75be73f6c to your computer and use it in GitHub Desktop.
Shopping List example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// **** GLOBAL STATE OBJECT **** | |
var state = { | |
items: [], | |
}; | |
// **** HTML TO RENDER **** | |
var listItemTemplate = | |
'<li>' + | |
'<span class="shopping-item js-shopping-item"></span>' + | |
'<div class="shopping-items-controls">' + | |
'<button class="js-shopping-item-toggle">' + | |
'<span class="button-label">Check</span>' + | |
'</button>' + | |
'<button class="js-shopping-item-delete">' + | |
'<span class="button-label">Delete</span>' + | |
'</button>' + | |
'</div>' + | |
'</li>'; | |
// **** STATE MGMT **** | |
function addItem(state, item) { | |
state.items.push({ | |
displayName: item, | |
checkedOff: false, | |
}); | |
} | |
function getItem(state, itemIndex) { | |
return state.items[itemIndex]; | |
} | |
function deleteItem(state, itemIndex) { | |
state.items.splice(itemIndex, 1); | |
} | |
function updateItem(state, itemIndex) { | |
state.items[itemIndex] = newItemState; | |
} | |
// **** DOM MANIPULATION **** | |
function renderItem(item, itemId, itemTemplate, itemDataAttr) { | |
var element = $(itemTemplate); | |
element.find('.js-shopping-item').text(item.displayName); | |
if (item.checkedOff) { | |
element.find('.js-shopping-item').addClass('shopping-item_checked'); | |
} | |
element.find('.js-shopping-item-toggle'); | |
element.attr(itemDataAttr, itemId); | |
return element; | |
} | |
function renderList(state, listElement, itemDataAttr) { | |
var itemsHTML = state.items.map(function (item, index) { | |
return renderItem(item, index, listItemTemplate, itemDataAttr); | |
}); | |
listElement.html(itemsHTML); | |
} | |
// **** LISTENERS **** | |
function handleItemAdds( | |
formElement, | |
newItemIdentifier, | |
itemDataAttr, | |
listElement, | |
state | |
) { | |
formElement.submit(function (event) { | |
event.preventDefault(); | |
var newItem = formElement.find(newItemIdentifier).val(); | |
addItem(state, newItem); | |
renderList(state, listElement, itemDataAttr); | |
this.reset(); | |
}); | |
} | |
function handleItemDeletes( | |
formElement, | |
removeIdentifier, | |
itemDataAttr, | |
listElement, | |
state | |
) { | |
listElement.on('click', removeIdentifier, function (event) { | |
var itemIndex = parseInt($(this).closest('li').attr(itemDataAttr)); | |
deleteItem(state, itemIndex); | |
renderList(state, listElement, itemDataAttr); | |
}); | |
} | |
function handleItemToggles( | |
listElement, | |
toggleIdentifier, | |
itemDataAttr, | |
state | |
) { | |
listElement.on('click', toggleIdentifier, function (event) { | |
var itemId = $(event.currentTarget.closest('li')).attr(itemDataAttr); | |
var oldItem = getItem(state, itemId); | |
updateItem(state, itemId, { | |
displayName: oldItem.displayName, | |
checkedOff: !oldItem.checkedOff, | |
}); | |
renderList(state, listElement, itemDataAttr); | |
}); | |
} | |
// **** CONTROLLER **** | |
$(function () { | |
var formElement = $('#js-shopping-list-form'); | |
var listElement = $('.js-shopping-list'); | |
var newItemIdentifier = '#js-new-item'; | |
var removeIdentifier = '.js-shopping-item-delete'; | |
var itemDataAttr = 'data-list-item-id'; | |
var toggleIdentifier = '.js-shopping-item-toggle'; | |
handleItemAdds( | |
formElement, | |
newItemIdentifier, | |
itemDataAttr, | |
listElement, | |
state | |
); | |
handleItemDeletes( | |
formElement, | |
removeIdentifier, | |
itemDataAttr, | |
listElement, | |
state | |
); | |
handleItemToggles(listElement, toggleIdentifier, itemDataAttr, state); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<title>Shopping List</title> | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/4.2.0/normalize.min.css"> | |
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet"> | |
<link rel="stylesheet" href="main.css"> | |
</head> | |
<body> | |
<div class="container"> | |
<h1>Shopping List</h1> | |
<form id="js-shopping-list-form"> | |
<label for="shopping-list-entry">Add an item</label> | |
<input type="text" name="shopping-list-entry" id="shopping-list-entry" placeholder="e.g., broccoli"> | |
<button type="submit">Add item</button> | |
</form> | |
<ul class="shopping-list"> | |
</ul> | |
<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script> | |
<script type="text/javascript" src="app.js"></script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* { | |
box-sizing: border-box; | |
} | |
body { | |
font-family: 'Roboto', sans-serif; | |
} | |
button, | |
input[type='text'] { | |
padding: 5px; | |
} | |
button:hover { | |
cursor: pointer; | |
} | |
#shopping-list-item { | |
width: 250px; | |
} | |
.container { | |
max-width: 600px; | |
margin: 0 auto; | |
} | |
.shopping-list { | |
list-style: none; | |
padding-left: 0; | |
} | |
.shopping-list > li { | |
margin-bottom: 20px; | |
border: 1px solid grey; | |
padding: 20px; | |
} | |
.shopping-item { | |
display: block; | |
color: grey; | |
font-style: italic; | |
font-size: 20px; | |
margin-bottom: 15px; | |
} | |
.shopping-item__checked { | |
text-decoration: line-through; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment