/* oak_DataTable */
oak_DataTable=function(o={}){
this.cfg = o;
/** fetch 参数 */
init= {method: "POST",credentials: "include", cache: "no-cache"};
this.initializer();
}
oak_DataTable.prototype = {
NAME:'oak_DataTable',
cfg:{},
data:[],
table:null,
datasource:[],
tbody:null,
_plugins:[],
jsonData:{},
/** 初始化函数,自动加载 css 文件,建立表格,表格头,表格体 */
initializer:function(){
this._getCss();
this.table = document.createElement('table');
this.table.classList.add('oak-editor-table');
this.table.style.width = this.cfg.width || '100%';
this.creatThead();
this.tbody = this.table.appendChild(document.createElement('tbody'));
},
/**
* 事件监听
* @param {事件名称} ev
* @param {绑定的事件处理函数} fn
*/
on:function(ev,fn){this.table.addEventListener(ev,fn);},
/**
* 取消事件监听
* @param {*事件名称} ev
* @param {*绑定的事件处理函数} fn
*/
detach:function(ev,fn){this.table.removeEventListener(ev,fn);},
/**
* 自定义时间发射
* @param {string 发射事件名字} e
* @param {object 事件跟随的参数} o
* @param {*} canBubble
* @param {*} cancelable
*/
fire:function(e,o={},canBubble=false,cancelable=false){
var evt = document.createEvent("HTMLEvents");
evt.initEvent(e, canBubble, cancelable);
Object.assign(evt,o);
this.table.dispatchEvent(evt);
},
/**
*
* @param {string 服务器url地址} url
* @param {Object fetch用配置参数 } init
* @param {function 回调函数} fn
* @param {选择返回的数据格式 json 或 text} format
*/
ajax:function(url,init,fn=null,format='json'){
if(!url){console.log('权限不足,请重新登陆');return;}
fetch(url,init).then((response) => {return response[format]();}).then((a) => {
if(typeof fn =='function')fn.call(this,a);
}).catch((e)=>{console.log('Fetch Error : ', e);});
},
/**
*
* @param {数组 或 字符串 url} source
* @param {对返回json 格式化的函数} fn
* @param {字典} map
* @param {选择返回的数据格式 json 或 text} format
*/
upData:function(source,fn=null,map=new Map(),format='json'){
source = source || this.cfg.datasource;
if(source instanceof Array)
this.uptbody(source);
else {
if(source){
if(typeof(FormData.prototype.set)=="undefined")FormData.prototype.set=FormData.prototype.append;
init.body = new FormData();
for(const [k, v] of map)init.body.set(k,v);
init.body.set('postvar',JSON.stringify(this.cfg.postvar));
this.ajax(source,init,function(a){if(fn)fn.call(this,a);else this.uptbody(a);},format);
}else console.log('没有数据源或远程数据接口。');
}
},
/**
* 更新表格数据
* @param {object,json 分析过的数据} o
*/
uptbody:function (o){
var d = this.tbody;
while(d.rows.length >0){d.deleteRow(d.rows.length-1)}
for(i=0;i<o.length;i++){
this.creatRow(i,o[i]);
}
},
setVar:function(k,v){this.cfg.postvar[k] = v;return this;},
delVar:function(k){delete this.cfg.postvar[k];return this;},
render:function(n){
n = document.querySelector(n);
n.appendChild(this.table);
//this.upData();
return this;
},
/** */
creatThead:function(){
var i,th,head = this.table.createTHead(),tr = head.insertRow(),
colgroup = document.createElement("colgroup"),cols=this.cfg.columns;
for(i=0; i < cols.length;i++){
let colN = document.createElement("col");
if(cols[i].width)colN.style.width = cols[i].width;
colgroup.appendChild(colN);
th = tr.appendChild(document.createElement('th'));
th.setAttribute('data-key',cols[i].key);
if(cols[i].onclick)
cols[i].onclick.call(this,{node:th,col:cols[i]});
th.innerHTML = cols[i].label;
}
this.table.appendChild(colgroup);
},
/** 建立表格行
* @param { number 索引} i
* @param { array 表格行用的数据} record
*/
creatRow:function(i,record){
var trNode = this.tbody.insertRow(),map = new Map(),cols =this.cfg.columns;
for(j=0;j < cols.length;j++){
map.set(cols[j].key,record[cols[j].key]);
this.creatCell(cols[j],trNode,map);
}
this.data[i] = map;
},
/** 在表格行插入列
* @param {Object 参数} column
* @param {node 表格行节点} row
* @param {map 字典} map
*/
creatCell:function(col,tr,map){
var td=tr.insertCell();
td.setAttribute('data-key',col.key);
td.innerHTML = map.get(col.key);
if(col.format){col.format.call(this,{col,td,map});}
if(col.edit){td.classList.add('cursor_pointer');td.onclick=this._onClick.bind(this,{col,td,map});}
},
/**
* 表格onclick 事件处理函数
* @param {附属参数} o
* @param {事件对象} e
*/
_onClick:function(o){
var changeData,td=o.td,value = td.innerHTML, host = this,n = this.creatNode('<input type="text"/>');
if(td.querySelector('input') || td.tagName != 'TD') return;
td.innerHTML='';
n.style.height = td.offsetHeight -5 +'px';
n.value = value;
n.blurfn = function(){
td.innerHTML = n.value || value ;
if(td.innerHTML == value) return;
changeData = {'key':o.col.key,'value':n.value};
o.map.set(o.col.key,n.value);
if(td.parentNode.rowIndex){
host.fire('savedata',{changeData:changeData,map:o.map});
}
n.remove(true);
};
n.onkeypress = function(e){e.which == 13 && n.blur();};
td.appendChild(n);
if(o.col.editformat)o.col.editformat.call(this,o);
n.onblur=n.blurfn;
n.focus();
},
/**
* 添加插件函数
* @param {string 插件类名字} Plugin
* @param {object 插件类实例化时的参数} config
*/
plug:function (Plugin, config) {
Plugin.prototype.HOST =this;
var o = new Plugin(config);
this[o.NAME] = o;
this._plugins[o.NAME] = Plugin;
return this;
},
/* 加载同目录下的同名字CSS文件 至引用html页面 */
_getCss:function(a=[]){
var host=this,cssPaths=[], o = document.getElementsByTagName('head').item(0) || document.getElementsByTagName('body').item(0);
a.forEach((function(v){cssPaths.push(this.jsPATH+v)}).bind(this));
cssPaths.push(this.jsPATH+this.NAME+'.css');
if (o){
cssPaths.forEach(function(css){
o.appendChild(host.creatNode('<link charset="utf-8" rel="stylesheet" href="'+css+'" async>'));
})};
},
/* 使用字符串建立节点,tr td th 除外 */
creatNode:function (s) {
var n = document.createElement("div");
n.innerHTML = s;
return n.childNodes[0];
},
/**
* 绝对定位窗口
* @param {顶部节点} topnode
* @param {加入窗口的节点及内容} node
* @param {*} v
* @param {点击事件调用函数} fn
*/
creatBox:function(topnode,node,fn=null){
var host = this,box = this.creatNode('<div style="overflow:auto;" class="oeditor-toolbar-box"></div>'),
o= document.querySelector('.oeditor-toolbar-box');
box.appendChild(node);
o&&o.remove(true);
box.style.left=Math.round(topnode.getBoundingClientRect().left) +'px';
box.style.top=Math.round(topnode.getBoundingClientRect().top)+topnode.offsetHeight+'px';
box.style.width=Math.round(topnode.getBoundingClientRect().width-2)+'px';
window.addEventListener('scroll',function(e){box.style.top=Math.round(topnode.getBoundingClientRect().top)+
topnode.offsetHeight+'px';});
box.onmouseleave=function(){box.remove();}
box.onclick=function(e){
fn.call(host,e.target);
box.remove();
};
return box;
}
}
/*
取得js路径,自动加载同目录下的同名字CSS文件使用。
*/
oak_DataTable.prototype.jsPATH = document.scripts[document.scripts.length - 1].src.substring(0, document.scripts[document.scripts.length - 1].src.lastIndexOf("/") + 1);