// JavaScript Document
if(!String.prototype.trim) {
 String.prototype.trim = function() {
 return this.replace(/^s+|s+$/g, ''); 
 }
}

if(!Array.prototype.findIndex) {
 Array.prototype.findIndex = function(match_func) {
 	for (var i=0;i<this.length;i++)
		if (match_func(this[i])) return i;
	return -1;
 }
}

if(!Array.prototype.forEach) {
 Array.prototype.forEach = function(func) {
 	for (var i=0;i<this.length;i++)
		func(this[i]); }
}
if(!Object.prototype.forEach) {
 Object.prototype.forEach = function(func) {
 	for (var i=0;i<this.length;i++)
		func(this[i]); }
}


function query(QueryOrElement,css){
	let _nodes;
	let _q={
		isQuery:true,
		QueryOrElement:QueryOrElement,
		get:(index)=>_q._get(index),
		arrayConvert:(originArray,convert)=>{
			let arr=[];
			for (let i=0;i<originArray.length;i++) arr.push(convert(originArray[i]));
			return arr;
		},
		_get:(index)=>{
			let q=_q.QueryOrElement;
			if(typeof(q)=='string'){
				if (q[0]=='<'){
					let parts=q.match(/(?<=<)[^>]+(?=>)/g);
					_nodes=_q.arrayConvert(parts,(tag)=>dom.create(tag.replace('/','')));
					for(let i=1;i<parts.length;i++)	_nodes[i-1].appendChild(_nodes[i]);
					QueryOrElement=_nodes;
					_q.QueryOrElement=_nodes;
				}else{
					let tmps=document.querySelectorAll(q);
					_nodes=[];
					for(let i=0;i<tmps.length;i++) _nodes.push(tmps[i]);
					if(_nodes==null) console.log('選擇器指定的元素不存在:'+q);
				}
			}else if(Array.isArray(q)){
				_nodes=_q.arrayConvert(q,
					q=>{return typeof q=='string'?document.querySelector(q):q});
			}else if(q.isQuery){
				_nodes=q.get();
			}else _nodes=[q];
			if (index===undefined) return _nodes;
			if (index>=_nodes.length) return {};
			return _nodes[index];
		},
		each:(func)=>{
			let items=_q._get();
			for(let i=0;i<items.length;i++) func(items[i]);
			return _q;
		},
		names:(strNames)=>{
			strNames.split(',')
		},
		add:(childNode)=>{
			return _q.each(function(c) {
				if (typeof(childNode)=='string') c.insertAdjacentHTML('beforeend', childNode);
				else if(childNode.isQuery) childNode.get().forEach(function(cc){_q.append(cc)});
				else c.appendChild(childNode);
			});
		},
		append:(childNode)=>_q.add(childNode),
		before:(insertNode)=>{
			return _q.each(function(c){
				if(typeof(insertNode)=='string') c.insertAdjacentHTML('beforebegin', childNode);
				else c.parentNode.insertBefore(insertNode,c)
			});
		},
		after:(insertNode)=>{
			return _q.each(function(c){
				if(typeof(insertNode)=='string'){
					c.insertAdjacentHTML('afterend', childNode);
					return;
				}
				let parent =c.parentNode;
				if(parent.lastChild ==c){
					parent.appendChild(insertNode);
				}else{
					parent.insertBefore(insertNode,c.nextSibling);}
			});		
		},
		appendTo:(parent)=>{
			if (parent.isQuery) parent.append(_q.get(0));
			else if(typeof(parent)=='string') query(parent).append(_q.get(0));
			else parent.appendChild(_q.get(0));
			return _q;
		},
		empty:()=>{
			let _empty=(c)=>{
				if (c && c.childNodes && c.childNodes.length)
				for(let i=(c.childNodes.length-1);i>=0;i--){
					if (c.childNodes[i].childNodes) _empty(c.childNodes[i].childNodes);
					c.removeChild(c.childNodes[i]);
				}
			}
			return _q.each(_empty);
		},
		remove:(childNode)=>{
			let _remove=(c)=>{
				while (c && c.childNodes && c.childNodes.length) c.childNodes.forEach(_remove);//(c.childNodes);
				if(c && c.parentNode) c.parentNode.removeChild(c);
			}
			return _q.each(_remove);
		},
		id:(value)=>{return _q.attr('id',value);},
		attr:(name,value)=>{
			if (value!==undefined)
				return _q.each(function(child){child.setAttribute(name,value);});
			else
				return _q._get(0).getAttribute(name);
		},
		removeAttr:(name)=>{
			return _q.each(function(child){child.removeAttribute(name)});
		},
		text:(content)=>{
			if (content===undefined) return _q._get(0).innerText;
			return _q.each(function(c){c.innerText=content});
		},
		html:(content)=>{
			if(content===undefined) return _q._get(0).innerHTML;
			return _q.each(function(c){c.innerHTML=content});
		},
		value:(content)=>{
			let isInput=(box)=>{return box.tagName.toLowerCase()=='input'||box.tagName.toLowerCase()=='select'};
			if(content===undefined) return isInput(_q._get(0))?_q._get(0).value:_q.text();
			return _q.each(function(c){if (isInput(c))c.value=content;else c.innerText=content});
		},
		val:(text)=>_q.value(text),
		css:(name,value)=>{
			if(name===undefined) return _q;
			if(typeof name=='string'){
				if (value===undefined) return _q.get(0).style[name];
				_q.each(function(child){child.style[name]=value});
			}else
				for (let key in name) _q.css(key,name[key]);
			return _q;
		},
		addClass:(className)=>{
			if (!className) return _q;
			if (className.indexOf(' ')>-1){
				let lst=className.split(' ').filter(function(s) {return s!=""}).forEach(_q.addClass);
				return _q;
			}
			return _q.each(function(c){c.classList.add(className)});
		},
		removeClass:(className)=>{
			return _q.each(function(c){c.classList.remove(className)});
		},
		width:(value)=>{
			if (value===undefined) return _q._get(0).offsetWidth;
			return _q.each(function(c){c.style.width=(typeof value=='string')?value:value+'px'});
		},
		height:(value)=>{
			if (value===undefined) return _q._get(0).offsetHeight;
			return _q.each(function(c){c.style.height=(typeof value=='string')?value:value+'px'});
		},
		parent:()=>{
			return _q._get(0).parentNode;
		},
		children:(selector,index)=>{
			let _nodes=[]
			_q.each((item)=>{
				let c=item.querySelectorAll(selector);
				for(let i=0;i<c.length;i++)_nodes.push(c[i]);
			});
			if (index!==undefined) {
				if (_nodes.length>=index) console.log('選擇器所指定的元件不存在: '+selector+' index:'+index);
				return new query(_nodes[index]);
			}
			return new query(_nodes);
		},
		child:(s,i)=>{return _q.children(s,i)},
		hide:()=>{
			return _q.each(function(child){child.style.display='none'});
		},
		show:(value)=>{
			return _q.each(function(child){child.style.display=(value==undefined)?'':value});
		},
		on:(event,callback,option)=>{
			if (callback===undefined) return _q;
			return _q.each(function(c){c.addEventListener(event,callback,option);});
		},
		off:(event,callback,option)=>{
			return _q.each(function(c){c.removeEventListener(event,callback,option)});
		},
		click:(callback,option)=>{
			if(!callback) return _q;
			if (option==undefined) option=true;
			return _q.each(function(c){c.addEventListener('click',callback,option)});//c.onclick=callback});
		},
		enter:()=>{
			return _q.each(function(c){c.appendChild(document.createElement('br'))});
		},
		addDiv:(className,text)=>{
			return _q.each(function(c) {c.appendChild(dom.create('div',className,text))});
		},
		addSpan:(className,text)=>{
			return _q.each(function(c) {c.appendChild(dom.create('span',className,text))});
		},
		addInput:(value,className)=>{
			return _q.each(function(c){c.appendChild(dom.newIput(value,className))});
		},
		addButton:(text,onclick,className)=>{
			return _q.each(function(c){c.appendChild(dom.newButton(text,onclick,className))});
		}
	}

	
	if (css!==undefined) _q.css(css);
	return _q;
}

