var $ = (id)=> { return document.getElementById(id); } var WEB = { async api(path,data,debug) { if(!path) return {}; var headers = new Headers({ 'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8' }); if(debug) { data = data||{}; data.debug = true; } var request = data? {req :JSON.stringify(data)}:{}; var params = { method: 'post', body: new URLSearchParams(request), headers: headers } var res = await fetch(path,params); var result = {}; var error = null; var res_text = await res.text(); // console.log(res_text); var test = UTIL.isJson(res_text); if(!test.valid) { result = {}; result.error = error result.text = res_text; } else { result = test?.output; var error = result?.error_code; if(error) { LS.remove("auth"); if(MAIN) { MAIN.processClear(); } } } return (debug? result:result?.data)||{}; }, } MODEL = {}; LOADED = {}; var UTIL= { genHash(length) { length = length || 10; var chars = "0123456789abcdefghijklmnopqrstuvwxyz"; var res = ''; for (var i = 0; i < length; i++) { res += chars.charAt(Math.random()*chars.length-1); } return res; }, getLength(input) { if(!input) return 0; switch(typeof input) { case "object": return Object.keys(input).length; case "array": case "string": return input.length; case "number": return input; } }, loop(array) { if(!array) return 0; switch(typeof array) { case "object": return Object.values(array); case "array": return items; case "number": return input; } }, loop2(array,callback) { if(!array) return 0; switch(typeof array) { case "object": return Object.keys(array).forEach((key)=>callback(array[key],key)); case "array": return array.forEach(callback); case "number": return Array.from({ length: array }, (_, i) => callback(i)); } }, getTimeString(date) { if(typeof date != "date") date = new Date(); var d = date; var hours = ("0" + d.getHours()).slice(-2); var mins = ("0" + d.getMinutes()).slice(-2); var secs = ("0" + d.getSeconds()).slice(-2); return hours + ":" + mins + ":" +secs; }, getDaysOfMonth(date) { var cur_date = new Date(); if(typeof date == "date") cur_date = date; var date_ = new Date(cur_date.getFullYear(),cur_date.getMonth()+1,0); return date_.getDate(); }, getDateString(date) { const options = { year: 'numeric', month: '2-digit', day: '2-digit' }; return (date || new Date()).toLocaleDateString('en-CA', options); }, getDayOfWeek(date) { if(typeof date != "date") date = new Date(); return date.toLocaleString("en-US",{weekday:'long'}) }, filterObj(obj,...keys) { if(!obj || UTIL.Empty(obj)) return {}; var clone = UTIL.deepCopy(obj); var output = {}; if(keys) { for(var key in keys) { var obj_key = keys[key]; output[obj_key] = clone[obj_key] } } return output; }, deepCopy(inObj) { var outObj, value, key; if (typeof inObj !== "object" || inObj === null) { return inObj; } // Create an array or object to hold the values outObj = Array.isArray(inObj) ? [] : {} for (key in inObj) { value = inObj[key] // Recursively (deep) copy for nested objects, including arrays outObj[key] = UTIL.deepCopy(value) } return outObj }, Empty(obj) { if(!obj)return true; if(obj instanceof Blob ) return obj.size===0; if(typeof obj === "object" && Object.keys(obj).length === 0) return true; if(typeof obj === "array" && obj.length === 0) return true; return false; }, getKeys(obj) { if(!obj)return []; if(typeof obj === "object") return Object.keys(obj); if(typeof obj === "array") return obj.keys(); }, deepMerge(target, source) { let output = Object.assign({}, target); if (UTIL.isObject(target) && UTIL.isObject(source)) { Object.keys(source).forEach(key => { if (UTIL.isObject(source[key])) { if (!(key in target)) Object.assign(output, { [key]: source[key] }); else output[key] = UTIL.deepMerge(target[key], source[key]); } else { var val = source[key]; if(val) { Object.assign(output, { [key]: val}); } else delete output[key]; } }); } return output; }, hasKeys(obj,keys) { var res = false; if(obj) { keys = keys?keys:[] res = true; for(var k in keys) { var key = keys[k]; if(!obj[key]) res = false; } } return res; }, isNumber(evt) { evt = (evt) ? evt : window.event; if(!evt)return true var charCode = (evt.which) ? evt.which : evt.keyCode; return this.isNum(charCode); }, isNum(charCode) { if ((charCode > 31 && (charCode < 48 || charCode > 57)) && charCode !== 46) { evt.preventDefault(); } else { return true; } }, isEqual(a, b) { if(UTIL.Empty(a) && UTIL.Empty(b))return true; if((this.isObject(a) && this.isObject(b)) || (this.isArray(a) && this.isArray(b))) { if(this.getLength(a) != this.getLength(b)) return false; for(var key in a) { var res = this.isEqual(a[key],b[key]); if(!res) return false; } return true; } else return a==b return false; }, isObject(obj) { return obj && obj.constructor === Object; }, isArray(arr) { return arr && arr.constructor === Array; }, isFunc(struct) { return (struct && typeof struct == "function"); }, async fetchText (path) { var result =""; if(path) { var res = await fetch(path); if(res.ok) result = (res.ok)? await res.text() : ""; } return result; }, showFile(blob) { console.log(blob); var newBlob = new Blob([blob], {type: "application/pdf"}) var data = URL.createObjectURL(newBlob) window.open(data) }, replaceAll(formula,key,value) { value = value||0; return formula.split(key).join(value); }, async fetchJson(url) { var options = {}; options.mode = "cors"; var result = await fetch(this.host+url,options); if (result?.headers.get("Content-Type") == "application/json") { return await result.json(); } return null; }, csvToJSon(csv) { if(!csv) { console.warn("csv is null or empty"); return {}; } var lines = csv.split("\n"); var res = []; if (lines && lines.length > 0) { var headers = lines[0].split(","); for (var i = 1; i < lines.length; i++) { var obj = {}; var currentline = lines[i].split(","); for (var j = 0; j < headers.length; j++) { var key = headers[j].replace(/['"]+/g, '') var value = currentline[j].replace(/['"]+/g, '') obj[key] = value; } res.push(obj); } } return res; }, jsonToCSV(array) { if(!UTIL.isArray(array)) { var new_array = []; if(UTIL.isObject(array)) { var new_array = []; var cols = null; for(var k in array) { var row = array[k]; if(!cols) { cols = []; for(var r_k in row) { cols.push(r_k); } new_array.push(cols); } var data_row = []; for(var c_k in cols) { var col = cols[c_k]; var cell = row[col]; data_row.push(cell||""); } new_array.push(data_row); } } array = new_array; } var str = ''; for (var k in array) { var row = array[k] str+= row.join(); str+= "\n" } return str; }, exportCSV(name,data) { var date = new Date().setTime(); var filename = name||'export_'+date+'.csv'; var charset = "utf-8"; var blob = new Blob([data], {type: "text/csv;charset="+ charset + ";"}); if (window.navigator.msSaveOrOpenBlob) { window.navigator.msSaveBlob(blob, filename); } else { var downloadLink = window.document.createElement("a"); downloadLink.setAttribute('href', window.URL.createObjectURL(blob)); downloadLink.setAttribute('download', filename); downloadLink.click(); } }, decodeHash(hash) { result = {}; if(!hash) hash = location.hash; if(hash) { var query = hash.substr(1) if(query) { try { var query = decodeURIComponent(query); var query_obj = query.split("&"); if(query_obj.length>0) { var props = {}; for(var kv of query_obj) { var entry = kv.split("="); if(entry[0]=="comp") result.comp = entry[1] ; else props[entry[0]] = entry[1] } result.props = props; } } catch (error) { console.log("ERROR",error); } } } return result; }, toNavHash(data) { var hash = "#"; if(UTIL.isObject(data)) { var json = JSON.stringify(data); // hash += btoa(json); hash+=json } return hash }, toCurrency(val,currency) { currency = currency||"R" return currency + (val.toFixed(2)); }, isBetween(val,a,b) { if(typeof val == "number" && typeof a == "number" && typeof b == "number") { return val>=a && val<=b; } return false; }, sum(input) { var total = 0; if (toString.call(input) !== "[object Array]") return total; for(var i=0;i max ? max : value; } return 0 }, isJson(text) { var res = {}; try { res.text = text; res.output = JSON.parse(text); } catch (e) { res.valid = false; res.error = e } res.valid = true; return res; }, capitalize(s) { return s && s[0].toUpperCase() + s.slice(1); }, sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }, includeJs(jsFilePath) { var script = document.createElement("script"); script.type = "text/javascript"; script.src = jsFilePath; script.async = false; document.body.appendChild(script); }, toRand(val) { return "R"+ Number(val||0).toFixed(2) }, download(data, fileName, type="text/plain") { // Create an invisible A element const a = document.createElement("a"); // Set the HREF to a Blob representation of the data to be downloaded var dat = atob(data); var dat2 = this.strToArray(dat); var blob = new Blob([dat2], { type:type }); var href = window.URL.createObjectURL(blob); a.href = href; // Use download attribute to set set desired file name a.setAttribute("download", fileName); // Trigger the download by simulating click a.click(); // Cleanup window.URL.revokeObjectURL(a.href); }, strToArray(bstr) { var result = new Uint8Array(bstr.length); for(var i=0;i console.log('Service worker registered')) .catch(error => console.error('Service worker registration failed:', error)); } }, escapeInvalidChars(text) { return text .replace(/\\/g, '\\\\') .replace(/"/g, '\\"') .replace(/\n/g, '\\n') .replace(/\r/g, '\\r') .replace(/\t/g, '\\t') .replace(/\r\n/g, '\\r\\n'); } } LS = { get(k) { return localStorage.getItem(k); }, set(k,v) { localStorage.setItem(k, v); }, remove(k) { localStorage.removeItem(k); } } Vue.prototype.$vmodel = function(vn) { this[vn] = this.value; this.$watch('value',(nv, ov)=>{ if(nv!=ov) this[vn] = nv;}); this.$watch(vn,(nv, ov)=>{ if(nv!=ov) this.$emit("input",nv);}); } Vue.prototype.$php = async function(func, input) { var tag = this.$options._componentTag; console.log(tag); return await this.$phpComp(tag, func, input); } var SVG = {}; var COMP = { host : "localhost", css:[], loaded:{},//loaded comps object to prevent unnecessary calls to fetch comp temppartslates base: { props:["value"], data(){return {val:{}}}, created() { this.$vmodel("val");}, }, initMain() { this.vue = new Vue ({ el:"#main", mixins:[{methods:UTIL}], data: { comp:"", comp_props:null, width:0, }, created() { window.onhashchange = ()=>this.$emit("onHash",UTIL.decodeHash()) window.onresize = ()=> this.isMobile() }, mounted() { document.addEventListener("keypress",(event)=> { if(event.key == "Enter") this.$emit("onEnterKey") }); this.$emit("onHash",UTIL.decodeHash()); this.isMobile() }, computed: { onMobile() { return this.isMobile(); }, }, methods: { log(val) { console.log(val); }, isMobile() { var isMobileDevice = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); var isTouchScreen = 'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0; var mobile = isMobileDevice || isTouchScreen; var w = window.innerWidth; var h = window.innerHeight; this.width = 0; var ratio = w/h var res = mobile || (this.width <= 1270 && ratio<1); if(this.width!=w) { this.width=w; } // console.log(this.width); return res; }, triggerEvent(el, eventName) { var event = new Event(eventName); el.dispatchEvent(event); } }, }); Vue.directive('DynamicEvents', { bind: (el, binding, vnode) => { const allEvents = binding.value; if(allEvents) { Object.keys(allEvents).forEach((event) => { vnode.componentInstance.$on(event, (eventData) => { const targetEvent = allEvents[event]; if(typeof targetEvent == "function") targetEvent(eventData) }); }); } }, unbind: function (el, binding, vnode) { vnode.componentInstance.$off(); }, }); }, Load(comp,comp_path,props,events) { if(!comp) { console.info("No Comp"); return; } if(!comp_path) { console.info("No Path"); return; } comp.comp = ""; comp.comp_props = {}; comp.events = {}; if(comp_path.substr(0,1)=="/") comp_path = comp_path.replace(/\//g,"-"); comp.comp = comp_path; comp.comp_props = props; if(!UTIL.Empty(events))comp.events = events; }, async externLoadComponent (resolv, reject, tag) { var path = "./comp.php?comp="+tag; try { if(COMP) { var json = COMP.loaded[tag]; var style = COMP.css[tag]; if(!json) { var response = await fetch(path); json = await response.text(); var comp = {}; if(json) { COMP.loaded[tag] = json try { eval(json); } catch (error) { console.log(error); console.log(path,tag); resolv(comp) } if(template) comp.template = template; if(newStyle) { if(!style) { COMP.css[tag] = newStyle; const head = document.head; const styleId = tag; const styleTag = document.getElementById(styleId); if (styleTag) { styleTag.innerHTML += newStyle; } else { const newStyleTag = document.createElement('style'); newStyleTag.id = styleId; newStyleTag.innerHTML = newStyle; head.appendChild(newStyleTag); } } // var div = document.createElement("DIV"); // div.setAttribute("id", tag); // div.innerHTML = ""; // document.body.appendChild(div); } if(!comp.methods) comp.methods = {}; if(comp.data && typeof(comp.data)=='function') comp.methods.__data = comp.data; // create a backup of the original data function comp.data = function() { var d = this.__data ? this.__data() : {}; d.tag = tag; return d }; // console.log(comp); resolv(comp) } else console.log("No Json"); } else console.log("No Json"); } } catch (error) { console.log("tag error",tag,error); reject(error) } }, } COMP.initMain();