wordpress_blog

This is a dynamic to static website.

Modern JavaScript (1)

(Complete guide, from Novice to Ninja)

Learning Udemy Course:Modern JavaScript

建立者:The Net Ninja (Shaun Pelling)

Learn Modern JavaScript from the very start to ninja-level & build awesome JavaScript applications.

您會學到

  • Learn how to program with modern JavaScript, from the very beginning to more advanced topics
  • Learn all about OOP (object-oriented programming) with JavaScript, working with prototypes & classes
  • Learn how to create real-world front-end applications with JavaScript (quizes, weather apps, chat rooms etc)
  • Learn how to make useful JavaScript driven UI components like popups, drop-downs, tabs, tool-tips & more.
  • Learn how to use modern, cutting-edge JavaScript features today by using a modern workflow (Babel & Webpack)
  • Learn how to use real-time databases to store, retrieve and update application data
  • Explore API’s to make the most of third-party data (such as weather information)

Introduction

Why You Should Take This Course

JavaScript is a Universal Language

  • websites & apps
  • server-side code (node.js)
  • programming robots
  • and much more…

JavaScript on the Front-end

  • JavaScript that runs in a browser
  • Add interactivity to web pages
  • Animations, web forms, UI elements, using API’S & data
  • Using modern JavaScript syntax & techniques

Why JavaScript is Amazing

Why JavaScript is Amazing…

Making AWESOME things in a browser

  • digital clocks, quizzes, chat rooms, weather apps…
  • Server side JavaScript using Node.js

The Possibilities are Endless…

  • make mobile apps
  • program robots
  • create a VR game

Setting up Your Environment

使用 Text Editor:Visual Studio Code
Extensions
  • Live Server
  • Material Icon Theme
  • Monokai++

What is a Server?

建立環境

doc + tab 或者 doc + enter

使用 Live Server

滑鼠右鍵後點選 Open with Live Server

Course Files

資源:Course Files on GitHub

JavaScript Basics

Adding JavaScript to a Web Page

  • add it anywhere between the head tax
    • 99%不會使用這種方式
  • add it anywhere between the body tax
  • link to an external file
// index.html
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Modern JavaScript</title>
    <!-- <script>
        alert('hello, world');
    </script> -->
</head>
<body>
    <h1>page title</h1>

    <!-- <script>
        alert('hello, world');
    </script> -->
    <!-- external files -->
    <script src="sandbox.js"></script>
</body>
</html>
// sandbox.js
alert('hello, world');

The Browser Console

打開 Google Console:按下 F12 之後,點擊 Console。

// Google Console
alert('hello');
// sandbox.js
console.log(1);
console.log(2);

We can use to log out values to the console and that is really going to help us when we’re learning.
We be using the console to test our code and see some results.

Variables, Constants & Comments

Variables

  • let – 用於宣告一個「只作用在當前區塊的變數」,初始值可選擇性的設定。
    • 主要使用
  • const – 常數不能重複指定值,也不能重複宣告。
  • var – 宣告一個變數, 同時可以非強制性地賦予一初始值。
    • 越來越少使用了
// sandbox.js
let age = 25;
let year = 2019;

 console.log(age, year);

age = 30;
console.log(age);
// sandbox.js
// 覆蓋或重複會產生錯誤
const points = 100;
points = 50;
console.log(points);
// sandbox.js
var score = 75;
console.log(score);
限制
  • can’t be any spaces
    • eg:my age,可以使用 myAge。
  • can’t start with a number
  • can’t use JavaScript Reserved Words
資源:Link to a list of reserved keywords in JavaScript
註解 – comments
// sandbox.js
// 1. comments
// log things to console
// console.log(age, year);

/* 2. comments */
/* age = 30;
console.log(age);

const points = 100;
console.log(points); */
補充說明

不是所有的瀏覽器都支援 let、const 語法,因此建議在之後的課程使用較新版本的 Google Chrome 來學習、練習。

Data Types at a Glance

JavaScript Data Types

Number 1, 2, 3, 100, 3.14
String ‘hello, world’ “mario@thenetninja.co.uk”
Boolean true / false
Null Explicitly(明確地) set a variable with no value
Undefined For variables that have not yet been defined
Object Complex data structures – Arrays, Dates, Literals etc
Symbol Used with objects

Strings

// sandbox.js

// strings
console.log('hello, world');

let email = 'mario@thenetninja.co.uk';
console.log(email);

// string concatenation
let firstName = 'Brandon';
let lastName = 'Sanderson';

let fullName = firstName + ' ' + lastName;
console.log(fullName);

// getting characters
console.log(fullName[2]);

// string length
console.log(fullName.length);

// string methods
console.log(fullName.toUpperCase());
let result = fullName.toLowerCase();
console.log(result, fullName);

let index = email.indexOf('@');
console.log(index);

Common String Methods

// sandbox.js
// common string methods

let email = 'mario@thenetninja.co.uk';

// let result = email.lastIndexOf('n');

// let  result = email.slice(2,5);

// let result = email.substr(4,10);

// let result = email.replace('m', 'w');

// let result = email.replace('n', 'w');

console.log(result);

Numbers

// sandbox.js

let radius = 10;
const pi = 3.14;

// console.log(radius, pi);

// math operations +, -, *, / , **, %

// 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');
// console.log(5 * 'hello');

