Working on cards.

This commit is contained in:
Uwe Oestermeier 2019-07-15 13:32:45 +02:00
parent 0e8c62eb4b
commit c3477244b9
5 changed files with 447 additions and 51 deletions

415
dist/iwmlib.js vendored
View File

@ -7548,11 +7548,6 @@
handleClicks() { handleClicks() {
this.domNode.addEventListener('click', event => { this.domNode.addEventListener('click', event => {
console.log('handleClicks', event.isTrusted);
/* Currently we cannot send synthesized click events to SVG elements without unwanted side effects.
Therefore we make an exception and let the original click event through.
*/
if (event.isTrusted) { if (event.isTrusted) {
Events.stop(event); Events.stop(event);
if (this.triggerSVGClicks && this.isSVGNode(event.target)) { if (this.triggerSVGClicks && this.isSVGNode(event.target)) {
@ -7565,10 +7560,6 @@
handleClicksAsTaps() { handleClicksAsTaps() {
this.domNode.addEventListener('click', event => { this.domNode.addEventListener('click', event => {
console.log('handleClicksAsTaps', event.isTrusted);
/* Currently we cannot send synthesized click events to SVG elements without unwanted side effects.
Therefore we make an exception and let the original click event through.
*/
if (event.isTrusted) { if (event.isTrusted) {
Events.stop(event); Events.stop(event);
@ -7593,9 +7584,7 @@
if (this.tapNodes.has(node)) if (this.tapNodes.has(node))
return true return true
for (let [selector, handler] of this.tapHandler.entries()) { for (let [selector, handler] of this.tapHandler.entries()) {
console.log("selector", this.domNode.querySelectorAll(selector));
for (let obj of this.domNode.querySelectorAll(selector)) { for (let obj of this.domNode.querySelectorAll(selector)) {
console.log("selector2", node, obj);
if (node == obj) { if (node == obj) {
return true return true
} }
@ -7658,7 +7647,6 @@
/* https://stackoverflow.com/questions/49564905/is-it-possible-to-use-click-function-on-svg-tags-i-tried-element-click-on-a /* https://stackoverflow.com/questions/49564905/is-it-possible-to-use-click-function-on-svg-tags-i-tried-element-click-on-a
proposes the dispatchEvent solution. But this leads to problems in flippable.html hiding the back page. proposes the dispatchEvent solution. But this leads to problems in flippable.html hiding the back page.
Therefore we use the original click event (see constructor). */ Therefore we use the original click event (see constructor). */
console.log("simulateClick", node, node.ownerSVGElement);
if (this.isSVGNode(node)) { if (this.isSVGNode(node)) {
if (this.triggerSVGClicks) { if (this.triggerSVGClicks) {
let click = new Event('click'); let click = new Event('click');
@ -7691,7 +7679,6 @@
} }
tap(event, calledBy='unknown') { tap(event, calledBy='unknown') {
console.log("tap", calledBy, event.alreadyTapped, event);
if (event.isTrusted) { if (event.isTrusted) {
let node = this.nearestActive(event); let node = this.nearestActive(event);
this.nodeTapped(node, event); this.nodeTapped(node, event);
@ -7715,7 +7702,406 @@
} }
} }
window.CardWrapper = CardWrapper;
/* eslint-disable no-console */
/* global TweenLite */
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>
* </defs>
* <image width="100" height="100" xlink:href="../assets/chess.jpg"/>
* <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}
*/
class Highlight extends Object {
static disableAnimations() {
_HighlightEnabled = false;
let expanded = document.querySelectorAll('.expanded');
for (let obj of expanded) {
this.shrink(obj);
}
}
static enableAnimations() {
_HighlightEnabled = true;
}
static removeAnimations(svgRoot) {
let expanded = svgRoot.querySelectorAll('.expanded');
for (let obj of expanded) {
TweenLite.set(obj, { scale: 1 });
obj.classList.remove('zooming');
obj.classList.remove('expanded');
}
let defs = svgRoot.querySelector('defs');
while (defs.firstChild) {
defs.firstChild.remove();
}
let maskImages = svgRoot.querySelectorAll('.addedImage');
for (let m of maskImages) {
m.remove();
}
let circles = svgRoot.querySelectorAll('circle');
for (let circle of circles) {
if (circle.classList.length == 0) {
circle.removeAttribute('class');
}
if (circle.hasAttribute('id') && circle.getAttribute('id').startsWith('@@')) {
circle.removeAttribute('id');
}
circle.removeAttribute('data-svg-origin');
circle.removeAttribute('transform');
circle.removeAttribute('style');
let cx = circle.getAttribute('cx');
let cy = circle.getAttribute('cy');
let r = circle.getAttribute('r');
circle.setAttribute('cx', round(cx));
circle.setAttribute('cy', round(cy));
circle.setAttribute('r', round(r));
}
}
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, {
scale: scale,
onUpdate: () => {
let scale = obj._gsTransform.scaleX;
obj.setAttribute('stroke-width', stroke / scale);
},
onComplete: () => {
console.log('expand complete');
obj.classList.remove('zooming');
obj.classList.add('expanded');
obj.setAttribute('stroke-width', stroke / scale);
if (onComplete) onComplete();
}
});
}
static shrink(obj, { duration = 0.5, stroke = 2 } = {}) {
//console.log("shrink")
if (obj == null)
return
obj.classList.add('zooming');
TweenLite.to(obj, duration, {
scale: 1,
onUpdate: () => {
let scale = obj._gsTransform.scaleX;
obj.setAttribute('stroke-width', stroke / scale);
},
onComplete: () => {
//console.log("shrink complete")
obj.classList.remove('zooming');
obj.classList.remove('expanded');
obj.setAttribute('stroke-width', stroke);
}
});
}
static animateCircle(target, callback) {
console.log('ANIMATE CIRCLE', this);
// ** DEBUG OUTPUTS **
let circle = target;
// We need a unique id to ensure correspondence between circle, mask, and maskImage
if (!circle.hasAttribute('id')) {
_CircleIds += 1;
circle.setAttribute('id', '@@' + _CircleIds);
}
let id = circle.getAttribute('id');
TweenLite.set(circle, { transformOrigin: '50% 50%' });
/*if (circle.classList.contains('zooming')) {
console.log("already zooming")
return
}*/
let svgRoot = circle.closest('svg');
let circleGroup = circle.parentNode;
let image = svgRoot.querySelector('image');
let stroke = parseFloat(circleGroup.getAttribute('stroke-width') || 6);
let defs = svgRoot.querySelector('defs');
if (defs == null) {
defs = document.createElementNS(svgRoot, 'defs');
svgRoot.insertBefore(defs, image);
}
// // We need direct children, therefore we cannot use querySelectorAll
let maskImageId = 'maskImage' + id;
let maskImage = svgRoot.getElementById(maskImageId);
if (circle.classList.contains('expanded')) {
if (!circle.classList.contains('zooming')) {
this.shrink(circle, { stroke });
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 in -> shrink")
this.shrink(circle, { stroke });
this.shrink(maskImage, { stroke });
return
}
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 });
}
let maskImages = circleGroup.querySelectorAll('.addedImage');
for (let m of maskImages) {
this.shrink(m, { stroke });
}
Highlight._createSVGMask(svgRoot, image, id);
// TweenLite.set(maskImage, { transformOrigin: `${tx}% ${ty}%` })
this.expand(circle, { stroke, onComplete: callback });
this.expand(maskImage);
return false
}
static openHighlight(target, {
animation = 0.5,
scale = 2,
onExpanded = null
} = {}) {
console.log('Open Highlight!', target);
if (Highlight._isExpanded(target)) {
console.log('Target is already expanded!');
return
} else {
let targetId = target.getAttribute('id');
console.log(targetId, targetId && targetId.startsWith('@@'));
if(targetId && targetId.startsWith('@@')){
let id = targetId.slice(2);
const imageId = '#maskImage'+id;
const parent = target.parentNode;
if(parent != null){
let image = parent.querySelector(imageId);
if(image){
this._bringToFront(image);
}else console.error('Could not find corresponding image element.');
}else console.log('Element was no parent:', target);
}
console.log("_bringToFront");
this._bringToFront(target);
let svgRoot = target.closest('svg');
let image = svgRoot.querySelector('image');
// eslint-disable-next-line no-unused-vars
let [mask, maskImage] = Highlight._getSVGMask(target, { svgRoot, image });
console.log({svgRoot, image, mask, maskImage});
let center = Highlight._calculateCenterRelativeTo(target, image);
TweenLite.set(maskImage, { transformOrigin: `${center.x}% ${center.y}%` });
TweenLite.set(target, { transformOrigin: '50% 50%' });
TweenLite.to([target, maskImage], animation, {
scale,
onComplete: onExpanded
});
target.classList.add('expanded');
console.log({target, maskImage, scale, animation});
console.log(maskImage);
}
return
}
static _bringToFront(target){
const parent = target.parentNode;
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);
}
static _getSVGMask(circle, { svgRoot = null, image = null } = {}) {
const id = this._retrieveId(circle);
const maskId = 'mask' + id;
const maskImageId = 'maskImage' + id;
if (!svgRoot) svgRoot = circle.closest('svg');
let mask = svgRoot.getElementById(maskId);
let maskImage = svgRoot.getElementById(maskImageId);
if (!mask || !maskImage)
[mask, maskImage] = Highlight._createSVGMask(circle, { svgRoot, image, id });
return [mask, maskImage]
}
/**
* Creates an SVG mask for a provided svgElement.
*
* @static
* @param {SVGElement} element - Element that should be masked.
* @param {object} opts - Optional parameters to avoid unnecessary fetching of elements.
* @param {SVGElement} opts.svgRoot - The root <svg> element of the element.
* @param {SVGImageElement} opts.image - The image that is used in the mask.
* @param {number} opts.id - The id of the mask.
* @returns
* @memberof Highlight
*/
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');
if (image == null) image = svgRoot.querySelector('image');
if (id == null) id = this._retrieveId(element);
let svg = 'http://www.w3.org/2000/svg';
let xlink = 'http://www.w3.org/1999/xlink';
let svgGroup = element.parentNode;
let src = image.getAttributeNS(xlink, 'href');
let maskId = 'mask' + id;
let maskImageId = 'maskImage' + id;
let mask = svgRoot.getElementById(maskId);
let maskImage = svgRoot.getElementById(maskImageId);
let defs = svgRoot.querySelector('defs');
if (defs == null) {
defs = document.createElementNS(svgRoot, 'defs');
svgRoot.insertBefore(defs, image);
}
if (mask == null) {
mask = document.createElementNS(svg, 'mask');
mask.setAttribute('id', maskId);
let maskCircle = element.cloneNode(true);
mask.appendChild(maskCircle);
defs.appendChild(mask);
}
let bbox = svgRoot.getElementsByTagName('image')[0].getBBox();
let width = bbox.width;
let height = bbox.height;
if (maskImage == null) {
maskImage = document.createElementNS(svg, 'image');
maskImage.style.pointerEvents = 'none';
maskImage.setAttribute('id', maskImageId);
maskImage.setAttributeNS(xlink, 'href', src);
maskImage.setAttribute('width', width);
maskImage.setAttribute('height', height);
maskImage.setAttribute('class', 'addedImage');
svgGroup.insertBefore(maskImage, element); // image.nextSibling)
TweenLite.set(maskImage, { scale: 1 });
maskImage.style.mask = 'url(#' + maskId + ')';
}
svgGroup.appendChild(maskImage);
// svgGroup.appendChild(element)
return [mask, maskImage]
}
static _calculateCenterRelativeTo(target, image) {
let bbox = image.getBBox();
let width = bbox.width;
let height = bbox.height;
let cx = target.getAttribute('cx');
let cy = target.getAttribute('cy');
return { x: (cx / width) * 100, y: (cy / height) * 100 }
}
static _isExpanded(target) {
return target.classList.contains(Highlight.expandedClass)
}
static _setExpanded(target) {
target.classList.add(Highlight.expandedClass);
}
static _notExpanded(target) {
target.classList.remove(Highlight.expandedClass);
}
static closeHighlight(target, { animation = 0.5 } = {}) {
console.log('Close Highlight');
Highlight._notExpanded(target);
// eslint-disable-next-line no-unused-vars
let [mask, maskImage] = Highlight._getSVGMask(target);
TweenLite.to([target, maskImage], animation, {
scale: 1
});
}
static animate(event) {
if (!_HighlightEnabled)
return
event.stopPropagation();
Highlight.animateCircle(event.target);
return false
}
static _retrieveId(target) {
let id = target.getAttribute('id');
// We need a unique id to ensure correspondence between circle, mask, and maskImage
if (!id) {
_CircleIds += 1;
target.setAttribute('id', '@@' + _CircleIds);
id = _CircleIds;
} else {
id = parseInt(id.substring(2));
}
return id
}
}
Highlight.expandedClass = 'expanded';
/* Needed to ensure that rollup.js includes class definitions and the classes /* Needed to ensure that rollup.js includes class definitions and the classes
are visible inside doctests. are visible inside doctests.
@ -7782,5 +8168,6 @@
window.randomFloat = randomFloat; window.randomFloat = randomFloat;
window.CardWrapper = CardWrapper; window.CardWrapper = CardWrapper;
window.Highlight = Highlight;
}()); }());

View File

@ -20,6 +20,9 @@ import {Cycle, Colors, Elements, Angle, Dates, Points, Polygon, Rect, Sets, Stri
import UITest from './uitest.js' import UITest from './uitest.js'
import {CardWrapper} from './card/wrapper.js' import {CardWrapper} from './card/wrapper.js'
import {Highlight} from './card/highlight.js'
/* Needed to ensure that rollup.js includes class definitions and the classes /* Needed to ensure that rollup.js includes class definitions and the classes
are visible inside doctests. are visible inside doctests.
*/ */
@ -85,3 +88,4 @@ window.randomInt = randomInt
window.randomFloat = randomFloat window.randomFloat = randomFloat
window.CardWrapper = CardWrapper window.CardWrapper = CardWrapper
window.Highlight = Highlight

View File

@ -30,7 +30,7 @@ function round(value) {
* @class Highlight * @class Highlight
* @extends {Object} * @extends {Object}
*/ */
class Highlight extends Object { export class Highlight extends Object {
static disableAnimations() { static disableAnimations() {
_HighlightEnabled = false _HighlightEnabled = false
@ -194,7 +194,7 @@ class Highlight extends Object {
onExpanded = null onExpanded = null
} = {}) { } = {}) {
console.log('Open Highlight!') console.log('Open Highlight!', target)
if (Highlight._isExpanded(target)) { if (Highlight._isExpanded(target)) {
console.log('Target is already expanded!') console.log('Target is already expanded!')
@ -202,7 +202,7 @@ class Highlight extends Object {
} else { } else {
let targetId = target.getAttribute('id') let targetId = target.getAttribute('id')
console.log(targetId) console.log(targetId, targetId && targetId.startsWith('@@'))
if(targetId && targetId.startsWith('@@')){ if(targetId && targetId.startsWith('@@')){
let id = targetId.slice(2) let id = targetId.slice(2)
const imageId = '#maskImage'+id const imageId = '#maskImage'+id
@ -214,7 +214,7 @@ class Highlight extends Object {
}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) }else console.log('Element was no parent:', target)
} }
console.log("_bringToFront")
this._bringToFront(target) this._bringToFront(target)
let svgRoot = target.closest('svg') let svgRoot = target.closest('svg')
@ -222,21 +222,21 @@ class Highlight extends Object {
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
let [mask, maskImage] = Highlight._getSVGMask(target, { svgRoot, image }) let [mask, maskImage] = Highlight._getSVGMask(target, { svgRoot, image })
console.log({svgRoot, image, mask, maskImage})
let center = Highlight._calculateCenterRelativeTo(target, 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.set(target, { transformOrigin: '50% 50%' })
TweenLite.to(target, 2, {
})
TweenLite.to([target, maskImage], animation, { TweenLite.to([target, maskImage], animation, {
scale, scale,
onComplete: onExpanded onComplete: onExpanded
}) })
target.classList.add('expanded') target.classList.add('expanded')
console.log({target, maskImage, scale, animation})
console.log(maskImage)
} }
return return
@ -397,4 +397,4 @@ class Highlight extends Object {
} }
Highlight.expandedClass = 'expanded' Highlight.expandedClass = 'expanded'
window.Highlight = Highlight

View File

@ -46,7 +46,7 @@
<h1 style="color: gray;">A Demo Card with onclick</h1> <h1 style="color: gray;">A Demo Card with onclick</h1>
<figure style="position: relative;"> <figure style="position: relative;">
<img width="75%" src="../examples/women.jpeg"> <img width="75%" src="../examples/women.jpeg">
<svg id="overlayBase" style="position: absolute; left: 0px; top: 0px; width: 100%; height: 100%;" <svg class="overlayBase" style="position: absolute; left: 0px; top: 0px; width: 100%; height: 100%;"
viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet"> viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet">
<circle cx="35" cy="50" r="35" class="highlight" onclick="alert('Highlight clicked')" stroke="white" <circle cx="35" cy="50" r="35" class="highlight" onclick="alert('Highlight clicked')" stroke="white"
fill="transparent" stroke-width="1" /> fill="transparent" stroke-width="1" />
@ -59,15 +59,23 @@
<article id="demoCardWithSelector" <article id="demoCardWithSelector"
style="position: absolute; left: 50%; top: 0%; padding: 16px; margin: 16px; border: 1px solid gray; width: 320px; height: 240px;"> style="position: absolute; left: 50%; top: 0%; padding: 16px; margin: 16px; border: 1px solid gray; width: 320px; height: 240px;">
<h1 style="color: gray;">A Demo Card with selectors</h1> <h1 style="color: gray;">A Demo Card with selectors</h1>
<figure style="position: relative;">
<img width="75%" src="../examples/king.jpeg"> <!-- Grr... The viewBox must reflect the width & height, using 0, 0, 100,
<svg id="overlayBase" style="position: absolute; left: 0px; top: 0px; width: 100%; height: 100%;" 100 leads to blank spaces -->
viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet"> <svg class="overlayBase" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 268 188"
<circle cx="35" cy="50" r="35" class="highlight" stroke="white" fill="transparent" style="width: 180px; height: 100px;" preserveAspectRatio="xMidYMid meet">
stroke-width="1" /> <defs>
</svg> </defs>
</figure> <image xlink:href="../examples/king.jpeg" x="0" y="0" height="188" width="268" />
<p>Lorem ipsum <a class="link" href="javascript:alert('Link clicked via href')" style="color:blue;">dolor</a> sit <g>
<circle cx="50%" cy="50%" r="25%" class="highlight" stroke="white" fill="transparent"
stroke-width="1%" />
</g>
</svg>
<p>Lorem ipsum <a class="link" href="javascript:alert('Link clicked via href')"
style="color:blue;">dolor</a> sit
amet, amet,
consetetur sadipscing elitr.</p> consetetur sadipscing elitr.</p>
</article> </article>
@ -84,8 +92,17 @@
const wrapper2 = new CardWrapper(demoCardWithSelector) const wrapper2 = new CardWrapper(demoCardWithSelector)
wrapper2.handleClicksAsTaps() wrapper2.handleClicksAsTaps()
wrapper2.onTap('.highlight', event => { wrapper2.onTap('.highlight', event => {
alert('.highlight clicked')
Highlight.openHighlight(event.target, {
onExpanded: () => {
console.log("onExpanded", event.target)
}
})
}) })
// Highlight.animate(event)
wrapper2.onTap('.link', event => { wrapper2.onTap('.link', event => {
alert('.link clicked') alert('.link clicked')
}) })
@ -94,7 +111,8 @@
<h2> <h2>
Using Cards within Scatters Using Cards within Scatters
</h2> </h2>
<p>Cards can be used within scatters. Since the <code>CardWrapper</code> implements the <code>ITapDelegate</code> protocol they can simply <p>Cards can be used within scatters. Since the <code>CardWrapper</code> implements the <code>ITapDelegate</code>
protocol they can simply
be attached to a DOMScatter object. See the <a href="../scatter.html">Scatter Doctest</a>. be attached to a DOMScatter object. See the <a href="../scatter.html">Scatter Doctest</a>.
</p> </p>
<div class="interactive grayBorder" style="position: relative;"> <div class="interactive grayBorder" style="position: relative;">
@ -104,6 +122,7 @@
References References
</h2> </h2>
<ul> <ul>
<li><a href="https://uicookies.com/css-card-design/">30 Visually Stunning CSS Cards Inspirations For Every Type Of Websites 2019</a></li> <li><a href="https://uicookies.com/css-card-design/">30 Visually Stunning CSS Cards Inspirations For Every Type
Of Websites 2019</a></li>
</ul> </ul>
</body> </body>

View File

@ -17,11 +17,6 @@ export class CardWrapper extends Object {
handleClicks() { handleClicks() {
this.domNode.addEventListener('click', event => { this.domNode.addEventListener('click', event => {
console.log('handleClicks', event.isTrusted)
/* Currently we cannot send synthesized click events to SVG elements without unwanted side effects.
Therefore we make an exception and let the original click event through.
*/
if (event.isTrusted) { if (event.isTrusted) {
Events.stop(event) Events.stop(event)
if (this.triggerSVGClicks && this.isSVGNode(event.target)) { if (this.triggerSVGClicks && this.isSVGNode(event.target)) {
@ -34,10 +29,6 @@ export class CardWrapper extends Object {
handleClicksAsTaps() { handleClicksAsTaps() {
this.domNode.addEventListener('click', event => { this.domNode.addEventListener('click', event => {
console.log('handleClicksAsTaps', event.isTrusted)
/* Currently we cannot send synthesized click events to SVG elements without unwanted side effects.
Therefore we make an exception and let the original click event through.
*/
if (event.isTrusted) { if (event.isTrusted) {
Events.stop(event) Events.stop(event)
@ -62,9 +53,7 @@ export class CardWrapper extends Object {
if (this.tapNodes.has(node)) if (this.tapNodes.has(node))
return true return true
for (let [selector, handler] of this.tapHandler.entries()) { for (let [selector, handler] of this.tapHandler.entries()) {
console.log("selector", this.domNode.querySelectorAll(selector))
for (let obj of this.domNode.querySelectorAll(selector)) { for (let obj of this.domNode.querySelectorAll(selector)) {
console.log("selector2", node, obj)
if (node == obj) { if (node == obj) {
return true return true
} }
@ -127,7 +116,6 @@ export class CardWrapper extends Object {
/* https://stackoverflow.com/questions/49564905/is-it-possible-to-use-click-function-on-svg-tags-i-tried-element-click-on-a /* https://stackoverflow.com/questions/49564905/is-it-possible-to-use-click-function-on-svg-tags-i-tried-element-click-on-a
proposes the dispatchEvent solution. But this leads to problems in flippable.html hiding the back page. proposes the dispatchEvent solution. But this leads to problems in flippable.html hiding the back page.
Therefore we use the original click event (see constructor). */ Therefore we use the original click event (see constructor). */
console.log("simulateClick", node, node.ownerSVGElement)
if (this.isSVGNode(node)) { if (this.isSVGNode(node)) {
if (this.triggerSVGClicks) { if (this.triggerSVGClicks) {
let click = new Event('click') let click = new Event('click')
@ -160,7 +148,6 @@ export class CardWrapper extends Object {
} }
tap(event, calledBy='unknown') { tap(event, calledBy='unknown') {
console.log("tap", calledBy, event.alreadyTapped, event)
if (event.isTrusted) { if (event.isTrusted) {
let node = this.nearestActive(event) let node = this.nearestActive(event)
this.nodeTapped(node, event) this.nodeTapped(node, event)
@ -184,4 +171,3 @@ export class CardWrapper extends Object {
} }
} }
window.CardWrapper = CardWrapper