1const globalCallbackStack = new Map(); 2const HtmlElements = document.querySelector('script[src*="HtmlElements.js"]'), 3 scriptSrc = HtmlElements ? HtmlElements.src : document.location.origin + '/_/scripts/rgElements/HtmlElements.js', 4 url = new URL(scriptSrc), 5 paths = url.pathname.split('/'); 6paths.pop(); 7paths.includes('src') && paths.push('Elements'); 8 9export class rgElement extends HTMLElement { 10 rootpath = ''; 11 form = null; 12 13 constructor() { 14 super(); 15 } 16 17 setUpElement() { 18 this.rootpath = paths.join('/') + (this.constructor.name ? '/' + this.constructor.name : ''); 19 this.form = this.closest('form'); 20 this.setAttribute('data-rgelement', true); 21 } 22 23 setupComplete() { 24 document.dispatchEvent(new CustomEvent('rgelement:initialized', {detail: {element: this}})); 25 } 26 27 getStyles(originalSelector, newSelector) { 28 originalSelector = originalSelector.replace('.', '\\.'); 29 let cssRules = ''; 30 [...document.styleSheets].map(styleSheet => { 31 try { 32 let sheetRules = styleSheet.cssRules || styleSheet.rules; 33 let rxOriginalSelector = new RegExp(originalSelector, 'g'); 34 [...sheetRules].map(rule => { 35 let cssMediaRules = ''; 36 if(rule.selectorText && rule.selectorText.match(originalSelector)) { 37 rule.selectorText = rule.selectorText.replace(rxOriginalSelector, newSelector); 38 cssRules = cssRules + rule.cssText; 39 } else if(rule.media && (rule.cssRules)) { 40 [...rule.cssRules].map(rule => { 41 if(rule.selectorText && rule.selectorText.match(originalSelector)) { 42 rule.selectorText = rule.selectorText.replace(rxOriginalSelector, newSelector); 43 cssMediaRules = cssMediaRules + rule.cssText; 44 } 45 }) 46 if(cssMediaRules !== '') { 47 cssRules = cssRules + ' @media ' + rule.conditionText + '{' + cssMediaRules + '} ' 48 } 49 } 50 }); 51 } catch(e) { 52 } 53 }); 54 return cssRules; 55 } 56 57 copyStyles(selector) { 58 let cssRules = ''; 59 [...document.styleSheets].map(styleSheet => { 60 try { 61 let sheetRules = styleSheet.cssRules || styleSheet.rules; 62 [...sheetRules].map(rule => { 63 let cssMediaRules = ''; 64 if(rule.selectorText && rule.selectorText.match(selector)) { 65 cssRules = cssRules + rule.cssText; 66 } else if(rule.media && (rule.cssRules)) { 67 [...rule.cssRules].map(rule => { 68 if(rule.selectorText && rule.selectorText.match(selector)) { 69 cssMediaRules = cssMediaRules + rule.cssText; 70 } 71 }) 72 if(cssMediaRules !== '') { 73 cssRules = cssRules + ' @media ' + rule.conditionText + '{' + cssMediaRules + '} ' 74 } 75 } 76 }); 77 } catch(e) { 78 } 79 }); 80 return cssRules; 81 } 82 83 parseAttribute(attribute) { 84 if(attribute !== undefined) { 85 if(attribute === 'false' || attribute === 'true') { 86 return JSON.parse(attribute); 87 } 88 if(attribute.match(/^\d+$/)) { 89 return Number(attribute); 90 } 91 } 92 return attribute; 93 } 94 95 loadFile(path, callback, type, insertPoint = null) { 96 if(!['css', 'js'].includes(type)) { 97 console.error('unsupportet type: "' + type + '"'); 98 return; 99 } 100 if(insertPoint === null) { 101 insertPoint = document.querySelector('head'); 102 } 103 let localCallbackStack = globalCallbackStack.get(insertPoint); 104 if(!localCallbackStack) { 105 localCallbackStack = new Map(); 106 globalCallbackStack.set(insertPoint, localCallbackStack); 107 } 108 let fileCallbackStack = localCallbackStack.get(path); 109 if(!fileCallbackStack) { 110 fileCallbackStack = { 111 loading: true, 112 callbacks: [] 113 }; 114 localCallbackStack.set(path, fileCallbackStack); 115 globalCallbackStack.set(insertPoint, localCallbackStack); 116 } 117 if(!fileCallbackStack.loading && typeof callback === 'function') { 118 callback(); 119 } else { 120 fileCallbackStack.callbacks.push(callback); 121 localCallbackStack.set(path, fileCallbackStack); 122 globalCallbackStack.set(insertPoint, localCallbackStack); 123 let selector; 124 switch(type) { 125 case 'css': 126 selector = 'link[href="' + path + '"]'; 127 break; 128 case 'js': 129 selector = 'script[src="' + path + '"]' 130 break; 131 } 132 if(!insertPoint.querySelector(selector)) { 133 let element; 134 switch(type) { 135 case 'css': 136 element = document.createElement('link'); 137 element.setAttribute('rel', 'stylesheet'); 138 element.setAttribute('href', path); 139 break; 140 case 'js': 141 element = document.createElement('script'); 142 element.setAttribute('src', path); 143 break; 144 } 145 element.onload = function() { 146 // let stack = globalCallbackStack.get(path); 147 fileCallbackStack.loading = false;
148 localCallbackStack.set(path, fileCallbackStack); 149 globalCallbackStack.set(insertPoint, localCallbackStack); 150 fileCallbackStack.callbacks.forEach(cb => { 151 if(typeof cb === 'function') { 152 cb(); 153 } 154 } 155 ) 156 } 157 insertPoint?.append(element); 158 } 159 } 160 } 161 162 loadCss(path, callback) { 163 this.loadFile(path, callback, 'css'); 164 } 165 166 loadScript(path, callback) { 167 this.loadFile(path, callback, 'js'); 168 } 169 170 loadFiles(files, callback) { 171 let promises = []; 172 for(const file of files) { 173 promises.push(new Promise((res, rej) => { 174 this.loadFile( 175 file.path, 176 () => { 177 if('callback' in file) { 178 file.callback(); 179 } 180 if('followup' in file) { 181 this.loadFiles(file.followup, () => { 182 res(); 183 }) 184 } else { 185 res(); 186 } 187 }, 188 file.type, 189 file.insertPoint ?? null); 190 })); 191 } 192 Promise.all(promises).then(() => { 193 callback(); 194 }) 195 } 196 197 extendApi(path) { 198 import( /* webpackIgnore: true */ this.rootpath + path).then(function(defaultExport) { 199 this.dispatchEvent(new CustomEvent(this.tagName.toLowerCase() + ':apiloaded', { 200 detail: { 201 el: this, 202 defaultExport: defaultExport 203 } 204 })); 205 }.bind(this)); 206 } 207}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.