let result = 'the blog has ' + likes + ' likes';
console.log(result);

Template Strings (樣板字串)

// sandbox.js
// 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 templates
let html = `
  <h2>${title}</h2>
  <p>By ${author}</p>
  <span>This blog has ${likes} likes</span>
`;

console.log(html);

Arrays(陣列)

// sandbox.js
let ninjas = ['shaun', 'ryu', 'chun-li'];

// ninjas[1] = 'ken';
// console.log(ninjas[1]);

// let ages = [20,25,30,35];
// console.log(ages[2]);

// let random = ['shaun', 'crystal', 30, 20];
// console.log(random);

// console.log(ninjas.length);

// array methods

// let result = ninjas.join(',');
// let result = ninjas.indexOf('chun-li');
// let result = ninjas.concat(['ken', 'crystal']);
let result = ninjas.push('ken');
result = ninjas.pop();

console.log(result);

Null & Undefined

// sandbox.js
// let age;
let age = null;

console.log(age, age + 3, `the age is ${age}`);

Booleans & Comparisons

// sandbox.js
// booleans & comparisons
console.log(true, false, "true", "false");

// methods can return booleans
let email = 'luigi@thenetninja.co.uk';
let names = ['mario', 'luigi', 'toad'];

// let result = email.includes('!');
// let result = names.includes('bowser');

// console.log(result);

// comparsion operators
let age =  25;

// console.log(age == 25);
// console.log(age == 30);
// console.log(age != 30);
// 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');

Loose vs Strict Comparison

// sandbox.js
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');

Type Conversion(類型轉換)

// sandbox.js
// 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);

Control Flow Basics

What is Control Flow?

Control Flow(控制流程)

Use Loops for cycling through data

control flow

Use conditional statements for checking conditions

if (some condition is true) {
  do something...
}

For Loops

// sandbox.js
// 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 = `<div>${names[i]}</div>`;
  console.log(html);
}

While Loops(While迴圈)

// sandbox.js
// 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

// sandbox.js
// do while loops

let i = 3;

do{
  console.log('val of i is: ', i);
  i++;
} while(i < 5);

If Statements

// sandbox.js
// 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");
// }

const password = 'p@ss';

if(password.length >= 8){
  console.log('that password is long enough!');
}

Else & Else If

// sandbox.js
// else if statements

const password = 'p@ss';

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(邏輯運算子)

// sandbox.js
// 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

// sandbox.js
// logical NOT (!)

let user = false;

if(!user){
  console.log('you must be logged in to continue');
}

console.log(!true);
console.log(!false);

Break & Continue

// sandbox.js
// 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 Statements

// sandbox.js
// switch statements
const grade = '50';

switch(grade){
  case '50':
    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');
}

// // using if statements
// if(grade === 'A'){

// } else if(grade === 'B'){

// } else if(grade === 'C'){

// } else if(grade === 'D'){

// } else if(grade === 'E'){

// } else {

// }

Variables & Block Scope

// sandbox.js
// variables & block scope
const age = 30;

if(true){
  const age = 40;
  const name = 'shaun'
  console.log('inside 1st code block: ', age, name);

  if(true){
    const age = 50;
    console.log('inside 2nd code block: ', age);
    // var test = 'hello';
  }
}

console.log('outside code block: ', age, name);
// console.log('outside code block: ', test);

Functions & Methods

What are Functions?

JavaScript Data Types

Object Arrays, Object Literals, Functions, Dates etc

Functions

Function Declarations & Expressions(函式宣告 & 表達式)

// sandbox.js
// function expression 函式表達式
const speak = function(){
  console.log('good day!');
};


// greet();
// greet();
// greet();

speak();
speak();
speak();

// function declaration 函式宣告
function greet(){
  console.log('hello there');
}
JavaScript裡面的hoisting、是一種提升的觀念。

Hoisting works with function declarations but it doesn’t work with function expressions.

JavaScript does not hoist function expressions only function declarations.

Arguments & Parameters(引數 & 參數)

// sandbox.js
// arguments & parameters 引數 & 參數

const speak = function(name = 'luigi', time = 'night'){ // 參數
  console.log(`good ${time} ${name}`);
};

speak();
speak('shaun'); // 引數
引用 stack overflow 的解答:
  • An argument is an expression used when calling the method.
  • A parameter is the variable which is part of the method’s signature (method declaration).

Returning Values(回傳值)

// sandbox.js
// returning values

const calcArea = function(radius){
  let area = 3.14 * radius**2;
  return area;
}

const area = calcArea(5);
console.log(area);
// sandbox.js
// returning values
const calcArea = function(radius){
  let area = 3.14 * radius**2;
  return area;
}

const a = calcArea(5);
console.log(a);
// sandbox.js
// returning values
const calcArea = function(radius){
  return 3.14 * radius**2;
}

const area = calcArea(5);
console.log(area);

Arrow Functions(箭頭函式)

// sandbox.js
// regular function
// const calcArea = function(radius) {
//   return 3.14 * radius**2;
// }

// arrow function
// const calcArea = (radius) => {
//   return 3.14 * radius**2;
// };

// simplify arrow function
// one parameter 才能使用
// 兩個以上參數要(radius, something)
// const calcArea = radius => {
//   return 3.14 * radius**2;
// };

// one line arrow function
const calcArea = radius => 3.14 * radius**2;

