js: BOM, DOM

Lakukan tugas rumah & ujian kamu dengan baik sekarang menggunakan Quizwiz!

<html> <body> <div> hi </div> </body> </html> console.log(document.nodeName) console.log(document.tagName) console.log(document.body.nodeName) console.log(document.body.tagName) console.log(document.body.children[1].nodeName) console.log(document.body.children[1].tagName)

"#document" undefined "BODY" "BODY" "DIV" "DIV" - tagName only on Element nodes - nodeName on every node

<body> <a id="a" href="#hello">link</a> </body> for (let e of document.querySelectorAll('a[href]')) { console.log(e.getAttribute('href')) }

"#hello" - how to retrieve value of attr

console.log(location.href)

"https://cdpn.io/boomboom/v2/index.html" - part of BOM - current URL

4 main node types

- 12, but 4 are used most often 1. document - entry point into DOM 2. element nodes - HTML tags, the tree building blocks 3. text nodes 4. comments

BOM

- Browser Object Model - additional objects for things other than doc - navigator object for info on browser - location object for current URL - setTimeout, alert, prompt, etc

DOM

- Document Object Model - main entry point is 'document' object (e.g. document.head, document.body) - represents all page content as objects that can be modified - standard at: https://dom.spec.whatwg.org

travel element nodes

- HTML tag nodes, excluding comments and text - with 'Element' in prop name - props: parentElement, children, previousElementSibling, nextElementSibling, firstElementChild, lastElementChild

<div id="foobar">foobar</div> <ul id="peeps"> <li>John</li> <li>Pete <ul> <li>Ed</li> <li>Cris</li> </ul> </li> </ul> const peeps2 = peeps.cloneNode(true) foobar.prepend(peeps2)

- deep clone a node and insert - cloneNode(false) is shallow clone

4 primary DOM node classes

- define node functionality 1. EventTarget - abstract root class 2. Node - abstract base for parentNode, nextSibling, ChildNode, etc 3. Element - base class for DOM elements for nextElementSibling, children, etc 4. HTMLElement - base class for HTML elements

let date = new Date(Date.now() - 1); date = date.toUTCString(); document.cookie = "user=fred; expires=" + date; console.log(document.cookie);

- deletes cookie user - needs to specify user=fred

methods to work with attributes

- elem.hasAttribute(name) - to check for existence - elem.getAttribute(name) - to get the value - elem.setAttribute(name, value) - to set the value - elem.removeAttribute(name) - to remove the attribute - elem.attributes is a collection of all attributes

Math.max( document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight, document.body.clientHeight, document.documentElement.clientHeight )

- for historical reasons, this is the best way to get the height of a document - same for Width - includes any scroll bars

<html> <body> <div id="foobar">hi</div> </body> </html> foobar.hidden = true

- hides the element - same as style="display:none"

getElementsBy*

- legacy query methods - e.g. elem.getElementsByClassName(class) - use querySelector() instead

when script runs, document.body

- might be null - hasn't been loaded yet - happens if script in <head>

methods for node insertion and removal

- node.append(...nodes or strings) - insert into node, at the end, - node.prepend(...nodes or strings) - insert into node, at the beginning, - node.before(...nodes or strings) - insert right before node, - node.after(...nodes or strings) - insert right after node, - node.replaceWith(...nodes or strings) - replace node.

const div = document.createElement("div"); div.className = "alert"; div.innerHTML = "yo mama"; foobar.append(div); setTimeout(() => div.remove(), 2000)

- remove element after 2 sec - could also just set innerHTML

.blue { background-color: blue } foobar.className = "blue"

- set background by using CSS class - must use 'className', not just 'class' - overwrites all classes; instead, use classList.add()

coordinate system: relative to document

- similar to position:absolute - calculated from document top/left edge

coordinate system: relative to window

- similar to position:fixed - calculated from window top/left edge

innerHTML and scripts

- they don't execute

topmost tree nodes

<html> = document.documentElement <body> = document.body <head> = document.head - all available as doc props

<html> <body> <ul> <li id="john">John</li> <li>Pete</li> </ul> </body> </html> console.log(document.querySelector('ul > li:last-child'))

<li>Pete</li> - use innerHTML to get to just Pete - retrieves first item found, not list

Element.prototype.bar = () => console.log('bar') document.body.bar() document.body.children[0].bar()

bar bar - add props to prototype

<body foo="bar"> ... </body> console.log(document.body.getAttribute('foo')) document.body.foo = "hey" console.log(document.body.getAttribute('foo')) console.log(document.body.foo)

bar bar hey - when HTML parsed, non-standard props are stored in special area - use getAtttribute() and setAttribute()

<html> <body> <div>hi</div></body><ul> <li>John</li> <li>Pete</li> </ul> </html> how to get to 'hi' by object reference

document.body.children[0]

