# Javascript ###### tags: `notes` ## Introduction HTML is the structure of web CSS is the display of it JS makes web interactive ## Reference - [x] 1. Basic tutorial: https://www.w3schools.com/js/js_intro.asp - [x] 2. Examples to practice: https://www.w3schools.com/js/js_examples.asp - [x] 3. Apply JS: https://www.w3schools.com/howto/howto_js_slideshow.asp - [x] 4. Project1: To Do List (F2E精神時光屋) 可編輯、可刪除、可提醒 https://codepen.io/search/pens?q=to%20do%20list&page=1&order=popularity&depth=everything&show_forks=false - [ ] 5. ES6 - [ ] 6. Advanced(JS 30): https://javascript30.com/ - [ ] 7. JQuery - [ ] 8. React ## Coding Style * camelCase * Global variables written in UPPERCASE * Constants (like PI) written in UPPERCASE * Line Length < 80 * use 4 spaces for indentation * Always end a simple statement with a semicolon * Hyphens are not allowed in JavaScript names ## Keep in mind * Minimize the use of global variables * Local variables must be declared with the var keyword, otherwise they will become global variables * It is a good coding practice to put all declarations at the top of each script or function * It is a good coding practice to initialize variables when you declare them. * Use === Comparison * Avoid Using eval() * Reduce DOM Size ``` var obj; obj = document.getElementById("demo"); //access once and use it locally obj.innerHTML = "Hello"; ``` * Avoid Unnecessary Variables Often you can replace code like this ``` var fullName = firstName + " " + lastName; document.getElementById("demo").innerHTML = fullName; ``` with this ``` document.getElementById("demo").innerHTML = firstName + " " + lastName ``` ## JS in HTML (script position) * In HTML, JavaScript code must be inserted between <script> and </script> tags ``` <script> document.getElementById("demo").innerHTML = "My First JavaScript"; </script> ``` * Scripts can be placed in the <body>, or in the <head> section of an HTML page, or in both 1. **Place in head** ``` <html> <head> /JS/ <script> function myFunction() { document.getElementById("demo").innerHTML = "Paragraph changed."; } </script> </head> <body> /html/ <h2>JavaScript in Head</h2> <p id="demo">A Paragraph.</p> <button type="button" onclick="myFunction()">Try it</button> </body> </html> ``` 2. **Place in body** placing scripts at the bottom of the <body> element improves the display speed, because script compilation slows down the display ``` <html> <body> /html/ <h2>JavaScript in Body</h2> <p id="demo">A Paragraph.</p> <button type="button" onclick="myFunction()">Try it</button> /JS/ <script> function myFunction() { document.getElementById("demo").innerHTML = "Paragraph changed."; } </script> </body> </html> ``` * External JavaScript ``` <script src="external.js"></script> ``` ## JavaScript Output Display * window: global object in a browser, the first thing that gets loaded into the browser, represents the browser's window. window object has the majority of the properties like length, innerWidth, innerHeight, name * document: document object is your html, aspx, php, or other document that will be loaded into the browser * document object (of the HTML DOM) is a property of the window object ``` window.document.getElementById("header"); ``` is the same as ``` document.getElementById("header"); ``` --- > **where does JS execute?** ### innerHTML: writing into an HTML element Changing the innerHTML property of an HTML element is a common way to display data in HTML. ``` <body> <p id="demo"></p> <script> //insert the value 11 in paragraph of id 'demo' document.getElementById("demo").innerHTML = 5 + 6; </script> </body> ``` ### document.write(): writing into the HTML output For testing purposes, it is convenient to use document.write() ``` <body> <h2>My First Web Page</h2> <p>My first paragraph.</p> <script> document.write(5 + 6); </script> </body> ``` ![](https://i.imgur.com/q0pXXuQ.png) Using document.write() after an HTML document is fully loaded, will delete all existing HTML ``` <body> <h2>My First Web Page</h2> <p>My first paragraph.</p> <button type="button" onclick="document.write(5 + 6)">Try it</button> </body> ``` ![](https://i.imgur.com/ThXBkex.png)-->![](https://i.imgur.com/UenotbE.png) ### window.alert(): writing into an alert box ``` <body> <h1>My First Web Page</h1> <p>My first paragraph.</p> <script> window.alert(5 + 6); </script> </body> ``` ![](https://i.imgur.com/A46z6F4.png) ### console.log(): writing into the browser console ``` <body> <h2>Activate debugging with F12</h2> <p>Select "Console" in the debugger menu. Then click Run again.</p> <script> console.log(5 + 6); </script> </body> ``` ![](https://i.imgur.com/EdBiQbD.png) ## Basic Scripts ### get element from html * get the whole element ```document.getElementById('ID').innerHTML``` ``` <body> <div id="demo">Get this text</div> </body> ``` *getElementById(): uses the method to "find" an HTML element* ![](https://i.imgur.com/FyQYYKp.png =300x) *innerHTML: html content* ![](https://i.imgur.com/rOubaob.png =300x) * get attribute of an element ```document.getElementById('ID').attribute``` ``` <body> <a href="//www.w3schools.com" id="demo2">w3schools.com</a> </body> ``` ![](https://i.imgur.com/n6PCsFW.png =300x) * get element style ```document.getElementById('demo').style``` 1. change font-size: ```.style.fontSize = '125px'``` 2. change display: ```.style.display = 'none'``` ## HTML Events ```<element event="some JavaScript">``` use 'this' to change the element itself ``` <button onclick="this.innerHTML = Date()">The time is?</button> ``` use function to change the element ``` <body> <button onclick="displayDate()">The time is?</button> <script> function displayDate() { document.getElementById("demo").innerHTML = Date(); } </script> <p id="demo"></p> </body> ``` ### Common HTML Events ![](https://i.imgur.com/luXfa6E.png) ### HTML DOM Events HTML DOM events allow JavaScript to register different event handlers on elements in an HTML document. https://www.w3schools.com/jsref/dom_obj_event.asp ## JS Syntax ### JavaScript Values There are two types of values: literal & variable literal: number, string ### Data Type * 5 different data types that can contain values: string (primitive data), number (primitive data), boolean (primitive data), object (complex data), function (complex data) * 3 types of objects: Object, Date, Array Object ``` var person = { firstName:"John", lastName:"Doe", age:50, eyeColor:"blue" }; ``` Date Array ``` var cars = ["Saab","Volvo","BMW"] ``` * 2 data types that cannot contain values: null, undefined null: null is "nothing", it's type is object undefined (primitive data): a variable without a value, or a variable with a value undefined ``` var car; //car is undefined now car = undefined; //the value of car is undefined now ``` * Difference between null and undefined: ``` typeof undefined // undefined typeof null // object null === undefined // false null == undefined // true ``` * empty value: (var car = "";) has nothing to do with undefined, it's a string * typeof operator ``` typeof "John" // Returns "string" typeof 3 // Returns "number" ``` ### Keywords Used to identify actions to be performed ![](https://i.imgur.com/328mGy9.png) #### void http://www.runoob.com/js/js-void.html void 是 JavaScript 中非常重要的關鍵字,該操作符指定要計算一個表達式但是不返回值。 ### JavaScript Code Blocks Put a seirs of scripts in a function ``` <body> <button type="button" onclick="myFunction()">Click Me!</button> <p id="demo1"></p> <p id="demo2"></p> <script> function myFunction() { document.getElementById("demo1").innerHTML = "Hello Dolly!"; document.getElementById("demo2").innerHTML = "How are you?"; } </script> </body> ``` ![](https://i.imgur.com/0vjQxwa.png)-->![](https://i.imgur.com/yB8ZFmj.png) ### Comparison Operators ![](https://i.imgur.com/jNtG3ZS.png) ### Logical Operators ![](https://i.imgur.com/2EcyY3b.png) ### Function * functions are defined with the **function** keyword * parameter: list in function * argument: the values received by the function * Inside the function, the arguments (the parameters) behave as local variables #### ways to define function ``` //Function Declaration function myFunction(a, b) { return a * b; } //Function Expression var x = function (a, b) {return a * b}; //Functions stored in variables do not need function names //with built-in function constructor Function() var myFunction = new Function("a", "b", "return a * b"); var x = myFunction(4, 3); ``` * function hoisting: moving declarations to the top #### Function Constructor #### self-invoking do not have to add () after the function, basically add () means call the function ``` //function without self-invoking function add() { var num = 0; return function() { num++; } } var plus = add(); plus; //ƒ () {return num++;} plus(); //0 plus(); //1 plus(); //2 //function with self-invoking var add = (function() { var num = 0; return function() { num++; } })(); add(); //0 add(); //1 add(); //2 ``` #### ways to invoke function 1. invoke as a method: if you define function in an object, it's called method ``` var myObject = { firstName:"John", lastName: "Doe", fullName: function () { return this.firstName + " " + this.lastName; } } myObject.fullName(); ``` 2. invoke with a function constructor ``` // This is a function constructor function myFunction(arg1, arg2) { this.firstName = arg1; this.lastName = arg2; } // This creates a new object var x = new myFunction("John", "Doe"); x.firstName; ``` 3. self-invoking ``` (function () { var x = "Hello!!"; // I will invoke myself })(); ``` #### Function Closure variables could be globally or locally, but in order to avoid function variables being revised, it's often better to use closure to set variable locally towards the window and globally inside the function * If we put variable globally, when we add 1 to the variable, the variable will be changed and store as new changed number. However, the global variable could be changed easily from the ouside which makes the variable being under danger ``` //put varible globally var num = 0; function add() { return num++ } add() //1 add() //2 ``` * If we put the variable locally inside the function, the variable change will not be stored ``` //put variable locally function add() { var num = 0; return num+1; } add() //1 add() //1 add() //1 ``` * So a balance way is to use closure letting the inner function owns the variable globally, but we cannot change it globally ``` function add() { var num = 0; return function() { return num++; } } var num_after_add = add(); num_after_add() //0 num_after_add() //1 num_after_add() //2 ``` P.S. for the function, num_after_add, it owns num as a global variable (for it, but for the outside window, num is still a locally variable), and could change it everytime num_after_add being called, if you didn't store num_after_add as a variable, the num will not be rememberd ``` function add() { var num = 0; return function() { return num++; } } add()(); //0 add()(); //0 add()(); //0 ``` #### Arrow Function ``` // ES5 var x = function(x, y) { return x * y; } // ES6 const x = (x, y) => return { x * y }; ``` ### Object When a JavaScript variable is declared with the keyword "new", the variable is created as an object #### Property ``` var person = { firstName:"John", lastName:"Doe", age:50, eyeColor:"blue", fullName: function() {return this.firstName + " " + this.lastName;} }; ``` ![](https://i.imgur.com/rDFCN4Z.png) * we can access property in two ways ``` person.firstName //John person["firstName"] //John ``` #### Do Not Declare Strings, Numbers, and Booleans as Objects, they complicate your code and slow down execution speed ``` var x = new String(); // Declares x as a String object var y = new Number(); // Declares y as a Number object var z = new Boolean(); // Declares z as a Boolean object ``` #### Objects cannot be compared ``` var object1 = {person: 'john'}; var object2 = {person: 'john'}; object1 == object2 //false ``` #### Objects are Mutable The object x is not a copy of person. It is person. Both x and person are the same object ``` var person = {firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"} var x = person; x.age = 10; // This will change both x.age and person.age ``` ### String #### string method although string is primitive, javascript allows it to act as object which has property and methods * length ``` var name = 'john'; name.length //return 4 ``` * indexOf * lastIndexOf * search * slice: extracts a part of a string ``` var str = "Apple, Banana, Kiwi"; str.slice(7, 13) //return Banana ``` If a parameter is negative, the position is counted from the end of the string. ``` var str = "Apple, Banana, Kiwi"; str.slice(-12, -6) //return Banana ``` * substr: the second parameter specifies the length of the extracted part ``` var str = "Apple, Banana, Kiwi"; str.substr(7, 6) //return Banana ``` * replace: replaces only the first match (if you want it to replace all matches, add /g flag), case sensitive (if you want it to be insensitive, add /i flag) ``` str = "Please visit Microsoft!"; str.replace("Microsoft", "W3Schools"); //Please visit W3Schools! ``` * concate ``` var text = "Hello".concat(" ", "World!"); //Hello World! ``` * split ``` var txt = "a,b,c,d,e"; // String txt.split(","); // Split on commas txt.split(" "); // Split on spaces txt.split("|"); txt.split(",")[0] //return 'a' ``` ### Number ``` var x = 123; typeof x //return number //You can also new a number with the following way, but not recommend because it slow down the speed var x = new Number(123); typeof x //return object ``` ### Array * belongs to object ``` var cars = ["Saab", "Volvo"] cars[0] //Saab //You can also new an array with the following way, but same as not recommended var cars = new Array("Saab", "") ``` * use arrary but not object to call array because some difference of them ``` //array use number to call elements var cars = ["Volvo", "Saab"] cars[0] //return Volvo //Object use name to call elements var cars = {first: "volvo", second: "saab"} cars.first //return volvo ``` * array element can be object * Associative Arrays: support array with name index * JS does not support associative array, if you try to use name index for JS array, it will automatically redefine as an object ``` var person = []; person[0] = "John"; person[1] = "Doe"; person[2] = 46; var x = person.length; // person.length will return 3 var y = person[0]; //will return undefined ``` * When to Use Arrays. When to use Objects. JavaScript does not support associative arrays. You should use objects when you want the element names to be strings (text). You should use arrays when you want the element names to be numbers. * push: add new element in the end of an array * pop: remove the last element in an array ``` var fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.push("Lemon"); //["Banana", "Orange", "Apple", "Mango", "Lemon"] fruits.pop(); //["Banana", "Orange", "Apple"] ``` * shift: add new element in the beginning of an array * unshift: remove the first element of an array * splice: could add and remove element ``` var fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.splice(2, 0, "Lemon", "Kiwi"); //2 means where to insert "Lemon" and "Mango", 0 means remove zero elements fruits.splice(0, 2); //0 means where to remove the element, 2 means how many elements to be removed ``` * concat: merge two arrays ``` var myGirls = ["Cecilie", "Lone"]; var myBoys = ["Emil", "Tobias", "Linus"]; var myChildren = myGirls.concat(myBoys); // Concatenates (joins) myGirls and myBoys ``` ### Conditional (Ternary) Operator ``` <input id="age"> <button onclick = "determineVoteable()">Try it</button> <p id="voteable-or-not"></p> <script> function determineVoteable() { var age = Number(document.getElementById('age').value); if (isNaN(age)) { var voteable = "please enter a number"; } else { var voteable = (age > 18) ? "Too young":"Old eoungh"; } document.getElementById('voteable-or-not').innerHTML = voteable; } </script> ``` ![](https://i.imgur.com/N08zwPb.png)-->![](https://i.imgur.com/6v5Z8HO.png) ### Conditional Statement ``` if (time < 10) { greeting = "Good morning"; } else if (time < 20) { greeting = "Good day"; } else { greeting = "Good evening"; } ``` ### Switch ``` <body> <p id="demo"></p> <script> var day; switch (new Date().getDay()) { case 0: day = "Sunday"; break; case 1: day = "Monday"; break; case 2: day = "Tuesday"; break; case 3: day = "Wednesday"; break; case 4: day = "Thursday"; break; case 5: day = "Friday"; break; case 6: day = "Saturday"; } document.getElementById('demo').innerHTML = "Today is " + day; </script> </body> //Today is Wednesday ``` The default keyword specifies the code to run if there is no case match , it's a good habit to end your switches with defaults ``` switch (new Date().getDay()) { case 6: text = "Today is Saturday"; break; case 0: text = "Today is Sunday"; break; default: text = "Looking forward to the Weekend"; } ``` common code blocks ``` switch (new Date().getDay()) { case 4: case 5: text = "Soon it is Weekend"; break; case 0: case 6: text = "It is Weekend"; break; default: text = "Looking forward to the Weekend"; } ``` ### Loop * for loop ``` <body> <p id="demo"></p> <script> var cars = ["BMW", "Volvo", "Saab", "Ford", "Fiat", "Audi"]; var text = ""; var i; for (i = 0; i < cars.length; i++) { text += cars[i] + "<br>"; } document.getElementById("demo").innerHTML = text; </script> </body> /*return BMW Volvo Saab Ford Fiat Audi */ ``` * statement1: i=0, could be placed outside the loop ``` var i = 0; var len = cars.length; var text = ""; for (; i < len; i++) { text += cars[i] + "<br>"; } ``` * statemen3: i++, could be placed inside the loop ``` var i = 0; var len = cars.length; var text = ""; for (; i < len;) { text += cars[i] + "<br>"; i++; } ``` ### for/in loop ``` var person = {fname:"John", lname:"Doe", age:25}; var text = ""; var x; for (x in person) { text += person[x]; } ``` ### while loop ``` while (i < 10) { text += "The number is " + i; i++; } ``` ### do/while loop ``` do { text += "The number is " + i; i++; } while (i < 10); ``` ### break/continue * break: jump out of a loop ``` for (i = 0; i < 10; i++) { if (i === 3) { break; } text += "The number is " + i + "<br>"; } /* The number is 0 The number is 1 The number is 2 */ ``` * continue: skip a certain condition in a loop ``` for (i = 0; i < 10; i++) { if (i === 3) { continue; } text += "The number is " + i + "<br>"; } /* The number is 0 The number is 1 The number is 2 //jump over 3 The number is 4 The number is 5 The number is 6 The number is 7 The number is 8 The number is 9 */ ``` ### Label ``` var cars = ["BMW", "Volvo", "Saab", "Ford"]; list: { text += cars[0] + "<br>"; text += cars[1] + "<br>"; text += cars[2] + "<br>"; break list; text += cars[3] + "<br>"; text += cars[4] + "<br>"; text += cars[5] + "<br>"; } ``` ### RegExp (Regular Expression) a sequence of characters that forms a search pattern ```/pattern/modifiers``` ``` /w3schools/i is a regular expression w3schools is a pattern (to be used in a search) i is a modifier (modifies the search to be case-insensitive) ``` * modifiers ![](https://i.imgur.com/Viw3ujR.png) * search() ``` var str = "Visit W3Schools"; //use search with RegExp var n = str.search(/w3schools/i); //use search with String var n = str.search("W3Schools"); ``` * replace() ``` var str = "Visit Microsoft!"; //use replace with RegExp var res = str.replace(/microsoft/i, "W3Schools"); //use replace with String var res = str.replace("Microsoft", "W3Schools"); ``` * test(): check if a pattern exists ``` var patt = /e/; patt.test("The best things in life are free!"); //true ``` ### Error error is a built in object (called err) with 'name' and 'message' two property #### error type (err.name) * Eval Error: an error in the eval() function ``` eval(): execute on a string eval("2+3") //5 ``` * Range Error: use a number that is outside the range of legal values ``` var num = 1; try { num.toPrecision(500); // A number cannot have 500 significant digits } catch(err) { document.getElementById("demo").innerHTML = err.name; } //RangeError ``` * Reference Error: use a variable that has not been declared ``` var x; try { x = y + 1; // y cannot be referenced (used) } catch(err) { document.getElementById("demo").innerHTML = err.name; } //ReferenceError ``` * Syntax Error: if you try to evaluate code with a syntax error ``` try { eval("alert('Hello)"); // Missing ' will produce an error } catch(err) { document.getElementById("demo").innerHTML = err.name; } //SyntaxError ``` * Type Error: if you use a value that is outside the range of expected types ``` var num = 1; try { num.toUpperCase(); // You cannot convert a number to upper case } catch(err) { document.getElementById("demo").innerHTML = err.name; } //TypeError ``` * URI Error: if you use illegal characters in a URI function ``` try { decodeURI("%%%"); // You cannot URI decode these percent signs } catch(err) { document.getElementById("demo").innerHTML = err.name; } //URIError ``` #### test error * try: try a block of code and test it * catch: catch the error and do sth. with it * throw: thrwo a message, allows you to create custom error message * finally: lets you execute code, after try and catch, regardless of the result Usage ``` try { Block of code to try } catch(err) { Block of code to handle errors } finally { Block of code to be executed regardless of the try / catch result } ``` Example ``` function myFunction() { var message, x; message = document.getElementById("p01"); message.innerHTML = ""; x = document.getElementById("demo").value; try { if(x == "") throw "is empty"; if(isNaN(x)) throw "is not a number"; x = Number(x); if(x > 10) throw "is too high"; if(x < 5) throw "is too low"; } catch(err) { message.innerHTML = "Error: " + err + "."; } finally { document.getElementById("demo").value = ""; } } ``` ### Hoisting * declarations are hoisted ``` x = 5; // Assign 5 to x elem = document.getElementById("demo"); // Find an element elem.innerHTML = x; // Display x in the element var x; // Declare x, this will be hoisted ``` * initializations are not hoisted ``` var x = 5; // Initialize x elem = document.getElementById("demo"); // Find an element elem.innerHTML = x + " " + y; // Display x and y var y = 7; // Initialize y, this will not be hoisted ``` #### Brain Storm why declaration will be hoisted, intialization will not? Guess: Initialization could be used in changing variable value, so we frequently us it in an order that only after we do something, we change the value, that is to say, if we hoisting initialization, the task order may be interupted. On the other hand, since declaration will not change variable value, and it's better call a variable after declaration, there's no concern for hoisting declaration. ### Use Strict * ```"use strict";``` defines that JavaScript code should be executed in "strict mode" * strict mode: does not allow using undeclared variables * why strict mode? if you mistyping a variable name as a global variable, the strict mode will throw you an error ## this Keyword use to mean the object that you are in ``` var person = { firstName: "John", lastName : "Doe", id : 5566, fullName : function() { return this.firstName + " " + this.lastName; }; ``` * access the method ``` person.fullName() //if you access a method without (), it will return the definition of the function ``` ### Function Binding ``` var person1 = { fullName: function() { return this.firstName + " " + this.lastName; } } var person2 = { firstName:"John", lastName: "Doe", } person1.fullName.call(person2); // Will return "John Doe" ``` ## HTML DOM (Document Object Model) ### introduction When a web page is loaded, the browser creates a Document Object Model of the page. With the HTML DOM, JavaScript can access and change all the elements of an HTML document. DOM: DOM defines a standard for accessing documents DOM standard is separated into 3 different parts: * Core DOM - standard model for all document types * XML DOM - standard model for XML documents * HTML DOM - standard object model and programming interface for HTML, Can be accessed with JavaScript (and with other programming languages). It defines: 1. The HTML elements as objects: in the DOM, all HTML elements are defined as objects 2. The **properties(values you can set/change)** of all HTML elements 3. The **methods(actions you can perform)** to access all HTML elements 4. The events for all HTML elements In other words: The HTML DOM is a standard for how to get, change, add, or delete HTML elements. ![](https://i.imgur.com/COtL2O2.png) ``` //getElementById is a method, while innerHTML is a property <body> <p id="demo"></p> <script> document.getElementById("demo").innerHTML = "Hello World!"; </script> </body> ``` ### Document Object the owner of all other objects in your web page, if you want to access any element in an HTML page, you always start with accessing the document object. ### get element | Method | Description | | -------- | -------- | | document.getElementById(id)| Find an element by element id| | document.getElementsByTagName(name)| Find elements by tag name| | document.getElementsByClassName(name)| Find elements by class name| |document.querySelectorAll(selector)|Find elements by css selector| * by tag name aware that when using tag name, you have to give index ([number]) to it, since there may exists several this kind of tags ``` <body> <p>first</p> <p>second</p> <p id="demo"></p> //will show 'first' <script> var x = document.getElementsByTagName('p'); document.getElementById('demo').innerHTML = x[0].innerHTML; </script> <body> ``` * by class name ``` <body> <p class='test'>first</p> <p class='test'>second</p> <p id="demo"></p> //will show 'first' <script> var x = document.getElementsByClassName('test') document.getElementById('demo').innerHTML = x[0].innerHTML </script> <body> ``` * by selector ``` <body> <p class='test'>first</p> <p class='test'>second</p> <p id="demo"></p> //will show 'first' <script> var x = document.querySelectorAll('p.test') document.getElementById('demo').innerHTML = x[0].innerHTML </script> <body> //by object collection ``` ### change element | Method | Description | | -------- | -------- | | *element.innerHTML = new html content*| Find an element by element id| | *element.attribute = new value* | Change the attribute value of an HTML element| | *element.setAttribute(attribute, value)*|Change the attribute value of an HTML element| |*element.style.property = new style*|Change the style of an HTML element| * change the attribute ``` <body> <img id="image" src="smiley.gif"> <script> document.getElementById("image").src = "landscape.jpg"; </script> </body> ``` * change the css style https://www.w3schools.com/jsref/dom_obj_style.asp ``` <body> <p id="p2">Hello World!</p> <script> document.getElementById("p2").style.color = "blue"; </script> </body> ``` * use event to change element ``` <body> <h1 id="id1">My Heading 1</h1> <button type="button" onclick="document.getElementById('id1').style.color = 'red'"> Click Me! </button> </body> ``` ### add/delete element |Method |Description| |-------|-----------| |document.createElement(element)|Create an HTML element| |document.removeChild(element)|Remove an HTML element| |document.appendChild(element)|Add an HTML element| |document.replaceChild(element)|Replace an HTML element| |document.write(text)|Write into the HTML output stream| ### add event handler |Method|Description| |------|-----------| |document.getElementById(id).onclick = function(){code}|Adding event handler code to an onclick event| ## AJAX (Asynchronous JavaScript And XML) ### XML introduction XML(E**x**tensible **M**arkup **L**anguage), kind of markdown language, which could be translated by computer ### AJAX introduction a technique for accessing web servers from a web page * XMLHttpRequest object + JS & HTML DOM * browser can transport data with XML, plain text, or JSON data type * working process ![](https://i.imgur.com/yrhShoh.png) |Process|Where| What(Who)| |-------|-----|-----| |1|Browser|event occur(user), create XMLHTTPRequest(JS)| |2|Network|sent HTTPRequest(JS)| |3|Server|process request(back-end language), create response(back-end language)| |4|Network|sent response(back-end)| |5|Browser|process response(JS), update page(JS)| ### AJAX Example ``` <body> <div id="demo"> <h2>Let AJAX change this text</h2> <button type="button" onclick="loadDoc()">Change Content</button> </div> <script> function loadDoc() { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { //tell server that browser is ready to do reaction if (this.readyState == 4 && this.status == 200) { document.getElementById("demo").innerHTML = this.responseText; } }; xhttp.open("GET", "ajax_info.txt", true); xhttp.send(); } </script> </body> ``` **1. var xhttp = new XMLHTTPRequest();** XMLHTTPRequest() is an object contains: onreadystatechange method, readyState, status, and responseText, etc. **2. onreadystatechange:** a function that triggered when readyState changes **3. readyState**: the status of XMLHttpRequest, value from 0~4 **4. status**: the status of the request, value 202 and 404 represents success and fail, reapectively **5. open method** ```xhttp.open(parameter)``` parameter includes * method: "GET", "POST", "PUT", "DELETE" * url * async (optional): true/false, indicating whether or not to perform the operation asynchronously, false means the send() method will not return until the response is received * user, password (optional) **6. send method** send request to the server, used for GET request **7. send(string) method** used for POST request #### important attibute of XMLHttpRequest http://www.w3school.com.cn/ajax/ajax_xmlhttprequest_onreadystatechange.asp ![](https://i.imgur.com/tCqFg0G.png =900x) ### POST or GET? post: no size limitation, more secure, often being used in sending user data #### GET ``` xhttp.open("GET", "demo_get.asp?t=" + Math.random(), true); xhttp.send(); ``` #### POST ``` xhttp.open("POST", "ajax_test.asp", true); xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xhttp.send("fname=Henry&lname=Ford"); ``` * setRequestHeader() sets the value of an HTTP request header, must be used after open() but before send() If this method is called several times with the same header, the values are merged into one single request header. ![](https://i.imgur.com/Dd20apQ.png) #### Synchronous true/false synchronous true: synchronous false: the code will wait until server completion, so there's no need for onreadystatechange() ``` xhttp.open("GET", "ajax_info.txt", false); xhttp.send(); document.getElementById("demo").innerHTML = xhttp.responseText; ``` Synchronous XMLHttpRequest (async = false) is not recommended because the JavaScript will stop executing until the server response is ready. If the server is busy or slow, the application will hang or stop. ## Synchronous and Asynchrnous ![](https://i.imgur.com/cg2kTaq.png) ## ES6 (ECMAScript 6) ### introduction ### var, let ,and const var: 認function的{} ES6 introduced the ```let``` declaration method, it's almost the same thing as ```var```, however, the variable that declarated by ```let``` could only work inside the block it exists. let: no hoisting ``` { let a = 1; var b = 2; } a //undefined b //2 ``` #### Condition for using 'let' It's suitable to use let in a for loop ``` for (let i = 0; i < 10; i++) { console.log(i); } //ReferenceError: i is not defined ``` there's error because i only exists in the for loop, outside the for loop, it's no longer existed #### Common error when using let ``` var a = []; for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 10 ``` Why a[6] output 10? Since ```var``` could be used outside the block it's exist, the i in ```console.log(i)``` changing as i changes value outside --- Using ```let``` to avoid this error: ``` var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 6 ``` 變量i是let聲明的,當前的i只在本輪循環有效,所以每一次循環的i其實都是一個新的變量 #### the special property of for loop the part of setting variable is a father environment of the script inside it ``` for (let i = 0; i < 3; i++) { let i = 'abc'; console.log(i); } // abc // abc // abc ``` #### Temporal Dead Zone (TDZ) 只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。 ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。 ``` var tmp = 123; if (true) { tmp = 'abc'; // ReferenceError let tmp; } // 不报错 var x = x; // ReferenceError: x is not defined let x = x; ``` #### Block (塊級作用域) 通过var声明的变量没有块级作用域 為甚麽要有塊級作用域? 如果只有 ## SVG ### Basic Shapes Ref: http://www.oxxostudio.tw/articles/201406/svg-03-basic-shapes.html 1. rectangle ``` <rect id="A" x="33" y="34" fill="#FF6CC4" stroke="#C30D23" stroke-width="3" width="75" height="75"/> ``` * x, y: the coordinate position of the left top point * fill: the fill color * stroke: the color of the border ``` <rect x="60" y="10" rx="10" ry="10" width="75" height="75" stroke="#FF5500" stroke-width="5" fill="#FFB255"/> ``` * rx, ry: set for circle corner radius 2. circle ``` <circle fill="#FF4343" stroke="#890000" stroke-width="5" cx="80.141" cy="73.446" r="44"/> ``` * cx, cy: circle center coordinate position * r: radius 3. ellipse ``` <ellipse fill="#77DD47" stroke="#246614" stroke-width="5" cx="100" cy="75" rx="67" ry="44"/> ``` * rx: radius of x-axis * ry: radius of y-axis 4. polygon ``` <polygon fill="#D271FF" points="100,56 62,107 37,49"/> <polygon fill="#68EADD" points="151,39 163,63 189,66 170,85 175,111 151,99 127,111 132,85 113,66 139,63 "/> <polygon fill="#FF7900" points="219,110 206,70 240,46 274,70 261,110 "/> ``` * use points coordinate position to draw ## D3.js put ```<script src="http://d3js.org/d3.v3.min.js"></script>``` in ```<header>``` firstly ### Basic Syntax #### select * by tag ``` d3.select('p') //select the only p tags d3.selectAll('p') //select all p tags ``` * by class name ``` d3.select('p.class-name') //select the class --- class-name in the p tags ``` #### Chaining Method HTML ``` <div>red <div>blue</div> </div> ``` JS ``` d3.select('div').style({ 'color': 'red'; }) d3.select('div div').style({ 'color': 'blue'; }) //or d3.select('div').style({ 'color': 'red'; }).select('div').style({ 'color': 'blue'; }) ``` ![](https://i.imgur.com/5dfBofN.png) #### Add elements * append (add after) ``` d3.select('body') .append('div') //same as appendChild in JS .html('I am div') //same as innerHTML method in JS .style({ 'border':'1px solid #000', 'width':'120px' }) ``` ![](https://i.imgur.com/OFS5hQd.png) ``` d3.select('body') .append('svg') .attr({ //use .attr to add attribute include classname of element 'width':200, 'height':200 }); ``` * insert (add before) ### Scale Most of time, the size of svg image is not our ideal size, it's too small or too big, in this case, we rely on scale method to control the size by ratio ``` var data = [ {x:0, y:1.89}, {x:1, y:2.77}, {x:2, y:0.86}, {x:3, y:3.45}, {x:4, y:4.13}, {x:5, y:3.59}, {x:6, y:2.33}, {x:7, y:3.79}, {x:8, y:2.61}, {x:9, y:2.15} ]; var width = 240, height = 120; var s = d3.select('#s'); s.attr({ 'width': width, 'height': height, }).style({ 'border':'1px solid #000' }); var line = d3.svg.line() .x(function(d) { return d.x; }).y(function(d) { return d.y; }); s.append('path') .attr({ 'd':line(data), 'stroke':'#09c', 'fill':'none' }); </script> ``` * Use number to set domain ``` //first of all, we define the scaleX,Y method about the scale on x-axis //range means the range you want to have //domain is the original scalar var scaleX = d3.scale.linear() .range([0,width]) .domain([0,9]); var scaleY = d3.scale.linear() .range([0,height]) .domain([0,5]); //then, change the position of x into scaleX(d.x) var line = d3.svg.line() .x(function(d) { return scaleX(d.x); }) .y(function(d) { return scaleY(d.y); }); ``` * Use min and max of data ``` var minX = d3.min(data, function(d) { return d.x }) var maxX = d3.max(data, function(d) { return d.x }) var scaleX = d3.scale.linear() .range([0, width]) .domain([minX, maxX]) ``` ## Frequent confused issues ### Height/Width * window.innerWidth Width (in pixels) of the browser window viewport including, if rendered, the vertical scrollbar. * window.screen.width * window.screen.availWidth amount of horizontal space in pixels available to the window * document.width * element.clientWidth inner width of an element in pixels. It includes padding but not the vertical scrollbar (if present, if rendered), border or margin. * element.offsetWidth * includes the element borders, the element horizontal padding, the element vertical scrollbar (if present, if rendered) and the element CSS width ### Apply syntax: `fn.apply(thisArg, [args])` thisArg: the value that call the function fn, when null, just call fn directly https://www.javascripttutorial.net/javascript-apply-method/ ### bind syntax: `bind(thisArg, arg1, ... , argN)` argi: Arguments to prepend to arguments provided to the bound function when invoking func ## Special Topics ### Introduction to events ref: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events Web events are not part of the core JavaScript language — they are defined as part of the APIs built into the browser. The event model in JavaScript for web pages differs from the event model for JavaScript as it is used in other environments. Ex. Node.js event model relies on ```listeners``` to listen for events and ```emitters``` to emit events periodically — it doesn't sound that different, but the code is quite different, making use of functions like ```on()``` to register an event listener, and ```once()``` to register an event listener that unregisters after it has run once. ### Bubbling and capturing The standard DOM Events describes 3 phases of event propagation: 1. Capturing phase – the event goes down to the element. 2. Target phase – the event reached the target element. 3. Bubbling phase – the event bubbles up from the element. ![](https://i.imgur.com/YKP9oTV.png) #### Bubbling When click on the ```<p>``` element, it'll trigger from ```p``` to ```div```to ```form``` ``` <form onclick="alert('form')">FORM <div onclick="alert('div')">DIV <p onclick="alert('p')">P</p> </div> </form> ``` ![](https://i.imgur.com/wfyManp.png) > Almost all events bubble. > For instance, a focus event does not bubble. There are other examples too, we’ll meet them. But still it’s an exception, rather than a rule, most events do bubble. #### Capturing For a click on ```<td>``` the event first goes through the ancestors chain down to the element (capturing phase), then it reaches the target and triggers there (target phase), and then it goes up (bubbling phase), calling handlers on its way. > Capturing phase is rarely used. Normally it is invisible to us. #### Each handler can access event object properties: **event.target**: the deepest element that originated the event, doesn’t change through the bubbling process. **event.currentTarget (=this)**: the current element that handles the event (the one that has the handler on it) **event.eventPhase**: the current phase (capturing=1, target=2, bubbling=3). #### Practice Question Suppose we have a page with a button inside a div. We then execute the following Javascript. What will the console read after the button is clicked? ``` $('div').on('click', function() { console.log('div clicked') }) $('button').on('click', function() { console.log('button clicked') }) ``` Answer: button clicked div clicked ### Web Extension **manifest_version, name, version**: mandatory and contain basic metadata for the extension **content_scripts**: which tells Firefox to load a script into Web pages whose URL matches a specific pattern ``` { "manifest_version": 2, "name": "Borderify", "version": "1.0", "description": "Adds a red border to all webpages matching mozilla.org.", "icons": { "48": "icons/border-48.png" }, "content_scripts": [ { "matches": ["*://*.mozilla.org/*"], "js": ["borderify.js"] } ] } ``` ### Map * Map sort ``` let freq = new Map() freq.set('a', 1) freq.set('b', 3) freq.set('c', 2) //sorted by value in descending order let sorted_freq = new Map([...freq].sort( (a,b) => b[1]-a[1] )) //sorted by key in descending order let sorted_freq = new Map([...freq].sort( (a,b) => b[0]-a[0] )) ``` ### String * repeat char syntax: ```str.repeat(times)``` Ex: ``` 'a'.repeat(3) //'aaa' ```