const area = calcArea(5);
console.log('area is:', area);
// sandbox.js
// practise arrow functions

// const greet = function() {
//   return 'hello, world';
// }

// const greet = () => {
//   return 'hello, world';
// }

// const greet = () => 'hello world';
// const result = greet();
// console.log(result);

// 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));

Functions vs Methods

// sandbox.js
const name = 'shaun';

// functions

const greet = () => 'hello';

let resultOne = greet();
console.log(resultOne);

// methods

let resultTwo = name.toUpperCase();
console.log(resultTwo);

Foreach Method & Callbacks

// sandbox.js
// callbacks & foreach

const myFunc = (callbackFunc) => {
  // do something
  let value = 50;
  callbackFunc(value);
};

myFunc(function(value){
  // do something
  console.log(value);
});

// sandbox.js
// callbacks & foreach

const myFunc = (callbackFunc) => {
  // do something
  let value = 50;
  callbackFunc(value);
};

myFunc(value => {
  // do something
  console.log(value);
});

// sandbox.js
// callbacks & foreach

let people = ['mario', 'luigi', 'ryu', 'shaun', 'chun-li'];

people.forEach(function(){
  console.log('something');
});
// sandbox.js
// callbacks & foreach

let people = ['mario', 'luigi', 'ryu', 'shaun', 'chun-li'];

people.forEach(function(person){
  console.log(person);
});
// sandbox.js
// callbacks & foreach

let people = ['mario', 'luigi', 'ryu', 'shaun', 'chun-li'];

people.forEach(person => {
  console.log(person);
});
// sandbox.js
// callbacks & foreach

let people = ['mario', 'luigi', 'ryu', 'shaun', 'chun-li'];

people.forEach((person, index) => {
  console.log(index, person);
});
// sandbox.js
// callbacks & foreach

let people = ['mario', 'luigi', 'ryu', 'shaun', 'chun-li'];

const logPerson = (person, index) => {
  console.log(`${index} - hello ${person}`);
}

people.forEach(logPerson);

Callback Functions in Action

// index.html
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Modern JavaScript</title>
</head>
<body>
    <h1>Functions!</h1>

    <ul class="people"></ul>

    <script src="sandbox.js"></script>
</body>
</html>
// sandbox.js
// get a reference to the 'ul'
const ul = document.querySelector('.people');

const people = ['mario', 'luigi', 'ryu', 'shaun', 'chun-li'];
// sandbox.js
// get a reference to the 'ul'
const ul = document.querySelector('.people');

const people = ['mario', 'luigi', 'ryu', 'shaun', 'chun-li'];

let html = ``;

people.forEach(function(person){
  // create html template
  html += `<li style="color: purple">${person}</li>`;
});

console.log(html);
ul.innerHTML = html;
sandbox.js
// get a reference to the 'ul'
const ul = document.querySelector('.people');

const people = ['mario', 'luigi', 'ryu', 'shaun', 'chun-li'];

let html = ``;

people.forEach(person => {
  // create html template
  html += `<li style="color: purple">${person}</li>`;
});

console.log(html);
ul.innerHTML = html;

Object Literals(物件實字)

Objects at a Glance

Objects(物件)

Objects in real life have properties & things they can do…

a phone
properties things it can do
– colour – ring
– size – take a picture
– modal – play music

Objects in JavaScript have properties & things they can do (methods)…

user object
properties methods
– email – login
– username – logout
– gender
blog object
properties methods
– title – publish
– content – unpublish
– author – delete

Creating an Object Literal

// sandbox.js
// 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);

// const key = 'location';
// console.log(user[key]);

console.log(user['location']);

console.log(user['name']);
console.log(user['email']);
user['name'] = 'chun-li';
console.log(user['name']);

console.log(typeof user);

Adding Methods

// sandbox.js
// 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'],
  login: function() {
    console.log('the user logged in');
  },
  logout: function() {
    console.log('the user logged out');
  },
  logBlogs: function() {
    
  }
};

user.login();
user.logout();

const name = 'mario';
name.toUpperCase();

‘this’ Keyword

// sandbox.js - 1
// 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'],
  login: function(){
    console.log('the user logged in');
  },
  logout: function(){
    console.log('the user logged out');
  },
  logBlogs: function(){
    console.log(blogs);
  }
};

user.logBlogs();
// Google Console -1
  x Uncaught ReferenceError: blogs is not defined at Object.logBlogs (sandbox.js:16) at sandbox.js:20
>
// sandbox.js - 2
// 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'],
  login: function(){
    console.log('the user logged in');
  },
  logout: function(){
    console.log('the user logged out');
  },
  logBlogs: function(){
    this.blogs
  }
};

// user.logBlogs();
console.log(this);
// Google Console -2
  Window {window: Window, self: Window, document: document, name: '', location: Location, …}
>
// sandbox.js -3
// 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'],
  login: function(){
    console.log('the user logged in');
  },
  logout: function(){
    console.log('the user logged out');
  },
  logBlogs: function(){
    console.log(this);
  }
};

user.logBlogs();
console.log(this);
// Google Console -3
  {name: 'crystal', age: 30, email: 'crystal@thenetninja.co.uk', location: 'berlin', blogs: Array(2), …}
  Window {window: Window, self: Window, document: document, name: '', location: Location, …}
