123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- ;(function (factory) {
- if (typeof window.module === 'object' && typeof window.module.exports === 'object') {
- factory(window.require('jquery'), window, document);
- } else {
- factory(jQuery, window, document);
- }
- }(function ($, window, document, undefined) {
- var treeClass = 'iwb-flow-tree',
- floorClass = 'floor-box',
- nodeFloorClass = 'floor-node',
- nodeClass = 'node-box',
- lineBoxClass = 'line-box',
- lineGroupClass = 'line-group',
- lineClass = 'line',
- lineSingleClass = 'line-single',
- lineUpClass = 'line-u',
- lineMidClass = 'line-m',
- lineDownClass = 'line-d',
- lineDownLeftClass = 'line-d-l',
- lineDownRightClass = 'line-d-r';
- var allChildrenCount = 0;
- var FlowTree = function (elem, opts) {
- this.$nodeContainer = $(elem);
- this.opts = opts;
- this.defaultOptions = {
- 'data': {},
- 'nodeTitle': 'name',
- 'nodeMinWith': 250,
- 'nodeId': 'id',
- 'parentId': 'parentId',
- 'path': 'path',
- 'parentPath': 'parentPath',
- 'nodeClass': '',
- 'visibleLevel': 999,
- 'exportButton': false,
- 'exportFilename': 'FlowTree',
- 'exportFileExtension': 'png',
- 'draggable': true,
- 'dragDelay':200,
- 'zoom': true,
- 'zoomMaxLimit': 2,
- 'zoomMinLimit': 0.5,
- 'exportDataInput': false,
- 'customMenu': 'flow-menu',
- 'customMenuBefore':null,
- 'offset': undefined
- };
- };
- FlowTree.prototype = {
- init: function(opts) {
- var that = this;
- allChildrenCount = 0;
- this.options = $.extend({}, this.defaultOptions, this.opts, opts || {});
- //
- var $nodeContainer = this.$nodeContainer;
- that.$nodeTree = $nodeContainer.find('.' + treeClass);
- if (this.$nodeTree && this.$nodeTree.length>0) {
- if (this.options.offset) {
- this.options.offset = this.$nodeTree.offset();
- }
- this.$nodeTree.remove();
- } else {
- this.options.offset = false;
- }
- var data = this.options.data;
- var $nodeTree = this.$nodeTree = $('<div>',
- {
- 'data': { 'options': this.options },
- 'class': treeClass + (this.options.nodeClass !== '' ? ' ' + this.options.nodeClass : '')
- });
- this.buildHierarchy($nodeTree, data);
- $nodeContainer.append($nodeTree);
- var width = allChildrenCount * this.options.nodeMinWith;
- if (width < this.options.nodeMinWith) {
- width = this.options.nodeMinWith;
- }
- $nodeTree.css('width', width + 'px');
- if (this.options.offset) {
- $nodeTree.offset(this.options.offset);
- }
- if (this.options.draggable) {
- this.drag(this.$nodeTree);
- }
- if (this.options.zoom) {
- this.$nodeContainer.on('wheel', { 'nt': that }, this.zoomWheel);
- }
- return this;
- },
- buildHierarchy: function($appendTo, data) {
- var that = this;
- var $floorBox = $('<div>', { 'class': floorClass });
- if (!data) {
- $floorBox.append('暂无数据!');
- return;
- }
- that.buildChildNode($floorBox, data);
- $appendTo.append($floorBox);
- },
- buildChildNode: function ($appendTo, data) {
- var that = this;
- //var opts = this.options;
- var childrenData = data.children;
- var hasChildren = childrenData ? childrenData.length : false;
- var $nodeDiv = that.createNode(data);
- var $floorNode = $('<div>', { 'class': nodeFloorClass });
- $floorNode.append($nodeDiv);
- if (hasChildren) {
- that.buildLine($floorNode,hasChildren);
- var $floorChildBox = $('<div>', { 'class': floorClass });
- childrenData.forEach(function(v) {
- allChildrenCount++;
- that.buildHierarchy($floorChildBox, v);
- });
- $floorNode.append($floorChildBox);
- }
- $appendTo.append($floorNode);
- },
- buildLine: function ($appendTo,childrenCount) {
- var $lineBox = $('<div>', { 'class': lineBoxClass });
- var $lineGroupUp = $('<div>', { 'class': lineGroupClass });
- if (childrenCount === 1) {
- $lineGroupUp.append('<div class="' +
- lineSingleClass +
- ' ' + lineClass + '" style="width:100%"><div class="' +
- lineDownClass +
- '"></div></div>');
- $lineBox.append($lineGroupUp);
- }
- else {
- $lineGroupUp.append('<div class="' +
- lineClass +
- '" style="width: 100%"><div class="' +
- lineUpClass +
- '"></div></div>');
- var $lineGroupMid = $('<div>', { 'class': lineGroupClass });
- var hiddenWidth = 50.00 / childrenCount;
- $lineGroupMid.append(
- '<div class="' +
- lineMidClass +
- '" style="width:' +
- hiddenWidth +
- '%;visibility: hidden; "></div><div class= "' +
- lineMidClass +
- '" style = "width: ' +
- (100 - hiddenWidth * 2) +
- '%;" ></div><div class="' +
- lineMidClass +
- '" style="width: ' +
- hiddenWidth +
- '%;visibility: hidden;"></div>');
- var $lineGroupDown = $('<div>', { 'class': lineGroupClass });
- var width = 100.00 / childrenCount;
- $lineGroupDown.append('<div class="' +
- lineClass +
- '" style="width: ' +
- width +
- '%"><div class="' +
- lineDownClass +
- ' ' +
- lineDownLeftClass +
- '"></div></div>');
- for (var j = 0; j < childrenCount - 2; j++) {
- $lineGroupDown.append('<div class="' +
- lineClass +
- '" style="width: ' +
- width +
- '%"><div class="' +
- lineDownClass +
- '"></div></div>');
- }
- $lineGroupDown.append('<div class="' +
- lineClass +
- '" style="width: ' +
- width +
- '%"><div class="' +
- lineDownClass +
- ' ' +
- lineDownRightClass +
- '"></div></div>');
- $lineBox.append($lineGroupUp).append($lineGroupMid).append($lineGroupDown);
- }
- $appendTo.append($lineBox);
- },
- createNode: function (data) {
- var that = this;
- var opts = that.options;
- var $nodeDiv =
- $('<div' +
- (data[opts.nodeId] ? ' id="' + data[opts.nodeId] + '"' : '') +
- (data[opts.parentId] ? ' data-parent="' + data[opts.parentId] + '"' : '') +
- '>').addClass(nodeClass + ' ' + (data.className || ''));
- if (opts.nodeTemplate) {
- $nodeDiv.append(opts.nodeTemplate(data));
- } else {
- $nodeDiv.append('<div class="title">' + data[opts.nodeTitle] + '</div>')
- .append(typeof opts.nodeContent !== 'undefined'
- ? '<div class="content">' + (data[opts.nodeContent] || '') + '</div>'
- : '');
- }
- $nodeDiv.find('[data-toggle="tip"]').tooltip({ 'placement': 'right', 'container': 'body', 'delay': 500 });
- //
- var nodeData = $.extend({}, data);
- delete nodeData.children;
- $nodeDiv.data('nodeData', nodeData);
- $nodeDiv.data('node-id', data[opts.nodeId]);
- $nodeDiv.data('path', data[opts.path]);
- $nodeDiv.data('parent-path', data[opts.parentPath]);
- $nodeDiv.find('.title').data('path', data[opts.path]);
- $nodeDiv.find('.title').data('parent-path', data[opts.parentPath]);
- $nodeDiv.find('.title-text').data('path', data[opts.path]);
- $nodeDiv.find('.title-text').data('parent-path', data[opts.parentPath]);
- // allow user to append dom modification after finishing node create of node tree
- if (opts.createNode) {
- opts.createNode($nodeDiv, data);
- }
-
- if (opts.customMenu) {
- this.customMenu($nodeDiv.find('.title'));
- this.customMenu($nodeDiv.find('.title-text'));
- }
- return $nodeDiv;
- },
- customMenu: function ($node) {
- var that = this;
- var opts = that.options;
- var $menu = typeof opts.customMenu === 'string' ? $('#' + opts.customMenu) : $(opts.customMenu);;
- $node.css('cursor', 'help');
- $node.contextmenu(function (e) {
- if (opts.customMenuBefore && $.type(opts.customMenuBefore) === 'function') {
- opts.customMenuBefore($node);
- }
- e = e || window.event;
- //鼠标点的坐标
- var oX = e.clientX;
- var oY = e.clientY;
- //菜单出现后的位置
- $menu.fadeIn();
- $menu.offset({ top: oY, left: oX });
- //阻止浏览器默认事件
- return false; //一般点击右键会出现浏览器默认的右键菜单,写了这句代码就可以阻止该默认事件。)
- });
- $(document).on('click', function () {
- //e = e || window.event;
- $menu.hide();
- });
- $node.on('click', function (e) {
- e = e || window.event;
- e.cancelBubble = true;
- });
- },
- zoomWheel: function(e) {
- var nt = e.data.nt;
- e.preventDefault();
- var newScale = 1 + (e.originalEvent.deltaY > 0 ? -0.05 : 0.05);
- nt.setChartScale(nt.$nodeTree, newScale);
- },
- setChartScale: function ($nodeTree, newScale) {
- var that = this;
- var opts = that.options;
- var lastTf = $nodeTree.css('transform');
- var matrix = '';
- var targetScale = 1;
- if (lastTf === 'none') {
- $nodeTree.css('transform', 'scale(' + newScale + ',' + newScale + ')');
- } else {
- matrix = lastTf.split(',');
- if (lastTf.indexOf('3d') === -1) {
- targetScale = Math.abs(window.parseFloat(matrix[3]) * newScale);
- if (targetScale > opts.zoomMinLimit && targetScale < opts.zoomMaxLimit) {
- $nodeTree.css('transform', lastTf + ' scale(' + newScale + ',' + newScale + ')');
- }
- } else {
- targetScale = Math.abs(window.parseFloat(matrix[1]) * newScale);
- if (targetScale > opts.zoomMinLimit && targetScale < opts.zoomMaxLimit) {
- $nodeTree.css('transform', lastTf + ' scale3d(' + newScale + ',' + newScale + ', 1)');
- }
- }
- }
- },
- drag: function($node) {
- var that = this;
- var opts = that.options;
- var x = 0;
- var y = 0;
- var l = 0;
- var t = 0;
- var cursor ='pointer';
- var timeout = undefined;
- $node.data('drag', false);
- //点击(松开后触发)
- $node.mousedown(function (e) {
- if (e.which === 3) {//禁止右键拖动
- return;
- }
- var $this = $(this);
- timeout = setTimeout(function () {
- //获取x坐标和y坐标
- x = e.clientX;
- y = e.clientY;
- //获取左部和顶部的偏移量
- l = that.$nodeTree.offset().left;
- t = that.$nodeTree.offset().top;
- //开关打开
- $node.data('drag', true);
- that.$nodeTree.fadeTo(20, 0.5);
- //设置样式
- cursor = $this.css('cursor');
- $this.css('cursor', 'move');
- }, opts.dragDelay);
- });
- that.$nodeContainer.mousemove(function(e) {
- e.preventDefault();
- if ($node.data('drag') !== true) {
- return;
- }
- //获取x和y
- var nx = e.clientX;
- var ny = e.clientY;
- //计算移动后的左偏移量和顶部的偏移量
- var nl = nx - (x - l);
- var nt = ny - (y - t);
- that.$nodeTree.offset({ top: nt, left: nl });
- });
- $node.mouseup(function() {
- //开关打开
- $node.data('drag', false);
- that.$nodeTree.fadeTo("fast", 1);
- //设置样式
- $(this).css('cursor', cursor);
- clearTimeout(timeout);
- });
- },
-
- exportData: function (input) {
- var that = this;
- var $nodeContainer = this.$nodeContainer;
- input = input || this.options.exportDataInput;
- if ($(this).children('.spinner').length) {
- return false;
- }
- var img;
- var sourceChart = $nodeContainer.addClass('canvasContainer').find('.'+treeClass+':not(".hidden")').get(0);
- var flag = that.options.direction === 'l2r' || that.options.direction === 'r2l';
- window.html2canvas(sourceChart, {
- 'width': flag ? sourceChart.clientHeight : sourceChart.clientWidth,
- 'height': flag ? sourceChart.clientWidth : sourceChart.clientHeight,
- 'onclone': function (cloneDoc) {
- $(cloneDoc).find('.canvasContainer').css('overflow', 'visible')
- .find('.' + treeClass +':not(".hidden"):first').css('transform', '');
- },
- 'onrendered': function (canvas) {
- img = canvas.toDataURL("image/png");
- console.log("exportData-over");
- input.val(img);
- }
- })
- .then(function () {
- $nodeContainer.removeClass('canvasContainer');
- });
- return img;
- }
- };
- $.fn.flowTree = function (opts) {
- return new FlowTree(this, opts).init();
- };
- }));
|