function setUpperWindow(window, upperSpGlobal) { spGlobal.upperWindow = window; spGlobal.upperSpGlobal = upperSpGlobal; } function grabSpGlobal() { return spGlobal; } var wbs_dir = {}; let spGlobal = { frameBackendCallback: null, tempCallbacks: null, UserOS: null, UserType: null, upperWindow: null, upperSpGlobal: null, serverData: null, webSockets: wbs_dir, __api_socket__: null, assembleToken: (length) => { let result = ''; const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; const charactersLength = characters.length; let counter = 0; while (counter < length) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); counter += 1; } return result; }, uniqueToken: (length, verify) => { let result = spGlobal.assembleToken(length); if (Array.isArray(verify)) { while (verify.includes(result)) { result = spGlobal.assembleToken(length); } } else if (typeof verify == "object") { while (verify[result]) { result = spGlobal.assembleToken(length); } } return result; }, applySwipeDetector: (element, options) => { if (!(spGlobal['__swipeDetectors__'])) { spGlobal['__swipeDetectors__'] = {}; } let swipeOptionsDefaults = { vertical: false, horizontal: true, threshold: "auto" }; if (!(options)) { options = {}; } for (let key in swipeOptionsDefaults) { if (!(options[key])) { options[key] = swipeOptionsDefaults[key]; } } //console.log(options) let pageWidth = window.outerWidth; if (options.threshold == "auto") { options.threshold = pageWidth * 0.1; } else if (options.threshold.includes("%")) { options.threshold = pageWidth * (parseFloat(options.threshold.replace("%", "")) / 100); } else if (typeof options.threshold == "string") { throw TypeError("Threshold needs to be 'auto', a % (ex. 30%), or number."); } let emID; if (element.id) { emID = element.id; } else { emID = "spSD_" + spGlobal.assembleToken(4); element.id = emID; } spGlobal['__swipeDetectors__'][emID] = { start: undefined, end: undefined, element: element, options: options, }; element.addEventListener("touchstart", (event) => { event.preventDefault(); let swipeE; if (!spGlobal['__swipeDetectors__'][event.target.id]) { //console.log("Find sw") for (let key in spGlobal['__swipeDetectors__']) { let tswipeE = spGlobal['__swipeDetectors__'][key]; //console.log(tswipeE, event.target, tswipeE.element.contains(event.target)) if (tswipeE.element.contains(event.target)) { //console.log("Found") swipeE = tswipeE; } } } else { swipeE = spGlobal['__swipeDetectors__'][event.target.id]; } if (event.changedTouches) { swipeE.start = event.changedTouches[0]; } return false; }); element.addEventListener("touchend", (event) => { event.preventDefault(); if (event.changedTouches) { let record; if (!spGlobal['__swipeDetectors__'][event.target.id]) { //console.log("Find sw") for (let key in spGlobal['__swipeDetectors__']) { let tswipeE = spGlobal['__swipeDetectors__'][key]; //console.log(tswipeE, event.target, tswipeE.element.contains(event.target)) if (tswipeE.element.contains(event.target)) { //console.log("Found") record = tswipeE; } } } else { record = spGlobal['__swipeDetectors__'][event.target.id]; } record.end = event.changedTouches[0]; if (record.options.vertical) { let changeY = record.start.pageY - record.end.pageY; if (Math.abs(changeY) > record.options.threshold) { if (record.start.pageY < record.end.pageY) { // swipe down record.element.dispatchEvent(new Event("swipeDown")); } else { // swipe up record.element.dispatchEvent(new Event("swipeUp")); } } } if (record.options.horizontal) { let changeX = record.start.pageX - record.end.pageX; if (Math.abs(changeX) > record.options.threshold) { if (record.start.pageX < record.end.pageX) { // swipe left record.element.dispatchEvent(new Event("swipeLeft")); } else { // swipe right record.element.dispatchEvent(new Event("swipeRight")); } } } } return false; }); }, displayScrolls: { setScrollSize: (holder) => { let bHeight; try { bHeight = parseInt(holder.parentElement.style.height.replace('px', '')); if (isNaN(bHeight)) { bHeight = 0; } } catch (error) { bHeight = 0; } setTimeout(() => { let e = holder.querySelector('.active'); if (e == undefined) { return; } let scrollHeight; try { scrollHeight = e.scrollHeight; } catch (error) { console.log(holder); } if (scrollHeight != 0 && scrollHeight > bHeight) { holder.parentElement.style.height = `${scrollHeight}px`; } else { if (scrollHeight == 0) { holder.parentElement.style.height = `300px`; } } }, 10); }, scroll: (holder, sw = 1, block = false) => { let bIndex = parseInt(holder.getAttribute("index")); if (sw) { bIndex += sw; if (bIndex > holder.children.length - 1) { bIndex = 0; } if (bIndex < 0) { bIndex = holder.children.length - 1; } holder.setAttribute("index", bIndex.toString()); } let bHeight; try { bHeight = parseInt(holder.parentElement.style.height.replace('px', '')); if (isNaN(bHeight)) { bHeight = 0; } } catch (error) { bHeight = 0; } holder.querySelectorAll(".item").forEach((e, index) => { if (index == bIndex) { e.style.display = "block"; e.classList.add('active'); setTimeout(() => { e.style.opacity = "100%"; }, 10); spGlobal.displayScrolls.setScrollSize(holder); setTimeout(() => { spGlobal.displayScrolls.setScrollSize(holder); }, 1000); } else { if (e.classList.contains('active')) { e.classList.remove('active'); } if (e.style.display == "block") { e.style.opacity = "0%"; setTimeout(() => { e.style.display = "none"; }, 500); } else { e.style.opacity = "0%"; } } }); if (block) { holder.setAttribute("block", "true"); } }, scrollItems: [], loadScrolls: () => { document.querySelectorAll(".SPscroll").forEach((scroll) => { scroll.style.position = "relative"; scroll.style.height = "100%"; scroll.style.display = "flex"; scroll.style.justifyContent = "center"; if (scroll.getAttribute("index") == null) { scroll.setAttribute("index", "0"); } if (scroll.getAttribute("itemTime") == null) { scroll.setAttribute("itemTime", "5"); } scroll.querySelectorAll(".item").forEach((e, index) => { e.style.transitionDuration = "500ms"; e.style.position = "absolute"; e.style.display = "none"; if (e.querySelector('a')?.href.includes('none')) { e.style.cursor = "unset"; e.removeAttribute("onclick"); e.querySelector('a').remove(); } else { e.setAttribute("onclick", "this.querySelector('a').click()"); } }); spGlobal.displayScrolls.scroll(scroll, 0); setTimeout(() => { spGlobal.displayScrolls.setScrollSize(scroll); }, 200); let scrollTime; try { scrollTime = parseInt(scroll.getAttribute("itemTime")); if (isNaN(scrollTime)) { scrollTime = 5; } } catch (error) { scrollTime = 5; } scroll.setAttribute("time", scrollTime); spGlobal.displayScrolls.scrollItems.push(scroll); }); setInterval(() => { spGlobal.displayScrolls.scrollItems.forEach((scroll) => { let scrollTime; if (scroll.getAttribute("manual") == "true") { return; } try { scrollTime = parseInt(scroll.getAttribute("itemTime")); if (isNaN(scrollTime)) { scrollTime = 5; } } catch (error) { scrollTime = 5; } let currentTime; try { currentTime = parseInt(scroll.getAttribute("time")); if (isNaN(currentTime)) { currentTime = 5; } } catch (error) { currentTime = 5; } let ScrollBlocking = scroll.getAttribute("block") == "true"; currentTime -= 1; if (currentTime == 0) { if (ScrollBlocking == false) { spGlobal.displayScrolls.scroll(scroll); } else { scroll.removeAttribute("block"); } currentTime = scrollTime; } scroll.setAttribute("time", currentTime); }); }, 1000); } }, timestampToDatetime: (timestamp, date = undefined) => { if (timestamp) { date = new Date(parseFloat(timestamp) * 1000); } const year = date.getFullYear(); const month = (date.getMonth() + 1).toString().padStart(2, "0"); const day = date.getDate().toString().padStart(2, "0"); const hours = date.getHours().toString().padStart(2, "0"); const minutes = date.getMinutes().toString().padStart(2, "0"); return `${year}-${month}-${day}T${hours}:${minutes}`; }, convertTimestamps: () => { document.querySelectorAll(".timestamp, input[type='datetime-local'").forEach((e) => { if (e.tagName == "INPUT") { if (e.value != "") { e.value = spGlobal.timestampToDatetime(e.value); } e.type = "datetime-local"; } }); }, urlify: (text, newPage = true) => { var urlRegex = /(https?:\/\/[^\s]+)/g; var target = newPage ? "_blank" : "_self"; return text.replace(urlRegex, function (url) { return '' + url + ''; }); }, collectInputs: (container, collectDisabled = true) => { let data = {}; let hexTorgb = (hex) => { return ['0x' + hex[1] + hex[2], '0x' + hex[3] + hex[4], '0x' + hex[5] + hex[6]]; }; container.querySelectorAll("input, select, textarea").forEach((input) => { if (input.name == "" && input.id != "") { input.name = input.id; } if (input.name == "") { return; } if (input.disabled && collectDisabled == false) { return; } if (input.type == "checkbox") { data[input.name] = input.checked; } else if (input.type == "color") { data[input.name] = hexTorgb(input.value); } else if (input.type == 'datetime-local') { let date = new Date(input.value); data[input.name] = Math.floor(date.getTime() / 1000); } else if (input.type == 'number') { let num = parseInt(input.value); if (!num) { num = 0; } data[input.name] = num; } else { data[input.name] = input.value; } }); return data; }, api: (service, action, data, headers = {}) => { return new Promise((res, rej) => { try { spGlobal.Proquest(`/${service}/api/${action}`, "POST", data, headers, "json", false, (resp) => { if (resp.hint) { alert(resp.hint); } if (resp.status == 1) { res(resp.data); } else { console.log(resp); rej(resp); } ; }); } catch (error) { console.log(error); rej(); } ; }); }, apiV3: async (service, store, action, data, timeout = 10000, interval) => { if (interval) { let respFunc = async () => { await interval.function(await spGlobal.apiV3(service, store, action, data, timeout)); setTimeout(respFunc, interval.time ? interval.time : 5000); }; interval.function(await spGlobal.apiV3(service, store, action, data, timeout)); setTimeout(respFunc, interval.time ? interval.time : 5000); return; } return new Promise(async (resolve, reject) => { let apiSock = await spGlobal.setupAPIWebSocket(); let call_id = spGlobal.uniqueToken(5, apiSock.calls); let activeCall = apiSock.calls[call_id] = { id: call_id, pending: true, timeout: timeout }; apiSock.sendJSON({ "service": service, "store": store, "action": action, "data": data, "call_id": call_id }); activeCall.resolve = resolve; activeCall.reject = reject; activeCall.timeout = setTimeout(() => { if (activeCall.pending) { reject("Timeout"); } delete apiSock.calls[call_id]; }, timeout); }); }, setupAPIWebSocket: async (password = undefined, port = 80) => { if (!(spGlobal.__api_socket__)) { spGlobal.__api_socket__ = "setting up"; } else if (spGlobal.__api_socket__ == "setting up") { let timeout = 100; return new Promise((res, rej) => { let st = setInterval(() => { if (spGlobal.__api_socket__ != "setting up") { res(spGlobal.__api_socket__); clearInterval(st); } timeout -= 1; if (timeout <= 0) { clearInterval(st); rej(); } }, 100); }); } else { return spGlobal.__api_socket__; } let api_socket = await spGlobal.setupWebSocket("/apiDir", (socket, data) => { let activeCall = api_socket.calls[data.call_id]; activeCall.pending = false; activeCall.response = data.response; if (data.response.status == 1) { activeCall.resolve(data.response.data); } else { if (data.response.hint) { alert(data.response.hint); } activeCall.reject(); console.log("REJECT", data.response); } return; }, password, port); spGlobal.__api_socket__ = api_socket; return api_socket; }, setupWebSocket: (route, communicator, password = undefined, port = 80) => { return new Promise(async (resolve, reject) => { let location = [ `wss://${window.location.hostname}/ws_proxy/websock_dir`, "ws://localhost:" + port + (port == 81 ? "/ws_proxy/websock_dir" : "/websock_dir") ][spGlobal.serverData.prod ? 0 : 1]; let thisSocket = { "calls": {}, "location": location, "route": route, "ready": false, "socket": undefined, "onData": communicator, "send": async (data) => { if (thisSocket.socket.readyState == thisSocket.socket.CLOSED) { await spGlobal.__init_socket__(thisSocket); } thisSocket.socket.send(data); }, "sendJSON": (data) => { thisSocket.send(JSON.stringify(data)); } }; try { await spGlobal.__init_socket__(thisSocket); resolve(thisSocket); } catch (error) { reject(error); } }); }, __init_socket__: (thisSocket) => { return new Promise((resolve, reject) => { if (!thisSocket.socket || thisSocket.socket == undefined) { thisSocket.socket = new WebSocket(thisSocket.location); } else if (thisSocket.socket.CLOSED) { thisSocket.socket = new WebSocket(thisSocket.location); } thisSocket.socket.onmessage = (ev) => { if (ev.data) { console.log("DATA", ev.data); try { let data = JSON.parse(ev.data); if (data.action == "setup") { thisSocket.id = data.id; spGlobal.webSockets[data.id] = thisSocket; thisSocket.pingInterval = setInterval(() => { thisSocket.send("ping"); }, 3000); thisSocket.ready = true; resolve(thisSocket); } else { if (data.hint) { alert(data.hint); } if (data.close) { thisSocket.socket.close(); } else if (data.ping) { } else { try { thisSocket.onData(thisSocket, data); } catch (error) { console.error(error); } } } } catch (error) { reject(error); } } }; thisSocket.socket.onclose = () => { thisSocket.ready = false; clearInterval(thisSocket.pingInterval); if (thisSocket.id && thisSocket.id == spGlobal.__api_socket__) { spGlobal.__api_socket__ = undefined; } }; thisSocket.socket.onopen = () => { thisSocket.socket.send(JSON.stringify({ "route": thisSocket.route })); }; }); }, apiV2: (service, store, action, data = {}, headers = {}) => { if (!(store)) { store = "any"; } if (!(data)) { data = {}; } if (!(headers)) { headers = {}; } return new Promise((res, rej) => { try { spGlobal.Proquest(`/apiDir/${service}/${store}/${action}`, "POST", data, headers, "json", false, (resp) => { if (resp.hint) { alert(resp.hint); } if (resp.status == 1) { res(resp.data); } else { console.log(resp); rej(resp); } ; }); } catch (error) { console.log(error); rej(); } ; }); }, apiV2D: (action, data = {}, headers = {}) => { return spGlobal.apiV2(spGlobal.location.service, spGlobal.location.store, action, data, headers); }, Proquest: (Address, Type = "GET", Data = {}, Headers = {}, RType = "text", ErrorIgnore = false, Callback = function (resp) { console.log(resp); }) => { if (Data) { try { Data = JSON.stringify(Data); } catch (error) { Data = Data; } } var xhttp = new XMLHttpRequest(); let resp; if (Callback) { xhttp.onreadystatechange = function () { if (this.readyState == 4 && this.status == 200) { if (RType == "json") { try { resp = JSON.parse(xhttp.responseText); } catch (error) { if (ErrorIgnore == false) { throw "Response Was Not JSON"; } else { Callback(xhttp.responseText); return; } } Callback(resp); return; } else { if (RType == "request") { Callback(xhttp); return; } else { if (RType == "text") { Callback(xhttp.responseText); return; } } } Callback(xhttp.responseText); } if (this.readyState == 4 && this.status != 200) { Callback([xhttp, "Error: " + this.status]); } }; } xhttp.open(Type, Address, true); if (Headers) { for (var header in Headers) { xhttp.setRequestHeader(header, Headers[header]); } ; } if (Data) { xhttp.send(Data); } else { xhttp.send(); } }, partitionTable: (table, key = "name", sep = " > ") => { let partitoned = {}; table.querySelectorAll('tbody tr').forEach(element => { if (element.querySelector(`td[key='${key}']`)) { let name = element.querySelector(`td[key='${key}']`).innerText.trim(); let nPart = partitoned; let parts = name.split(sep); for (let i in parts) { let part = parts[i]; if (parseInt(i) >= parts.length - 1) { nPart[part] = element; element.setAttribute("tablestep", parts.slice(0, -1).length); element.setAttribute("tablepart", part); element.setAttribute("tabledir", parts.slice(0, -1).join('.')); } else { if (!nPart[part]) { nPart[part] = {}; } nPart = nPart[part]; } } } }); function buildSet(dict, step = 0, prev = undefined) { for (let key in dict) { let dir = prev ? `${prev}.${key}` : key; if (typeof dict[key] == "object" && !(dict[key].innerHTML)) { if (!table.querySelector(`#${dir}`)) { let rowHeader = document.createElement("tr"); rowHeader.setAttribute("rowHeader", dir); let rowTD = document.createElement("td"); rowHeader.appendChild(rowTD); rowTD.setAttribute("colspan", "100%"); rowTD.style.textAlign = "left"; rowTD.style.fontWeight = "bold"; rowTD.style.padding = "5px"; rowTD.style.fontSize = "larger"; rowTD.innerHTML = `${'    '.repeat(step)}${key}`; table.querySelector("tbody").appendChild(rowHeader); } buildSet(dict[key], step + 1, dir); } } } buildSet(partitoned); table.querySelectorAll("tr[tabledir]").forEach(e => { let query = `tr[rowHeader='${e.getAttribute('tabledir')}']`; let rowH = table.querySelector(query); if (rowH) { let name = e.getAttribute("tablepart"); let step = parseInt(e.getAttribute("tablestep")); e.querySelector(`td[key='${key}']`).innerHTML = `${'    '.repeat(step)}- ${name}`; rowH.after(e); } }); }, buildTable: (table, data, order, clear) => { let tbody = table.querySelector("tbody"); let thead = table.querySelector("thead"); if (clear) { tbody.innerHTML = ""; } if (order == true) { order = []; thead.querySelectorAll("td").forEach(e => { order.push(e.getAttribute("key")); }); } else { if (!Array.isArray(order)) { throw Error("order not specified"); } ; } for (let item of data) { let row = document.createElement("tr"); for (let key of order) { let cell = document.createElement("td"); cell.setAttribute("key", key); cell.innerHTML = item[key] ?? ""; row.appendChild(cell); } ; tbody.appendChild(row); } }, applySaveKeys: (func) => { document.addEventListener("keydown", function (e) { if (e.key === 's' && (navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey)) { e.preventDefault(); func(); } }, false); }, buildFormV2: (container, data, clear = false) => { if (clear) { container.innerHTML = ""; } let baseItems = []; for (let item of data) { if (item.type == "fieldset") { let holder = document.createElement("fieldset"); holder.innerHTML = `${item.label}`; container.appendChild(holder); spGlobal.buildFormV2(holder, item.items); } else { baseItems.push(item); } } if (baseItems.length > 0) { let baseTable = document.createElement("table"); baseTable.innerHTML = ""; container.appendChild(baseTable); let tbody = baseTable.querySelector("tbody"); for (let item of baseItems) { tbody.appendChild(spGlobal.__build_row__(item, tbody)); } } }, __build_row__: (item, tbody = undefined) => { let row = document.createElement("tr"); let items = [item]; if (item.items) { items.concat(item.items); } for (let tdInfo of items) { let cell = document.createElement("td"); cell.setAttribute("name", tdInfo.name); cell.innerHTML = tdInfo.label ? tdInfo.label : tdInfo.name; row.appendChild(cell); let input_cell = document.createElement("td"); let input; if (tdInfo.type == "select") { input = document.createElement("select"); for (let opt of tdInfo.options) { let sel_opt = document.createElement("option"); if (typeof opt == "object") { opt.label ? sel_opt.innerHTML = opt.label : opt.name; sel_opt.value = opt.value; } else if (typeof opt == "string") { sel_opt.innerHTML = opt; sel_opt.value = opt; } input.appendChild(sel_opt); } } else if (tdInfo.type == "checkbox") { input = document.createElement("input"); input.type = "checkbox"; } else if (tdInfo.type == "textarea") { cell.setAttribute("colspan", "100%"); tbody.appendChild(row); row = document.createElement("tr"); input_cell.setAttribute("colspan", "100%"); input = document.createElement("textarea"); input.type = "checkbox"; } else { input = document.createElement("input"); input.type = tdInfo.type ? tdInfo.type : "text"; } tdInfo.required ? input.required = tdInfo.required : null; input.name = tdInfo.name; tdInfo.id ? input.id = tdInfo.id : null; tdInfo.placeholder ? input.placeholder = tdInfo.placeholder : null; tdInfo.value ? input.value = tdInfo.value : null; if (tdInfo.type == "checkbox") { tdInfo.value ? input.checked = tdInfo.value : null; } tdInfo.disabled ? input.disabled = true : null; input_cell.appendChild(input); row.appendChild(input_cell); if (tdInfo.visible == false) { row.style.display = "none"; } } ; return row; }, buildForm: (table, data, clear = false) => { let tbody = table.querySelector("tbody"); if (clear) { tbody.innerHTML = ""; } for (let item of data) { tbody.appendChild(spGlobal.__build_row__(item, tbody)); } }, fillForm: (container, data, clear) => { container.querySelectorAll("input, select, textarea").forEach((input) => { if (input.name == "" && input.id != "") { input.name = input.id; } if (input.name == "") { return; } if (!(data[input.name])) { return; } if (input.type == "checkbox") { input.checked = data[input.name]; } else { if (input.type == "datetime-local") { data[input.name] = spGlobal.timestampToDatetime(data[input.name]); } data[input.name] ? input.value = data[input.name] : (clear ? input.value = "" : null); } }); }, applyDetectEnter: (element, after) => { element.addEventListener("keyup", (e) => { if ((e.keyCode == 13 || e.key == "Enter") && !e.shiftKey) { if (after != undefined) { e.preventDefault(); return after(element.value, element); } else { e.preventDefault(); return true; } } else { return false; } }); }, __onwindow_closed__: [], onWindowClosed: (func) => { spGlobal.__onwindow_closed__.push(func); }, __window_closed__: (vars) => { spGlobal.__onwindow_closed__.forEach((e) => { new Promise(() => { e(vars); }); }); spGlobal.__onwindow_closed__ = []; }, __window_loaded__: undefined, openWindow: (src, callBacks, onLoad = undefined) => { overlayFrame.style.display = "none"; overlayWindow.style.display = "flex"; spGlobal.tempCallbacks = callBacks; overlayFrame.src = src; spGlobal.__window_loaded__ = onLoad; return new Promise((res, rej) => { spGlobal.__onwindow_closed__.push(res); }); }, closeThisWindow: () => { spGlobal.upperWindow.grabSpGlobal().closeWindow(); }, closeWindow: () => { overlayFrame.style.display = "none"; overlayWindow.style.display = "none"; spGlobal.tempCallbacks = undefined; overlayFrame.src = ""; spGlobal.__window_closed__(undefined); }, tempUploadCallbacks: undefined, promptImageUpload: (callback, multiple = false, directory = undefined, keepName = false) => { spGlobal.tempUploadCallbacks = callback; return spGlobal.openWindow('/app/imageUpload?' + (multiple ? 'multiple=True&' : '') + (keepName ? 'keepName=True&' : ''), { "imageUploaded": (ids) => { spGlobal.tempUploadCallbacks(ids); spGlobal.tempUploadCallbacks = undefined; spGlobal.closeWindow(); }, "directory": directory }); }, promptFileUpload: (callback, multiple = false, directory = undefined) => { spGlobal.tempUploadCallbacks = callback; spGlobal.openWindow('/app/fileUpload' + (multiple ? '?multiple=True' : ''), { "fileUploaded": (ids) => { spGlobal.tempUploadCallbacks(ids); spGlobal.tempUploadCallbacks = undefined; }, "directory": directory }); }, checkNoticeList: async (notices) => { for (let notice of notices) { await spGlobal.checkNotice(notice); } }, checkNotice: (notice) => { if (!(localStorage.getItem(`${notice}`))) { return spGlobal.openWindow(`/notices/${notice}`, undefined); } }, toClipboard: (txt) => { navigator.clipboard.writeText(txt); }, uploadImage: async (base64, type = "img", progress = undefined, useDirectory = undefined, keepName = false, name) => { let response; if (base64.length > 6000000) { let multiPartToken; let chunks = []; for (var i = 0, charsLength = base64.length; i < charsLength; i += 8000000) { chunks.push(base64.substring(i, i + 8000000)); } multiPartToken = await spGlobal.api("main", "uploadAppImage", { "type": type, "multipart": { "multipart": true, "length": chunks.length } }); console.log("Multipart token", multiPartToken); i = 0; for (var chunk in chunks) { let ok = await spGlobal.api("main", "uploadAppImage", { "type": type, "multipart": { "key": multiPartToken, "multipart": true, "data": chunks[chunk], "position": i } }); if (progress) { progress(i, chunks.length); } if (ok != "accepted") { throw "Not accepted"; } i += 1; } response = await spGlobal.api("main", "uploadAppImage", { "type": type, "multipart": { "multipart": true, "finish": true, "key": multiPartToken }, "directory": useDirectory, "keepName": keepName, "name": name }); console.log("Upload Finished Req", response); } else { response = await spGlobal.api("main", "uploadAppImage", { "bs64": base64, "type": type, "directory": useDirectory, "keepName": keepName, "name": name }); } return response; }, inputToBase64: (input, callback) => { var files = input.files; function get_b64(file) { var reader = new FileReader(); reader.onload = function () { var res = reader.result; callback(res, file.type, file.name); }; reader.readAsDataURL(file); reader.onerror = function (error) { alert("There was an error reading this image, try again"); }; } if (files) { [].forEach.call(files, get_b64); } }, appImageURL: (id, type = "image") => { if (type == "image") { return `/images/appImages/${id}${id.includes('.') ? '' : '.webp'}`; } else if (type == "video") { return `/images/appImages/${id}.mp4`; } }, __money_formatter__: new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', // These options are needed to round to whole numbers if that's what you want. //minimumFractionDigits: 0, // (this suffices for whole numbers, but will print 2500.10 as $2,500.1) //maximumFractionDigits: 0, // (causes 2500.99 to be printed as $2,501) }), formatMoney: (value) => { return spGlobal.__money_formatter__.format(value); }, images: { __canvas__: document.createElement("canvas"), resize: async (imageB64, resize = 900, format = "jpeg") => { return new Promise((res, rej) => { var img = new Image(); img.onload = (ev) => { let canvas = spGlobal.images.__canvas__; if (ev.target.width > resize || ev.target.height > resize) { if (ev.target.width > ev.target.height) { var scaleFactor = resize / ev.target.width; canvas.width = resize; canvas.height = ev.target.height * scaleFactor; } else { var scaleFactor = resize / ev.target.height; canvas.height = resize; canvas.width = ev.target.width * scaleFactor; } } var ctx = canvas.getContext('2d'); ctx.drawImage(ev.target, 0, 0, canvas.width, canvas.height); res(ctx.canvas.toDataURL('image/' + format, 1)); }; img.src = imageB64; }); } }, location: { service: undefined, store: undefined, __load_funcs__: [], updateURL: (url) => { window.history.pushState({}, "", url); }, onLoad: (func) => (spGlobal.location.__load_funcs__.push(func)), args: {}, __loadArgFuncs__: {}, ifArgFunc: (name, func) => { if (spGlobal.location.args[name]) { new Promise(() => { func(spGlobal.location.args[name]); }); } }, onLoadArgFunc: (name, func) => { if (!(spGlobal.location.__loadArgFuncs__[name])) { spGlobal.location.__loadArgFuncs__[name] = []; } spGlobal.location.__loadArgFuncs__[name].push(func); }, }, loadFrame: (name, frame) => { let upper = false; if (name && !frame) { frame = document.querySelector(`iframe[loader='${name}']`); if (!frame) { if (spGlobal.upperWindow) { frame = spGlobal.upperWindow.document.querySelector(`iframe[loader='${name}']`); } if (!frame) { console.error("There was no frame found with that loader name:", name); return; } else { upper = true; } } } if (frame.getAttribute("loader")) { let loaderFunc = frame.getAttribute("loader"); let winFunc = upper ? spGlobal.upperWindow[loaderFunc] : window[loaderFunc]; if (winFunc) { let windowVars = winFunc(frame); for (let key in windowVars) { frame.contentWindow[key] = windowVars[key]; if (frame.contentWindow['Set' + key]) { try { frame.contentWindow['Set' + key](windowVars[key]); } catch (error) { console.log(`The Function: ["Set${key}"] threw an error while setting call backs `, error); } } else { console.log(`Function: ["Set${key}"] does not exist on page.`); } } } else { console.log(`The frame requested a function that did not exist: ${loaderFunc}`); } } if (frame.classList.contains("setsize")) { frame.style.height = frame.contentDocument.body.scrollHeight.toString() + "px"; } } }; let overlayWindow; let overlayFrame; window.addEventListener("load", () => { if (!sessionStorage.getItem('sds.sop')) { spGlobal.apiV2('server', 'any', 'sds.sop', undefined).then(r => { sessionStorage.setItem('sds.sop', JSON.stringify(r)); spGlobal.serverData = r; }); } else { spGlobal.serverData = JSON.parse(sessionStorage.getItem('sds.sop')); } let p = window.location.pathname.split("/"); if (p.length >= 3) { spGlobal.location.service = p[1]; spGlobal.location.store = p[2]; } if (document.querySelectorAll(".SPscroll").length > 0) { spGlobal.displayScrolls.loadScrolls(); } try { document.querySelectorAll("iframe").forEach(frame => { frame.onload = () => { if (frame.contentWindow) { if (frame.contentWindow.setUpperWindow) { frame.contentWindow.setUpperWindow(window, spGlobal); } } }; if (frame.contentWindow) { if (frame.contentWindow.setUpperWindow) { frame.contentWindow.setUpperWindow(window, spGlobal); } } if (frame.getAttribute("loader")) { spGlobal.loadFrame(undefined, frame); } }); } catch (error) { } overlayWindow = document.createElement("div"); overlayWindow.id = "spGlobalOverlay"; overlayWindow.style.position = "fixed"; overlayWindow.style.top = "0px"; overlayWindow.style.left = "0px"; overlayWindow.style.display = "none"; overlayWindow.style.backgroundColor = "rgba(0,0,0,0.75)"; overlayWindow.style.width = "100%"; overlayWindow.style.height = "100%"; overlayWindow.style.zIndex = "10000"; overlayWindow.style.alignItems = "center"; overlayWindow.style.alignContent = "center"; overlayWindow.style.justifyContent = "center"; overlayWindow.onclick = event => { overlayWindow.style.display = "none"; overlayFrame.src = ""; spGlobal.__window_closed__(undefined); }; document.body.appendChild(overlayWindow); overlayFrame = document.createElement("iframe"); overlayFrame.onclick = event => { event.preventDefault(); }; overlayFrame.style.width = "95%"; overlayFrame.style.height = "90%"; overlayFrame.style.border = "none"; overlayFrame.style.margin = "auto"; overlayFrame.style.backgroundColor = "rgba(0,0,0,0)"; overlayFrame.style.display = "none"; overlayFrame.onload = e => { if (overlayFrame.contentWindow) { if (overlayFrame.contentWindow.setUpperWindow) { overlayFrame.contentWindow.setUpperWindow(window, spGlobal); } } if (overlayFrame.contentWindow.location.href.includes("frontendClose")) { let keep; if (spGlobal.frameBackendCallback) { keep = spGlobal.frameBackendCallback(Object.fromEntries(new URLSearchParams(overlayFrame.contentWindow.location.search))); spGlobal.frameBackendCallback = undefined; } if (!keep) { overlayWindow.style.display = "none"; overlayFrame.src = ""; spGlobal.__window_closed__(Object.fromEntries(new URLSearchParams(overlayFrame.contentWindow.location.search))); } } else { if (overlayFrame.contentWindow.location.href != "") { overlayFrame.style.display = "block"; if (spGlobal.tempCallbacks) { for (let key in spGlobal.tempCallbacks) { if (overlayFrame.contentWindow['Set' + key]) { try { overlayFrame.contentWindow['Set' + key](spGlobal.tempCallbacks[key]); } catch (error) { console.log(`The Function: ["Set${key}"] threw an error while setting call backs `, error); } } else { console.log(`Function: ["Set${key}"] does not exist on page.`); } } } } } if (spGlobal.__window_loaded__) { new Promise(() => { spGlobal.__window_loaded__(overlayFrame); }); } }; overlayWindow.appendChild(overlayFrame); let urlArgs = new URL(window.location.toString()); urlArgs.searchParams.forEach((val, key) => { spGlobal.location.args[key] = val; }); setTimeout(() => { for (var func of spGlobal.location.__load_funcs__) { new Promise(() => { func(); }); } for (var key in spGlobal.location.args) { var val = spGlobal.location.args[key]; if (spGlobal.location.__loadArgFuncs__[key]) { spGlobal.location.__loadArgFuncs__[key].forEach((func) => { new Promise(() => { func(val); }); }); } } }, 100); if (false) { if (Notification.permission != 'granted') { Notification.requestPermission().then(() => { navigator.serviceWorker.register("/scripts/service_worker.js", { "type": "module" }).then((reg) => { }).catch((r) => { console.log(r); }); }); } else { navigator.serviceWorker.register("/scripts/service_worker.js", { "type": "module" }).then((reg) => { }).catch((r) => { console.log(r); }); } } window.addEventListener("error", function (event) { spGlobal.apiV2("logger", "any", "subimit", { "location": window.location.href, "user": window.navigator.userAgent, "event": event, "error.message": event.message, "stack": console.trace() }); }); }); setInterval(() => { document.querySelectorAll(".blink").forEach(e => { e.style.backgroundColor = "red"; }); setTimeout(() => { document.querySelectorAll(".blink").forEach(e => { e.style.backgroundColor = ""; }); }, 1000); }, 3000);