JavaScript & DOM
JS intro
- init to make webpages alive .., run on platforms with JS engine (in browser aka “JS VM”, e.g. “V8” in Chrome & Opera) ..
- JS in HTML:
<script>..</script>
&<script src=..></script>
.. - in-browser JS restrictions …
DOM tree
- repre HTML/XML doc structure .. (inc
<!DOCTYPE HTML>
..), built when pages loading .. (auto-correction ..) - rooted at
document
(repre the whole doc..) —document.documentElement/.head /.body
.. - interact DOM elem in console ..
DOM node class hierarchy ..
- Node: Element, Text, Comment, Document (e.g.
HTMLDocument
instancedocument
..) - type check:
node.nodeName
/elem.tagName
..
HTML Attr & JS Prop
- HTML-attr: case-insensitive & value: str ..
- HTML
hidden
attr —style="display:none
..
- HTML
- DOM prop: case-sensitive & value: any type ..
- access attr by elem methods ..
- prop-attr sync .. & prop-attr type diff ..
- customized attr ..: pass data to JS || “mark” HTML-elem for JS
- naming:
data-*
, access:dataset.xxx
(mtp-word camelCase)
- naming:
DOM modification
Node Creation: document.createElement(tag: str)
.., elem.cloneNode(..)
..
Node Selection ..
elem.querySelector*(css: str)
— css:'tag[attr]'
.. & ..- other query methods ..
- nav props (child, parent, sibling, read-only) ..
- table props ..
Node modification
Content
elem.innerHTML
..- innerHTML += xxx: replace instead addition (resrc reload, selection & input rmed)
- insert
<script>
by innerHTML: inserted but not executed - elem.outerHTML = innerHTML + elem itself ..
- write to elem.outerHTML: replace node in DOM but not change elem itself (var still ref to the old value) — query again
elem.textContent
: inner text without tags, insert as text (safer theninnerHTML
)Text/Comment.data
: text/cmt content of the node (similar to nodeValue prop) ..- task: Count descendants, Create a calendar, Sort the table
Style
css class style (prefer ..)
- read class style:
getComputedStyle(elem, ..).<camelCaseProp>
: str with unit (of resolved value), e.g. “20px” .. - set class:
elem.className
(whole replace) /elem.classList
(single class) ..
style-attr style: elem.style.<camelCaseProp>
: str with unit, e.g. “100px”, writable ..
- rm style :
elem.style.xxx = ''
- full rewrite
elem.style.cssText = xxx
||setAttribute('style', cssText)
..
Size, coords & scroll
geometry props: return num (in “px”) ..
- Size props:
offset*
,client*
… - scrolled props:
scroll*
…, …1
2
3
4elem.style.height = `${elem.scrollHeight}px`; // expand elem to full height
elem.scrollTop = elem.scrollHeight; // auto-scroll up [Events mouseover/mouseout, relatedTarget]
elem.scrollTop = 0 / Infinity // scroll to top/bottom - coords props ..:
clientX/Y
(rel to win, css position: fixed) &pageX/Y
(rel to doc, css position: absolute) .., ..document.elementFromPoint(clientX, clientY)
: most nested elem, null if out of win ..
- get coords:
- tasks: Find win coords of the field, Position the note inside (absolute)
Notes
- text overflow — padding-bottom area may filled with text ..
- for elem width/height/distance, use geometry prop (e.g. clientWidth) instead getComputedStyle() .., ..
- get win size:
document.documentElement.clientWidth/H
(without sbar) vswindow.innerWeight/H
(inc sbar) .. - get doc size (with scroll out part) ..
Node insert, move & rm
- insert (replace) as text:
node.append/prepend/before/after/replaceWith(..)
..- move nodes by inserting existing one (auto rm from old place) ..
- insert as HTML:
elem.insertAdjacentHTML(..)
.. - removal:
node.remove()
.. - the old insert/rm methods .. &
document.write(html: str)
..: call when onload to write html into page “right here and now” (call af load replace page content)
Event handling
Event & event obj
events list …
event happen -> browser create event-obj (puts details into it) & pass as arg to event handler ..
Event obj: e.type
(e.g. “click”) ..
Event Bubbling & event delegation pattern
- 3 Event phase (Capturing, Target, Bubbling —
e.eventPhase
..) - event delegation (handle event on container for mtp elems) ..
e.target
,e.currentTarget
..- stop bubbling …
- tasks: Hide messages with delegation, toogle tree menu, Sortable table, Tooltip behavior
script-gen event ..
- construct .. & .., dispatch ..
- diff user event & script-gen event:
e.isTrusted
.. - custom event &
detail
prop .., ..
Event Processing Queue: Asycnly & Syncly ..
Event handler: fn(e)
add/rm Event handler
elem.addEventListener(e-type, handler, ..)
..- HTML attr
on<event>="fn-body"
.. || DOM propelem.on<event> = fn
.., e.g. onclick
Others
this
in handler: e.currentTarget .. & ..elem.setAttribute('on<event>', handler)
not work for event handler ..- Tasks: Move the ball across the field, Create a sliding menu, Add a closing button, Carousel
Prevent default actions
e.preventDefault()
on handler || on<event>
handler return false ..
e.defaultPrevented
(status check): true (means the event is handled somewhere) .. &elem.dispatchEvent(event)
return false ..passive: true
option ofaddEventListener
: signals that the handler not to call preventDefault() why needed?- default browser action list ..
- Tasks: Why “return false” doesn’t work?, Image gallery
Mouse Event
- events list …
- mouse coords:
e.clientX/Y, e.pageX/Y
.., mouse btn:e.button
(=0 left-btn, =1 middle, =2 right-btn) .. - mouse event also inc info of modifier keys:
e.shiftKey/altKey/ctrlKey/metaKey
(Mac): bool (true if pressed) .. - disable selection (on dblclick) & copy:
onmousedown/oncopy return false
..
Mouse & Pointer Event
mousemove
.., mouseover/out
event & e.relatedTarget
(diff with mouseenter/leave
) ..
- event delegation example ..
- task: “Smart” tooltip (tooltip style)
- impl by mouse events: overall algorithm .., pointer correct positioning .., drappable elem hightlight ..
- draggable elem always above other elem when dragging & mouse event only happen on the top elem, so eh on other elem not work, can fix by
1
2
3draggble.hidden = true;
let elemBelow = document.elementFromPoint(e.clientX, event.clientY);
draggble.hidden = false;- task: Slider, Drag superheroes around the field (not checked yet)
- draggable elem always above other elem when dragging & mouse event only happen on the top elem, so eh on other elem not work, can fix by
- Pointer Event: handling mouse, touch and pen events simultaneously, with a single piece of code ..
Scroll Event
scroll
event on elem & win ..- task: Endless page, Up/down button, Load visible images
Keyboard Event
keydown
, keyup
..
-
e.code
(physical key loc, e.g “KeyZ”, “ShiftLeft”) vsevent.key
(meaning of key, ie. char inputted, e.g. “z” || “Z”) .. - key repeat: key pressed for a long enough time ..
- task: Extended hotkeys
Form Ctrl
- named collection:
document.forms
&form/fieldset.elements
(fieldset as subform) .. - back-ref:
elem.form
.. - Form elements: input/textarea, select and option ..
Focusing Event
focus
/ blur
event .. & elem.focus/blur()
..
- event not bubble (but capturable) — bubble version
focusin
/focusout
event (handler assign byelem.addEventListener
)
Others
- get current focused elem:
document.activeElement
.. — css:focus
.. autofocus
attr ..- enable any elem focusable:
tabindex
attr ||elem.tabindex
.. - input validate attr:
required
,pattern
…
task: Editable div, Edit TD on click, Keyboard-driven mouse
Data update events
change
event: on finish change, e.g. text-input elem blur, select-opt changes ..input
event: on any value change ..cut/copy/paste
event …
Form submit event
submit
event on form (sent data to server):
- trigger on press “Enter” on input field => trigger click on input[type=submit] ..
- submit form manually:
form.submit()
: (submit
event not generated) - tasks: Modal form
Doc & resrc loading
Page load events
document.DOMContentLoaded
: HTML & DOM tree ready, form autofill ..window.load
: external resrc (css, img) loaded (img size known) ..window.beforeunload/unload
: user leaving this page: nav to other pages/close win ..window.onbeforeunload
return false / non-empty str: cancel the event (prevent default?) & show the str as msg e.g. “change not save, sure to leave?” — answer negative block page-nav? ..
Others
document.readState
: “loading”, “interactive” , “complete” — the old document.readystatechange ..- Whole process …
External script attr: async, defer
Both only for external script (ignored if no src
attr) .., .. and load not-block (load script in bg)
async
: run in load-1st order ..- Dynamic scripts (gen by JS) load af insert to the doc ..
defer
: run (in doc order) when DOM ready (but bf DOMContentLoaded event) ..
Resrc loading event
Most resrcs start loading when added to the doc, except <img>
(load when gets src & cached ..)