<html> <body> <div>hi</div> <ul> <li id="john">John</li> <li>Pete</li> </ul> </body> </html> how to get to 'Pete' by object reference

document.body.children[1].children[1]

how to delete cookies

document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"; - overwrite with expiry date in past

document.foo = () => console.log('foo') document.foo()

foo - add props to document obj

<html> <body> <div id="foobar"> hi </div> </body> </html> console.log(foobar.textContent) foobar.textContent = "bye" console.log(foobar.textContent)

hi bye - gets item by referencing id - and prints only text minus tags - safer way to change text

<body data-foo="yoyo"> ... </body> console.log(document.body.dataset.foo)

yoyo - prefix attr with data- to put into dataset - special attrs

<html> <body> <ul> <li id="john">John</li> <li id="pete">Pete</li> </ul> </body> </html> console.log(document.querySelector('ul > li:last-child').matches('li[id="pete"]') )

true - tests if matches CSS selector

elem.children[0] === elem.firstElementChild

true - firstChild is fast access to first element in childNodes array

elem.children[elem.children.length - 1] === elem.lastElementChild

true - lastChild is fast access to last element in childNodes array

console.log(document instanceof HTMLDocument); console.log(Object.getPrototypeOf(HTMLDocument)); console.log(Object.getPrototypeOf(Document)); console.log(Object.getPrototypeOf(Node));

