Fixed closing issue with cards.
This commit is contained in:
+147
-59
@@ -1,5 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
'use strict';
|
||||
import Highlight from './highlight.js'
|
||||
|
||||
/** To avoid problems with relative URL paths, we use inline data URI to load svg icons. */
|
||||
const closeIconDataURI = `data:image/svg+xml;utf8,
|
||||
@@ -33,10 +34,17 @@ const enableNearestNeighborTaps = false
|
||||
export default class Card {
|
||||
static setup(context, modules = []) {
|
||||
console.log('Setup Card...', modules)
|
||||
context.modules = []
|
||||
|
||||
/**
|
||||
* This is required for the callback functions to work properly.
|
||||
*/
|
||||
window.Card = Card
|
||||
|
||||
context.modules = []
|
||||
context.module = {}
|
||||
|
||||
context.onClose = null
|
||||
|
||||
context.classList.add('info-card')
|
||||
context.setAttribute('data-id', Card.id++)
|
||||
|
||||
@@ -51,16 +59,57 @@ export default class Card {
|
||||
|
||||
static remove(context) {
|
||||
for (let module of Object.values(context.module)) {
|
||||
module.remove()
|
||||
const moduleHasRemoveFunction = typeof module.remove === 'function'
|
||||
if (moduleHasRemoveFunction) module.remove()
|
||||
}
|
||||
}
|
||||
|
||||
static eventClose(event) {
|
||||
static close(event) {
|
||||
let context = this.getContext(event.target)
|
||||
|
||||
if (context) {
|
||||
this.constructor.close(context)
|
||||
} else console.error('Could not find context!', event.target)
|
||||
if (context.onClose != null) {
|
||||
context.onClose()
|
||||
} else {
|
||||
this.remove(context)
|
||||
}
|
||||
|
||||
// console.error("Remove")
|
||||
// let context = this.getContext(event.target)
|
||||
|
||||
// if (context) {
|
||||
// this.remove(context)
|
||||
// } else console.error('Could not find context!', event.target)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an on close method to the provided context.
|
||||
* This will overwrite the default closing behaviour.
|
||||
* Removing the
|
||||
*
|
||||
* @static
|
||||
* @param {DOMElement} context - Context on which the onClose will be set.
|
||||
* @param {Function} callback - Callback function of the onClose.
|
||||
* @memberof Card
|
||||
*/
|
||||
static setOnClose(context, callback) {
|
||||
if (context.onClose != null) console.error('OnClose was already set. It was overwritten by the new method.')
|
||||
context.onClose = callback
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsets the onClose.
|
||||
*
|
||||
* Note: This may be used in conjunction with the setOnClose method.
|
||||
* Using the setOnClose method to adjust behaviour before closing the card.
|
||||
* Then unsetting the onClose to close the Card appropriately by calling the
|
||||
* Card.Close again.
|
||||
*
|
||||
* @static
|
||||
* @param {DOMElement} context - Context on which the remove will be executed.
|
||||
* @memberof Card
|
||||
*/
|
||||
static removeOnClose(context) {
|
||||
context.onClose = null
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,12 +119,12 @@ export default class Card {
|
||||
* @param {*} event
|
||||
* @memberof Card
|
||||
*/
|
||||
static close(context) {
|
||||
console.log('CLOSE CARD!!!')
|
||||
this.unregisterAllEvents(context)
|
||||
if (context.onClose) {
|
||||
context.onClose(event)
|
||||
} else context.parentNode.removeChild(context)
|
||||
static remove(context) {
|
||||
if (context.parentNode != null) {
|
||||
context.parentNode.removeChild(context)
|
||||
} else {
|
||||
console.error('Tried removing card but it was already removed.')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,8 +137,8 @@ export default class Card {
|
||||
* @memberof Card
|
||||
*/
|
||||
static _replaceAttributes(context, html, attribute, replaceFunc) {
|
||||
let clickables = html.querySelectorAll(`[${attribute}]`)
|
||||
clickables.forEach(element => {
|
||||
let attributeCarrier = html.querySelectorAll(`[${attribute}]`)
|
||||
attributeCarrier.forEach(element => {
|
||||
let attributeVal = element.getAttribute(attribute)
|
||||
element.removeAttribute(attribute)
|
||||
replaceFunc.call(this, context, element, attributeVal)
|
||||
@@ -124,11 +173,23 @@ export default class Card {
|
||||
let argsStrings = trimmedArgs.split(',').filter(entry => {
|
||||
return entry.trim() != ''
|
||||
})
|
||||
|
||||
/**
|
||||
* As we determine a function by a string we must traverse from the window object to
|
||||
* get the associated javascript function.
|
||||
*/
|
||||
let callStack = window
|
||||
let last = 'window'
|
||||
do {
|
||||
callStack = callStack[callParts.shift().trim()]
|
||||
let func = callParts.shift().trim()
|
||||
if (callStack[func] == null) {
|
||||
callStack = null
|
||||
console.error(
|
||||
`Could not access callback function: ${attributeVal}. Member ${func} of ${last} could not be found.`
|
||||
)
|
||||
break
|
||||
} else callStack = callStack[func]
|
||||
} while (callParts.length > 0)
|
||||
let targetFunc = callStack
|
||||
|
||||
let that = this
|
||||
|
||||
@@ -161,8 +222,9 @@ export default class Card {
|
||||
}
|
||||
})
|
||||
event.stopPropagation()
|
||||
if (callStack) callStack.call(that, ...args)
|
||||
else {
|
||||
if (targetFunc) {
|
||||
targetFunc.call(that, ...args)
|
||||
} else {
|
||||
console.error('Could not call callback function ' + attributeVal, ...args)
|
||||
}
|
||||
})
|
||||
@@ -190,13 +252,6 @@ export default class Card {
|
||||
/<\s*(a|video|img|image|circle)\s(.*?)(xlink:href|href|src)\s*=\s*["'](\..*?)["']\s*(.*?)>/g,
|
||||
function(data) {
|
||||
let path = that._getRelativePath(arguments[4])
|
||||
|
||||
console.log('REPLACE ', arguments[1])
|
||||
if (arguments[1] == 'a') {
|
||||
console.error('NOT REPLACING LINKS')
|
||||
return ''
|
||||
}
|
||||
|
||||
const tag = `<${arguments[1]} ${arguments[2]} ${arguments[3]}="${path}" ${arguments[5]}>`
|
||||
/* if (that.debug) */ console.log('Adjusted: ', tag)
|
||||
return tag
|
||||
@@ -751,7 +806,7 @@ export default class Card {
|
||||
|
||||
let point = svgPoint.matrixTransform(matrix)
|
||||
let closestDiv = node.closest('div')
|
||||
console.log('closestDiv', closestDiv, point)
|
||||
// console.log('closestDiv', closestDiv, point)
|
||||
let global = Points.fromNodeToPage(closestDiv, point)
|
||||
let local = Points.fromPageToNode(context, global)
|
||||
|
||||
@@ -763,7 +818,7 @@ export default class Card {
|
||||
// we could load the data while the circle is animating.
|
||||
// but for simplicity it's just done here for now.
|
||||
// TODO: Adjust to load while animating (Problem: Unload when cancelled).
|
||||
console.log('loadHighlightPopup', src, position, local)
|
||||
// console.log('loadHighlightPopup', src, position, local)
|
||||
this._loadPopupContent(context, src)
|
||||
.then(content => {
|
||||
this._openPopup(context, src, local, content, {
|
||||
@@ -1214,7 +1269,7 @@ export default class Card {
|
||||
*
|
||||
* @param {*} card - The card to expand
|
||||
* @param {string} html - The original HTML of the card
|
||||
* @param {*} tagName - The tagname of the element that is used as exanded element
|
||||
* @param {*} tagName - The tagname of the element that is used as expanded element
|
||||
* @param {*} src - The src of the expanded element
|
||||
* @param {*} callback - A callback that is called when the expanded element is closed
|
||||
*/
|
||||
@@ -1257,7 +1312,6 @@ export default class Card {
|
||||
let scaleY = globalPreviewRect.height / globalIndexCardRect.height
|
||||
|
||||
let padding = parseInt(this.css(indexbox, 'padding'))
|
||||
let maxWidth = this.css(card, 'max-width')
|
||||
|
||||
TweenLite.set(clone, {
|
||||
css: {
|
||||
@@ -1295,7 +1349,6 @@ export default class Card {
|
||||
|
||||
if (this.dynamicHeight) {
|
||||
let targetHeight = subcardContent.offsetHeight
|
||||
console.log(targetHeight)
|
||||
subcardContent.classList.add('dynamic-height')
|
||||
/**
|
||||
* Scale the content from 100% to it's target size.
|
||||
@@ -1309,7 +1362,7 @@ export default class Card {
|
||||
}
|
||||
|
||||
//jquery hyphenate below
|
||||
if (this.constructor._jQueryIsPresent()) {
|
||||
if (this._isJQueryPresent()) {
|
||||
$('.column')
|
||||
.not('.overview')
|
||||
.children('p')
|
||||
@@ -1389,7 +1442,7 @@ export default class Card {
|
||||
if (enableNearestNeighborTaps) {
|
||||
//look for nearby popups on tap
|
||||
InteractionMapper.on('tap', indexbox, () => {
|
||||
console.log('Tap handler called', editable)
|
||||
// console.log('Tap handler called', editable)
|
||||
if (!editable) {
|
||||
this.findNearbyPopups(event, card)
|
||||
}
|
||||
@@ -1407,24 +1460,55 @@ export default class Card {
|
||||
if (isDirty) {
|
||||
mainController.saveNode(html.innerHTML, url => {
|
||||
callback(url)
|
||||
this._closeIndexCard(context, card,{
|
||||
this._closeIndexCard(context, card, clone, articleClone, {
|
||||
eventElements,
|
||||
src
|
||||
})
|
||||
})
|
||||
} else {
|
||||
this._closeIndexCard(context, card)
|
||||
this._closeIndexCard(context, card, clone, articleClone)
|
||||
}
|
||||
} else {
|
||||
this._closeIndexCard(context, card)
|
||||
this._closeIndexCard(context, card, clone, articleClone)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
static _closeIndexCard(context, card, {
|
||||
eventElements = [],
|
||||
src = null
|
||||
} = []) {
|
||||
/**
|
||||
* Closes the index card again.
|
||||
*
|
||||
* @static
|
||||
* @param {DOMElement} context - The Card element.
|
||||
* @param {DOMElement} subcard - The original subcard element visible on the main card.
|
||||
* @param {DOMElement} clonedSubcard - The cloned subcard that's going to be expanded.
|
||||
* @param {DOMElement} clonedArticle - The article part of the ClonedSubcard.
|
||||
* @param {Object} [{ eventElements = [], src = null }=[]]
|
||||
* @memberof Card
|
||||
*/
|
||||
static _closeIndexCard(
|
||||
context,
|
||||
subcard,
|
||||
clonedSubcard,
|
||||
clonedArticle,
|
||||
|
||||
{ eventElements = [], src = null } = []
|
||||
) {
|
||||
let indexbox = context.querySelector('.mainview')
|
||||
let padding = parseInt(this.css(indexbox, 'padding'))
|
||||
|
||||
let globalPreviewRect = Card._getGlobalRect(subcard)
|
||||
let globalIndexCardRect = Card._getGlobalRect(indexbox)
|
||||
|
||||
let scale = {
|
||||
x: globalPreviewRect.width / globalIndexCardRect.width,
|
||||
y: globalPreviewRect.height / globalIndexCardRect.height
|
||||
}
|
||||
|
||||
let titlebar = clonedSubcard.querySelector('.titlebar')
|
||||
|
||||
let desiredBorderBottomWidth = parseInt(window.getComputedStyle(titlebar).borderBottomWidth)
|
||||
let localOrigin = Points.fromPageToNode(indexbox, Rect.getPosition(globalPreviewRect))
|
||||
|
||||
//logging
|
||||
if (src) {
|
||||
let strparts = src.split('/')
|
||||
@@ -1442,15 +1526,14 @@ export default class Card {
|
||||
this._subcardChanged(context, true)
|
||||
this._enableCardCloseButton(context)
|
||||
|
||||
let previewTitlebar = card.querySelector('.titlebar')
|
||||
let previewTitlebar = subcard.querySelector('.titlebar')
|
||||
let titlebarStyle = window.getComputedStyle(previewTitlebar)
|
||||
let titlebar = clone.querySelector('.titlebar')
|
||||
|
||||
TweenLite.to(titlebar, this.animation.articleTransition, {
|
||||
height: parseInt(titlebarStyle.height)
|
||||
})
|
||||
|
||||
TweenLite.to(articleClone, this.animation.articleTransition / 2, {
|
||||
TweenLite.to(clonedArticle, this.animation.articleTransition / 2, {
|
||||
autoAlpha: 0
|
||||
})
|
||||
|
||||
@@ -1465,24 +1548,25 @@ export default class Card {
|
||||
})
|
||||
}
|
||||
|
||||
TweenLite.set(card, { autoAlpha: 1, css: { maxWidth } })
|
||||
TweenLite.to(clone, this.animation.articleTransition, {
|
||||
let maxWidth = this.css(subcard, 'max-width')
|
||||
TweenLite.set(subcard, { autoAlpha: 1, css: { maxWidth } })
|
||||
TweenLite.to(clonedSubcard, this.animation.articleTransition, {
|
||||
x: localOrigin.x - padding,
|
||||
y: localOrigin.y - padding,
|
||||
scaleX,
|
||||
scaleY,
|
||||
ease: ExpoScaleEase.config(1, scaleX),
|
||||
rotation: angle,
|
||||
scaleX: scale.x,
|
||||
scaleY: scale.y,
|
||||
ease: ExpoScaleEase.config(1, scale.x),
|
||||
// rotation: angle,
|
||||
onComplete: () => {
|
||||
// article.remove()
|
||||
TweenLite.to(clone, this.animation.fade, {
|
||||
TweenLite.to(clonedSubcard, this.animation.fade, {
|
||||
//delay: 0.2,
|
||||
autoAlpha: 0,
|
||||
onComplete: () => {
|
||||
if (editable) {
|
||||
if (Card.isEditable()) {
|
||||
mainController.popController()
|
||||
}
|
||||
clone.remove()
|
||||
clonedSubcard.remove()
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -1508,7 +1592,7 @@ export default class Card {
|
||||
* Tests if jQuery is properly included in the project.
|
||||
* Otherwise specific features may not work correctly (e.g. hyphenation)
|
||||
*/
|
||||
_jQueryIsPresent() {
|
||||
static _isJQueryPresent() {
|
||||
let jQueryInitialized = typeof $ != 'undefined'
|
||||
if (!jQueryInitialized) console.error('No jQuery is provided. Specific features may fail.')
|
||||
return jQueryInitialized
|
||||
@@ -1542,7 +1626,7 @@ export default class Card {
|
||||
* @memberof Card
|
||||
*/
|
||||
static openIndexCard(event, src) {
|
||||
//console.log("openIndexCard", src)
|
||||
console.log('openIndexCard', src)
|
||||
/*
|
||||
* Called by the expandIndexCard(...)
|
||||
*/
|
||||
@@ -1593,9 +1677,7 @@ export default class Card {
|
||||
}
|
||||
|
||||
static _enableCardCloseButton(context) {
|
||||
//console.log("ENABLE")
|
||||
let btn = this._selectCardCloseButton(context)
|
||||
//console.log(btn)
|
||||
btn.classList.remove('disabled')
|
||||
}
|
||||
|
||||
@@ -1706,11 +1788,9 @@ export default class Card {
|
||||
* @memberof Card
|
||||
*/
|
||||
static postProcessResponseText(context, htmlString) {
|
||||
console.error('RUN POSTPROCESS')
|
||||
let editable = this.isEditable()
|
||||
|
||||
htmlString = this._adjustRelativeLinks(htmlString)
|
||||
//console.log(htmlString)
|
||||
let parser = new DOMParser()
|
||||
let html = parser.parseFromString(htmlString, 'text/html')
|
||||
if (!editable) {
|
||||
@@ -1835,7 +1915,7 @@ export default class Card {
|
||||
this._setPopupSource(popup, source)
|
||||
context.popup = popup
|
||||
|
||||
if (this.constructor._jQueryIsPresent()) {
|
||||
if (this._isJQueryPresent()) {
|
||||
//jquery hyphenate below
|
||||
console.log('hyphenated popup:', $('span').hyphenate('de'))
|
||||
}
|
||||
@@ -1908,6 +1988,14 @@ export default class Card {
|
||||
context.subcard = null
|
||||
}
|
||||
|
||||
static _subcardChanged(context, closed = false) {
|
||||
for (let [key, module] of Object.entries(context.module)) {
|
||||
if (module.subcardChanged) {
|
||||
module.subcardChanged(closed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static incrementZIndex(context) {
|
||||
if (!context.zIndex) context.zIndex = 0
|
||||
context.zIndex++
|
||||
|
||||
Reference in New Issue
Block a user