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.
<a href="page.html" onclick="doSomething()">The link</a>
"When this happens do that"
let a = document.querySelector('#theatag')
a.addEventListener('click', buttonClicked)
function buttonClicked(event){
console.log('You clicked the link!')
}
let a = document.querySelector('#theatag')
a.addEventListener('click', function(event){
console.log('You clicked the link!')
})
let a = document.querySelector('#theatag')
a.addEventListener('click', event => {
console.log('You clicked the link!')
})
using Named function expressions
let a = document.querySelector('#theatag')
a.addEventListener('click', function buttonClicked(event){
console.log('You can only click me once!')
a.removeEventListener('click', buttonClicked)
})
let a = document.querySelector('#atag')
let p = document.querySelector('#ptag')
a.addEventListener('click', function(event){
console.log('You clicked the link!')
event.stopPropagation()
})
p.addEventListener('click', function(event){
console.log('Damn you a! I will not be called.')
})
p.addEventListener('click', function(event){
console.log('Hihi! Captured it!')
}, true)
Inside an event handler this
will reference the element
which triggered the event.
let a = document.querySelector('#atag')
a.addEventListener('click', function(event){
a === this // true
a === event.target // true
this === event.target // true
})
The old fashion way (do not do this... anymore)
let a = document.querySelector('#atag')
let that = this
a.addEventListener('click', function(event){
// Use that to refer to this outside of the function.
})
use bind() or...
let a = document.querySelector('#atag')
a.addEventListener('click', function(event){
a === this // false
a === event.target // true
this === event.target // false
}.bind(this))
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
... use Arrow Functions (if possible)
let a = document.querySelector('#atag')
a.addEventListener('click', event => {
a === this // false
a === event.target // true
this === event.target // false
})
Closures can cause headache
<div id="links">
<a href="#">The first link</a>
<a href="#">The second link</a>
<a href="#">The third link</a>
<a href="#">The forth link</a>
</div>
let aTags = document.querySelectorAll('#links a')
for(let i = 0 ; i < aTags.length; i += 1) {
aTags[i].addEventListener('click', function(event) {
console.log('Clicked link ', i) // 4
console.log(event.target.textContent) // Correct ('The first link'...)
})
}
Functions ftw, or?
<div id="links">
<a href="#">The first link</a>
<a href="#">The second link</a>
<a href="#">The third link</a>
<a href="#">The forth link</a>
</div>
let aTags = document.querySelectorAll('#links a')
aTags.forEach( (a, i) => {
a.addEventListener('click', event => {
console.log(i) // Correct (0 ... 1 ... 2)
console.log(event.target.textContent) // Correct
})
})
Add one listener instead of four
<div id="links">
<a href="#">The first link</a>
<a href="#">The second link</a>
<a href="#">The third link</a>
<a href="#">The forth link</a>
</div>
let div = document.querySelector('#links')
div.addEventListener('click', event => {
console.log(event.target.textContent) // "The first link"
event.currentTarget === div //true
})
let a = document.querySelector('#atag')
a.addEventListener('click', event => {
console.log('I got this. Don´t activate the link!')
event.preventDefault()
})
Another alternative is to return false from the listener.
Timeout:
let timer = setTimeout( () => {
console.log('At least 3 seconds passed..')
}, 3000)
clearTimeout(timer) // Stops the timer
Interval:
let timer = setInterval( () => {
console.log('At least 3 seconds passed..')
}, 3000)
clearInterval(timer) // Stops the interval
We can create custom events for our custom elements
in my-custom-element.js
let signupEvent = new window.CustomEvent('signup', { detail: myInput.value })
myCustomElement.dispatchEvent(signupEvent) // This will "trigger"/dispatch the event
using the custom element
let element = document.querySelector('#theCustomElement')
element.addEventListener('signup', event => {
console.log(event.detail)
})
bart-board.js
class BartBoard extends window.HTMLElement {
...
connectedCallback () {
this.addEventListener('mousedown', this._onWrite)
this.addEventListener('mouseup', this._onStopWriting)
this.addEventListener('mouseleave', this._onStopWriting)
}
disconnectedCallback () {
this.removeEventListener('mousedown', this._onWrite)
this.removeEventListener('mouseup', this._onStopWriting)
this.removeEventListener('mouseleave', this._onStopWriting)
}
bart-board.js
class BartBoard extends window.HTMLElement {
...
_onWrite (event) {
this._intervalID = setInterval(() => {
if (this._p.offsetHeight >= this.offsetHeight) {
let event = new window.CustomEvent('filled', { detail: {} })
this.dispatchEvent(event)
this._onStopWriting()
return // no use to keep on writing
}
... // Write on board
}, 200)
app.js
bb1.addEventListener('filled', () => {
console.log('Looks like the board is full! Maybee wipe?')
})
setTimeout( () => {
console.log('Sending a message to the event queue')
}, 0)
let a = document.querySelectorAll('a')[0]
a.addEventListener('click', event => {
console.log('Sending a message when user clicks link')
})