text: /** Extended JavaScript Functions v0.1
   * @author Wireless4024
   * @licence Apache 2.0
   * @licence https://www.apache.org/licenses/LICENSE-2.0
   */
  /** get return value from promise (await needed) */
  Promise.prototype.get||(Promise.prototype.get=async function(){
  	let val;
  	await this.then(function(a){val=a});
  	return val
  });
  /** invoke callback if true
   * @return Promise<any>
   */
  Promise.prototype.if||(Promise.prototype.if=function(callback){
  	this.then(function(a){a&&callback()})
  });
  /** invoke callback if false
   * @return Promise<any>
   */
  Promise.prototype.else||(Promise.prototype.else=function(callback){
  	this.then(function(a){!a&&callback()})
  });
  /** format string like "%s %s".format('hi','hello') become "hi hello"
   * @return string
   */
  String.prototype.format||(String.prototype.format=function(...args){
  	let index=0;
  	return this.replace(/%s\b/g,(match)=>args[index++]||match)
  	           .replace('%^s','%s')
  });
  /** sleep function
   * (await needed)
   * @param ms time to sleep in millisecond
   * @return {Promise<number>}
   */
  sleep=function(ms){
  	new Promise(function(resolve){setTimeout(resolve,ms);})
  };
  run=function(fnc){
  	const e=setInterval(function(){
  		clearInterval(e);
  		fnc();
  	})
  };
  /**
   * remove current script tag
   */
  remove=function(){
  	document.currentScript
  	        .remove();
  };
  /**
   * print text (html will auto escape) before this element
   * @param val value to print
   * @return ?
   */
  print=function(val){
  	document.currentScript&&
  	document.currentScript
  	        .parentNode
  	        .insertBefore(document.createTextNode(String(val)),document.currentScript)
  };
  /**
   * print text (html will auto escape) with new line character before this element
   * @param val value to print
   * @return ?
   */
  println=function(val){
  	document.currentScript&&
  	document.currentScript
  	        .parentNode
  	        .insertBefore(document.createTextNode(String(val)+'\n'),document.currentScript);
  };
  /**
   * print text (html will auto escape) + <br> before this element
   * @param val value to print
   * @return void
   */
  printbr=function(val){
  	document.currentScript&&
  	document.currentScript
  	        .parentNode
  	        .insertBefore(document.createTextNode(String(val)),document.currentScript);
  	document.currentScript&&
  	document.currentScript
  	        .parentNode
  	        .insertBefore(document.createElement('br'),document.currentScript)
  };
  /**
   * shorthand of console.log(this)
   */
  Object.prototype.log||Object.defineProperty(Object.prototype,"log",{
  	value:function(){
  		!!this&&console.log(this);
  	},
  	enumerable:false
  });
  
  /**
   * shorthand of print(this)
   */
  Object.prototype.print||Object.defineProperty(Object.prototype,"print",{
  	value:function(){
  		!!this&&print(this);
  	},
  	enumerable:false
  });
  
  /**
   * search element in array
   * @param condition value to find or function to find
   * @param typeCoercion use === instead of == (if condition is object)
   * @param defaultvalue return this value if not found
   * @return {?|undefined} index of item or defaultvalue not found
   */
  function search(condition,typeCoercion=false,defaultvalue=undefined){
  	if(typeof condition=='function'){
  		for(let i in this)
  			if(condition(this[i]))
  				return i;
  	}else{
  		if(typeCoercion){
  			for(let i in this)
  				if(condition===this[i])
  					return i;
  		}else{
  			for(let i in this)
  				if(condition==this[i])
  					return i;
  		}
  	}
  	return defaultvalue;
  }
  
  /**
   * search element in array using binary
   * @param array array to find
   * @param value value to find
   * @param typeCoercion use === instead of == (if condition is object)
   * @param defaultvalue return value if not found
   * @return {?|undefined} index of item or undefined not found
   */
  function bsearch(array,value,typeCoercion=false,defaultvalue=undefined){
  	let low=0,high=this.length-1,mid;
  	if(typeCoercion)
  		while(low<=high){
  			mid=(low+high)>>1;
  			if(value===this[mid]) return mid;
  			else if(this[mid]<value) low=mid+1;
  			else high=mid-1;
  		}
  	else
  		while(low<=high){
  			mid=(low+high)>>1;
  			if(value==this[mid]) return mid;
  			else if(this[mid]<value) low=mid+1;
  			else high=mid-1;
  		}
  	return defaultvalue;
  }
  
  class OrderedLoad extends Promise{
  	constructor(){
  		super(function(){});
  	}
  
  	/**
  	 * use to create element
  	 * @param name element name
  	 * @param property object property {attribute:value,...}
  	 */
  	static createElement(name,property){
  		const elem=document.createElement(name);
  		for(let i in property)
  			elem.setAttribute(i,property[i]);
  		return elem;
  	}
  
  	/**
  	 *
  	 * @param uri url to load css file
  	 * @returns {OrderedLoad}
  	 */
  	css(uri){
  		document.head.appendChild(
  			OrderedLoad.createElement('link',{
  				type:"text/css",
  				rel:"stylesheet",
  				href:uri
  			}));
  		return this;
  	}
  
  	/**
  	 *
  	 * @param uri url to load javascript file
  	 * @returns {OrderedLoad}
  	 */
  	js(uri){
  		document.body.appendChild(
  			OrderedLoad.createElement('script',{
  				type:"text/javascript",
  				src:uri
  			}));
  		return this;
  	}
  
  	then(fnc,rej=undefined){
  		return new Promise(fnc||function(){},rej||function(){});
  	}
  }