/*
* http://github.com/adamjimenez/jstree-table
*
* This plugin handles adding columns to a tree to display additional data
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
* Works only with jstree version >= 3.0.0
*
* $Revision: 3.4.2 $
*/
/*jslint nomen:true */
/*jshint unused:vars */
/*global navigator, document, jQuery, define, localStorage */
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery', 'jstree'], factory);
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
var renderATitle, getIndent, copyData, htmlstripre, findLastClosedNode, BLANKRE = /^\s*$/g,
IDREGEX = /[\\:&!^|()\[\]<>@*'+~#";,= \/${}%]/g, escapeId = function (id) {
return (id||"").replace(IDREGEX,'\\$&');
}, NODE_DATA_ATTR = "data-jstreetable", COL_DATA_ATTR = "data-jstreetable-column",
SPECIAL_TITLE = "_DATA_", LEVELINDENT = 24, styled = false, TABLECELLID_PREFIX = "jstable_",TABLECELLID_POSTFIX = "_col",
MINCOLWIDTH = 10,
findDataCell = function (from,id) {
return from.find("div["+NODE_DATA_ATTR+'="'+ escapeId(id) +'"]');
},
isClickedSep = false, toResize = null, oldMouseX = 0, newMouseX = 0;
/*jslint regexp:true */
htmlstripre = /<\/?[^>]+>/gi;
/*jslint regexp:false */
getIndent = function(node,tree) {
var div, i, li, width;
// did we already save it for this tree?
tree._tableSettings = tree._tableSettings || {};
if (tree._tableSettings.indent > 0) {
width = tree._tableSettings.indent;
} else {
// create a new div on the DOM but not visible on the page
div = $("
");
i = node.prev("i");
li = i.parent();
// add to that div all of the classes on the tree root
div.addClass(tree.get_node("#",true).attr("class"));
// move the li to the temporary div root
li.appendTo(div);
// attach to the body quickly
div.appendTo($("body"));
// get the width
width = i.width() || LEVELINDENT;
// detach the li from the new div and destroy the new div
li.detach();
div.remove();
// save it for the future
tree._tableSettings.indent = width;
}
return(width);
};
copyData = function (fromtree,from,totree,to,recurse) {
var i, j;
to.data = $.extend(true, {}, from.data);
if (from && from.children_d && recurse) {
for(i = 0, j = from.children_d.length; i < j; i++) {
copyData(fromtree,fromtree.get_node(from.children_d[i]),totree,totree.get_node(to.children_d[i]),recurse);
}
}
};
findLastClosedNode = function (tree,id) {
// first get our node
var ret, node = tree.get_node(id), children = node.children;
// is it closed?
if (!children || children.length <= 0 || !node.state.opened) {
ret = id;
} else {
ret = findLastClosedNode(tree,children[children.length-1]);
}
return(ret);
};
renderAWidth = function(node,tree) {
var depth, width,
fullWidth = parseInt(tree.settings.table.columns[0].width,10) + parseInt(tree._tableSettings.treeWidthDiff,10);
// need to use a selector in jquery 1.4.4+
depth = tree.get_node(node).parents.length;
width = fullWidth - depth*getIndent(node,tree);
// the following line is no longer needed, since we are doing this inside a
//a.css({"vertical-align": "top", "overflow":"hidden"});
return(fullWidth);
};
renderATitle = function(node,t,tree) {
var a = node.get(0).tagName.toLowerCase() === "a" ? node : node.children("a"), title, col = tree.settings.table.columns[0];
// get the title
title = "";
if (col.title) {
if (col.title === SPECIAL_TITLE) {
title = tree.get_text(t);
} else if (t.attr(col.title)) {
title = t.attr(col.title);
}
}
// strip out HTML
title = title.replace(htmlstripre, '');
if (title) {
a.attr("title",title);
}
};
$.jstree.defaults.table = {
width: 'auto'
};
$.jstree.plugins.table = function(options,parent) {
var _this = this;
this._initialize = function () {
if (!this._initialized) {
var s = this.settings.table || {}, styles, container = this.element, i,
gs = this._tableSettings = {
columns : s.columns || [],
treeClass : "jstree-table-col-0",
context: s.contextmenu || false,
columnWidth : s.columnWidth,
defaultConf : {"*display":"inline","*+display":"inline"},
isThemeroller : !!this._data.themeroller,
treeWidthDiff : 0,
resizable : s.resizable,
draggable : s.draggable,
stateful: s.stateful,
indent: 0,
sortFn: [],
sortOrder: 'text',
sortAsc: true,
fixedHeader: s.fixedHeader !== false,
headerContextMenu: s.headerContextMenu !== false,
checkIcon: 'fa fa-check',
arrowDownIcon: 'fa fa-chevron-down',
arrowUpIcon: 'fa fa-chevron-up',
width: s.width,
height: s.height
}, cols = gs.columns, treecol = 0;
// find which column our tree shuld go in
for (i=0;i'+styles.join("\n")+'').appendTo("head");
}
this.tableWrapper = $("").addClass("jstree-table-wrapper").insertAfter(container);
this.headerWrapper = $("").addClass("jstree-table-headerwrapper").appendTo(this.tableWrapper);
this.midWrapper = $("").addClass("jstree-table-midwrapper").appendTo(this.tableWrapper);
// set the wrapper width
if (s.width) {
this.tableWrapper.width(s.width);
}
if (s.height) {
this.tableWrapper.height(s.height);
}
// create the data columns
for (i=0;i").addClass("jstree-default jstree-table-column jstree-table-column-"+i+" jstree-table-column-root-"+this.rootid).appendTo(this.midWrapper);
}
this.midWrapper.children("div:eq("+treecol+")").append(container);
container.addClass("jstree-table-cell");
//move header with scroll
/*
if (gs.fixedHeader) {
this.tableWrapper.scroll(function() {
$(this).find('.jstree-table-header').css('top', $(this).scrollTop());
});
}
*/
// copy original sort function
var defaultSort = $.proxy(this.settings.sort, this);
// override sort function
this.settings.sort = function (a, b) {
var bigger;
if (gs.sortOrder==='text') {
bigger = defaultSort(a, b);
} else {
var nodeA = this.get_node(a);
var nodeB = this.get_node(b);
var valueA = nodeA.data[gs.sortOrder];
var valueB = nodeB.data[gs.sortOrder];
if(valueA && valueB){
if(gs.sortFn[gs.sortOrder]){
bigger = gs.sortFn[gs.sortOrder](valueA, valueB, nodeA, nodeB);
}else{
// Default sorting
bigger = (valueA > valueB ? 1 : -1);
}
}else{
// undefined is second
if(valueA){
bigger = 1;
}else if(valueB){
bigger = -1;
}else{
// Compare two nodes without values
bigger = defaultSort(a, b);
}
}
}
if (gs.sortAsc===false){
bigger = -bigger;
}
return bigger;
};
// sortable columns when jQuery UI is available
if (gs.draggable) {
if (!$.ui || !$.ui.sortable) {
console.warn('[jstree-table] draggable option requires jQuery UI');
} else {
var from, to;
this.headerWrapper.sortable({
axis: "x",
//handle: ".jstree-table-header-cell",
cancel: ".jstree-table-separator",
start: function (event, ui) {
ui.item.parent().children().css('display', 'inline-block');
from = ui.item.index();
},
stop: function (event, ui) {
ui.item.parent().children().css('display', 'table-cell');
to = ui.item.index();
if (to===from) return;
gs.columns.splice(to, 0, gs.columns.splice(from, 1)[0]);
var col = $('.jstree-table-midwrapper>div').eq(from);
if (to>from) {
col.insertAfter(col.parent().children("div").eq(to));
} else if (to |