add simple js treegrid implementation
parent
1ca49f6bf5
commit
b3476556ed
|
@ -0,0 +1,83 @@
|
|||
/* some common clear */
|
||||
html, body { font-size: 100%; font-family: sans-serif; width: 100%; height: 100%; padding: 0; margin: 0; }
|
||||
select, input, textarea { box-sizing: border-box; font-size: 100%; }
|
||||
table, td, th { vertical-align: top; font-size: 100%; }
|
||||
img { vertical-align: middle; }
|
||||
body { -moz-text-size-adjust: none; } /* do not scale fonts in mobile firefox */
|
||||
table { border-collapse: collapse; }
|
||||
|
||||
/* scroll div styles */
|
||||
.scroller
|
||||
{
|
||||
float: left;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.scroller > .inner
|
||||
{
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
/* fixed header table styles */
|
||||
table.grid tbody tr:hover, table.grid tbody tr:hover td
|
||||
{
|
||||
background-color: #e2eff8;
|
||||
}
|
||||
|
||||
table.grid tr.selected
|
||||
{
|
||||
background-color: #c1ddf1;
|
||||
}
|
||||
|
||||
table.grid thead th
|
||||
{
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
table.grid th
|
||||
{
|
||||
font-weight: normal;
|
||||
color: #405060;
|
||||
}
|
||||
|
||||
table.grid
|
||||
{
|
||||
width: auto;
|
||||
}
|
||||
|
||||
table.grid td, table.grid th
|
||||
{
|
||||
border: 1px solid #ccc;
|
||||
background-clip: padding-box; /* O_o firefox draws background over borders */
|
||||
padding: 3px;
|
||||
font-size: 13px;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/* treegrid styles */
|
||||
table.grid .collapser
|
||||
{
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
float: left;
|
||||
margin: 0 4px 0 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
table.grid .collapser-collapsed
|
||||
{
|
||||
background: url(unfold2.png);
|
||||
}
|
||||
|
||||
table.grid .collapser-expanded
|
||||
{
|
||||
background: url(fold2.png);
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
/**
|
||||
* Very simple and fast tree grid/table, compatible with dynamic loading and jQuery fixedHeaderTable
|
||||
* License: MPL 2.0+, (c) Vitaliy Filippov 2016
|
||||
*/
|
||||
|
||||
/**
|
||||
* USAGE:
|
||||
*
|
||||
* var TG = new TreeGrid(items, header);
|
||||
* document.body.appendChild(TG.table);
|
||||
*
|
||||
* items: [ node={
|
||||
* cells: [ 'html' or { innerHTML, style, className, title }, ... ],
|
||||
* children: [ node... ],
|
||||
* leaf: true/false,
|
||||
* collapsed: true/false
|
||||
* }, ... ]
|
||||
*
|
||||
* header: [ 'html' or { innerHTML, style, className, title }, ... ]
|
||||
*/
|
||||
function TreeGrid(items, header)
|
||||
{
|
||||
this.bindProps = { 'style': 1, 'className': 1, 'title': 1, 'innerHTML': 1 };
|
||||
this.levelIndent = 20;
|
||||
this.table = document.createElement('table');
|
||||
this.table.className = 'grid';
|
||||
this.thead = document.createElement('thead');
|
||||
this.tbody = document.createElement('tbody');
|
||||
this.table.appendChild(this.thead);
|
||||
this.table.appendChild(this.tbody);
|
||||
this.thead.appendChild(document.createElement('tr'));
|
||||
this.setHeader(header);
|
||||
new TreeGridNode({ children: items }, this);
|
||||
}
|
||||
|
||||
TreeGrid.prototype.setHeader = function(newHeader)
|
||||
{
|
||||
var tr = this.thead.rows[0];
|
||||
tr.innerHTML = '';
|
||||
for (var i = 0; i < newHeader.length; i++)
|
||||
{
|
||||
var th = document.createElement('th');
|
||||
this._setProps(th, newHeader[i]);
|
||||
tr.appendChild(th);
|
||||
}
|
||||
this.header = newHeader;
|
||||
// header change clears the whole grid by now
|
||||
if (this.root)
|
||||
this.root.setChildren([]);
|
||||
}
|
||||
|
||||
TreeGrid.prototype.onExpand = function(node)
|
||||
{
|
||||
// handle node expand/collapse here
|
||||
return true;
|
||||
}
|
||||
|
||||
TreeGrid.prototype._setProps = function(el, props)
|
||||
{
|
||||
if (typeof props == 'string')
|
||||
el.innerHTML = props;
|
||||
else
|
||||
for (var j in this.bindProps)
|
||||
if (props[j])
|
||||
el[j] = props[j];
|
||||
}
|
||||
|
||||
function TreeGridNode(node, grid, level, insertBefore, startHidden)
|
||||
{
|
||||
this.grid = grid;
|
||||
this.level = level;
|
||||
if (this.level === undefined)
|
||||
this.level = -1;
|
||||
if (!grid.root)
|
||||
grid.root = this;
|
||||
else
|
||||
{
|
||||
this.leaf = node.leaf;
|
||||
this.collapsed = node.collapsed || !node.leaf && (!node.children || !node.children.length);
|
||||
this.cells = node.cells || [];
|
||||
this.tr = document.createElement('tr');
|
||||
if (startHidden)
|
||||
this.tr.style.display = 'none';
|
||||
this.tr._level = this.level;
|
||||
for (var i = 0; i < this.grid.header.length; i++)
|
||||
{
|
||||
var td = document.createElement('td');
|
||||
if (this.cells[i])
|
||||
grid._setProps(td, this.cells[i]);
|
||||
this.tr.appendChild(td);
|
||||
}
|
||||
var collapser = document.createElement('div');
|
||||
if (this.leaf)
|
||||
collapser.className = 'collapser collapser-inactive';
|
||||
else
|
||||
{
|
||||
collapser.className = this.collapsed ? 'collapser collapser-collapsed' : 'collapser collapser-expanded';
|
||||
var self = this;
|
||||
addListener(collapser, 'click', function(e) { self._toggleHandler(); });
|
||||
}
|
||||
var c0 = this.tr.cells[0];
|
||||
c0.childNodes.length ? c0.insertBefore(collapser, c0.firstChild) : c0.appendChild(collapser);
|
||||
if (grid._initialPadding === undefined)
|
||||
{
|
||||
var p0 = curStyle(c0).paddingLeft || '';
|
||||
if (p0.substr(p0.length-2) == 'px')
|
||||
p0 = parseInt(p0.substr(0, p0.length-2));
|
||||
else
|
||||
p0 = 0;
|
||||
grid._initialPadding = p0;
|
||||
}
|
||||
c0.style.paddingLeft = (grid._initialPadding + grid.levelIndent * level) + 'px';
|
||||
insertBefore ? grid.tbody.insertBefore(this.tr, insertBefore) : grid.tbody.appendChild(this.tr);
|
||||
}
|
||||
this.children = [];
|
||||
if (node.children)
|
||||
for (var i = 0; i < node.children.length; i++)
|
||||
this.children.push(new TreeGridNode(node.children[i], grid, this.level+1, insertBefore, this.collapsed));
|
||||
}
|
||||
|
||||
TreeGridNode.prototype._toggleHandler = function()
|
||||
{
|
||||
if (!this.grid.onExpand(this))
|
||||
return;
|
||||
this.toggle();
|
||||
}
|
||||
|
||||
TreeGridNode.prototype.toggle = function()
|
||||
{
|
||||
if (this.leaf)
|
||||
return;
|
||||
this.collapsed = !this.collapsed;
|
||||
this.tr.cells[0].firstChild.className = this.collapsed ? 'collapser collapser-collapsed' : 'collapser collapser-expanded';
|
||||
if (this.collapsed)
|
||||
{
|
||||
// collapse all children
|
||||
var c = this.tr.nextSibling;
|
||||
while (c && c._level > this.level)
|
||||
{
|
||||
c.style.display = 'none';
|
||||
c = c.nextSibling;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// expand all children except children of collapsed subnodes
|
||||
var st = this.children.concat([]);
|
||||
while (st.length)
|
||||
{
|
||||
var e = st.pop();
|
||||
e.tr.style.display = '';
|
||||
if (!e.collapsed)
|
||||
st = st.concat(e.children);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TreeGridNode.prototype.setChildren = function(isLeaf, newChildren)
|
||||
{
|
||||
if (!this.tr)
|
||||
this.grid.tbody.innerHTML = '';
|
||||
else
|
||||
while (this.tr.nextSibling && this.tr.nextSibling._level > this.level)
|
||||
this.grid.tbody.removeChild(this.tr.nextSibling);
|
||||
this.leaf = isLeaf;
|
||||
if (this.leaf)
|
||||
this.tr.cells[0].firstChild.className = 'collapser collapser-inactive';
|
||||
else
|
||||
this.tr.cells[0].firstChild.className = this.collapsed ? 'collapser collapser-collapsed' : 'collapser collapser-expanded';
|
||||
this.children = [];
|
||||
var insertBefore = this.tr && this.tr.nextSibling;
|
||||
for (var i = 0; i < newChildren.length; i++)
|
||||
this.children.push(new TreeGridNode(newChildren[i], this.grid, this.level+1, insertBefore, this.collapsed));
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<link rel="stylesheet" type="text/css" href="treegrid.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../tplext/fht/defaultTheme.css">
|
||||
<script type="text/javascript" src="../tplext/jquery-1.11.2.min.js"></script>
|
||||
<script type="text/javascript" src="../tplext/fht/jquery.fixedheadertable.js"></script>
|
||||
<script type="text/javascript" src="util.js"></script>
|
||||
<script type="text/javascript" src="treegrid.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="scroller"><div class="inner" id="innerdiv">
|
||||
</div></div>
|
||||
<script>
|
||||
<!--
|
||||
onDomReady(function() {
|
||||
var i = {
|
||||
cells: [ 'Payment from Gazprom to Shell 2', '4', '5' ]
|
||||
};
|
||||
var TG = new TreeGrid([ {
|
||||
cells: [ 'Payment from Gazprom to Shell', '2', '3' ]
|
||||
} ], [ '', '15 фев', '16 фев', '17 фев', '18 фев', '19 фев', '20 фев', '21 фев' ]);
|
||||
TG.table.className = 'grid';
|
||||
TG.onExpand = function(node)
|
||||
{
|
||||
// Dynamic loading example
|
||||
if (!node.children.length)
|
||||
node.setChildren(false, [ i ]);
|
||||
return true;
|
||||
|
||||
// Another example with delay (emulation of server interaction)
|
||||
setTimeout(function() {
|
||||
if (!node.children.length)
|
||||
node.setChildren(false, [ i ]);
|
||||
node.toggle();
|
||||
}, 100);
|
||||
return false;
|
||||
};
|
||||
document.getElementById('innerdiv').appendChild(TG.table);
|
||||
$(TG.table).fixedHeaderTable({});
|
||||
});
|
||||
//-->
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
5
util.js
5
util.js
|
@ -278,3 +278,8 @@ window.unmg = function(id, str)
|
|||
str = decodeURIComponent(str.replace(/([\x20-\x24\x26-\x79])|(%..)/g, function(m, m1, m2) { return m2 || ('%'+(159-m1.charCodeAt(0)).toString(16)); }));
|
||||
document.getElementById(id).innerHTML = '<a href="ma'+'ilt'+'o:'+str+'">'+str+'</a>';
|
||||
};
|
||||
|
||||
window.curStyle = function(e)
|
||||
{
|
||||
return window.getComputedStyle ? getComputedStyle(e) : e.currentStyle;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue