Prettified all files.
This commit is contained in:
+482
-380
File diff suppressed because it is too large
Load Diff
+50
-37
@@ -4,17 +4,15 @@
|
||||
let _HighlightEnabled = true
|
||||
let _CircleIds = 0
|
||||
|
||||
|
||||
/** Helper method to round values with one digit precision */
|
||||
function round(value) {
|
||||
return Math.round(parseFloat(value) * 10) / 10
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A namespace with static functions to expand and shrink highlighted image regions.
|
||||
* Assumes an SVG image with the following structure:
|
||||
*
|
||||
*
|
||||
* <svg viewbox="0 0 100 100">
|
||||
* <!-- The defs section must be defined and cannot be generated in JavaScript -->
|
||||
* <defs>
|
||||
@@ -23,15 +21,14 @@ function round(value) {
|
||||
* <circle onclick="Highlight.animateZoom(event)" cx="47" cy="18" r="8" stroke-width="0.5" />
|
||||
* <circle onclick="Highlight.animateZoom(event)" cx="60" cy="67" r="8" stroke-width="0.5" />
|
||||
* </svg>
|
||||
*
|
||||
*
|
||||
* The SVG root element should use a viewbox with 0 0 100 100 to ensure that the positions and size of the
|
||||
* circles can be represnted in percent.
|
||||
*
|
||||
*
|
||||
* @class Highlight
|
||||
* @extends {Object}
|
||||
*/
|
||||
export default class Highlight extends Object {
|
||||
|
||||
static disableAnimations() {
|
||||
_HighlightEnabled = false
|
||||
let expanded = document.querySelectorAll('.expanded')
|
||||
@@ -64,7 +61,10 @@ export default class Highlight extends Object {
|
||||
if (circle.classList.length == 0) {
|
||||
circle.removeAttribute('class')
|
||||
}
|
||||
if (circle.hasAttribute('id') && circle.getAttribute('id').startsWith('@@')) {
|
||||
if (
|
||||
circle.hasAttribute('id') &&
|
||||
circle.getAttribute('id').startsWith('@@')
|
||||
) {
|
||||
circle.removeAttribute('id')
|
||||
}
|
||||
circle.removeAttribute('data-svg-origin')
|
||||
@@ -79,9 +79,11 @@ export default class Highlight extends Object {
|
||||
}
|
||||
}
|
||||
|
||||
static expand(obj, { scale = 2, duration = 3, stroke = 2, onComplete = null } = {}) {
|
||||
if (obj == null)
|
||||
return
|
||||
static expand(
|
||||
obj,
|
||||
{ scale = 2, duration = 3, stroke = 2, onComplete = null } = {}
|
||||
) {
|
||||
if (obj == null) return
|
||||
//console.log("expand")
|
||||
obj.classList.add('zooming')
|
||||
TweenLite.to(obj, duration, {
|
||||
@@ -102,8 +104,7 @@ export default class Highlight extends Object {
|
||||
|
||||
static shrink(obj, { duration = 0.5, stroke = 2 } = {}) {
|
||||
//console.log("shrink")
|
||||
if (obj == null)
|
||||
return
|
||||
if (obj == null) return
|
||||
obj.classList.add('zooming')
|
||||
TweenLite.to(obj, duration, {
|
||||
scale: 1,
|
||||
@@ -141,7 +142,6 @@ export default class Highlight extends Object {
|
||||
let circleGroup = circle.parentNode
|
||||
let image = svgRoot.querySelector('image')
|
||||
|
||||
|
||||
let stroke = parseFloat(circleGroup.getAttribute('stroke-width') || 6)
|
||||
|
||||
let defs = svgRoot.querySelector('defs')
|
||||
@@ -160,15 +160,16 @@ export default class Highlight extends Object {
|
||||
this.shrink(maskImage, { stroke })
|
||||
return
|
||||
}
|
||||
//console.log("animate called while zooming out -> expand")
|
||||
}
|
||||
else if (circle.classList.contains('zooming')) {
|
||||
//console.log("animate called while zooming out -> expand")
|
||||
} else if (circle.classList.contains('zooming')) {
|
||||
//console.log("animate called while zooming in -> shrink")
|
||||
this.shrink(circle, { stroke })
|
||||
this.shrink(maskImage, { stroke })
|
||||
return
|
||||
}
|
||||
let circles = Array.from(circleGroup.children).filter(e => e.tagName == 'circle')
|
||||
let circles = Array.from(circleGroup.children).filter(
|
||||
e => e.tagName == 'circle'
|
||||
)
|
||||
for (let c of circles) {
|
||||
//console.log("shrinking all circles")
|
||||
this.shrink(c, { stroke })
|
||||
@@ -188,11 +189,10 @@ export default class Highlight extends Object {
|
||||
return false
|
||||
}
|
||||
|
||||
static openHighlight(target, {
|
||||
animation = 0.5,
|
||||
scale = 2,
|
||||
onExpanded = null
|
||||
} = {}) {
|
||||
static openHighlight(
|
||||
target,
|
||||
{ animation = 0.5, scale = 2, onExpanded = null } = {}
|
||||
) {
|
||||
if (Highlight._isExpanded(target)) {
|
||||
console.log('Target is already expanded!')
|
||||
return
|
||||
@@ -206,7 +206,10 @@ export default class Highlight extends Object {
|
||||
let image = parent.querySelector(imageId)
|
||||
if (image) {
|
||||
this._bringToFront(image)
|
||||
} else console.error('Could not find corresponding image element.')
|
||||
} else
|
||||
console.error(
|
||||
'Could not find corresponding image element.'
|
||||
)
|
||||
} else console.log('Element was no parent:', target)
|
||||
}
|
||||
this._bringToFront(target)
|
||||
@@ -215,10 +218,15 @@ export default class Highlight extends Object {
|
||||
let image = svgRoot.querySelector('image')
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let [mask, maskImage] = Highlight._getSVGMask(target, { svgRoot, image })
|
||||
let [mask, maskImage] = Highlight._getSVGMask(target, {
|
||||
svgRoot,
|
||||
image
|
||||
})
|
||||
let center = Highlight._calculateCenterRelativeTo(target, image)
|
||||
|
||||
TweenLite.set(maskImage, { transformOrigin: `${center.x}% ${center.y}%` })
|
||||
TweenLite.set(maskImage, {
|
||||
transformOrigin: `${center.x}% ${center.y}%`
|
||||
})
|
||||
TweenLite.set(target, { transformOrigin: '50% 50%' })
|
||||
|
||||
TweenLite.to([target, maskImage], animation, {
|
||||
@@ -233,8 +241,7 @@ export default class Highlight extends Object {
|
||||
static toggleHighlight(node) {
|
||||
if (Highlight._isExpanded(node)) {
|
||||
Highlight.closeHighlight(node)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
Highlight.openHighlight(node)
|
||||
}
|
||||
}
|
||||
@@ -244,7 +251,12 @@ export default class Highlight extends Object {
|
||||
if (target && parent) {
|
||||
parent.removeChild(target)
|
||||
parent.appendChild(target)
|
||||
} else console.error('Could not bring to front. Either no target or no parent.', target, parent)
|
||||
} else
|
||||
console.error(
|
||||
'Could not bring to front. Either no target or no parent.',
|
||||
target,
|
||||
parent
|
||||
)
|
||||
}
|
||||
|
||||
static _getSVGMask(circle, { svgRoot = null, image = null } = {}) {
|
||||
@@ -258,13 +270,15 @@ export default class Highlight extends Object {
|
||||
let maskImage = svgRoot.getElementById(maskImageId)
|
||||
|
||||
if (!mask || !maskImage)
|
||||
[mask, maskImage] = Highlight._createSVGMask(circle, { svgRoot, image, id })
|
||||
[mask, maskImage] = Highlight._createSVGMask(circle, {
|
||||
svgRoot,
|
||||
image,
|
||||
id
|
||||
})
|
||||
|
||||
return [mask, maskImage]
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Creates an SVG mask for a provided svgElement.
|
||||
*
|
||||
@@ -277,8 +291,10 @@ export default class Highlight extends Object {
|
||||
* @returns
|
||||
* @memberof Highlight
|
||||
*/
|
||||
static _createSVGMask(element, { svgRoot = null, image = null, id = null } = {}) {
|
||||
|
||||
static _createSVGMask(
|
||||
element,
|
||||
{ svgRoot = null, image = null, id = null } = {}
|
||||
) {
|
||||
// We can fetch these values here, but it's more efficient to
|
||||
// simply pass them in, as it's likely they were already retrieved beforehand.
|
||||
if (svgRoot == null) svgRoot = element.closest('svg')
|
||||
@@ -316,7 +332,6 @@ export default class Highlight extends Object {
|
||||
let height = bbox.height
|
||||
|
||||
if (maskImage == null) {
|
||||
|
||||
maskImage = document.createElementNS(svg, 'image')
|
||||
maskImage.style.pointerEvents = 'none'
|
||||
maskImage.setAttribute('id', maskImageId)
|
||||
@@ -369,8 +384,7 @@ export default class Highlight extends Object {
|
||||
}
|
||||
|
||||
static animate(event) {
|
||||
if (!_HighlightEnabled)
|
||||
return
|
||||
if (!_HighlightEnabled) return
|
||||
|
||||
event.stopPropagation()
|
||||
Highlight.animateCircle(event.target)
|
||||
@@ -394,4 +408,3 @@ export default class Highlight extends Object {
|
||||
}
|
||||
|
||||
Highlight.expandedClass = 'expanded'
|
||||
|
||||
|
||||
+160
-132
@@ -1,13 +1,12 @@
|
||||
export var CardPlugin = CardPlugin || {}
|
||||
|
||||
export class CardPluginBase {
|
||||
|
||||
apply(context) {
|
||||
if (this.verify(context)) {
|
||||
this.append(context)
|
||||
console.log("Plugin " + this.name + " was verified successfully.")
|
||||
console.log('Plugin ' + this.name + ' was verified successfully.')
|
||||
return true
|
||||
} else console.error("Could not verify module " + this.name + ".")
|
||||
} else console.error('Could not verify module ' + this.name + '.')
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -32,19 +31,20 @@ export class CardPluginBase {
|
||||
missing.push(selector)
|
||||
}
|
||||
}
|
||||
const valid = (missing.length == 0)
|
||||
if (!valid) console.error("Elements were missing: ", missing.join(", "))
|
||||
const valid = missing.length == 0
|
||||
if (!valid) console.error('Elements were missing: ', missing.join(', '))
|
||||
return valid
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appends the Plugin to the context.
|
||||
*
|
||||
* @memberof CardPlugin
|
||||
*/
|
||||
append(context) {
|
||||
console.error("Call of abstract method CardPlugin.prototype.append(context). Plugins need to overwrite the append method!")
|
||||
console.error(
|
||||
'Call of abstract method CardPlugin.prototype.append(context). Plugins need to overwrite the append method!'
|
||||
)
|
||||
}
|
||||
|
||||
_getVerificationFunctions(context) {
|
||||
@@ -56,7 +56,7 @@ export class CardPluginBase {
|
||||
|
||||
_verifyContext(context) {
|
||||
if (!(context instanceof HTMLElement)) {
|
||||
console.error("Context is not of type HTML Element.", context)
|
||||
console.error('Context is not of type HTML Element.', context)
|
||||
return false
|
||||
} else return true
|
||||
}
|
||||
@@ -71,13 +71,18 @@ export class CardPluginBase {
|
||||
}
|
||||
})
|
||||
|
||||
const valid = (missing.length == 0)
|
||||
if (!valid) console.error("Could not apply module '" + this.name + "'. Following modules are required but were missing: " + missing.join(","))
|
||||
else console.log("All requirements were met! Well done!")
|
||||
const valid = missing.length == 0
|
||||
if (!valid)
|
||||
console.error(
|
||||
"Could not apply module '" +
|
||||
this.name +
|
||||
"'. Following modules are required but were missing: " +
|
||||
missing.join(',')
|
||||
)
|
||||
else console.log('All requirements were met! Well done!')
|
||||
return valid
|
||||
}
|
||||
|
||||
|
||||
_collectAllRequirements() {
|
||||
let requirements = []
|
||||
let klass = this.__proto__
|
||||
@@ -91,9 +96,6 @@ export class CardPluginBase {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
CardPlugin.LightBox = class LightBox extends CardPluginBase {
|
||||
constructor(className, style = {}) {
|
||||
super()
|
||||
@@ -102,27 +104,30 @@ CardPlugin.LightBox = class LightBox extends CardPluginBase {
|
||||
}
|
||||
|
||||
append(context) {
|
||||
let wrapper = document.createElement("div")
|
||||
let wrapper = document.createElement('div')
|
||||
wrapper.className = this.className
|
||||
|
||||
Object.assign(wrapper.style, {
|
||||
zIndex: 1000,
|
||||
// backgroundColor: "black",
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: "100%",
|
||||
height: "100%"
|
||||
}, this.style, {
|
||||
display: "none",
|
||||
position: "absolute",
|
||||
})
|
||||
Object.assign(
|
||||
wrapper.style,
|
||||
{
|
||||
zIndex: 1000,
|
||||
// backgroundColor: "black",
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: '100%'
|
||||
},
|
||||
this.style,
|
||||
{
|
||||
display: 'none',
|
||||
position: 'absolute'
|
||||
}
|
||||
)
|
||||
|
||||
context.appendChild(wrapper)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The Enlargeable Overlay module allows the user to click on the thumbnail image,
|
||||
* and the images gets enlarged inside the card.
|
||||
@@ -131,12 +136,15 @@ CardPlugin.LightBox = class LightBox extends CardPluginBase {
|
||||
* @extends {CardPlugin}
|
||||
*/
|
||||
CardPlugin.EnlargeableThumbnail = class EnlargeableThumbnail extends CardPluginBase {
|
||||
|
||||
constructor(wrapperSelector, overlaySelector = null, {
|
||||
zoomAnimationDuration = 0.4,
|
||||
fadeAnimationDuration = 0.4,
|
||||
interactionType = "tap"
|
||||
} = {}) {
|
||||
constructor(
|
||||
wrapperSelector,
|
||||
overlaySelector = null,
|
||||
{
|
||||
zoomAnimationDuration = 0.4,
|
||||
fadeAnimationDuration = 0.4,
|
||||
interactionType = 'tap'
|
||||
} = {}
|
||||
) {
|
||||
super()
|
||||
this.wrapperSelector = wrapperSelector
|
||||
this.overlaySelector = overlaySelector
|
||||
@@ -147,15 +155,18 @@ CardPlugin.EnlargeableThumbnail = class EnlargeableThumbnail extends CardPluginB
|
||||
}
|
||||
|
||||
get require() {
|
||||
return [
|
||||
CardPlugin.LightBox
|
||||
]
|
||||
return [CardPlugin.LightBox]
|
||||
}
|
||||
|
||||
_getVerificationFunctions(context) {
|
||||
let arr = super._getVerificationFunctions(context)
|
||||
let funcs = [
|
||||
this._verifyElementsExist.bind(this, context, this.wrapperSelector, this.overlaySelector)
|
||||
this._verifyElementsExist.bind(
|
||||
this,
|
||||
context,
|
||||
this.wrapperSelector,
|
||||
this.overlaySelector
|
||||
)
|
||||
]
|
||||
return arr.concat(funcs)
|
||||
}
|
||||
@@ -165,7 +176,6 @@ CardPlugin.EnlargeableThumbnail = class EnlargeableThumbnail extends CardPluginB
|
||||
this.setupEnlargeableThumbnail(context, source)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the preview image.
|
||||
*
|
||||
@@ -177,26 +187,25 @@ CardPlugin.EnlargeableThumbnail = class EnlargeableThumbnail extends CardPluginB
|
||||
* @memberof EnlargeableThumbnail
|
||||
*/
|
||||
_retrieveSource(context) {
|
||||
let img = context.querySelector(this.wrapperSelector + " img")
|
||||
let src = img.getAttribute("src")
|
||||
let parts = src.split("/")
|
||||
let img = context.querySelector(this.wrapperSelector + ' img')
|
||||
let src = img.getAttribute('src')
|
||||
let parts = src.split('/')
|
||||
parts.pop()
|
||||
parts.push(parts[parts.length - 1])
|
||||
let imagePath = parts.join("/") + ".jpg"
|
||||
let imagePath = parts.join('/') + '.jpg'
|
||||
return imagePath
|
||||
}
|
||||
|
||||
|
||||
setupEnlargeableThumbnail(context, src) {
|
||||
let wrapper = context.querySelector(this.wrapperSelector)
|
||||
let overlay = context.querySelector(this.overlaySelector)
|
||||
|
||||
let icon = document.createElement("div")
|
||||
icon.className = "button corner-button bottom-right icon zoom"
|
||||
let icon = document.createElement('div')
|
||||
icon.className = 'button corner-button bottom-right icon zoom'
|
||||
wrapper.appendChild(icon)
|
||||
|
||||
Object.assign(wrapper.style, {
|
||||
cursor: "pointer"
|
||||
cursor: 'pointer'
|
||||
})
|
||||
|
||||
InteractionMapper.on(this.interactionType, wrapper, () => {
|
||||
@@ -209,28 +218,28 @@ CardPlugin.EnlargeableThumbnail = class EnlargeableThumbnail extends CardPluginB
|
||||
}
|
||||
|
||||
openThumbnailDetail(context, src) {
|
||||
let overlay = context.querySelector(".img-overlay")
|
||||
overlay.innerHTML = ""
|
||||
let overlay = context.querySelector('.img-overlay')
|
||||
overlay.innerHTML = ''
|
||||
let source = context.querySelector(this.wrapperSelector)
|
||||
let sourceStyle = window.getComputedStyle(source)
|
||||
let imageWrapper = source.cloneNode(true)
|
||||
let image = imageWrapper.querySelector("img")
|
||||
let image = imageWrapper.querySelector('img')
|
||||
|
||||
Object.assign(imageWrapper.style, {
|
||||
maxWidth: "none",
|
||||
maxHeight: "none"
|
||||
maxWidth: 'none',
|
||||
maxHeight: 'none'
|
||||
})
|
||||
|
||||
Object.assign(image.style, {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
objectFit: "cover"
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
objectFit: 'cover'
|
||||
})
|
||||
|
||||
this._replaceIcon(imageWrapper)
|
||||
|
||||
image.onload = () => {
|
||||
let header = context.querySelector("header")
|
||||
let header = context.querySelector('header')
|
||||
let headerStlye = window.getComputedStyle(header)
|
||||
|
||||
/**
|
||||
@@ -242,20 +251,20 @@ CardPlugin.EnlargeableThumbnail = class EnlargeableThumbnail extends CardPluginB
|
||||
/**
|
||||
* The minor side should not exceed the height of the context window.
|
||||
*/
|
||||
const maxMinorSize = context.offsetHeight - 2 * parseInt(headerStlye.paddingTop) - 2 * parseInt(headerStlye.marginTop)
|
||||
|
||||
|
||||
const maxMinorSize =
|
||||
context.offsetHeight -
|
||||
2 * parseInt(headerStlye.paddingTop) -
|
||||
2 * parseInt(headerStlye.marginTop)
|
||||
|
||||
const max = {
|
||||
width: context.offsetWidth * maxFillRatio,
|
||||
height: context.offsetHeight * maxFillRatio
|
||||
}
|
||||
|
||||
|
||||
let majorSide
|
||||
let minorSide
|
||||
const _width = { name: "width", axis: "x" }
|
||||
const _height = { name: "height", axis: "y" }
|
||||
const _width = { name: 'width', axis: 'x' }
|
||||
const _height = { name: 'height', axis: 'y' }
|
||||
if (image.naturalHeight > image.naturalWidth) {
|
||||
majorSide = _height
|
||||
minorSide = _width
|
||||
@@ -268,14 +277,17 @@ CardPlugin.EnlargeableThumbnail = class EnlargeableThumbnail extends CardPluginB
|
||||
return string.charAt(0).toUpperCase() + string.slice(1)
|
||||
}
|
||||
function getImageSize(side) {
|
||||
return image["natural" + capitalize(side.name)]
|
||||
return image['natural' + capitalize(side.name)]
|
||||
}
|
||||
|
||||
const majorImageSize = getImageSize(majorSide)
|
||||
// const minorImageSize = getImageSize(minorSide)
|
||||
|
||||
let ratio = getImageSize(minorSide) / getImageSize(majorSide)
|
||||
let size = (majorImageSize > max[majorSide.name]) ? max[majorSide.name] : majorImageSize
|
||||
let size =
|
||||
majorImageSize > max[majorSide.name]
|
||||
? max[majorSide.name]
|
||||
: majorImageSize
|
||||
|
||||
if (size * ratio > maxMinorSize) {
|
||||
size = maxMinorSize / ratio
|
||||
@@ -286,8 +298,10 @@ CardPlugin.EnlargeableThumbnail = class EnlargeableThumbnail extends CardPluginB
|
||||
height: 0
|
||||
}
|
||||
|
||||
|
||||
let position = Points.fromPageToNode(context, Points.fromNodeToPage(source, { x: 0, y: 0 }))
|
||||
let position = Points.fromPageToNode(
|
||||
context,
|
||||
Points.fromNodeToPage(source, { x: 0, y: 0 })
|
||||
)
|
||||
|
||||
let targetOffset = {
|
||||
x: 0,
|
||||
@@ -297,8 +311,14 @@ CardPlugin.EnlargeableThumbnail = class EnlargeableThumbnail extends CardPluginB
|
||||
targetDimensions[majorSide.name] = size
|
||||
targetDimensions[minorSide.name] = size * ratio
|
||||
|
||||
targetOffset[majorSide.axis] = (context["offset" + capitalize(majorSide.name)] - targetDimensions[majorSide.name]) / 2
|
||||
targetOffset[minorSide.axis] = (context["offset" + capitalize(minorSide.name)] - targetDimensions[minorSide.name]) / 2
|
||||
targetOffset[majorSide.axis] =
|
||||
(context['offset' + capitalize(majorSide.name)] -
|
||||
targetDimensions[majorSide.name]) /
|
||||
2
|
||||
targetOffset[minorSide.axis] =
|
||||
(context['offset' + capitalize(minorSide.name)] -
|
||||
targetDimensions[minorSide.name]) /
|
||||
2
|
||||
|
||||
overlay.appendChild(imageWrapper)
|
||||
|
||||
@@ -307,14 +327,13 @@ CardPlugin.EnlargeableThumbnail = class EnlargeableThumbnail extends CardPluginB
|
||||
top: 0,
|
||||
x: position.x,
|
||||
y: position.y,
|
||||
position: "absolute",
|
||||
position: 'absolute',
|
||||
width: parseInt(sourceStyle.width),
|
||||
height: parseInt(sourceStyle.height)
|
||||
})
|
||||
|
||||
|
||||
TweenMax.set(overlay, {
|
||||
display: "flex",
|
||||
display: 'flex',
|
||||
autoAlpha: 0
|
||||
})
|
||||
|
||||
@@ -322,7 +341,7 @@ CardPlugin.EnlargeableThumbnail = class EnlargeableThumbnail extends CardPluginB
|
||||
x: targetOffset.x,
|
||||
y: targetOffset.y,
|
||||
width: targetDimensions.width,
|
||||
height: targetDimensions.height,
|
||||
height: targetDimensions.height
|
||||
})
|
||||
TweenMax.to(overlay, this.fadeAnimationTime, {
|
||||
autoAlpha: 1
|
||||
@@ -333,35 +352,40 @@ CardPlugin.EnlargeableThumbnail = class EnlargeableThumbnail extends CardPluginB
|
||||
}
|
||||
|
||||
_replaceIcon(clone) {
|
||||
let zoomIcon = clone.querySelector(".icon.zoom")
|
||||
zoomIcon.classList.remove("zoom")
|
||||
zoomIcon.classList.add("close")
|
||||
let zoomIcon = clone.querySelector('.icon.zoom')
|
||||
zoomIcon.classList.remove('zoom')
|
||||
zoomIcon.classList.add('close')
|
||||
}
|
||||
|
||||
getBorderHeight(style) {
|
||||
const borderWidth = parseInt(style.borderTopWidth) + parseInt(style.borderBottomWidth)
|
||||
const padding = parseInt(style.paddingTop) + parseInt(style.paddingBottom)
|
||||
const borderWidth =
|
||||
parseInt(style.borderTopWidth) + parseInt(style.borderBottomWidth)
|
||||
const padding =
|
||||
parseInt(style.paddingTop) + parseInt(style.paddingBottom)
|
||||
return parseInt(style.width) + borderWidth + padding
|
||||
}
|
||||
|
||||
getBorderWidth(style) {
|
||||
const borderWidth = parseInt(style.borderLeftWidth) + parseInt(style.borderRightWidth)
|
||||
const padding = parseInt(style.paddingLeft) + parseInt(style.paddingRight)
|
||||
const borderWidth =
|
||||
parseInt(style.borderLeftWidth) + parseInt(style.borderRightWidth)
|
||||
const padding =
|
||||
parseInt(style.paddingLeft) + parseInt(style.paddingRight)
|
||||
return parseInt(style.width) + borderWidth + padding
|
||||
}
|
||||
|
||||
closeThumnailDetail(context) {
|
||||
let overlay = context.querySelector(".img-overlay")
|
||||
let overlay = context.querySelector('.img-overlay')
|
||||
|
||||
let timeline = new TimelineLite()
|
||||
|
||||
timeline.to(overlay, this.fadeAnimationDuration, {
|
||||
autoAlpha: 0
|
||||
}).set(overlay, {
|
||||
display: "none"
|
||||
})
|
||||
timeline
|
||||
.to(overlay, this.fadeAnimationDuration, {
|
||||
autoAlpha: 0
|
||||
})
|
||||
.set(overlay, {
|
||||
display: 'none'
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CardPlugin.Ui = class UiPlugin extends CardPluginBase {
|
||||
@@ -373,56 +397,52 @@ CardPlugin.Ui = class UiPlugin extends CardPluginBase {
|
||||
|
||||
_getVerificationFunctions(context) {
|
||||
let arr = super._getVerificationFunctions(context)
|
||||
let func = [
|
||||
this._doesParentExist.bind(this, context, this.parent)
|
||||
]
|
||||
let func = [this._doesParentExist.bind(this, context, this.parent)]
|
||||
return arr.concat(func)
|
||||
}
|
||||
|
||||
_doesParentExist(context, parent) {
|
||||
if (parent == null) return true
|
||||
let valid = (context.querySelector(parent) != null)
|
||||
if (!valid) console.error("Could not find parent on context.", context, parent)
|
||||
let valid = context.querySelector(parent) != null
|
||||
if (!valid)
|
||||
console.error('Could not find parent on context.', context, parent)
|
||||
return valid
|
||||
}
|
||||
|
||||
append(context) {
|
||||
parent = (this.parent == null) ? context : context.querySelector(this.parent).appendChild(container)
|
||||
let container = document.createElement("div")
|
||||
parent =
|
||||
this.parent == null
|
||||
? context
|
||||
: context.querySelector(this.parent).appendChild(container)
|
||||
let container = document.createElement('div')
|
||||
container.className = this.className
|
||||
parent.appendChild(container)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CardPlugin.Speech = class SpeechPlugin extends CardPluginBase {
|
||||
|
||||
constructor(parentSelector, className, interactionType = "tap") {
|
||||
constructor(parentSelector, className, interactionType = 'tap') {
|
||||
super()
|
||||
this.className = className
|
||||
this.parentSelector = parentSelector
|
||||
this.interactionType = interactionType
|
||||
|
||||
}
|
||||
|
||||
get require() {
|
||||
return [
|
||||
CardPlugin.Ui
|
||||
]
|
||||
return [CardPlugin.Ui]
|
||||
}
|
||||
|
||||
append(context) {
|
||||
let container = context.querySelector(this.parentSelector)
|
||||
this.button = document.createElement("div")
|
||||
this.button.className = "icon button " + this.className
|
||||
this.button = document.createElement('div')
|
||||
this.button.className = 'icon button ' + this.className
|
||||
container.appendChild(this.button)
|
||||
|
||||
InteractionMapper.on(this.interactionType, this.button, () => {
|
||||
let subcard = context.querySelector(".mainview > .subcard")
|
||||
let target = (subcard) ? subcard : context
|
||||
let subcard = context.querySelector('.mainview > .subcard')
|
||||
let target = subcard ? subcard : context
|
||||
|
||||
this.speak(target)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
@@ -433,8 +453,7 @@ CardPlugin.Speech = class SpeechPlugin extends CardPluginBase {
|
||||
}
|
||||
|
||||
_activateButton() {
|
||||
if (this.button)
|
||||
this.button.classList.add("active")
|
||||
if (this.button) this.button.classList.add('active')
|
||||
}
|
||||
|
||||
_deactivate() {
|
||||
@@ -442,36 +461,32 @@ CardPlugin.Speech = class SpeechPlugin extends CardPluginBase {
|
||||
}
|
||||
|
||||
_deactivateButton() {
|
||||
if (this.button)
|
||||
this.button.classList.remove("active")
|
||||
if (this.button) this.button.classList.remove('active')
|
||||
}
|
||||
|
||||
_isSameNode(node) {
|
||||
//console.log(this.currentText, node.innerText)
|
||||
return (this.currentText == node.innerText)
|
||||
return this.currentText == node.innerText
|
||||
}
|
||||
|
||||
speak(node) {
|
||||
|
||||
console.log(this._isSameNode(node))
|
||||
|
||||
if (!window.speechSynthesis.speaking) {
|
||||
console.log("Noone talking!")
|
||||
console.log('Noone talking!')
|
||||
this._start(node)
|
||||
} else if (this._isSameNode(node)) {
|
||||
console.log("Requested same!")
|
||||
console.log('Requested same!')
|
||||
this._stop()
|
||||
|
||||
} else {
|
||||
console.log("Requested Different!")
|
||||
console.log('Requested Different!')
|
||||
this._stop()
|
||||
this._start(node)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_disableActive() {
|
||||
console.log("disableActive:", this.active)
|
||||
console.log('disableActive:', this.active)
|
||||
if (this.active) {
|
||||
this.active._deactivate()
|
||||
}
|
||||
@@ -483,28 +498,40 @@ CardPlugin.Speech = class SpeechPlugin extends CardPluginBase {
|
||||
|
||||
let voices = window.speechSynthesis.getVoices()
|
||||
console.log(voices)
|
||||
let voice = voices.filter((val) => {
|
||||
let voice = voices.filter(val => {
|
||||
//console.log(val)
|
||||
return val.name == "Microsoft Hedda Desktop - German"
|
||||
return val.name == 'Microsoft Hedda Desktop - German'
|
||||
})[0]
|
||||
|
||||
//console.log(voice)
|
||||
|
||||
utterance.voice = voice
|
||||
console.log("TALK: ", utterance)
|
||||
console.log('TALK: ', utterance)
|
||||
window.speechSynthesis.speak(utterance)
|
||||
this._activate()
|
||||
window.speechSynthesis.resume()
|
||||
|
||||
|
||||
utterance.onboundary = () => { console.log("onboundary", node.innerText); if (this.currentText.substring(0, 5) != node.innerText.substring(0, 5)) { console.log("text for speech synth changed!", this.currentText, node.innerText); this._stop() } }
|
||||
utterance.onend = () => console.log("onend", node.innerText)
|
||||
utterance.onerror = () => console.log("onerror", node.innerText)
|
||||
utterance.onmark = () => console.log("onmark", node.innerText)
|
||||
utterance.onpause = () => console.log("onpause", node.innerText)
|
||||
utterance.onresume = () => console.log("onresume", node.innerText)
|
||||
utterance.onstart = () => console.log("onstart", node.innerText)
|
||||
utterance.onerror = () => console.log("onerror", node.innerText)
|
||||
utterance.onboundary = () => {
|
||||
console.log('onboundary', node.innerText)
|
||||
if (
|
||||
this.currentText.substring(0, 5) !=
|
||||
node.innerText.substring(0, 5)
|
||||
) {
|
||||
console.log(
|
||||
'text for speech synth changed!',
|
||||
this.currentText,
|
||||
node.innerText
|
||||
)
|
||||
this._stop()
|
||||
}
|
||||
}
|
||||
utterance.onend = () => console.log('onend', node.innerText)
|
||||
utterance.onerror = () => console.log('onerror', node.innerText)
|
||||
utterance.onmark = () => console.log('onmark', node.innerText)
|
||||
utterance.onpause = () => console.log('onpause', node.innerText)
|
||||
utterance.onresume = () => console.log('onresume', node.innerText)
|
||||
utterance.onstart = () => console.log('onstart', node.innerText)
|
||||
utterance.onerror = () => console.log('onerror', node.innerText)
|
||||
}
|
||||
|
||||
_stop() {
|
||||
@@ -517,7 +544,9 @@ CardPlugin.Speech = class SpeechPlugin extends CardPluginBase {
|
||||
return this.constructor.active
|
||||
}
|
||||
|
||||
set active(val) { this.constructor.active = val }
|
||||
set active(val) {
|
||||
this.constructor.active = val
|
||||
}
|
||||
|
||||
get currentText() {
|
||||
return this.constructor.text
|
||||
@@ -526,5 +555,4 @@ CardPlugin.Speech = class SpeechPlugin extends CardPluginBase {
|
||||
set currentText(val) {
|
||||
this.constructor.text = val
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+31
-39
@@ -6,8 +6,6 @@ import Card from './card.js'
|
||||
* @class ScatterCard
|
||||
*/
|
||||
export default class ScatterCard extends Card {
|
||||
|
||||
|
||||
/**
|
||||
* TODO: Find a more suitable name.
|
||||
* Adjusts the HTML to work in the new context.
|
||||
@@ -19,32 +17,27 @@ export default class ScatterCard extends Card {
|
||||
* @param {*} [opts={}]
|
||||
* @memberof Card
|
||||
*/
|
||||
static setup(context, htmlString, {
|
||||
basePath = "./",
|
||||
modules = []
|
||||
} = {}) {
|
||||
context.classList.add("info-card")
|
||||
static setup(context, htmlString, { basePath = './', modules = [] } = {}) {
|
||||
context.classList.add('info-card')
|
||||
|
||||
this.relativePath = basePath
|
||||
htmlString = this._adjustRelativeLinks(htmlString)
|
||||
|
||||
let parser = new DOMParser()
|
||||
let html = parser.parseFromString(htmlString, "text/html")
|
||||
let html = parser.parseFromString(htmlString, 'text/html')
|
||||
|
||||
/**
|
||||
* Conflicts with the FindTarget method of the Abstract scatter.
|
||||
*/
|
||||
this._replaceAttributes(html, "onclick", this._replaceCallback)
|
||||
this._replaceAttributes(html, 'onclick', this._replaceCallback)
|
||||
|
||||
|
||||
let content = html.querySelector(".mainview")
|
||||
let content = html.querySelector('.mainview')
|
||||
context.appendChild(content)
|
||||
|
||||
super.setup(context, modules)
|
||||
return context
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appends a close listener to the scatter element.
|
||||
*
|
||||
@@ -59,7 +52,6 @@ export default class ScatterCard extends Card {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a scatter for the card and applies the card to it,
|
||||
*
|
||||
@@ -71,11 +63,12 @@ export default class ScatterCard extends Card {
|
||||
* @returns
|
||||
* @memberof Card
|
||||
*/
|
||||
static createCardScatter(html, scatterContainer, {
|
||||
basePath = "./",
|
||||
modules = []
|
||||
} = {}) {
|
||||
let element = document.createElement("div")
|
||||
static createCardScatter(
|
||||
html,
|
||||
scatterContainer,
|
||||
{ basePath = './', modules = [] } = {}
|
||||
) {
|
||||
let element = document.createElement('div')
|
||||
|
||||
scatterContainer.element.appendChild(element)
|
||||
new DOMScatter(element, scatterContainer, {
|
||||
@@ -90,8 +83,6 @@ export default class ScatterCard extends Card {
|
||||
return element
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*Utility function to create a fully functional card scatter.
|
||||
*
|
||||
@@ -103,24 +94,27 @@ export default class ScatterCard extends Card {
|
||||
* @returns
|
||||
* @memberof CardScatter
|
||||
*/
|
||||
static loadAndCreateScatterCard(scatterContainer, item, {
|
||||
basePath = "../",
|
||||
modules = [],
|
||||
onClose = null
|
||||
} = {}) {
|
||||
static loadAndCreateScatterCard(
|
||||
scatterContainer,
|
||||
item,
|
||||
{ basePath = '../', modules = [], onClose = null } = {}
|
||||
) {
|
||||
console.log(basePath)
|
||||
return new Promise((resolve, reject) => {
|
||||
let url = basePath + "/" + item + "/index.html"
|
||||
console.log("Loading", url)
|
||||
let url = basePath + '/' + item + '/index.html'
|
||||
console.log('Loading', url)
|
||||
this.loadHTML(url)
|
||||
.then(html => {
|
||||
console.log("Received", html)
|
||||
let element = this.createCardScatter(html, scatterContainer, {
|
||||
basePath,
|
||||
modules
|
||||
})
|
||||
if (onClose)
|
||||
this.addOnCloseListener(element, onClose)
|
||||
console.log('Received', html)
|
||||
let element = this.createCardScatter(
|
||||
html,
|
||||
scatterContainer,
|
||||
{
|
||||
basePath,
|
||||
modules
|
||||
}
|
||||
)
|
||||
if (onClose) this.addOnCloseListener(element, onClose)
|
||||
resolve(element)
|
||||
})
|
||||
.catch(e => reject(e))
|
||||
@@ -134,14 +128,12 @@ export default class ScatterCard extends Card {
|
||||
static _getLanguage(context) {
|
||||
return context.language
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ScatterCard.selectedLanguage = 0
|
||||
ScatterCard.languages = ["Deutsch", "English"]
|
||||
ScatterCard.languages = ['Deutsch', 'English']
|
||||
ScatterCard.languageTags = {
|
||||
Deutsch: "de",
|
||||
English: "en"
|
||||
Deutsch: 'de',
|
||||
English: 'en'
|
||||
}
|
||||
ScatterCard.scatterContainer = null
|
||||
|
||||
|
||||
+3
-6
@@ -7,7 +7,6 @@
|
||||
* @class Theme
|
||||
*/
|
||||
export default class Theme {
|
||||
|
||||
/**
|
||||
* Loads a config file and parses it to JSON.
|
||||
*
|
||||
@@ -18,17 +17,15 @@ export default class Theme {
|
||||
*/
|
||||
static loadConfig(path = null) {
|
||||
return new Promise((resolve, reject) => {
|
||||
path = (path) ? path : './config.json'
|
||||
path = path ? path : './config.json'
|
||||
|
||||
let xhttp = new XMLHttpRequest()
|
||||
xhttp.onreadystatechange = function () {
|
||||
xhttp.onreadystatechange = function() {
|
||||
if (this.readyState == 4) {
|
||||
|
||||
if (this.status == 200 || Theme._isLocal()) {
|
||||
try {
|
||||
const json = JSON.parse(this.responseText)
|
||||
resolve(json)
|
||||
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
@@ -41,6 +38,6 @@ export default class Theme {
|
||||
}
|
||||
|
||||
static _isLocal() {
|
||||
return (window.location.protocol == 'file:')
|
||||
return window.location.protocol == 'file:'
|
||||
}
|
||||
}
|
||||
|
||||
+53
-43
@@ -5,8 +5,10 @@ import Events from '../events.js'
|
||||
import { Points } from '../utils.js'
|
||||
|
||||
export default class CardWrapper extends Object {
|
||||
|
||||
constructor(domNode, { triggerSVGClicks = true, allowClickDistance = 44 } = {}) {
|
||||
constructor(
|
||||
domNode,
|
||||
{ triggerSVGClicks = true, allowClickDistance = 44 } = {}
|
||||
) {
|
||||
super()
|
||||
this.domNode = domNode
|
||||
this.triggerSVGClicks = triggerSVGClicks
|
||||
@@ -16,42 +18,43 @@ export default class CardWrapper extends Object {
|
||||
}
|
||||
|
||||
handleClicks() {
|
||||
this.domNode.addEventListener('click', event => {
|
||||
if (event.isTrusted) {
|
||||
Events.stop(event)
|
||||
if (this.triggerSVGClicks && this.isSVGNode(event.target)) {
|
||||
this.tap(event, "triggerSVGClicks")
|
||||
this.domNode.addEventListener(
|
||||
'click',
|
||||
event => {
|
||||
if (event.isTrusted) {
|
||||
Events.stop(event)
|
||||
if (this.triggerSVGClicks && this.isSVGNode(event.target)) {
|
||||
this.tap(event, 'triggerSVGClicks')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}, true)
|
||||
},
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
handleClicksAsTaps() {
|
||||
this.domNode.addEventListener('click', event => {
|
||||
if (event.isTrusted) {
|
||||
Events.stop(event)
|
||||
|
||||
}
|
||||
this.tap(event)
|
||||
}, true)
|
||||
this.domNode.addEventListener(
|
||||
'click',
|
||||
event => {
|
||||
if (event.isTrusted) {
|
||||
Events.stop(event)
|
||||
}
|
||||
this.tap(event)
|
||||
},
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
isClickable(node) {
|
||||
if (node == null)
|
||||
return false
|
||||
if (node.tagName == 'A' && node.hasAttribute("href"))
|
||||
return true
|
||||
if (node.hasAttribute("onclick"))
|
||||
return true
|
||||
if (node == null) return false
|
||||
if (node.tagName == 'A' && node.hasAttribute('href')) return true
|
||||
if (node.hasAttribute('onclick')) return true
|
||||
return false
|
||||
}
|
||||
|
||||
hasClickHandler(node) {
|
||||
if (node == null)
|
||||
return false
|
||||
if (this.tapNodes.has(node))
|
||||
return true
|
||||
if (node == null) return false
|
||||
if (this.tapNodes.has(node)) return true
|
||||
for (let [selector, handler] of this.tapHandler.entries()) {
|
||||
for (let obj of this.domNode.querySelectorAll(selector)) {
|
||||
if (node == obj) {
|
||||
@@ -68,15 +71,13 @@ export default class CardWrapper extends Object {
|
||||
* See https://stackoverflow.com/questions/11455515/how-to-check-whether-dynamically-attached-event-listener-exists-or-not
|
||||
* Therefore we can only detect the following standard cases:
|
||||
* I. All clickable objects like activeNodes
|
||||
* II. Objects that have been attached a click handler by the scatter itself via
|
||||
* II. Objects that have been attached a click handler by the scatter itself via
|
||||
*/
|
||||
activeNodes() {
|
||||
let result = []
|
||||
for (let node of this.domNode.querySelectorAll("*")) {
|
||||
if (this.isClickable(node))
|
||||
result.push(node)
|
||||
if (this.hasClickHandler(node))
|
||||
result.push(node)
|
||||
for (let node of this.domNode.querySelectorAll('*')) {
|
||||
if (this.isClickable(node)) result.push(node)
|
||||
if (this.hasClickHandler(node)) result.push(node)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -84,14 +85,26 @@ export default class CardWrapper extends Object {
|
||||
nearestActive(event) {
|
||||
let element = this.domNode
|
||||
let activeNodes = this.activeNodes()
|
||||
let globalClick = (event.center) ? event.center : { x: event.x, y: event.y }
|
||||
let globalClick = event.center
|
||||
? event.center
|
||||
: { x: event.x, y: event.y }
|
||||
let localClick = Points.fromPageToNode(element, globalClick)
|
||||
|
||||
let clickRects = activeNodes.map(link => {
|
||||
let rect = link.getBoundingClientRect()
|
||||
let topLeft = Points.fromPageToNode(element, rect)
|
||||
let center = Points.fromPageToNode(element, { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 })
|
||||
return { x: topLeft.x, y: topLeft.y, width: rect.width, height: rect.height, center, link }
|
||||
let center = Points.fromPageToNode(element, {
|
||||
x: rect.x + rect.width / 2,
|
||||
y: rect.y + rect.height / 2
|
||||
})
|
||||
return {
|
||||
x: topLeft.x,
|
||||
y: topLeft.y,
|
||||
width: rect.width,
|
||||
height: rect.height,
|
||||
center,
|
||||
link
|
||||
}
|
||||
})
|
||||
|
||||
let distances = []
|
||||
@@ -147,12 +160,12 @@ export default class CardWrapper extends Object {
|
||||
return false
|
||||
}
|
||||
|
||||
tap(event, calledBy='unknown') {
|
||||
tap(event, calledBy = 'unknown') {
|
||||
if (event.isTrusted) {
|
||||
let node = this.nearestActive(event)
|
||||
this.nodeTapped(node, event)
|
||||
|
||||
/* let node = document.elementFromPoint(event.clientX, event.clientY)
|
||||
/* let node = document.elementFromPoint(event.clientX, event.clientY)
|
||||
if (!this.nodeTapped(node, event)) {
|
||||
node = this.nearestActive(event)
|
||||
this.nodeTapped(node, event)
|
||||
@@ -161,13 +174,10 @@ export default class CardWrapper extends Object {
|
||||
}
|
||||
|
||||
onTap(objOrSelector, handler) {
|
||||
if (typeof (objOrSelector) == 'string') {
|
||||
if (typeof objOrSelector == 'string') {
|
||||
this.tapHandler.set(objOrSelector, handler)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.tapNodes.set(objOrSelector, handler)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user