function Storage(store){
	return {
		save:function(name,value){
			let obj={_isJson:true,value:value};
			store.setItem(name,JSON.stringify(obj));
		},
		read:function(name){
			let txt=store.getItem(name);
			if(txt==null) return txt;
			try{
				let obj=JSON.parse(txt);
				if (obj._isJson) return obj.value;
				return obj;
			}catch{	return txt;}
		},
		remove:function(name){
			store.removeItem(name);
		}
	}
}

var dom={
	install:function(){
		$=dom.$;
		//$=query;
	},
	$:function(q,css){
		return query(q,css);
		//return new query(q); //回傳的一定是新元件，不需要new
	},
	isDarkMode:function(){
		try{return window.matchMedia('(prefers-color-scheme: dark)').matches;}
		catch{return false;}
	},
	create:function(tag,className,text,id){
		let ele=document.createElement(tag?tag:'div');
		if (className!=null) ele.className=className;
		if (text!=null)ele.innerText=text;
		if (id!=null)ele.id=id;
		return ele;
	},
	newInput:function(value,className){
		let input=dom.create('input',className);
		input.type='text';
		input.value=value;
		return input;
	},
	newButton:function(text,onclick,className){
		let btn=dom.create('input',className);
		btn.type='button';
		if(text!=null)btn.value=text;
		btn.onclick=onclick;
		return btn;
	},
	newTable:function(columnNumber, rowNumber, classNames,IDs){
		let table=dom.create('table');
		let body=dom.create('tbody')
		table.appendChild(body);
		table.addRow=function(){
			let tr=dom.create('tr')
			tr.add=function(text,className){
				let td=dom.create('td',className,text)
				tr.appendChild(td);
				return td;
			}
			body.appendChild(tr);
			return tr;
		}
		for(let c=0;c<columnNumber;c++){
			let tr=table.addRow();
			for(let r=0;r<rowNumber;r++){
				let td=tr.add();
				if (classNames && classNames[r])td.className=classNames[r];
				if (IDs && IDs[r])td.id=IDs[r];
				tr.appendChild(td);
			}
		}
		table.cell=(r,c)=>table.rows[r].cells[c];
		return table;
	},
	newImg:function(src,onclick,className,created){
		let img= dom.create('img',className);
		img.src=src;
		img.onclick=onclick;
		if (created!==undefined) created(img);
		return img;
	},
	getArgs:function(form,encode){
		if (typeof(form)=='string'){
			return dom.getUrlArgs()[form];
		}

		var args={};
		var toValue=function(node){
			if(['INPUT','SELECT'].indexOf(node.tagName.toUpperCase())>-1)
				return node.value;
			else{
				if (node.contentType=='html') return node.innerHTML;
				else return node.innerText;}
			/*if (node.tagName.toUpperCase()!='INPUT'){
				if (node.contentType=='html') return node.innerHTML;
				else return node.innerText;
			}else return node.value;*/
		}

		if (encode==null) encode=encodeURIComponent;

		var encodeValue=function(node){
			return encode(toValue(node));
		}
		let nodes=form.querySelectorAll('*[name]');
		for (var i=0;i<nodes.length;i++){
			if (nodes[i].getAttribute('name')!=null){
				if (nodes[i].type=="checkbox" && !nodes[i].checked) continue;

				let name=encode(nodes[i].getAttribute('name'));
				let value;
				if (nodes[i].type=="checkbox")	value=nodes[i].value;
				else	value=encodeValue(nodes[i]);
				//args[name]=encodeValue(nodes[i]);
				if (args[name]) args[name] += ","+ value;
				else args[name]=value;
				console.log("讀取參數: name="+nodes[i].getAttribute('name')+", value:"+toValue(nodes[i]));
			}
		}
		args.addRange=function(arrayArgs){
			for(let i=0;i<arrayArgs.length;i++) args[arrayArgs[i].name]=arrayArgs[i].value;
		}
		return args;
	},
	setting:new Storage(window.localStorage),
	cache:new Storage(window.sessionStorage),
	storage:function(name,value){
		if(value===undefined) return dom.setting.read(name);
		else dom.setting.save(name,value);
	},
	session:function(name,value){
		if(value===undefined) return dom.cache.read(name);
		else dom.cache.save(name,value);
	},
	cookie:function(name,value){
		if(value===undefined)
			return readCookie(name);
		else{
			document.cookie= name + "="+value;
		}
	},
	request:function(method,url,success,error,finished){
		this.args={};
		this.url=url;
		this.method=method.toUpperCase();
		this.send=function(newArgs,beforeSend){
			let content;
			if (typeof(newArgs)=='string'){
				content=newArgs;
			}else{
				let str_args=[];
				let addArgs=function(args){
					for(let name in args) {
						if(typeof args[name]=='function') continue; 
						str_args.push(name+'='+args[name]);
					}
				}
				addArgs(this.args);
				if(newArgs!==undefined)addArgs(newArgs);
				content=str_args.join('&');
			}

			this.xhr=new XMLHttpRequest();
			let xhr = this.xhr;
			xhr.open(this.method, url+((this.method=='GET' && content)?('?'+content):''));
			if (beforeSend) beforeSend(xhr);
			xhr.onreadystatechange=function()
			{
				if(xhr.readyState==4)
				{				
					if (xhr.status==200)
					{
						let obj;
						try{obj=JSON.parse(xhr.responseText);
						}catch{obj=xhr.responseText;}
						if(success) success(obj);
					}
					else if(xhr.status==0){
						if(error) error("伺服器無回應");
					}else{
						try{
							if (error) error(JSON.parse(xhr.responseText,xhr.status));
						}catch{
							if(error) error(xhr.responseText,xhr.status);
						}
					}
					if(finished) finished();
					xhr=null;
				}
			};
			xhr.send((this.method=='POST'?content:''));//讀取附件資訊
			return this;
		}
		return this;
	},
	get:function(url,success,error,finished){
		return dom.request('get',url,success,error,finished).send();
	},
	post:function(url,args,success,error,finished){
		return dom.request('post',url,success,error,finished).send(args);
	},
	postJson:function(url, args, success,error,finished){
		let req=dom.request('post',url,success,error,finished);
		return req.send(JSON.stringify(args),function(xhr){
			xhr.setRequestHeader("Content-Type","application/json; charset=utf-8");
		});
	},
	getUrlArgs:function(encoded){
		if (location.search.indexOf("?") == -1) return {};
		let decode=encoded?decodeURIComponent:e=>e;
		let args={};
		let texts=location.search.split("?")[1].split('&');
		for(let i=0;i<texts.length;i++) args[texts[i].split('=')[0]]=decode(texts[i].split('=')[1]);
		return args;
	 },
	 combinePath:function(...p){
		 return Array.from(p.filter((txt)=>{return txt}),function(a){return a.replace(/^(\\|\/)|(\\|\/)$/g,'')}).join('\/');
		//return Array.from(p,function(a){return a.replace(/^(\\|\/)|(\\|\/)$/g,'')}).join('\/');
	},
	copy:function(obj){
		return JSON.parse(JSON.stringify(obj));
	},
	update:function(dest, source){
		let obj=dom.copy(dest);
		for (let k in source) obj[k]=source[k];
		return obj;
	}
}

