Creating replacement for leaderline
This commit is contained in:
		
							parent
							
								
									340b0eef6b
								
							
						
					
					
						commit
						a3251f2fdd
					
				
					 1 changed files with 143 additions and 0 deletions
				
			
		
							
								
								
									
										143
									
								
								amd/src/simpleline.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								amd/src/simpleline.js
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,143 @@ | ||||||
|  | /*eslint no-console: "off"*/ | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Copies defined properties in to, over from the from object. Does so recursively | ||||||
|  |  * Ysed to copy user defined parameters onto a pre-existing object with defaults preset. | ||||||
|  |  * @param {Object} to The object to copy to | ||||||
|  |  * @param {Object} from The object tp copy from (but only the properties already named in "to") | ||||||
|  |  */ | ||||||
|  | const specsCopy = (to, from) => { | ||||||
|  |     for(const ix in to){ | ||||||
|  |         if(from.hasOwnProperty(ix)){ | ||||||
|  |             if( typeof to[ix] == "object" | ||||||
|  |                 && typeof from[ix] == "object") | ||||||
|  |             { | ||||||
|  |                 if(Array.isArray(to[ix])){ | ||||||
|  |                     if(Array.isArray(from[ix])){ | ||||||
|  |                         to[ix] = Array.from(from[ix]); | ||||||
|  |                     } // else, skip...
 | ||||||
|  |                 } else { | ||||||
|  |                     specsCopy(to[ix], from[ix]); // recursive copy
 | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             else { | ||||||
|  |                 to[ix] = from[ix]; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * 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 | ||||||
|  |  *  1 A position value other than static (fixed, absolute, relative, or sticky). | ||||||
|  |  *  2 A transform or perspective value other than none | ||||||
|  |  *  3 A will-change value of transform or perspective | ||||||
|  |  *  4 A filter value other than none or a will-change value of filter (only works on Firefox) | ||||||
|  |  *  5 A contain value of layout, paint, strict or content (e.g. contain: paint;) | ||||||
|  |  *  6 A container-type value other than normal | ||||||
|  |  *  7 A backdrop-filter other than none (e.g. backdrop-filter: blur(10px);) | ||||||
|  |  * @param {HTMLElement} el | ||||||
|  |  * @returns {Boolean} | ||||||
|  |  */ | ||||||
|  | const isContainingElement = (el) => { | ||||||
|  |     const cssStyle = getComputedStyle(el); | ||||||
|  |     return      ["fixed","absolute","relative","sticky",].includes(cssStyle.position) | ||||||
|  |             ||  cssStyle.transform !== "none" | ||||||
|  |             ||  cssStyle.perspective !== "none" | ||||||
|  |             ||  ["transform","perspective"].includes(cssStyle.willChange) | ||||||
|  |             ||  cssStyle.filter !== "none" | ||||||
|  |             ||  cssStyle.contain == "paint" | ||||||
|  |             ||  cssStyle.backdropFilter !== "none"; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | export class SimpleLine { | ||||||
|  | 
 | ||||||
|  |     constructor(start, end, specs){ | ||||||
|  |         this.svg = null; | ||||||
|  | 
 | ||||||
|  |         // setup defaults
 | ||||||
|  |         this.specs = { | ||||||
|  |             container: null, | ||||||
|  |             class: "", | ||||||
|  |             colors: { | ||||||
|  |                 line : "currentcolor", | ||||||
|  |                 arrow: "currentcolor", | ||||||
|  |             }, | ||||||
|  |             anchors: { | ||||||
|  |                 // top, middle, bottom
 | ||||||
|  |                 // left, center, right
 | ||||||
|  |                 start: ["middle","right"], | ||||||
|  |                 end: ["middle", "left"], | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         specsCopy(this.specs,specs); | ||||||
|  | 
 | ||||||
|  |         // Validate start element
 | ||||||
|  |         if(start instanceof HTMLElement) { | ||||||
|  |             this.start = start; | ||||||
|  |         } else if (typeof this.start === 'string' || this.start instanceof String) { | ||||||
|  |             this.startSelector = start; | ||||||
|  |             this.start = document.querySelector(start); | ||||||
|  |             if(!(this.start instanceof HTMLElement)){ | ||||||
|  |                 console.error("Cannot find start element:",start); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             console.error("Start element not string or dom element",start); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Validate end element
 | ||||||
|  |         if(end instanceof HTMLElement) { | ||||||
|  |             this.end = end; | ||||||
|  |         } else if (typeof this.end === 'string' || this.end instanceof String) { | ||||||
|  |             this.endSelector = end; | ||||||
|  |             this.end = document.querySelector(end); | ||||||
|  |             if(!(this.end instanceof HTMLElement)){ | ||||||
|  |                 console.error("Cannot find end element:",end); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             console.error("End element not string or dom element",start); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // 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; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     paintSvg(){ | ||||||
|  |         const svg = document.createElement("svg"); | ||||||
|  |         svg.attributes["viewBox"] = ""; | ||||||
|  |         svg.attributes["width"] = ""; | ||||||
|  |         svg.attributes["height"] = ""; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | } | ||||||
		Reference in a new issue
	
	 PMKuipers
						PMKuipers