>
// sandbox.js - 4
// 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'],
  login: function(){
    console.log('the user logged in');
  },
  logout: function(){
    console.log('the user logged out');
  },
  logBlogs: function(){
    console.log(this.blogs);
  }
};

user.logBlogs();
console.log(this);
// Google Console - 4
  (2) ['why mac & cheese rules', '10 things to make with marmite']
  Window {window: Window, self: Window, document: document, name: '', location: Location, …}
>
// sandbox.js - 5
// 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'],
  login: function(){
    console.log('the user logged in');
  },
  logout: function(){
    console.log('the user logged out');
  },
  logBlogs: function(){
    // console.log(this.blogs);
    console.log('this user has written the following blogs:');
    this.blogs.forEach(blog => {
      console.log(blog);
    })
  }
};

user.logBlogs();
console.log(this);
Google Console - 5
  this user has written the following blogs:
  thy mac & cheese rules
  10 things to make with marmite
  Window {window: Window, self: Window, document: document, name: '', location: Location, …}
>
// sandbox.js - 6
// 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'],
  login: function(){
    console.log('the user logged in');
  },
  logout: function(){
    console.log('the user logged out');
  },
  logBlogs: () => {
    // console.log(this.blogs);
    // console.log('this user has written the following blogs:');
    // this.blogs.forEach(blog => {
    //   console.log(blog);
    // })
    console.log(this);
  }
};

user.logBlogs();
console.log(this);
// Google Console - 6
  Window {window: Window, self: Window, document: document, name: '', location: Location, …}
  Window {window: Window, self: Window, document: document, name: '', location: Location, …}
>
// sandbox.js - 7
// 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'],
  login: function(){
    console.log('the user logged in');
  },
  logout: function(){
    console.log('the user logged out');
  },
  logBlogs: function() {
    // console.log(this.blogs);
    console.log('this user has written the following blogs:');
    this.blogs.forEach(blog => {
      console.log(blog);
    });
  }
};

user.logBlogs();
console.log(this);
// Google Console - 7
  this user has written the following blogs:
  why mac & cheese rules
  10 things to make with marmite
  Window {window: Window, self: Window, document: document, name: '', location: Location, …}
>
// sandbox.js - 8
// 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'],
  login(){
    console.log('the user logged in');
  },
  logout(){
    console.log('the user logged out');
  },
  logBlogs(){
    // console.log(this.blogs);
    console.log('this user has written the following blogs:');
    this.blogs.forEach(blog => {
      console.log(blog);
    });
  }
};

user.logBlogs();
console.log(this);
// Google Console - 8
  this user has written the following blogs:
  why mac & cheese rules
  10 things to make with marmite
  Window {window: Window, self: Window, document: document, name: '', location: Location, …}
>

Objects in Arrays

// sandbox.js - 1 
// object literals

const blogs = [
  { title: 'why mac & cheese rules', likes: 30 },
  { title: '10 things to make with marmite', likes: 50 }
];

console.log(blogs);
// Google Console - 1
  (2) [{...}, {...}]
>
// sandbox.js - 2
// object literals

// 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.blogs);
    console.log('this user has written the following blogs:');
    this.blogs.forEach(blog => {
      console.log(blog.title, blog.likes);
    });
  }
};

user.logBlogs();
// Google Console - 2
  this user has written the following blogs:
  why mac & cheese rules 30
  10 things to make with marmite 50
>

Math Object

// sandbox.js
// 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));
console.log(Math.round(random * 100));
// Google Console
  Math {abs: ƒ, acos: ƒ, acosh: ƒ, asin: ƒ, asinh: ƒ, …}
  3.141592653589793
  2.718281828459045
  8
  7
  8
  7
  0.15006583288702902
  0
  15
>

Primitive vs Reference Types

Primitive & Reference Types

Primitive Types

  • numbers
  • strings
  • Booleans
  • null
  • undefined
  • symbols

Reference Types

  • all types of objects
  • object literals
  • arrays
  • functions
  • dates
  • all other objects

Stack & Heap

Stack & Heap
  • primitive types 儲存在 stack
  • reference types 儲存在 heap
// sandbox.js
// primitive values

let scoreOne = 50;
let scoreTwo = scoreOne;

console.log(`scoreOne: ${scoreOne}`, `scoreTwo: ${scoreTwo}`);

scoreOne = 100;
console.log(`scoreOne: ${scoreOne}`, `scoreTwo: ${scoreTwo}`);
// Google Console
   scoreOne: 50 scoreTwo: 50
   scoreOne: 100 scoreTwo: 50
>
// sandbox.js
// reference values

const userOne = { name: 'ryu', age: 30 };
const userTwo = userOne;

console.log(userOne, userTwo);

userOne.age = 40;
userOne.name = 'chun-li';
console.log(userOne, userTwo);
// Google Console
   {name: 'ryu', age: 30} {name: 'ryu', age: 30}
   {name: 'chun-li', age: 40} {name: 'chun-li', age: 40}
>

The Document Object Model

Interacting with the Browser

Interacting with a Browser

  • add content to the browser
  • change CSS styles
  • react to user events (e.g clicking)
  • cool effects like popups

Interacting with a Browser

  • Document Object Model (DOM)
  • Add, change & delete content
  • Make a cool pop-up effect in the web page

VSCode Extensions:Live Server

The DOM Explained

