HTML Accessibility Tag
To improve accessiblity, we are encouraged to use semantic tag of HTML5
Why to use it?
Common semantic tags
- Layout:
headerfooternavmainsectionarticleaside<header role="banner"><section role="search">
- Form:
labelinputbutton<label for="search"><input type="text" ><input type="submit" />
- Table:
<caption><table summury="caption">th - Image:
<img alt="img.png" title="This is a beautiful girl" >aria-labelledby- empty
alt: necessary if the image is only for decoration use
- text:
<em>vs<i><strong>vs<b><abbr title="Hypertext Markup Language"> HTML <abbr>
- position:
absolution positionis better thandisplay: noneorvisibility: hidden: to overlap all div with differentz-index- since
display: noneorvisibility: hiddenwill hide content from screenreader
- Layout:
How to improve accessibility?
use
:focus&:hoverpseudo-class to highlight the chosen tag1
2
3
4a:hover, input:hover, button:hover, select:hover,
a:focus, input:focus, button:focus, select:focus {
font-weight: bold;
}
JavaScript in accessibility
- provide client-side form validating, rather than server-side
<video>has control button for keyboardmouseover==onfocus&mouseout==onblur
mobile accessibility
touch:
onmousedown==ontouchstart&&onmouseup==ontouchstopside menu
@medialogical operator:
and,not,only,,(like 'or')1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30<!-- 1. media in <link> -->
<link href="mobile.css" rel="stylesheet" media="screen and (max-width: 600px)">
<!-- 2. media in <style> -->
<style media="all and (max-width: 500px)">
p {
color: blue;
background-color: yellow;
}
</style>
<!-- 3. media in <script> -->
<script>
if (window.matchMedia("(min-width: 400px)").matches) {
// the viewport is at least 400 pixels wide
} else {
// the viewport is less than 400 pixels wide
}
</script>
<!-- 4. media inside style -->
<style>
@media screen and (min-width: 30em) and (max-width: 992px) {
body { background-color: blue; }
}
@media (min-height: 680px), screen and (orientation: portrait){
body { background-color: blue; }
}
</style>
@importsyntax:
1
2@import 'custom.css';
@import url('landscape.css') screen and (orientation:landscape);
Why use React?
Credit to: https://reactjs.org/blog/2013/06/05/why-react.html
- React is not MVC, is only “V”
- Support small, reusable component
- efficient DOM update, using diff algorithm
reconcilation process: the way React used to update real DOM, by only updating changed components node and its children- Every time
propsorstatechange leading torender()execution, which will produce either aStringorvirtual DOM node; - Either way, React will compare it with previous
Stringorvirtual DOM node, to determine which node in real DOM need to be updated diff/reconcilationprocess only happens afterrender(), it will compare current tree with previous tree
keyin a list of nodes: makediffefficiently- there are cases that a node is added in front to a list, without
key, React just compare each pair of nodes from previous tree and current tree, and re-render all the nodes in real DOM in that list; Even thought, it only needs to insert a new node to real DOM tree - Attaching a
keyto each node in a list, will help React know which node need to be re-render in real DOM tree. - Nodes with the same
keyinside a list, will be stable across different re-renders
- there are cases that a node is added in front to a list, without
React Lifecyle
Mounting phase
constructor()getDerivedStateFromProps()render()componentDidMount()
Updating phase
getDerivedStateFromProps()shouldComponentUpdate()render(): after either newpropsor newstatecomponentDidUpdate()
Unmounting phase
componentWillUnmount()
Other API:
setState()&forceUpdate()setState(): can take both object and callback function as parametersetState( (prevState, props) => updatedState )1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// BAD: updated state will only take one increment
// i.e. in the end, counter=1
componentDidMount(){
this.setState({counter: this.state.counter+1})
this.setState({counter: this.state.counter+1})
this.setState({counter: this.state.counter+1})
})
// GOOD: updated state will take all increment
// i.e. in the end, counter=3
componentDidMount(){
this.setState( counter=>{counter: state.counter + 1} )
this.setState( counter=>{counter: state.counter + 1} )
this.setState( counter=>{counter: state.counter + 1} )
})
How to implement infinite scroll loading
Credit to: https://segmentfault.com/a/1190000004974824
Which event do we use?
- We assume the user will scroll down the screen, in order to load more content
- So we use the
scrollevent onwindoworblock elementwith a height set already
Three conditions for AJAX cal
container bottom - window bottom < certain value,i.e. the container don’t have too much content to show- not in the middle of loading
- still have content to load, i.e. not the end of all the content
code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23var isLoading = false;
var isEnd = false;
var triggerDistance = 200;
function fetchData() {
var distance = container.getBoundingClientRect().bottom - window.innerHeight;
if ( !isLoading && !isEnd && distance < triggerDistance ) {
isLoading = true;
fetch(path).then(res => {
isLoading = false;
// if not end, will short-circut latter statement
// if reach end, will still check the latter one, which will set isEnd to true
res.data.length === 0 && isEnd = true;
doSomething(res.data);
});
}
}
window.addEventListener('scroll', fetchData);
The rendering order: CSS, JS, HTML
- credit to:
- General order
- JS in
<head>will block downloading of following resource - Browser downloads and parses HTML to DOM
- when encounter
<script>,- if not external, render engine hand control power to js engine
- if is external, render engine keep rendering, while downloads external
- JS in
CSS: profile & edit image link
Implement the requirement
consider accessibility
1 | // 1. Mouse is not over the picture |
Flex Layout
flex container:
NOTE:
floatclearvertical-alignfor the items inside flex boxwill become invaliddisplay: inline-flexvsdisplay: flex:- only apply to flex container, to make it display as
inlineorblock - won’t affect flex items inside
- only apply to flex container, to make it display as
flex-directionflex-wrap: break new line or not when exceeding it containerflex-flowis combinatin of first 2 items:1
2
3
4flex-direction: row;
flex-wrap: wrap;
<==>
flex-flow: row wrap;
align-items: center;: where flex items sit on the cross axisjustify-content: space-around;: where the flex items sit on the main axis
flex items:
flex: 1 1 20px: three attributes:flex-growflex-shrinkflex-basisorder: 3: like the smaller will be put in frontalign-self: override its container’salign-itemslayout, update position of itself
Grid Layout
Grid Container
- display:
display: gridvsdisplay: inline-grid: only apply on grid container - gap:
grid-row-gapgrid-column-gapgrid-gap: set the gap between items - col num/width:
grid-template-columns: define num of columns and their width - row num/width:
grid-template-rows: define num of rows and their width - horizontally align:
justify-content: center, start, end, space-evenly, space-around, space-between - vertically align:
align-content: center, start, end, space-evenly, space-around, space-between
- display:
Grid Items
line:
grid-row-startgrid-column-end: specify the start & end of span it coversline shorthand 1 :
grid-rowgrid-columngrid-row:1 / 3:range: [line1 line3]grid-column: 1/span 3: from line1, take 3 units,range: [line1 line4]
line shorthand 2 :
grid-area=grid-row-start+grid-column-start+grid-row-end+grid-column-endgrid-area: 1 / 2 / 5 / 6: start on row-line 1 and column-line 2, and end on row-line 5 and column line 6:grid-area: 2 / 1 / span 2 / span 3:NOTE: can assign names to grid items, cooperate with
grid-template-areas. Used to assign space to the named item1
2
3
4
5
6
7
8
9
10
11
12
13
14https://www.w3schools.com/css/tryit.asp?filename=trycss_grid_grid-area_named1
.item1 { grid-area: header; }
.item2 { grid-area: menu; }
.item3 { grid-area: main; }
.item4 { grid-area: right; }
.item5 { grid-area: footer; }
.grid-container {
grid-template-areas:
'header header header header header header'
'menu main main main right right'
'menu footer footer footer footer footer';
}order: specified by
starting line#andending line#1
2
3
4
5
6.item1 { grid-area: 1 / 3 / 2 / 4; }
.item2 { grid-area: 2 / 3 / 3 / 4; }
.item3 { grid-area: 1 / 1 / 2 / 2; }
.item4 { grid-area: 1 / 2 / 2 / 3; }
.item5 { grid-area: 2 / 1 / 3 / 2; }
.item6 { grid-area: 2 / 2 / 3 / 3; }
CSS:
float&position&box modelfloat- when container box has no height, and need to cover all it floating children:
clear: both&overflow: hidden
- when container box has no height, and need to cover all it floating children:
box-sizing=>content-box/border-boxbox-sizing: content-box;actual width=width+padding+border
Thewidthandheightproperties include the content, but does not include the padding, border, or margin.box-sizing: border-box;actual width =width=content+padding+border
Thewidthandheightproperties include the content, padding, and border, but do not include the margin
cursor: pointercursor acts like<a>when hoverpxvsptvsremvsem
https://kyleschaeffer.com/development/css-font-size-em-vs-px-vs-pt-vs/pt: physical measurement, fixed when media once producedpx: calculated relative topt; can be adjustedrem: related to root font-size (default: 16px)em: related to its parents font-size (default: 16px)
resize: indicate how this block element can be resized- horizontal: can only resized horizontally
- vertical: can only resized vertically
- both: can be resized on both directions
- none: none resizable
- initial: == none resizable
width&heightmake the aspect-ratio stay the same: adjust one, set other one
autotweak image while keep aspect-ratio the same
some time will overflow: can add
overflow: hiddento its parent1
2
3
4
5
6
7
8div{
width: 100px;
height: 100px;
}
.img{
width: 100%;
height: auto;
}
white-space:nowrap,pre,normal- how to handle text’s space inside a block to be displayed
nowrap: ignore all white-space in one line, like in<span>normal: make text content displayed against the block, change line based on spacepre: take in all kind of space (include new line) displayed as they specified in html tag
overflow: deal with inner box exceeding outer box:hiddenorscrolltext-overflow:deal with too many words inside box, clip or ellipsisclip(default)ellipsis(省略号)
word-break:deal with long word, which may exceeds width of its containernormalbreak-word;: the best clipping way to show the word
max-widthvswidthwidth: set the tentative value`max-widthset the rule, to restrict the value ofwidthsome time can change the aspect-ratio
1
2
3
4.image{
width: 100%;
height: 100%;
}
CSS: block vs inline vs inline-block
credit to: http://dustwell.com/div-span-inline-block.html
<div>- A “block-level element”
- can contain all other elements!
- can only be inside other block-level elements
- defines a rectangular region on the page
- tries to be as wide as possible
- begins on a “new line”, and has an “carriage return” at the end, like a
<p>
<span>- An “inline element”
- cannot contain block-level elements!!
- can be inside any other element
- tries to be as narrow as possible
- defines a “snake” on the page
- doesn’t create any new lines.
blockvsinlinevsinline-blockblock:- has width, height, margin, padding
- force a new line after the block
inline:- no width, no height; only respect left/right margin, left/right padding
- allow other elements to sit on the same line
inline-block:- has width, height, margin, padding
- allow other elements to sit in a line, that’s why called
inline
CSS: how to center an element?
- https://css-tricks.com/centering-css-complete-guide/
- Horizontally
- center inline element inside block element:
text-align: center
- center block element inside another block element:
- outer block with specified width:
margin: 0 auto - outer block with no width: inner width will spread its width to outer, so no need for
margin: 0 auto
- outer block with specified width:
- center multiple block element in a row inside another block element:
display: inline-blockdisplay: flex
- center multiple block element in different rows inside another block element:
margin: 0 auto
- center inline element inside block element:
- Vertically for inline elements
- center single inline element inside block element:
height==line-heightpadding-top == padding-bottom
- center multiple inline elements inside block element:
display: table&display: table-cell+vertial-align: middle:display: flex&align-items: center- ghost element:
- full-height pseudo element is placed inside the container and the text is vertically aligned with that (both are
inline-block) - trick: contain multiple lines into a
inline-blockto be a whole inline element - adjacent with another
inline-blockwithheight=100% inline-blockelements will align on baseline, ifvertical-aligndoesn’t specify any other value- if
vertical-alignspecifymiddle: browser will try to align all inline boxes in middle, rather than baseline - NOTE:
vertical-alignspecify how will itself to be aligned vertically
- full-height pseudo element is placed inside the container and the text is vertically aligned with that (both are
- center single inline element inside block element:
- Vertically for block elements
- if
heightof inner block is known: useposition: abosulute&top&margin:0.5*height - if
heightof inner block is not known: useposition: abosulutetop&transform: translateY(-50%) - Again:
display: flex
- if
- Both Horizontally & Vertically
- if
heightof inner block is known: useposition: abosulute&top&margin:0.5*height - if
heightof inner block is not known: useposition: abosulutetop&transform: translateY(-50%) - Again:
display: flex display: grid
- if
DOM structure
difference between
HTMLCollection&NodeListHTMLCollection: a collection of element nodesNodeList: a collection of all types of nodes: element node/ text node/ comment node- convert them to array, to extract info:
Array.prototype.slice.call(NodeList)
everything in an HTML document is a node:
- The entire document is a document node
- Every HTML element is an element node
- The text inside HTML elements are text nodes
- All comments are comment nodes
navigate across the DOM tree using attibutes: [element node, text node, comment node]
- parentNode
- childNodes [nodenumber]
- firstChild
- lastChild
- nextSibling
- previousSibling
A common error in DOM processing is to expect an element node to contain text.
<title id="demo">DOM Tutorial</title>The element node
<title>(in the example above) does not contain text.It contains a text node with the value “DOM Tutorial”.
The value of the text node can be accessed by the node’s innerHTML property:
1
2
3
4
5
6
7var myTitle = document.getElementById("demo").innerHTML;
// or
var myTitle = document.getElementById("demo").firstChild.nodeValue;
// or
var myTitle = document.getElementById("demo").childNodes[0].nodeValue;
DOM API:
get style & set style of an element
set style
- directly use it as attribute
elements.style.fontSize = '10px' - NOTE: the style name must be camelCase
- directly use it as attribute
get style:
if style is set using
styleorjs, directly get the styleif style is set using
csswithoutelement.stylekeyword, we will usegetComputedStyle()document.defaultView.getComputedStyle(ele,null).getPropertyValue("font-size")1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<html lang="en">
<head>
<script>
function cStyles() {
var RefDiv = document.getElementById("d1");
var txtHeight = document.getElementById("t1");
var h_style = document.defaultView.getComputedStyle(RefDiv, null).getPropertyValue("height");
txtHeight.value = h_style;
}
</script>
<style>
#d1 {
margin-left: 10px;
background-color: rgb(173, 216, 230);
height: 20px;
max-width: 20px;
}
</style>
</head>
<body>
<div id="d1"> </div>
<form action="">
<p>
<button type="button" onclick="cStyles();">getComputedStyle</button>
height<input id="t1" type="text" value="1" />
</p>
</form>
</body>
</html>
console.trace()can be used to trace the call stack of a certain functionaddEventListener&removeEventListener1
2
3
4
5// Attach an event handler to the document
document.addEventListener("mousemove", myFunction);
// Remove the event handler from the document
document.removeEventListener("mousemove", myFunction);
createAttribute()&setAttributeNode()1
2
3
4
5
6function myFunction() {
var h1 = document.getElementsByTagName("H1")[0];
var att = document.createAttribute("class");
att.value = "democlass";
h1.setAttributeNode(att);
}
createElement()&intersetBefore()&appendChild()1
2
3
4var btn = document.createElement("BUTTON"); // Create a <button> element
var t = document.createTextNode("CLICK ME"); // Create a text node
btn.appendChild(t); // Append the text to <button>
document.body.appendChild(btn); // Append <button> to <body>
querySelector&querySelectorAll()querySelector()returns the first element that matches a specified CSS selector(s)1
2
3
4
5
6
7
8
9
10// 1. select first p element whose parent is a div
function myFunction() {
var x = document.querySelector("div > p");
x.style.backgroundColor = "red";
}
// 2. select all a element has target attribute
function myFunction() {
document.querySelector("a[target]").style.border = "10px solid red";
}
querySelectorAll()returns all elements in the document that matches a specified CSS selector(s), as a static NodeList object.1
2
3
4
5
6
7function myFunction() {
var x = document.querySelectorAll("a[target]");
var i;
for (i = 0; i < x.length; i++) {
x[i].style.border = "10px solid red";
}
}
element.childNodesvselement.childrenelement.childNodes: returns aNodeList object, including element nodes, text nodes, and comment nodeselement.children: return aHTMLCollection object- difference:
- childNodes: contain all nodes, including text nodes and comment nodes
- children: only contain element nodes.
element.firstChildvselement.firstElementChild- difference:
- firstChild returns the first child node as an element node, a text node or a comment node (depending on which one’s first),
- firstElementChild returns the first child node as an element node (ignores text and comment nodes).
- difference:
element.parentNodevselement.parentElementparentElement: returns null if the parent node is not an element node
parentNode: is probably the most popular
1
2
3
4
5document.body.parentNode; // Returns the <html> element
document.body.parentElement; // Returns the <html> element
document.documentElement.parentNode; // Returns the Document node
document.documentElement.parentElement; // Returns null (<html> does not have a parent ELEMENT node)
element.previousSiblingvselement.previousElementSibling- previousSibling: returns the previous sibling node as an element node, a text node or a comment node
- previousElementSibling: returns the previous sibling node as an element node (ignores text and comment nodes).
DOM events
[Trick]: bind data on element as
attribute, then usee.target.getAttribute("data-info")common types:
onloadoninputonchangeonfocusonmouseover&onmouseoutonclick&onmousedown&onmouseuponkeypress&onkeydown&onkeyuponresizeonscroll
event propagation: bubbling & capturing
- Event propagation is a way of defining the element order when an event occurs.
- bubbling: the inner most element’s event is handled first and then the outer: the
<p>element’s click event is handled first, then the<div>element’s click event. - capturing: the outer most element’s event is handled first and then the inner: the
<div>element’s click event will be handled first, then the<p>element’s click event.
Array-like object under the hood
- All credit to: http://2ality.com/2013/05/quirk-array-like-objects.html
- An array-like object
- only has:
indexto access to elements:a[0]- the property
lengththat tells us how many elements the object has:a.length
- does not have: array methods such as
push,forEachandindexOf; have to borrow these methods - NOTE:
NodeListhas theforEachattributeHTMLCollectiondoesn’t haveforEachattribute
- “borrow” : that why we use:
[].slice(array-like)[].indexOf(array-like)[].forEach(array-like)
- only has:
- Two examples of array-like objects
- result of the DOM method
document.getElementsByClassName()(many DOM methods return array-like objects) - the special variable
arguments.- You can determine the number of arguments via
arguments.length - you can access a single argument, e.g. read the first argument:
arguments[0]
- You can determine the number of arguments via
- result of the DOM method
Array methods, however, have to be borrowed. You can do that, because most of those methods are generic
Three ways to convert Array-like objects to Array.
Array.prototype.slice.call(arguments)`
Array.from(arguments)use
bindto create a new functionslice()function on array-like object, so we can reuse it1
2
3
4
5
6let = getIndexOfA = function(){
let myIndexOf = [].indexOf.bind(arguments);
return myIndexOf("a") // NOTE: mustn't use arguments.myIndexOf()
}
console.log( getIndexOfA("d", "d", "a","d") ) // 2
What can be put inside <head>?
https://github.com/xiaoyu2er/HEAD
JS coding: mutate array according new indices
1 | Given an input array and another array that describes a new index for each element, mutate the input array so that each element ends up in their new index. |
<script async> & <script defer>
- normal
<script src="script.js" >- The HTML parsing is paused for the script to be both fetched and executed
<script async>- The HTML parsing is not paused for the script to be fetched,
- but still be paused for js to be executed
<script defer>- The HTML parsing is not paused for the script to be fetched,
- oppositely, the execution of js is paused util the HTML finish parsing
- same as
<script>right before the</body>tag
How to check data types in JS
https://webbjocke.com/javascript-check-data-types/
write a promise
Promise
1 | <!DOCTYPE html> |
AJAX
XMLHttpRequestis browser built-in object, used to pull data in backgroundMethods:
open(method, url, async, user, psw): specify the request- method: the request type GET or POST
- url: the file location
- async: true (asynchronous) or false (synchronous)
- user: optional user name
- psw: optional password
setRequestHeader(): Adds a label/value pair to the header to be sentsend(str): Sends the request to the server (GETorPOST)- if no
strprovided, send asGET - if
stris provided, send as the parameters forPOST
- if no
properties:
onreadystatechange: function used to be called when state changereadyState: Holds the status of the XMLHttpRequest.- 0: request not initialized
- 1: server connection established
- 2: request received
- 3: processing request
- 4: request finished and response is ready
status: Returns the status-number of a request- 200: “OK”
- 403: “Forbidden”
- 404: “Not Found”
responseText: Returns the response data as a stringresponseXML: Returns the response data as XML data
steps
- An event occurs in a web page (the page is loaded, a button is clicked)
- An XMLHttpRequest object is created by JavaScript
- The XMLHttpRequest object sends a request to a web server
- The server processes the request
- The server sends a response back to the web page
- The response is read by JavaScript
- Proper action (like page update) is performed by JavaScript
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24/* --------------- 1. GET --------------- */
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demo").innerHTML = this.responseText;
}
};
xhttp.open("GET", "demo_get.asp", true);
xhttp.send();
}
/* --------------- 2. POST --------------- */
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState === 4 && this.status === 200) {
document.getElementById("demo").innerHTML = this.responseText;
}
};
xhttp.open("POST", "demo_post2.asp", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send("fname=Henry&lname=Ford");
}
Check if undeclared, undefined or null
1 | // 1. `undeclared` check |