var NewMTable = (function(){
'use strict';
var tmpl = new Tmpl;
return function(t, o, scb){
return new MTable(t, o, scb);
};
function MTable(t, obj, selectCB){
let rowSelect = obj.rowSelect !== false,
events = new EventManager,
tableObj = new TableObj(obj, rowSelect),
tableTemplate = tmpl.index,
pagination = null,
rowsArray = [],
masterSelect = null,
activeSort = null,
tableReference = null,
rowsReference = null,
table = null,
maxPerPage = null,
currentPage = 1,
checkboxList = [],
searchActive = false,
searchKey = '',
searchValue = '',
onPageChange = obj.onPageChange || function() {};
this.getTableReference = getTableReference;
this.getSelectedRows = getSelectedRows;
this.getAllRows = getAllRows;
this.setTable = setTable;
this.sort = sort;
this.exit = exit;
this.search = search;
this.qSA= t.querySelectorAll.bind(t);
function initialize(){ table = render(tableTemplate, tableObj); if(table) initTable(table); }
function initTable(table){ setTable(table); processMaster(getHeader(t), getRows(t), getSelectColumns(t)); }
// Controller-level helper fns
function getTableReference(){ return tableReference; }
function getSelectedRows(){
var d = [];
loop(rowsArray, function(k, v){
if(!!v.getState && v.getState()){
d.push(v);
}
});
return d;
}
function getActiveRowsCount(){
var c = 0;
loop(rowsArray, function(k,v){
if(v.disabled !== true){
c++;
}
});
return c;
}
function getAllRows(){
var d = [];
loop(rowsArray, function(k, v){ d.push(v); });
return d;
}
function setTable(table){
t.innerHTML = table;
tableReference = t.childNodes[0];
rowsReference = tableReference.querySelector('rows');
}
function setPagination(t, l, mpp){
if(isDefined(pagination)){
pagination.updatePageCount(l, mpp);
} else {
pagination = new Pagination(t, l/mpp, 10, paginationUpdate);
}
shuffleRows();
}
function setMaxPerPage(o){ return maxPerPage = o.maxPerPage; }
function isShuffleItem(i, p){ return !p || (p && isInSet(i)); }
function isSearchItem(item){ return item.getData()[searchKey].toLowerCase().indexOf(searchValue) > -1; }
function isInSet(i){ return (Math.floor(i / maxPerPage) + 1) == currentPage; }
function searchRows(){ loop(rowsArray, function(k,v){ v.disabled = !isSearchItem(v); }); }
function processPagination(){
var mpp = setMaxPerPage(obj),
l = getActiveRowsCount();
if(isDefined(mpp)) setPagination(t, l, mpp);
}
function processMaster(header, rows, selectCols){
processHeader(header);
if(rowSelect === true){
processRows(header, rows, selectCols);
} else {
processNonSelectRows(header, rows);
}
processPagination();
}
function processRows(h, r, s){
loop(s, function(k,v){
if(k > 0){
var i = k-1;
rowsArray.push(new Row(r[i], v, i));
} else {
masterSelect = new MasterSelect(h, v);
}
});
}
function processNonSelectRows(h, r){ loop(r, function(k,v){ rowsArray.push(new Row(v, null, k)); }); }
function processHeader(h){
loop(h.querySelectorAll('cell-block'), function(k,v){
new Column(v, tableObj.columns[k], k);
});
}
function search(key, value){
if(isDefined(key) && isDefined(value) && isDefined(obj.columns[key])){
searchActive = true;
searchKey = key;
searchValue = value.toLowerCase();
}
else {
searchActive = false;
searchKey = '';
searchValue = '';
}
searchRows();
processPagination();
//shuffleRows();
}
function shuffleRows(){
var pA = isDefined(pagination);
if(pA) removeRows();
rowsReference.appendChild(shuffleAction(getFragment(), pA));
onPageChange(t);
}
function shuffleAction(f, pA){
var sCount = 0;
loop(rowsArray, function(k,v){
if(v.disabled === true) return;
if(isShuffleItem(sCount, pA)){
f.appendChild(v.getElement());
defer(v.refresh);
}
sCount++;
});
return f;
}
function sort(key, direction){
sortByColumn(key, direction, obj.columns[key].valueType);
}
function sortByColumn(key, direction, valueType){ rowsArray.sort(getSortFn(key, direction, valueType)); shuffleRows(); }
function removeRows(){ loop(Array.prototype.slice.call(rowsReference.childNodes).reverse(), function(k,v){ rowsReference.removeChild(v); }); }
function paginationUpdate(e){ currentPage = e; shuffleRows(); }
var Column = function(c, d, i){
var state = 1,
obj = { 'i' : i, 'unset' : unset };
bindColumn();
this.unset = unset;
function bindColumn(){ if(d.sortable !== false) events.add(c, 'click', clickAction); }
function clickAction(e){ if(e && e.preventDefault) e.preventDefault(); if(state === 0 || state === -1) setAscending(); else if(state === 1) setDescending(); }
function setAscending(){ if(!isActiveSort()) updateActiveSort(); state = 1; sortByColumn(d.key, state, d.valueType); setAscClass(); }
function setDescending(){ if(!isActiveSort()) updateActiveSort(); state = -1; sortByColumn(d.key, state, d.valueType); setDescClass(); }
function isActiveSort(){ return activeSort != null ? i == activeSort.i : false; }
function updateActiveSort(){ if(activeSort != null) activeSort.unset(); activeSort = obj; }
function unset(){ state = 0; unsetClasses(); }
function setAscClass(){ c.classList.add('asc'); c.classList.remove('desc'); }
function setDescClass(){ c.classList.add('desc'); c.classList.remove('asc'); }
function unsetClasses(){ c.classList.remove('asc'); c.classList.remove('desc'); }
};
var Row = function(t, s, i){
var input = isDefined(s) ? new Checkbox(s, inputUpdate) : null,
state = false,
cells = [];
if(input) checkboxList.push(input);
loop(t.querySelectorAll('cell-block'), function(k,v){
if(!!input && k === '0') return;
cells.push(new CellBlock(k, v));
});
this.getElement = getElement;
this.getData = getData;
this.exit = exit;
this.disabled = false;
this.refresh = refresh;
if(input !== null){
this.set = externalSet;
this.unset = externalunset;
this.getState = getState;
}
function inputUpdate(e){ if(e) set(true); else unset(true); }
function externalSet(){ input.set(); set(); }
function externalunset(){ input.unset(); unset(); }
function set(internal){ if(internal && selectCB) sendCB(); state = true; t.classList.add('selected'); }
function unset(internal){ if(internal && selectCB) sendCB(); state = false; t.classList.remove('selected'); }
function getState(){ return state; }
function getElement(){ return t; }
function getData(){ return JSON.parse(JSON.stringify(obj.rows[i])); }
function refresh(){
loop(cells, function(k,v){
v.refresh();
});
}
function exit(){ if(input) input.exit(); input = null; t = null; s = null; i = null; }
function sendCB(){ setTimeout(selectCB, 1); }
};
function CellBlock(k, v){
var cellCss = null,
spn = v.querySelector('span'),
owidth = 0,
ewidth = 0,
delta = 0,
tDur = 0, // Transition duration
expanded = false,
incPadding = 12,
locked = false,
loaded = false;
this.refresh = refresh;
this.expand = expand;
this.minimize = minimize;
function refresh(){
if(locked || loaded) return; // If only I could do, 'if locked AND loaded'..
locked = true;
defer(function(){ locked = false; });
cellCss = window.getComputedStyle(v);
owidth = v.offsetWidth;
ewidth = getEWidth();
delta = ewidth - owidth;
if(owidth === 0 || delta <= 0){
return;
}
delta += incPadding;
ewidth += incPadding;
setPadding();
var expnd = document.createElement('expand');
tDur = Math.ceil(delta / 100) * 100;
v.setAttribute('cssTransition', 'linear' + tDur);
v.appendChild(expnd);
events.add(expnd, 'click', toggle);
loaded = true;
}
function toggle(){
if(!expanded){
expand();
} else {
minimize();
}
}
function expand(){
if(locked) return;
locked = expanded = true;
v.classList.add('expanded');
v.style.width = ewidth + 'px';
v.style.marginRight = ((ewidth - owidth) * -1) + 'px';
setTimeout(function(){ locked = false; }, tDur);
}
function minimize(){
if(locked) return;
locked = true;
v.style.width = owidth + 'px';
v.style.marginRight = '';
setTimeout(function(){
locked = expanded = false;
v.classList.remove('expanded');
}, tDur);
}
function setPadding(){
v.style.paddingRight = parseFloat(cellCss.paddingRight) + incPadding + 'px';
cellCss = window.getComputedStyle(v);
}
function getEWidth(){
var spnCss = window.getComputedStyle(spn);
return Math.ceil(getPaddingValue(cellCss) + getPaddingValue(spnCss) + measureText(spn.textContent, spnCss.font));
}
function getPaddingValue(css){
var v = 0;
v += parseFloat(css.borderLeftWidth);
v += parseFloat(css.paddingLeft);
v += parseFloat(css.paddingRight);
v += parseFloat(css.borderRightWidth);
return v;
}
}
var MasterSelect = function(t, s){
var input = isDefined(s) ? new Checkbox(s, inputUpdate) : null;
if(input) checkboxList.push(input);
this.exit = exit;
function inputUpdate(e){ if(e) set(true); else unset(true); }
function set(internal){ if(internal && selectCB) sendCB(); state = true; t.classList.add('selected'); setRows(); }
function unset(internal){ if(internal && selectCB) sendCB(); state = false; t.classList.remove('selected'); unsetRows(); }
function setRows(){ loop(rowsArray, function(k,v){ v.set(); }); }
function unsetRows(){ loop(rowsArray, function(k,v){ v.unset(); }); }
function exit(){ if(input) input.exit(); input = null; t = null; s = null; }
function sendCB(){ setTimeout(selectCB, 1); }
};
function exit(){
if(events) events.reset();
if(tableReference) removeChild(t, tableReference);
if(rowsArray) exitRows();
if(checkboxList) exitCheckboxes();
tableObj = null;
tableTemplate = null;
masterSelect = null;
activeSort = null;
tableReference = null;
rowsReference = null;
table = null;
checkboxList = rowsArray = null;
}
function exitCheckboxes(){ forEach(checkboxList, p, true); function p(t, d, i){ if(t.exit) t.exit(); d.splice(i, 1); } }
function exitRows(){ loop(rowsArray, function(k,v){ v.exit(); }); }
initialize();
}
function Tmpl(){
var s = '{{# sortable }}sortable{{/ sortable }}',
c = '{{# centered }}centered{{/ centered }}',
w = '{{# width }}style="width: {{ . }}px"{{/ width }}',
t = '{{# title }}{{ . }}{{/ title }}',
si = '{{# sortable }}{{/ sortable }}';
var rc = '{{# centered }}centered{{/ centered }}',
rw = '{{# width }}style="width: {{ . }}px"{{/ width }}',
rs = '{{ html }}';
this.headerCell = ''+ t + si + '';
this.header = '{{# columns }}' + this.headerCell + '{{/ columns }}';
this.rowCell = '' + rs + '';
this.row = '{{# . }}' + this.rowCell + '{{/ . }}
';
this.rows = '{{# rows }}' + this.row + '{{/ rows }}';
this.index = '' + this.header + this.rows + '';
}
function TableObj(o, rs){
this.columns = getColumnArray(o.columns, rs);
this.rows = getRowsArray(o.rows, this.columns, rs);
}
function RowObj(o, k, col, c){
var t = getRowItemKey(k, o),
html = null;
if(t != null && typeof t === 'object' && 'title' in t) {
if('noTitle' in t) this.noTitle = true;
this.value = t.value;
html = t.html || t.title;
t = t.title;
}
this.title = getFormattedValue(t, col[c].formatType);
this.html = html || this.title;
this.value = isDefined(this.value) ? this.value : this.title;
this.width = col[c].width; this.key = col[c].key; this.centered = col[c].centered || false;
}
function getRowItemKey(k, o){ if(k === '#') return o.displayOrder; return o[k]; }
function getFormattedValue(s, formatType){
if(!isDefined(s)) return '';
if(!isDefined(formatType)) return s;
if(formatType == 'locale') return s.toLocaleString();
if(formatType == 'currency' && typeof s === 'number') return s.toFixed(2);
return s;
}
function getHeader(t){ return t.querySelector('header'); }
function getRows(t){ return t.querySelectorAll('row'); }
function getSelectColumns(t){ return t.querySelectorAll('.selectColumn'); }
function getRowsArray(d, col, rs){
var a = [];
loop(d, function(k, v){ a.push(getRowArray(v, col, rs)); });
return a;
}
function getRowArray(o, col, rs){
var a = [],
c = 0;
if(rs === true){
a.push({ 'width' : col[c].width, 'key' : col[c++].key });
}
loop(getKeyOrder(col, rs), function(k){
a.push(new RowObj(o, k, col, c++));
});
return a;
}
function getSortFn(key, direction, valueType){
if(valueType == 'number') {
return getNumberSortClosure(key, direction);
} else {
return getStringSortClosure(key, direction);
}
}
function getKeyOrder(a, rs){
var o = {},
si = (rs === true) ? 1 : 0;
loop(a, function(k,v){
if(k >= si){
o[v.key] = null;
}
});
return o;
}
function getRowSelectColumn(){ return { 'sortable' : false, 'width' : '60', 'key' : 'select' }; }
function getNumberSortClosure(k, d){ var key = k != '#' ? k : 'displayOrder'; return getTemplateSortClosure(key, d === 1 ? sortNumberAsc : sortNumberDesc); }
function getStringSortClosure(k, d){ return getTemplateSortClosure(k, d === 1 ? sortStringAsc : sortStringDesc); }
function getTemplateSortClosure(k, fn){
return function(k, fn){
return function(a, b){
if(a.getData()['__ignore__']) return 1000; // hacky, I know...
a = a.getData()[k];
b = b.getData()[k];
if(typeof a == 'object' && 'value' in a) {
a = a.value;
}
if(typeof b == 'object' && 'value' in b) {
b = b.value;
}
return fn(a, b);
};
}(k, fn);
}
function getColumnArray(o, rs){
var a = [];
if(rs === true){
a.push(getRowSelectColumn());
}
loop(o, function(k,v){ processColumn(v, k, a); });
return a;
}
function sortNumberAsc(a, b){ return a - b; }
function sortNumberDesc(a, b){ return b - a; }
function sortStringAsc(a, b){ return sortString(a, b, 1, -1); }
function sortStringDesc(a, b){ return sortString(a, b, -1, 1); }
function sortString(a, b, f, s){ if(a>b) return f; else if(a