karbor-dashboard/karbor_dashboard/static/karbordashboard/js/jquery.treetable.js

419 lines
10 KiB
JavaScript

/*
* jQuery treeTable Plugin
*/
(function() {
var $, Node, Tree, methods;
$ = jQuery;
Node = (function() {
function Node(row, tree, settings) {
var parentId;
this.row = row;
this.tree = tree;
this.settings = settings;
this.id = this.row.data(this.settings.nodeIdAttr);
parentId = this.row.data(this.settings.parentIdAttr);
if (parentId != null && parentId !== "") {
this.parentId = parentId;
}
this.treeCell = $(this.row.children(this.settings.columnElType)[this.settings.column]);
this.expander = $(this.settings.expanderTemplate);
this.indenter = $(this.settings.indenterTemplate);
this.children = [];
this.initialized = false;
this.treeCell.prepend(this.indenter);
}
Node.prototype.addChild = function(child) {
return this.children.push(child);
};
Node.prototype.ancestors = function() {
var ancestors, node;
node = this;
ancestors = [];
while (node = node.parentNode()) {
ancestors.push(node);
}
return ancestors;
};
Node.prototype.collapse = function() {
this._hideChildren();
this.row.removeClass("expanded").addClass("collapsed");
this.expander.attr("title", this.settings.stringExpand);
if (this.initialized && this.settings.onNodeCollapse != null) {
this.settings.onNodeCollapse.apply(this);
}
return this;
};
Node.prototype.expand = function() {
if (this.initialized && this.settings.onNodeExpand != null) {
this.settings.onNodeExpand.apply(this);
}
this.row.removeClass("collapsed").addClass("expanded");
this._showChildren();
this.expander.attr("title", this.settings.stringCollapse);
return this;
};
Node.prototype.expanded = function() {
return this.row.hasClass("expanded");
};
Node.prototype.hide = function() {
this._hideChildren();
this.row.hide();
return this;
};
Node.prototype.isBranchNode = function() {
if(this.children.length > 0 || this.row.data(this.settings.branchAttr) === true) {
return true;
} else {
return false;
}
};
Node.prototype.level = function() {
return this.ancestors().length;
};
Node.prototype.parentNode = function() {
if (this.parentId != null) {
return this.tree[this.parentId];
} else {
return null;
}
};
Node.prototype.removeChild = function(child) {
var i = $.inArray(child, this.children);
return this.children.splice(i, 1)
};
Node.prototype.render = function() {
var settings = this.settings, target;
if (settings.expandable === true && this.isBranchNode()) {
this.indenter.html(this.expander);
target = settings.clickableNodeNames === true ? this.treeCell : this.expander;
target.unbind("click.treetable").bind("click.treetable", function(event) {
$(this).parents("table").treetable("node", $(this).parents("tr").data(settings.nodeIdAttr)).toggle();
return event.preventDefault();
});
}
if (settings.expandable === true && settings.initialState === "collapsed") {
this.collapse();
} else {
this.expand();
}
this.indenter[0].style.marginLeft = "" + (this.level() * settings.indent) + "px";
return this;
};
Node.prototype.reveal = function() {
if (this.parentId != null) {
this.parentNode().reveal();
}
return this.expand();
};
Node.prototype.setParent = function(node) {
if (this.parentId != null) {
this.tree[this.parentId].removeChild(this);
}
this.parentId = node.id;
this.row.data(this.settings.parentIdAttr, node.id);
return node.addChild(this);
};
Node.prototype.show = function() {
if (!this.initialized) {
this._initialize();
}
this.row.show();
if (this.expanded()) {
this._showChildren();
}
return this;
};
Node.prototype.toggle = function() {
if (this.expanded()) {
this.collapse();
} else {
this.expand();
}
return this;
};
Node.prototype._hideChildren = function() {
var child, _i, _len, _ref, _results;
_ref = this.children;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
child = _ref[_i];
_results.push(child.hide());
}
return _results;
};
Node.prototype._initialize = function() {
this.render();
if (this.settings.onNodeInitialized != null) {
this.settings.onNodeInitialized.apply(this);
}
return this.initialized = true;
};
Node.prototype._showChildren = function() {
var child, _i, _len, _ref, _results;
_ref = this.children;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
child = _ref[_i];
_results.push(child.show());
}
return _results;
};
return Node;
})();
Tree = (function() {
function Tree(table, settings) {
this.table = table;
this.settings = settings;
this.tree = {};
// Cache the nodes and roots in simple arrays for quick access/iteration
this.nodes = [];
this.roots = [];
}
Tree.prototype.collapseAll = function() {
var node, _i, _len, _ref, _results;
_ref = this.nodes;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
node = _ref[_i];
_results.push(node.collapse());
}
return _results;
};
Tree.prototype.expandAll = function() {
var node, _i, _len, _ref, _results;
_ref = this.nodes;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
node = _ref[_i];
_results.push(node.expand());
}
return _results;
};
Tree.prototype.loadRows = function(rows) {
var node, row, i;
if (rows != null) {
for (i = 0; i < rows.length; i++) {
row = $(rows[i]);
if (row.data(this.settings.nodeIdAttr) != null) {
node = new Node(row, this.tree, this.settings);
this.nodes.push(node);
this.tree[node.id] = node;
if (node.parentId != null) {
this.tree[node.parentId].addChild(node);
} else {
this.roots.push(node);
}
}
}
}
return this;
};
Tree.prototype.render = function() {
var root, _i, _len, _ref;
_ref = this.roots;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
root = _ref[_i];
root.show();
}
return this;
};
Tree.prototype.unloadBranch = function(node) {
var child, children, i;
for (i = 0; i < node.children.length; i++) {
child = node.children[i];
// Recursively remove all descendants of +node+
this.unloadBranch(child);
// Remove child from DOM (<tr>)
child.row.remove();
// Clean up Tree object (so Node objects are GC-ed)
delete this.tree[child.id];
this.nodes.splice($.inArray(child, this.nodes), 1)
}
// Reset node's collection of children
node.children = [];
return this;
};
return Tree;
})();
// jQuery Plugin
methods = {
init: function(options) {
var settings;
settings = $.extend({
branchAttr: "ttBranch",
clickableNodeNames: false,
column: 0,
columnElType: "td", // i.e. 'td', 'th' or 'td,th'
expandable: false,
expanderTemplate: "<a href='#'>&nbsp;</a>",
indent: 19,
indenterTemplate: "<span class='indenter'></span>",
initialState: "collapsed",
nodeIdAttr: "ttId", // maps to data-tt-id
parentIdAttr: "ttParentId", // maps to data-tt-parent-id
stringExpand: "Expand",
stringCollapse: "Collapse",
// Events
onInitialized: null,
onNodeCollapse: null,
onNodeExpand: null,
onNodeInitialized: null
}, options);
return this.each(function() {
var el, tree;
tree = new Tree(this, settings);
tree.loadRows(this.rows).render();
el = $(this).addClass("treetable").data("treetable", tree);
if (settings.onInitialized != null) {
settings.onInitialized.apply(tree);
}
return el;
});
},
destroy: function() {
return this.each(function() {
return $(this).removeData("treetable").removeClass("treetable");
});
},
collapseAll: function() {
this.data("treetable").collapseAll();
return this;
},
collapseNode: function(id) {
var node = this.data("treetable").tree[id];
if (node) {
node.collapse();
} else {
throw new Error("Unknown node '" + id + "'");
}
return this;
},
expandAll: function() {
this.data("treetable").expandAll();
return this;
},
expandNode: function(id) {
var node = this.data("treetable").tree[id];
if (node) {
node.expand();
} else {
throw new Error("Unknown node '" + id + "'");
}
return this;
},
loadBranch: function(node, rows) {
rows = $(rows);
rows.insertAfter(node.row);
this.data("treetable").loadRows(rows);
return this;
},
node: function(id) {
return this.data("treetable").tree[id];
},
reveal: function(id) {
var node = this.data("treetable").tree[id];
if (node) {
node.reveal();
} else {
throw new Error("Unknown node '" + id + "'");
}
return this;
},
unloadBranch: function(node) {
this.data("treetable").unloadBranch(node);
return this;
}
};
$.fn.treetable = function(method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
return $.error("Method " + method + " does not exist on jQuery.treetable");
}
};
// Expose classes to world
this.TreeTable || (this.TreeTable = {});
this.TreeTable.Node = Node;
this.TreeTable.Tree = Tree;
}).call(this);