1 2async function getMustacheTemplate(branch, callback) { 3 let response = await GET('mustache/get/'+branch, callback, 'json'); 4 if (callback != undefined) callback(response.results); 5 return response.results; 6} 7 8async function getMustacheIcon(callback) { 9 let response = await GET('mustache/icon/get', callback, 'json'); 10 if (callback != undefined) callback(response.results); 11 return response.results; 12} 13 14async function getExtensionMustacheTemplate(extension, branch, callback) { 15 let response = await GET(`mustache/extension/get/${extension}/${branch}`, callback, 'json'); 16 if (callback != undefined) callback(response.results); 17 return response.results; 18} 19 20async function getAllCountry(callback) { 21 let response = await GET('country/all', callback, 'json'); 22 if (callback != undefined) callback(response); 23 return response; 24} 25 26async function getLocale(language, oldLanguage, callback) { 27 let response = await GET('locale/'+language+'/'+oldLanguage, callback, 'json', true); 28 if (response == undefined) response = {results: {}} 29 if (callback != undefined) callback(response.results); 30 return response.results; 31} 32 33async function setTextLocale(text, callback) { 34 let response = await GET('locale/set/'+text.encodeHex(), callback, 'json'); 35 if (callback != undefined) callback(response); 36 return response; 37} 38 39async function setChunkTextLocale(data, callback) { 40 let response = await GET('locale/chunk/set', data, callback, 'json'); 41 if (callback != undefined) callback(response); 42 return response; 43} 44 45async function START(page) { 46 await main.init(); 47} 48 49String.prototype.encodeHex = function(){ 50 let encoder = new TextEncoder(); 51 let array = encoder.encode(this) 52 let result = ""; 53 for (let i=0; i < array.length; i++) { 54 result += array[i].toString(16); 55 } 56 return result 57} 58 59String.prototype.decodeHex = function(){ 60 let str = ''; 61 for (let n = 0; n < this.length; n += 2) { 62 str += String.fromCharCode(parseInt(this.substr(n, 2), 16)); 63 } 64 return str; 65} 66 67// async function sha256(str) { 68// return crypto.subtle.digest("SHA-256", new TextEncoder("utf-8").encode(str)).then(buf => { 69// return Array.prototype.map.call(new Uint8Array(buf), x=>(('00'+x.toString(16)).slice(-2))).join(''); 70// }); 71// } 72 73async function sha1(str) { 74 const enc = new TextEncoder(); 75 const hash = await crypto.subtle.digest('SHA-1', enc.encode(str)); 76 return Array.from(new Uint8Array(hash)) 77 .map(v => v.toString(16).padStart(2, '0')) 78 .join(''); 79} 80 81async function sha512(str) { 82 let hasher = new Sha512(); 83 let bytes = new TextEncoder().encode(str); 84 hasher.process(bytes); 85 hasher.finish(); 86 let hashedArray = Array.from(new Uint8Array(hasher.result)); 87 return hashedArray.map(b => b.toString(16).padStart(2, '0')).join(''); 88 // return crypto.subtle.digest("SHA-512", new TextEncoder("utf-8").encode(str)).then(buf => { 89 // return Array.prototype.map.call(new Uint8Array(buf), x=>(('00'+x.toString(16)).slice(-2))).join(''); 90 // }); 91} 92 93function randomString(length) { 94 let result = ''; 95 let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 96 let charactersLength = characters.length; 97 for (let i = 0; i < length; i++ ) { 98 result += characters.charAt(Math.floor(Math.random() * charactersLength)); 99 } 100 return result; 101} 102 103async function GET_TEMPLATE(name, isExtension) { 104 if (!isExtension) return eval(`TEMPLATE.${name}`); 105 if (window.EXTENSION_TEMPLATE == undefined) window.EXTENSION_TEMPLATE = {}; 106 if (window.EXTENSION_TEMPLATE[name] != undefined) return window.EXTENSION_TEMPLATE[name]; 107 let response = await GET('mustache/each/get/'+name); 108 window.EXTENSION_TEMPLATE[name] = response.results; 109 return response.results; 110} 111 112async function LOAD_CSS(url, callback) { 113 if (window.LOADED_CSS == undefined) window.LOADED_CSS = {}; 114 if (window.LOADED_CSS[url] != undefined) return; 115 return new Promise(function(resolve, reject) { 116 let script = document.createElement("link"); 117 script.onload = function() { 118 window.LOADED_CSS[url] = url; 119 resolve(); 120 if (callback != undefined) callback(); 121 } 122 script.setAttribute("rel", "stylesheet"); 123 script.setAttribute("type", "text/css"); 124 script.setAttribute("href", `${rootURL}${url}?${Date.now()}`); 125 document.getElementsByTagName("head")[0].appendChild(script); 126 }); 127} 128 129async function APPEND_LINK_TO_HEAD(rel, url) { 130 if (window.HEAD_LINK == undefined) window.HEAD_LINK = {}; 131 if (window.HEAD_LINK[url] != undefined) return; 132 return new Promise(function(resolve, reject) { 133 let script = document.createElement("link"); 134 script.onload = function() { 135 window.HEAD_LINK[url] = url; 136 resolve(); 137 } 138 script.setAttribute("rel", rel); 139 script.setAttribute("href", `${rootURL}${url}?${Date.now()}`); 140 document.getElementsByTagName("head")[0].appendChild(script); 141 }); 142} 143 144async function LOAD_JS(url, callback) { 145 if (window.LOADED_JS == undefined) window.LOADED_JS = {}; 146 if (window.LOADED_JS[url] != undefined) return; 147 return new Promise(function(resolve, reject) { 148 let script = document.createElement("script"); 149 script.onload = function(event) { 150 window.LOADED_JS[url] = url; 151 resolve(); 152 if (callback != undefined) callback(); 153 } 154 155 script.onerror = function(event){ 156 reject(event); 157 } 158 script.setAttribute("type", "text/javascript"); 159 script.setAttribute("src", `${rootURL}${url}?${Date.now()}`); 160 document.getElementsByTagName("head")[0].appendChild(script); 161 }); 162} 163 164async function LOAD_JS_EXTENSION(extension, url, callback) { 165 if (window.LOADED_JS == undefined) window.LOADED_JS = {}; 166 if (window.LOADED_JS[url] != undefined) return; 167 try { 168 let temp = url.split('/'); 169 temp = temp[temp.length-1] 170 let name = temp.split('.'); 171 name = name[0];
172 eval(name); 173 return; 174 } catch { 175 } 176 return new Promise(function(resolve, reject) { 177 let script = document.createElement("script"); 178 script.onload = function() { 179 window.LOADED_JS[url] = url; 180 resolve(); 181 if (callback != undefined) callback(); 182 } 183 script.setAttribute("type", "text/javascript"); 184 script.setAttribute("src", `${rootURL}share/${extension}/js/${url}?${Date.now()}`); 185 document.getElementsByTagName("head")[0].appendChild(script); 186 }); 187} 188 189async function GET_JS_EXTENSION(extension, name, callback) { 190 try { 191 let temp = eval(name); 192 if (typeof temp == 'function') return temp; 193 } catch (error) { 194 } 195 return new Promise(function(resolve, reject) { 196 let script = document.createElement("script"); 197 let urls = JS_EXTENSION[extension]; 198 if (urls == undefined) return; 199 let url = JS_EXTENSION[extension][name]; 200 if (url == undefined) return; 201 if (window.LOADED_JS == undefined) window.LOADED_JS = {}; 202 let path = `share/${extension}/js/${url}`; 203 script.onload = function() { 204 window.LOADED_JS[path] = path; 205 resolve(eval(name)); 206 if (callback != undefined) callback(); 207 } 208 script.onerror = function() { 209 resolve(undefined); 210 } 211 script.setAttribute("type", "text/javascript"); 212 script.setAttribute("src", `${rootURL}${path}?${Date.now()}`); 213 document.getElementsByTagName("head")[0].appendChild(script); 214 }); 215} 216 217async function INIT_STATE() { 218 window.addEventListener('popstate', async (event) => { 219 await RENDER_STATE(event); 220 }); 221} 222 223async function GET_CURRENT_PAGE(event) { 224 if (event == undefined) event = history; 225 let page = main.pageIDDict[event.state.PAGE]; 226 return page 227} 228 229 230async function RENDER_SARFUNKEL_STATE(event) { 231 if (event == undefined) event = history; 232 let query = new URLSearchParams(window.location.search); 233 let pageID = query.get('p'); 234 let page = main.pageIDDict[pageID]; 235 let isDynamic = query.get('dynamic'); 236 if (page == undefined && isDynamic == undefined) return; 237 if (page == undefined) { 238 page = new DynamicModelPage(main, undefined, query.get('m'), query.get('e')); 239 await page.onCreate(); 240 } 241 if (page.menu) { 242 await page.menu.handleHighlight() 243 } else if (page.menu == undefined) { 244 let tabPage = main.pageIDDict[page.tabPageID]; 245 if (tabPage && tabPage.menu) { 246 await tabPage.menu.handleHighlight(); 247 } 248 } 249 250 await SHOW_LOADING_DIALOG(async () => { 251 await page.renderByURL(query); 252 }); 253} 254 255function CLEAR_HIGHLIGHT_MENU() { 256 let menuItems = main.home.dom.menuBar.querySelectorAll('.menuItem'); 257 for (let item of menuItems) { 258 item.classList.remove('highlightMenu'); 259 } 260} 261 262async function RENDER_STATE(event) { 263 if (event == undefined) event = history; 264 let query = new URLSearchParams(window.location.search); 265 let state = event.state; 266 CLEAR_HIGHLIGHT_MENU(); 267 if (query.get('sfk') != null) return await RENDER_SARFUNKEL_STATE(event); 268 let pageID = query.get('pageID'); 269 if (pageID != null) { 270 state = query.get('state'); 271 state= JSON.parse(state.b64decode()); 272 } 273 let pageName = query.get('p'); 274 if ((pageName == null && pageID == null) || state == null) { 275 if (main.homeMenu != undefined) { 276 await main.homeMenu.dom.menu.click(); 277 } else { 278 await main.render(); 279 } 280 return; 281 } 282 let page = main.pageIDDict[state.PAGE]; 283 if (page == undefined) { 284 REDIRECT('backend'); 285 return; 286 } 287 try { 288 await RENDER_NAVIGATOR(state); 289 } catch (error) { 290 console.error(error); 291 } 292 if (state.isInit != undefined && state.isInit) { 293 let isSubMenu = false; 294 let menuDetail = main.menuDict[page.pageID]; 295 let parentID; 296 if (menuDetail && menuDetail.parent) { 297 parentID = menuDetail.parent; 298 isSubMenu = true; 299 } 300 if (state.isRenderFromTab) { 301 menuDetail = main.menuDict[state.tabPageID]; 302 if (menuDetail && menuDetail.parent) { 303 parentID = menuDetail.parent; 304 isSubMenu = true; 305 } 306 } 307 let subMenu = main.subMenu[page.pageID]; 308 if (subMenu != undefined) subMenu.isSubMenu = true; 309 310 if (menuDetail && !isSubMenu && subMenu != undefined) { 311 for (let item of subMenu) { 312 if (!item.html.classList.contains("hidden")) { 313 let subPage = main.pageIDDict[item.data.pageID]; 314 await subPage.highlightMenu(item.dom.menu, isSubMenu, false); 315 await page.highlightMenu(menuDetail.menu.dom.menu, false, false); 316 main.selectedSubMenu.push(item.dom.menu); 317 await subPage.setPageState(); 318 SHOW_LOADING_DIALOG(async function(){ 319 await subPage.onPrepareState(); 320 await subPage.render(); 321 });
322 return; 323 } 324 } 325 } 326 327 if (menuDetail && isSubMenu) { 328 let parent = main.menuDict[parentID]; 329 if (parent) await page.highlightMenu(parent.menu.dom.menu, false, true); 330 await page.highlightMenu(menuDetail.menu.dom.menu, isSubMenu, !isSubMenu); 331 if (parent) main.selectedMenu.push(parent.menu.dom.menu); 332 main.selectedSubMenu.push(menuDetail.menu.dom.menu); 333 } else if (menuDetail) { 334 await page.highlightMenu(menuDetail.menu.dom.menu, false, false); 335 main.selectedMenu.push(menuDetail.menu.dom.menu); 336 } 337 338 SHOW_LOADING_DIALOG(async function(){ 339 await page.onPrepareState(); 340 await page.render(state); 341 }); 342 } else { 343 SHOW_LOADING_DIALOG(async function(){ 344 await page.onPrepareState(); 345 await page.renderState(state); 346 await page.renderOtherState(state); 347 }); 348 } 349 // await RENDER_MOST_USED(page); 350} 351 352async function GET_STATE_URL(page, data) { 353 data.PAGE = page.pageID; 354 data.PAGE_NAME = page.title; 355 state = JSON.stringify(data); 356 state = state.b64encode(); 357 // let url = await sha1(`${randomString(10)}_${Date.now()}`); 358 // localStorage.setItem(url, state); 359 return window.location.pathname + `?pageID=${page.pageID}&title=${page.title}&state=${state}`; 360 // return rootURL + `?pageID=${page.pageID}&title=${page.title}&state=${state}`; 361 // return rootURL + `?p=${url}`; 362} 363 364function PUSH_SARFUNKEL_STATE(url) { 365 let current = window.location.search; 366 if (url == current) return; 367 history.pushState(undefined, '', window.location.pathname+url); 368} 369 370function REPLACE_SARFUNKEL_STATE(url) { 371 let current = window.location.search; 372 if (url == current) return; 373 history.replaceState(undefined, '', window.location.pathname+url); 374} 375 376async function PUSH_STATE(page, data, url) { 377 if(history.state){ 378 let state = history.state; 379 let dataPAGE = url.split('/')[0]; 380 let dataState = url.split('/')[1]; 381 if(dataState == undefined && data.state == undefined) dataState = ''; 382 if(state.PAGE == dataPAGE && state.state == dataState) return; 383 else if(state.PAGE == dataPAGE && dataState == undefined) return; 384 } 385 data.PAGE = page.pageID; 386 data.PAGE_NAME = page.title; 387 state = JSON.stringify(data) 388 state = state.b64encode() 389 390 let pathName = ""; 391 // localStorage.setItem(url, state); 392 if (!data.isLegacy) { 393 let parameter = `?pageID=${page.pageID}&title=${page.title}&state=${state}` 394 pathName = window.location.pathname + parameter; 395 } else { 396 // url = await sha1(`${randomString(10)}_${Date.now()}`); 397 url = `${randomString(10)}_${Date.now()}`.hashCode(); 398 pathName = window.location.pathname + '?p='+url; 399 } 400 history.pushState(data, '', pathName); 401 await RENDER_NAVIGATOR(data); 402} 403 404async function PUSH_SIMPLE_STATE(data, url = '/'){ 405 let oldURL = GET_PARAMS_FROM_URL(); 406 let length = Object.keys(data).length; 407 let count = 0; 408 for(let i in data){ 409 if(oldURL[i] != undefined && oldURL[i] == data[i]) count = count + 1; 410 } 411 if(count == length) return; 412 let params = []; 413 for (let i in data) { 414 params.push(`${i}=${data[i]}`); 415 } 416 url = url + '?' + params.join('&'); 417 history.pushState(data, '', url); 418} 419 420function GET_PARAMS_FROM_URL(){ 421 const params = new URLSearchParams(location.search); 422 let data = {}; 423 let keys = params.keys(); 424 for (let key of keys) { 425 data[key] = params.get(key); 426 } 427 return data; 428} 429 430async function CREATE_MENU(pageID, name, icon, isSubMenu, isImage, hasAdd=false, addCallBack=undefined) { 431 if (isImage == undefined) isImage = false; 432 let iconDict = {}; 433 if (!isImage) iconDict = await CREATE_SVG_ICON(icon); 434 else iconDict = await CREATE_IMAGE_ICON(icon); 435 let menu = {'name': name, 'isSVG': iconDict.isSVG, 'icon': iconDict.icon, 'hasAdd': hasAdd, 'isMobile': isMobile()}; 436 let tag; 437 if (isSubMenu == undefined) isSubMenu = false; 438 let page = main.pageIDDict[pageID]; 439 if (page == undefined) return; 440 let url = await page.getPageStateURL(); 441 menu.url = url; 442 menu.pageID = pageID; 443 if (isSubMenu) tag = new DOMObject(TEMPLATE.SubMenuItem, menu); 444 else tag = new DOMObject(TEMPLATE.MenuItem, menu); 445 446 main.home.dom.container.onclick = function(){ 447 main.home.dom.subMenuContainer.hide(); 448 } 449 tag.dom.link.onclick = async function(e) { 450 e.preventDefault(); 451 } 452 if (!isSubMenu) { 453 tag.dom.menu.addEventListener('click', async function(e) { 454 e.preventDefault(); 455 if (tag.hasChild) { 456 // await page.highlightMenu(tag.dom.menu, isSubMenu, true); 457 main.selectedMenu.push(tag.dom.menu); 458 main.home.dom.menuName.html(name); 459 await APPEND_SUB_MENU(main.subMenu[pageID]); 460 main.home.dom.subMenuContainer.show(); 461 462 } else { 463 await page.highlightMenu(tag.dom.menu, isSubMenu, false); 464 main.selectedMenu.push(tag.dom.menu); 465 if (isMobile()) main.home.dom.menuContainer.classList.add('hidden'); 466 await page.setPageState(); 467 SHOW_LOADING_DIALOG(async function(){ 468 await page.onPrepareState(); 469 await page.render(); 470 }); 471 main.home.dom.subMenuContainer.hide(); 472 await setMostUsed(page); 473 // await RENDER_MOST_USED(page); 474 } 475 await RENDER_NAVIGATOR(); 476 }); 477 } else { 478 tag.dom.menuButton.addEventListener('click', async function(e) { 479 e.preventDefault(); 480 if (isMobile()) main.home.dom.menuContainer.classList.add('hidden'); 481 await page.highlightMenu(tag.dom.menu, isSubMenu, false); 482 main.selectedSubMenu.push(tag.dom.menu); 483 await page.setPageState(); 484 SHOW_LOADING_DIALOG(async function(){ 485 await page.onPrepareState(); 486 await page.render(); 487 }); 488 main.home.dom.subMenuContainer.hide(); 489 await RENDER_NAVIGATOR(); 490 await setMostUsed(page); 491 // await RENDER_MOST_USED(page); 492 }); 493 if(tag.dom.add){ 494 if(!CHECK_PERMISSION_USER(page.extension, page.role, ['WRITE'])) tag.dom.add.remove(); 495 else{ 496 tag.dom.add.addEventListener('click', async function(e) { 497 if (isMobile()) main.home.dom.menuContainer.classList.add('hidden'); 498 await page.highlightMenu(tag.dom.menu, isSubMenu, false); 499 main.selectedSubMenu.push(tag.dom.menu); 500 SHOW_LOADING_DIALOG(async function(){ 501 await page.onPrepareState(); 502 if(addCallBack == undefined) await page.renderView(page.model); 503 else await addCallBack(page); 504 });
505 main.home.dom.subMenuContainer.hide(); 506 await setMostUsed(page); 507 }); 508 } 509 } 510 } 511 512 async function setMostUsed(page){ 513 if(localStorage.getItem('mostUsed') == null) localStorage.setItem('mostUsed', JSON.stringify({})); 514 let mostUsed = JSON.parse(localStorage.getItem('mostUsed')); 515 if(mostUsed[page.pageID] == undefined){ 516 mostUsed[page.pageID] = {}; 517 mostUsed[page.pageID].count = 0; 518 mostUsed[page.pageID].pageID = page.pageID; 519 } 520 mostUsed[page.pageID].title = page.title; 521 mostUsed[page.pageID].extension = page.extension; 522 mostUsed[page.pageID].count += 1; 523 localStorage.setItem('mostUsed', JSON.stringify(mostUsed)); 524 } 525 return tag; 526} 527 528async function RENDER_NAVIGATOR(config){ 529 let isSetNavigator = true; 530 if(config != undefined && main.pageIDDict[config.PAGE]){ 531 if(main.pageIDDict[config.PAGE].isSetNavigator == undefined) main.pageIDDict[config.PAGE].isSetNavigator = true; 532 isSetNavigator = main.pageIDDict[config.PAGE].isSetNavigator; 533 if(!isSetNavigator){ 534 let navigator = main.personalBar.home.dom.navigator; 535 navigator.html(''); 536 return; 537 } 538 } 539 let state = history.state; 540 if (config != undefined) state = config; 541 if (main.personalBar != undefined && state != undefined && state.PAGE_NAME != undefined) { 542 let navigator = main.personalBar.home.dom.navigator; 543 navigator.html(''); 544 let parent = main.pageIDDict[state.PAGE].parent; 545 if(parent.parentID == undefined && parent.menu != undefined){ 546 let name = parent.menu.data.name; 547 if(main.pageIDDict[state.PAGE].referencePage != undefined){ 548 let referencePage = main.pageIDDict[state.PAGE].referencePage; 549 let page = main.pageIDDict[referencePage]; 550 name = page.parent.menu.data.name; 551 } 552 navigator.html(new DOMObject(`<div class="" localize>${name}</div>`)); 553 let icon = await CREATE_SVG_ICON('ChevronRight'); 554 navigator.append(new DOMObject(icon.icon)); 555 } 556 if(main.pageIDDict[state.PAGE].referencePage != undefined){ 557 let referencePage = main.pageIDDict[state.PAGE].referencePage; 558 let page = main.pageIDDict[referencePage]; 559 let button = new DOMObject(`<div class="item" localize>${page.title}</div>`); 560 navigator.append(button); 561 button.html.onclick = async function(){ 562 await page.render(state); 563 if (state.state) await page.setPageState(); 564 else page.setPageState(state); 565 } 566 }else{ 567 let button = new DOMObject(`<div class="item" localize>${state.PAGE_NAME}</div>`); 568 navigator.append(button); 569 button.html.onclick = async function(){ 570 let page = main.pageIDDict[state.PAGE]; 571 // if(page.referencePage){ 572 // page = main.pageIDDict[page.referencePage]; 573 // await page.render(); 574 // page.home.dom.menuList[event.state.PAGE].onclick(); 575 // }else 576 await page.render(state); 577 if (state.state) await page.setPageState(); 578 else page.setPageState(state); 579 // RENDER_STATE(); 580 // main.pageIDDict[state.PAGE].render(); 581 } 582 } 583 584 // if(parent.parentPageID != undefined && parent.parentID == undefined && parent.menu != undefined){ 585 // navigator.html(new DOMObject(`<div class="" localize>${parent.parentPageID}</div>`)); 586 // let icon = await CREATE_SVG_ICON('ChevronRight'); 587 // navigator.append(new DOMObject(icon.icon)); 588 // if(parent.parentID == undefined && parent.menu != undefined){ 589 // let button = new DOMObject(`<div class="item" localize>${parent.menu.data.name}</div>`) 590 // navigator.append(button); 591 // button.html.onclick = async function(){ 592 // console.log(config); 593 // await parent.render(); 594 // await parent.setPageState(); 595 // } 596 // let icon = await CREATE_SVG_ICON('ChevronRight'); 597 // navigator.append(new DOMObject(icon.icon)); 598 // } 599 // let button = new DOMObject(`<div class="" localize>${state.PAGE_NAME}</div>`); 600 // navigator.append(button); 601 // }else{ 602 // if(parent.parentID == undefined && parent.menu != undefined){ 603 // navigator.html(new DOMObject(`<div class="" localize>${parent.menu.data.name}</div>`)); 604 // let icon = await CREATE_SVG_ICON('ChevronRight'); 605 // navigator.append(new DOMObject(icon.icon)); 606 // } 607 // let button = new DOMObject(`<div class="item" localize>${state.PAGE_NAME}</div>`); 608 // navigator.append(button); 609 // button.html.onclick = async function(){ 610 // let page = main.pageIDDict[state.PAGE]; 611 // if(page.referencePage){ 612 // page = main.pageIDDict[page.referencePage]; 613 // await page.render(); 614 // page.home.dom.menuList[state.PAGE].onclick(); 615 // }else await page.render(); 616 // await page.setPageState(); 617 // // RENDER_STATE();
618 // // main.pageIDDict[state.PAGE].render(); 619 // } 620 // } 621 } 622 if(state == undefined) return; 623 if (main.personalBar != undefined && state != undefined && state.title != undefined){ 624 let navigator = main.personalBar.home.dom.navigator; 625 let icon = await CREATE_SVG_ICON('ChevronRight'); 626 navigator.append(new DOMObject(icon.icon)); 627 if(state.data == undefined){ 628 navigator.append(new DOMObject(`<div class="" localize>Add</div>`)); 629 }else{ 630 if(state.isView) navigator.append(new DOMObject(`<div class="" localize>View</div>`)); 631 else navigator.append(new DOMObject(`<div class="" localize>Edit</div>`)); 632 } 633 } else if (main.pageIDDict[state.PAGE] != undefined && main.pageIDDict[state.PAGE].referencePage != undefined){ 634 let navigator = main.personalBar.home.dom.navigator; 635 let icon = await CREATE_SVG_ICON('ChevronRight'); 636 navigator.append(new DOMObject(icon.icon)); 637 navigator.append(new DOMObject(`<div class="" localize>${main.pageIDDict[state.PAGE].title}</div>`)); 638 } 639} 640 641async function RENDER_MOST_USED(page){ 642 if(localStorage.getItem('mostUsed') == null) return; 643 let mostUsed = JSON.parse(localStorage.getItem('mostUsed')); 644 let mostUsedList = Object.keys(mostUsed).map(function(key) { 645 return [key, mostUsed[key]]; 646 }); 647 mostUsedList.sort(function(a, b) { 648 return b[1].count - a[1].count; 649 }); 650 if(page.home == undefined) return; 651 page.home.dom.mostUsed.html(''); 652 let extension = {}; 653 for(let i in mostUsedList){ 654 if(extension[mostUsedList[i][1].extension] == undefined) extension[mostUsedList[i][1].extension] = []; 655 extension[mostUsedList[i][1].extension].push(mostUsedList[i][1]); 656 if(i == 4) break; 657 } 658 for(let i in extension){ 659 let title = `${i.charAt(0).toUpperCase()}${i.substring(1, i.length)}`; 660 title = `<div class="bold" style="padding:10px 15px;user-select:none;text-decoration:underline;">${title}</div>`; 661 if(i != 'undefined') page.home.dom.mostUsed.append(title); 662 for(let j in extension[i]){ 663 let onclickEvent = `RENDER_MOST_USED_PAGE(main.pageIDDict['${extension[i][j].pageID}'])`; 664 let menu = { 665 onclickEvent: onclickEvent, 666 name: main.pageIDDict[extension[i][j].pageID].title, 667 } 668 let domObject = new DOMObject(TEMPLATE.MostUsedItem, menu); 669 if(i == 'undefined') domObject.html.style = 'padding:10px 15px;'; 670 page.home.dom.mostUsed.append(domObject); 671 } 672 } 673} 674 675async function RENDER_MOST_USED_PAGE(page){ 676 await page.setPageState(); 677 await SHOW_LOADING_DIALOG(async () => { 678 await page.onPrepareState(); 679 await page.render(); 680 }); 681 // await RENDER_MOST_USED(page); 682} 683 684let LOADING_DIALOG_DEPTH = 0; 685async function SHOW_LOADING_DIALOG(callback){ 686 LOADING_DIALOG_DEPTH += 1; 687 main.home.dom.loading.classList.add('!z-[99999]'); 688 main.home.dom.loading.show(); 689 try{ 690 if(callback != undefined) await callback(); 691 }catch(e){ 692 console.error(e); 693 SHOW_ALERT_DIALOG(e); 694 }finally{ 695 LOADING_DIALOG_DEPTH -= 1; 696 if(LOADING_DIALOG_DEPTH <= 0){ 697 LOADING_DIALOG_DEPTH = 0; 698 main.home.dom.loading.hide(); 699 } 700 } 701} 702 703function FORCE_HIDE_LOADING_DIALOG(){ 704 LOADING_DIALOG_DEPTH = 0; 705 main.home.dom.loading.hide(); 706} 707 708async function SHOW_PRE_LOADING_DIALOG(callback){ 709 let body = document.querySelector('body'); 710 let content = `<div class="abstract_dialog hidden" rel="loading"> 711 <div class="abstract_dialog_container abstract_loading"> 712 <div class="flex-column gap-20px"> 713 <div class="flex center"><img src="{{{rootURL}}}share/icon/loading.gif"></div> 714 <div localize>Loading</div> 715 </div> 716 </div> 717 </div>`; 718 let dialog = new DOMObject(content, rootURL); 719 body.appendChild(dialog.html); 720 dialog.dom.loading.show(); 721 if(callback != undefined) await callback(); 722 dialog.dom.loading.hide(); 723} 724 725async function CREATE_IMAGE_ICON(path) { 726 return {'isSVG': false, 'icon': path}; 727} 728 729async function CREATE_SVG_ICON(name) { 730 if (Object.keys(ICON).length == 0) ICON = await getMustacheIcon(); 731 if (name == undefined) return {'isSVG': true, 'icon': ''}; 732 let items = name.split('.'); 733 let template = JSON.parse(JSON.stringify(ICON)); 734 for (let item of items) { 735 if (template[item] != undefined) template = template[item] 736 else break 737 } 738 if (typeof template == 'object') template = ''; 739 return {'isSVG': true, 'icon': template}; 740} 741 742async function APPEND_SUB_MENU(subMenu) { 743 main.home.dom.subMenuBar.html(''); 744 for(let i in subMenu){ 745 subMenu[i].isSubMenu = true; 746 main.home.dom.subMenuBar.append(subMenu[i]); 747 subMenu[i].renderLocalize(); 748 } 749} 750 751function GET_PAGE_NAME(label) { 752 return label.replace(/ /g, '') + 'Page'; 753} 754 755function isMobile() { 756 return /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()); 757} 758 759function isTablet() { 760 return /(ipad|tablet|(android(?!.*mobile))|(windows(?!.*phone)(.*touch))|kindle|playbook|silk|(puffin(?!.*(IP|AP|WP))))
760/.test(navigator.userAgent.toLowerCase()); 761} 762 763function swapArrayIndex(array, origin, destination) { 764 let temp = JSON.parse(JSON.stringify(array)); 765 let value = temp[origin]; 766 array.splice(origin, 1) 767 array.splice(destination, 0, value); 768} 769 770function getScheduleEventType(eventType) { 771 if (GLOBAL.SCHEDULE_EVENT_TYPE == undefined) return; 772 return GLOBAL.SCHEDULE_EVENT_TYPE[eventType]; 773} 774 775function getNotificationEventType(eventType) { 776 if (GLOBAL.NOTIFICATION_EVENT_TYPE == undefined) return; 777 return GLOBAL.NOTIFICATION_EVENT_TYPE[eventType]; 778} 779 780async function OPEN_FILE(blob, fileName) { 781 let objectURL = window.URL.createObjectURL(blob); 782 window.open(objectURL); 783} 784 785async function LOAD_FILE(filePath) { 786 let result = null; 787 let xmlhttp = new XMLHttpRequest(); 788 xmlhttp.open("GET", filePath, false); 789 xmlhttp.send(); 790 if (xmlhttp.status==200) { 791 result = xmlhttp.responseText; 792 } 793 return result; 794} 795 796function arrayBufferToBase64(buffer) { 797 let binary = ''; 798 let bytes = new Uint8Array(buffer); 799 let len = bytes.byteLength; 800 for (let i = 0; i < len; i++) { 801 binary += String.fromCharCode(bytes[ i ]); 802 } 803 return btoa(binary); 804} 805 806function uint8ArrayToBase64(bytes) { 807 let binary = ''; 808 let len = bytes.byteLength; 809 for (let i = 0; i < len; i++) { 810 binary += String.fromCharCode(bytes[ i ]); 811 } 812 return btoa(binary); 813} 814 815function arrayBufferFromBase64(text) { 816 let array = Uint8Array.from(atob(text), c => c.charCodeAt(0)); 817 return array.buffer; 818} 819 820async function REDIRECT(url) { 821 location.href = `${rootURL}${url}`; 822} 823 824async function GET_PICTURE_FROM_CAMERA() { 825 826} 827 828async function SHOW_ALERT_DIALOG(text, callback){ 829 let dialog = new DOMObject(TEMPLATE.AlertDialog, {text: text}); 830 main.home.dom.alertDialog.html(dialog); 831 832 let body = document.getElementsByTagName('body')[0]; 833 body.style.overflow = 'hidden'; 834 dialog.html.style.top = `${window.pageYOffset}px`; 835 836 dialog.dom.confirm.onclick = async function(){ 837 await CLOSE_ALERT_DIALOG(); 838 if(callback != undefined) callback(); 839 } 840 return dialog; 841} 842 843async function SHOW_CONFIRM_DIALOG(text, confirmCallback, cancelCallback){ 844 845 let dialog = new DOMObject(TEMPLATE.ConfirmDialog, {text: text, isForm: false}); 846 if (typeof text == 'object') { 847 dialog.dom.body.innerHTML = ""; 848 dialog.dom.body.appendChild(text.html); 849 } 850 main.home.dom.alertDialog.html(dialog); 851 852 let body = document.getElementsByTagName('body')[0]; 853 body.style.overflow = 'hidden'; 854 dialog.html.style.top = `${window.pageYOffset}px`; 855 856 dialog.dom.confirm.onclick = async function(){ 857 await CLOSE_ALERT_DIALOG(); 858 if(confirmCallback != undefined) confirmCallback(); 859 } 860 dialog.dom.cancel.onclick = async function(){ 861 await CLOSE_ALERT_DIALOG(); 862 if(cancelCallback != undefined) cancelCallback(); 863 } 864 return dialog; 865} 866 867async function SHOW_FINISHED_DIALOG(text, callback){ 868 let dialog = new DOMObject(TEMPLATE.FinishedDialog, {text: text, isForm: false}); 869 main.home.dom.alertDialog.html(dialog); 870 871 let body = document.getElementsByTagName('body')[0]; 872 body.style.overflow = 'hidden'; 873 dialog.html.style.top = `${window.pageYOffset}px`; 874 875 dialog.dom.confirm.onclick = async function(){ 876 await CLOSE_ALERT_DIALOG(); 877 if(callback != undefined) callback(); 878 } 879 return dialog; 880} 881 882async function SHOW_CONFIRM_DELETE_DIALOG(text, confirmCallback, cancelCallback){ 883 let dialog = new DOMObject(TEMPLATE.ConfirmDeleteDialog, {text: text, isForm: false}); 884 main.home.dom.alertDialog.html(dialog); 885 886 let body = document.getElementsByTagName('body')[0]; 887 body.style.overflow = 'hidden'; 888 dialog.html.style.top = `${window.pageYOffset}px`; 889 890 dialog.dom.confirm.onclick = async function(){ 891 await CLOSE_ALERT_DIALOG(); 892 if(confirmCallback != undefined) confirmCallback(); 893 } 894 dialog.dom.cancel.onclick = async function(){ 895 await CLOSE_ALERT_DIALOG(); 896 if(cancelCallback != undefined) cancelCallback(); 897 } 898 return dialog; 899} 900 901async function SHOW_INFORMATION_DIALOG(text, callback){ 902 let dialog = new DOMObject(TEMPLATE.InformationDialog, {text: text, isForm: false}); 903 main.home.dom.alertDialog.html(dialog); 904 905 let body = document.getElementsByTagName('body')[0]; 906 body.style.overflow = 'hidden'; 907 dialog.html.style.top = `${window.pageYOffset}px`; 908 909 dialog.dom.confirm.onclick = async function(){ 910 await CLOSE_ALERT_DIALOG(); 911 if(callback != undefined) callback(); 912 } 913 return dialog; 914} 915 916async function SHOW_BLANK_DIALOG(title, text, color, cancelCallback){ 917 let dialog = new DOMObject(TEMPLATE.BlankDialog, {title: title, text: text, color: color, isForm: false}); 918 main.home.dom.alertDialog.html(dialog); 919 920 let body = document.getElementsByTagName('body')[0]; 921 body.style.overflow = 'hidden'; 922 dialog.html.style.top = `${window.pageYOffset}px`; 923 924 dialog.dom.cancel.onclick = async function(){ 925 await CLOSE_ALERT_DIALOG(); 926 if(cancelCallback != undefined) cancelCallback(); 927 } 928 return dialog; 929} 930 931async function SHOW_IMAGE_PREVIEW(path){ 932 let dialog = new DOMObject(TEMPLATE.ImagePreview, {path}); 933 main.home.dom.alertDialog.html(dialog); 934 let body = document.getElementsByTagName('body')[0]; 935 body.style.overflow = 'hidden'; 936 dialog.html.style.top = `${window.pageYOffset}px`; 937 938 dialog.dom.close.onclick = async function(){ 939 await CLOSE_ALERT_DIALOG(); 940 } 941 return dialog; 942} 943 944async function CLOSE_ALERT_DIALOG(){ 945 main.home.dom.alertDialog.html(''); 946 let body = document.getElementsByTagName('body')[0]; 947 body.style.overflowY = 'auto'; 948} 949 950function START_PAGE_AFTER_LOAD(start){ 951 document.addEventListener("DOMContentLoaded", function(event){ 952 if(isPreload){ 953 preloader = new Preloader(); 954 preloader.preload(preloadJS, preloadCSS).then(function(){ 955 start(); 956 }); 957 }else{ 958 start(); 959 } 960 }); 961} 962 963function SHOW_LOCATION_VIEWER(positions, labels, colors, callbacks){ 964 function findCenter(positions) { 965 const lats = positions.map(m => m[1]); 966 const lngs = positions.map(m => m[0]); 967 return { 968 lat: (Math.min(...lats) + Math.max(...lats)) / 2, 969 lng: (Math.min(...lngs) + Math.max(...lngs)) / 2 970 }; 971 } 972 973 let center = findCenter(positions) 974 let dialog = new DOMObject(TEMPLATE.LocationPickerDialog, {text: "Position", isForm: false, height: `calc(90vh - 97px)`, width: "90vw"}); 975
976 const map = L.map(dialog.dom.body).setView([center.lat, center.lng], 14); 977 L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map); 978 map._onResize(); 979 980 const markersGroup = L.layerGroup(); 981 map.addLayer(markersGroup); 982 983 let template = `<svg width="36" height="36" viewBox="0 0 24 24"><path fill="{{color}}" d="M12,11.5A2.5,2.5 0 0,1 9.5,9A2.5,2.5 0 0,1 12,6.5A2.5,2.5 0 0,1 14.5,9A2.5,2.5 0 0,1 12,11.5M12,2A7,7 0 0,0 5,9C5,14.25 12,22 12,22C12,22 19,14.25 19,9A7,7 0 0,0 12,2Z" /></svg>` 984 985 markersGroup.clearLayers(); 986 for (let i = 0; i < positions.length; i++) { 987 let marker = L.marker([positions[i][1], positions[i][0]], { 988 icon: L.divIcon({ 989 className: "marker-icon", 990 html: Mustache.render(template, {color: colors[i]}), 991 iconSize: [36, 36], 992 iconAnchor: [18, 36], 993 }) 994 }).addTo(markersGroup); 995 // marker.bindTooltip(labels[i], {permanent: true, direction: 'bottom', opacity: 1}).openTooltip(); 996 marker.on('click', function(e) { 997 callbacks[i](); 998 CLOSE_ALERT_DIALOG(); 999 }); 1000 } 1001 1002 main.home.dom.alertDialog.html(dialog); 1003 dialog.dom.container.style.maxWidth = '90vw'; 1004 dialog.dom.container.style.maxHeight = '90vh'; 1005 dialog.dom.container.style.top = '5vh'; 1006 // dialog.dom.container.style.maxWidth = '80vw'; 1007 1008 let body = document.getElementsByTagName('body')[0]; 1009 body.style.overflow = 'hidden'; 1010 dialog.html.style.top = `${window.pageYOffset}px`; 1011 dialog.dom.title.html('Location Viewer'); 1012 dialog.dom.cancel.html('Close'); 1013 dialog.dom.confirm.hide(); 1014 dialog.dom.cancel.onclick = async function(){ 1015 await CLOSE_ALERT_DIALOG(); 1016 } 1017 return dialog; 1018} 1019 1020async function getDateRangeInput() { 1021 let timeType = 'date'; 1022 let now = new Date(); 1023 let view = new DOMObject(await TEMPLATE.get("DateRangeInput"), {rootURL}); 1024 let startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 6); 1025 let endDate = now; 1026 1027 function setDate(startDate, endDate) { 1028 view.dom.start.value = `${startDate.getFullYear()}-${String(startDate.getMonth()+1).padStart(2, '0')}-${String(startDate.getDate()).padStart(2, '0')}`; 1029 view.dom.end.value = `${endDate.getFullYear()}-${String(endDate.getMonth()+1).padStart(2, '0')}-${String(endDate.getDate()).padStart(2, '0')}`; 1030 let formatter = new Intl.DateTimeFormat(LANGUAGE, {year: "numeric", month: "long", day: '2-digit'}); 1031 view.dom.filter.innerHTML = `${formatter.format(startDate)} - ${formatter.format(endDate)}` 1032 1033 view.dom.start.max = view.dom.end.value; 1034 view.dom.end.min = view.dom.start.value; 1035 } 1036 1037 setDate(startDate, endDate); 1038 view.dom.lastSevenDays.classList.add('highlight'); 1039 1040 view.dom.filterContainer.onclick = async function() { 1041 view.dom.filterContextMenu.classList.toggle('hideMenuOnMobile'); 1042 } 1043 1044 function highlightMenu(tag) { 1045 let contextMenus = view.html.getElementsByClassName("contextMenu"); 1046 for (let contextMenu of contextMenus) { 1047 contextMenu.classList.remove('highlight'); 1048 } 1049 tag.classList.add('highlight'); 1050 view.dom.customRageContainer.classList.add('hidden'); 1051 view.dom.filterContextMenu.classList.remove('expanded') 1052 } 1053 1054 function getFilterData() { 1055 let result = { 1056 value: {}, 1057 date: {}, 1058 month: {}, 1059 year: {} 1060 }; 1061 let startTime = new Date(view.dom.start.value); 1062 let endTime = new Date(view.dom.end.value); 1063 1064 result.value.start = view.dom.start.value; 1065 result.value.end = view.dom.end.value; 1066 1067 result.date.start = dateToDateID(view.dom.start.value); 1068 result.date.end = dateToDateID(view.dom.end.value); 1069 result.timeType = timeType; 1070 1071 result.month.start = 12 * (startTime.getFullYear() - 1970) + (startTime.getMonth() + 1); 1072 result.month.end = 12 * (endTime.getFullYear() - 1970) + (endTime.getMonth() + 1); 1073 1074 result.year.start = startTime.getFullYear(); 1075 result.year.end = endTime.getFullYear(); 1076 return result 1077 } 1078 1079 view.dom.today.onclick = async function() { 1080 let now = new Date(); 1081 setDate(now, now); 1082 highlightMenu(this); 1083 timeType = 'date'; 1084 view.refresh(); 1085 } 1086 1087 view.dom.yesterday.onclick = async function() { 1088 let now = new Date(); 1089 now.setDate(now.getDate() - 1); 1090 timeType = 'date'; 1091 setDate(now, now); 1092 highlightMenu(this); 1093 view.refresh();
1094 } 1095 1096 view.dom.lastSevenDays.onclick = async function() { 1097 let now = new Date(); 1098 let start = new Date(); 1099 start.setDate(start.getDate() - 6); 1100 timeType = 'date'; 1101 setDate(start, now); 1102 highlightMenu(this); 1103 view.refresh(); 1104 } 1105 1106 view.dom.lastThirtyDays.onclick = async function() { 1107 let now = new Date(); 1108 let start = new Date(); 1109 start.setDate(start.getDate() - 29); 1110 timeType = 'date'; 1111 setDate(start, now); 1112 highlightMenu(this); 1113 view.refresh(); 1114 } 1115 1116 view.dom.thisMonth.onclick = async function() { 1117 let now = new Date(); 1118 let start = new Date(now.getFullYear(), now.getMonth(), 1); 1119 let end = new Date(now.getFullYear(), now.getMonth() + 1, 0); 1120 timeType = 'date'; 1121 setDate(start, end); 1122 highlightMenu(this); 1123 view.refresh(); 1124 } 1125 1126 view.dom.lastMonth.onclick = async function() { 1127 let now = new Date(); 1128 let start = new Date(now.getFullYear(), now.getMonth() - 1, 1); 1129 let end = new Date(now.getFullYear(), now.getMonth(), 0); 1130 timeType = 'date'; 1131 setDate(start, end); 1132 highlightMenu(this); 1133 view.refresh(); 1134 } 1135 1136 view.dom.thisYear.onclick = async function() { 1137 let now = new Date(); 1138 let start = new Date(now.getFullYear(), 0, 1); 1139 let end = new Date(now.getFullYear(), 12, 0); 1140 timeType = 'month'; 1141 setDate(start, end); 1142 highlightMenu(this); 1143 view.refresh(); 1144 } 1145 1146 view.dom.lastYear.onclick = async function() { 1147 let now = new Date(); 1148 let start = new Date(now.getFullYear() - 1, 0, 1); 1149 let end = new Date(now.getFullYear() - 1, 12, 0); 1150 timeType = 'month'; 1151 setDate(start, end); 1152 highlightMenu(this); 1153 view.refresh(); 1154 } 1155 1156 view.dom.lastFiveYears.onclick = async function() { 1157 let now = new Date(); 1158 let start = new Date(now.getFullYear() - 4, 0, 1); 1159 let end = new Date(now.getFullYear(), 12, 0); 1160 timeType = 'year'; 1161 setDate(start, end); 1162 highlightMenu(this); 1163 view.refresh(); 1164 } 1165 1166 view.dom.customRange.onclick = async function() { 1167 highlightMenu(this); 1168 view.dom.customRageContainer.classList.remove('hidden'); 1169 view.dom.filterContextMenu.classList.add('expanded') 1170 } 1171 1172 view.dom.start.onchange = async function() { 1173 let start = new Date(view.dom.start.value); 1174 let end = new Date(view.dom.end.value); 1175 setDate(start, end); 1176 view.refresh(); 1177 } 1178 view.dom.end.onchange = async function() { 1179 view.refresh(); 1180 } 1181 1182 view.refresh = async function() { 1183 if (view.onchange != undefined) { 1184 let value = getFilterData(); 1185 view.onchange(value); 1186 } 1187 } 1188 view.getFilterData = getFilterData; 1189 return view; 1190} 1191 1192const isInStandaloneMode = () => (window.matchMedia('(display-mode: standalone)').matches) || (window.navigator.standalone) || document.referrer.includes('android-app://'); 1193 1194FormData.prototype.isEmpty = function() { 1195 return this.entries().next().done; 1196} 1197 1198function CHECK_ROOT_USER(){ 1199 IS_ROOT = false; 1200 if(GLOBAL.USER.permissions.indexOf('root') != -1) IS_ROOT = true; 1201 return IS_ROOT; 1202} 1203 1204function CHECK_PERMISSION_USER(extension, roles, permissions){ 1205 if(CHECK_ROOT_USER()) return true; 1206 for(let i in roles){ 1207 let role = roles[i]; 1208 for(let j in permissions){ 1209 let permission = permissions[j]; 1210 if(GLOBAL.USER.permissions.indexOf(`${extension}.${role}.${permission}`) != -1) return true; 1211 } 1212 } 1213 return false; 1214} 1215 1216async function SEND_OPERATION(operation, data) { 1217} 1218 1219 1220function GET_FILE_BY_DATA_URL(dataurl, filename){ 1221 let arr = dataurl.split(','), 1222 mime = arr[0].match(/:(.*?);/)[1], 1223 bstr = atob(arr[1]), 1224 n = bstr.length, 1225 u8arr = new Uint8Array(n); 1226 while(n--){ 1227 u8arr[n] = bstr.charCodeAt(n); 1228 } 1229 return new File([u8arr], filename, {type:mime}); 1230} 1231 1232function GENERATE_RANDOM_HEX(length = 16) { 1233 const arr = new Uint8Array(length / 2); 1234 window.crypto.getRandomValues(arr); 1235 return Array.from(arr, byte => byte.toString(16).padStart(2, '0')).join(''); 1236} 1237 1238function SHOW_TOAST(code, message = null) { 1239 message = LOCALE[message] ? LOCALE[message] : message; 1240 let toastContainer = document.getElementById('toast_alert'); 1241 1242 if (!toastContainer) { 1243 toastContainer = document.createElement('div'); 1244 toastContainer.id = 'toast_alert'; 1245 toastContainer.className = 'fixed top-10 left-1/2 -translate-x-1/2 z-[9999] flex flex-col items-center gap-2.5'; 1246 document.body.appendChild(toastContainer); 1247 } 1248 1249 const statusCode = String(code); 1250 1251 if (!message || message.trim() === "") { 1252 const statusCodeStr = String(statusCode); 1253 1254 if (['200', '201'].includes(statusCodeStr)) { 1255 message = 'à¸à¸³à¹à¸à¸´à¸à¸à¸²à¸£à¹à¸ªà¸£à¹à¸à¸ªà¸´à¹à¸à¸ªà¸³à¹à¸£à¹à¸'; 1256 } else if (statusCodeStr === '400') { 1257 message = 'à¸à¸³à¸à¸à¹à¸¡à¹à¸à¸¹à¸à¸à¹à¸à¸ à¸à¸£à¸¸à¸à¸²à¸à¸£à¸§à¸à¸ªà¸à¸à¸à¹à¸à¸¡à¸¹à¸¥à¸à¸µà¸à¸à¸£à¸±à¹à¸'; 1258 } else if (statusCodeStr === '401') { 1259 message = 'à¹à¸¡à¹à¸¡à¸µà¸ªà¸´à¸à¸à¸´à¹à¹à¸à¹à¸²à¸à¸¶à¸ à¸à¸£à¸¸à¸à¸²à¹à¸à¹à¸²à¸ªà¸¹à¹à¸£à¸°à¸à¸à¹à¸«à¸¡à¹'; 1260 } else if (statusCodeStr === '403') { 1261 message = 'à¸à¸à¸´à¹à¸ªà¸à¸à¸²à¸£à¹à¸à¹à¸²à¸à¸¶à¸ à¸à¸¸à¸à¹à¸¡à¹à¸¡à¸µà¸ªà¸´à¸à¸à¸´à¹à¹à¸à¸ªà¹à¸§à¸à¸à¸µà¹'; 1262 } else if (statusCodeStr === '404') { 1263 message = 'à¹à¸¡à¹à¸à¸à¸à¹à¸à¸¡à¸¹à¸¥à¸«à¸£à¸·à¸à¸«à¸à¹à¸²à¸à¸µà¹à¸à¸¸à¸à¸à¹à¸à¸à¸à¸²à¸£'; 1264 } else if (['500', '502', '503', '504'].includes(statusCodeStr)) { 1265 message = 'ระà¸à¸à¸«à¸¥à¸±à¸à¸à¹à¸²à¸à¹à¸à¸´à¸à¸à¹à¸à¸à¸´à¸à¸à¸¥à¸²à¸ (Server Error)'; 1266 } else if (statusCodeStr === 'warning') { 1267 message = 'à¸à¸£à¸¸à¸à¸²à¸£à¸°à¸¡à¸±à¸à¸£à¸°à¸§à¸±à¸ à¸à¸£à¸§à¸à¸ªà¸à¸à¸à¸§à¸²à¸¡à¸à¸¹à¸à¸à¹à¸à¸'; 1268 } else { 1269 message = `à¸à¸³à¸¥à¸±à¸à¸à¸£à¸°à¸¡à¸§à¸¥à¸à¸¥à¸£à¸«à¸±à¸ªà¸ªà¸à¸²à¸à¸°: ${statusCodeStr}`; 1270 } 1271 } 1272 1273 let config = { 1274 bg: 'bg-blue-100', 1275 text: 'text-blue-800', 1276 iconColor: 'text-blue-500', 1277 icon: ` 1278 <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"> 1279 <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"></path> 1280 </svg> 1281 ` 1282 }; 1283 1284 if (statusCode === '200') { 1285 config = { 1286 bg: 'bg-green-100', 1287 text: 'text-green-800', 1288 iconColor: 'text-green-600', 1289 icon: ` 1290 <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"> 1291 <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path> 1292 </svg> 1293 ` 1294 }; 1295 } else if (['400', '401', '403', '404', '500'].includes(statusCode)) { 1296 config = { 1297 bg: 'bg-red-100', 1298 text: 'text-red-800', 1299 iconColor: 'text-red-600', 1300 icon: ` 1301 <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"> 1302 <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" clip-rule="evenodd"></path> 1303 </svg> 1304 ` 1305 }; 1306 } else if (statusCode === 'warning') { 1307 config = { 1308 bg: 'bg-amber-100', 1309 text: 'text-amber-800', 1310 iconColor: 'text-amber-600', 1311 icon: ` 1312 <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"> 1313 <path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd"></path> 1314 </svg> 1315 ` 1316 }; 1317 } 1318 1319 const toastItem = document.createElement('div'); 1320 1321 toastItem.className = ` 1322 ${config.bg} ${config.text} 1323 font-['IBMPlexSansThai'] px-6 py-3 rounded-lg shadow-md 1324 flex items-center gap-3 max-w-[450px] 1325 transition-all duration-300 ease-in-out opacity-0 -translate-y-5 1326 overflow-hidden max-h-40 1327 `; 1328 1329 toastItem.innerHTML = ` 1330 <div class="${config.iconColor} flex-shrink-0">${config.icon}</div> 1331 <div class="text-sm font-normal break-words">${message}</div> 1332 `; 1333 1334 toastContainer.appendChild(toastItem); 1335 1336 setTimeout(() => { 1337 toastItem.classList.remove('opacity-0', '-translate-y-5'); 1338 toastItem.classList.add('opacity-100', 'translate-y-0'); 1339 }, 50); 1340 1341 setTimeout(() => { 1342 toastItem.classList.remove('opacity-100', 'translate-y-0'); 1343 toastItem.classList.add('opacity-0', '-translate-y-5'); 1344 setTimeout(() => { 1345 toastItem.style.maxHeight = '0px'; 1346 toastItem.style.paddingTop = '0px'; 1347 toastItem.style.paddingBottom = '0px'; 1348 toastItem.style.marginTop = '-10px'; 1349 setTimeout(() => { 1350 toastItem.remove(); 1351 }, 300); 1352 }, 150); 1353 }, 3000); 1354} 1355 1356String.prototype.b64encode = function() { 1357 let text = this + ''; 1358 let result = btoa(unescape(encodeURIComponent(text))); 1359 return result; 1360}; 1361String.prototype.b64decode = function() { 1362 let text = this + ''; 1363 return decodeURIComponent(escape(atob(text))); 1364}; 1365 1366String.prototype.hexEncode = function(){ 1367 let hex, i;
1368 1369 let result = ""; 1370 for (i=0; i<this.length; i++) { 1371 hex = this.charCodeAt(i).toString(16); 1372 result += ("000"+hex).slice(-4); 1373 } 1374 1375 return result 1376} 1377 1378String.prototype.hexDecode = function(){ 1379 let j; 1380 let hexes = this.match(/.{1,4}/g) || []; 1381 let back = ""; 1382 for(j = 0; j<hexes.length; j++) { 1383 back += String.fromCharCode(parseInt(hexes[j], 16)); 1384 } 1385 1386 return back; 1387} 1388 1389function BACK(callback){ 1390 if(callback != undefined) callback(); 1391 else history.back(); 1392} 1393 1394String.prototype.hashCode = function() { 1395 let hash = 0; 1396 for (let i = 0; i < this.length; i++) { 1397 let char = this.charCodeAt(i); 1398 hash = ((hash<<5)-hash)+char; 1399 hash = hash & hash; // Convert to 32bit integer 1400 } 1401 return hash; 1402} 1403 1404Object.id = function(o) { 1405 if (window.OBJECT_ID == undefined) window.OBJECT_ID = 0; 1406 if ( typeof o.__unique__ != "undefined" ) { 1407 return o.__unique__; 1408 } 1409 Object.defineProperty(o, "__unique__", { 1410 value: ++window.OBJECT_ID, 1411 enumerable: false, 1412 writable: false 1413 }); 1414 return o.__unique__; 1415}; 1416 1417// Element.prototype._addEventListener = Element.prototype.addEventListener; 1418// Element.prototype.addEventListener = function(a, b, c) { 1419// if(!this.event) this.event = {}; 1420// if(!this.event[a]) this.event[a] = {}; 1421// if(!this.event[a][b]) this._addEventListener(a, b, c); 1422// this.event[a][b] = b; 1423// }; 1424 1425function NUMBER_WITH_COMMAS(num){ 1426 if(!num) return num; 1427 return num.toString().replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ","); 1428} 1429 1430function GET_FRACTION_TO_NUMBER(faction){ 1431 return parseFloat(Fraction(faction).toString()); 1432} 1433 1434function GET_CURRENCY_FORMAT(value, decimal = 2){ 1435 if(typeof(value) == 'string') value = GET_FRACTION_TO_NUMBER(value); 1436 return NUMBER_WITH_COMMAS(value.toFixed(decimal)); 1437}
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.