true function Document() { [native code] } function Node() { [native code] } function EventTarget() { [native code]

<html> <body> <ul> <li id="john">John</li> <li>Pete</li> </ul> </body> </html> const list = document.querySelectorAll('ul > li:last-child') for (let elem of list) { console.log(elem.innerHTML) }

Pete - return all elements matching CSS selector

<body> <div data-widget-name="mama">yo</div> </body> let e = document.querySelector('[data-widget-name]') console.log(e, e.dataset.widgetName)

"<div data-widget-name='mama'>yo</div>" "mama" - note how attr name is in '[]' because not tag name - value is in the element's dataset prop because prefixed with data- - and it is camel cased

console.log(navigator.userAgent)

"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36" - part of BOM - info on browser

<html> <body> <a id="a" href="#hello">link</a> </body> </html> console.log(a.href) console.log(a.getAttribute('href'))

"https://cdpn.io/boomboom/v2/index.html?editors=1111&key=iFrameKey-3148f8c5-b81b-7391-70a8-db8f2e298acf#hello" "#hello" - standard props are available directly, but may be modified - full URL for anchor tag - use getAttribute to get unmodified value

let date = new Date(Date.now() + 86400e3); date = date.toUTCString(); document.cookie = "user=fred; expires=" + date; console.log(document.cookie);

"name=ed; user=fred" - expire in a day

DOM node class: EventTarget > Node

- abstract, never created - base for DOM nodes for tree access - parentNode, nextSibling, childNodes, etc - derivatives: Text, Element and Comment

DOM node class: EventTarget

- abstract, never created - base for all DOM nodes for event handling - parent is Object

.blue { background-color: blue } .dotted { outline-style: dotted } foobar.classList.add('blue') foobar.classList.add('dotted')

- add classes to list - also, remove(), toggle(), contains()

document.write('<h3>foo</h3>') document.writeln('<h3>foo</h3>')

- add to end of document - also, with newline - old school - don't use! - replaces all HTML and has perf issues - instead, get an element and set innerHTML

travel DOM nodes

- all nodes, including comments and text - props: parentNode, childNodes, previousSibling, nextSibling, firstChild, lastChild

console.log(document.body instanceof HTMLBodyElement); console.log(document.body instanceof HTMLElement); console.log(document.body instanceof Element); console.log(document.body instanceof Node); console.log(document.body instanceof EventTarget); console.log(document.body instanceof Object);

- all true

in DOM, every HTML tag is

- an object - nested tags are children

<div id="blah">foobar</div> blah.after('beforebegin', 'blah')

- anything with 'id' can be referenced by that value - unless there's another, then not defined

HTML comments

- are part of the DOM - everything in HTML are part of DOM - browser will fix up elements (e.g. add closing tags if needed, add TBODY to table)

elem.children

- array (like) structure of children - use for..of to iterate (NOT for..in) - ONLY contains elements, no blank nodes or comments - immutable (use other methods to mutate)

elem.childNodes

- array (like) structure of children - use for..of to iterate (NOT for..in) - includes blank nodes, comments - immutable (use other methods to mutate)

DOM node class: EventTarget > Node > Element

- base for DOM element tree access - nextElementSibling, children, getElementsByTagName, querySelector - derivatives: SVGElement, XMLElement, HTMLElement

DOM node class: EventTarget > Node > Element > HTMLElement

- base for HTML elements - derivatives: HTMLInputElement (for <input>), HTMLBodyElement (for <body>), HTMLAnchorElement (for <a>) ...

<button data-toggle-id="subscribe">Show form</button> <form id="subscribe" hidden> Email: <input type="email"></form> document.addEventListener('click', ev => { let id = event.target.dataset.toggleId if (!id) return let elem = document.getElementById(id) elem.hidden = !elem.hidden })

- behavior pattern - adds show/hide via data-toggle-id attr - via addEventListener on document via dataset prop

const div = document.createElement('div') div.innerHTML = 'yo mama' document.body.append(div)

- create and append new element

methods to create new nodes

- document.createElement(tag) - creates an element with the given tag, - document.createTextNode(value) - creates a text node (rarely used), - elem.cloneNode(deep) - clones the element, if deep==true then with all descendants.

<html> <body> <div>hi</div> <ul> <li id="john">John</li> <li>Pete</li> </ul> </body> </html> how to get to 'John' and set background

- document.querySelector('li[id=john]').style.background = "yellow" (preferred) - document.getElementById('john').style.background = 'red' - john.style.background = "red"

rarely used methods

- elem.insertAdjacentHTML(where, html) - elem.insertAdjacentText - elem.insertAdjacentElement

previousElementSibling, nextElementSibling

- move between siblings/peers - e.g. head, body are peers

if elem is arbitrary DOM node, is it true that elem.children[0].previousSibling is always null?

- no - previousSibling could be a text or comment node - elem.firstChild.previousSibling would always be null - if there are no children at all, this will error

elem.nodeType

- old school way to get node type 1 = element 3 = text 9 = document

"old school" methods

- parent.appendChild(node) - parent.insertBefore(node, nextSibling) - parent.removeChild(node) - parent.replaceChild(newElem, node)

element = document.querySelector(selectors) document.querySelector(".myclass") document.querySelector("div.user-panel.main input[name='login']")

- preferred way to get to HTMLElement - returns first element that matches if found, null otherwise - uses depth-first pre-order traversal starting with first element in document's markup

elementList = parentNode.querySelectorAll(selectors) document.querySelectorAll("p") document.querySelectorAll("div.note, div.alert") document.querySelectorAll('a[href]')

- preferred way to get to NodeList containing one Element object for each that matches

document.querySelectorAll(':hover')

- return list of elements that pointer is over, from outermost HTML to innermost

foobar.style.background = "yellow" foobar.style = "background: red; outline: dotted;" foobar.style.cssText = "background: red; outline: dotted;"

- set background by setting style - object of camelCased styles - prefer using classes

if elem is arbitrary DOM node, is it true that elem.lastChild.nextSibling is always null?

- yes - lastChild is always the last, so no nextSibling - if there are no children at all, this will error

window object roles

1. global object 2. represents browser window with methods to control it

6 main methods to search for nodes

1. querySelector (preferred) 2. querySelectorAll (preferred) 3. getElementById (legacy, prefer querySelector) 4. getElementsByName (legacy, prefer querySelectorAll) 5. getElementsByTagName (legacy, prefer querySelectorAll) 6. getElementsByClassName (legacy, prefer querySelectorAll)

<div id="elem1"></div> <div id="elem2"></div> <div id="elem3"></div> let text = "<b>text</b>"; elem1.append(document.createTextNode(text)); elem2.innerHTML = text; elem3.textContent = text; // which do same?

<b>text</b> text <b>text</b> - first and third do same - second interprets HTML

<html> <body> <div> hi </div> </body> </html> console.log(document.body.children[1].outerHTML) document.body.children[1].outerHTML = "<div>foo" console.log(document.body.children[1].outerHTML)

<div>hi</div> <div>foo</div> - HTML content of node including tag - element node is replaced entirely, and fixed - any further changes to node require a re-query

<html> <body> <ul class="foo"> <li id="john">John</li> <li id="pete"> Pete </li> </ul> </body> </html> const elem = document.getElementById('john') console.log(elem.closest('.foo'))

<ul class="foo">...</ul> - walks parents till it finds match - element itself is included in search

<body> <ul> <li>John</li> <li>Pete <ul> <li>Ed</li> <li>Cris</li></ul> </li> </ul> </body> for (let li of document.querySelectorAll('li')) { console.log(li.firstChild.data.trim()) } console.log(document.querySelectorAll('li').length)

John Pete Ed Cris - gets all <li>, even nested - print out text and length

<html> <body> <div> hi </div> </body> </html> console.log(document.body.children[1].innerHTML) document.body.children[1].innerHTML = "<b>foo" console.log(document.body.children[1].innerHTML)

hi <b>foo</b> - HTML content of node excluding tag - browser fixes errors - only valid for element nodes


Set pelajaran terkait

DTR Domain II (34%) - Nutrition Care for Individuals and Groups

View Set

Chapter 1 NCLEX Questions + Prequiz

View Set

Ch 8. Assess: General Status and Vital Signs

View Set

Arkansas Health Insurance Study Questions

View Set

Chapter 16 - Inventory and Operations Management

View Set