Document Object Model – 文件物件模型 (DOM)

  • Created by the browser
  • ‘document’ object
// Google Console
>  document
<  #document
>  document.location
<  Location {ancestorOrigins: DOMStringList, href: 'http://127.0.0.1:5500/index.html', origin: 'http://127.0.0.1:5500', protocol: 'http:', host: '127.0.0.1:5500', …}
>  document.URL
<  'http://127.0.0.1:5500/index.html'
>

Document Object Model – 文件物件模型 (DOM)

DOM

The Query Selector

// index.html - 1

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Modern JavaScript</title>
</head>
<body>
    <h1>The DOM</h1>

    <div>
        <p>hello, world</p>
        <p>lorem ipsum</p>
        <p class="error">this is an error message</p>
    </div>


    <script src="sandbox.js"></script>
</body>
</html>
// sandbox.js - 1
const para = document.querySelector('p');

console.log(para);
// Google Console - 1
   <p>hello, world</p>
>
// all.js - 2

const para = document.querySelector('.error');

console.log(para);
// Google Console - 2
   <p class="error">this is an error message</p>
>
// index.html - 3

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Modern JavaScript</title>
</head>
<body>
    <h1>The DOM</h1>

    <div>
        <p>hello, world</p>
        <p>lorem ipsum</p>
        <p class="error">this is an error message</p>
    </div>

    <div class="error">this is another error</div>

    <script src="sandbox.js"></script>
</body>
</html>
// sandbox.js - 3

const para = document.querySelector('div.error');

console.log(para);
// Google Console - 3
   <div class="error">this is another error</div>
>
// sandbox.js - 4

const para = document.querySelector('body > h1');

console.log(para);
// Google Console - 4
   <h1>The DOM</h1>
>
// sandbox.js - 5

// const para = document.querySelector('body > h1');

// console.log(para);

const paras = document.querySelectorAll('p');

console.log(paras);
// Google Console - 5
   NodeList(3) [p, p, p.error]
>
// all.js - 6

// const para = document.querySelector('body > h1');

// console.log(para);

const paras = document.querySelectorAll('p');

console.log(paras);
console.log(paras[0]);
console.log(paras[2]);
// Google Console - 6
   NodeList(3) [p, p, p.error]
   <p>hello, world</p>
   <p class="error">this is an error messate</p>
>
// sandbox.js - 7

// const para = document.querySelector('body > h1');

// console.log(para);

const paras = document.querySelectorAll('p');

paras.forEach(para => {
  console.log(para);
})

// console.log(paras[2]);
// Google Console - 7
   <p>hello, world</p>
   <p>lorem ipsum</p>
   <p class="error>this is an error message</p>
>
// sandbox.js - 8

// const para = document.querySelector('body > h1');

// console.log(para);

const paras = document.querySelectorAll('p');
const errors = document.querySelectorAll('.error');

console.log(errors);
// Google Console - 8
   NodeList(2) [p.error, div.error]
>

Other Ways to Query the DOM

// index.html

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Modern JavaScript</title>
</head>
<body>
    <h1 id="page-title">The DOM</h1>

    <div>
        <p>hello, world</p>
        <p>lorem ipsum</p>
        <p class="error">this is an error message</p>
    </div>

    <div class="error">this is another error</div>

    <script src="sandbox.js"></script>
</body>
</html>
// sandbox.js - 1

// get an element by ID
const title = document.getElementById('page-title');
console.log(title);

// get elements by their class name
const errors = document.getElementsByClassName('error');
console.log(errors);
console.log(errors[0]);
errors.forEach(error => {
  console.log(error);
});

// get elements by their tag name
// Google Console - 1
   h1#page-title
   HTMLCollection(2) [p.error, div.error]
   p.error
x  Uncaught TypeError: errors.forEach is not a function at sandbox.js:9
>
// sandbox.js - 2

// get elements by their tag name
const paras = document.getElementsByTagName('p');
console.log(paras);
console.log(paras[1]);
// Google Console - 2
   HTMLCollection(3) [p, p, p.error]
   <p>lorem ipsum</p>
>

Adding & Changing Page Content

// index.html

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Modern JavaScript</title>
</head>
<body>
    <h1 id="page-title">The DOM</h1>

    <div>
        <p>hello, world</p>
        <p>lorem ipsum</p>
        <p class="error">this is an error message</p>
    </div>

    <div class="content">
        <p>this is the content</p>
    </div>

    <script src="sandbox.js"></script>
</body>
</html>
// sandbox.js - 1

const para = document.querySelector('p');
console.log(para.innerText);
// Google Console - 1
   hello, world
>
// sandbox.js - 2

const para = document.querySelector('p');

// console.log(para.innerText);
para.innerText = 'ninjas are awesome';
// 瀏覽器畫面 - 2
The DOM

ninjas are awesome
lorem ipsum
this is an error message
this is the content
// sandbox.js - 3

const para = document.querySelector('p');

// console.log(para.innerText);
para.innerText += 'ninjas are awesome';
// 瀏覽器畫面 - 3
The DOM

hello, worldninjas are awesome
lorem ipsum
this is an error message
this is the content
// sandbox.js - 4

const para = document.querySelector('p');

// console.log(para.innerText);
// para.innerText += 'ninjas are awesome';

const paras = document.querySelectorAll('p');

