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) ..
    • browser env: window (root obj) => JS / DOM / BOM ..
    • BOM: navigator obj, location.href, model win fn: alert(), prompt(), confirm() ..
  • JS in HTML: <script>..</script> & <script src=..></script> ..
    • type="text/javascript" language="javascript" attr no need anymore ..
    • inline content ignored if src set ..
    • browser cache external script for re-use ..
  • 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 instance document ..)
  • type check: node.nodeName / elem.tagName ..

HTML Attr & JS Prop

  • HTML-attr: case-insensitive & value: str ..
    • HTML hidden attr — style="display:none ..
  • 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)

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 then innerHTML)
  • 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
    4
    elem.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
    • get doc scrolled-out part size: window.pageX/YOffset (num in px) ..
    • scroll doc: window.scrollBy/To(..) .. & elem.scrollToView(top=true): scroll page to make elem top / bottom of the win
    • enable/forbid scroll: style.overflow[X/Y]='scroll/hidden' (same as CSS overflow[-x/-y]) .. & ..
  • 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:
      • elem.getBoundingClientRect() return num (in “px”)
      • style.left/top .., style.width/height .. => str with unit
    • 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) vs window.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

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, ..) ..
    • work for custom event ..; allow mtp handlers (call it mtp times)
    • support obj.handleEvent(e) as handler ..
  • HTML attr on<event>="fn-body" .. || DOM prop elem.on<event> = fn .., e.g. onclick
    • built-in events .., 1 handler ..

Others

Prevent default actions

e.preventDefault() on handler || on<event> handler return false ..

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
      3
      draggble.hidden = true;
      let elemBelow = document.elementFromPoint(e.clientX, event.clientY);
      draggble.hidden = false;
  • Pointer Event: handling mouse, touch and pen events simultaneously, with a single piece of code ..

Scroll Event

Keyboard Event

keydown, keyup ..

  • e.code (physical key loc, e.g “KeyZ”, “ShiftLeft”) vs event.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 by elem.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 ..
    • see <img> node but size = 0
    • wait non-async script exe .., but not wait external-CSS (unless script require it) ..
    • handle by addEventListener() ..
  • 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 ..)

  • load/error events: external resrc (tag with src attr .., e.g. script, img, css) loaded successfully / err ..
  • iframe.onload: on loading finished ( successful || error) (history) ..
  • track other errors: window.onerror ..
  • CORS & script crossorigin attr