Intermediate
This commit is contained in:
		
							parent
							
								
									a3251f2fdd
								
							
						
					
					
						commit
						854f3ad13e
					
				
					 1 changed files with 107 additions and 32 deletions
				
			
		| 
						 | 
					@ -27,6 +27,38 @@ const specsCopy = (to, from) => {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Get the position of an element relative to another
 | 
				
			||||||
 | 
					 * @param {HTMLElement} el The element whose position to determine
 | 
				
			||||||
 | 
					 * @param {HTMLElement} reference Relative to this element
 | 
				
			||||||
 | 
					 * @returns 
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const getElementPosition = (el, reference) => {
 | 
				
			||||||
 | 
					    if(!el || !(el instanceof HTMLElement)){
 | 
				
			||||||
 | 
					        // Always return 0,0 if the element is invalid
 | 
				
			||||||
 | 
					        return {x: 0, y: 0};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!reference || !(reference instanceof HTMLElement)){
 | 
				
			||||||
 | 
					        // Take the document body as reference if the reference is invalud
 | 
				
			||||||
 | 
					        reference = document.querySelector("body");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if( el.offsetParent === reference){
 | 
				
			||||||
 | 
					        // easily done if the reference element is also the offsetParent.. 
 | 
				
			||||||
 | 
					        return {x: el.offsetLeft, y: el.offsetTop};
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        const elR = el.getBoundingClientRect();
 | 
				
			||||||
 | 
					        const refR = reference.getBoundingClientRect();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return {x: elR.left - refR.left, 
 | 
				
			||||||
 | 
					                y: elR.top - refR.top};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Check if an element is a containing element and can thus be a parent for absolute positioning
 | 
					 * Check if an element is a containing element and can thus be a parent for absolute positioning
 | 
				
			||||||
 * Which is the cas if the element has
 | 
					 * Which is the cas if the element has
 | 
				
			||||||
| 
						 | 
					@ -86,6 +118,7 @@ export class SimpleLine {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            console.error("Start element not string or dom element",start);
 | 
					            console.error("Start element not string or dom element",start);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Validate end element
 | 
					        // Validate end element
 | 
				
			||||||
| 
						 | 
					@ -100,43 +133,85 @@ export class SimpleLine {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            console.error("End element not string or dom element",start);
 | 
					            console.error("End element not string or dom element",start);
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Validate or determine container
 | 
					 | 
				
			||||||
        if(this.specs.container){
 | 
					 | 
				
			||||||
            if(this.specs.container instanceof HTMLElement){
 | 
					 | 
				
			||||||
                this.container = this.specs.container;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (typeof this.specs.container === 'string' || this.specs.container instanceof String) {
 | 
					 | 
				
			||||||
                this.container = document.querySelector(this.specs.container);
 | 
					 | 
				
			||||||
                if(!(this.container instanceof HTMLElement)){
 | 
					 | 
				
			||||||
                    console.warn("Cannot find specified container element:",this.specs.container);
 | 
					 | 
				
			||||||
                    this.specs.container = null;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else {
 | 
					 | 
				
			||||||
                console.warn("Container specified is not a string or element:",this.specs.container);
 | 
					 | 
				
			||||||
                this.specs.container = null;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if(!this.specs.container) { // if originally empty, or cleared
 | 
					 | 
				
			||||||
            // find the first parent element of start that has position css attribute set (or body if none has it set)
 | 
					 | 
				
			||||||
            const body = document.querySelector("body");
 | 
					 | 
				
			||||||
            let el = this.start.parentElement;
 | 
					 | 
				
			||||||
            while( el !== body && !isContainingElement(el)){
 | 
					 | 
				
			||||||
                el = el.parentElement;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            this.container = el;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getContainer(){
 | 
				
			||||||
 | 
					        // Validate or determine container
 | 
				
			||||||
 | 
					        let container = this.startstart.offsetParent;
 | 
				
			||||||
 | 
					        if(!container) {
 | 
				
			||||||
 | 
					            if(document.getComputedStyle(this.start).position == "fixed"){
 | 
				
			||||||
 | 
					                container = document.querySelector("body");
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                console.error("Start element has no offsetParent. likely ")
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return container;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    getAnchorPoint(anchor){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let el = this.start;
 | 
				
			||||||
 | 
					        if(anchor != "start"){
 | 
				
			||||||
 | 
					            anchor = "end";
 | 
				
			||||||
 | 
					            el = this.end;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let x, dirX;
 | 
				
			||||||
 | 
					        let y, dirY;
 | 
				
			||||||
 | 
					        // determine start coordinates
 | 
				
			||||||
 | 
					        if(this.specs.anchors[anchor].includes("left")){
 | 
				
			||||||
 | 
					            x = 0;
 | 
				
			||||||
 | 
					            dirX = -1;
 | 
				
			||||||
 | 
					        } else if (this.specs.anchors[anchor].includes("right")) {
 | 
				
			||||||
 | 
					            x = el.offsetWidth -1;
 | 
				
			||||||
 | 
					            dirX = 1;
 | 
				
			||||||
 | 
					        } else { // center
 | 
				
			||||||
 | 
					            x = el.offsetWidth / 2;
 | 
				
			||||||
 | 
					            dirX = 0;
 | 
				
			||||||
 | 
					        } 
 | 
				
			||||||
 | 
					        if(this.specs.anchors[anchor].includes("top")){
 | 
				
			||||||
 | 
					            y = 0;
 | 
				
			||||||
 | 
					            dirY = 1;
 | 
				
			||||||
 | 
					        } else if (this.specs.anchors[anchor].includes("bottom")) {
 | 
				
			||||||
 | 
					            x = el.offsetHeight -1;
 | 
				
			||||||
 | 
					            dirY = -1;
 | 
				
			||||||
 | 
					        } else { // middle
 | 
				
			||||||
 | 
					            x = el.offsetHeight / 2;
 | 
				
			||||||
 | 
					            dirY = 0;
 | 
				
			||||||
 | 
					        } 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const rotation = Math.atan2(dirX,dirY);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return { x: x, y: y, rot: rotation};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    paintSvg(){
 | 
					    paintSvg(){
 | 
				
			||||||
        const svg = document.createElement("svg");
 | 
					        const container = this.getContainer();
 | 
				
			||||||
        svg.attributes["viewBox"] = "";
 | 
					        if (!container) { return; } // Do not create any svg if container is empty
 | 
				
			||||||
        svg.attributes["width"] = "";
 | 
					
 | 
				
			||||||
        svg.attributes["height"] = "";
 | 
					        if(!this.svg || !(this.svg instanceof HTMLElement)){
 | 
				
			||||||
 | 
					            this.svg = document.createElement("svg");
 | 
				
			||||||
 | 
					            container.append(this.svg);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // determine proper x, y ,h and w
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        this.svg.attributes["viewBox"] = `0 0 ${w}, ${h}`;
 | 
				
			||||||
 | 
					        this.svg.attributes["width"] = `${w}px`;
 | 
				
			||||||
 | 
					        this.svg.attributes["height"] = `${h}px`;
 | 
				
			||||||
 | 
					        this.svg.style.position = "absolute";
 | 
				
			||||||
 | 
					        this.svg.style.left = `${x}px`;
 | 
				
			||||||
 | 
					        this.svg.style.top  = `${y}px`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Draw the arrows....
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Reference in a new issue