phantasma/app/static/js/pandora-scroll.js
2022-09-07 12:12:31 +02:00

157 lines
4.6 KiB
JavaScript

class PandoraScroll extends HTMLElement {
constructor() {
super()
if (this.attributes.src && this.attributes.src.value) {
const attributes = parseIframeURL(this.attributes.src.value)
Object.keys(attributes).forEach(key => {
if (key[0] != '_') {
this.setAttribute(key, attributes[key])
}
})
}
const shadow = this.attachShadow({mode: 'open'})
const link = document.createElement('link')
link.rel = 'stylesheet'
link.href = document.head.querySelector('link[rel="stylesheet"]').href
const style = document.createElement('style')
const body = document.createElement('div')
body.classList.add('pandora-scroll')
shadow.appendChild(link)
shadow.appendChild(style)
shadow.appendChild(body)
window.addEventListener('resize', () => {
this._resize()
}, false)
this.mute = function() {
shadow.querySelectorAll('video').forEach(video => {
video.muted = true
})
}
}
static get observedAttributes() { return ['muted']; }
connectedCallback() {
this._loadAnnotations()
this._updateStyle()
}
disconnectedCallback() {
//console.log('scroll disconnected')
}
adoptedCallback() {
//console.log('element moved to new page.');
}
attributeChangedCallback(name, oldValue, newValue) {
//console.log('value changed', name, oldValue, newValue);
this._updateStyle()
}
_updateStyle() {
const shadow = this.shadowRoot;
const childNodes = shadow.childNodes;
for (const node of childNodes) {
if (node.nodeName === 'STYLE') {
node.textContent = `
.pandora-scroll {
position: relative;
display: block;
}
`
}
}
}
_config() {
var config = {}
for (var i=0; i<this.attributes.length; i++) {
var a = this.attributes[i]
config[a.name] = a.value
if (a.name == 'layers') {
config[a.name] = a.value.split(' ')
} else if (['in', 'out'].indexOf(a.name) > -1) {
config[a.name] = parseTime(a.value)
} else {
config[a.name] = a.value
}
}
return config
}
_loadAnnotations() {
var config = this._config()
config.root = this.shadowRoot.querySelector('.pandora-scroll')
config.video = document.querySelector('video')
loadAnnotations(config).then(config => {
config.loaded = true
if (config.mode == "single") {
renderSingleMode(config)
} else {
config.annotations.forEach(annotation => {
annotation.src = `${streamPrefix}/${annotation.id.split('/')[0]}/480p.webm`
renderAnnotation(window.config, config.video, config.root, annotation)
})
}
})
}
_resize() {
var video = this.shadowRoot.querySelector('video')
if (video && video._frame) {
var rect = video._frame.getBoundingClientRect(),
root_rect = video._root.getBoundingClientRect(),
top = rect.top - root_rect.top;
video.style.top = top + 'px'
}
}
}
class PandoraItem extends HTMLElement {
constructor() {
super()
}
}
class PandoraEdit extends HTMLElement {
constructor() {
super()
}
}
customElements.define("pandora-scroll", PandoraScroll);
customElements.define("pandora-item", PandoraItem);
customElements.define("pandora-edit", PandoraEdit);
function parseIframeURL(value) {
var config = {}
value = value.replace('/player/', '/')
value = value.replace('/editor/', '/')
var data = value.split('#embed?')
function decodeValue(value) {
return decodeURIComponent(value)
.replace(/_/g, ' ').replace(/\t/g, '_')
.replace(/\x0E/g, '<').replace(/\x0F/g, '>');
}
var args = data[1].replace('&amp;', '&').split('&').map(kv => {
kv = kv.split('=')
//console.log(kv, decodeValue(kv[1]))
return [kv[0], JSON.parse(decodeValue(kv[1]))]
}).reduce((k, v) => {
k[v[0]] = v[1]
return k
}, {})
var parts = data[0].split('/')
config.item = parts[3]
var ts = parts[4].split(',')
config['in'] = ts[0]
config['out'] = ts[1]
config._args = args
if (args.showLayers) {
config.layers = args.showLayers.join(' ')
}
if (args.showTimeline) {
config.timeline = "slitscan"
}
return config
}