function getXmlHttp(){
	var objXMLHttp = null;
	if (window.XMLHttpRequest)
	{
		// Firefox, Opera 8.0+, Safari
		objXMLHttp = new XMLHttpRequest();

	}
	else if (window.ActiveXObject)
	{
		// Internet Explorer
		try 
		{
			objXMLHttp = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e) 
		{
			objXMLHttp = new ActiveXObject("Microsoft.XMLHTTP");
		}
	
	}
	return objXMLHttp;
}

function JSLIB()
{
	
	this.lib={};
	//將程式碼載入<head>標籤中
	//dom: document
	//code: 程式碼內容
	this.append=function(dom,file,callback)
	{
		var ext=file.path.split('.').pop();
		var extlib={
			"js":	{"label":"script","type":"text/javascript"},
			"css":	{"label":"style" ,"type":"text/css"}};
		
		if (extlib[ext])
		{
			var obj=dom.createElement(extlib[ext].label);
			obj.setAttribute("type",extlib[ext].type);
			obj.setAttribute("source_name",file.path.split('//').pop());
			obj.innerHTML=file.code;
			dom.getElementsByTagName("head")[0].appendChild(obj);
		}
		else
		{
			alert("檔案:["+file.path+"]\n"+"無法辨識!");	
		}
		if (callback) callback();
	}

	
	this.preload=function(path,callback)
	{
		var key=path;
		if (this.lib[key])
		{
			if(callback) callback();
			return;
		}
		var obj=this;
		var req=getXmlHttp();
		req.open("GET",path,true);
		req.onreadystatechange=function()
		{
			if(req.readyState==4 && req.status==200)
			{
				obj.lib[key]={"path":path,"code":req.responseText};
				if (callback) callback();
			}
		};

		req.send();
	}
	
	//載入程式碼
	this.load=function(dom,path,callback)
	{
		var obj=this;
		if (obj.lib[path])
			obj.append(dom,obj.lib[path],callback);
		else
			this.preload(path,function(){
				obj.append(dom,obj.lib[path],callback);
				//if (callback) callback();
			});
	}
	
	//載入iframe內容
	this.iframe_load=function(f,path,callback)
	{
		var obj=this;
		this.preload(path,function(){
			f.onload=callback;
			/*f.sendbox='allow-scripts allow-same-origin';
			f.srcdoc=obj.lib[path].code;*/
			//f.contentWindow.document.innerHTML=obj.lib[path].code;
			f.contentWindow.document.open();
			f.contentWindow.document.write(obj.lib[path].code);
			f.contentWindow.document.close();
			//if (callback) callback();
			});
	}
}


//讀取Cookie
function readCookie(name) {
   var nameEQ = name + "=";
   var ca = document.cookie.split(';');
   for (var i = 0; i < ca.length; i++) {
      var c = ca[i];
      while (c.charAt(0) == ' ') c = c.substring(1, c.length);
      if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
   }
   return null;
}

function delCookie(name)//删除cookie
{
    var exp = new Date();
    exp.setTime(exp.getTime() - 1);
    var cval=readCookie(name);
    if(cval!=null) document.cookie= name + "="+cval+";expires="+exp.toGMTString()+";path="+location.pathname;
}

function clearAllCookie() {
	var keys = document.cookie.match(/[^ =;]+(?=\=)/g);
	if(keys) {
		for(var i = keys.length; i--;)
			document.cookie = keys[i] + '=0;expires=' + new Date(0).toUTCString()
	}
}

function replaceCookie(text){
	var cookies=text.split(';');
	cookies.forEach(c=>{document.cookie=c});
}