To do list with plain JS to work out the hurdles before re-making with Vue.js
buttons totes nicked from this amazing pen https://codepen.io/nopr/pen/AfHin
<section class="container"> | |
<div class="heading"> | |
<img class="heading__img" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/756881/laptop.svg"> | |
<h1 class="heading__title">To-Do List</h1> | |
</div> | |
<form class="form"> | |
<div> | |
<label class="form__label" for="todo">~ Today I need to ~</label> | |
<input class="form__input" | |
type="text" | |
id="todo" | |
name="to-do" | |
size="30" | |
required> | |
<button class="button"><span>Submit</span></button> | |
</div> | |
</form> | |
<div> | |
<ul class="toDoList"> | |
</ul> | |
</div> | |
</section> |
// IEFE | |
(() => { | |
// state variables | |
let toDoListArray = []; | |
let itemId; | |
// ui variables | |
const form = document.querySelector(".form"); | |
const input = form.querySelector(".form__input"); | |
const ul = document.querySelector(".toDoList"); | |
// event listeners | |
form.addEventListener('submit', e => { | |
// prevent default behaviour - Page reload | |
e.preventDefault(); | |
// give item a unique ID | |
itemId = String(Date.now()); | |
// get/assign input value and pass through to functions | |
let toDoItem = input.value; | |
addItemToDOM(toDoItem); | |
addItemToArray(toDoItem); | |
// clear the input box. (this is default behaviour but we got rid of that) | |
input.value = ''; | |
}) | |
ul.addEventListener('click', e => { | |
let id = e.target.getAttribute('data-id') | |
if (!id) return // user clicked in something else | |
//pass id through to functions | |
removeItemFromDOM(id); | |
removeItemFromArray(id); | |
}) | |
// functions | |
function addItemToDOM(toDoItem) { | |
// create an li | |
const li = document.createElement('li') | |
li.setAttribute("data-id", itemId); | |
// add toDoItem text to li | |
li.innerText = toDoItem | |
// add li to the DOM | |
ul.appendChild(li); | |
} | |
function addItemToArray(toDoItem) { | |
// add item to array as an object with an ID so we can find and delete it later | |
const id = itemId; | |
toDoListArray.push({ toDoItem, id }); | |
console.log(toDoListArray) | |
} | |
function removeItemFromDOM(id) { | |
// get the list item by data ID | |
var li = document.querySelector('[data-id="' + id + '"]'); | |
// remove list item | |
ul.removeChild(li); | |
} | |
function removeItemFromArray(id) { | |
// create a new toDoListArray with all li's that don't match the ID | |
toDoListArray = toDoListArray.filter(item => item.id !== id); | |
console.log(toDoListArray); | |
} | |
})(); |
@import url('https://fonts.googleapis.com/css?family=Gochi+Hand'); | |
body { | |
background-color: #a39bd2; | |
height: 100vh; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
color: hsl(198, 1%, 29%); | |
font-family: 'Gochi Hand', cursive; | |
text-align: center; | |
font-size: 140%; | |
} | |
.container { | |
width: calc(100% - 100px); | |
min-height: calc(100% - 100px); | |
max-width: 500px; | |
min-width: 500px; | |
background: #f1f5f8; | |
background-image: radial-gradient(#bfc0c1 7.2%, transparent 0); | |
background-size: 25px 25px; | |
border-radius: 20px; | |
box-shadow: 4px 3px 7px 2px #00000040; | |
padding: 1rem; | |
box-sizing: border-box; | |
} | |
.heading { | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
margin-bottom: 1rem; | |
} | |
.heading__title { | |
transform: rotate(2deg); | |
padding: 0.2rem 1.2rem; | |
border-radius: 20% 5% 20% 5%/5% 20% 25% 20%; | |
background-color: hsla(166, 100%, 50%, 0.7); | |
} | |
.heading__img { | |
width: 24%; | |
} | |
.form__label { | |
display: block; | |
margin-bottom: 0.5rem; | |
} | |
.form__input { | |
box-sizing: border-box; | |
background-color: transparent; | |
padding: 0.7rem; | |
border-bottom-right-radius: 15px 3px; | |
border-bottom-left-radius:3px 15px; | |
border: solid 3px transparent; | |
border-bottom: dashed 3px #ea95e0; | |
font-family: 'Gochi Hand', cursive; | |
font-size: 1rem; | |
color: hsla(260, 2%, 25%, 0.7); | |
&:focus { | |
outline: none; | |
border: solid 3px #ea95e0; | |
} | |
} | |
.button { | |
padding: 0; | |
border: none; | |
transform: rotate(4deg); | |
transform-origin: center; | |
font-family: 'Gochi Hand', cursive; | |
text-decoration: none; | |
padding-bottom: 3px; | |
border-radius: 5px; | |
box-shadow: 0 2px 0 hsl(198, 1%, 29%); | |
transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); | |
background-image: url('data:image/gif;base64,R0lGODlhBAAEAIABAAAAAAAAACH/C1hNUCBEYXRhWE1QPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS4wLWMwNjEgNjQuMTQwOTQ5LCAyMDEwLzEyLzA3LTEwOjU3OjAxICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1LjEgV2luZG93cyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo5NUY1OENCRDdDMDYxMUUyOTEzMEE1MEM5QzM0NDVBMyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo5NUY1OENCRTdDMDYxMUUyOTEzMEE1MEM5QzM0NDVBMyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjk1RjU4Q0JCN0MwNjExRTI5MTMwQTUwQzlDMzQ0NUEzIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjk1RjU4Q0JDN0MwNjExRTI5MTMwQTUwQzlDMzQ0NUEzIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Af/+/fz7+vn49/b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397d3Nva2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7q5uLe2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl5aVlJOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0c3JxcG9ubWxramloZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlFQT05NTEtKSUhHRkVEQ0JBQD8+PTw7Ojk4NzY1NDMyMTAvLi0sKyopKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLCgkIBwYFBAMCAQAAIfkEAQAAAQAsAAAAAAQABAAAAgYEEpdoeQUAOw=='); | |
background-color: hsla(166, 100%, 50%, 0.7); | |
} | |
.button span { | |
background: #f1f5f8; | |
display: block; | |
padding: 0.5rem 1rem; | |
border-radius: 5px; | |
border: 2px solid hsl(198, 1%, 29%); | |
} | |
.button:active, .button:focus { | |
transform: translateY(4px); | |
padding-bottom: 0px; | |
outline: 0; | |
} | |
.toDoList { | |
text-align: left; | |
li { | |
position: relative; | |
padding: 0.5rem; | |
} | |
li:hover { | |
text-decoration: line-through wavy #24bffb; | |
} | |
} | |
To do list with plain JS to work out the hurdles before re-making with Vue.js
buttons totes nicked from this amazing pen https://codepen.io/nopr/pen/AfHin