/* * Created by MaiXinRong on 2017/2/9. * 项目管理 专用树结构 */ (function($) { var _setting = { tree: { id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', btnColumn: 1, nullId: -1 }, columns: [ { head: '工程列表', data: 'name', static: false, width: '100%', event: { getText: null, getIcon: null } } ], dataTemp: { id: -1, parentId: -1, nextId: -1, isTemp: true }, viewEvent: { beforeSelect: null, onSelectNode: null } }; var Node = (function () { function Node(tree, data) { this.parent = null; this.nextSibling = null; this.children = []; this.tree = tree; this.data = data; this.setting = tree.setting; this.expanded = true; this.row = null; this.expandBtn = null; } Node.prototype.firstChild = function() { return (this.children.length === 0) ? null : this.children[0]; }; Node.prototype.lastChild = function () { return (this.children.length === 0) ? null : this.children[this.children.length - 1]; } Node.prototype.deepestRow = function () { return (this.children.length === 0) ? this.row : this.lastChild().deepestRow(); } Node.prototype.addChild = function (child, childNext) { if (childNext){ this.children.push(child); } else { if (this.childIndex(childNext) > -1){ this.children.splice(this.childIndex(childNext) - 1, 0, child); } else { this.children.push(child); } } return child; }; Node.prototype.childIndex = function (child) { return this.children.indexOf(child); }; Node.prototype.depth = function () { return this.parent ? this.parent.depth() + 1 : 0; }; Node.prototype.domId = function () { return this.data ? this.tree.domId + '_' + this.data[this.setting.tree.id] : ''; }; Node.prototype.expand = function (bool) { this.expanded = bool; _view._refreshTreeBtn(this); if (this.expanded) { _view._showNodes(this.children); } else { _view._hideNodes(this.children); } }; Node.prototype.preSibling = function () { var iIndex = this.parent.childIndex(this); if (iIndex === -1){ return null; } else { return iIndex > 0 ? this.parent.children[iIndex-1] : null; } }; Node.prototype.setParent = function (parent) { if (parent && this.parent !== parent) { this.parent = parent; this.data[this.setting.tree.pid] = this.pid(); } }; Node.prototype.setNextSibling = function (nextSibling) { if (this.nextSibling !== nextSibling) { this.nextSibling = nextSibling; this.data[this.setting.tree.nid] = this.nid(); } } Node.prototype.id = function () { return this.data ? this.data[this.setting.tree.id] : -1; }; Node.prototype.pid = function () { return this.parent ? this.parent.id() : -1; }; Node.prototype.nid = function () { return this.nextSibling ? this.nextSibling.id() : -1; }; Node.prototype.propertyJoin = function (dataName) { return this.parent ? this.parent.propertyJoin(dataName) + ';' + this.data[dataName] : this.data[dataName]; } return Node; })(); var Tree = (function () { function Tree(obj, setting) { this._root = new Node(this); this.treeObj = obj; this.domId = obj.attr('id'); this.treeHeadObj = _view._makeTableHead(this.treeObj, setting); this.treeBodyObj = _view._makeTableBody(this.treeObj); this.setting = setting; var _maxNodeId = 0; this.newNodeId = function (id) { if (arguments.length > 0){ _maxNodeId = (id > _maxNodeId) ? id : _maxNodeId; } else { _maxNodeId += 1; return _maxNodeId; } }; this.maxNodeId = function (id){ if (arguments.length > 0) { _maxNodeId = Math.max(id, _maxNodeId); } else { return _maxNodeId; } } }; Tree.prototype.firstNode = function (){ return this._root.firstChild(); }; Tree.prototype.traverseDF = function(callback){ var recurse = function (node) { var i; if (node !== this._root) { callback(node); } for (i = 0; i < node.children.length; i++){ recurse(node.children[i]); } } recurse(this._root); }; Tree.prototype.findNode = function (id){ var treenode = null, callback = function (node) { if (node.data && node.data[node.setting.tree.id] === id){ treenode = node; } }; this.traverseDF.call(this, callback); return treenode; }; Tree.prototype.findNodeByDomId = function (domId) { var treenode = null, callback = function (node) { if (node.domId === domId) { treenode = node; } }; this.traverseDF.call(this, callback); return treenode; }; Tree.prototype.removeNode = function (node) { var iIndex; if (node) { iIndex = node.parent.childIndex(node); if (iIndex > 0) { node.parent.children[iIndex - 1].setNextSibling(node.nextSibling); } node.parent.children.splice(iIndex, 1); } _view._removeNodesRowDom([node]); }; Tree.prototype.loadData = function (arrData) { var i, that = this; var createTempNode = function (id, setting) { var tempData = {}; tempData[setting.tree.id] = id; return new Node(that, tempData); }; var loadNode = function (data, setting) { var node = that.findNode(data[setting.tree.id]) || null, parent = that.findNode(data[setting.tree.pid]) || null, next = that.findNode(data[setting.tree.nid]) || null, tempData; if (!node) { node = new Node(that, data); } node.data = data; that.maxNodeId(node.id()); if (!parent){ if (data[setting.tree.pid] === setting.tree.nullId) { parent = that._root; } else { parent = createTempNode(data[setting.tree.pid], setting); parent.parent = that._root; that._root.children.push(parent); } } if (node.parent && node.parent !== parent) { node.parent.children.splice(node.parent.childIndex(node), 1); } node.parent = parent; if (!next && data[setting.tree.nid] !== setting.tree.nullId) { next = createTempNode(data[setting.tree.nid], setting); next.parent = parent; parent.children.push(next); } node.nextSibling = next; if (parent.childIndex(node) === -1){ if (!next){ parent.children.push(node); } else if (parent.childIndex(next) === -1){ parent.children.push(node); parent.children.push(next); } else { parent.children.splice(parent.childIndex(next), 0, node); } } else if (parent.childIndex(node) !== parent.childIndex(node.next) - 1) { parent.children.splice(parent.childIndex(node), 1); parent.children.splice(parent.childIndex(next), 0, node); }; }; for (i = 0; i < arrData.length; i++){ loadNode(arrData[i], this.setting); } }; Tree.prototype.refreshNodesDom = function (nodes, recurse){ var that = this; nodes.forEach(function (node) { if (node.row) { $('td', node.row).remove(); _view._makeTableRowCells(node.row, node); } else if (node !== that._root) { _view._makeRowDom(that.treeBodyObj, node); } if (recurse) { that.refreshNodesDom(node.children, recurse); } }) }; Tree.prototype.refreshTreeDom = function () { this.refreshNodesDom(this._root.children, true); }; Tree.prototype.addNodeData = function (data, parent, nextSibling) { var node = null; var pNode = parent ? parent : this._root; if (!nextSibling || (nextSibling.parent === pNode && pNode.childIndex(nextSibling) > -1)) { node = new Node(this, data); this.maxNodeId(data[this.setting.tree.id]); node.row = _view._makeRowDom(this.treeBodyObj, node); this.move(node, pNode, nextSibling); } return node; } Tree.prototype.move = function(node, parent, nextSibling) { var iIndex = -1, pre; if (parent && (!nextSibling || (nextSibling.parent === parent && parent.childIndex(nextSibling) > -1))) { if (node) { if (node.parent) { iIndex = node.parent.childIndex(node); if (iIndex > 0) { node.parent.children[iIndex - 1].setNextSibling(node.nextSibling); } node.parent.children.splice(iIndex, 1); this.refreshNodesDom([node.parent], false); } if (nextSibling) { iIndex = parent.childIndex(nextSibling); if (iIndex > 0){ pre = parent.children[iIndex - 1]; pre.setNextSibling(node); parent.children.splice(iIndex - 1, 0, node); } else { parent.children.splice(0, 0, node); } } else { if (parent.children.length > 0){ pre = parent.lastChild(); pre.setNextSibling(node); } parent.children.push(node); } node.setParent(parent); node.setNextSibling(nextSibling); if (node.row) { if (pre) { _view._moveRowDom(node, pre.deepestRow()); } else if (parent.id() !== this.setting.tree.nullId) { _view._moveRowDom(node, parent.row); } else if (nextSibling) { _view._moveRowDomBefore(node, nextSibling.row); } } if (node.parent.row) { this.refreshNodesDom([node.parent], false); } } } else { this.e.throw('Error: information of moving node has mistake.'); } }; Tree.prototype.selected = (function () { var selectNode = null; var select = function (node) { if (arguments.length === 0) { return selectNode; } else { if (node) { if (selectNode && selectNode.row) { selectNode.row.removeClass('table-active'); } selectNode = node; node.row.addClass('table-active'); } } } return select; })(); return Tree; })(); _data = { clone: function (obj) { if (obj === null) return null; var o = _data.isArray(obj) ? [] : {}; for (var i in obj) { o[i] = (obj[i] instanceof Date) ? new Date(obj[i].getTime()) : (typeof obj[i] === "object" ? _data.clone(obj[i]) : obj[i]); } return o; }, isArray: function (arr) { return Object.prototype.toString.apply(arr) === "[object Array]"; } }, _event = { _selectProj: function (node) { if (node.setting.viewEvent.beforeSelect) { node.setting.viewEvent.beforeSelect(node.tree.selected()); } node.tree.selected(node); if (node.setting.viewEvent.onSelectNode) { node.setting.viewEvent.onSelectNode(node); } } } _view = { _makeTableHeadCell: function (obj, col){ var th; th = $(''); th.attr('width', col.width); th.text(col.head); obj.append(th); }, _makeTableHead: function (obj, setting){ var thead, tr, i; thead = $(''); tr = $(''); for (i = 0; i < setting.columns.length; i++){ _view._makeTableHeadCell(tr, setting.columns[i]); } thead.append(tr); obj.append(thead); return thead; }, _makeTableBody: function (obj){ var tbody; tbody = $(''); obj.append(tbody); return tbody; }, _makeTableRowCell: function (obj, node, columns, index) { var html = [], td, i, url; html.push(''); if (node.children.length !== 0) { html.push(''); } else { html.push(''); } } else { html.push('>'); } if (columns.event.getIcon) { columns.event.getIcon(html, node); } if (columns.name !== '') { if (columns.event.getText) { columns.event.getText(html, node, node.data[columns.data]); } else { html.push(node.data[columns.name]); } } html.push(''); td = $(html.join('')); if (index === node.setting.tree.btnColumn) { node.expandBtn = $('.tree-open>.fa', td); node.expandBtn.bind('click', {node: node}, function(e){ e.data.node.expand(!e.data.node.expanded); }); node.icon = $('.tree-icon', td); } if (columns.event.tdBindEvent) { columns.event.tdBindEvent(td, node); } obj.append(td); return td; }, _makeTableRowCells: function (obj, node) { for (i = 0; i < node.setting.columns.length; i++){ _view._makeTableRowCell(obj, node, node.setting.columns[i], i); } }, _makeRowDom: function (obj, node) { var tr, i; tr = $(''); obj.append(tr); tr.attr('id', node.domId()); node.row = tr; _view._makeTableRowCells(tr, node); tr.click(function(){ _event._selectProj(node); }); /*$(tr).draggable({ helper: "clone", opacity: .75, refreshPositions: true, // Performance? revert: "invalid", revertDuration: 300, scroll: true }); tr.droppable({ drop: function (e, ui) { var target = node.tree.findNodeByDomId($(this).attr('id')), drag = node.tree.findNodeByDomId($(ui).attr('id')); tree.move(drag, target); } }); */ return tr; }, _moveRowDomBefore: function (node, destination) { var moveNodesRowDomBefore = function (nodes) { nodes.forEach(function (node) { node.row.insertBefore(destination); moveNodesRowDomBefore(node.children); }); } moveNodesRowDomBefore([node]); _view._refreshNodesLevelCss([node]); }, _moveRowDom: function (node, destination) { var pre = destination, moveNodeRowDom = function (node) { node.row.insertAfter(pre); pre = node.row; moveChildrenRowDom(node); }, moveChildrenRowDom = function(node){ var i; for (i = 0; i < node.children.length; i++){ moveNodeRowDom(node.children[i]); } }; moveNodeRowDom(node); _view._refreshNodesLevelCss([node]); }, _refreshTreeBtn: function (node) { var i; if (node.children.length === 0) { node.expandBtn.hide(); } else { node.expandBtn.show(); if (node.expanded) { node.expandBtn.removeClass('fa-plus-square-o'); node.expandBtn.addClass('fa-minus-square-o'); } else { node.expandBtn.removeClass('fa-minus-square-o'); node.expandBtn.addClass('fa-plus-square-o'); } } }, _refreshNodesLevelCss: function (nodes) { nodes.forEach(function(node){ var td = $('td:eq(' + node.setting.tree.btnColumn.toString() + ')', node.row); td.attr('class', 'in-'+ node.depth().toString()); _view._refreshNodesLevelCss(node.children); }) }, _hideNodes: function (nodes) { var i, node; for (i = 0; i < nodes.length; i++){ node = nodes[i]; node.row.hide(); _view._hideNodes(node.children); } }, _showNodes: function (nodes) { var i, node; for (i = 0; i < nodes.length; i++){ node = nodes[i]; node.row.show(); if (node.expanded) { _view._showNodes(node.children); } } }, _removeNodesRowDom: function (nodes) { var i, node; for (i = 0; i < nodes.length; i++){ node = nodes[i]; _view._removeNodesRowDom(node.children); if (node.row) { node.row.remove(); } } } }; $.fn.treeTable = { init: function(obj, setting, arrData){ var _treeSetting, _tree; _treeSetting = _data.clone(_setting); $.extend(true, _treeSetting, setting); var _tree = new Tree(obj, _treeSetting); _tree.loadData(arrData); _tree.refreshTreeDom(); return _tree; } } })(jQuery);