paras.forEach(para => {
  console.log(para.innerText);
})
// Google Console - 4
   hello, world
   lorem ipsum
   this is an error message
   this is the content
>
// sandbox.js - 5

const para = document.querySelector('p');

// console.log(para.innerText);
// para.innerText += 'ninjas are awesome';

const paras = document.querySelectorAll('p');

paras.forEach(para => {
  console.log(para.innerText);
  para.innerText += ' new text';
})
// 瀏覽器畫面 - 5
The DOM

hello, world new text
lorem ipsum new text
this is an error message new text
this is the content new text
// sandbox.js - 6

const para = document.querySelector('p');

// console.log(para.innerText);
// para.innerText += 'ninjas are awesome';

const paras = document.querySelectorAll('p');

// paras.forEach(para => {
//   console.log(para.innerText);
//   para.innerText += ' new text';
// })

const content = document.querySelector('.content');

// console.log(content.innerHTML);
content.innerHTML = '<h2>THIS IS A NEW H2</h2>';
// 瀏覽器畫面 - 6
The DOM

hello, world
lorem ipsum
this is an error message
THIS IS A NEW H2
// sandbox.js - 7

const para = document.querySelector('p');

// console.log(para.innerText);
// para.innerText += 'ninjas are awesome';

const paras = document.querySelectorAll('p');

// paras.forEach(para => {
//   console.log(para.innerText);
//   para.innerText += ' new text';
// })

const content = document.querySelector('.content');

// console.log(content.innerHTML);
content.innerHTML += '<h2>THIS IS A NEW H2</h2>';
// 瀏覽器畫面 - 7
The DOM

hello, world
lorem ipsum
this is an error message
this is the content
THIS IS A NEW H2
// sandbox.js - 8

const para = document.querySelector('p');

// console.log(para.innerText);
// para.innerText += 'ninjas are awesome';

const paras = document.querySelectorAll('p');

// paras.forEach(para => {
//   console.log(para.innerText);
//   para.innerText += ' new text';
// })

const content = document.querySelector('.content');

// console.log(content.innerHTML);
// content.innerHTML += '<h2>THIS IS A NEW H2</h2>';

const people = ['mario', 'luigi', 'yoshi'];

people.forEach(person => {
  content.innerHTML += `<p>${person}</p>`;
});
// 瀏覽器畫面 - 8
The DOM

hello, world
lorem ipsum
this is an error message
this is the content
mario
luigi
yoshi

Getting & Setting Attributes

// sandbox.js

const link = document.querySelector('a');

console.log(link.getAttribute('href'));
link.setAttribute('href','https://www.thenetninja.co.uk');
link.innerText = 'The Net Ninja Website';

const mssg = document.querySelector('p');

console.log(mssg.getAttribute('class'));
mssg.setAttribute('class','success');
mssg.setAttribute('style', 'color: green;');
// Google Console
   https://www.google.com
   error
>
// Google Elements

<html lang="en">
  <head>...</head>
  <body>
    <h1>The DOM</h1>
    <a href="https://www.thenetninja.co.uk">The Net Ninja Website</a>
    <p class="success" style="color: green;">lorem ipsum</p>
    <script src="sandbox.js"></script>
    <!-- Code injected by live-server -->
    <script type="text/javascript>...</script>
  </body>
</html>

Changing CSS Styles

// index.html

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Modern JavaScript</title>
</head>
<body>
    <h1 style="color: orange">The DOM</h1>

    <script src="sandbox.js"></script>
</body>
</html>
// sandbox.js

const title = document.querySelector('h1');

// title.setAttribute('style', 'marin: 50px;');

console.log(title.style);
console.log(title.style.color);

title.style.margin = '50px';
title.style.color = 'crimson';
// font-size 使用小駝峰命名,要寫成 fontSize
title.style.fontSize = '60px';
// 移除樣式
title.style.margin = '';
// Google Console
   CSSStyleDeclaration {0: 'color', accentColor: '', additiveSymbols: '', alignContent: '', alignItems: '', alignSelf: '', …}
   orange
>

Adding & Removing Classes

// index.html - 1

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>Modern JavaScript</title>
</head>
<body>
    <h1>The DOM</h1>

    <p>
        Lorem ipsum dolor, sit amet consectetur adipisicing elit. Molestiae minus iusto et.
    </p>

    <script src="sandbox.js"></script>
</body>
</html>
// style.css - 1

.error {
  padding: 10px;
  color: crimson;
  border: 1px dotted crimson;
}

.success {
  padding: 10px;
  color: limegreen;
  border: 1px dotted limegreen;
}
// sandbox.js - 1

const content = document.querySelector('p');

console.log(content.classList);
content.classList.add('error');
content.classList.remove('error');
content.classList.add('success');
// Google Console - 1
   DOMTokenList [value: '']
>
// index.html - 2

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>Modern JavaScript</title>
</head>
<body>
    <h1 class="title">The DOM</h1>

    <p>lorem error ipsum</p>
    <p>lorem success ipsum</p>
    <p>lorem ipsum lorem</p>
    <p>lorem ipsum success</p>
    <p>error lorem ipsum</p>
    <p>lorem ipsum lorem</p>
    <p>lorem ipsum error</p>
    <p>success lorem ipsum</p>

    <script src="sandbox.js"></script>
</body>
</html>
// style.css - 2

.error {
  padding: 10px;
  color: crimson;
  border: 1px dotted crimson;
}

.success {
  padding: 10px;
  color: limegreen;
  border: 1px dotted limegreen;
}
// sandbox.js - 2

const paras = document.querySelectorAll('p');

paras.forEach(p => {
  // console.log(p.textContent);
  if(p.textContent.includes('error')){
    p.classList.add('error');
  }
  if(p.innerText.includes('success')){
    p.classList.add('success');
  }
});

const title = document.querySelector('.title');

title.classList.toggle('test');
title.classList.toggle('test');

Parents, Children & Siblings

Siblings
Parents & Children
// index.html - 1

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Modern JavaScript</title>
</head>
<body>
    <h1>The DOM</h1>

    <article>
        <h2>article title</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
        <div>written by the net ninja</div>
    </article>

    <script src="sandbox.js"></script>
</body>
</html>
// sandbox.js - 1

const article = document.querySelector('article');

console.log(article.children);
console.log(Array.from(article.children));
console.log(article.children);
// Google Console - 1
   HTMLCollection(5) [h2, p, p, p, div]
   (5) [h2, p, p, p, div]
   HTMLCollection(5) [h2, p, p, p, div]
>
// sandbox.js - 2

const article = document.querySelector('article');

// console.log(article.children);
// console.log(Array.from(article.children));
// console.log(article.children);

Array.from(article.children).forEach(child => {
  child.classList.add('article-element');
}); 
// Google Elements - 2

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Modern JavaScript</title>
</head>
<body>
    <h1>The DOM</h1>

    <article>
        <h2 class="article-element">article title</h2>
        <p class="article-element">Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
        <p class="article-element">Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
        <p class="article-element">Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
        <div class="article-element">written by the net ninja</div>
    </article>

    <script src="sandbox.js"></script>
</body>
</html>
// index.html - 3

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Modern JavaScript</title>
</head>
<body>
    <h1>The DOM</h1>

    <article>
        <p>new sibling</p>
        <h2>article title</h2>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
        <div>written by the net ninja</div>
    </article>

    <script src="sandbox.js"></script>
</body>
</html>
// sandbox.js - 3

const article = document.querySelector('article');

// console.log(article.children);
// console.log(Array.from(article.children));
// console.log(article.children);

// Array.from(article.children).forEach(child => {
//   child.classList.add('article-element');
// });

const title = document.querySelector('h2');

console.log(title.parentElement);
console.log(title.parentElement.parentElement);
console.log(title.nextElementSibling);
console.log(title.previousElementSibling);

// chaining
console.log(title.nextElementSibling.parentElement.children);
// Google Console - 3
   <article>...</article>
   <body>...</body>
   <p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
   <p>new sibling</p>
   HTMLCollection(6) [p, h2, p, p, p, div]
>

Event Basics (click events)

// index.html - 1

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Modern JavaScript</title>
    <style>
        li {
            list-style-type: none;
            max-width: 200px;
            padding: 8px;
            margin: 8px auto;
            background: #eee;
            border: 1px dotted #ddd;
        }
    </style>
