;(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 = $('
', { '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 = $('
', { '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 = $('
', { 'class': nodeFloorClass }); $floorNode.append($nodeDiv); if (hasChildren) { that.buildLine($floorNode,hasChildren); var $floorChildBox = $('
', { 'class': floorClass }); childrenData.forEach(function(v) { allChildrenCount++; that.buildHierarchy($floorChildBox, v); }); $floorNode.append($floorChildBox); } $appendTo.append($floorNode); }, buildLine: function ($appendTo,childrenCount) { var $lineBox = $('
', { 'class': lineBoxClass }); var $lineGroupUp = $('
', { 'class': lineGroupClass }); if (childrenCount === 1) { $lineGroupUp.append('
'); $lineBox.append($lineGroupUp); } else { $lineGroupUp.append('
'); var $lineGroupMid = $('
', { 'class': lineGroupClass }); var hiddenWidth = 50.00 / childrenCount; $lineGroupMid.append( '
'); var $lineGroupDown = $('
', { 'class': lineGroupClass }); var width = 100.00 / childrenCount; $lineGroupDown.append('
'); for (var j = 0; j < childrenCount - 2; j++) { $lineGroupDown.append('
'); } $lineGroupDown.append('
'); $lineBox.append($lineGroupUp).append($lineGroupMid).append($lineGroupDown); } $appendTo.append($lineBox); }, createNode: function (data) { var that = this; var opts = that.options; var $nodeDiv = $('').addClass(nodeClass + ' ' + (data.className || '')); if (opts.nodeTemplate) { $nodeDiv.append(opts.nodeTemplate(data)); } else { $nodeDiv.append('
' + data[opts.nodeTitle] + '
') .append(typeof opts.nodeContent !== 'undefined' ? '
' + (data[opts.nodeContent] || '') + '
' : ''); } $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(); }; }));