This work is produced by Johan Leitet for the course Client-based Web Programming (1DV022) at Linnaeus University.
All content in this work excluding photographs, icons, picture of course litterature and Linnaeus University logotype and symbol, is licensied under a
Creative Commons Attribution 4.0 International License.
If you change the content do not use the photographs, icons, picture of the course literature or Linnaeus University logotype and symbol in your new work!
At all times you must give credit to: ”Linnaeus university – Client-based Web Programming (1DV022)” with the link https://coursepress.lnu.se/kurs/klientbaserad-webbprogrammering/ and to the Creative Common-license above.
Document object model
<html>
<head>
<title>Incident report</title>
</head>
<body>
<h1>Incident report</h1>
<p><a href="#">Last report</a></p>
<p><img src="photo" alt="" /></p>
</body>
</html>
The javascript engines API against the rendering engine.
Name | Value | |
---|---|---|
H1 | ELEMENT_NODE | 1 |
#text | TEXT_NODE | 3 |
#comment | COMMENT_NODE | 8 |
#document | DOCUMENT_NODE | 9 |
... | ... | ... |
<html>\n
••<head>\n
••••<title>Incident report</title>\n
••</head>\n
••<body>\n
••••<h1>Incident report</h1>\n
••••<p><a href="#">Last report</a></p>\n
••••<p><img src="photo" alt="" /></p>\n
••</body>\n
</html>\n
Parameter (ex) | Returns | |
---|---|---|
getElementById | id | Element |
getElementsByTagName | tag | HTMLCollection |
getElementsByClassName | class | HTMLCollection |
let mainDiv = document.getElementById('main')
let pTags = document.getElementsByTagName('p')
console.log(pTags.length)
let tags = document.getElementsByClassName('post')
console.log(tags.length)
Returns | |
---|---|
querySelector | Element |
querySelectorAll | Node-list |
let mainDiv = document.querySelector('#main')
let pTags = document.querySelectorAll('p')
let tags = document.querySelectorAll('p.tag')
NodeList.prototype !== Array.prototype
forEach implemented in modern browsers (not on HTMLCollection)
pTagsNodeList.forEach(element => {
// Do something
})
Convert to an array to use with other array-methods
let pTagsArray = Array.from(pTagsNodeList)
How to move, insert, delete, copy nodes in the DOM
let newTag = document.createElement('p')
let newText = document.createTextNode('Cool text!')
newTag.appendChild(newText)
document.querySelector('#main').appendChild(newTag)
element.textContent = 'Text...'
element.innerHTML = '<p>Some text</p>'
let newTag = document.createElement('img')
newTag.setAttribute('src', 'image/picture.svg')
// The browser fetches and caches the 'picture.svg'
document.querySelector('#main').appendChild(newTag)
let node = document.querySelector('#discovery')
node.style.color = '#AA5698'
<p id="discovery" style="color: #AA5698">Hello</p>
CSS Property | Identifier |
---|---|
font-size | fontSize |
margin-left | marginLeft |
... | ... |
float | cssFloat |
![]() |
.html | Structure |
![]() |
.css | Presentation |
![]() |
.js | Behavior |
Avoid putting your css in the .js-file, use classes instead!
Exception: Properties that change dynamically
...
movingElement.style.left = `${x}px`
movingElement.style.top = `${y}px`
...
.js
let node = document.querySelector('#discovery')
node.classList.add('jschanged')
.html
<p id="discovery" class="whatever jschanged">Hello</p>
.css
.jschanged {
color: #AA5698;
}
.js
let div = document.createElement('div')
div.classList.add('post')
let ul = document.createElement('ul')
let li1 = document.createElement('li')
let li2 = document.createElement('li')
li1.classList.add('active')
let a1 = document.createElement('a')
a1.setAttribute('href', '#')
let text1 = document.createTextNode('The first link')
a1.appendChild(text1)
let a2 = document.createElement('a')
a2.setAttribute('href', '#')
let text2 = document.createTextNode('The second link')
a2.appendChild(text2)
li1.appendChild(a1)
li2.appendChild(a2)
ul.appendChild(li1)
ul.appendChild(li2)
div.appendChild(ul)
document.querySelector('body').appendChild(div)
.html
<template id='post-template'>
<div class='post'>
<ul>
<li class='active'>
<a href='#'>The first link</a>
</li>
<li>
<a href='#'>The second link</a>
</li>
</ul>
</div>
</template>
.js
let template = document.querySelector('#post-template')
let clone = template.content.cloneNode(true)
document.querySelector('body').appendChild(clone)
Mustache, Underscore Templates, HandlebarsJS, Pug....
.js
const template = document.createElement('template')
template.innerHTML = /*html*/`
<div class='post'>
<ul>
<li class='active'>
<a href='#'>The first link</a>
</li>
<li>
<a href='#'>The second link</a>
</li>
</ul>
</div>`
.js
let clone = template.content.cloneNode(true)
document.querySelector('body').appendChild(clone)
app.html
<bart-board text='I will not polute the global scope'></bart-board>
bart-board.js
class BartBoard extends window.HTMLElement {...}
window.customElements.define('bart-board', BartBoard)
app.html
<bart-board text='I will not polute the global scope'></bart-board>
app.js
let bb2 = document.createElement('bart-board')
bb2.setAttribute(text, 'I will not use == ever again')
bart-board.js
class BartBoard extends window.HTMLElement {
constructor() {
super()
}
connectedCallback () { // Called when added to the document
let text = this.hasAttribute('text') ? this.getAttribute('text') : ''
this.textContent = Array(10).join(text)
}
}
Problem: What if the attribute is changed after the element is added to the document?
bart-board.js
class BartBoard extends window.HTMLElement {
constructor() {
super()
}
connectedCallback () {
this._updateRendering()
}
static get observedAttributes() {
return ['text'];
}
attributeChangedCallback(name, oldValue, newValue) {
this._updateRendering()
}
_updateRendering() {
let text = this.hasAttribute('text') ? this.getAttribute('text') : ''
this.textContent = Array(10).join(text)
}
}
app.html
<bart-board text='I will not polute the global scope'></bart-board>
<video></video>
bart-board.js
const template = document.createElement('template')
template.innerHTML = /*html*/`
<style>
:host {
background:#002418;
...
}
</style>
<p id='board-text'></p>
`
class BartBoard extends window.HTMLElement {
constructor () {
super()
this.attachShadow({mode: 'open'})
this.shadowRoot.appendChild(template.content.cloneNode(true))
}
...
_updateRendering() {
let text = this.hasAttribute('text') ? this.getAttribute('text') : ''
this.shadowRoot.querySelector('#board-text').textContent = Array(10).join(text)
}
Best practices from https://developers.google.com/web/fundamentals/web-components/