diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 00000000..ed94f44b
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "git.ignoreLimitWarning": true
+}
\ No newline at end of file
diff --git a/chapter_10_todos/app.js b/chapter_10_todos/app.js
new file mode 100644
index 00000000..9cb9a57f
--- /dev/null
+++ b/chapter_10_todos/app.js
@@ -0,0 +1,61 @@
+//ADD TODOS
+//1. get a reference to this form, and store it to a variable called addForm
+const addForm = document.querySelector('.add');
+
+//4. since we want to inject the template string into the
, we need to get a reference of it
+const list = document.querySelector('.todos');
+
+//3. create a function to generate a template for the todo in
tag, and inject into the DOM.
+const generateTemplate = todo => {
+ const html = `
+
+ ${todo}
+
+
+ `;
+ //5. inject the template into the list
+ list.innerHTML += html;
+};
+
+//2. attach a submit event listener to the form. We are not listening to the submit event, and we take the event as a parameter into the callback function
+addForm.addEventListener('submit', e => {
+ //below method prevents the web page from reloading
+ e.preventDefault();
+ const todo = addForm.add.value.trim();
+ if (todo.length) {
+ generateTemplate(todo);
+ addForm.reset();
+ }
+});
+
+//DELETE TODOS
+//1. attach event listener to the list (ul)
+//2. when we click on the element, we check whether the target element was 'delete' (the trash can)
+//3. if it was, then remove the parent element of that trash can; if not we do nothing
+list.addEventListener('click', e => {
+ if (e.target.classList.contains('delete')) {
+ e.target.parentElement.remove();
+ }
+});
+
+//SEARCH TODOS
+//1. get a reference of the input field directly (not the form with the class of search), becasue we are listening to a keyup event on the input, not a submit eventon the form.
+const search = document.querySelector('.search input');
+
+//4. create a function that filters out the todos that does not include the term and add a class to them; and filters out the todos that include the term and remove the class from them.
+const filterTodos = term => {
+ Array.from(list.children)
+ .filter(todo => !todo.textContent.toLowerCase().includes(term))
+ .forEach(todo => todo.classList.add('filtered'));
+
+ Array.from(list.children)
+ .filter(todo => todo.textContent.toLowerCase().includes(term))
+ .forEach(todo => todo.classList.remove('filtered'));
+};
+
+//2. attach a keyup event listener to the input
+search.addEventListener('keyup', e => {
+ //3. get the user input, and trim it
+ const term = search.value.trim().toLowerCase();
+ filterTodos(term);
+});
diff --git a/chapter_10_todos/index.html b/chapter_10_todos/index.html
new file mode 100644
index 00000000..26324914
--- /dev/null
+++ b/chapter_10_todos/index.html
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+ Todos
+
+
+
+
+
Todo List
+
+
+
+
+ play mariokart
+
+
+
+ defeat ganon in zelda
+
+
+
+ make a veggie pie
+
+
+
+
+
+
+
+
diff --git a/chapter_10_todos/styles.css b/chapter_10_todos/styles.css
new file mode 100644
index 00000000..43d8f8e0
--- /dev/null
+++ b/chapter_10_todos/styles.css
@@ -0,0 +1,25 @@
+
+body{
+ background: #352f5b;
+}
+.container{
+ max-width: 400px;
+}
+/* [attribute] selector, it is used to select element that have specific attributes or attribute values */
+input[type=text],
+input[type=text]:focus{
+ color: #fff;
+ border: none;
+ background: rgba(0,0,0,0.2);
+ max-width: 400px;
+}
+.todos li{
+ background: #423a6f;
+ color: #fff;
+}
+.delete{
+ cursor: pointer;
+}
+.filtered {
+ display: none !important;
+}
\ No newline at end of file
diff --git a/chapter_11/date&time.js b/chapter_11/date&time.js
new file mode 100644
index 00000000..83b33ae5
--- /dev/null
+++ b/chapter_11/date&time.js
@@ -0,0 +1,31 @@
+//date & times
+
+//constructor - is going to generally create a new object for us.
+
+const now = new Date();
+
+console.log(now);
+
+//the date and time fall under the object data type
+console.log(typeof now);
+
+//year, months, day, times
+console.log('getFullYear: ', now.getFullYear());
+console.log('getMonth: ', now.getMonth());
+console.log('getDate: ', now.getDate());
+console.log('getDay: ', now.getDay());
+console.log('getHours ', now.getHours());
+console.log('getMinutes ', now.getMinutes());
+console.log('getSeconds', now.getSeconds());
+
+//timestamps
+console.log('timestamps: ', now.getTime());
+
+//date strings
+console.log('date strings: ', now.toDateString());
+
+//time strings
+console.log('time strings: ', now.toTimeString());
+
+//local date and time strings
+console.log('local date and time strings: ', now.toLocaleString());
\ No newline at end of file
diff --git a/chapter_11/datefns.js b/chapter_11/datefns.js
new file mode 100644
index 00000000..227424f6
--- /dev/null
+++ b/chapter_11/datefns.js
@@ -0,0 +1,17 @@
+//date-fns.org
+const now = new Date();
+
+// console.log(dateFns.isToday(now))
+
+// formatting options
+
+console.log(dateFns.format(now, 'YYYY'));
+console.log(dateFns.format(now, 'MMM'));
+console.log(dateFns.format(now, 'dddd'));
+console.log(dateFns.format(now, 'Do'));
+console.log(dateFns.format(now, 'dddd Do MMMM YYYY'));
+
+//comparing dates
+const before = new Date('February 1 2019 12:00:00');
+
+console.log(dateFns.distanceInWords(now, before, {addSuffix: true}))
\ No newline at end of file
diff --git a/chapter_11/digitalclock.js b/chapter_11/digitalclock.js
new file mode 100644
index 00000000..9e7ba1ef
--- /dev/null
+++ b/chapter_11/digitalclock.js
@@ -0,0 +1,22 @@
+//get a reference of the element by its class
+const clock = document.querySelector('.clock');
+
+//create a function to record the current time and store it in an template string to be injected into the DOM
+const tick = ()=>{
+ const now = new Date();
+
+ const h = now.getHours();
+ const m = now.getMinutes();
+ const s = now.getSeconds();
+
+ // console.log(h, m, s)
+ const html = `
+ ${h} :
+ ${m} :
+ ${s}
+ `;
+ clock.innerHTML = html;
+}
+
+//use the setInterval method to call the function every 1 second
+setInterval(tick, 1000);
\ No newline at end of file
diff --git a/chapter_11/index.html b/chapter_11/index.html
new file mode 100644
index 00000000..75a4a81c
--- /dev/null
+++ b/chapter_11/index.html
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+ Array Methods
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/chapter_11/timestamps.js b/chapter_11/timestamps.js
new file mode 100644
index 00000000..22d9ac55
--- /dev/null
+++ b/chapter_11/timestamps.js
@@ -0,0 +1,20 @@
+//timestamps
+const before = new Date('February 1 2019 7:30:59');
+const now = new Date();
+
+// console.log(now.getTime(), before.getTime());
+
+const diff = now.getTime() - before.getTime()
+console.log(diff)
+
+const mins = Math.round(diff/1000/60);
+const hours = Math.round(mins/60);
+const days = Math.round(hours/24);
+
+console.log(mins, hours, days);
+
+console.log(`the blog was written ${days} days ago`);
+
+//converting timestamps into date objects
+const timestamp = 1675938474990;
+console.log(new Date(timestamp));
\ No newline at end of file
diff --git a/chapter_12_Async/async-await.js b/chapter_12_Async/async-await.js
new file mode 100644
index 00000000..cec86c8e
--- /dev/null
+++ b/chapter_12_Async/async-await.js
@@ -0,0 +1,30 @@
+//async & await - set off all of our asynchronous code into a single function (asynchronous function), and then use the await keyword inside to chain promises together in a much more readable and logical way.
+
+//by adding async in front of the parenthesis, we made an asynchronous function. It always return a promise regardless of what's inside.
+const getTodos = async () => {
+ //this await keyword stalls JavaScript right here, it stops it from assigning a value to this variable until the promise has resolved. Once the promise has resolved, we can take the value from the resolve function and assign it to a variable.
+ const response = await fetch('todos/luigi.json');
+ const data = await response.json()
+ return data;
+}
+
+//***This asynchronous function itself is non-blocking. The entire block of code is being handled somewhere else in the browser, so the rest of our code could carry on if it wanted to. So, the await keyword only stalls inside the asynchronous function.
+
+console.log(1);
+console.log(2);
+
+getTodos()
+ .then(data => console.log('resolved', data))
+
+console.log(3);
+console.log(4);
+
+// fetch('todos/luigi.json').then(response => {
+// console.log('resolved', response)
+// return response.json()
+// }).then(data => {
+// console.log(data)
+// }).catch(err => {
+// console.log('rejected', err)
+// })
+
diff --git a/chapter_12_Async/custom-errors.js b/chapter_12_Async/custom-errors.js
new file mode 100644
index 00000000..b2b0a736
--- /dev/null
+++ b/chapter_12_Async/custom-errors.js
@@ -0,0 +1,22 @@
+//throwing & catching errors
+
+const getTodos = async () => {
+
+ const response = await fetch('todos/luigis.json');
+
+ if(response.status !== 200){
+ //when we through an error inside an asynchronous function, the promise returned by this asynchronous function is rejected. Therefore, if it is rejected, we are going to catch it one line 19. As a result, we get the custom error instead of the error given by the response.json() on line 12.
+ throw new Error('cannot fetch the data');
+ }
+
+ const data = await response.json();
+
+ return data;
+}
+
+getTodos()
+ .then(data => console.log('resolved: ', data))
+ .catch(err => console.log('rejected: ', err.message));
+
+
+
diff --git a/chapter_12_Async/fetch-api.js b/chapter_12_Async/fetch-api.js
new file mode 100644
index 00000000..f9efc81d
--- /dev/null
+++ b/chapter_12_Async/fetch-api.js
@@ -0,0 +1,15 @@
+//fetch api
+
+//fetch('todos/luigi.json) returns towards a promise. A promise is basically saying, at some point I will either resolve if we have a success or reject if there's an error.
+fetch('todos/luigi.json').then(response => {
+ if(response.status === 200) {
+ console.log('resolved', response)
+ return response.json()
+ }
+}).then(data => {
+ console.log(data)
+}).catch(err => {
+ console.log('rejected', err)
+})
+
+//the way the Fetch API works is that the promise is only ever rejected when we get some kind of network error. For example, if we're offlice or we can't reach the API for some reason.
\ No newline at end of file
diff --git a/chapter_12_Async/http-request-1.js b/chapter_12_Async/http-request-1.js
new file mode 100644
index 00000000..e08096d9
--- /dev/null
+++ b/chapter_12_Async/http-request-1.js
@@ -0,0 +1,24 @@
+
+// step 1: create a request object.
+
+//This is a JavaScript build-in method to create a request object.
+
+//XML represents an old data format we used to work with much before JASON arrived on the scene.
+
+//This request object can work with any kind of data: XML, JSON, plain text, etc.
+
+const request = new XMLHttpRequest();
+
+//step 4: attached an event listener to the request itself. The callback fires whenever there is a state change. And there are 4 state changes in total.
+request.addEventListener('readystatechange', ()=>{
+ // console.log(request, request.readyState);
+ if(request.readyState === 4){
+ console.log(request.responseText);
+ }
+})
+
+//step 2 : make a GET request from the designated API endpoint (where to send the request to)
+request.open('GET', 'https://jsonplaceholder.typicode.com/todos/')
+
+//step 3: to actually send the request. If we open the browser and look at Network, we should be able to see the request and the data.
+request.send();
\ No newline at end of file
diff --git a/chapter_12_Async/http-request-2.js b/chapter_12_Async/http-request-2.js
new file mode 100644
index 00000000..19a3961f
--- /dev/null
+++ b/chapter_12_Async/http-request-2.js
@@ -0,0 +1,43 @@
+const getTodos = (callback) => {
+ //step 1: create a request object.
+ //This is a JavaScript build-in method to create a request object.
+ //XML represents an old data format we used to work with much before JASON arrived on the scene.
+ //This request object can work with any kind of data: XML, JSON, plain text, etc.
+ const request = new XMLHttpRequest();
+
+ //step 4: attached an event listener to the request itself. The callback fires whenever there is a state change. And there are 4 state changes in total.
+ request.addEventListener('readystatechange', ()=>{
+ // console.log(request, request.readyState);
+ if(request.readyState === 4 && request.status === 200){
+ //check the data here. Since it passed the if statement, err is of course undefined, and the data comes through
+ callback(undefined, request.responseText);
+ } else if(request.readyState === 4){
+ //check the err here. Since it did not pass the if statement and it went to the else if statement, then err becomes true, data becomes undefined.
+ callback('could not fetch data', undefined);
+ }
+ })
+
+ //step 2 : make a GET request from the designated API endpoint (where to send the request to)
+ request.open('GET', 'https://jsonplaceholder.typicode.com/todos/')
+
+ //step 3: to actually send the request.
+ //If we open the browser and look at Network, we should be able to see the request and the data.
+ request.send();
+}
+
+console.log(1);
+console.log(2);
+
+//taking in 2 parameters to the callback function, err and data. err always comes before data because its the convention.
+ getTodos((err, data)=>{
+ console.log('callback fired!')
+ // console.log(err, data);
+ if(err){
+ console.log(err);
+ } else {
+ console.log(data)
+ }
+ });
+
+console.log(3);
+console.log(4);
\ No newline at end of file
diff --git a/chapter_12_Async/index.html b/chapter_12_Async/index.html
new file mode 100644
index 00000000..36424a74
--- /dev/null
+++ b/chapter_12_Async/index.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+ Async JavaScript
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/chapter_12_Async/jason-data-1.js b/chapter_12_Async/jason-data-1.js
new file mode 100644
index 00000000..b94946d0
--- /dev/null
+++ b/chapter_12_Async/jason-data-1.js
@@ -0,0 +1,31 @@
+//JSON data looks like an array with lots of JacaScript object inside it, but it is just a string. A string that is formatted in a way that looks like JavaScript objects (curly braces and key value).
+
+const getTodos = (callback) => {
+
+ const request = new XMLHttpRequest();
+
+ request.addEventListener('readystatechange', ()=>{
+ if(request.readyState === 4 && request.status === 200){
+ //We want to turn the JSON data(string) into objects in an array, in order to have access have its different properties - using JSON.parse()
+ const data = JSON.parse(request.responseText)
+ callback(undefined, data);
+ } else if(request.readyState === 4){
+ callback('could not fetch data', undefined);
+ }
+ })
+
+ request.open('GET', 'https://jsonplaceholder.typicode.com/todos/')
+
+ // request.open('GET', 'todos.json')
+
+ request.send();
+}
+
+ getTodos((err, data)=>{
+ console.log('callback fired!')
+ if(err){
+ console.log(err);
+ } else {
+ console.log(data)
+ }
+ });
diff --git a/chapter_12_Async/jason-data-2.js b/chapter_12_Async/jason-data-2.js
new file mode 100644
index 00000000..133d7c5d
--- /dev/null
+++ b/chapter_12_Async/jason-data-2.js
@@ -0,0 +1,27 @@
+//if we have several files(endpoints) that we need to get one after the other
+const getTodos = (apis, callback) => {
+ const request = new XMLHttpRequest();
+
+ request.addEventListener('readystatechange', ()=>{
+ if(request.readyState === 4 && request.status === 200){
+ const data = JSON.parse(request.responseText)
+ callback(undefined, data);
+ } else if(request.readyState === 4){
+ callback('could not fetch data', undefined);
+ }
+ })
+
+ request.open('GET', apis)
+ request.send();
+}
+
+//this is callback hell situation, it's very messy when there are many requests/callbacks - and this is when PROMISES comes into play
+ getTodos('todos/luigi.json', (err, data)=>{
+ console.log(data)
+ getTodos('todos/mario.json', (err, data)=>{
+ console.log(data)
+ getTodos('todos/shaun.json', (err, data)=>{
+ console.log(data)
+ })
+ })
+ });
diff --git a/chapter_12_Async/promise-1.js b/chapter_12_Async/promise-1.js
new file mode 100644
index 00000000..519425ee
--- /dev/null
+++ b/chapter_12_Async/promise-1.js
@@ -0,0 +1,45 @@
+//if we have several files(endpoints) that we need to get one after the other
+const getTodos = (apis, callback) => {
+ const request = new XMLHttpRequest();
+
+ request.addEventListener('readystatechange', ()=>{
+ if(request.readyState === 4 && request.status === 200){
+ const data = JSON.parse(request.responseText)
+ callback(undefined, data);
+ } else if(request.readyState === 4){
+ callback('could not fetch data', undefined);
+ }
+ })
+
+ request.open('GET', apis)
+ request.send();
+}
+
+//promise example
+
+const getSomething = () => {
+ // step 1: when we use promises the first thing we do is to return a new promise
+ return new Promise((resolve, reject)=>{
+ //fetch something
+ // resolve('some data');
+ reject('some error');
+ });
+}
+
+//when we resolve something in a promise, it fires the callback(first parametor) inside the then method, and that callback function takes the data we pass through to the resolve function.
+//same thing with the reject method, when promise has a reject outcome, the callback(second parameter) will fire inside the then method, and that callback function takes the data we pass through to the reject function.
+// getSomething().then((data)=>{
+// console.log(data); //will display 'some data'
+// }, (err)=>{
+// console.log(err) //will display 'some err'
+// })
+
+
+//Below works the same but looks neater, especially when it comes to chainning promises together.
+//If the promise gets resolved, then it fires the callback in the then() method. If it get rejected, instead it comes to the catch() method and fires the callback inside of it.
+
+getSomething().then(data => {
+ console.log(data)
+}).catch(err => {
+ console.log(err)
+})
\ No newline at end of file
diff --git a/chapter_12_Async/promise-2.js b/chapter_12_Async/promise-2.js
new file mode 100644
index 00000000..3d7f6048
--- /dev/null
+++ b/chapter_12_Async/promise-2.js
@@ -0,0 +1,23 @@
+const getTodos = (apis) => {
+ return new Promise((resolve, reject)=>{
+ const request = new XMLHttpRequest();
+
+ request.addEventListener('readystatechange', ()=>{
+ if(request.readyState === 4 && request.status === 200){
+ const data = JSON.parse(request.responseText)
+ resolve(data)
+ } else if(request.readyState === 4){
+ reject('encountered some error!')
+ }
+ })
+ request.open('GET', apis)
+ request.send();
+ })
+
+}
+
+getTodos('todos/luigi.json').then(data=>{
+ console.log('promise resolved: ', data)
+}).catch(err => {
+ console.log('promise rejected: ', err)
+})
\ No newline at end of file
diff --git a/chapter_12_Async/promise-3.js b/chapter_12_Async/promise-3.js
new file mode 100644
index 00000000..a6d26e87
--- /dev/null
+++ b/chapter_12_Async/promise-3.js
@@ -0,0 +1,31 @@
+const getTodos = (apis) => {
+ return new Promise((resolve, reject)=>{
+ const request = new XMLHttpRequest();
+
+ request.addEventListener('readystatechange', ()=>{
+ if(request.readyState === 4 && request.status === 200){
+ const data = JSON.parse(request.responseText)
+ resolve(data)
+ } else if(request.readyState === 4){
+ reject('encountered some error!')
+ }
+ })
+ request.open('GET', apis)
+ request.send();
+ })
+
+}
+
+//chain promises together (huge benefits)
+getTodos('todos/luigi.json').then(data=>{
+ console.log('promise 1 resolved: ', data)
+ //below line of code means the parent now has a return value of a promise
+ return getTodos('todos/mario.json');
+}).then(data => {
+ console.log('promise 2 resolved: ', data)
+ return getTodos('todos/shaun.json')
+}).then(data => {
+ console.log('promise 3 resolved: ', data)
+}).catch(err => {
+ console.log('promise rejected: ', err)
+})
\ No newline at end of file
diff --git a/chapter_12_Async/sandbox.js b/chapter_12_Async/sandbox.js
new file mode 100644
index 00000000..d9940dec
--- /dev/null
+++ b/chapter_12_Async/sandbox.js
@@ -0,0 +1,10 @@
+console.log(1)
+console.log(2)
+
+//This is asynchronous code in action. In this case we are not fetching data from a database, this is just wait in two seconds to emulate that request and then we are firing the console log.
+setTimeout(()=>{
+ console.log('callback function fired')
+}, 2000)
+
+console.log(3)
+console.log(4)
\ No newline at end of file
diff --git a/chapter_12_Async/todos.json b/chapter_12_Async/todos.json
new file mode 100644
index 00000000..17982136
--- /dev/null
+++ b/chapter_12_Async/todos.json
@@ -0,0 +1,14 @@
+[
+ {
+ "text": "play mariokart",
+ "author": "shaun"
+ },
+ {
+ "text": "buy some bread",
+ "author": "mario"
+ },
+ {
+ "text": "do the plumming",
+ "author": "luigi"
+ }
+]
diff --git a/chapter_12_Async/todos/luigi.json b/chapter_12_Async/todos/luigi.json
new file mode 100644
index 00000000..0a7cdf67
--- /dev/null
+++ b/chapter_12_Async/todos/luigi.json
@@ -0,0 +1,5 @@
+[
+ {"text": "do the plumming", "author": "Luigi"},
+ {"text": "avoid mario", "author": "Luigi"},
+ {"text": "go kart racing", "author": "Luigi"}
+]
\ No newline at end of file
diff --git a/chapter_12_Async/todos/mario.json b/chapter_12_Async/todos/mario.json
new file mode 100644
index 00000000..5ab76086
--- /dev/null
+++ b/chapter_12_Async/todos/mario.json
@@ -0,0 +1,5 @@
+[
+ {"text": "make fun of luigi", "author": "Mario"},
+ {"text": "rescue peach (again)", "author": "Mario"},
+ {"text": "go kart racing", "author": "Mario"}
+]
\ No newline at end of file
diff --git a/chapter_12_Async/todos/shaun.json b/chapter_12_Async/todos/shaun.json
new file mode 100644
index 00000000..838ef9af
--- /dev/null
+++ b/chapter_12_Async/todos/shaun.json
@@ -0,0 +1,5 @@
+[
+ {"text": "play mariokart", "author": "Shaun"},
+ {"text": "buy some bread", "author": "Shaun"},
+ {"text": "take a nap", "author": "Shaun"}
+]
\ No newline at end of file
diff --git a/chapter_13_weather_app/img/day.svg b/chapter_13_weather_app/img/day.svg
new file mode 100644
index 00000000..de48965e
--- /dev/null
+++ b/chapter_13_weather_app/img/day.svg
@@ -0,0 +1,14 @@
+
diff --git a/chapter_13_weather_app/img/icons/1.svg b/chapter_13_weather_app/img/icons/1.svg
new file mode 100644
index 00000000..00eaf5f6
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/1.svg
@@ -0,0 +1,19 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/11.svg b/chapter_13_weather_app/img/icons/11.svg
new file mode 100644
index 00000000..2eb3dea2
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/11.svg
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/12.svg b/chapter_13_weather_app/img/icons/12.svg
new file mode 100644
index 00000000..724bb2f2
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/12.svg
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/13.svg b/chapter_13_weather_app/img/icons/13.svg
new file mode 100644
index 00000000..036d5270
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/13.svg
@@ -0,0 +1,22 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/14.svg b/chapter_13_weather_app/img/icons/14.svg
new file mode 100644
index 00000000..eb4e4fc8
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/14.svg
@@ -0,0 +1,21 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/15.svg b/chapter_13_weather_app/img/icons/15.svg
new file mode 100644
index 00000000..0e9b2c64
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/15.svg
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/16.svg b/chapter_13_weather_app/img/icons/16.svg
new file mode 100644
index 00000000..0e9b2c64
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/16.svg
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/17.svg b/chapter_13_weather_app/img/icons/17.svg
new file mode 100644
index 00000000..f01f2606
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/17.svg
@@ -0,0 +1,21 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/18.svg b/chapter_13_weather_app/img/icons/18.svg
new file mode 100644
index 00000000..c7d0cc2c
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/18.svg
@@ -0,0 +1,14 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/19.svg b/chapter_13_weather_app/img/icons/19.svg
new file mode 100644
index 00000000..ebc775c0
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/19.svg
@@ -0,0 +1,18 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/2.svg b/chapter_13_weather_app/img/icons/2.svg
new file mode 100644
index 00000000..c1fc09c0
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/2.svg
@@ -0,0 +1,20 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/20.svg b/chapter_13_weather_app/img/icons/20.svg
new file mode 100644
index 00000000..888a922e
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/20.svg
@@ -0,0 +1,19 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/21.svg b/chapter_13_weather_app/img/icons/21.svg
new file mode 100644
index 00000000..888a922e
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/21.svg
@@ -0,0 +1,19 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/22.svg b/chapter_13_weather_app/img/icons/22.svg
new file mode 100644
index 00000000..c6d2fb5f
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/22.svg
@@ -0,0 +1,15 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/23.svg b/chapter_13_weather_app/img/icons/23.svg
new file mode 100644
index 00000000..e8851987
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/23.svg
@@ -0,0 +1,17 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/24.svg b/chapter_13_weather_app/img/icons/24.svg
new file mode 100644
index 00000000..c6d2fb5f
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/24.svg
@@ -0,0 +1,15 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/25.svg b/chapter_13_weather_app/img/icons/25.svg
new file mode 100644
index 00000000..3bf11e15
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/25.svg
@@ -0,0 +1,17 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/26.svg b/chapter_13_weather_app/img/icons/26.svg
new file mode 100644
index 00000000..77fbd77c
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/26.svg
@@ -0,0 +1,17 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/27.svg b/chapter_13_weather_app/img/icons/27.svg
new file mode 100644
index 00000000..367b602d
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/27.svg
@@ -0,0 +1,18 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/3.svg b/chapter_13_weather_app/img/icons/3.svg
new file mode 100644
index 00000000..c1fc09c0
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/3.svg
@@ -0,0 +1,20 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/30.svg b/chapter_13_weather_app/img/icons/30.svg
new file mode 100644
index 00000000..b45d03f5
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/30.svg
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/31.svg b/chapter_13_weather_app/img/icons/31.svg
new file mode 100644
index 00000000..caf0fd15
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/31.svg
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/32.svg b/chapter_13_weather_app/img/icons/32.svg
new file mode 100644
index 00000000..03e12e54
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/32.svg
@@ -0,0 +1,14 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/33.svg b/chapter_13_weather_app/img/icons/33.svg
new file mode 100644
index 00000000..a3d7f863
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/33.svg
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/34.svg b/chapter_13_weather_app/img/icons/34.svg
new file mode 100644
index 00000000..a3d7f863
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/34.svg
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/35.svg b/chapter_13_weather_app/img/icons/35.svg
new file mode 100644
index 00000000..ee057b31
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/35.svg
@@ -0,0 +1,16 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/36.svg b/chapter_13_weather_app/img/icons/36.svg
new file mode 100644
index 00000000..ee057b31
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/36.svg
@@ -0,0 +1,16 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/37.svg b/chapter_13_weather_app/img/icons/37.svg
new file mode 100644
index 00000000..f1f462a9
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/37.svg
@@ -0,0 +1,17 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/38.svg b/chapter_13_weather_app/img/icons/38.svg
new file mode 100644
index 00000000..ee057b31
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/38.svg
@@ -0,0 +1,16 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/39.svg b/chapter_13_weather_app/img/icons/39.svg
new file mode 100644
index 00000000..8bb77cad
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/39.svg
@@ -0,0 +1,23 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/4.svg b/chapter_13_weather_app/img/icons/4.svg
new file mode 100644
index 00000000..c1fc09c0
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/4.svg
@@ -0,0 +1,20 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/40.svg b/chapter_13_weather_app/img/icons/40.svg
new file mode 100644
index 00000000..8bb77cad
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/40.svg
@@ -0,0 +1,23 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/41.svg b/chapter_13_weather_app/img/icons/41.svg
new file mode 100644
index 00000000..b17070b5
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/41.svg
@@ -0,0 +1,18 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/42.svg b/chapter_13_weather_app/img/icons/42.svg
new file mode 100644
index 00000000..b17070b5
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/42.svg
@@ -0,0 +1,18 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/43.svg b/chapter_13_weather_app/img/icons/43.svg
new file mode 100644
index 00000000..e90922c1
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/43.svg
@@ -0,0 +1,21 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/44.svg b/chapter_13_weather_app/img/icons/44.svg
new file mode 100644
index 00000000..952452dd
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/44.svg
@@ -0,0 +1,21 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/5.svg b/chapter_13_weather_app/img/icons/5.svg
new file mode 100644
index 00000000..6564301c
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/5.svg
@@ -0,0 +1,21 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/6.svg b/chapter_13_weather_app/img/icons/6.svg
new file mode 100644
index 00000000..3ca9a4c8
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/6.svg
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/7.svg b/chapter_13_weather_app/img/icons/7.svg
new file mode 100644
index 00000000..3ca9a4c8
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/7.svg
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/icons/8.svg b/chapter_13_weather_app/img/icons/8.svg
new file mode 100644
index 00000000..3ca9a4c8
--- /dev/null
+++ b/chapter_13_weather_app/img/icons/8.svg
@@ -0,0 +1,11 @@
+
+
+
+
diff --git a/chapter_13_weather_app/img/night.svg b/chapter_13_weather_app/img/night.svg
new file mode 100644
index 00000000..73823b3d
--- /dev/null
+++ b/chapter_13_weather_app/img/night.svg
@@ -0,0 +1,51 @@
+
diff --git a/chapter_13_weather_app/index.html b/chapter_13_weather_app/index.html
new file mode 100644
index 00000000..238e95a6
--- /dev/null
+++ b/chapter_13_weather_app/index.html
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+ Weather App
+
+
+
+
Weather App
+
+
+
+
+
+
+
+
+
+
City name
+
Weather Condition
+
+ temp
+ °C
+
+
+
+
+
+
+
+
+
+
diff --git a/chapter_13_weather_app/scripts/app.js b/chapter_13_weather_app/scripts/app.js
new file mode 100644
index 00000000..ff42b353
--- /dev/null
+++ b/chapter_13_weather_app/scripts/app.js
@@ -0,0 +1,144 @@
+//DOM manipulation in this document - show things on the page
+
+/*
+// forcast.js
+const cityForm = document.querySelector('form');
+const card = document.querySelector('.card');
+const details = document.querySelector('.details');
+const time = document.querySelector('img.time');
+const icon = document.querySelector('.icon img');
+
+const updateUI = (data) => {
+
+ console.log(data)
+ // const cityDetails = data.cityDetails;
+ // const weather = data.weather;
+
+ //below is Destructuring, which works the same as line 10 & 11 but less code and better readability
+ //Desctruturing is an easy way to get properties from an object and them store them in a constant of the sname name.
+ const {cityDetails, weather} = data;
+
+ //update details template
+ details.innerHTML = `
+
${cityDetails.EnglishName}
+
${weather.WeatherText}
+
+ ${weather.Temperature.Metric.Value}
+ °C
+
+ `;
+
+ //update the night/day & icon images
+ const iconSrc = `img/icons/${weather.WeatherIcon}.svg`;
+ icon.setAttribute('src', iconSrc)
+
+ //Ternary Operator
+ let timeSrc = weather.IsDayTime ? 'img/day.svg' : 'img/night.svg';
+ // if(weather.IsDayTime){
+ // timeSrc = 'img/day.svg';
+ // } else {
+ // timeSrc = 'img/night.svg'
+ // }
+ time.setAttribute('src', timeSrc)
+
+ //remove the d-none class if present
+ if(card.classList.contains('d-none')){
+ card.classList.remove('d-none')
+ }
+}
+
+const updateCity = async (city) => {
+
+ // console.log(city)
+
+ const cityDetails = await getCity(city);
+ const weather = await getWeather(cityDetails.Key);
+
+ // return {
+ // cityDetails: cityDetails,
+ // weather: weather
+ // }
+
+ //object shorthand notation - when we have a property name and a value that are exactly the same name.
+ return { cityDetails, weather }
+}
+
+cityForm.addEventListener('submit', e=>{
+ //prevent default action
+ e.preventDefault();
+
+ //get city value (user input)
+ const city = cityForm.city.value.trim();
+ cityForm.reset();
+
+ //update the ui with new city
+ updateCity(city)
+ .then(data => updateUI(data))
+ .catch(err => console.log(err))
+
+ localStorage.setItem('city',city)
+})
+
+if(localStorage.getItem('city')){
+ updateCity(localStorage.getItem('city'))
+ .then(data => updateUI(data))
+ .catch(err => console.log(err))
+}
+*/
+
+
+
+// forecast_class.js
+const cityForm = document.querySelector('form');
+const card = document.querySelector('.card');
+const details = document.querySelector('.details');
+const time = document.querySelector('img.time');
+const icon = document.querySelector('.icon img');
+const forecast = new Forecast();
+
+// console.log(forecast)
+
+const updateUI = (data) => {
+
+ const {cityDetails, weather} = data;
+
+ details.innerHTML = `
+
${cityDetails.EnglishName}
+
${weather.WeatherText}
+
+ ${weather.Temperature.Metric.Value}
+ °C
+
+ `
+
+ const iconSrc = `img/icons/${weather.WeatherIcon}.svg`;
+ icon.setAttribute('src', iconSrc)
+
+ let timeSrc = weather.IsDayTime ? 'img/day.svg' : 'img/night.svg';
+
+ time.setAttribute('src', timeSrc)
+
+ if(card.classList.contains('d-none')){
+ card.classList.remove('d-none')
+ }
+};
+
+cityForm.addEventListener('submit', e=>{
+
+ e.preventDefault();
+
+ const city = cityForm.city.value.trim();
+ cityForm.reset();
+
+ forecast.updateCity(city)
+ .then(data => updateUI(data))
+ .catch(err => console.log(err))
+
+ localStorage.setItem('city',city)
+})
+
+if(localStorage.getItem('city')){
+ forecast.updateCity(localStorage.getItem('city'))
+ .then(data => updateUI(data))
+ .catch(err => console.log(err))
+}
diff --git a/chapter_13_weather_app/scripts/forecast.js b/chapter_13_weather_app/scripts/forecast.js
new file mode 100644
index 00000000..1839f651
--- /dev/null
+++ b/chapter_13_weather_app/scripts/forecast.js
@@ -0,0 +1,41 @@
+//this document contains all of the JavaScript that will be responsible for interacting with the weather API and getting data
+
+// this is the end point to the accuWeather API
+const key = 'RjKdmCGXOVfvKql2HIhD8aEGQkaKB2Bv';
+
+//when we're requesting data from the end point to this API, we're going to have to do two different things:
+//1. we need to make a request to a certain end point to get city information(a city code)
+//2. use that city code to make a second request to a weather conditions API end point. We're going to send that city code to it so it can identify where we want to get the weather and it will send us the weather conditions back for that area.
+
+//get weather information
+const getWeather = async (id) => {
+ const base = 'http://dataservice.accuweather.com/currentconditions/v1/';
+ const query = `${id}?apikey=${key}`;
+
+ const response = await fetch(base + query);
+ const data = await response.json();
+
+ // console.log(data)
+ return data[0];
+}
+
+//get city information
+const getCity = async (city) => {
+ const base = 'http://dataservice.accuweather.com/locations/v1/cities/search';
+ const query = `?apikey=${key}&q=${city}`;
+
+ const response = await fetch(base + query);
+ const data = await response.json();
+
+ // console.log(data)
+ return data[1];
+}
+
+
+// getCity('richmond')
+// .then(data => {
+// //we want to take the data and get the Key(city code), and pass it into a get weather request - getWeather(). We return a promise by returning the whole thing, so we can chain these things together.
+// return getWeather(data.Key)})
+// .then(data => {
+// console.log(data)})
+// .catch(err => console.log(err))
\ No newline at end of file
diff --git a/chapter_13_weather_app/scripts/forecast_class.js b/chapter_13_weather_app/scripts/forecast_class.js
new file mode 100644
index 00000000..9a8b7d27
--- /dev/null
+++ b/chapter_13_weather_app/scripts/forecast_class.js
@@ -0,0 +1,26 @@
+//this document contains all of the JavaScript that will be responsible for interacting with the weather API and getting data
+
+class Forecast {
+ constructor(){
+ this.key = 'RjKdmCGXOVfvKql2HIhD8aEGQkaKB2Bv'
+ this.weatherURI = 'http://dataservice.accuweather.com/currentconditions/v1/'
+ this.cityURI = 'http://dataservice.accuweather.com/locations/v1/cities/search'
+ }
+ async updateCity(city){
+ const cityDetails = await this.getCity(city);
+ const weather = await this.getWeather(cityDetails.Key);
+ return { cityDetails, weather }
+ }
+ async getWeather(id){
+ const query = `${id}?apikey=${this.key}`;
+ const response = await fetch(this.weatherURI + query);
+ const data = await response.json();
+ return data[0];
+ }
+ async getCity(city){
+ const query = `?apikey=${this.key}&q=${city}`;
+ const response = await fetch(this.cityURI + query);
+ const data = await response.json();
+ return data[1];
+ }
+}
\ No newline at end of file
diff --git a/chapter_13_weather_app/styles.css b/chapter_13_weather_app/styles.css
new file mode 100644
index 00000000..0f2d5150
--- /dev/null
+++ b/chapter_13_weather_app/styles.css
@@ -0,0 +1,15 @@
+body{
+ background: #eeedec;
+ letter-spacing: 0.2em;
+ font-size: 0.8em;
+}
+.container{
+ max-width: 400px;
+}
+.icon {
+ position: relative;
+ top: -50px;
+ border-radius: 100px;
+ width: 100px;
+ margin-bottom: -50px;
+}
\ No newline at end of file
diff --git a/chapter_14_local_storage/index.html b/chapter_14_local_storage/index.html
new file mode 100644
index 00000000..554da6fd
--- /dev/null
+++ b/chapter_14_local_storage/index.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+ Local Storage
+
+
+
+
+
+
diff --git a/chapter_14_local_storage/sandbox1.js b/chapter_14_local_storage/sandbox1.js
new file mode 100644
index 00000000..8ae108d4
--- /dev/null
+++ b/chapter_14_local_storage/sandbox1.js
@@ -0,0 +1,28 @@
+//store data in local storage
+localStorage.setItem('name', 'mario');
+localStorage.setItem('age', 50);
+
+//get data from local storage
+let name = localStorage.getItem('name');
+let age = localStorage.getItem('age');
+
+console.log(name, age)
+
+//updating data
+//all this does is to see if name already exists. If it does, it's going to replace that. If it doesn't. it will create a new one.
+localStorage.setItem('name','luigi');
+localStorage.age = 50
+
+name = localStorage.getItem('name')
+age = localStorage.getItem('age')
+
+console.log(name, age)
+
+//deleting data from local storage
+// localStorage.removeItem('name')
+localStorage.clear();
+
+name = localStorage.getItem('name')
+age = localStorage.getItem('age')
+
+console.log(name, age)
\ No newline at end of file
diff --git a/chapter_14_local_storage/sandbox2.js b/chapter_14_local_storage/sandbox2.js
new file mode 100644
index 00000000..a31caa4a
--- /dev/null
+++ b/chapter_14_local_storage/sandbox2.js
@@ -0,0 +1,11 @@
+const todos = [
+ {text: 'play mariokart', author: 'shaun'},
+ {text: 'buy some milk', author: 'mario'},
+ {text: 'buy some bread', author: 'luigi'}
+];
+
+localStorage.setItem('todos', JSON.stringify(todos))
+const stored = localStorage.getItem('todos')
+const converted = JSON.parse(stored)
+console.log(converted)
+
diff --git a/chapter_15_object_oriented_javascript/index.html b/chapter_15_object_oriented_javascript/index.html
new file mode 100644
index 00000000..d3778999
--- /dev/null
+++ b/chapter_15_object_oriented_javascript/index.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+ Object Oriented JavaScript
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/chapter_15_object_oriented_javascript/sandbox1.js b/chapter_15_object_oriented_javascript/sandbox1.js
new file mode 100644
index 00000000..b5456245
--- /dev/null
+++ b/chapter_15_object_oriented_javascript/sandbox1.js
@@ -0,0 +1,18 @@
+ // classes
+ class User {
+ constructor(username, email){
+ //set up properties
+ this.username = username
+ this.email = email
+ }
+ }
+
+ const userOne = new User('mario', 'mario@learn.ca')
+ const userTwo = new User('luigi','luigi@learn.ca')
+
+ console.log(userOne, userTwo)
+
+ // the 'new' keyword
+ // 1 - it creates a new empty object {}
+ // 2 - it binds the value of 'this' keyword to the new empty object
+ // 3 - it calls the constructor function to 'build' the object
\ No newline at end of file
diff --git a/chapter_15_object_oriented_javascript/sandbox2.js b/chapter_15_object_oriented_javascript/sandbox2.js
new file mode 100644
index 00000000..efc166d9
--- /dev/null
+++ b/chapter_15_object_oriented_javascript/sandbox2.js
@@ -0,0 +1,20 @@
+ // define functions in class
+ class User {
+ constructor(username, email){
+ this.username = username
+ this.email = email
+ }
+ login(){
+ console.log(`${this.username} just logged in`)
+ }
+ logout(){
+ console.log(`${this.username} just logged out`)
+ }
+}
+
+const userOne = new User('mario', 'mario@learn.ca')
+const userTwo = new User('luigi','luigi@learn.ca')
+
+console.log(userOne, userTwo)
+userOne.logout()
+userTwo.logout()
diff --git a/chapter_15_object_oriented_javascript/sandbox3.js b/chapter_15_object_oriented_javascript/sandbox3.js
new file mode 100644
index 00000000..e8f7ced6
--- /dev/null
+++ b/chapter_15_object_oriented_javascript/sandbox3.js
@@ -0,0 +1,27 @@
+ //class methods & method chaining
+ class User {
+ constructor(username, email){
+ this.username = username
+ this.email = email
+ this.score = 0
+ }
+ login(){
+ console.log(`${this.username} just logged in`)
+ return this
+ }
+ logout(){
+ console.log(`${this.username} just logged out`)
+ return this
+ }
+ increScore(){
+ this.score ++
+ console.log(`${this.username} has a score of ${this.score}`)
+ return this
+ }
+}
+
+const userOne = new User('mario', 'mario@learn.ca')
+const userTwo = new User('luigi','luigi@learn.ca')
+
+userOne.logout().increScore().increScore().logout()
+
diff --git a/chapter_15_object_oriented_javascript/sandbox4.js b/chapter_15_object_oriented_javascript/sandbox4.js
new file mode 100644
index 00000000..6e24b50b
--- /dev/null
+++ b/chapter_15_object_oriented_javascript/sandbox4.js
@@ -0,0 +1,38 @@
+// class inheritance (subclasses)
+ class User {
+ constructor(username, email){
+ this.username = username
+ this.email = email
+ this.score = 0
+ }
+ login(){
+ console.log(`${this.username} just logged in`)
+ return this
+ }
+ logout(){
+ console.log(`${this.username} just logged out`)
+ return this
+ }
+ increScore(){
+ this.score ++
+ console.log(`${this.username} has a score of ${this.score}`)
+ return this
+ }
+}
+
+class Admin extends User {
+ deleteUser(userBeingDeleted){
+ users = users.filter(user => user.username !== userBeingDeleted.username)
+ }
+}
+
+const userOne = new User('mario', 'mario@learn.ca')
+const userTwo = new User('luigi','luigi@learn.ca')
+const userThree = new Admin('shaun','shaun@learn.ca')
+
+
+let users = [userOne, userTwo, userThree]
+console.log(users)
+
+userThree.deleteUser(userTwo)
+console.log(users)
\ No newline at end of file
diff --git a/chapter_15_object_oriented_javascript/sandbox5.js b/chapter_15_object_oriented_javascript/sandbox5.js
new file mode 100644
index 00000000..274a94c1
--- /dev/null
+++ b/chapter_15_object_oriented_javascript/sandbox5.js
@@ -0,0 +1,38 @@
+// super()
+
+ class User {
+ constructor(username, email){
+ this.username = username
+ this.email = email
+ this.score = 0
+ }
+ login(){
+ console.log(`${this.username} just logged in`)
+ return this
+ }
+ logout(){
+ console.log(`${this.username} just logged out`)
+ return this
+ }
+ increScore(){
+ this.score ++
+ console.log(`${this.username} has a score of ${this.score}`)
+ return this
+ }
+}
+
+class Admin extends User {
+ constructor(username, email, title){
+ super(username, email)
+ this.title = title
+ }
+ deleteUser(userBeingDeleted){
+ users = users.filter(user => user.username !== userBeingDeleted.username)
+ }
+}
+
+const userOne = new User('mario', 'mario@learn.ca')
+const userTwo = new User('luigi','luigi@learn.ca')
+const userThree = new Admin('shaun','shaun@learn.ca', 'wower')
+
+console.log(userThree)
\ No newline at end of file
diff --git a/chapter_15_object_oriented_javascript/sandbox6.js b/chapter_15_object_oriented_javascript/sandbox6.js
new file mode 100644
index 00000000..d685a0bd
--- /dev/null
+++ b/chapter_15_object_oriented_javascript/sandbox6.js
@@ -0,0 +1,23 @@
+// constructor functions - how class works under the hood
+
+function User(username, email){
+ this.username = username
+ this.email = email
+ this.login = function(){
+ console.log(`${username} has logged in`)
+ }
+}
+
+// class User {
+// constructor(username, email){
+// this.username = username
+// this.email = email
+// }
+// }
+
+ const userOne = new User('mario', 'mario@learn.ca')
+ const userTwo = new User('luigi','luigi@learn.ca')
+
+ console.log(userOne, userTwo)
+
+ userOne.login()
\ No newline at end of file
diff --git a/chapter_15_object_oriented_javascript/sandbox7.js b/chapter_15_object_oriented_javascript/sandbox7.js
new file mode 100644
index 00000000..47ae02ae
--- /dev/null
+++ b/chapter_15_object_oriented_javascript/sandbox7.js
@@ -0,0 +1,22 @@
+// prototype model
+
+function User(username, email){
+ this.username = username
+ this.email = email
+}
+
+User.prototype.login = function(){
+ console.log(`${this.username} has logged in`)
+ return this
+}
+User.prototype.logout = function(){
+ console.log(`${this.username} has logged out`)
+ return this
+}
+
+ const userOne = new User('mario', 'mario@learn.ca')
+ const userTwo = new User('luigi','luigi@learn.ca')
+
+ console.log(userOne, userTwo)
+
+ userOne.login().logout()
\ No newline at end of file
diff --git a/chapter_15_object_oriented_javascript/sandbox8.js b/chapter_15_object_oriented_javascript/sandbox8.js
new file mode 100644
index 00000000..00920956
--- /dev/null
+++ b/chapter_15_object_oriented_javascript/sandbox8.js
@@ -0,0 +1,33 @@
+// prototypal inheritance
+
+function User(username, email){
+ this.username = username
+ this.email = email
+}
+
+User.prototype.login = function(){
+ console.log(`${this.username} has logged in`)
+ return this
+}
+User.prototype.logout = function(){
+ console.log(`${this.username} has logged out`)
+ return this
+}
+
+function Admin(username, email, title){
+ User.call(this, username, email)
+ this.title = title
+}
+
+Admin.prototype = Object.create(User.prototype)
+ const userOne = new User('mario', 'mario@learn.ca')
+ const userTwo = new User('luigi','luigi@learn.ca')
+ const userThree = new Admin('shaun', 'shaun@learn.ca', 'expert')
+
+ Admin.prototype.deleteUser = function(){
+ // delete a user
+ }
+
+ console.log(userOne, userTwo, userThree)
+
+ userOne.login().logout()
\ No newline at end of file
diff --git a/chapter_16_databases/index.html b/chapter_16_databases/index.html
new file mode 100644
index 00000000..e0bc6b28
--- /dev/null
+++ b/chapter_16_databases/index.html
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+ Databases (Firebase)
+
+
+
+
Recipes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/chapter_16_databases/sandbox.js b/chapter_16_databases/sandbox.js
new file mode 100644
index 00000000..b966bbf4
--- /dev/null
+++ b/chapter_16_databases/sandbox.js
@@ -0,0 +1,71 @@
+const list = document.querySelector('ul');
+const form = document.querySelector('form');
+const button = document.querySelector('button')
+
+const addRecipe = (recipe, id) => {
+ let time = recipe.created_at.toDate()
+ let html = `
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/chapter_17_live_chatroom/scripts/app.js b/chapter_17_live_chatroom/scripts/app.js
new file mode 100644
index 00000000..80193700
--- /dev/null
+++ b/chapter_17_live_chatroom/scripts/app.js
@@ -0,0 +1,47 @@
+// dom queries
+const chatList = document.querySelector('.chat-list');
+const newChatForm = document.querySelector('.new-chat');
+const newNameForm = document.querySelector('.new-name');
+const updateMssg = document.querySelector('.update-mssg');
+const rooms = document.querySelector('.chat-rooms');
+
+// add a new chat
+newChatForm.addEventListener('submit', e => {
+ e.preventDefault();
+ const message = newChatForm.message.value.trim();
+ chatroom.addChat(message)
+ .then(() => newChatForm.reset())
+ .catch(err => console.log(err));
+})
+
+// update username
+newNameForm.addEventListener('submit', e => {
+ e.preventDefault();
+ // update name via chatroom
+ const newName = newNameForm.name.value.trim();
+ chatroom.updateName(newName);
+ // reset the form
+ newNameForm.reset();
+ // show then hide the update message
+ updateMssg.innerText = `Your name was updated to ${newName}!`;
+ setTimeout(() => updateMssg.innerText = '', 3000)
+});
+
+//update the chat room
+rooms.addEventListener('click', e => {
+ if(e.target.tagName === 'BUTTON'){
+ chatUI.clear();
+ chatroom.updateRoom(e.target.getAttribute('id'));
+ chatroom.getChats(chat => chatUI.render(chat));
+ }
+})
+
+// check local storage for a name
+const username = localStorage.username ? localStorage.username : 'anon';
+
+// class instances
+const chatUI = new ChatUI(chatList);
+const chatroom = new Chatroom('general', username);
+
+// get chats and render
+chatroom.getChats(data => chatUI.render(data));
\ No newline at end of file
diff --git a/chapter_17_live_chatroom/scripts/chat.js b/chapter_17_live_chatroom/scripts/chat.js
new file mode 100644
index 00000000..72deb578
--- /dev/null
+++ b/chapter_17_live_chatroom/scripts/chat.js
@@ -0,0 +1,53 @@
+ // adding new chat documents
+ // setting up a read-time listener to get new chats
+ // updating the username
+ // updating the room
+
+class Chatroom {
+ constructor(room, username){
+ this.room = room;
+ this.username = username;
+ this.chats = db.collection('chats');
+ this.unsub
+ }
+ async addChat(message){
+ //format a chat object
+ const now = new Date();
+ const chat = {
+ message,
+ username: this.username,
+ room: this.room,
+ created_at: firebase.firestore.Timestamp.fromDate(now)
+ };
+ //save the chat document
+ const response = await this.chats.add(chat);
+ return response;
+ }
+ getChats(callback){
+ this.unsub = this.chats
+ .where('room', '==', this.room)
+ .orderBy('created_at')
+ .onSnapshot(snapshot => {
+ snapshot.docChanges().forEach(change => {
+ if(change.type === 'added'){
+ //update the ui
+ callback(change.doc.data());
+ }
+ })
+ })
+ }
+ updateName(username){
+ this.username = username;
+ localStorage.setItem('username', username);
+ }
+ updateRoom(room){
+ this.room = room;
+ console.log(room)
+ if(this.unsub){
+ this.unsub()
+ }
+ }
+}
+
+
+
diff --git a/chapter_17_live_chatroom/scripts/ui.js b/chapter_17_live_chatroom/scripts/ui.js
new file mode 100644
index 00000000..6d1c6a9d
--- /dev/null
+++ b/chapter_17_live_chatroom/scripts/ui.js
@@ -0,0 +1,26 @@
+// render chat template to the DOM
+// clear the list of chats (when the room changes)
+
+class ChatUI {
+ constructor(list){
+ this.list = list;
+ }
+ clear(){
+ this.list.innerHTML = '';
+ }
+ render(data){
+ const when = dateFns.distanceInWordsToNow(
+ data.created_at.toDate(),
+ {addSuffix: true},
+ )
+ const html = `
+
+ ${data.username}
+ ${data.message}
+
${when}
+
+ `;
+
+ this.list.innerHTML += html;
+ }
+}
\ No newline at end of file
diff --git a/chapter_17_live_chatroom/styles.css b/chapter_17_live_chatroom/styles.css
new file mode 100644
index 00000000..140492b4
--- /dev/null
+++ b/chapter_17_live_chatroom/styles.css
@@ -0,0 +1,23 @@
+.container{
+ max-width: 600px;
+}
+.btn{
+ background: #43d9be;
+ color: white;
+ outline: none !important;
+ box-shadow: none !important;
+}
+.btn:focus{
+ outline: none !important;
+}
+.username {
+ font-weight: bold;
+}
+.time {
+ font-size: 0.7em;
+ color: #999;
+}
+.update-mssg {
+ text-align: center;
+ margin: 20px auto;
+}
\ No newline at end of file
diff --git a/chapter_18_ES6/index.html b/chapter_18_ES6/index.html
new file mode 100644
index 00000000..ebb01d46
--- /dev/null
+++ b/chapter_18_ES6/index.html
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+ More Modern Features
+
+
+
+
+
+
+
+
diff --git a/chapter_18_ES6/sandbox1.js b/chapter_18_ES6/sandbox1.js
new file mode 100644
index 00000000..59b1b107
--- /dev/null
+++ b/chapter_18_ES6/sandbox1.js
@@ -0,0 +1,23 @@
+// rest parameter
+const double = (...nums) => {
+ console.log(nums);
+ // return nums;
+ return nums.map(num => num*2);
+}
+
+const result = double(1,2,3,4,5,6,7,8)
+console.log(result);
+
+// spread syntax (arrays)
+const people = ['shaun', 'ryu', 'crystal'];
+console.log(people);
+console.log(...people);
+const members = ['mario', 'chun-li', ...people];
+console.log(members);
+// a good use case of spread would be when we want to take the elements of one array and spread them into another array.
+
+// spread syntax (objects)
+
+const person = {name: 'shaun', age: 30, job: 'net ninja'};
+const personClone = {...person, location: 'london'};
+console.log(personClone);
\ No newline at end of file
diff --git a/chapter_18_ES6/sandbox2.js b/chapter_18_ES6/sandbox2.js
new file mode 100644
index 00000000..a138cc0a
--- /dev/null
+++ b/chapter_18_ES6/sandbox2.js
@@ -0,0 +1,22 @@
+// sets
+const namesArray = ['ryu', 'chun-li', 'ryu', 'shaun'];
+console.log(namesArray);
+
+// const namesSet = new Set(['ryu', 'chun-li', 'ryu', 'shaun']);
+// const namesSet = new Set(namesArray);
+// console.log(namesSet);
+
+// const uniqueNames = [...namesSet];
+const uniqueNames = [...new Set(namesArray)];
+console.log(uniqueNames);
+
+const ages = new Set();
+ages.add(20).add(30);
+ages.delete(30);
+
+console.log(ages, ages.size);
+
+ages.clear();
+console.log(ages);
+
+
diff --git a/chapter_18_ES6/sandbox3.js b/chapter_18_ES6/sandbox3.js
new file mode 100644
index 00000000..55964512
--- /dev/null
+++ b/chapter_18_ES6/sandbox3.js
@@ -0,0 +1,24 @@
+const symbolOne = Symbol();
+const symbolTwo = Symbol();
+
+console.log(symbolOne, symbolTwo, typeof symbolOne);
+console.log(symbolOne === symbolTwo);
+
+const ninja = {};
+
+ninja.age = 30;
+ninja['belt'] = 'orange';
+// ninja.belt = 'orange';
+
+console.log(ninja)
+
+
+
+
+
+
+
+
+
+
+
diff --git a/chapter_2/index.html b/chapter_2/index.html
new file mode 100644
index 00000000..7d7eeb97
--- /dev/null
+++ b/chapter_2/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+ Chapter 2
+
+
+
Variables & ...
+
+
+
+
diff --git a/chapter_2/sandbox.js b/chapter_2/sandbox.js
new file mode 100644
index 00000000..c64d2101
--- /dev/null
+++ b/chapter_2/sandbox.js
@@ -0,0 +1,235 @@
+// 1
+/*
+let age = 25
+let year = 2019
+
+console.log(age, year)
+
+age = 30
+console.log(age)
+
+const point = 100
+// point = 50;
+console.log(point)
+
+var score = 75 //older way of defining variables
+console.log(score)
+*/
+
+// 2
+/*
+//strings
+console.log('hello, world')
+
+let email = 'evelyn@gmail.com'
+console.log(email)
+
+//string concatenation
+let firstName = 'Brandon'
+let lastName = 'Sanderson'
+
+let fullName = firstName + ' ' + lastName
+console.log(fullName)
+
+//getting characters
+console.log(fullName[0])
+
+//string length
+console.log(fullName.length)
+
+//string methods
+console.log(fullName.toUpperCase())
+let result = fullName.toLowerCase()
+console.log(result, fullName) //these methods dont alter the original variables
+
+let index = email.indexOf('@');
+console.log(index)
+*/
+
+// 3
+/*
+//common string methods
+
+let email = 'mario@thenetninja.co.uk'
+
+// let result = email.lastIndexOf('n')
+
+// let result = email.slice(0, 5);
+
+// let result = email.substr(0, 10)
+
+// let result = email.replace('m', 'w')
+
+let result = email.replace('n', 'w')
+
+console.log(result)
+*/
+
+// 4
+/*
+let radius = 10
+const pi = 3.14
+
+// console.log(radius, pi)
+
+//math operators +, -, *, /, **, %
+
+// console.log(10/2);
+
+// let result = radius % 3;
+
+// let result = pi * radius ** 2
+
+//order of operation - B I D M A S
+
+// let result = 5 * (10 - 3) ** 2
+
+// console.log(result)
+
+let likes = 10;
+
+// likes = likes + 1
+// likes++
+// likes--
+
+// likes += 10;
+// likes -= 5;
+// likes *=2;
+// likes /= 2;
+
+// console.log(likes)
+
+//NaN - not a number
+// console.log(5* 'hello')
+
+let result = 'the blog has ' + likes + ' likes'
+console.log(result)
+*/
+
+//5
+/*
+//template strings
+const title = 'Best reads of 2019'
+const author = 'Mario'
+const likes = 30
+
+//concatenation way
+// let result =
+// 'The blog called ' + title + ' by ' + author + ' has ' + likes + ' likes'
+// console.log(result)
+
+//template string way
+let result = `The blog called ${title} by ${author} has ${likes} likes`;
+ console.log(result)
+
+//creating html tmeplates
+let html = `
+
${title}
+
By ${author}
+ This blog has ${likes} likes
+`;
+
+console.log(html)
+*/
+
+// 6
+/*
+let ninjas = ['shaun', 'ryu', 'chun-li'];
+
+// ninjas[1] = 'ken';
+
+// console.log(ninjas[1])
+
+// let random = ['shaun', 'crystal', 30, 20]
+
+// console.log(ninjas.length)
+
+//array methods
+
+// let result = ninjas.join(',')
+// let result = ninjas.concat(['John', 'Crystal'])
+let result = ninjas.push('ken');
+result = ninjas. pop();
+
+console.log(ninjas)
+*/
+
+// 7
+/*
+let age = null;
+
+console.log(age, age + 3, `the age is ${age}`)
+*/
+
+//8
+/*
+//booleans & comparisons
+// console.log(true, false, 'true', 'false')
+
+//method can return booleans
+let email = 'luigi@thenetninjas.co.uk'
+let names = ['mario', 'luigi', 'toad']
+
+// let result = email.includes('!')
+// let result = names.includes('luigi')
+
+// console.log(result)
+
+//comparison operators
+let age = 25;
+
+// console.log(age == 25);
+// console.log(age == 30);
+// console.log(age != 25);
+// console.log(age > 20);
+// console.log(age < 20);
+// console.log(age <= 25);
+// console.log(age >= 25);
+
+let name = 'shaun';
+
+// console.log(name == 'shaun');
+// console.log(name == 'Shaun');
+// console.log(name > 'crystal');
+// console.log(name > 'Shaun');
+// console.log(name > 'Crystal');
+*/
+
+//9
+/*
+let age = 25
+//loose comparison (different types can still be equal)
+
+// console.log(age == 25);
+// console.log(age == '25');
+
+// console.log(age != 25);
+// console.log(age != '25');
+
+//strict comparison (different types cannot be equal)
+
+console.log(age === 25)
+console.log(age === '25')
+console.log(age !== 25)
+console.log(age !== '25')
+*/
+
+//10
+/*
+//type conversion
+let score = '100';
+
+// score = Number(score)
+// console.log(score + 1)
+// console.log(typeof score)
+
+// let result = Number('hello')
+
+// let result = String(50);
+
+// let result = Boolean(0);
+
+let result = Boolean('')
+
+console.log(result, typeof result)
+*/
diff --git a/chapter_3/index.html b/chapter_3/index.html
new file mode 100644
index 00000000..6a5c52d7
--- /dev/null
+++ b/chapter_3/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+ Chapter 3
+
+
+
Flow Control Techiques
+
+
+
+
diff --git a/chapter_3/sandbox.js b/chapter_3/sandbox.js
new file mode 100644
index 00000000..fe5a26bc
--- /dev/null
+++ b/chapter_3/sandbox.js
@@ -0,0 +1,164 @@
+/*
+//FOR LOOPS
+
+// for (let i = 0; i < 5; i++) {
+// console.log('in loop: ', i)
+// }
+// console.log('loop finished');
+
+const names = ['shaun', 'mario', 'luigi']
+
+for (let i = 0; i < names.length; i++) {
+ // console.log(names[i])
+ let html = `
${names[i]}
`
+ console.log(html)
+}
+*/
+
+/*
+//WHILE LOOPS
+const names = ['shaun', 'mario', 'luigi']
+
+// let i = 0;
+
+// while(i < 5) {
+// console.log('in loop: ', i)
+// i++;
+// }
+
+let i = 0
+while (i < names.length) {
+ console.log(names[i]);
+ i++;
+}
+*/
+
+/*
+//DO WHILE LOOPS
+
+let i = 5
+
+do {
+ console.log('val of i is ', i)
+ i++
+} while (i < 5)
+*/
+
+/*
+//IF STATEMENTS
+// const age = 25;
+
+// if(age > 20){
+// console.log('you are over 20 years old');
+// }
+
+// const ninjas = ['shaun', 'ryu', 'chun-li', 'yoshi'];
+
+// if(ninjas.length > 4) {
+// console.log("that's a lot of ninjas")
+// }
+*/
+
+/*
+//IF ELSE STATEMENTS
+// const password = 'p@ssword1234'
+
+// if (password.length >= 12) {
+// console.log('that password is mighty strong')
+// } else if (password.length >= 8) {
+// console.log('that password is long enough!')
+// } else {
+// console.log('password is not long enough')
+// }
+*/
+
+/*
+//LOGICAL OPERATORS - OR || and AND &&
+
+const password = 'p@ss12'
+
+if (password.length >= 12 && password.includes('@')) {
+ console.log('that password is mighty strong')
+} else if (password.length >= 8 || password.includes('@') && password.length > 5) {
+ console.log('that password is strong enough!')
+} else {
+ console.log('password is not strong enough')
+}
+*/
+
+/*
+//LOGICAL NOT (!)
+
+let user = false;
+
+if(!user){
+ console.log('you must be logged in to continue')
+}
+console.log(!true)
+console.log(!false)
+*/
+
+/*
+//BREAK AND CONTINUE
+const scores = [50, 25, 0, 30, 100, 20, 10]
+
+for (let i = 0; i < scores.length; i++) {
+ if (scores[i] === 0) {
+ continue
+ }
+ console.log('your score: ', scores[i])
+
+ if (scores[i] === 100) {
+ console.log('congrats, you got the top score!')
+ break
+ }
+}
+*/
+
+/*
+//SWITCH STATEMENT
+const grade = 'C'
+
+switch (grade) {
+ case 'A':
+ console.log('you got an A!')
+ break
+ case 'B':
+ console.log('you got an B!')
+ break
+
+ case 'C':
+ console.log('you got an C!')
+ break
+
+ case 'D':
+ console.log('you got an D!')
+ break
+
+ case 'E':
+ console.log('you got an E!')
+ break
+
+ default:
+ console.log('not a valid grade')
+}
+*/
+
+/*
+//VARIABLES & BLOCK SCOPE
+
+let age = 30
+
+if (true) {
+ let age = 40
+ let name = 'shaun'
+ console.log('inside 1st code block: ', age, name)
+
+ if (true) {
+ let age = 50
+ console.log('inside 2nd code block: ', age)
+ }
+}
+
+console.log('outside code block: ', age, name)
+*/
\ No newline at end of file
diff --git a/chapter_4/index.html b/chapter_4/index.html
new file mode 100644
index 00000000..18a8943b
--- /dev/null
+++ b/chapter_4/index.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+ Chapter 4
+
+
+
Functions
+
+
+
+
+
+
+
+
+
+
+
diff --git a/chapter_4/sandbox1.js b/chapter_4/sandbox1.js
new file mode 100644
index 00000000..27299164
--- /dev/null
+++ b/chapter_4/sandbox1.js
@@ -0,0 +1,13 @@
+//FUNCTION DECLARATION
+function greet() {
+ console.log('hello there')
+}
+
+greet() //this is calling the function, aka invoking the function
+
+//FUNCTION EXPRESSION
+const speak = function () {
+ console.log('good day!')
+}
+
+speak()
diff --git a/chapter_4/sandbox2.js b/chapter_4/sandbox2.js
new file mode 100644
index 00000000..82ea6021
--- /dev/null
+++ b/chapter_4/sandbox2.js
@@ -0,0 +1,13 @@
+//arguements & parameters
+const speak = function (name = 'luigi', time = 'night') {
+ console.log(`good ${time} ${name}`)
+}
+
+
+// speak('mario', 'morning')
+speak()
+
+//Note:
+// 1. the name variable has a local scope and cannot be accessed outside of the function
+
+// 2. the order is important. The order of the arguements must match the order of the parameters.
\ No newline at end of file
diff --git a/chapter_4/sandbox3.js b/chapter_4/sandbox3.js
new file mode 100644
index 00000000..b2a2ee6c
--- /dev/null
+++ b/chapter_4/sandbox3.js
@@ -0,0 +1,17 @@
+//returning values
+
+const calcArea = function (radius) {
+ let area = 3.14 * radius ** 2
+ return area //area now is a returned value, but a local scope and cannot be accessed outside of the function
+}
+
+//below is short form
+const calcArea2 = function (radius) {
+ return 3.14 * radius ** 2
+}
+
+const area = calcArea(5) //set the returned value to a new constant, and it now has a global scope
+
+console.log(area) //now we can use the value outside of the function
+
+
diff --git a/chapter_4/sandbox4.js b/chapter_4/sandbox4.js
new file mode 100644
index 00000000..07ebc159
--- /dev/null
+++ b/chapter_4/sandbox4.js
@@ -0,0 +1,47 @@
+//regular function
+// const calcArea2 = function (radius) {
+// return 3.14 * radius ** 2
+// }
+
+//arrow function
+const calcArea = (radius) => {
+ return 3.14 * radius ** 2
+}
+
+//without parentheses (only works when this is exactly one parameter)
+const calcArea2 = (radius) => {
+ return 3.14 * radius ** 2
+}
+
+const area = calcArea(5)
+console.log('area is: ', area)
+//practice arrow function
+
+// 1.
+// const greet = function(){
+// return 'hello, world';
+// }
+
+const greet = () => 'hello, world'
+const result = greet()
+console.log(result)
+
+// 2.
+// const bill = function (products, tax) {
+// let total = 0
+// for (let i = 0; i < products.length; i++) {
+// total += products[i] + products[i] * tax
+// }
+// return total
+// }
+
+
+const bill = (products, tax) => {
+ let total = 0
+ for (let i = 0; i < products.length; i++) {
+ total += products[i] + products[i] * tax
+ }
+ return total
+}
+
+console.log(bill([10, 15, 30], 0.2))
diff --git a/chapter_4/sandbox5.js b/chapter_4/sandbox5.js
new file mode 100644
index 00000000..73c392c3
--- /dev/null
+++ b/chapter_4/sandbox5.js
@@ -0,0 +1,12 @@
+const nameOne = 'shaun'
+
+//functions
+const greet = () => 'hello'
+
+let resultOne = greet()
+
+console.log(resultOne)
+
+//methods
+let resultTwo = nameOne.toUpperCase()
+console.log(resultTwo)
\ No newline at end of file
diff --git a/chapter_4/sandbox6.js b/chapter_4/sandbox6.js
new file mode 100644
index 00000000..b579f5a7
--- /dev/null
+++ b/chapter_4/sandbox6.js
@@ -0,0 +1,28 @@
+//callbacks & foreach
+const myFunc = (callbackFunc) => {
+ //do something
+ let value = 50
+ callbackFunc(value)
+}
+
+myFunc((value) => {
+ //do something
+ console.log(value)
+})
+
+// what callback function does:
+// pass a function into another function as an arguement, and at some point in another function, that callback function will probably be called and maybe passed value which we can take in.
+
+//forEach is a method which iterate over an array
+let people = ['mario', 'luigi', 'ryu', 'shaun', 'chun-li']
+
+//below forEach method iterate through [people], for each element inside the array, it calls this callback function
+people.forEach((person, index) => {
+ console.log(index, person) //this will be called 5 times because there are 5 elements in the [people]
+})
+
+const logPerson = (person, index) => {
+ console.log(`${index} - hello ${person}`)
+}
+
+people.forEach(logPerson)
diff --git a/chapter_4/sandbox7.js b/chapter_4/sandbox7.js
new file mode 100644
index 00000000..d88745a5
--- /dev/null
+++ b/chapter_4/sandbox7.js
@@ -0,0 +1,15 @@
+//get a reference to the 'ul'
+const ul = document.querySelector('.people')
+
+const people = ['mario', 'luigi', 'ryu', 'shaun', 'chun-li']
+
+//set a variable html as an empty template string
+let html = ``;
+
+people.forEach(person=>{
+ //create a html template for each person
+ html += `
${person}
`
+})
+console.log(html)
+
+ul.innerHTML = html;
\ No newline at end of file
diff --git a/chapter_5/index.html b/chapter_5/index.html
new file mode 100644
index 00000000..9f99327e
--- /dev/null
+++ b/chapter_5/index.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+ Chapter 5
+
+
+
Objects
+
+
+
+
+
+
+
+
+
+
diff --git a/chapter_5/sandbox1.js b/chapter_5/sandbox1.js
new file mode 100644
index 00000000..59f7dce5
--- /dev/null
+++ b/chapter_5/sandbox1.js
@@ -0,0 +1,21 @@
+//creating an object literals
+
+let user = {
+ name: 'crystal',
+ age: 30,
+ email: 'crystal@thenetninja.co.uk',
+ location: 'berlin',
+ blogs: ['why mac & cheese rules', '10 things to make with marmite']
+};
+
+console.log(user)
+console.log(user.name)
+
+user.age = 35;
+console.log(user.age)
+
+console.log(user['location'])
+user['name'] = 'chun-li'
+console.log(user['name'])
+
+console.log(typeof user)
\ No newline at end of file
diff --git a/chapter_5/sandbox2.js b/chapter_5/sandbox2.js
new file mode 100644
index 00000000..9897aece
--- /dev/null
+++ b/chapter_5/sandbox2.js
@@ -0,0 +1,19 @@
+//adding methods to the object
+
+let user = {
+ name: 'crystal',
+ age: 30,
+ email: 'crystal@thenetninja.co.uk',
+ location: 'berlin',
+ blogs: ['why mac & cheese rules', '10 things to make with marmite'],
+ login: function () {
+ console.log('the user logged in')
+ },
+ logout: function() {
+ console.log('the user logged out')
+ }
+}
+
+user.login()
+user.logout()
+
diff --git a/chapter_5/sandbox3.js b/chapter_5/sandbox3.js
new file mode 100644
index 00000000..f16201ea
--- /dev/null
+++ b/chapter_5/sandbox3.js
@@ -0,0 +1,24 @@
+//'this' keyword
+
+let user = {
+ name: 'crystal',
+ age: 30,
+ email: 'crystal@thenetninja.co.uk',
+ location: 'berlin',
+ blogs: ['why mac & cheese rules', '10 things to make with marmite'],
+ login() {
+ console.log('the user logged in')
+ },
+ logout() {
+ console.log('the user logged out')
+ },
+ logBlogs() {
+ console.log('this user has written the following blogs')
+ this.blogs.forEach((blog) => {
+ console.log(blog)
+ })
+ },
+}
+
+user.logBlogs()
+// console.log(this)
diff --git a/chapter_5/sandbox4.js b/chapter_5/sandbox4.js
new file mode 100644
index 00000000..59eafa38
--- /dev/null
+++ b/chapter_5/sandbox4.js
@@ -0,0 +1,34 @@
+//Object in Arrays
+
+// const blogs = [
+// {title: 'why mac & cheese rules', likes: 30},
+// {title: '10 things to make with marmite', likes: 50},
+// ]
+
+// console.log(blogs);
+
+let user = {
+ name: 'crystal',
+ age: 30,
+ email: 'crystal@thenetninja.co.uk',
+ location: 'berlin',
+ blogs: [
+ {title: 'why mac & cheese rules', likes: 30},
+ {title: '10 things to make with marmite', likes: 50},
+ ],
+ login() {
+ console.log('the user logged in')
+ },
+ logout() {
+ console.log('the user logged out')
+ },
+ logBlogs() {
+ console.log('this user has written the following blogs')
+ this.blogs.forEach((blog) => {
+ console.log(blog.title, blog.likes)
+ })
+ },
+}
+
+user.logBlogs()
+// console.log(this)
diff --git a/chapter_5/sandbox5.js b/chapter_5/sandbox5.js
new file mode 100644
index 00000000..6a2cec59
--- /dev/null
+++ b/chapter_5/sandbox5.js
@@ -0,0 +1,20 @@
+//Math object
+
+console.log(Math)
+console.log(Math.PI)
+console.log(Math.E)
+
+const area = 7.7
+
+console.log(Math.round(area))
+console.log(Math.floor(area))
+console.log(Math.ceil(area))
+console.log(Math.trunc(area))
+
+//random numbers
+
+const random = Math.random()
+
+console.log(random)
+
+console.log(Math.round(random * 100))
\ No newline at end of file
diff --git a/chapter_5/sandbox6.js b/chapter_5/sandbox6.js
new file mode 100644
index 00000000..07b31e63
--- /dev/null
+++ b/chapter_5/sandbox6.js
@@ -0,0 +1,20 @@
+//primitive values
+
+let scoreOne = 50;
+let scoreTwo = scoreOne;
+
+console.log(`scoreOne: ${scoreOne}`, `scoreTwo:${scoreTwo}`);
+
+scoreOne = 100;
+console.log(`scoreOne: ${scoreOne}`, `scoreTwo:${scoreTwo}`);
+
+
+//reference values
+
+const userOne = {name: 'ryu', age: 30};
+const userTwo = userOne;
+
+console.log(userOne, userTwo);
+
+userOne.name = 'chun-li'
+console.log(userOne, userTwo);
diff --git a/chapter_6/event.html b/chapter_6/event.html
new file mode 100644
index 00000000..2ec74fb6
--- /dev/null
+++ b/chapter_6/event.html
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+ Chapter 6
+
+
+
+