//Superior array class Arc { public names:Array; public values:Array; public length:number = 0; public keys:any; private id:number; constructor() { this.names = []; this.values = []; this.id = 0; this.keys = {}; } //Add new element with name add(name:string, value:any) { if (is(this.keys[name])) { this.change(name, value); return; } this.names.push(name); this.values.push(value); this.length = this.names.length; this.keys[name] = this.length - 1; } //Get value by name value(name:string) { return this.values[ this.keys[name] ]; } //Add new unnamed element push(value:any) { var id:string = "arcUnicId" + this.id++; this.add(id, value); return id; } //Change value by name change(name:string, value:any) { if (not(this.keys[name])) return; this.values[ this.keys[name] ] = value; } //Remote element by name remove(name:string) { if (not(this.keys[name])) return; this.names.splice( this.keys[name], 1 ); this.values.splice( this.keys[name], 1 ); this.length = this.names.length; delete this.keys[name]; } //Get name by value. Only first occurrence. search(value:any) { const i = this.values.indexOf(value); if (i === -1) return undefined; return this.names[i]; } //Functional for forEach(callback:Function) { for(let i in this.names) { let breakPoint = callback(this.names[i], this.values[i]); if (breakPoint === "break") break; } } //Copy Arc copy(arc:Arc) { this.values = arc.values.slice(); this.names = arc.names.slice(); this.length = arc.length; this.id = Math.max(this.id, arc.id); this.updateKeys(); } //Share values share(arc:Arc, names:Array) { for(let name of names) { arc.add( name, this.values[ this.keys[name] ] ); } arc.id = Math.max(arc.id, this.id); } //Get string form of all elements toString() { var trace:string = ""; for(let i in this.names) { trace += `[${this.names[i]}] ${this.values[i]}\n`; }; return trace; } //Recursive output stringify(tab:string="") { var trace:string = ""; for(let i in this.names) { trace += `${tab}[${this.names[i]}] `; if ( isObject(this.values[i]) ) { var classname = this.values[i].constructor.name; if (classname === "Arc") trace += "\n" + this.values[i].stringify(tab + "__ "); else trace += JSON.stringify(this.values[i]) + "\n"; } else if ( isArray(this.values[i]) ) { trace += JSON.stringify(this.values[i]) + "\n"; } else if ( isString(this.values[i]) ) { trace += `"${this.values[i]}"\n`; } else { trace += this.values[i] + "\n"; } }; return trace; } //Change name of element rename(name:string, newname:string) { this.add(newname, this.value(name)); this.remove(name); } //Reverse Arc reverse() { this.values.reverse(); this.names.reverse(); } //Get object form object() { var object:any = {}; for(let i in this.names) { object[this.names[i]] = this.values[i]; } return object; } //Import from object form importObject(object:any) { for(let name in object) { this.add(name, object[name]); } } //Get complex array form array() { var complex = []; for(let i in this.names) { complex.push({ name: this.names[i], value: this.values[i] }); } return complex; } //Import from array form importArray(array:Array) { for(let v of array) { this.push(v); } } private updateKeys() { var keys:any = {}; for(let i in this.names) { keys[this.names[i]] = i; } this.keys = keys; } //Sort Arc sort(handler:any) { var array = this.array(); array.sort(handler); for(let i in array) { this.names[i] = array[i].name; this.values[i] = array[i].value; } this.updateKeys(); } //Shuffle Arc shuffle() { var array = this.array(); for (let i = array.length; i; i--) { let j = Math.floor(Math.random() * i); [array[i - 1], array[j]] = [array[j], array[i - 1]]; } for(let i in array) { this.names[i] = array[i].name; this.values[i] = array[i].value; } this.updateKeys(); } //Concat Arcs concat(...arcs:Array) { for(let arc of arcs) { this.names = this.names.concat(arc.names); this.values = this.values.concat(arc.values); this.id = Math.max(this.id, arc.id); } this.length = this.names.length; this.updateKeys(); } } //Superior Promise class Async { value:any; onload:Events; constructor(private param:any = {}) { if (not(this.param.disposable)) this.param.disposable = false; this.onload = new Events(); } then(res:Function) { this.onload.push(res); if (is(this.value)) res(this.value); } set(value:any) { this.value = value; this.onload.run(value); if (this.param.disposable) this.onload = new Events(); } } //Easy way to check that any parameters aren't set. function check(list:Array) { if (not(list)) return false; if (not(list.length)) return false; for(let items of list) { if(not(items)) return false; if(not(items.length)) return false; var parent = items[0]; if (not(parent)) return false; for(let i = 1; i < items.length; i++) { parent = parent[items[i]]; if (not(parent)) return false; } } return true; } //Functions for working with cookie function getCookie(name) { var matches = document.cookie.match(new RegExp( "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, "\\$1") + "=([^;]*)" )); return matches ? decodeURIComponent(matches[1]) : undefined; } function createCookie(name, value, days) { if (days) { var date = new Date(); date.setTime(date.getTime() + (days*24*60*60*1000)); var expires = "; expires=" + date.toUTCString(); } else var expires = ""; document.cookie = name + "=" + value + expires + "; path=/"; } function setCookie(name, value) { createCookie(name, value, 365); } function delCookie(name) { createCookie(name,"",-1); } //Errors manager class Errors { errors:Array = []; exists:boolean = false; addError(message?, code?) { var f = this; message = message || "Unknown error"; code = code || 0; f.errors.push({ message: message, code: code }); f.exists = true; return f; } checkError(code) { var f = this; for(let error of f.errors) { if (error.code === code) return true; } return false; } getErrors() { var f = this; if (!f.exists) return ""; let errors = "", i = 0; for(let error of f.errors) { errors += `[${i+1}] Error`; if (error.code) errors += ` ${error.code}`; errors += ": " + error.message; i++; if (i === f.errors.length) break; errors += "\n"; } return errors; } exportErrors() { var f = this; var errors:any = {}; Object.assign(errors, { error: f.exists }); if (f.exists) Object.assign(errors, { errors: f.errors }); return errors; } importErrors(res) { var f = this; f.exists = res.error; if (f.exists) { f.errors = res.errors; } return f; } } function getErrors(errors) { return (new Errors()).importErrors(errors).getErrors(); } //Easy way to call lots of functions class Events { events:Arc; constructor() { var f = this; f.events = new Arc(); } add(id:string, event:Function) { var f = this; f.events.add(id, event); } push(event:Function) { var f = this; return f.events.push(event); } remove(id:string) { var f = this; if (not(id)) return; f.events.remove(id); } pick(id:string, param?:any) { var f = this; f.events.value(id)(param); } idpick(id:string, param?:any) { var f = this; f.events.value(id)(id, param); } run(param?:any) { var f = this; for(let i in f.events.names) { f.pick(f.events.names[i], param); } } idrun(param?:any) { var f = this; for(let i in f.events.names) { f.idpick(f.events.names[i], param); } } } //Is object exist? function is(obj:any) { if (obj === null || obj === undefined) return false; if (isNumber(obj) && isNaN(obj)) return false; else return true; } //Not exist? function not(obj:any) { return !is(obj); } //Choose first existing object function or(...list:Array) { for(let value of list) { if (is(value)) return value; } return null; } //Check type function isObject( objectToCheck ) { return Object.prototype.toString.call( objectToCheck ) === "[object Object]"; } function isNumber( numberToCheck ) { return Object.prototype.toString.call( numberToCheck ) === "[object Number]"; } function isString( stringToCheck ) { return Object.prototype.toString.call( stringToCheck ) === "[object String]"; } function isArray( arrayToCheck ) { return Object.prototype.toString.call( arrayToCheck ) === "[object Array]"; } function isFunction( functionToCheck ) { return Object.prototype.toString.call( functionToCheck ) === "[object Function]"; } function isBoolean( booleanToCheck ) { return Object.prototype.toString.call( booleanToCheck ) === "[object Boolean]"; } //When you have to wait a lot of callbacks class Loading { param:any = {}; vars:any = {}; constructor(callback) { var f = this; f.param.callback = callback; f.vars.loadings = 0; f.vars.loaded = 0; f.vars.isStarted = false; } add() { var f = this; f.vars.loadings++; } done() { var f = this; f.vars.loaded++; f.check(); } start() { var f = this; f.vars.isStarted = true; f.check(); } check() { var f = this; if (!f.vars.isStarted) return; if (f.vars.loaded >= f.vars.loadings) f.param.callback(); } } //More simple random function function rand(a:number, b:number):number { var c:number; var d:number; c = b - a; if (c < 0) return -1; d = Math.random()*c; d = Math.round(d); d += a; return d; } //Print random string function randstr(length:number):string { var trace:string = ""; for(let i=0; i { if (f.stoped) return; f.param.callback(); if (f.stoped) return; f.interval(); }, f.param.duration); } set(param) { var f = this; if (is(param.duration)) f.param.duration = param.duration; if (is(param.callback)) f.param.callback = param.callback; if (is(param.after)) f.param.aftercallback = param.aftercallback; } run() { var f = this; if (f.stoped) return; f.param.callback(); return f; } start() { var f = this; if (not(f.param.duration) || not(f.param.callback)) return; f.stoped = false; f.interval(); } after(aftercallback:Function) { var f = this; f.set({ after: aftercallback }); } stop() { var f = this; if (f.stoped) return; clearTimeout(f.vars.timeoutID); f.stoped = true; if (is(f.param.aftercallback)) f.param.aftercallback(); } remove() { this.stop(); } } class Timeout extends Interval { protected interval() { var f = this; if (f.stoped) return; f.vars.timeoutID = setTimeout(() => { if (f.stoped) return; f.param.callback(); }, f.param.duration); } } //It's just a timer... class Timer { checkpoints:Array; isStarted:boolean; last:number; constructor() { this.restart(); } restart() { this.checkpoints = []; this.isStarted = false; } start() { if (this.isStarted) return; this.isStarted = true; this.checkpoints.push( Date.now() ); } stop() { if (!this.isStarted) return; this.isStarted = false; this.checkpoints.push( Date.now() ); } ms() { var now = Date.now(); var pauseTime = false; var ms = 0; for(let key in this.checkpoints) { let i:number = parseInt(key); if (pauseTime) { ms += this.checkpoints[i] - this.checkpoints[ i-1 ]; } pauseTime = !pauseTime; } if (pauseTime) { ms += now - this.checkpoints[ this.checkpoints.length-1 ]; } return ms; } s() { var ms = this.ms(); return round(ms/1000, 3); } delay(sec) { if (not(this.last)) return 0; return round(sec - this.last, 3); } i() { var sec = this.s(); var delay:number, delay = this.delay(sec); var info:string = sec + ""; if (is(this.last)) info += " (+" + delay + ") sec"; this.last = sec; return info; } }