1import 'https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js'; 2import 'https://d1zibq5kp019rb.cloudfront.net/node_modules/vue/vue.js'; 3// import 'https://cdn.jsdelivr.net/gh/alpinejs/[email protected]/dist/alpine.min.js'; 4 5window.getHeaders = () => ({ 'Token': getCookie('Token'), 'SubAppId': getCookie('SubAppId'), 'Content-Type': 'application/json;charset=UTF-8', 'Accept': 'application/json' }); 6window.flatten = (arr) => { return arr.reduce((flat, toFlatten) => flat.concat(Array.isArray(toFlatten) ? window.flatten(toFlatten) : toFlatten), []); }; 7window.AsyncFunction = Object.getPrototypeOf(async () => { }).constructor; 8window.deleteCookie = function (name) { setCookie(name, '', -1); }; 9 10window.getCookie = function (cname) { 11 var name = cname + '='; 12 var decodedCookie = decodeURIComponent(document.cookie); 13 var ca = decodedCookie.split(';'); 14 for (var i = 0; i < ca.length; i++) { 15 var c = ca[i]; 16 while (c.charAt(0) == ' ') { 17 c = c.substring(1); 18 } 19 20 if (c.indexOf(name) == 0) { 21 return c.substring(name.length, c.length); 22 } 23 } 24 25 return ''; 26}; 27 28window.setCookie = function (name, value, days) { 29 const d = new Date(); 30 d.setTime(d.getTime() + 24 * 60 * 60 * 1000 * (days || 18250)); 31 document.cookie = name + "=" + value + ";path=/;expires=" + d.toGMTString(); 32}; 33 34window.postRequest = async function (url = '', data = {}, headers = { 'Content-Type': 'application/json;charset=UTF-8', 'Accept': 'application/json' }, cache = 'no-cache') { 35 const response = await fetch(url, { 36 method: 'POST', 37 headers, 38 cache, 39 body: JSON.stringify(data || {}), 40 }); 41 42 const contentType = response.headers.get('content-type'); 43 const responseData = await (contentType && contentType.includes('application/json') ? response.json() : response.text()); 44 if (!response.ok) { 45 throw { 46 message: response.statusText, 47 response: { 48 status: response.status, 49 data: responseData, 50 headers: Object.fromEntries(response.headers.entries()), 51 }, 52 }; 53 } 54 55 return { data: responseData }; 56}; 57 58window.getRequest = async function (url = '', data = {}, headers = { 'Content-Type': 'application/json;charset=UTF-8', 'Accept': 'application/json' }) { 59 const response = await fetch(url, { 60 method: 'GET', 61 headers 62 }); 63 64 const contentType = response.headers.get('content-type'); 65 const responseData = await (contentType && contentType.includes('application/json') ? response.json() : response.text()); 66 if (!response.ok) { 67 throw { 68 message: response.statusText, 69 response: { 70 status: response.status, 71 data: responseData, 72 headers: Object.fromEntries(response.headers.entries()), 73 }, 74 }; 75 } 76 77 return { data: responseData }; 78}; 79 80window.debounce = function debounce(func, wait, immediate) { 81 let timeout, args, context, timestamp, result; 82 if (wait == null) wait = 100; 83 84 function later() { 85 const last = Date.now() - timestamp; 86 87 if (last < wait && last >= 0) { 88 timeout = setTimeout(later, wait - last); 89 } else { 90 timeout = null; 91 if (!immediate) { 92 result = func.apply(context, args); 93 context = args = null; 94 } 95 } 96 }; 97 98 const debounced = function () { 99 context = this; 100 args = arguments; 101 timestamp = Date.now(); 102 const callNow = immediate && !timeout; 103 if (!timeout) timeout = setTimeout(later, wait); 104 if (callNow) { 105 result = func.apply(context, args); 106 context = args = null; 107 } 108 109 return result; 110 }; 111 112 debounced.clear = function () { 113 if (timeout) { 114 clearTimeout(timeout); 115 timeout = null; 116 } 117 }; 118 119 debounced.flush = function () { 120 if (timeout) { 121 result = func.apply(context, args); 122 context = args = null; 123 124 clearTimeout(timeout); 125 timeout = null; 126 } 127 }; 128 129 return debounced; 130}; 131 132window.to = async function (promise) { 133 return promise.then((data) => [null, data]).catch((err) => [err, null]); 134}; 135 136class MarsBase { 137 constructor(id, serverData) {
138 this._marsId = id; 139 this._marsEl = document.getElementById(id); 140 this._marsData = serverData; 141 142 this.initApi(); 143 this.initEvents(); 144 145 window[this._marsId] = this; 146 } 147 148 initApi() { 149 this.api = { 150 _hidden: false, 151 hide: () => { this._marsEl.classList.add('d-none') }, 152 show: () => { this._marsEl.classList.remove('d-none') }, 153 get hidden() { return this._hidden; }, 154 set hidden(val) { 155 val ? this.hide() : this.show(); 156 this._hidden = val; 157 }, 158 }; 159 160 const defaultMethods = [{ name: 'reRender', block: 'MarsJs' }]; 161 if (!this._marsData) { this._marsData = {}; } 162 if (!this._marsData.methods) { this._marsData.methods = []; } 163 164 [...this._marsData.methods, ...defaultMethods].forEach(i => { 165 this.api[i.name] = (...args) => { 166 return new Promise((resolve, reject) => { 167 window.postRequest(`/api/ExecuteApiMethod?blockName=${i.block}&methodName=${i.name}`, { "blockData": this._marsData, "methodData": args }, window.getHeaders()) 168 .then((response) => { 169 resolve(response.data); 170 }) 171 .catch((error) => { 172 reject(error); 173 }); 174 }); 175 } 176 }); 177 178 this.api.reload = async (optionalData) => { 179 const r = await this.api.reRender(this._marsData._blockName, { Id: this._marsId, ...this._marsData, ...(optionalData || {}) }); 180 181 // remove all children objects 182 delete window[this._marsId]; 183 let children = document.querySelectorAll(`#${this._marsId} [id]`); 184 children.forEach(i => { 185 if (window[i.id]) { 186 delete window[i.id]; 187 } 188 }); 189 190 $(`#${this._marsId}`).replaceWith(r); 191 return r; 192 } 193 } 194 195 initEvents() { 196 this._marsEvents = { 197 initEvent: (eventName) => { 198 if (!this[eventName]) { 199 const eventHandlersKey = `${eventName}_Handlers`; 200 this._marsEvents[eventHandlersKey] = []; 201 Object.defineProperty(this, eventName, { 202 set: (handler) => { 203 if (!this._marsEvents[eventHandlersKey].find(t => t.toString() === handler.toString())) { 204 this._marsEvents[eventHandlersKey].push(handler); 205 } 206 }, 207 // get: () => { 208 // return this._marsEvents[eventHandlersKey]; 209 // }, 210 }); 211 } 212 }, 213 fireEvent: (eventName, ...eventData) => { 214 const eventHandlersKey = `${eventName}_Handlers`; 215 if (this._marsEvents[eventHandlersKey] && this._marsEvents[eventHandlersKey].length) { 216 this._marsEvents[eventHandlersKey].forEach(t => t(...eventData)); 217 } 218 }, 219 }; 220 221 this.fire = {}; 222 if (this._marsData.events) { 223 for (let eventName in this._marsData.events) { 224 this._marsEvents.initEvent(eventName); 225 this.fire[eventName] = (...eventData) => { 226 this._marsEvents.fireEvent(eventName, ...eventData); 227 }; 228 } 229 } 230 } 231} 232 233class MarsBlock extends MarsBase { 234 constructor(id, serverData, app) { 235 super(id, { ...serverData, events: app.events }); 236 237 Object.getOwnPropertyNames(app).map(property => { 238 const propertyDescriptor = Object.getOwnPropertyDescriptor(app, property); 239 Object.defineProperty(this, property, propertyDescriptor); 240 }); 241 242 window.dispatchEvent(new CustomEvent(id, { detail: this })); 243 } 244} 245 246class MarsVue extends MarsBase { 247 constructor(id, serverData, app) { 248 if (!id) { 249 return; 250 } 251 252 super(id, { ...serverData, events: app.events }); 253 const vue = new Vue(Object.assign(app, { el: `#${id}` })); 254 255 Object.getOwnPropertyNames(this).map(property => { 256 const propertyDescriptor = Object.getOwnPropertyDescriptor(this, property); 257 Object.defineProperty(vue, property, propertyDescriptor); 258 }); 259 260 window[id] = vue; 261 this.vue = vue; 262 window.dispatchEvent(new CustomEvent(id, { detail: vue })); 263 } 264} 265 266/* 267class MarsAlpine extends MarsBase { 268 init() { 269 return this._marsData; 270 } 271 272 get data() { 273 return this._marsData.$el.__x.$data; 274 } 275 276 constructor(instanceId, serverData, app) { 277 if (!instanceId) { 278 return; 279 } 280 281 super(instanceId, { ...serverData, ...app }); 282 this._marsData.fire = this.fire; 283 284 const el = document.getElementById(instanceId); 285 el.setAttribute('x-data', instanceId + '.init()'); 286 Alpine.initializeComponent(el); 287 } 288} 289*/ 290 291window['MarsBlock'] = MarsBlock; 292window['MarsVue'] = MarsVue; 293// window['MarsAlpine'] = MarsAlpine; 294 295const awaitForBlock = async function (blockId) { 296 const isMarsObject = (block) => (block && block.constructor && (block instanceof Vue || block instanceof MarsBlock || block.constructor.name === 'MarsBlock')); 297 return new Promise((resolve, reject) => { 298 const block = window[blockId]; 299 if (isMarsObject(block)) { 300 resolve(block); 301 return; 302 } 303 304 window.addEventListener(blockId, (e) => { 305 if (isMarsObject(e.detail)) { 306 resolve(e.detail); 307 } 308 });
309 }); 310}; 311 312const awaitForDomNode = async function (selector) { 313 return new Promise((resolve, reject) => { 314 const node = document.querySelector(selector); 315 if (node) { 316 resolve(node); 317 return; 318 } 319 320 new MutationObserver((mutationRecords, observer) => { 321 const node = document.querySelector(selector); 322 if (node) { 323 resolve(node); 324 observer.disconnect(); 325 return; 326 } 327 }).observe(document.documentElement, { childList: true, subtree: true }); 328 }); 329}; 330 331window.executeAppBlock = async function executeAppBlock(f, props, ...children) { 332 // regular html tags 333 if (typeof (f) === 'string') { 334 const htmlProps = props ? Object.entries(props).map(([key, value]) => `${key}="${value}"`).join(' ') : null; 335 return `<${f} ${htmlProps || ''}>${(await Promise.all(flatten(children))).join('')}</${f}>` 336 } 337 338 // function block 339 if (children && children.length > 0) { 340 props = props || {}; 341 props.children = await Promise.all(flatten(children)); 342 /*props.children = await Promise.all(props.children.map(t => { 343 const r = t.render ? t.render() : t; 344 return r; 345 }));*/ 346 } 347 348 return f.name === 'anonymous' ? f(Mars, props) : f(props); 349}; 350 351 352function editData(name, objectId, path, options = {}) { 353 const editUrl = `/mars/edit-data/${name}/blocks?objectId=${objectId || ''}&path=${path || 'Config'}`; 354 console.log('editUrl', editUrl) 355 Modal.open(`/api/RenderFormByModel?Id=RenderDataByModel1&modelName=${name}&path=${path || 'Config'}&collectionName=blocks&objectId=${objectId || ''}&iframeUrl=${encodeURIComponent(editUrl)}`, 356 { ...{ width: '550px', noPadding: true, title: `Edit ${name}` }, ...options }) 357} 358 359function editDataModel(name, objectId, options = {}) { 360 const editUrl = `/mars/edit-data-args/${name}`; 361 console.log('editUrl', editUrl) 362 Modal.open(`/api/RenderFormByModel?height=900px&Id=RenderDataByModel1&modelName=${name}&path=DataArgs&collectionName=blocks&objectId=${objectId || ''}&iframeUrl=${encodeURIComponent(editUrl)}`, 363 { ...{ width: '800px', height: '100%', noPadding: true, title: `Edit model: ${name}` }, ...options }) 364} 365 366window.Mars = { 367 executeAppBlock, 368 editData, 369 editDataModel, 370 awaitForBlock, 371 awaitForDomNode, 372}; 373 374// to create removeEventListeners - https://stackoverflow.com/a/47117084 375(function () { 376 const target = EventTarget.prototype; 377 const functionName = 'addEventListener'; 378 const func = target[functionName]; 379 380 const symbolHidden = Symbol('hidden'); 381 382 function hidden(instance) { 383 if (instance[symbolHidden] === undefined) { 384 const area = {}; 385 instance[symbolHidden] = area; 386 return area; 387 } 388 389 return instance[symbolHidden]; 390 } 391 392 function listenersFrom(instance) { 393 const area = hidden(instance); 394 if (!area.listeners) { area.listeners = []; } 395 return area.listeners; 396 } 397 398 target[functionName] = function (type, listener) { 399 if (!this) { 400 return; 401 } 402 403 const listeners = listenersFrom(this); 404 listeners.push({ type, listener }); 405 func.apply(this, [type, listener]); 406 }; 407 408 target['removeEventListeners'] = function (targetType) { 409 if (!this) { 410 return; 411 } 412 413 const self = this; 414 const listeners = listenersFrom(this); 415 listeners.forEach(item => { 416 const type = item.type; 417 const listener = item.listener; 418 if (type == targetType) { 419 self.removeEventListener(type, listener); 420 } 421 }); 422 }; 423})(); 424 425// to observe window.location.href changes 426let currentHref = document.location.href; 427window.onload = function () { 428 const observer = new MutationObserver(function (mutations) { 429 mutations.forEach(function (mutation) { 430 if (currentHref != document.location.href) { 431 currentHref = document.location.href; 432 window.dispatchEvent(new Event('onLocationChange')); 433 } 434 }); 435 }); 436 437 const body = document.querySelector('body'); 438 observer.observe(body, { childList: true, subtree: true }); 439}; 440window.resizeIFrameToFitContent = (iFrame) => { 441 const height = iFrame.contentWindow.document.body.scrollHeight; 442 iFrame.width = iFrame.contentWindow.document.body.scrollWidth; 443 iFrame.height = height > 550 ? height : 550; 444} 445 446window.scrollToAnchor = (topOffset) => { 447 if (location.hash && location.hash.length > 1) { 448 $('html, body').animate({ 449 scrollTop: $('h1,h2,h3,h4,h5,h6').filter(':contains("' + decodeURIComponent(location.hash.slice(1)) + '")').scroll().offset().top + (topOffset || 0) 450 }) 451 } 452} 453 454window.marsAlert = (message, status) => { 455 Modal.open('/api/MessageTemplate', { center: true, hideModalHeader: true, width: '350px', noPadding: true, hideCloseButton: true }, null, { message, status }) 456} 457/* load new page content when user clicks on an element with data-target-partial tag and prevent default navigation */ 458$(document).on('click', '[data-target-partial]', function (e) { 459 e.preventDefault(); 460 const targetUrl = $(this).attr('href'); 461 if (targetUrl) { 462 targetUrl.startsWith('http') || targetUrl.startsWith('www.') 463 ? window.open(targetUrl) 464 : window.goTo(targetUrl); 465 } 466 467 return false;
468}); 469 470window.history.replaceState(location.pathname, '', location.href); 471 472window.onpopstate = function (e) { 473 if (e.state != null) { 474 if (typeof (e.state) === 'string') window.goTo(e.state, true, null, true) 475 else window.goTo(e.state.targetUrl, true, e.state, true); 476 } 477} 478 479window.goTo = async (targetUrl, dontScroll, cachedData, goBack = false) => { 480 if (!targetUrl) targetUrl = location.href; 481 if (!goBack) { window.history.pushState(targetUrl, '', targetUrl); } 482 history.replaceState(targetUrl, null, targetUrl); 483 pageLoadSpinner.hidden = false; 484 485 function replaceHtmlOnPage(t) { 486 if (history.state !== targetUrl) return 487 488 const namedSlot = $(`#${t.data.master}`); 489 const slot = $(`[data-master-content]:first`); 490 491 // if the target page master is nested, then we reload the page since we cannot do ajax in this case 492 if (!$(`[data-master-content]`).toArray().map(t => t.id).includes(t.data.master)) { 493 location.reload(); 494 return; 495 } 496 window.dispatchEvent(new Event('locationchange')); 497 498 // if it is first level navigation we scroll to the top 499 if ($(`[data-master-content]`).length === 1 && !dontScroll) { 500 // console.log('scroll to top') 501 window.scrollTo(0, 0); 502 } 503 504 (namedSlot.length > 0 ? namedSlot : slot).html(typeof (t.data) === 'string' ? t.data : t.data.html); 505 pageLoadSpinner.hidden = true; 506 507 document.title = t.data.pageTitle; 508 // google analytics page view tracking 509 if (window.webMesurementId && gtag) { 510 window.gtag('event', 'page_view', { 511 page_title: document.title, 512 page_location: location.href, 513 page_path: location.pathname, 514 send_to: window.webMesurementId, 515 }); 516 } 517 518 scrollToAnchor(); 519 //history.pushState({ data: t.data, targetUrl: targetUrl }, null, targetUrl); 520 } 521 522 if (cachedData) { 523 replaceHtmlOnPage(cachedData); 524 } else { 525 return window.getRequest(targetUrl + (targetUrl.includes('?') ? '&' : '?') + 'noMaster=true').then(replaceHtmlOnPage).catch(function (reason) { console.error(reason); return reason; }); 526 } 527}
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.