</head>
<body>
    <h1>Todos</h1>

    <ul>
        <li>buy milk</li>
        <li>read a book</li>
        <li>play the guitar</li>
        <li>pay the bills :(</li>
    </ul>

    <button>click me</button>

    <script src="sandbox.js"></script>
</body>
</html>
// sandbox.js - 1

const button = document.querySelector('button');

button.addEventListener('click', () => {
  console.log('you clicked me');
});
// Google Console - 1
   you clicked me
>
// all.js - 2

// const button = document.querySelector('button');

// button.addEventListener('click', () => {
//   console.log('you clicked me');
// });

const items = document.querySelectorAll('li');

items.forEach(item => {
  item.addEventListener('click', e => {
    // console.log('item clicked');
    // console.log(e);
    // console.log(e.target);
    // console.log(item);
    e.target.style.textDecoration = 'line-through';
  });
});

Creating & Removing Elements

// index.html - 1

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Modern JavaScript</title>
    <style>
        li {
            list-style-type: none;
            max-width: 200px;
            padding: 8px;
            margin: 8px auto;
            background: #eee;
            border: 1px dotted #ddd;
        }
    </style>
</head>
<body>
    <h1>Todos</h1>

    <ul>
        <li>buy milk</li>
        <li>read a book</li>
        <li>play the guitar</li>
        <li>pay the bills :(</li>
    </ul>

    <button>click me</button>

    <script src="sandbox.js"></script>
</body>
</html>
// sandbox.js - 1

// const ul = document.querySelector('ul');
// ul.remove();

const items = document.querySelectorAll('li');

items.forEach(item => {
  item.addEventListener('click', e => {

    // e.target.style.textDecoration = 'line-through';
    e.target.remove();
    
  });
});
// index.html - 2

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Modern JavaScript</title>
    <style>
        li {
            list-style-type: none;
            max-width: 200px;
            padding: 8px;
            margin: 8px auto;
            background: #eee;
            border: 1px dotted #ddd;
        }
    </style>
</head>
<body>
    <h1>Todos</h1>

    <ul>
        <li>buy milk</li>
        <li>read a book</li>
        <li>play the guitar</li>
        <li>pay the bills :(</li>
    </ul>

    <button>add new todo</button>

    <script src="sandbox.js"></script>
</body>
</html>
// sandbox.js - 2

const ul = document.querySelector('ul');
// ul.remove();

const button = document.querySelector('button');

button.addEventListener('click', () => {
  ul.innerHTML += '<li>something new</li>';
});

const items = document.querySelectorAll('li');

items.forEach(item => {
  item.addEventListener('click', e => {

    // e.target.style.textDecoration = 'line-through';
    e.target.remove();

  });
});
// sandbox.js - 3

const ul = document.querySelector('ul');
// ul.remove();

const button = document.querySelector('button');

button.addEventListener('click', () => {
  const li = document.createElement('li');
  li.textContent = 'something new to do';
  // ul.append(li);
  ul.prepend(li);
});

const items = document.querySelectorAll('li');

items.forEach(item => {
  item.addEventListener('click', e => {

    // e.target.style.textDecoration = 'line-through';
    e.target.remove();

  });
});

Event Bubbling (and delegation)

// index.html - 1

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Modern JavaScript</title>
    <style>
        li {
            list-style-type: none;
            max-width: 200px;
            padding: 8px;
            margin: 8px auto;
            background: #eee;
            border: 1px dotted #ddd;
        }
    </style>
</head>
<body>
    <h1>Todos</h1>

    <ul>
        <li>buy milk</li>
        <li>read a book</li>
        <li>play the guitar</li>
        <li>pay the bills :(</li>
    </ul>

    <button>add new todo</button>

    <script src="sandbox.js"></script>
</body>
</html>
// sandbox.js - 1

const ul = document.querySelector('ul');
const button = document.querySelector('button');

button.addEventListener('click', () => {
  const li = document.createElement('li');
  li.textContent = 'something new to do';
  ul.prepend(li);
});

const items = document.querySelectorAll('li');

items.forEach(item => {
  item.addEventListener('click', e => {
    console.log('event in LI');
    e.stopPropagation();
    e.target.remove();
  });
});

ul.addEventListener('click', e => {
  console.log('event in UL');
});
// sandbox.js - 2

const ul = document.querySelector('ul');
const button = document.querySelector('button');

button.addEventListener('click', () => {
  const li = document.createElement('li');
  li.textContent = 'something new to do';
  ul.prepend(li);
});

// const items = document.querySelectorAll('li');

// items.forEach(item => {
//   item.addEventListener('click', e => {
//     console.log('event in LI');
//     e.stopPropagation();
//     e.target.remove();
//   });
// });

ul.addEventListener('click', e => {
  // console.log('event in UL');
  // console.log(e.target);
  // console.log(e);

  // tagName not found 
  if(e.target.nodeName === 'LI') {
    e.target.remove();
  }
});

More DOM Events

// index.html

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Modern JavaScript</title>
    <style>
        .box {
            width: 200px;
            height: 200px;
            margin: 10px 0;
            background: #eee;
            text-align: center;
            padding: 20px;
        }
    </style>
</head>
<body>
    <p class="copy-me">Lorem ipsum dolor sit, amet consectetur</p>
    <div class="box">move the mouse around this box</div>

    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p>
    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p>
    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p>
    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p>
    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p>
    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p>
    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p>
    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p>
    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p>
    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p>
    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p>
    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p>
    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p>
    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p>
    <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit.</p>

    <script src="sandbox.js"></script>
</body>
</html>
// sandbox.js

const copy = document.querySelector('.copy-me');

copy.addEventListener('copy', () => {
  console.log('OI! my content is copyright');
});

const box = document.querySelector('.box');

box.addEventListener('mousemove', e => {
  // console.log(e);
  // console.log(e.offsetX, e.offsetY);
  box.textContent = `x pos - ${e.offsetX} y pos - ${e.offsetY}`;
});

document.addEventListener('wheel', e => {
  // console.log(e);
  console.log(e.pageX, e.pageY);
});

Building a Popup

// index.html

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>Modern JavaScript</title>
</head>
<body>
    
    <button>click me</button>

    <div class="popup-wrapper">

        <div class="popup">
            <div class="popup-close">x</div>
            <div class="popup-content">
                <h2>NINJA SALE!!</h2>
                <p>50% off all ninja clothing, don't miss out!!</p>
                <a href="#">view clothing</a>
            </div>
        </div>

    </div>

    <script src="popup.js"></script>
</body>
</html>
// style.css

button {
  display: block;
  margin: 20px auto;
  background: crimson;
  color: white;
  border: 0;
  padding: 6px 10px;
}

.popup-wrapper {
  background: rgba(0,0,0,0.5);
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: none;
}

.popup {
  font-family: arial;
  text-align: center;
  width: 100%;
  max-width: 300px;
  margin: 10% auto;
  padding: 20px;
  background: white;
  position: relative;
}

.popup a {
  background: crimson;
  color: white;
  text-decoration: none;
  padding: 6px 10px;
}

.popup-close {
  position: absolute;
  top: 5px;
  right: 8px;
  cursor: pointer;
}
// popup.js

const button = document.querySelector('button');
const popup = document.querySelector('.popup-wrapper');
const close = document.querySelector('.popup-close');

button.addEventListener('click', () => {
  popup.style.display = 'block';
});

close.addEventListener('click', () => {
  popup.style.display = 'none';
});

popup.addEventListener('click', () => {
  popup.style.display = 'none';
});