Merge branch 'master' of gitea.iwm-tuebingen.de:IWMBrowser/iwmlib
# Conflicts: # dist/iwmlib.js
This commit is contained in:
		
						commit
						4009ddd422
					
				
							
								
								
									
										169
									
								
								dist/iwmlib.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										169
									
								
								dist/iwmlib.js
									
									
									
									
										vendored
									
									
								
							@ -987,6 +987,13 @@
 | 
				
			|||||||
            return Math.sqrt(dx * dx + dy * dy)
 | 
					            return Math.sqrt(dx * dx + dy * dy)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Distance == 0.0 indicates an inside relation.
 | 
				
			||||||
 | 
					        static distanceToRect(p, r) {
 | 
				
			||||||
 | 
					            var cx = Math.max(Math.min(p.x, r.x + r.width), r.x);
 | 
				
			||||||
 | 
					            var cy = Math.max(Math.min(p.y, r.y + r.height), r.y);
 | 
				
			||||||
 | 
					            return Math.sqrt((p.x - cx) * (p.x - cx) + (p.y - cy) * (p.y - cy))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        static fromPageToNode(element, p) {
 | 
					        static fromPageToNode(element, p) {
 | 
				
			||||||
            //    if (window.webkitConvertPointFromPageToNode) {
 | 
					            //    if (window.webkitConvertPointFromPageToNode) {
 | 
				
			||||||
            //             return window.webkitConvertPointFromPageToNode(element,
 | 
					            //             return window.webkitConvertPointFromPageToNode(element,
 | 
				
			||||||
@ -5044,7 +5051,7 @@
 | 
				
			|||||||
                context.stroke();
 | 
					                context.stroke();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            requestAnimationFrame(dt => {
 | 
					            requestAnimationFrame(dt => {
 | 
				
			||||||
                this.showTouches(dt);
 | 
					                this.showTouches(dt, canvas);
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -5155,7 +5162,8 @@
 | 
				
			|||||||
                width = null, // required
 | 
					                width = null, // required
 | 
				
			||||||
                height = null,  // required
 | 
					                height = null,  // required
 | 
				
			||||||
                resizable = false,
 | 
					                resizable = false,
 | 
				
			||||||
                simulateClick = false,
 | 
					                clickOnTap = false,
 | 
				
			||||||
 | 
					                allowClickDistance = 44,
 | 
				
			||||||
                verbose = true,
 | 
					                verbose = true,
 | 
				
			||||||
                onResize = null,
 | 
					                onResize = null,
 | 
				
			||||||
                touchAction = 'none',
 | 
					                touchAction = 'none',
 | 
				
			||||||
@ -5206,7 +5214,7 @@
 | 
				
			|||||||
            this.height = height;
 | 
					            this.height = height;
 | 
				
			||||||
            this.throwVisibility = Math.min(width, height, throwVisibility);
 | 
					            this.throwVisibility = Math.min(width, height, throwVisibility);
 | 
				
			||||||
            this.container = container;
 | 
					            this.container = container;
 | 
				
			||||||
            this.simulateClick = simulateClick;
 | 
					            this.clickOnTap = clickOnTap;
 | 
				
			||||||
            this.scale = startScale;
 | 
					            this.scale = startScale;
 | 
				
			||||||
            this.rotationDegrees = this.startRotationDegrees;
 | 
					            this.rotationDegrees = this.startRotationDegrees;
 | 
				
			||||||
            this.transformOrigin = transformOrigin;
 | 
					            this.transformOrigin = transformOrigin;
 | 
				
			||||||
@ -5219,7 +5227,8 @@
 | 
				
			|||||||
                rotation: this.startRotationDegrees,
 | 
					                rotation: this.startRotationDegrees,
 | 
				
			||||||
                transformOrigin: transformOrigin
 | 
					                transformOrigin: transformOrigin
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					            this.tapNodes = new Map();
 | 
				
			||||||
 | 
					            this.allowClickDistance = allowClickDistance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // For tweenlite we need initial values in _gsTransform
 | 
					            // For tweenlite we need initial values in _gsTransform
 | 
				
			||||||
            TweenLite.set(element, this.initialValues);
 | 
					            TweenLite.set(element, this.initialValues);
 | 
				
			||||||
@ -5412,16 +5421,99 @@
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        onTap(event, interaction, point) {
 | 
					        onTap(event, interaction, point) {
 | 
				
			||||||
            if (this.simulateClick) {
 | 
					            
 | 
				
			||||||
                let p = Points.fromPageToNode(this.element, point);
 | 
					            if (this.clickOnTap) {
 | 
				
			||||||
                let element = document.elementFromPoint(p.x, p.y);
 | 
					                let directNode = document.elementFromPoint(point.x, point.y);
 | 
				
			||||||
                if (element != null) {
 | 
					                let nearestNode = this.nearestClickable(event);
 | 
				
			||||||
                    console.log('tap simulates click');
 | 
					
 | 
				
			||||||
                    element.click();
 | 
					                console.log("onTap", directNode, nearestNode.tagName);
 | 
				
			||||||
 | 
					                if (directNode != null && this.isClickable(directNode)) {
 | 
				
			||||||
 | 
					                    directNode.click();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else {
 | 
				
			||||||
 | 
					                    if (nearestNode.tagName == 'svg' && this.isClickable(nearestNode)) {
 | 
				
			||||||
 | 
					                        let handler = this.tapNodes.get(nearestNode);
 | 
				
			||||||
 | 
					                        console.log("Clicking beneath SVG: to be done", handler);
 | 
				
			||||||
 | 
					                        Events.stop(event);
 | 
				
			||||||
 | 
					                        //nearestNode.click()
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * Adds a click or tap behavior to the node. Uses
 | 
				
			||||||
 | 
					         * either the scatter clickOnTap version which requires click handlers
 | 
				
			||||||
 | 
					         * or uses the hammer.js driven tap handler.
 | 
				
			||||||
 | 
					         *
 | 
				
			||||||
 | 
					         * @param {*} node
 | 
				
			||||||
 | 
					         * @param {*} handler
 | 
				
			||||||
 | 
					         * @memberof DOMScatter
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        addTapListener(node, handler) {
 | 
				
			||||||
 | 
					            if (this.clickOnTap) {
 | 
				
			||||||
 | 
					                node.addEventListener('click', handler);
 | 
				
			||||||
 | 
					                this.tapNodes.set(node, handler);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                InteractionMapper$1.on('tap', node, handler);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        isClickable(node) {
 | 
				
			||||||
 | 
					            if (node.tagName == 'A')
 | 
				
			||||||
 | 
					                return true
 | 
				
			||||||
 | 
					            if (this.tapNodes.has(node)) 
 | 
				
			||||||
 | 
					                return true
 | 
				
			||||||
 | 
					            return false
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * Returns an array of all clickable nodes.
 | 
				
			||||||
 | 
					         * Unfortunately we cannot search for all nodes with an attached 'click' event listener
 | 
				
			||||||
 | 
					         * 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 clickables
 | 
				
			||||||
 | 
					         * II. Objects that have been attached a click handler by the scatter itself via 
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        clickableNodes() {
 | 
				
			||||||
 | 
					            let result = [];
 | 
				
			||||||
 | 
					            for (let node of this.element.querySelectorAll("*")) {
 | 
				
			||||||
 | 
					                if (this.isClickable(node))
 | 
				
			||||||
 | 
					                    result.push(node);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return result
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        nearestClickable(event) {
 | 
				
			||||||
 | 
					            let element = this.element;
 | 
				
			||||||
 | 
					            let clickables = this.clickableNodes();
 | 
				
			||||||
 | 
					            let globalClick = (event.center) ? event.center : { x: event.x, y: event.y };
 | 
				
			||||||
 | 
					            let localClick = Points.fromPageToNode(element, globalClick);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let clickRects = clickables.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 distances = [];
 | 
				
			||||||
 | 
					            clickRects.forEach(rect => {
 | 
				
			||||||
 | 
					                let distance = Points.distanceToRect(localClick, rect);
 | 
				
			||||||
 | 
					                distances.push(parseInt(distance));
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let closestClickIndex = distances.indexOf(Math.min(...distances));
 | 
				
			||||||
 | 
					            let closestClickable = clickables[closestClickIndex];
 | 
				
			||||||
 | 
					            if (distances[closestClickIndex] < this.allowClickDistance) {
 | 
				
			||||||
 | 
					                console.log("found closest clickables", closestClickable);
 | 
				
			||||||
 | 
					                return closestClickable
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return null
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        isDescendant(parent, child) {
 | 
					        isDescendant(parent, child) {
 | 
				
			||||||
            let node = child.parentNode;
 | 
					            let node = child.parentNode;
 | 
				
			||||||
            while (node != null) {
 | 
					            while (node != null) {
 | 
				
			||||||
@ -5573,12 +5665,12 @@
 | 
				
			|||||||
            this.maxHeight = maxHeight != null ? maxHeight : window.innerHeight;
 | 
					            this.maxHeight = maxHeight != null ? maxHeight : window.innerHeight;
 | 
				
			||||||
            this.addedNode = null;
 | 
					            this.addedNode = null;
 | 
				
			||||||
            console.log({
 | 
					            console.log({
 | 
				
			||||||
             
 | 
					
 | 
				
			||||||
                width,
 | 
					                width,
 | 
				
			||||||
                height,
 | 
					                height,
 | 
				
			||||||
                maxWidth,
 | 
					                maxWidth,
 | 
				
			||||||
                maxHeight,
 | 
					                maxHeight,
 | 
				
			||||||
               
 | 
					
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -5741,6 +5833,7 @@
 | 
				
			|||||||
                translatable = true,
 | 
					                translatable = true,
 | 
				
			||||||
                scalable = true,
 | 
					                scalable = true,
 | 
				
			||||||
                rotatable = true,
 | 
					                rotatable = true,
 | 
				
			||||||
 | 
					                clickOnTap = false,
 | 
				
			||||||
                onFront = null,
 | 
					                onFront = null,
 | 
				
			||||||
                onBack = null,
 | 
					                onBack = null,
 | 
				
			||||||
                onClose = null,
 | 
					                onClose = null,
 | 
				
			||||||
@ -5760,6 +5853,7 @@
 | 
				
			|||||||
            this.translatable = translatable;
 | 
					            this.translatable = translatable;
 | 
				
			||||||
            this.scalable = scalable;
 | 
					            this.scalable = scalable;
 | 
				
			||||||
            this.rotatable = rotatable;
 | 
					            this.rotatable = rotatable;
 | 
				
			||||||
 | 
					            this.clickOnTap = clickOnTap;
 | 
				
			||||||
            this.onFrontFlipped = onFront;
 | 
					            this.onFrontFlipped = onFront;
 | 
				
			||||||
            this.onBackFlipped = onBack;
 | 
					            this.onBackFlipped = onBack;
 | 
				
			||||||
            this.onClose = onClose;
 | 
					            this.onClose = onClose;
 | 
				
			||||||
@ -5814,7 +5908,8 @@
 | 
				
			|||||||
                        translatable: this.translatable,
 | 
					                        translatable: this.translatable,
 | 
				
			||||||
                        scalable: this.scalable,
 | 
					                        scalable: this.scalable,
 | 
				
			||||||
                        rotatable: this.rotatable,
 | 
					                        rotatable: this.rotatable,
 | 
				
			||||||
                        overdoScaling: this.overdoScaling
 | 
					                        overdoScaling: this.overdoScaling,
 | 
				
			||||||
 | 
					                        clickOnTap: this.clickOnTap
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -5823,7 +5918,6 @@
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (this.closeOnMinScale) {
 | 
					                if (this.closeOnMinScale) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
                    const removeOnMinScale = function () {
 | 
					                    const removeOnMinScale = function () {
 | 
				
			||||||
                        if (scatter.scale <= scatter.minScale) {
 | 
					                        if (scatter.scale <= scatter.minScale) {
 | 
				
			||||||
                            this.flippable.close();
 | 
					                            this.flippable.close();
 | 
				
			||||||
@ -5838,11 +5932,7 @@
 | 
				
			|||||||
                                scatter.onTransform.splice(callbackIdx, 1);
 | 
					                                scatter.onTransform.splice(callbackIdx, 1);
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
                    }.bind(this);
 | 
					                    }.bind(this);
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    scatter.addTransformEventCallback(removeOnMinScale);
 | 
					                    scatter.addTransformEventCallback(removeOnMinScale);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -5878,8 +5968,11 @@
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        start({ targetCenter = null } = {}) {
 | 
					        start({ targetCenter = null } = {}) {
 | 
				
			||||||
            console.log('DOMFlip.start', targetCenter);
 | 
					            console.log("DOMFlip.start", targetCenter);
 | 
				
			||||||
            if (this.preloadBack) this.flippable.start({ duration: this.flipDuration, targetCenter });
 | 
					            if (this.preloadBack) {
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                this.flippable.start({ duration: this.flipDuration, targetCenter });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            else {
 | 
					            else {
 | 
				
			||||||
                let back = this.cardWrapper.querySelector('.back');
 | 
					                let back = this.cardWrapper.querySelector('.back');
 | 
				
			||||||
                let flippable = this.flippable;
 | 
					                let flippable = this.flippable;
 | 
				
			||||||
@ -5931,7 +6024,7 @@
 | 
				
			|||||||
            this.flipDuration = flip.flipDuration;
 | 
					            this.flipDuration = flip.flipDuration;
 | 
				
			||||||
            this.fadeDuration = flip.fadeDuration;
 | 
					            this.fadeDuration = flip.fadeDuration;
 | 
				
			||||||
            scatter.addTransformEventCallback(this.scatterTransformed.bind(this));
 | 
					            scatter.addTransformEventCallback(this.scatterTransformed.bind(this));
 | 
				
			||||||
            console.log('lib.DOMFlippable', 5000);
 | 
					
 | 
				
			||||||
            TweenLite.set(this.element, { perspective: 5000 });
 | 
					            TweenLite.set(this.element, { perspective: 5000 });
 | 
				
			||||||
            TweenLite.set(this.card, { transformStyle: 'preserve-3d' });
 | 
					            TweenLite.set(this.card, { transformStyle: 'preserve-3d' });
 | 
				
			||||||
            TweenLite.set(this.back, { rotationY: -180 });
 | 
					            TweenLite.set(this.back, { rotationY: -180 });
 | 
				
			||||||
@ -5944,15 +6037,24 @@
 | 
				
			|||||||
            this.backBtn = element.querySelector('.backBtn');
 | 
					            this.backBtn = element.querySelector('.backBtn');
 | 
				
			||||||
            this.closeBtn = element.querySelector('.closeBtn');
 | 
					            this.closeBtn = element.querySelector('.closeBtn');
 | 
				
			||||||
            /* Buttons are not guaranteed to exist. */
 | 
					            /* Buttons are not guaranteed to exist. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (this.infoBtn) {
 | 
					            if (this.infoBtn) {
 | 
				
			||||||
                InteractionMapper$1.on('tap', this.infoBtn, event => this.flip.start());
 | 
					                scatter.addTapListener(this.infoBtn, event => {
 | 
				
			||||||
 | 
					                    console.log("within click handler", this);
 | 
				
			||||||
 | 
					                    this.flip.start();
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
                this.enable(this.infoBtn);
 | 
					                this.enable(this.infoBtn);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (this.backBtn) {
 | 
					            if (this.backBtn) {
 | 
				
			||||||
                InteractionMapper$1.on('tap', this.backBtn, event => this.start());
 | 
					                scatter.addTapListener(this.backBtn, event => {
 | 
				
			||||||
 | 
					                    console.log("within click handler", this);
 | 
				
			||||||
 | 
					                    this.start();
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (this.closeBtn) {
 | 
					            if (this.closeBtn) {
 | 
				
			||||||
                InteractionMapper$1.on('tap', this.closeBtn, event => this.close());
 | 
					                scatter.addTapListener(this.closeBtn, event => {
 | 
				
			||||||
 | 
					                    this.close();
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
                this.enable(this.closeBtn);
 | 
					                this.enable(this.closeBtn);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            this.scaleButtons();
 | 
					            this.scaleButtons();
 | 
				
			||||||
@ -6002,18 +6104,6 @@
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        scaleButtons() {
 | 
					        scaleButtons() {
 | 
				
			||||||
            //This also works for svgs.
 | 
					 | 
				
			||||||
            // if (this.infoBtn)
 | 
					 | 
				
			||||||
            //     this.infoBtn.style.transform = "scale(" + this.buttonScale + ")"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // if (this.backBtn)
 | 
					 | 
				
			||||||
            //     this.backBtn.style.transform = "scale(" + this.buttonScale + ")"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // if (this.closeBtn)
 | 
					 | 
				
			||||||
            //     this.closeBtn.style.transform = "scale(" + this.buttonScale + ")"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            console.log(this.buttonScale);
 | 
					 | 
				
			||||||
            //// This did not work with svgs!
 | 
					 | 
				
			||||||
            TweenLite.set([this.infoBtn, this.backBtn, this.closeBtn], {
 | 
					            TweenLite.set([this.infoBtn, this.backBtn, this.closeBtn], {
 | 
				
			||||||
                scale: this.buttonScale
 | 
					                scale: this.buttonScale
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
@ -6026,6 +6116,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        clickInfo() {
 | 
					        clickInfo() {
 | 
				
			||||||
            this.bringToFront();
 | 
					            this.bringToFront();
 | 
				
			||||||
 | 
					            console.log("clickInfo");
 | 
				
			||||||
            this.infoBtn.click();
 | 
					            this.infoBtn.click();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -6067,8 +6158,6 @@
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        enable(button) {
 | 
					        enable(button) {
 | 
				
			||||||
            this.show(button, this.fadeDuration);
 | 
					            this.show(button, this.fadeDuration);
 | 
				
			||||||
            if (button) {
 | 
					            if (button) {
 | 
				
			||||||
@ -6078,9 +6167,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        disable(button) {
 | 
					        disable(button) {
 | 
				
			||||||
            this.hide(button, this.fadeDuration);
 | 
					            this.hide(button, this.fadeDuration);
 | 
				
			||||||
            if (button) {
 | 
					 | 
				
			||||||
                TweenLite.set(button, { pointerEvents: 'none' });
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        start({ targetCenter = null } = {}) {
 | 
					        start({ targetCenter = null } = {}) {
 | 
				
			||||||
@ -6124,7 +6210,6 @@
 | 
				
			|||||||
            let x = this.flipped ? xx : this.startX;
 | 
					            let x = this.flipped ? xx : this.startX;
 | 
				
			||||||
            let y = this.flipped ? yy : this.startY;
 | 
					            let y = this.flipped ? yy : this.startY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            console.log("DOMFlippable.start", this.flipped, targetCenter, x, y, this.saved);
 | 
					 | 
				
			||||||
            let onUpdate = this.onUpdate !== null ? () => this.onUpdate(this) : null;
 | 
					            let onUpdate = this.onUpdate !== null ? () => this.onUpdate(this) : null;
 | 
				
			||||||
            console.log(this.flipDuration);
 | 
					            console.log(this.flipDuration);
 | 
				
			||||||
            TweenLite.to(this.card, this.flipDuration, {
 | 
					            TweenLite.to(this.card, this.flipDuration, {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										167
									
								
								dist/iwmlib.pixi.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										167
									
								
								dist/iwmlib.pixi.js
									
									
									
									
										vendored
									
									
								
							@ -3263,6 +3263,13 @@
 | 
				
			|||||||
            return Math.sqrt(dx * dx + dy * dy)
 | 
					            return Math.sqrt(dx * dx + dy * dy)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Distance == 0.0 indicates an inside relation.
 | 
				
			||||||
 | 
					        static distanceToRect(p, r) {
 | 
				
			||||||
 | 
					            var cx = Math.max(Math.min(p.x, r.x + r.width), r.x);
 | 
				
			||||||
 | 
					            var cy = Math.max(Math.min(p.y, r.y + r.height), r.y);
 | 
				
			||||||
 | 
					            return Math.sqrt((p.x - cx) * (p.x - cx) + (p.y - cy) * (p.y - cy))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        static fromPageToNode(element, p) {
 | 
					        static fromPageToNode(element, p) {
 | 
				
			||||||
            //    if (window.webkitConvertPointFromPageToNode) {
 | 
					            //    if (window.webkitConvertPointFromPageToNode) {
 | 
				
			||||||
            //             return window.webkitConvertPointFromPageToNode(element,
 | 
					            //             return window.webkitConvertPointFromPageToNode(element,
 | 
				
			||||||
@ -6917,7 +6924,8 @@
 | 
				
			|||||||
                width = null, // required
 | 
					                width = null, // required
 | 
				
			||||||
                height = null,  // required
 | 
					                height = null,  // required
 | 
				
			||||||
                resizable = false,
 | 
					                resizable = false,
 | 
				
			||||||
                simulateClick = false,
 | 
					                clickOnTap = false,
 | 
				
			||||||
 | 
					                allowClickDistance = 44,
 | 
				
			||||||
                verbose = true,
 | 
					                verbose = true,
 | 
				
			||||||
                onResize = null,
 | 
					                onResize = null,
 | 
				
			||||||
                touchAction = 'none',
 | 
					                touchAction = 'none',
 | 
				
			||||||
@ -6968,7 +6976,7 @@
 | 
				
			|||||||
            this.height = height;
 | 
					            this.height = height;
 | 
				
			||||||
            this.throwVisibility = Math.min(width, height, throwVisibility);
 | 
					            this.throwVisibility = Math.min(width, height, throwVisibility);
 | 
				
			||||||
            this.container = container;
 | 
					            this.container = container;
 | 
				
			||||||
            this.simulateClick = simulateClick;
 | 
					            this.clickOnTap = clickOnTap;
 | 
				
			||||||
            this.scale = startScale;
 | 
					            this.scale = startScale;
 | 
				
			||||||
            this.rotationDegrees = this.startRotationDegrees;
 | 
					            this.rotationDegrees = this.startRotationDegrees;
 | 
				
			||||||
            this.transformOrigin = transformOrigin;
 | 
					            this.transformOrigin = transformOrigin;
 | 
				
			||||||
@ -6981,7 +6989,8 @@
 | 
				
			|||||||
                rotation: this.startRotationDegrees,
 | 
					                rotation: this.startRotationDegrees,
 | 
				
			||||||
                transformOrigin: transformOrigin
 | 
					                transformOrigin: transformOrigin
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					            this.tapNodes = new Map();
 | 
				
			||||||
 | 
					            this.allowClickDistance = allowClickDistance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // For tweenlite we need initial values in _gsTransform
 | 
					            // For tweenlite we need initial values in _gsTransform
 | 
				
			||||||
            TweenLite.set(element, this.initialValues);
 | 
					            TweenLite.set(element, this.initialValues);
 | 
				
			||||||
@ -7174,16 +7183,99 @@
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        onTap(event, interaction, point) {
 | 
					        onTap(event, interaction, point) {
 | 
				
			||||||
            if (this.simulateClick) {
 | 
					            
 | 
				
			||||||
                let p = Points.fromPageToNode(this.element, point);
 | 
					            if (this.clickOnTap) {
 | 
				
			||||||
                let element = document.elementFromPoint(p.x, p.y);
 | 
					                let directNode = document.elementFromPoint(point.x, point.y);
 | 
				
			||||||
                if (element != null) {
 | 
					                let nearestNode = this.nearestClickable(event);
 | 
				
			||||||
                    console.log('tap simulates click');
 | 
					
 | 
				
			||||||
                    element.click();
 | 
					                console.log("onTap", directNode, nearestNode.tagName);
 | 
				
			||||||
 | 
					                if (directNode != null && this.isClickable(directNode)) {
 | 
				
			||||||
 | 
					                    directNode.click();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else {
 | 
				
			||||||
 | 
					                    if (nearestNode.tagName == 'svg' && this.isClickable(nearestNode)) {
 | 
				
			||||||
 | 
					                        let handler = this.tapNodes.get(nearestNode);
 | 
				
			||||||
 | 
					                        console.log("Clicking beneath SVG: to be done", handler);
 | 
				
			||||||
 | 
					                        Events$1.stop(event);
 | 
				
			||||||
 | 
					                        //nearestNode.click()
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * Adds a click or tap behavior to the node. Uses
 | 
				
			||||||
 | 
					         * either the scatter clickOnTap version which requires click handlers
 | 
				
			||||||
 | 
					         * or uses the hammer.js driven tap handler.
 | 
				
			||||||
 | 
					         *
 | 
				
			||||||
 | 
					         * @param {*} node
 | 
				
			||||||
 | 
					         * @param {*} handler
 | 
				
			||||||
 | 
					         * @memberof DOMScatter
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        addTapListener(node, handler) {
 | 
				
			||||||
 | 
					            if (this.clickOnTap) {
 | 
				
			||||||
 | 
					                node.addEventListener('click', handler);
 | 
				
			||||||
 | 
					                this.tapNodes.set(node, handler);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                InteractionMapper$1.on('tap', node, handler);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        isClickable(node) {
 | 
				
			||||||
 | 
					            if (node.tagName == 'A')
 | 
				
			||||||
 | 
					                return true
 | 
				
			||||||
 | 
					            if (this.tapNodes.has(node)) 
 | 
				
			||||||
 | 
					                return true
 | 
				
			||||||
 | 
					            return false
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * Returns an array of all clickable nodes.
 | 
				
			||||||
 | 
					         * Unfortunately we cannot search for all nodes with an attached 'click' event listener
 | 
				
			||||||
 | 
					         * 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 clickables
 | 
				
			||||||
 | 
					         * II. Objects that have been attached a click handler by the scatter itself via 
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        clickableNodes() {
 | 
				
			||||||
 | 
					            let result = [];
 | 
				
			||||||
 | 
					            for (let node of this.element.querySelectorAll("*")) {
 | 
				
			||||||
 | 
					                if (this.isClickable(node))
 | 
				
			||||||
 | 
					                    result.push(node);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return result
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        nearestClickable(event) {
 | 
				
			||||||
 | 
					            let element = this.element;
 | 
				
			||||||
 | 
					            let clickables = this.clickableNodes();
 | 
				
			||||||
 | 
					            let globalClick = (event.center) ? event.center : { x: event.x, y: event.y };
 | 
				
			||||||
 | 
					            let localClick = Points.fromPageToNode(element, globalClick);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let clickRects = clickables.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 distances = [];
 | 
				
			||||||
 | 
					            clickRects.forEach(rect => {
 | 
				
			||||||
 | 
					                let distance = Points.distanceToRect(localClick, rect);
 | 
				
			||||||
 | 
					                distances.push(parseInt(distance));
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let closestClickIndex = distances.indexOf(Math.min(...distances));
 | 
				
			||||||
 | 
					            let closestClickable = clickables[closestClickIndex];
 | 
				
			||||||
 | 
					            if (distances[closestClickIndex] < this.allowClickDistance) {
 | 
				
			||||||
 | 
					                console.log("found closest clickables", closestClickable);
 | 
				
			||||||
 | 
					                return closestClickable
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return null
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        isDescendant(parent, child) {
 | 
					        isDescendant(parent, child) {
 | 
				
			||||||
            let node = child.parentNode;
 | 
					            let node = child.parentNode;
 | 
				
			||||||
            while (node != null) {
 | 
					            while (node != null) {
 | 
				
			||||||
@ -7335,12 +7427,12 @@
 | 
				
			|||||||
            this.maxHeight = maxHeight != null ? maxHeight : window.innerHeight;
 | 
					            this.maxHeight = maxHeight != null ? maxHeight : window.innerHeight;
 | 
				
			||||||
            this.addedNode = null;
 | 
					            this.addedNode = null;
 | 
				
			||||||
            console.log({
 | 
					            console.log({
 | 
				
			||||||
             
 | 
					
 | 
				
			||||||
                width,
 | 
					                width,
 | 
				
			||||||
                height,
 | 
					                height,
 | 
				
			||||||
                maxWidth,
 | 
					                maxWidth,
 | 
				
			||||||
                maxHeight,
 | 
					                maxHeight,
 | 
				
			||||||
               
 | 
					
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -7369,6 +7461,7 @@
 | 
				
			|||||||
                translatable = true,
 | 
					                translatable = true,
 | 
				
			||||||
                scalable = true,
 | 
					                scalable = true,
 | 
				
			||||||
                rotatable = true,
 | 
					                rotatable = true,
 | 
				
			||||||
 | 
					                clickOnTap = false,
 | 
				
			||||||
                onFront = null,
 | 
					                onFront = null,
 | 
				
			||||||
                onBack = null,
 | 
					                onBack = null,
 | 
				
			||||||
                onClose = null,
 | 
					                onClose = null,
 | 
				
			||||||
@ -7388,6 +7481,7 @@
 | 
				
			|||||||
            this.translatable = translatable;
 | 
					            this.translatable = translatable;
 | 
				
			||||||
            this.scalable = scalable;
 | 
					            this.scalable = scalable;
 | 
				
			||||||
            this.rotatable = rotatable;
 | 
					            this.rotatable = rotatable;
 | 
				
			||||||
 | 
					            this.clickOnTap = clickOnTap;
 | 
				
			||||||
            this.onFrontFlipped = onFront;
 | 
					            this.onFrontFlipped = onFront;
 | 
				
			||||||
            this.onBackFlipped = onBack;
 | 
					            this.onBackFlipped = onBack;
 | 
				
			||||||
            this.onClose = onClose;
 | 
					            this.onClose = onClose;
 | 
				
			||||||
@ -7442,7 +7536,8 @@
 | 
				
			|||||||
                        translatable: this.translatable,
 | 
					                        translatable: this.translatable,
 | 
				
			||||||
                        scalable: this.scalable,
 | 
					                        scalable: this.scalable,
 | 
				
			||||||
                        rotatable: this.rotatable,
 | 
					                        rotatable: this.rotatable,
 | 
				
			||||||
                        overdoScaling: this.overdoScaling
 | 
					                        overdoScaling: this.overdoScaling,
 | 
				
			||||||
 | 
					                        clickOnTap: this.clickOnTap
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -7451,7 +7546,6 @@
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (this.closeOnMinScale) {
 | 
					                if (this.closeOnMinScale) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
                    const removeOnMinScale = function () {
 | 
					                    const removeOnMinScale = function () {
 | 
				
			||||||
                        if (scatter.scale <= scatter.minScale) {
 | 
					                        if (scatter.scale <= scatter.minScale) {
 | 
				
			||||||
                            this.flippable.close();
 | 
					                            this.flippable.close();
 | 
				
			||||||
@ -7466,11 +7560,7 @@
 | 
				
			|||||||
                                scatter.onTransform.splice(callbackIdx, 1);
 | 
					                                scatter.onTransform.splice(callbackIdx, 1);
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
                    }.bind(this);
 | 
					                    }.bind(this);
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    scatter.addTransformEventCallback(removeOnMinScale);
 | 
					                    scatter.addTransformEventCallback(removeOnMinScale);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -7506,8 +7596,11 @@
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        start({ targetCenter = null } = {}) {
 | 
					        start({ targetCenter = null } = {}) {
 | 
				
			||||||
            console.log('DOMFlip.start', targetCenter);
 | 
					            console.log("DOMFlip.start", targetCenter);
 | 
				
			||||||
            if (this.preloadBack) this.flippable.start({ duration: this.flipDuration, targetCenter });
 | 
					            if (this.preloadBack) {
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                this.flippable.start({ duration: this.flipDuration, targetCenter });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            else {
 | 
					            else {
 | 
				
			||||||
                let back = this.cardWrapper.querySelector('.back');
 | 
					                let back = this.cardWrapper.querySelector('.back');
 | 
				
			||||||
                let flippable = this.flippable;
 | 
					                let flippable = this.flippable;
 | 
				
			||||||
@ -7559,7 +7652,7 @@
 | 
				
			|||||||
            this.flipDuration = flip.flipDuration;
 | 
					            this.flipDuration = flip.flipDuration;
 | 
				
			||||||
            this.fadeDuration = flip.fadeDuration;
 | 
					            this.fadeDuration = flip.fadeDuration;
 | 
				
			||||||
            scatter.addTransformEventCallback(this.scatterTransformed.bind(this));
 | 
					            scatter.addTransformEventCallback(this.scatterTransformed.bind(this));
 | 
				
			||||||
            console.log('lib.DOMFlippable', 5000);
 | 
					
 | 
				
			||||||
            TweenLite.set(this.element, { perspective: 5000 });
 | 
					            TweenLite.set(this.element, { perspective: 5000 });
 | 
				
			||||||
            TweenLite.set(this.card, { transformStyle: 'preserve-3d' });
 | 
					            TweenLite.set(this.card, { transformStyle: 'preserve-3d' });
 | 
				
			||||||
            TweenLite.set(this.back, { rotationY: -180 });
 | 
					            TweenLite.set(this.back, { rotationY: -180 });
 | 
				
			||||||
@ -7572,15 +7665,24 @@
 | 
				
			|||||||
            this.backBtn = element.querySelector('.backBtn');
 | 
					            this.backBtn = element.querySelector('.backBtn');
 | 
				
			||||||
            this.closeBtn = element.querySelector('.closeBtn');
 | 
					            this.closeBtn = element.querySelector('.closeBtn');
 | 
				
			||||||
            /* Buttons are not guaranteed to exist. */
 | 
					            /* Buttons are not guaranteed to exist. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (this.infoBtn) {
 | 
					            if (this.infoBtn) {
 | 
				
			||||||
                InteractionMapper$1.on('tap', this.infoBtn, event => this.flip.start());
 | 
					                scatter.addTapListener(this.infoBtn, event => {
 | 
				
			||||||
 | 
					                    console.log("within click handler", this);
 | 
				
			||||||
 | 
					                    this.flip.start();
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
                this.enable(this.infoBtn);
 | 
					                this.enable(this.infoBtn);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (this.backBtn) {
 | 
					            if (this.backBtn) {
 | 
				
			||||||
                InteractionMapper$1.on('tap', this.backBtn, event => this.start());
 | 
					                scatter.addTapListener(this.backBtn, event => {
 | 
				
			||||||
 | 
					                    console.log("within click handler", this);
 | 
				
			||||||
 | 
					                    this.start();
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (this.closeBtn) {
 | 
					            if (this.closeBtn) {
 | 
				
			||||||
                InteractionMapper$1.on('tap', this.closeBtn, event => this.close());
 | 
					                scatter.addTapListener(this.closeBtn, event => {
 | 
				
			||||||
 | 
					                    this.close();
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
                this.enable(this.closeBtn);
 | 
					                this.enable(this.closeBtn);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            this.scaleButtons();
 | 
					            this.scaleButtons();
 | 
				
			||||||
@ -7630,18 +7732,6 @@
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        scaleButtons() {
 | 
					        scaleButtons() {
 | 
				
			||||||
            //This also works for svgs.
 | 
					 | 
				
			||||||
            // if (this.infoBtn)
 | 
					 | 
				
			||||||
            //     this.infoBtn.style.transform = "scale(" + this.buttonScale + ")"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // if (this.backBtn)
 | 
					 | 
				
			||||||
            //     this.backBtn.style.transform = "scale(" + this.buttonScale + ")"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // if (this.closeBtn)
 | 
					 | 
				
			||||||
            //     this.closeBtn.style.transform = "scale(" + this.buttonScale + ")"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            console.log(this.buttonScale);
 | 
					 | 
				
			||||||
            //// This did not work with svgs!
 | 
					 | 
				
			||||||
            TweenLite.set([this.infoBtn, this.backBtn, this.closeBtn], {
 | 
					            TweenLite.set([this.infoBtn, this.backBtn, this.closeBtn], {
 | 
				
			||||||
                scale: this.buttonScale
 | 
					                scale: this.buttonScale
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
@ -7654,6 +7744,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        clickInfo() {
 | 
					        clickInfo() {
 | 
				
			||||||
            this.bringToFront();
 | 
					            this.bringToFront();
 | 
				
			||||||
 | 
					            console.log("clickInfo");
 | 
				
			||||||
            this.infoBtn.click();
 | 
					            this.infoBtn.click();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -7695,8 +7786,6 @@
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        enable(button) {
 | 
					        enable(button) {
 | 
				
			||||||
            this.show(button, this.fadeDuration);
 | 
					            this.show(button, this.fadeDuration);
 | 
				
			||||||
            if (button) {
 | 
					            if (button) {
 | 
				
			||||||
@ -7706,9 +7795,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        disable(button) {
 | 
					        disable(button) {
 | 
				
			||||||
            this.hide(button, this.fadeDuration);
 | 
					            this.hide(button, this.fadeDuration);
 | 
				
			||||||
            if (button) {
 | 
					 | 
				
			||||||
                TweenLite.set(button, { pointerEvents: 'none' });
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        start({ targetCenter = null } = {}) {
 | 
					        start({ targetCenter = null } = {}) {
 | 
				
			||||||
@ -7752,7 +7838,6 @@
 | 
				
			|||||||
            let x = this.flipped ? xx : this.startX;
 | 
					            let x = this.flipped ? xx : this.startX;
 | 
				
			||||||
            let y = this.flipped ? yy : this.startY;
 | 
					            let y = this.flipped ? yy : this.startY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            console.log("DOMFlippable.start", this.flipped, targetCenter, x, y, this.saved);
 | 
					 | 
				
			||||||
            let onUpdate = this.onUpdate !== null ? () => this.onUpdate(this) : null;
 | 
					            let onUpdate = this.onUpdate !== null ? () => this.onUpdate(this) : null;
 | 
				
			||||||
            console.log(this.flipDuration);
 | 
					            console.log(this.flipDuration);
 | 
				
			||||||
            TweenLite.to(this.card, this.flipDuration, {
 | 
					            TweenLite.to(this.card, this.flipDuration, {
 | 
				
			||||||
 | 
				
			|||||||
@ -72,7 +72,7 @@ if (Capabilities.supportsTemplate()) {
 | 
				
			|||||||
                            flipTemplate,
 | 
					                            flipTemplate,
 | 
				
			||||||
                            new ImageLoader('./examples/king.jpeg'),
 | 
					                            new ImageLoader('./examples/king.jpeg'),
 | 
				
			||||||
                            new ImageLoader('./examples/women.jpeg'),
 | 
					                            new ImageLoader('./examples/women.jpeg'),
 | 
				
			||||||
                            { onUpdate: e => console.log(e)})
 | 
					                            { clickOnTap: true})
 | 
				
			||||||
    flip.load().then((flip) => {
 | 
					    flip.load().then((flip) => {
 | 
				
			||||||
        flip.centerAt({ x: 150, y: 120})
 | 
					        flip.centerAt({ x: 150, y: 120})
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
@ -80,10 +80,5 @@ if (Capabilities.supportsTemplate()) {
 | 
				
			|||||||
else {
 | 
					else {
 | 
				
			||||||
    alert("Templates not supported, use Edge, Chrome, Safari or Firefox.")
 | 
					    alert("Templates not supported, use Edge, Chrome, Safari or Firefox.")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
setTimeout(function() {
 | 
					 | 
				
			||||||
    const infoBtn = document.querySelector('.infoBtn')
 | 
					 | 
				
			||||||
    InteractionMapper.on('tap', infoBtn, event => console.log('go'))
 | 
					 | 
				
			||||||
}, 2000)
 | 
					 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
</body>
 | 
					</body>
 | 
				
			||||||
 | 
				
			|||||||
@ -31,12 +31,12 @@ export class CardLoader {
 | 
				
			|||||||
        this.maxHeight = maxHeight != null ? maxHeight : window.innerHeight
 | 
					        this.maxHeight = maxHeight != null ? maxHeight : window.innerHeight
 | 
				
			||||||
        this.addedNode = null
 | 
					        this.addedNode = null
 | 
				
			||||||
        console.log({
 | 
					        console.log({
 | 
				
			||||||
         
 | 
					
 | 
				
			||||||
            width,
 | 
					            width,
 | 
				
			||||||
            height,
 | 
					            height,
 | 
				
			||||||
            maxWidth,
 | 
					            maxWidth,
 | 
				
			||||||
            maxHeight,
 | 
					            maxHeight,
 | 
				
			||||||
           
 | 
					
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -199,6 +199,7 @@ export class DOMFlip {
 | 
				
			|||||||
            translatable = true,
 | 
					            translatable = true,
 | 
				
			||||||
            scalable = true,
 | 
					            scalable = true,
 | 
				
			||||||
            rotatable = true,
 | 
					            rotatable = true,
 | 
				
			||||||
 | 
					            clickOnTap = false,
 | 
				
			||||||
            onFront = null,
 | 
					            onFront = null,
 | 
				
			||||||
            onBack = null,
 | 
					            onBack = null,
 | 
				
			||||||
            onClose = null,
 | 
					            onClose = null,
 | 
				
			||||||
@ -218,6 +219,7 @@ export class DOMFlip {
 | 
				
			|||||||
        this.translatable = translatable
 | 
					        this.translatable = translatable
 | 
				
			||||||
        this.scalable = scalable
 | 
					        this.scalable = scalable
 | 
				
			||||||
        this.rotatable = rotatable
 | 
					        this.rotatable = rotatable
 | 
				
			||||||
 | 
					        this.clickOnTap = clickOnTap
 | 
				
			||||||
        this.onFrontFlipped = onFront
 | 
					        this.onFrontFlipped = onFront
 | 
				
			||||||
        this.onBackFlipped = onBack
 | 
					        this.onBackFlipped = onBack
 | 
				
			||||||
        this.onClose = onClose
 | 
					        this.onClose = onClose
 | 
				
			||||||
@ -272,7 +274,8 @@ export class DOMFlip {
 | 
				
			|||||||
                    translatable: this.translatable,
 | 
					                    translatable: this.translatable,
 | 
				
			||||||
                    scalable: this.scalable,
 | 
					                    scalable: this.scalable,
 | 
				
			||||||
                    rotatable: this.rotatable,
 | 
					                    rotatable: this.rotatable,
 | 
				
			||||||
                    overdoScaling: this.overdoScaling
 | 
					                    overdoScaling: this.overdoScaling,
 | 
				
			||||||
 | 
					                    clickOnTap: this.clickOnTap
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -281,7 +284,6 @@ export class DOMFlip {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (this.closeOnMinScale) {
 | 
					            if (this.closeOnMinScale) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
                const removeOnMinScale = function () {
 | 
					                const removeOnMinScale = function () {
 | 
				
			||||||
                    if (scatter.scale <= scatter.minScale) {
 | 
					                    if (scatter.scale <= scatter.minScale) {
 | 
				
			||||||
                        this.flippable.close()
 | 
					                        this.flippable.close()
 | 
				
			||||||
@ -296,11 +298,7 @@ export class DOMFlip {
 | 
				
			|||||||
                            scatter.onTransform.splice(callbackIdx, 1)
 | 
					                            scatter.onTransform.splice(callbackIdx, 1)
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
                }.bind(this)
 | 
					                }.bind(this)
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                scatter.addTransformEventCallback(removeOnMinScale)
 | 
					                scatter.addTransformEventCallback(removeOnMinScale)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -336,8 +334,11 @@ export class DOMFlip {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    start({ targetCenter = null } = {}) {
 | 
					    start({ targetCenter = null } = {}) {
 | 
				
			||||||
        console.log('DOMFlip.start', targetCenter)
 | 
					        console.log("DOMFlip.start", targetCenter)
 | 
				
			||||||
        if (this.preloadBack) this.flippable.start({ duration: this.flipDuration, targetCenter })
 | 
					        if (this.preloadBack) {
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            this.flippable.start({ duration: this.flipDuration, targetCenter })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
            let back = this.cardWrapper.querySelector('.back')
 | 
					            let back = this.cardWrapper.querySelector('.back')
 | 
				
			||||||
            let flippable = this.flippable
 | 
					            let flippable = this.flippable
 | 
				
			||||||
@ -389,7 +390,7 @@ export class DOMFlippable {
 | 
				
			|||||||
        this.flipDuration = flip.flipDuration
 | 
					        this.flipDuration = flip.flipDuration
 | 
				
			||||||
        this.fadeDuration = flip.fadeDuration
 | 
					        this.fadeDuration = flip.fadeDuration
 | 
				
			||||||
        scatter.addTransformEventCallback(this.scatterTransformed.bind(this))
 | 
					        scatter.addTransformEventCallback(this.scatterTransformed.bind(this))
 | 
				
			||||||
        console.log('lib.DOMFlippable', 5000)
 | 
					
 | 
				
			||||||
        TweenLite.set(this.element, { perspective: 5000 })
 | 
					        TweenLite.set(this.element, { perspective: 5000 })
 | 
				
			||||||
        TweenLite.set(this.card, { transformStyle: 'preserve-3d' })
 | 
					        TweenLite.set(this.card, { transformStyle: 'preserve-3d' })
 | 
				
			||||||
        TweenLite.set(this.back, { rotationY: -180 })
 | 
					        TweenLite.set(this.back, { rotationY: -180 })
 | 
				
			||||||
@ -402,15 +403,24 @@ export class DOMFlippable {
 | 
				
			|||||||
        this.backBtn = element.querySelector('.backBtn')
 | 
					        this.backBtn = element.querySelector('.backBtn')
 | 
				
			||||||
        this.closeBtn = element.querySelector('.closeBtn')
 | 
					        this.closeBtn = element.querySelector('.closeBtn')
 | 
				
			||||||
        /* Buttons are not guaranteed to exist. */
 | 
					        /* Buttons are not guaranteed to exist. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (this.infoBtn) {
 | 
					        if (this.infoBtn) {
 | 
				
			||||||
            InteractionMapper.on('tap', this.infoBtn, event => this.flip.start())
 | 
					            scatter.addTapListener(this.infoBtn, event => {
 | 
				
			||||||
 | 
					                console.log("within click handler", this)
 | 
				
			||||||
 | 
					                this.flip.start()
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
            this.enable(this.infoBtn)
 | 
					            this.enable(this.infoBtn)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (this.backBtn) {
 | 
					        if (this.backBtn) {
 | 
				
			||||||
            InteractionMapper.on('tap', this.backBtn, event => this.start())
 | 
					            scatter.addTapListener(this.backBtn, event => {
 | 
				
			||||||
 | 
					                console.log("within click handler", this)
 | 
				
			||||||
 | 
					                this.start()
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (this.closeBtn) {
 | 
					        if (this.closeBtn) {
 | 
				
			||||||
            InteractionMapper.on('tap', this.closeBtn, event => this.close())
 | 
					            scatter.addTapListener(this.closeBtn, event => {
 | 
				
			||||||
 | 
					                this.close()
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
            this.enable(this.closeBtn)
 | 
					            this.enable(this.closeBtn)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        this.scaleButtons()
 | 
					        this.scaleButtons()
 | 
				
			||||||
@ -460,18 +470,6 @@ export class DOMFlippable {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    scaleButtons() {
 | 
					    scaleButtons() {
 | 
				
			||||||
        //This also works for svgs.
 | 
					 | 
				
			||||||
        // if (this.infoBtn)
 | 
					 | 
				
			||||||
        //     this.infoBtn.style.transform = "scale(" + this.buttonScale + ")"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // if (this.backBtn)
 | 
					 | 
				
			||||||
        //     this.backBtn.style.transform = "scale(" + this.buttonScale + ")"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // if (this.closeBtn)
 | 
					 | 
				
			||||||
        //     this.closeBtn.style.transform = "scale(" + this.buttonScale + ")"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        console.log(this.buttonScale)
 | 
					 | 
				
			||||||
        //// This did not work with svgs!
 | 
					 | 
				
			||||||
        TweenLite.set([this.infoBtn, this.backBtn, this.closeBtn], {
 | 
					        TweenLite.set([this.infoBtn, this.backBtn, this.closeBtn], {
 | 
				
			||||||
            scale: this.buttonScale
 | 
					            scale: this.buttonScale
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
@ -484,6 +482,7 @@ export class DOMFlippable {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    clickInfo() {
 | 
					    clickInfo() {
 | 
				
			||||||
        this.bringToFront()
 | 
					        this.bringToFront()
 | 
				
			||||||
 | 
					        console.log("clickInfo")
 | 
				
			||||||
        this.infoBtn.click()
 | 
					        this.infoBtn.click()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -525,8 +524,6 @@ export class DOMFlippable {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    enable(button) {
 | 
					    enable(button) {
 | 
				
			||||||
        this.show(button, this.fadeDuration)
 | 
					        this.show(button, this.fadeDuration)
 | 
				
			||||||
        if (button) {
 | 
					        if (button) {
 | 
				
			||||||
@ -537,7 +534,7 @@ export class DOMFlippable {
 | 
				
			|||||||
    disable(button) {
 | 
					    disable(button) {
 | 
				
			||||||
        this.hide(button, this.fadeDuration)
 | 
					        this.hide(button, this.fadeDuration)
 | 
				
			||||||
        if (button) {
 | 
					        if (button) {
 | 
				
			||||||
            TweenLite.set(button, { pointerEvents: 'none' })
 | 
					           // TweenLite.set(button, { pointerEvents: 'none' })
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -582,7 +579,6 @@ export class DOMFlippable {
 | 
				
			|||||||
        let x = this.flipped ? xx : this.startX
 | 
					        let x = this.flipped ? xx : this.startX
 | 
				
			||||||
        let y = this.flipped ? yy : this.startY
 | 
					        let y = this.flipped ? yy : this.startY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        console.log("DOMFlippable.start", this.flipped, targetCenter, x, y, this.saved)
 | 
					 | 
				
			||||||
        let onUpdate = this.onUpdate !== null ? () => this.onUpdate(this) : null
 | 
					        let onUpdate = this.onUpdate !== null ? () => this.onUpdate(this) : null
 | 
				
			||||||
        console.log(this.flipDuration)
 | 
					        console.log(this.flipDuration)
 | 
				
			||||||
        TweenLite.to(this.card, this.flipDuration, {
 | 
					        TweenLite.to(this.card, this.flipDuration, {
 | 
				
			||||||
 | 
				
			|||||||
@ -15,10 +15,10 @@
 | 
				
			|||||||
        context.clearRect(0, 0, debugCanvas.width, debugCanvas.height)
 | 
					        context.clearRect(0, 0, debugCanvas.width, debugCanvas.height)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let stage = scatterContainer.polygon
 | 
					        let stage = scatterContainer.polygon
 | 
				
			||||||
        stage.draw(context, { stroke: '#FF0000'})
 | 
					        stage.draw(context, { stroke: '#0000FF'})
 | 
				
			||||||
        for(let scatter of scatterContainer.scatter.values()) {
 | 
					        for(let scatter of scatterContainer.scatter.values()) {
 | 
				
			||||||
            let polygon = scatter.polygon
 | 
					            let polygon = scatter.polygon
 | 
				
			||||||
            polygon.draw(context, { stroke: '#FF0000'})
 | 
					            polygon.draw(context, { stroke: '#0000FF'})
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -48,7 +48,7 @@ we describe the more basic DOM scatter.
 | 
				
			|||||||
    <img id="women" draggable="false" style="position: absolute;" src="examples/women.jpeg" />
 | 
					    <img id="women" draggable="false" style="position: absolute;" src="examples/women.jpeg" />
 | 
				
			||||||
    <img id="king" draggable="false"  style="position: absolute;" src="examples/king.jpeg" />
 | 
					    <img id="king" draggable="false"  style="position: absolute;" src="examples/king.jpeg" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <canvas id="debugCanvas" height="280" style="z-index: 100000; pointer-events: none; position: absolute; border: 1px solid red;">
 | 
					    <canvas id="debugCanvas" height="280" style="z-index: 100000; pointer-events: none; position: absolute; border: 1px solid blue;">
 | 
				
			||||||
        Canvas not supported.
 | 
					        Canvas not supported.
 | 
				
			||||||
    </canvas>
 | 
					    </canvas>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
@ -81,4 +81,39 @@ app.run()
 | 
				
			|||||||
animatePolygons()
 | 
					animatePolygons()
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<h1>
 | 
				
			||||||
 | 
						Interactive Content
 | 
				
			||||||
 | 
					</h1>
 | 
				
			||||||
 | 
					<p>
 | 
				
			||||||
 | 
					Scatter objects may contain interactive HTML structures. There is one major flag that allows
 | 
				
			||||||
 | 
					to simulate click events by using taps. If the scatter detects a tap it looks for clickable
 | 
				
			||||||
 | 
					elements under or nearby the event position and calls the click handler. Thus gestures
 | 
				
			||||||
 | 
					can be disambiguated as moves, zooms. or taps.
 | 
				
			||||||
 | 
					</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div id="main2" class="grayBorder interactive" style="position: relative; width: 100%; height: 280px;">
 | 
				
			||||||
 | 
					    <!-- Note that we need to set draggable to false to avoid conflicts. The DOM elements
 | 
				
			||||||
 | 
					    must also be positioned absolutely. -->
 | 
				
			||||||
 | 
					    <div id="interactiveContent">
 | 
				
			||||||
 | 
					        <img draggable="false" style="position: absolute;" src="examples/women.jpeg" />
 | 
				
			||||||
 | 
					        <a style="position:absolute; top: 10px; right: 10px; color:white;" href="https://www.iwm-tuebingen.de" target="_blank">A Link</a>
 | 
				
			||||||
 | 
					        <div onclick="alert('clicked')" style="position:absolute; top: 30px; right: 10px; color:white;">A Div with click handler</div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script class="doctest">
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					    let app2 = new App()
 | 
				
			||||||
 | 
					    let scatterContainer2 = new DOMScatterContainer(main2)
 | 
				
			||||||
 | 
					    let scatter2 = new DOMScatter(interactiveContent, scatterContainer2, {
 | 
				
			||||||
 | 
					                        x: 44,
 | 
				
			||||||
 | 
					                        y: 44,
 | 
				
			||||||
 | 
					                        width: 274,
 | 
				
			||||||
 | 
					                        height: 184,
 | 
				
			||||||
 | 
					                        throwVisibility: 88,
 | 
				
			||||||
 | 
					                        minScale: 0.5,
 | 
				
			||||||
 | 
					                        maxScale: 1.5})
 | 
				
			||||||
 | 
					    app2.run()
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</body>
 | 
					</body>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										105
									
								
								lib/scatter.js
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								lib/scatter.js
									
									
									
									
									
								
							@ -931,7 +931,7 @@ export class DOMScatterContainer {
 | 
				
			|||||||
            context.stroke()
 | 
					            context.stroke()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        requestAnimationFrame(dt => {
 | 
					        requestAnimationFrame(dt => {
 | 
				
			||||||
            this.showTouches(dt)
 | 
					            this.showTouches(dt, canvas)
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1042,7 +1042,8 @@ export class DOMScatter extends AbstractScatter {
 | 
				
			|||||||
            width = null, // required
 | 
					            width = null, // required
 | 
				
			||||||
            height = null,  // required
 | 
					            height = null,  // required
 | 
				
			||||||
            resizable = false,
 | 
					            resizable = false,
 | 
				
			||||||
            simulateClick = false,
 | 
					            clickOnTap = false,
 | 
				
			||||||
 | 
					            allowClickDistance = 44,
 | 
				
			||||||
            verbose = true,
 | 
					            verbose = true,
 | 
				
			||||||
            onResize = null,
 | 
					            onResize = null,
 | 
				
			||||||
            touchAction = 'none',
 | 
					            touchAction = 'none',
 | 
				
			||||||
@ -1093,7 +1094,7 @@ export class DOMScatter extends AbstractScatter {
 | 
				
			|||||||
        this.height = height
 | 
					        this.height = height
 | 
				
			||||||
        this.throwVisibility = Math.min(width, height, throwVisibility)
 | 
					        this.throwVisibility = Math.min(width, height, throwVisibility)
 | 
				
			||||||
        this.container = container
 | 
					        this.container = container
 | 
				
			||||||
        this.simulateClick = simulateClick
 | 
					        this.clickOnTap = clickOnTap
 | 
				
			||||||
        this.scale = startScale
 | 
					        this.scale = startScale
 | 
				
			||||||
        this.rotationDegrees = this.startRotationDegrees
 | 
					        this.rotationDegrees = this.startRotationDegrees
 | 
				
			||||||
        this.transformOrigin = transformOrigin
 | 
					        this.transformOrigin = transformOrigin
 | 
				
			||||||
@ -1106,7 +1107,8 @@ export class DOMScatter extends AbstractScatter {
 | 
				
			|||||||
            rotation: this.startRotationDegrees,
 | 
					            rotation: this.startRotationDegrees,
 | 
				
			||||||
            transformOrigin: transformOrigin
 | 
					            transformOrigin: transformOrigin
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        this.tapNodes = new Map()
 | 
				
			||||||
 | 
					        this.allowClickDistance = allowClickDistance
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // For tweenlite we need initial values in _gsTransform
 | 
					        // For tweenlite we need initial values in _gsTransform
 | 
				
			||||||
        TweenLite.set(element, this.initialValues)
 | 
					        TweenLite.set(element, this.initialValues)
 | 
				
			||||||
@ -1299,16 +1301,99 @@ export class DOMScatter extends AbstractScatter {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    onTap(event, interaction, point) {
 | 
					    onTap(event, interaction, point) {
 | 
				
			||||||
        if (this.simulateClick) {
 | 
					        
 | 
				
			||||||
            let p = Points.fromPageToNode(this.element, point)
 | 
					        if (this.clickOnTap) {
 | 
				
			||||||
            let element = document.elementFromPoint(p.x, p.y)
 | 
					            let directNode = document.elementFromPoint(point.x, point.y)
 | 
				
			||||||
            if (element != null) {
 | 
					            let nearestNode = this.nearestClickable(event)
 | 
				
			||||||
                console.log('tap simulates click')
 | 
					
 | 
				
			||||||
                element.click()
 | 
					            console.log("onTap", directNode, nearestNode.tagName)
 | 
				
			||||||
 | 
					            if (directNode != null && this.isClickable(directNode)) {
 | 
				
			||||||
 | 
					                directNode.click()
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else {
 | 
				
			||||||
 | 
					                if (nearestNode.tagName == 'svg' && this.isClickable(nearestNode)) {
 | 
				
			||||||
 | 
					                    let handler = this.tapNodes.get(nearestNode)
 | 
				
			||||||
 | 
					                    console.log("Clicking beneath SVG: to be done", handler)
 | 
				
			||||||
 | 
					                    Events.stop(event)
 | 
				
			||||||
 | 
					                    //nearestNode.click()
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Adds a click or tap behavior to the node. Uses
 | 
				
			||||||
 | 
					     * either the scatter clickOnTap version which requires click handlers
 | 
				
			||||||
 | 
					     * or uses the hammer.js driven tap handler.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param {*} node
 | 
				
			||||||
 | 
					     * @param {*} handler
 | 
				
			||||||
 | 
					     * @memberof DOMScatter
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    addTapListener(node, handler) {
 | 
				
			||||||
 | 
					        if (this.clickOnTap) {
 | 
				
			||||||
 | 
					            node.addEventListener('click', handler)
 | 
				
			||||||
 | 
					            this.tapNodes.set(node, handler)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            InteractionMapper.on('tap', node, handler)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    isClickable(node) {
 | 
				
			||||||
 | 
					        if (node.tagName == 'A')
 | 
				
			||||||
 | 
					            return true
 | 
				
			||||||
 | 
					        if (this.tapNodes.has(node)) 
 | 
				
			||||||
 | 
					            return true
 | 
				
			||||||
 | 
					        return false
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Returns an array of all clickable nodes.
 | 
				
			||||||
 | 
					     * Unfortunately we cannot search for all nodes with an attached 'click' event listener
 | 
				
			||||||
 | 
					     * 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 clickables
 | 
				
			||||||
 | 
					     * II. Objects that have been attached a click handler by the scatter itself via 
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    clickableNodes() {
 | 
				
			||||||
 | 
					        let result = []
 | 
				
			||||||
 | 
					        for (let node of this.element.querySelectorAll("*")) {
 | 
				
			||||||
 | 
					            if (this.isClickable(node))
 | 
				
			||||||
 | 
					                result.push(node)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return result
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    nearestClickable(event) {
 | 
				
			||||||
 | 
					        let element = this.element
 | 
				
			||||||
 | 
					        let clickables = this.clickableNodes()
 | 
				
			||||||
 | 
					        let globalClick = (event.center) ? event.center : { x: event.x, y: event.y }
 | 
				
			||||||
 | 
					        let localClick = Points.fromPageToNode(element, globalClick)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let clickRects = clickables.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 distances = []
 | 
				
			||||||
 | 
					        clickRects.forEach(rect => {
 | 
				
			||||||
 | 
					            let distance = Points.distanceToRect(localClick, rect)
 | 
				
			||||||
 | 
					            distances.push(parseInt(distance))
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let closestClickIndex = distances.indexOf(Math.min(...distances))
 | 
				
			||||||
 | 
					        let closestClickable = clickables[closestClickIndex]
 | 
				
			||||||
 | 
					        if (distances[closestClickIndex] < this.allowClickDistance) {
 | 
				
			||||||
 | 
					            console.log("found closest clickables", closestClickable)
 | 
				
			||||||
 | 
					            return closestClickable
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return null
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    isDescendant(parent, child) {
 | 
					    isDescendant(parent, child) {
 | 
				
			||||||
        let node = child.parentNode
 | 
					        let node = child.parentNode
 | 
				
			||||||
        while (node != null) {
 | 
					        while (node != null) {
 | 
				
			||||||
 | 
				
			|||||||
@ -402,6 +402,13 @@ export class Points {
 | 
				
			|||||||
        return Math.sqrt(dx * dx + dy * dy)
 | 
					        return Math.sqrt(dx * dx + dy * dy)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Distance == 0.0 indicates an inside relation.
 | 
				
			||||||
 | 
					    static distanceToRect(p, r) {
 | 
				
			||||||
 | 
					        var cx = Math.max(Math.min(p.x, r.x + r.width), r.x)
 | 
				
			||||||
 | 
					        var cy = Math.max(Math.min(p.y, r.y + r.height), r.y)
 | 
				
			||||||
 | 
					        return Math.sqrt((p.x - cx) * (p.x - cx) + (p.y - cy) * (p.y - cy))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static fromPageToNode(element, p) {
 | 
					    static fromPageToNode(element, p) {
 | 
				
			||||||
        //    if (window.webkitConvertPointFromPageToNode) {
 | 
					        //    if (window.webkitConvertPointFromPageToNode) {
 | 
				
			||||||
        //             return window.webkitConvertPointFromPageToNode(element,
 | 
					        //             return window.webkitConvertPointFromPageToNode(element,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user