提交 07068d8c 编写于 作者: C Catouse

* treemap support collapse by click and listen resize event and redraw lines.

上级 5f344c32
......@@ -36,12 +36,14 @@
position: 'center',
rowSpace: 30,
nodeSpace: 20,
listenNodeResize: true,
nodeTemplate: '<div class="treemap-node"><a class="treemap-node-wrapper"></a></div>',
foldable: true,
// sort: false, // Boolean or function
// tooltip: null,
// nodeStyle: null,
},
DEFAULT_NODE = {
};
// var DEFAULT_NODE = {
// id: uuid(), // uuid
// text: '', // main text,
// html: '', // main text as html format
......@@ -55,7 +57,7 @@
// attrs: null // attrs
// title: '' // node title
// tooltip: '' // node tooltip
};
// };
var getDataFromUlList = function($list) {
return $list.children('li,.treemap-data-item').map(function() {
......@@ -111,157 +113,201 @@
// Bind events
that.render();
that.$nodes.on('resize', '.treemap-node-wrapper', function() {
that.delayDrawLines();
}).on('click', '.treemap-node-fold-icon', function() {
$(this).closest('.treemap-node').toggleClass('collapsed');
that.drawLines();
});
};
Treemap.prototype.render = function(data) {
var that = this;
that.createNodes();
that.drawLines();
that.callEvent('afterRender');
};
Treemap.prototype.createNodes = function(nodes, parent, callback) {
var that = this,
options = that.options,
$nodes = that.$nodes,
rowSpace = options.rowSpace;
data = data || that.data;
rowSpace = options.rowSpace,
$nodes = that.$nodes;
if(!parent) {
$nodes.find('.treemap-node-wrapper').off('resize.' + NAME);
$nodes.empty();
}
if(options.sort) {
nodes.sort($.isFunction(options.sort) ? options.sort : function(nodeX, nodeY) {
return (nodeX.order || 0) - (nodeY.order);
});
}
var lastNode = null;
$.each(nodes || that.data, function(idx, node) {
// Create node element
var $node = $.isFunction(options.nodeTemplate) ? options.nodeTemplate(node, that) : $(options.nodeTemplate);
// Create node wrapper element
var $wrapper = $node.find('.treemap-node-wrapper');
if(!$wrapper.length) {
$wrapper = $('<div class="treemap-node-wrapper"/>').appendTo($node);
}
var cableStyle = {};
if(options.cableWidth) cableStyle.borderWidth = options.cableWidth;
if(options.cableStyle) cableStyle.borderStyle = options.cableStyle;
if(options.cableColor) cableStyle.borderColor = options.cableColor;
var rowSpaceHalf = Math.floor(rowSpace/2);
var children = node.children;
var hasChild = children && children.length;
node.isOnlyOneChild = hasChild === 1;
// Set node data attributes
node.idx = idx;
$node.toggleClass('treemap-node-has-child', !!hasChild)
.toggleClass('treemap-node-has-parent', !!parent)
.toggleClass('treemap-node-one-child', hasChild === 1)
.toggleClass('collapsed', !!node.collapsed)
.attr('data-id', node.id).data('node', node);
var row = parent ? (parent.row + 1) : 0;
node.row = row;
$node.toggleClass('treemap-node-root', !row);
// Set node element attributes and sytle
var style = $.extend({}, options.nodeStyle, node.style);
if(node.textColor) style.color = node.textColor;
if(node.color) style.backgroundColor = node.color;
if(node.border) style.border = node.border;
var attrs = $.extend({}, node.attrs, {
title: node.title
});
if(node.tooltip) {
attrs['data-toggle'] = 'tooltip';
attrs.title = node.tooltip;
}
$wrapper.attr(attrs).css(style);
if(lastNode) {
$node.css('padding-left', options.nodeSpace);
}
if(node.html) $wrapper.append(node.html);
else if(node.text) $wrapper.text(node.text);
var createNodes = function(nodes, parent, callback) {
if(options.sort) {
nodes.sort($.isFunction(options.sort) ? options.sort : function(nodeX, nodeY) {
return (nodeX.order || 0) - (nodeY.order);
});
// append node element to ducument
$node.appendTo(parent ? parent.$children : $nodes);
// Save sizes
node.bounds = {
width : $wrapper.outerWidth(),
height : $wrapper.outerHeight()
};
if(lastNode) {
lastNode.next = node;
}
var lastNode = null;
$.each(nodes, function(idx, node) {
// Create node element
var $node = $.isFunction(options.nodeTemplate) ? options.nodeTemplate(node, that) : $(options.nodeTemplate);
// Create node wrapper element
var $wrapper = $node.find('.treemap-node-wrapper');
if(!$wrapper.length) {
$wrapper = $('<div class="treemap-node-wrapper"/>').appendTo($node);
node.prev = lastNode;
node.parent = parent;
node.$ = $node;
node.$wrapper = $wrapper;
// Create children
if(hasChild) {
var $children = $node.find('.treemap-node-children');
if(!$children.length) {
$children = $('<div class="treemap-node-children"/>').appendTo($node);
}
$children.css('margin-top', rowSpace);
node.$children = $children;
that.createNodes(children, node);
}
// Set node data attributes
node.idx = idx;
$node.toggleClass('treemap-node-has-child', !!(node.children && node.children.length))
.toggleClass('treemap-node-has-parent', !!parent)
.attr('data-id', node.id).data('node', node);
var row = parent ? (parent.row + 1) : 0;
node.row = row;
$node.toggleClass('treemap-node-root', !row);
// Set node element attributes and sytle
var style = $.extend({}, node.style);
if(node.textColor) style.color = node.textColor;
if(node.color) style.backgroundColor = node.color;
if(node.border) style.border = node.border;
var attrs = $.extend({}, node.attrs, {
title: node.title
if(options.listenNodeResize) {
$wrapper.on('resize.' + NAME, function() {
node.bounds.width = $wrapper.outerWidth();
node.bounds.height = $wrapper.outerHeight();
that.delayDrawLines();
});
if(node.tooltip) {
attrs['data-toggle'] = 'tooltip';
attrs.title = node.tooltip;
}
$wrapper.attr(attrs).css(style);
if(lastNode) {
$node.css('padding-left', options.nodeSpace);
}
if(node.html) $wrapper.append(node.html);
else if(node.text) $wrapper.text(node.text);
}
// append node element to ducument
$node.appendTo(parent ? parent.$children : $nodes);
lastNode = node;
callback && callback($node, node);
});
// Save sizes
node.bounds = {
width : $wrapper.outerWidth(),
height : $wrapper.outerHeight()
};
if(!parent) {
// Init tooltip
$nodes.find('[data-toggle="tooltip"]').tooltip(options.tooltip);
}
};
if(lastNode) {
lastNode.next = node;
Treemap.prototype.delayDrawLines = function() {
var that = this;
clearTimeout(that.delayDrawLinesTask);
that.delayDrawLinesTask = setTimeout(function() {
that.drawLines();
}, 10);
};
Treemap.prototype.drawLines = function(nodes, parent) {
var that = this,
options = that.options,
rowSpace = options.rowSpace;
var cableStyle = {};
if(options.cableWidth) cableStyle.borderWidth = options.cableWidth;
if(options.cableStyle) cableStyle.borderStyle = options.cableStyle;
if(options.cableColor) cableStyle.borderColor = options.cableColor;
var rowSpaceHalf = Math.round(rowSpace/2);
var nodesOffsetLeft = that.$nodes.offset().left;
$.each(nodes || that.data, function(idx, node) {
var $wrapper = node.$wrapper;
var children = node.children;
var nodeCableStyle = $.extend({
height: rowSpaceHalf,
top: -rowSpaceHalf - 1,
left: Math.round(($wrapper.outerWidth() - cableStyle.borderWidth)/2)
}, cableStyle);
if(parent && !parent.isOnlyOneChild) {
var $topLine = $wrapper.find('.treemap-line-top');
if(!$topLine.length) {
$topLine = $('<div class="treemap-line-top"/>').appendTo($wrapper);
}
node.prev = lastNode;
node.parent = parent;
node.$ = $node;
node.$wrapper = $wrapper;
// Create children
var children = node.children;
if(children && children.length) {
var $children = $node.find('.treemap-node-children');
if(!$children.length) {
$children = $('<div class="treemap-node-children"/>').appendTo($node);
}
$children.css('margin-top', rowSpace);
node.$children = $children;
createNodes(children, node);
$topLine.css(nodeCableStyle);
}
if(children && children.length) {
nodeCableStyle.top = $wrapper.outerHeight() - 1;
if(node.isOnlyOneChild) {
nodeCableStyle.height = rowSpace;
}
lastNode = node;
callback && callback($node, node);
});
};
var createLines = function(nodes, parent) {
var nodesOffsetLeft = $nodes.offset().left;
$.each(nodes, function(idx, node) {
var $wrapper = node.$wrapper;
var nodeCableStyle = $.extend({
height: rowSpaceHalf,
top: -rowSpaceHalf-1,
left: Math.floor((node.bounds.width - cableStyle.borderWidth)/2)
}, cableStyle);
if(parent) {
var $topLine = $wrapper.find('.treemap-line-top');
if(!$topLine.length) {
$topLine = $('<div class="treemap-line-top"/>').appendTo($wrapper);
var $bottomLine = $wrapper.find('.treemap-line-bottom');
if(!$bottomLine.length) {
$bottomLine = $('<div class="treemap-line-bottom"/>').appendTo($wrapper);
if(options.foldable) {
$bottomLine.append('<i class="treemap-node-fold-icon icon icon-minus-sign" style="transform: translate(-' + Math.round(nodeCableStyle.borderWidth/2) + 'px, ' + rowSpaceHalf + 'px)"/>');
}
$topLine.css(nodeCableStyle);
}
var children = node.children;
if(children && children.length) {
nodeCableStyle.top = node.bounds.height - 1;
var $bottomLine = $wrapper.find('.treemap-line-bottom');
if(!$bottomLine.length) {
$bottomLine = $('<div class="treemap-line-bottom"/>').appendTo($wrapper);
}
$bottomLine.css(nodeCableStyle);
createLines(children, node);
if(children.length > 1) {
var firstChild = children[0],
lastChild = children[children.length - 1];
var $centerLine = node.$.children('.treemap-line');
if(!$centerLine.length) {
$centerLine = $('<div class="treemap-line"/>').insertAfter($wrapper);
}
var lineLeft = Math.floor(firstChild.$wrapper.offset().left - nodesOffsetLeft + firstChild.bounds.width/2);
$centerLine.css($.extend({
marginTop: rowSpaceHalf,
left: lineLeft,
width: lastChild.$wrapper.offset().left - nodesOffsetLeft -lineLeft + lastChild.bounds.width/2
}, cableStyle));
$bottomLine.css(nodeCableStyle);
that.drawLines(children, node);
if(children.length > 1) {
var firstChild = children[0],
lastChild = children[children.length - 1];
var $centerLine = node.$.children('.treemap-line');
if(!$centerLine.length) {
$centerLine = $('<div class="treemap-line"/>').insertAfter($wrapper);
}
var lineLeft = Math.round(firstChild.$wrapper.offset().left - nodesOffsetLeft + firstChild.bounds.width/2);
$centerLine.css($.extend({
marginTop: rowSpaceHalf,
left: lineLeft,
width: lastChild.$wrapper.offset().left - nodesOffsetLeft -lineLeft + lastChild.bounds.width/2
}, cableStyle));
}
});
};
// Create nodes
$nodes.empty();
createNodes(data);
createLines(data);
// Init tooltip
$nodes.find('[data-toggle="tooltip"]').tooltip(options.tooltip);
}
});
that.callEvent('afterRender');
if(!parent) {
that.callEvent('afterDrawLines');
}
};
// Call event helper
// Call event
Treemap.prototype.callEvent = function(name, params) {
var that = this;
if(!$.isArray(params)) params = [params];
......@@ -272,6 +318,7 @@
};
Treemap.DEFAULTS = DEFAULTS;
Treemap.NAME = NAME;
$.fn.treemap = function(option, params) {
return this.each(function() {
......
......@@ -9,7 +9,9 @@
text-align: center;
}
.treemap-data {display: none}
.treemap-data {
text-align: left;
}
.treemap-nodes {
-moz-user-select: none;
......@@ -29,6 +31,7 @@
padding: 5px 10px;
position: relative;
border-radius: 1px;
z-index: 5;
a& {
color: @color-fore;
......@@ -43,11 +46,15 @@
text-decoration: none;
}
}
.treemap-node-root > & {
background-color: rgba(0,0,0,.1);
}
}
.treemap-node-children {
display: table;
margin-top: 20px;
margin-top: 20px auto 0;
> .treemap-node {
display: table-cell;
......@@ -75,4 +82,39 @@
right: 0;
border-right: none!important;
border-bottom: none!important;
z-index: 1;
}
.treemap-node-fold-icon {
transition: opacity .2s;
opacity: 0;
background-color: @color-back;
border-radius: 7px;
display: block!important;
width: 14px;
height: 14px;
line-height: 14px;
position: absolute;
left: -6px;
top: -8px;
z-index: 10;
}
.treemap-node-wrapper:hover .treemap-node-fold-icon {
opacity: 1;
}
.treemap-node.collapsed {
> .treemap-line,
.treemap-line-bottom {border-color: transparent!important;}
> .treemap-node-children {display: none}
.treemap-node-fold-icon {
opacity: 1;
color: @color-gray;
transform: none!important;
top: -1px;
&:before {
content: @icon-plus-sign;
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册