flamingo-carotene-dev-server
Version:
Provide the functionality to add file watchers for developing projects with the Flamingo Carotene tooling
136 lines (112 loc) • 3.52 kB
JavaScript
export default class HotReloading {
constructor () {
this.elements = []
this.loadedElements = 0
this.securityWarningLogged = false
}
selectElements (tagName, requiredAttributes) {
this.elements = []
const allNodes = Array.from(document.getElementsByTagName(tagName))
allNodes.forEach(function (element) {
let elementMatches = true
requiredAttributes.forEach(function (requiredAttribute) {
if (!element.hasAttribute(requiredAttribute.name)) {
elementMatches = false
} else {
if (element.getAttribute(requiredAttribute.name) !== requiredAttribute.value) {
elementMatches = false
}
}
})
if (elementMatches) {
this.elements.push(element)
}
}.bind(this))
}
removeElement (elementToRemove) {
this.elements = this.elements.filter(function (element) {
return element !== elementToRemove
})
}
addElement (element) {
this.elements.push(element)
}
makeReloadUrl (url) {
const search = url.match(/hotReload=([0-9]+)$/)
if (search) {
url = url.replace(search[0], 'hotReload=' + (parseInt(search[1], 10) + 1))
} else {
if (url.indexOf('?') === -1) {
url += '?'
} else {
url += '&'
}
url += 'hotReload=1'
}
return url
}
reloadResources (hrefAttribute, elementLoader, onFinish) {
this.loadedElements = 0
this.elements.forEach(function (element) {
// create a NEW element and attach this after the original element
const newElement = element.cloneNode(true)
newElement.setAttribute(hrefAttribute, this.makeReloadUrl(element.getAttribute(hrefAttribute)))
elementLoader.call(this, newElement, element, function () {
this.removeElement(element)
if (element.remove) {
element.remove()
}
else {
// IE11
element.parentNode.removeChild(element)
}
this.addElement(newElement)
}.bind(this), onFinish)
}.bind(this))
}
elementLoaderJS (newElement, oldElement, onLoad, onFinishAll) {
// TODO
oldElement.parentNode.insertBefore(newElement, oldElement.nextSibling)
}
elementLoaderCSS (newElement, oldElement, onLoad, onFinishAll) {
this.securityWarningLogged = false
let timeoutId = null
let intervalId = null
const loadEvent = _ => {
clearInterval(intervalId)
clearTimeout(timeoutId)
if (typeof onLoad === 'function') {
onLoad()
}
this.loadedElements = this.loadedElements + 1
if (this.loadedElements >= this.elements.length) {
if (typeof onFinishAll === 'function') {
onFinishAll()
}
}
}
const checkCss = _ => {
if (this._cssIsLoaded(newElement)) {
loadEvent()
} else {
intervalId = setTimeout(checkCss, 100)
}
}
checkCss()
timeoutId = setTimeout(function () {
loadEvent()
}, 10000)
oldElement.parentNode.insertBefore(newElement, oldElement.nextSibling)
}
_cssIsLoaded (newElement) {
try {
return newElement.styleSheet && newElement.styleSheet.rules.length || newElement.sheet && newElement.sheet.cssRules.length
} catch (e) {
if (e.name === 'SecurityError' && !this.securityWarningLogged) {
console.warn('Your stylesheet is from a different domain. Hot reloading is limited.')
this.securityWarningLogged = true
}
return false
}
}
}