diff --git a/README.md b/README.md index 97a2536..288d9ce 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,8 @@ How about making the labels push each other and find where they can stay with ov [left](http://twitter.github.io/labella.js/basic_left.html) | [right](http://twitter.github.io/labella.js/basic_right.html) | [with text (v)](http://twitter.github.io/labella.js/with_text.html) | -[with text (h)](http://twitter.github.io/labella.js/with_text2.html) +[with text (h)](http://twitter.github.io/labella.js/with_text2.html) | +[with flex height](http://twitter.github.io/labella.js/with_flex_height.html) * Read the instructions on this page or API reference. Moreover, if you are looking for a ready-to-use timeline component with Labella's smart labeling instead of building your own timeline from scratch, check out [d3Kit-timeline](https://github.com/kristw/d3kit-timeline). diff --git a/dist/labella-extra.js b/dist/labella-extra.js index 7dc97fc..5870ae1 100644 --- a/dist/labella-extra.js +++ b/dist/labella-extra.js @@ -95,6 +95,7 @@ return /******/ (function(modules) { // webpackBootstrap // return negative if overlap + _createClass(Node, [{ key: 'distanceFrom', value: function distanceFrom(node) { @@ -546,6 +547,11 @@ return /******/ (function(modules) { // webpackBootstrap return array.map(accessor).reduce(function (prev, current) { return prev + current; }, 0); + }, + functor: function functor(v) { + return typeof v === "function" ? v : function () { + return v; + }; } }; @@ -1821,10 +1827,12 @@ return /******/ (function(modules) { // webpackBootstrap var helper = __webpack_require__(4); + var DEFAULT_NODE_HEIGHT = 10; + function Renderer(options) { this.options = helper.extend({ layerGap: 60, - nodeHeight: 10, + nodeHeight: DEFAULT_NODE_HEIGHT, direction: 'down' }, options); } @@ -1859,30 +1867,31 @@ return /******/ (function(modules) { // webpackBootstrap Renderer.prototype.getWaypoints = function (node) { var options = this.options; + var nodeHeight = helper.functor(options.nodeHeight)(node.data); var direction = options.direction; var hops = node.getPathFromRoot(); - var gap = options.nodeHeight + options.layerGap; + var gap = nodeHeight + options.layerGap; if (direction === 'left') { return [[[0, hops[0].idealPos]]].concat(hops.map(function (hop, level) { var xPos = gap * (level + 1) * -1; - return [[xPos + options.nodeHeight, hop.currentPos], [xPos, hop.currentPos]]; + return [[xPos + nodeHeight, hop.currentPos], [xPos, hop.currentPos]]; })); } else if (direction === 'right') { return [[[0, hops[0].idealPos]]].concat(hops.map(function (hop, level) { var xPos = gap * (level + 1); - return [[xPos - options.nodeHeight, hop.currentPos], [xPos, hop.currentPos]]; + return [[xPos - nodeHeight, hop.currentPos], [xPos, hop.currentPos]]; })); } else if (direction === 'up') { return [[[hops[0].idealPos, 0]]].concat(hops.map(function (hop, level) { var yPos = gap * (level + 1) * -1; - return [[hop.currentPos, yPos + options.nodeHeight], [hop.currentPos, yPos]]; + return [[hop.currentPos, yPos + nodeHeight], [hop.currentPos, yPos]]; })); } else { return [[[hops[0].idealPos, 0]]].concat(hops.map(function (hop, level) { var yPos = gap * (level + 1); - return [[hop.currentPos, yPos - options.nodeHeight], [hop.currentPos, yPos]]; + return [[hop.currentPos, yPos - nodeHeight], [hop.currentPos, yPos]]; })); } }; @@ -1890,44 +1899,76 @@ return /******/ (function(modules) { // webpackBootstrap Renderer.prototype.layout = function (nodes) { var options = this.options; + var nodeHeightFn = helper.functor(options.nodeHeight); + if (typeof options.nodeHeight === 'function') { + var gaps = []; + nodes.forEach(function (node, index) { + gaps[index] = options.layerGap + options.nodeHeight(node.data); + }); + } + var gap = options.layerGap + options.nodeHeight; switch (options.direction) { case 'left': - nodes.forEach(function (node) { - var pos = node.getLayerIndex() * gap + options.layerGap; - node.x = -pos - options.nodeHeight; + nodes.forEach(function (node, index) { + var pos = 0; + if (gaps) { + //if the nodeHeight is a function + pos = node.getLayerIndex() * gaps[index] + options.layerGap; + } else { + pos = node.getLayerIndex() * gap + options.layerGap; + } + node.x = -pos - nodeHeightFn(node.data); node.y = node.currentPos; - node.dx = options.nodeHeight; + node.dx = nodeHeightFn(node.data); node.dy = node.width; }); break; case 'right': - nodes.forEach(function (node) { - var pos = node.getLayerIndex() * gap + options.layerGap; + nodes.forEach(function (node, index) { + var pos = 0; + if (gaps) { + //if the nodeHeight is a function + pos = node.getLayerIndex() * gaps[index] + options.layerGap; + } else { + pos = node.getLayerIndex() * gap + options.layerGap; + } node.x = pos; node.y = node.currentPos; - node.dx = options.nodeHeight; + node.dx = nodeHeightFn(node.data); node.dy = node.width; }); break; case 'up': - nodes.forEach(function (node) { - var pos = node.getLayerIndex() * gap + options.layerGap; + nodes.forEach(function (node, index) { + var pos = 0; + if (gaps) { + //if the nodeHeight is a function + pos = node.getLayerIndex() * gaps[index] + options.layerGap; + } else { + pos = node.getLayerIndex() * gap + options.layerGap; + } node.x = node.currentPos; - node.y = -pos - options.nodeHeight; + node.y = -pos - nodeHeightFn(node.data); node.dx = node.width; - node.dy = options.nodeHeight; + node.dy = nodeHeightFn(node.data); }); break; default: case 'down': - nodes.forEach(function (node) { - var pos = node.getLayerIndex() * gap + options.layerGap; + nodes.forEach(function (node, index) { + var pos = 0; + if (gaps) { + //if the nodeHeight is a function + pos = node.getLayerIndex() * gaps[index] + options.layerGap; + } else { + pos = node.getLayerIndex() * gap + options.layerGap; + } node.x = node.currentPos; node.y = pos; node.dx = node.width; - node.dy = options.nodeHeight; + node.dy = nodeHeightFn(node.data); }); break; } diff --git a/dist/labella-extra.min.js b/dist/labella-extra.min.js index 6f9e784..7f6f6cd 100644 --- a/dist/labella-extra.min.js +++ b/dist/labella-extra.min.js @@ -1 +1 @@ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.labella=e():t.labella=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return t[r].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){"use strict";t.exports={Node:n(1),Force:n(2),Distributor:n(3),Renderer:n(10),metrics:n(11),util:n(12)}},function(t,e){"use strict";function n(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var r=function(){function t(t,e){for(var n=0;n=this.currentPos-e&&t<=this.currentPos+e}},{key:"positionBefore",value:function(t){var e=arguments.length<=1||void 0===arguments[1]?0:arguments[1];return t.currentLeft()-this.width/2-e}},{key:"positionAfter",value:function(t){var e=arguments.length<=1||void 0===arguments[1]?0:arguments[1];return t.currentRight()+this.width/2+e}},{key:"currentRight",value:function(){return this.currentPos+this.width/2}},{key:"currentLeft",value:function(){return this.currentPos-this.width/2}},{key:"idealRight",value:function(){return this.idealPos+this.width/2}},{key:"idealLeft",value:function(){return this.idealPos-this.width/2}},{key:"createStub",value:function(e){var n=new t(this.idealPos,e,this.data);return n.currentPos=this.currentPos,n.child=this,this.parent=n,n}},{key:"removeStub",value:function(){return this.parent&&(this.parent.child=null,this.parent=null),this}},{key:"isStub",value:function(){return!!this.child}},{key:"getPathToRoot",value:function(){for(var t=[],e=this;e;)t.push(e),e=e.parent;return t}},{key:"getPathFromRoot",value:function(){return this.getPathToRoot().reverse()}},{key:"getPathToRootLength",value:function(){for(var t=0,e=this;e;){var n=e.parent?e.parent.currentPos:e.idealPos;t+=Math.abs(e.currentPos-n),e=e.parent}return t}},{key:"getRoot",value:function(){for(var t=this,e=this;e;)t=e,e=e.parent;return t}},{key:"getLayerIndex",value:function(){return this.layerIndex}},{key:"clone",value:function(){var e=new t(this.idealPos,this.width,this.data);return e.currentPos=this.currentPos,e.layerIndex=this.layerIndex,e}}]),t}();t.exports=i},function(t,e,n){"use strict";var r=n(3),i=n(4),o=n(8),s={nodeSpacing:3,minPos:0,maxPos:null,algorithm:"overlap",removeOverlap:!0,density:.85,stubWidth:1},u=function(t){var e={},n=i.extend({},s),u=new r,a=[],c=null;return e.nodes=function(t){return arguments.length?(a=t,c=[t],e):a},e.getLayers=function(){return c},e.options=function(t){if(!arguments.length)return n;n=i.extend(n,t);var o=i.pick(n,Object.keys(r.DEFAULT_OPTIONS));return i.isDefined(n.minPos)&&i.isDefined(n.maxPos)?o.layerWidth=n.maxPos-n.minPos:o.layerWidth=null,u.options(o),e},e.options(t),e.compute=function(){var t=i.pick(n,Object.keys(o.DEFAULT_OPTIONS));return a.forEach(function(t){t.removeStub()}),c=u.distribute(a),c.map(function(e,r){e.forEach(function(t){t.layerIndex=r}),n.removeOverlap&&o(e,t)}),e},e.start=function(){console.log("[warning] force.start() is deprecated. Please use force.compute() instead.")},e};u.DEFAULT_OPTIONS=s,t.exports=u},function(t,e,n){"use strict";var r=n(4),i=n(6),o={algorithm:"overlap",layerWidth:1e3,density:.75,nodeSpacing:3,stubWidth:1},s=function(t){var e={};t=r.extend({},o,t),e.options=function(n){return arguments.length?(t=r.extend(t,n),e):t},e.computeRequiredWidth=function(e){return r.sum(e,function(e){return e.width+t.nodeSpacing})-t.nodeSpacing},e.maxWidthPerLayer=function(){return t.density*t.layerWidth},e.needToSplit=function(t){return e.estimateRequiredLayers(t)>1},e.estimateRequiredLayers=function(n){return t.layerWidth?Math.ceil(e.computeRequiredWidth(n)/e.maxWidthPerLayer()):1};var n={simple:function(n){for(var r=e.estimateRequiredLayers(n),i=[],o=0;r>o;o++)i.push([]);return n.forEach(function(e,n){var o=n%r;i[o].push(e);for(var s=e,u=o-1;u>=0;u--)s=s.createStub(t.stubWidth),i[u].push(s)}),i},roundRobin:function(t){var e=[];return e},overlap:function(n){for(var r=[],i=e.maxWidthPerLayer(),o=n.concat(),s=e.computeRequiredWidth(o);s>i;){e.countIdealOverlaps(o);var u=o.concat(),a=s;for(o=[];u.length>2&&a>i;){u.sort(function(t,e){return e.overlapCount-t.overlapCount});var c=u.shift();a-=c.width,a+=t.stubWidth,c.overlaps.forEach(function(t){t.overlapCount--}),o.push(c)}r.push(u),s=e.computeRequiredWidth(o)}o.length>0&&r.push(o);for(var h=r.length-1;h>=1;h--)for(var f=r[h],l=0;l=0;v--)d=d.createStub(t.stubWidth),r[v].push(d)}return r}};return e.countIdealOverlaps=function(e){var n=new i(t.layerWidth/2);return e.forEach(function(t){n.add([t.idealLeft(),t.idealRight(),t])}),e.forEach(function(t){var e=n.search(t.idealLeft(),t.idealRight());t.overlaps=e.map(function(t){return t.data[2]}),t.overlapCount=e.length}),e},e.distribute=function(i){if(!i||0===i.length)return[];if("none"==t.algorithm||!r.isDefined(t.algorithm))return[i];if(!e.needToSplit(i))return[i];if(i=i.concat().sort(function(t,e){return t.idealPos-e.idealPos}),"function"==typeof t.algorithm)return t.algorithm(i,t);if(n.hasOwnProperty(t.algorithm))return n[t.algorithm](i);throw"Unknown algorithm: "+t.algorithm},e};s.DEFAULT_OPTIONS=o,t.exports=s},function(t,e,n){"use strict";var r={isDefined:function(t){return null!==t&&void 0!==t},last:function(t){return t.length>0?t[t.length-1]:null},pick:function(t,e){return e.reduce(function(e,n){return e[n]=t[n],e},{})},sum:function(t,e){return t.map(e).reduce(function(t,e){return t+e},0)}};r.extend=n(5),t.exports=r},function(t,e){"use strict";var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol?"symbol":typeof t},r=Object.prototype.hasOwnProperty,i=Object.prototype.toString,o=function(t){return"function"==typeof Array.isArray?Array.isArray(t):"[object Array]"===i.call(t)},s=function(t){if(!t||"[object Object]"!==i.call(t))return!1;var e=r.call(t,"constructor"),n=t.constructor&&t.constructor.prototype&&r.call(t.constructor.prototype,"isPrototypeOf");if(t.constructor&&!e&&!n)return!1;var o;for(o in t);return void 0===o||r.call(t,o)};t.exports=function u(){var t,e,r,i,a,c,h=arguments[0],f=1,l=arguments.length,p=!1;for("boolean"==typeof h?(p=h,h=arguments[1]||{},f=2):("object"!==("undefined"==typeof h?"undefined":n(h))&&"function"!=typeof h||null==h)&&(h={});l>f;++f)if(t=arguments[f],null!=t)for(e in t)r=h[e],i=t[e],h!==i&&(p&&i&&(s(i)||(a=o(i)))?(a?(a=!1,c=r&&o(r)?r:[]):c=r&&s(r)?r:{},h[e]=u(p,c,i)):void 0!==i&&(h[e]=i));return h}},function(t,e,n){"use strict";function r(t,e){if(e||(e={}),this.startKey=e.startKey||0,this.endKey=e.endKey||1,this.intervalHash={},this.pointTree=new c({compare:function(t,e){if(null==t)return-1;if(null==e)return 1;var n=t[0]-e[0];return n>0?1:0==n?0:-1}}),this._autoIncrement=0,!t||"number"!=typeof t)throw new Error("you must specify center index as the 2nd argument.");this.root=new u(t,this)}function i(t,e){return e.end>1,this)),i.call(this,t.left,e)):t.idx>1,this)),i.call(this,t.right,e)):t.insert(e)}function o(t,e,n){return t?et.idx?(t.ends.every(function(t){var r=t.end>=e;return r&&n.push(t.result()),r}),o.call(this,t.right,e,n)):void t.starts.map(function(t){n.push(t.result())}):void 0}function s(t,e,n){if(0>=e-t)throw new Error("end must be greater than start. start: "+t+", end: "+e);var r={},i=[];o.call(this,this.root,t+e>>1,i,!0),i.forEach(function(t){r[t.id]=!0});for(var s=this.pointTree.bsearch([t,null]),u=this.pointTree;s>=0&&u[s][0]==t;)s--;var a=this.pointTree.bsearch([e,null]);if(a>=0){for(var c=u.length-1;c>=a&&u[a][0]<=e;)a++;u.slice(s+1,a).forEach(function(t){var e=t[1];r[e]=!0},this),Object.keys(r).forEach(function(r){var i=this.intervalHash[r];n.push(i.result(t,e))},this)}}function u(t){this.idx=t,this.starts=new c({compare:function(t,e){if(null==t)return-1;if(null==e)return 1;var n=t.start-e.start;return n>0?1:0==n?0:-1}}),this.ends=new c({compare:function(t,e){if(null==t)return-1;if(null==e)return 1;var n=t.end-e.end;return 0>n?1:0==n?0:-1}})}function a(t,e,n,r){if(this.id=e,this.start=t[n],this.end=t[r],this.data=t,"number"!=typeof this.start||"number"!=typeof this.end)throw new Error("start, end must be number. start: "+this.start+", end: "+this.end);if(this.start>=this.end)throw new Error("start must be smaller than end. start: "+this.start+", end: "+this.end)}var c=n(7);r.prototype.add=function(t,e){if(this.intervalHash[e])throw new Error("id "+e+" is already registered.");if(void 0==e){for(;this.intervalHash[this._autoIncrement];)this._autoIncrement++;e=this._autoIncrement}var n=new a(t,e,this.startKey,this.endKey);this.pointTree.insert([n.start,e]),this.pointTree.insert([n.end,e]),this.intervalHash[e]=n,this._autoIncrement++,i.call(this,this.root,n)},r.prototype.search=function(t,e){var n=[];if("number"!=typeof t)throw new Error(t+": invalid input");if(void 0==e)o.call(this,this.root,t,n);else{if("number"!=typeof e)throw new Error(t+","+e+": invalid input");s.call(this,t,e,n)}return n},r.prototype.remove=function(t){},u.prototype.insert=function(t){this.starts.insert(t),this.ends.insert(t)},a.prototype.result=function(t,e){var n={id:this.id,data:this.data};if("number"==typeof t&&"number"==typeof e){var r=Math.max(this.start,t),i=Math.min(this.end,e),o=i-r;n.rate1=o/(e-t),n.rate2=o/(this.end-this.start)}return n},t.exports=r},function(t,e){"use strict";var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol?"symbol":typeof t},r=function i(){var t=null,e={},r=arguments;["0","1"].forEach(function(i){var o=r[i];Array.isArray(o)?t=o:o&&"object"==("undefined"==typeof o?"undefined":n(o))&&(e=o)}),"function"==typeof e.filter&&(this._filter=e.filter),"function"==typeof e.compare?this._compare=e.compare:"string"==typeof e.compare&&i.compares[e.compare]&&(this._compare=i.compares[e.compare]),this._unique=!!e.unique,e.resume&&t?t.forEach(function(t,e){this.push(t)},this):t&&this.insert.apply(this,t)};r.create=function(t,e){return new r(t,e)},r.prototype=new Array,r.prototype.constructor=Array.prototype.constructor,r.prototype.insertOne=function(t){var e=this.bsearch(t);return this._unique&&null!=this.key(t,e)?!1:this._filter(t,e)?(this.splice(e+1,0,t),e+1):!1},r.prototype.insert=function(){return Array.prototype.map.call(arguments,function(t){return this.insertOne(t)},this)},r.prototype.remove=function(t){return this.splice(t,1),this},r.prototype.bsearch=function(t){if(!this.length)return-1;for(var e,n=0,r=this.length;r-n>1;){e=Math.floor((n+r)/2);var i=this[e],o=this._compare(t,i);if(0==o)return e;o>0?n=e:r=e}return 0==n&&this._compare(this[0],t)>0?-1:n},r.prototype.key=function(t,e){null==e&&(e=this.bsearch(t));var n=e;if(-1==n||this._compare(this[n],t)<0)return n+1=1&&0==this._compare(this[n-1],t);)n--;return n},r.prototype.keys=function(t,e){var n=[];null==e&&(e=this.bsearch(t));for(var r=e;r>=0&&0==this._compare(this[r],t);)n.push(r),r--;var i=this.length;for(r=e+1;i>r&&0==this._compare(this[r],t);)n.push(r),r++;return n.length?n:null},r.prototype.unique=function(t){if(t)return this.filter(function(t,e){return 0==e||0!=this._compare(this[e-1],t)},this);var e=0;return this.map(function(t,n){return 0==n||0!=this._compare(this[n-1],t)?null:n-e++},this).forEach(function(t){null!=t&&this.remove(t)},this),this},r.prototype.toArray=function(){return this.slice()},r.prototype._filter=function(t,e){return!0},r.compares={number:function(t,e){var n=t-e;return n>0?1:0==n?0:-1},string:function(t,e){return t>e?1:t==e?0:-1}},r.prototype._compare=r.compares.string,t.exports=r},function(t,e,n){"use strict";function r(t){var e=new s.Variable(t.targetPos);return e.node=t,e}function i(t,e){if(t.length>0){e=o.extend(u,e),t.forEach(function(t,e){t.targetPos=t.parent?t.parent.currentPos:t.idealPos,t.index=e}),t.sort(function(t,e){var n=t.targetPos-e.targetPos;if(0!==n)return n;var r=t.isStub()-e.isStub();return 0!==r?r:t.index-e.index});for(var n=t.map(r),i=[],a=1;at;++t)this.ps.addVariable(this.vars[t]);this.posn=this.ps.getPosn()},t.prototype.compute_lm=function(t,e,n){var r=this,i=t.dfdv();return t.visitNeighbours(e,function(e,o){var s=r.compute_lm(o,t,n);o===e.right?(i+=s*e.left.scale,e.lm=s):(i+=s*e.right.scale,e.lm=-s),n(e)}),i/t.scale},t.prototype.populateSplitBlock=function(t,e){var n=this;t.visitNeighbours(e,function(e,r){r.offset=t.offset+(r===e.right?e.gap:-e.gap),n.addVariable(r),n.populateSplitBlock(r,t)})},t.prototype.traverse=function(t,e,n,r){var i=this;void 0===n&&(n=this.vars[0]),void 0===r&&(r=null),n.visitNeighbours(r,function(r,o){e.push(t(r)),i.traverse(t,e,o,n)})},t.prototype.findMinLM=function(){var t=null;return this.compute_lm(this.vars[0],null,function(e){!e.equality&&(null===t||e.lmr;++r){var o=t.vars[r];o.offset+=n,this.addVariable(o)}this.posn=this.ps.getPosn()},t.prototype.cost=function(){for(var t=0,e=this.vars.length;e--;){var n=this.vars[e],r=n.position()-n.desiredPosition;t+=r*r*n.weight}return t},t}();n.Block=s;var u=function(){function t(t){this.vs=t;var e=t.length;for(this.list=new Array(e);e--;){var n=new s(t[e]);this.list[e]=n,n.blockInd=e}}return t.prototype.cost=function(){for(var t=0,e=this.list.length;e--;)t+=this.list[e].cost();return t},t.prototype.insert=function(t){t.blockInd=this.list.length,this.list.push(t)},t.prototype.remove=function(t){var e=this.list.length-1,n=this.list[e];this.list.length=e,t!==n&&(this.list[t.blockInd]=n,n.blockInd=t.blockInd)},t.prototype.merge=function(t){var e=t.left.block,n=t.right.block,r=t.right.offset-t.left.offset-t.gap;e.vars.lengths;++s){var u=r[s];if(!u.unsatisfiable){var a=u.slack();if((u.equality||e>a)&&(e=a,n=u,o=s,u.equality))break}}return o!==i&&(e=0?this.inactive.push(e):this.bs.merge(e)}}},t.prototype.solve=function(){this.satisfy();for(var t=Number.MAX_VALUE,e=this.bs.cost();Math.abs(t-e)>1e-4;)this.satisfy(),t=e,e=this.bs.cost();return e},t.LAGRANGIAN_TOLERANCE=-1e-4,t.ZERO_UPPERBOUND=-1e-10,t}();n.Solver=a,t.exports=n},function(t,e,n){"use strict";function r(t){this.options=c.extend({layerGap:60,nodeHeight:10,direction:"down"},t)}function i(t){return"L "+t.join(" ")}function o(t){return"M "+t.join(" ")}function s(t,e,n){return"C "+t.join(" ")+" "+e.join(" ")+" "+n.join(" ")}function u(t,e){var n=(t[1]+e[1])/2;return s([t[0],n],[e[0],n],e)}function a(t,e){var n=(t[0]+e[0])/2;return s([n,t[1]],[n,e[1]],e)}var c=n(4);r.lineTo=i,r.moveTo=o,r.curveTo=s,r.vCurveBetween=u,r.hCurveBetween=a,r.prototype.getWaypoints=function(t){var e=this.options,n=e.direction,r=t.getPathFromRoot(),i=e.nodeHeight+e.layerGap;return"left"===n?[[[0,r[0].idealPos]]].concat(r.map(function(t,n){var r=i*(n+1)*-1;return[[r+e.nodeHeight,t.currentPos],[r,t.currentPos]]})):"right"===n?[[[0,r[0].idealPos]]].concat(r.map(function(t,n){var r=i*(n+1);return[[r-e.nodeHeight,t.currentPos],[r,t.currentPos]]})):"up"===n?[[[r[0].idealPos,0]]].concat(r.map(function(t,n){var r=i*(n+1)*-1;return[[t.currentPos,r+e.nodeHeight],[t.currentPos,r]]})):[[[r[0].idealPos,0]]].concat(r.map(function(t,n){var r=i*(n+1);return[[t.currentPos,r-e.nodeHeight],[t.currentPos,r]]}))},r.prototype.layout=function(t){var e=this.options,n=e.layerGap+e.nodeHeight;switch(e.direction){case"left":t.forEach(function(t){var r=t.getLayerIndex()*n+e.layerGap;t.x=-r-e.nodeHeight,t.y=t.currentPos,t.dx=e.nodeHeight,t.dy=t.width});break;case"right":t.forEach(function(t){var r=t.getLayerIndex()*n+e.layerGap;t.x=r,t.y=t.currentPos,t.dx=e.nodeHeight,t.dy=t.width});break;case"up":t.forEach(function(t){var r=t.getLayerIndex()*n+e.layerGap;t.x=t.currentPos,t.y=-r-e.nodeHeight,t.dx=t.width,t.dy=e.nodeHeight});break;default:case"down":t.forEach(function(t){var r=t.getLayerIndex()*n+e.layerGap;t.x=t.currentPos,t.y=r,t.dx=t.width,t.dy=e.nodeHeight})}return t},r.prototype.generatePath=function(t){var e=this.options,n=e.direction,r=this.getWaypoints(t,n),s=[o(r[0][0])];return"left"===n||"right"===n?r.reduce(function(t,e,n){return s.push(a(t[t.length-1],e[0])),n=i)return t.width;if(e>r)return e-r}if(s.isDefined(n)){if(r>=n)return t.width;if(i>n)return i-n}return 0})})},u.overDensitySpace=function(t,e,n){var i=arguments.length<=3||void 0===arguments[3]?0:arguments[3];if(0===t.length||!s.isDefined(e)||!s.isDefined(n))return 0;var o=e*n,u=r(t);return s.sum(u,function(t){var e=s.sum(t,function(t){return t.width+i})-i;return o>=e?0:e-o})},u.overlapCount=function(t,e){if(0===t.length)return 0;var n=r(t);return s.sum(n,function(t){for(var n=0,r=0;ri?Math.abs(i):0}return e})/i(e)},u.weightedAllocation=function(t){if(0===t.length)return 0;var e=r(t);return s.sum(e,function(t,e){return e*t.filter(function(t){return!t.isStub()}).length})},u.weightedAllocatedSpace=function(t){if(0===t.length)return 0;var e=r(t);return s.sum(e,function(t,e){return e*s.sum(t,function(t){return t.width})})},t.exports=u},function(t,e,n){"use strict";var r=n(1),i=n(4);t.exports={generateNodes:function(t,e){var n=[];e=i.extend({},{minWidth:20,maxWidth:20,minPos:0,maxPos:800},e);for(var o=e.maxPos-e.minPos,s=e.maxWidth-e.minWidth,u=0;t>u;u++)n.push(new r(Math.floor(Math.random()*o)+e.minPos,Math.floor(Math.random()*s)+e.minWidth));return n}}}])}); \ No newline at end of file +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.labella=e():t.labella=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return t[r].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){"use strict";t.exports={Node:n(1),Force:n(2),Distributor:n(3),Renderer:n(10),metrics:n(11),util:n(12)}},function(t,e){"use strict";function n(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var r=function(){function t(t,e){for(var n=0;n=this.currentPos-e&&t<=this.currentPos+e}},{key:"positionBefore",value:function(t){var e=arguments.length<=1||void 0===arguments[1]?0:arguments[1];return t.currentLeft()-this.width/2-e}},{key:"positionAfter",value:function(t){var e=arguments.length<=1||void 0===arguments[1]?0:arguments[1];return t.currentRight()+this.width/2+e}},{key:"currentRight",value:function(){return this.currentPos+this.width/2}},{key:"currentLeft",value:function(){return this.currentPos-this.width/2}},{key:"idealRight",value:function(){return this.idealPos+this.width/2}},{key:"idealLeft",value:function(){return this.idealPos-this.width/2}},{key:"createStub",value:function(e){var n=new t(this.idealPos,e,this.data);return n.currentPos=this.currentPos,n.child=this,this.parent=n,n}},{key:"removeStub",value:function(){return this.parent&&(this.parent.child=null,this.parent=null),this}},{key:"isStub",value:function(){return!!this.child}},{key:"getPathToRoot",value:function(){for(var t=[],e=this;e;)t.push(e),e=e.parent;return t}},{key:"getPathFromRoot",value:function(){return this.getPathToRoot().reverse()}},{key:"getPathToRootLength",value:function(){for(var t=0,e=this;e;){var n=e.parent?e.parent.currentPos:e.idealPos;t+=Math.abs(e.currentPos-n),e=e.parent}return t}},{key:"getRoot",value:function(){for(var t=this,e=this;e;)t=e,e=e.parent;return t}},{key:"getLayerIndex",value:function(){return this.layerIndex}},{key:"clone",value:function(){var e=new t(this.idealPos,this.width,this.data);return e.currentPos=this.currentPos,e.layerIndex=this.layerIndex,e}}]),t}();t.exports=i},function(t,e,n){"use strict";var r=n(3),i=n(4),o=n(8),s={nodeSpacing:3,minPos:0,maxPos:null,algorithm:"overlap",removeOverlap:!0,density:.85,stubWidth:1},u=function(t){var e={},n=i.extend({},s),u=new r,a=[],c=null;return e.nodes=function(t){return arguments.length?(a=t,c=[t],e):a},e.getLayers=function(){return c},e.options=function(t){if(!arguments.length)return n;n=i.extend(n,t);var o=i.pick(n,Object.keys(r.DEFAULT_OPTIONS));return i.isDefined(n.minPos)&&i.isDefined(n.maxPos)?o.layerWidth=n.maxPos-n.minPos:o.layerWidth=null,u.options(o),e},e.options(t),e.compute=function(){var t=i.pick(n,Object.keys(o.DEFAULT_OPTIONS));return a.forEach(function(t){t.removeStub()}),c=u.distribute(a),c.map(function(e,r){e.forEach(function(t){t.layerIndex=r}),n.removeOverlap&&o(e,t)}),e},e.start=function(){console.log("[warning] force.start() is deprecated. Please use force.compute() instead.")},e};u.DEFAULT_OPTIONS=s,t.exports=u},function(t,e,n){"use strict";var r=n(4),i=n(6),o={algorithm:"overlap",layerWidth:1e3,density:.75,nodeSpacing:3,stubWidth:1},s=function(t){var e={};t=r.extend({},o,t),e.options=function(n){return arguments.length?(t=r.extend(t,n),e):t},e.computeRequiredWidth=function(e){return r.sum(e,function(e){return e.width+t.nodeSpacing})-t.nodeSpacing},e.maxWidthPerLayer=function(){return t.density*t.layerWidth},e.needToSplit=function(t){return e.estimateRequiredLayers(t)>1},e.estimateRequiredLayers=function(n){return t.layerWidth?Math.ceil(e.computeRequiredWidth(n)/e.maxWidthPerLayer()):1};var n={simple:function(n){for(var r=e.estimateRequiredLayers(n),i=[],o=0;r>o;o++)i.push([]);return n.forEach(function(e,n){var o=n%r;i[o].push(e);for(var s=e,u=o-1;u>=0;u--)s=s.createStub(t.stubWidth),i[u].push(s)}),i},roundRobin:function(t){var e=[];return e},overlap:function(n){for(var r=[],i=e.maxWidthPerLayer(),o=n.concat(),s=e.computeRequiredWidth(o);s>i;){e.countIdealOverlaps(o);var u=o.concat(),a=s;for(o=[];u.length>2&&a>i;){u.sort(function(t,e){return e.overlapCount-t.overlapCount});var c=u.shift();a-=c.width,a+=t.stubWidth,c.overlaps.forEach(function(t){t.overlapCount--}),o.push(c)}r.push(u),s=e.computeRequiredWidth(o)}o.length>0&&r.push(o);for(var h=r.length-1;h>=1;h--)for(var f=r[h],l=0;l=0;v--)d=d.createStub(t.stubWidth),r[v].push(d)}return r}};return e.countIdealOverlaps=function(e){var n=new i(t.layerWidth/2);return e.forEach(function(t){n.add([t.idealLeft(),t.idealRight(),t])}),e.forEach(function(t){var e=n.search(t.idealLeft(),t.idealRight());t.overlaps=e.map(function(t){return t.data[2]}),t.overlapCount=e.length}),e},e.distribute=function(i){if(!i||0===i.length)return[];if("none"==t.algorithm||!r.isDefined(t.algorithm))return[i];if(!e.needToSplit(i))return[i];if(i=i.concat().sort(function(t,e){return t.idealPos-e.idealPos}),"function"==typeof t.algorithm)return t.algorithm(i,t);if(n.hasOwnProperty(t.algorithm))return n[t.algorithm](i);throw"Unknown algorithm: "+t.algorithm},e};s.DEFAULT_OPTIONS=o,t.exports=s},function(t,e,n){"use strict";var r={isDefined:function(t){return null!==t&&void 0!==t},last:function(t){return t.length>0?t[t.length-1]:null},pick:function(t,e){return e.reduce(function(e,n){return e[n]=t[n],e},{})},sum:function(t,e){return t.map(e).reduce(function(t,e){return t+e},0)},functor:function(t){return"function"==typeof t?t:function(){return t}}};r.extend=n(5),t.exports=r},function(t,e){"use strict";var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol?"symbol":typeof t},r=Object.prototype.hasOwnProperty,i=Object.prototype.toString,o=function(t){return"function"==typeof Array.isArray?Array.isArray(t):"[object Array]"===i.call(t)},s=function(t){if(!t||"[object Object]"!==i.call(t))return!1;var e=r.call(t,"constructor"),n=t.constructor&&t.constructor.prototype&&r.call(t.constructor.prototype,"isPrototypeOf");if(t.constructor&&!e&&!n)return!1;var o;for(o in t);return void 0===o||r.call(t,o)};t.exports=function u(){var t,e,r,i,a,c,h=arguments[0],f=1,l=arguments.length,p=!1;for("boolean"==typeof h?(p=h,h=arguments[1]||{},f=2):("object"!==("undefined"==typeof h?"undefined":n(h))&&"function"!=typeof h||null==h)&&(h={});l>f;++f)if(t=arguments[f],null!=t)for(e in t)r=h[e],i=t[e],h!==i&&(p&&i&&(s(i)||(a=o(i)))?(a?(a=!1,c=r&&o(r)?r:[]):c=r&&s(r)?r:{},h[e]=u(p,c,i)):void 0!==i&&(h[e]=i));return h}},function(t,e,n){"use strict";function r(t,e){if(e||(e={}),this.startKey=e.startKey||0,this.endKey=e.endKey||1,this.intervalHash={},this.pointTree=new c({compare:function(t,e){if(null==t)return-1;if(null==e)return 1;var n=t[0]-e[0];return n>0?1:0==n?0:-1}}),this._autoIncrement=0,!t||"number"!=typeof t)throw new Error("you must specify center index as the 2nd argument.");this.root=new u(t,this)}function i(t,e){return e.end>1,this)),i.call(this,t.left,e)):t.idx>1,this)),i.call(this,t.right,e)):t.insert(e)}function o(t,e,n){return t?et.idx?(t.ends.every(function(t){var r=t.end>=e;return r&&n.push(t.result()),r}),o.call(this,t.right,e,n)):void t.starts.map(function(t){n.push(t.result())}):void 0}function s(t,e,n){if(0>=e-t)throw new Error("end must be greater than start. start: "+t+", end: "+e);var r={},i=[];o.call(this,this.root,t+e>>1,i,!0),i.forEach(function(t){r[t.id]=!0});for(var s=this.pointTree.bsearch([t,null]),u=this.pointTree;s>=0&&u[s][0]==t;)s--;var a=this.pointTree.bsearch([e,null]);if(a>=0){for(var c=u.length-1;c>=a&&u[a][0]<=e;)a++;u.slice(s+1,a).forEach(function(t){var e=t[1];r[e]=!0},this),Object.keys(r).forEach(function(r){var i=this.intervalHash[r];n.push(i.result(t,e))},this)}}function u(t){this.idx=t,this.starts=new c({compare:function(t,e){if(null==t)return-1;if(null==e)return 1;var n=t.start-e.start;return n>0?1:0==n?0:-1}}),this.ends=new c({compare:function(t,e){if(null==t)return-1;if(null==e)return 1;var n=t.end-e.end;return 0>n?1:0==n?0:-1}})}function a(t,e,n,r){if(this.id=e,this.start=t[n],this.end=t[r],this.data=t,"number"!=typeof this.start||"number"!=typeof this.end)throw new Error("start, end must be number. start: "+this.start+", end: "+this.end);if(this.start>=this.end)throw new Error("start must be smaller than end. start: "+this.start+", end: "+this.end)}var c=n(7);r.prototype.add=function(t,e){if(this.intervalHash[e])throw new Error("id "+e+" is already registered.");if(void 0==e){for(;this.intervalHash[this._autoIncrement];)this._autoIncrement++;e=this._autoIncrement}var n=new a(t,e,this.startKey,this.endKey);this.pointTree.insert([n.start,e]),this.pointTree.insert([n.end,e]),this.intervalHash[e]=n,this._autoIncrement++,i.call(this,this.root,n)},r.prototype.search=function(t,e){var n=[];if("number"!=typeof t)throw new Error(t+": invalid input");if(void 0==e)o.call(this,this.root,t,n);else{if("number"!=typeof e)throw new Error(t+","+e+": invalid input");s.call(this,t,e,n)}return n},r.prototype.remove=function(t){},u.prototype.insert=function(t){this.starts.insert(t),this.ends.insert(t)},a.prototype.result=function(t,e){var n={id:this.id,data:this.data};if("number"==typeof t&&"number"==typeof e){var r=Math.max(this.start,t),i=Math.min(this.end,e),o=i-r;n.rate1=o/(e-t),n.rate2=o/(this.end-this.start)}return n},t.exports=r},function(t,e){"use strict";var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol?"symbol":typeof t},r=function i(){var t=null,e={},r=arguments;["0","1"].forEach(function(i){var o=r[i];Array.isArray(o)?t=o:o&&"object"==("undefined"==typeof o?"undefined":n(o))&&(e=o)}),"function"==typeof e.filter&&(this._filter=e.filter),"function"==typeof e.compare?this._compare=e.compare:"string"==typeof e.compare&&i.compares[e.compare]&&(this._compare=i.compares[e.compare]),this._unique=!!e.unique,e.resume&&t?t.forEach(function(t,e){this.push(t)},this):t&&this.insert.apply(this,t)};r.create=function(t,e){return new r(t,e)},r.prototype=new Array,r.prototype.constructor=Array.prototype.constructor,r.prototype.insertOne=function(t){var e=this.bsearch(t);return this._unique&&null!=this.key(t,e)?!1:this._filter(t,e)?(this.splice(e+1,0,t),e+1):!1},r.prototype.insert=function(){return Array.prototype.map.call(arguments,function(t){return this.insertOne(t)},this)},r.prototype.remove=function(t){return this.splice(t,1),this},r.prototype.bsearch=function(t){if(!this.length)return-1;for(var e,n=0,r=this.length;r-n>1;){e=Math.floor((n+r)/2);var i=this[e],o=this._compare(t,i);if(0==o)return e;o>0?n=e:r=e}return 0==n&&this._compare(this[0],t)>0?-1:n},r.prototype.key=function(t,e){null==e&&(e=this.bsearch(t));var n=e;if(-1==n||this._compare(this[n],t)<0)return n+1=1&&0==this._compare(this[n-1],t);)n--;return n},r.prototype.keys=function(t,e){var n=[];null==e&&(e=this.bsearch(t));for(var r=e;r>=0&&0==this._compare(this[r],t);)n.push(r),r--;var i=this.length;for(r=e+1;i>r&&0==this._compare(this[r],t);)n.push(r),r++;return n.length?n:null},r.prototype.unique=function(t){if(t)return this.filter(function(t,e){return 0==e||0!=this._compare(this[e-1],t)},this);var e=0;return this.map(function(t,n){return 0==n||0!=this._compare(this[n-1],t)?null:n-e++},this).forEach(function(t){null!=t&&this.remove(t)},this),this},r.prototype.toArray=function(){return this.slice()},r.prototype._filter=function(t,e){return!0},r.compares={number:function(t,e){var n=t-e;return n>0?1:0==n?0:-1},string:function(t,e){return t>e?1:t==e?0:-1}},r.prototype._compare=r.compares.string,t.exports=r},function(t,e,n){"use strict";function r(t){var e=new s.Variable(t.targetPos);return e.node=t,e}function i(t,e){if(t.length>0){e=o.extend(u,e),t.forEach(function(t,e){t.targetPos=t.parent?t.parent.currentPos:t.idealPos,t.index=e}),t.sort(function(t,e){var n=t.targetPos-e.targetPos;if(0!==n)return n;var r=t.isStub()-e.isStub();return 0!==r?r:t.index-e.index});for(var n=t.map(r),i=[],a=1;at;++t)this.ps.addVariable(this.vars[t]);this.posn=this.ps.getPosn()},t.prototype.compute_lm=function(t,e,n){var r=this,i=t.dfdv();return t.visitNeighbours(e,function(e,o){var s=r.compute_lm(o,t,n);o===e.right?(i+=s*e.left.scale,e.lm=s):(i+=s*e.right.scale,e.lm=-s),n(e)}),i/t.scale},t.prototype.populateSplitBlock=function(t,e){var n=this;t.visitNeighbours(e,function(e,r){r.offset=t.offset+(r===e.right?e.gap:-e.gap),n.addVariable(r),n.populateSplitBlock(r,t)})},t.prototype.traverse=function(t,e,n,r){var i=this;void 0===n&&(n=this.vars[0]),void 0===r&&(r=null),n.visitNeighbours(r,function(r,o){e.push(t(r)),i.traverse(t,e,o,n)})},t.prototype.findMinLM=function(){var t=null;return this.compute_lm(this.vars[0],null,function(e){!e.equality&&(null===t||e.lmr;++r){var o=t.vars[r];o.offset+=n,this.addVariable(o)}this.posn=this.ps.getPosn()},t.prototype.cost=function(){for(var t=0,e=this.vars.length;e--;){var n=this.vars[e],r=n.position()-n.desiredPosition;t+=r*r*n.weight}return t},t}();n.Block=s;var u=function(){function t(t){this.vs=t;var e=t.length;for(this.list=new Array(e);e--;){var n=new s(t[e]);this.list[e]=n,n.blockInd=e}}return t.prototype.cost=function(){for(var t=0,e=this.list.length;e--;)t+=this.list[e].cost();return t},t.prototype.insert=function(t){t.blockInd=this.list.length,this.list.push(t)},t.prototype.remove=function(t){var e=this.list.length-1,n=this.list[e];this.list.length=e,t!==n&&(this.list[t.blockInd]=n,n.blockInd=t.blockInd)},t.prototype.merge=function(t){var e=t.left.block,n=t.right.block,r=t.right.offset-t.left.offset-t.gap;e.vars.lengths;++s){var u=r[s];if(!u.unsatisfiable){var a=u.slack();if((u.equality||e>a)&&(e=a,n=u,o=s,u.equality))break}}return o!==i&&(e=0?this.inactive.push(e):this.bs.merge(e)}}},t.prototype.solve=function(){this.satisfy();for(var t=Number.MAX_VALUE,e=this.bs.cost();Math.abs(t-e)>1e-4;)this.satisfy(),t=e,e=this.bs.cost();return e},t.LAGRANGIAN_TOLERANCE=-1e-4,t.ZERO_UPPERBOUND=-1e-10,t}();n.Solver=a,t.exports=n},function(t,e,n){"use strict";function r(t){this.options=c.extend({layerGap:60,nodeHeight:h,direction:"down"},t)}function i(t){return"L "+t.join(" ")}function o(t){return"M "+t.join(" ")}function s(t,e,n){return"C "+t.join(" ")+" "+e.join(" ")+" "+n.join(" ")}function u(t,e){var n=(t[1]+e[1])/2;return s([t[0],n],[e[0],n],e)}function a(t,e){var n=(t[0]+e[0])/2;return s([n,t[1]],[n,e[1]],e)}var c=n(4),h=10;r.lineTo=i,r.moveTo=o,r.curveTo=s,r.vCurveBetween=u,r.hCurveBetween=a,r.prototype.getWaypoints=function(t){var e=this.options,n=c.functor(e.nodeHeight)(t.data),r=e.direction,i=t.getPathFromRoot(),o=n+e.layerGap;return"left"===r?[[[0,i[0].idealPos]]].concat(i.map(function(t,e){var r=o*(e+1)*-1;return[[r+n,t.currentPos],[r,t.currentPos]]})):"right"===r?[[[0,i[0].idealPos]]].concat(i.map(function(t,e){var r=o*(e+1);return[[r-n,t.currentPos],[r,t.currentPos]]})):"up"===r?[[[i[0].idealPos,0]]].concat(i.map(function(t,e){var r=o*(e+1)*-1;return[[t.currentPos,r+n],[t.currentPos,r]]})):[[[i[0].idealPos,0]]].concat(i.map(function(t,e){var r=o*(e+1);return[[t.currentPos,r-n],[t.currentPos,r]]}))},r.prototype.layout=function(t){var e=this.options,n=c.functor(e.nodeHeight);if("function"==typeof e.nodeHeight){var r=[];t.forEach(function(t,n){r[n]=e.layerGap+e.nodeHeight(t.data)})}var i=e.layerGap+e.nodeHeight;switch(e.direction){case"left":t.forEach(function(t,o){var s=0;s=r?t.getLayerIndex()*r[o]+e.layerGap:t.getLayerIndex()*i+e.layerGap,t.x=-s-n(t.data),t.y=t.currentPos,t.dx=n(t.data),t.dy=t.width});break;case"right":t.forEach(function(t,o){var s=0;s=r?t.getLayerIndex()*r[o]+e.layerGap:t.getLayerIndex()*i+e.layerGap,t.x=s,t.y=t.currentPos,t.dx=n(t.data),t.dy=t.width});break;case"up":t.forEach(function(t,o){var s=0;s=r?t.getLayerIndex()*r[o]+e.layerGap:t.getLayerIndex()*i+e.layerGap,t.x=t.currentPos,t.y=-s-n(t.data),t.dx=t.width,t.dy=n(t.data)});break;default:case"down":t.forEach(function(t,o){var s=0;s=r?t.getLayerIndex()*r[o]+e.layerGap:t.getLayerIndex()*i+e.layerGap,t.x=t.currentPos,t.y=s,t.dx=t.width,t.dy=n(t.data)})}return t},r.prototype.generatePath=function(t){var e=this.options,n=e.direction,r=this.getWaypoints(t,n),s=[o(r[0][0])];return"left"===n||"right"===n?r.reduce(function(t,e,n){return s.push(a(t[t.length-1],e[0])),n=i)return t.width;if(e>r)return e-r}if(s.isDefined(n)){if(r>=n)return t.width;if(i>n)return i-n}return 0})})},u.overDensitySpace=function(t,e,n){var i=arguments.length<=3||void 0===arguments[3]?0:arguments[3];if(0===t.length||!s.isDefined(e)||!s.isDefined(n))return 0;var o=e*n,u=r(t);return s.sum(u,function(t){var e=s.sum(t,function(t){return t.width+i})-i;return o>=e?0:e-o})},u.overlapCount=function(t,e){if(0===t.length)return 0;var n=r(t);return s.sum(n,function(t){for(var n=0,r=0;ri?Math.abs(i):0}return e})/i(e)},u.weightedAllocation=function(t){if(0===t.length)return 0;var e=r(t);return s.sum(e,function(t,e){return e*t.filter(function(t){return!t.isStub()}).length})},u.weightedAllocatedSpace=function(t){if(0===t.length)return 0;var e=r(t);return s.sum(e,function(t,e){return e*s.sum(t,function(t){return t.width})})},t.exports=u},function(t,e,n){"use strict";var r=n(1),i=n(4);t.exports={generateNodes:function(t,e){var n=[];e=i.extend({},{minWidth:20,maxWidth:20,minPos:0,maxPos:800},e);for(var o=e.maxPos-e.minPos,s=e.maxWidth-e.minWidth,u=0;t>u;u++)n.push(new r(Math.floor(Math.random()*o)+e.minPos,Math.floor(Math.random()*s)+e.minWidth));return n}}}])}); \ No newline at end of file diff --git a/dist/labella.js b/dist/labella.js index 69e7271..b8a6b6c 100644 --- a/dist/labella.js +++ b/dist/labella.js @@ -92,6 +92,7 @@ return /******/ (function(modules) { // webpackBootstrap // return negative if overlap + _createClass(Node, [{ key: 'distanceFrom', value: function distanceFrom(node) { @@ -543,6 +544,11 @@ return /******/ (function(modules) { // webpackBootstrap return array.map(accessor).reduce(function (prev, current) { return prev + current; }, 0); + }, + functor: function functor(v) { + return typeof v === "function" ? v : function () { + return v; + }; } }; @@ -1818,10 +1824,12 @@ return /******/ (function(modules) { // webpackBootstrap var helper = __webpack_require__(4); + var DEFAULT_NODE_HEIGHT = 10; + function Renderer(options) { this.options = helper.extend({ layerGap: 60, - nodeHeight: 10, + nodeHeight: DEFAULT_NODE_HEIGHT, direction: 'down' }, options); } @@ -1856,30 +1864,31 @@ return /******/ (function(modules) { // webpackBootstrap Renderer.prototype.getWaypoints = function (node) { var options = this.options; + var nodeHeight = helper.functor(options.nodeHeight)(node); var direction = options.direction; var hops = node.getPathFromRoot(); - var gap = options.nodeHeight + options.layerGap; + var gap = nodeHeight + options.layerGap; if (direction === 'left') { return [[[0, hops[0].idealPos]]].concat(hops.map(function (hop, level) { var xPos = gap * (level + 1) * -1; - return [[xPos + options.nodeHeight, hop.currentPos], [xPos, hop.currentPos]]; + return [[xPos + nodeHeight, hop.currentPos], [xPos, hop.currentPos]]; })); } else if (direction === 'right') { return [[[0, hops[0].idealPos]]].concat(hops.map(function (hop, level) { var xPos = gap * (level + 1); - return [[xPos - options.nodeHeight, hop.currentPos], [xPos, hop.currentPos]]; + return [[xPos - nodeHeight, hop.currentPos], [xPos, hop.currentPos]]; })); } else if (direction === 'up') { return [[[hops[0].idealPos, 0]]].concat(hops.map(function (hop, level) { var yPos = gap * (level + 1) * -1; - return [[hop.currentPos, yPos + options.nodeHeight], [hop.currentPos, yPos]]; + return [[hop.currentPos, yPos + nodeHeight], [hop.currentPos, yPos]]; })); } else { return [[[hops[0].idealPos, 0]]].concat(hops.map(function (hop, level) { var yPos = gap * (level + 1); - return [[hop.currentPos, yPos - options.nodeHeight], [hop.currentPos, yPos]]; + return [[hop.currentPos, yPos - nodeHeight], [hop.currentPos, yPos]]; })); } }; @@ -1887,44 +1896,76 @@ return /******/ (function(modules) { // webpackBootstrap Renderer.prototype.layout = function (nodes) { var options = this.options; + var nodeHeightFn = helper.functor(options.nodeHeight); + if (typeof options.nodeHeight === 'function') { + var gaps = []; + nodes.forEach(function (node, index) { + gaps[index] = options.layerGap + options.nodeHeight(node); + }); + } + var gap = options.layerGap + options.nodeHeight; switch (options.direction) { case 'left': - nodes.forEach(function (node) { - var pos = node.getLayerIndex() * gap + options.layerGap; - node.x = -pos - options.nodeHeight; + nodes.forEach(function (node, index) { + var pos = 0; + if (gaps) { + //if the nodeHeight is a function + pos = node.getLayerIndex() * gaps[index] + options.layerGap; + } else { + pos = node.getLayerIndex() * gap + options.layerGap; + } + node.x = -pos - nodeHeightFn(node); node.y = node.currentPos; - node.dx = options.nodeHeight; + node.dx = nodeHeightFn(node); node.dy = node.width; }); break; case 'right': - nodes.forEach(function (node) { - var pos = node.getLayerIndex() * gap + options.layerGap; + nodes.forEach(function (node, index) { + var pos = 0; + if (gaps) { + //if the nodeHeight is a function + pos = node.getLayerIndex() * gaps[index] + options.layerGap; + } else { + pos = node.getLayerIndex() * gap + options.layerGap; + } node.x = pos; node.y = node.currentPos; - node.dx = options.nodeHeight; + node.dx = nodeHeightFn(node); node.dy = node.width; }); break; case 'up': - nodes.forEach(function (node) { - var pos = node.getLayerIndex() * gap + options.layerGap; + nodes.forEach(function (node, index) { + var pos = 0; + if (gaps) { + //if the nodeHeight is a function + pos = node.getLayerIndex() * gaps[index] + options.layerGap; + } else { + pos = node.getLayerIndex() * gap + options.layerGap; + } node.x = node.currentPos; - node.y = -pos - options.nodeHeight; + node.y = -pos - nodeHeightFn(node); node.dx = node.width; - node.dy = options.nodeHeight; + node.dy = nodeHeightFn(node); }); break; default: case 'down': - nodes.forEach(function (node) { - var pos = node.getLayerIndex() * gap + options.layerGap; + nodes.forEach(function (node, index) { + var pos = 0; + if (gaps) { + //if the nodeHeight is a function + pos = node.getLayerIndex() * gaps[index] + options.layerGap; + } else { + pos = node.getLayerIndex() * gap + options.layerGap; + } node.x = node.currentPos; node.y = pos; node.dx = node.width; - node.dy = options.nodeHeight; + node.dy = nodeHeightFn(node); }); break; } diff --git a/dist/labella.min.js b/dist/labella.min.js index 591d8dd..3f2511b 100644 --- a/dist/labella.min.js +++ b/dist/labella.min.js @@ -1 +1 @@ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.labella=e():t.labella=e()}(this,function(){return function(t){function e(n){if(r[n])return r[n].exports;var i=r[n]={exports:{},id:n,loaded:!1};return t[n].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var r={};return e.m=t,e.c=r,e.p="",e(0)}([function(t,e,r){"use strict";t.exports={Node:r(1),Force:r(2),Distributor:r(3),Renderer:r(10)}},function(t,e){"use strict";function r(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var n=function(){function t(t,e){for(var r=0;r=this.currentPos-e&&t<=this.currentPos+e}},{key:"positionBefore",value:function(t){var e=arguments.length<=1||void 0===arguments[1]?0:arguments[1];return t.currentLeft()-this.width/2-e}},{key:"positionAfter",value:function(t){var e=arguments.length<=1||void 0===arguments[1]?0:arguments[1];return t.currentRight()+this.width/2+e}},{key:"currentRight",value:function(){return this.currentPos+this.width/2}},{key:"currentLeft",value:function(){return this.currentPos-this.width/2}},{key:"idealRight",value:function(){return this.idealPos+this.width/2}},{key:"idealLeft",value:function(){return this.idealPos-this.width/2}},{key:"createStub",value:function(e){var r=new t(this.idealPos,e,this.data);return r.currentPos=this.currentPos,r.child=this,this.parent=r,r}},{key:"removeStub",value:function(){return this.parent&&(this.parent.child=null,this.parent=null),this}},{key:"isStub",value:function(){return!!this.child}},{key:"getPathToRoot",value:function(){for(var t=[],e=this;e;)t.push(e),e=e.parent;return t}},{key:"getPathFromRoot",value:function(){return this.getPathToRoot().reverse()}},{key:"getPathToRootLength",value:function(){for(var t=0,e=this;e;){var r=e.parent?e.parent.currentPos:e.idealPos;t+=Math.abs(e.currentPos-r),e=e.parent}return t}},{key:"getRoot",value:function(){for(var t=this,e=this;e;)t=e,e=e.parent;return t}},{key:"getLayerIndex",value:function(){return this.layerIndex}},{key:"clone",value:function(){var e=new t(this.idealPos,this.width,this.data);return e.currentPos=this.currentPos,e.layerIndex=this.layerIndex,e}}]),t}();t.exports=i},function(t,e,r){"use strict";var n=r(3),i=r(4),o=r(8),s={nodeSpacing:3,minPos:0,maxPos:null,algorithm:"overlap",removeOverlap:!0,density:.85,stubWidth:1},u=function(t){var e={},r=i.extend({},s),u=new n,a=[],c=null;return e.nodes=function(t){return arguments.length?(a=t,c=[t],e):a},e.getLayers=function(){return c},e.options=function(t){if(!arguments.length)return r;r=i.extend(r,t);var o=i.pick(r,Object.keys(n.DEFAULT_OPTIONS));return i.isDefined(r.minPos)&&i.isDefined(r.maxPos)?o.layerWidth=r.maxPos-r.minPos:o.layerWidth=null,u.options(o),e},e.options(t),e.compute=function(){var t=i.pick(r,Object.keys(o.DEFAULT_OPTIONS));return a.forEach(function(t){t.removeStub()}),c=u.distribute(a),c.map(function(e,n){e.forEach(function(t){t.layerIndex=n}),r.removeOverlap&&o(e,t)}),e},e.start=function(){console.log("[warning] force.start() is deprecated. Please use force.compute() instead.")},e};u.DEFAULT_OPTIONS=s,t.exports=u},function(t,e,r){"use strict";var n=r(4),i=r(6),o={algorithm:"overlap",layerWidth:1e3,density:.75,nodeSpacing:3,stubWidth:1},s=function(t){var e={};t=n.extend({},o,t),e.options=function(r){return arguments.length?(t=n.extend(t,r),e):t},e.computeRequiredWidth=function(e){return n.sum(e,function(e){return e.width+t.nodeSpacing})-t.nodeSpacing},e.maxWidthPerLayer=function(){return t.density*t.layerWidth},e.needToSplit=function(t){return e.estimateRequiredLayers(t)>1},e.estimateRequiredLayers=function(r){return t.layerWidth?Math.ceil(e.computeRequiredWidth(r)/e.maxWidthPerLayer()):1};var r={simple:function(r){for(var n=e.estimateRequiredLayers(r),i=[],o=0;n>o;o++)i.push([]);return r.forEach(function(e,r){var o=r%n;i[o].push(e);for(var s=e,u=o-1;u>=0;u--)s=s.createStub(t.stubWidth),i[u].push(s)}),i},roundRobin:function(t){var e=[];return e},overlap:function(r){for(var n=[],i=e.maxWidthPerLayer(),o=r.concat(),s=e.computeRequiredWidth(o);s>i;){e.countIdealOverlaps(o);var u=o.concat(),a=s;for(o=[];u.length>2&&a>i;){u.sort(function(t,e){return e.overlapCount-t.overlapCount});var c=u.shift();a-=c.width,a+=t.stubWidth,c.overlaps.forEach(function(t){t.overlapCount--}),o.push(c)}n.push(u),s=e.computeRequiredWidth(o)}o.length>0&&n.push(o);for(var h=n.length-1;h>=1;h--)for(var l=n[h],f=0;f=0;v--)d=d.createStub(t.stubWidth),n[v].push(d)}return n}};return e.countIdealOverlaps=function(e){var r=new i(t.layerWidth/2);return e.forEach(function(t){r.add([t.idealLeft(),t.idealRight(),t])}),e.forEach(function(t){var e=r.search(t.idealLeft(),t.idealRight());t.overlaps=e.map(function(t){return t.data[2]}),t.overlapCount=e.length}),e},e.distribute=function(i){if(!i||0===i.length)return[];if("none"==t.algorithm||!n.isDefined(t.algorithm))return[i];if(!e.needToSplit(i))return[i];if(i=i.concat().sort(function(t,e){return t.idealPos-e.idealPos}),"function"==typeof t.algorithm)return t.algorithm(i,t);if(r.hasOwnProperty(t.algorithm))return r[t.algorithm](i);throw"Unknown algorithm: "+t.algorithm},e};s.DEFAULT_OPTIONS=o,t.exports=s},function(t,e,r){"use strict";var n={isDefined:function(t){return null!==t&&void 0!==t},last:function(t){return t.length>0?t[t.length-1]:null},pick:function(t,e){return e.reduce(function(e,r){return e[r]=t[r],e},{})},sum:function(t,e){return t.map(e).reduce(function(t,e){return t+e},0)}};n.extend=r(5),t.exports=n},function(t,e){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol?"symbol":typeof t},n=Object.prototype.hasOwnProperty,i=Object.prototype.toString,o=function(t){return"function"==typeof Array.isArray?Array.isArray(t):"[object Array]"===i.call(t)},s=function(t){if(!t||"[object Object]"!==i.call(t))return!1;var e=n.call(t,"constructor"),r=t.constructor&&t.constructor.prototype&&n.call(t.constructor.prototype,"isPrototypeOf");if(t.constructor&&!e&&!r)return!1;var o;for(o in t);return void 0===o||n.call(t,o)};t.exports=function u(){var t,e,n,i,a,c,h=arguments[0],l=1,f=arguments.length,p=!1;for("boolean"==typeof h?(p=h,h=arguments[1]||{},l=2):("object"!==("undefined"==typeof h?"undefined":r(h))&&"function"!=typeof h||null==h)&&(h={});f>l;++l)if(t=arguments[l],null!=t)for(e in t)n=h[e],i=t[e],h!==i&&(p&&i&&(s(i)||(a=o(i)))?(a?(a=!1,c=n&&o(n)?n:[]):c=n&&s(n)?n:{},h[e]=u(p,c,i)):void 0!==i&&(h[e]=i));return h}},function(t,e,r){"use strict";function n(t,e){if(e||(e={}),this.startKey=e.startKey||0,this.endKey=e.endKey||1,this.intervalHash={},this.pointTree=new c({compare:function(t,e){if(null==t)return-1;if(null==e)return 1;var r=t[0]-e[0];return r>0?1:0==r?0:-1}}),this._autoIncrement=0,!t||"number"!=typeof t)throw new Error("you must specify center index as the 2nd argument.");this.root=new u(t,this)}function i(t,e){return e.end>1,this)),i.call(this,t.left,e)):t.idx>1,this)),i.call(this,t.right,e)):t.insert(e)}function o(t,e,r){return t?et.idx?(t.ends.every(function(t){var n=t.end>=e;return n&&r.push(t.result()),n}),o.call(this,t.right,e,r)):void t.starts.map(function(t){r.push(t.result())}):void 0}function s(t,e,r){if(0>=e-t)throw new Error("end must be greater than start. start: "+t+", end: "+e);var n={},i=[];o.call(this,this.root,t+e>>1,i,!0),i.forEach(function(t){n[t.id]=!0});for(var s=this.pointTree.bsearch([t,null]),u=this.pointTree;s>=0&&u[s][0]==t;)s--;var a=this.pointTree.bsearch([e,null]);if(a>=0){for(var c=u.length-1;c>=a&&u[a][0]<=e;)a++;u.slice(s+1,a).forEach(function(t){var e=t[1];n[e]=!0},this),Object.keys(n).forEach(function(n){var i=this.intervalHash[n];r.push(i.result(t,e))},this)}}function u(t){this.idx=t,this.starts=new c({compare:function(t,e){if(null==t)return-1;if(null==e)return 1;var r=t.start-e.start;return r>0?1:0==r?0:-1}}),this.ends=new c({compare:function(t,e){if(null==t)return-1;if(null==e)return 1;var r=t.end-e.end;return 0>r?1:0==r?0:-1}})}function a(t,e,r,n){if(this.id=e,this.start=t[r],this.end=t[n],this.data=t,"number"!=typeof this.start||"number"!=typeof this.end)throw new Error("start, end must be number. start: "+this.start+", end: "+this.end);if(this.start>=this.end)throw new Error("start must be smaller than end. start: "+this.start+", end: "+this.end)}var c=r(7);n.prototype.add=function(t,e){if(this.intervalHash[e])throw new Error("id "+e+" is already registered.");if(void 0==e){for(;this.intervalHash[this._autoIncrement];)this._autoIncrement++;e=this._autoIncrement}var r=new a(t,e,this.startKey,this.endKey);this.pointTree.insert([r.start,e]),this.pointTree.insert([r.end,e]),this.intervalHash[e]=r,this._autoIncrement++,i.call(this,this.root,r)},n.prototype.search=function(t,e){var r=[];if("number"!=typeof t)throw new Error(t+": invalid input");if(void 0==e)o.call(this,this.root,t,r);else{if("number"!=typeof e)throw new Error(t+","+e+": invalid input");s.call(this,t,e,r)}return r},n.prototype.remove=function(t){},u.prototype.insert=function(t){this.starts.insert(t),this.ends.insert(t)},a.prototype.result=function(t,e){var r={id:this.id,data:this.data};if("number"==typeof t&&"number"==typeof e){var n=Math.max(this.start,t),i=Math.min(this.end,e),o=i-n;r.rate1=o/(e-t),r.rate2=o/(this.end-this.start)}return r},t.exports=n},function(t,e){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol?"symbol":typeof t},n=function i(){var t=null,e={},n=arguments;["0","1"].forEach(function(i){var o=n[i];Array.isArray(o)?t=o:o&&"object"==("undefined"==typeof o?"undefined":r(o))&&(e=o)}),"function"==typeof e.filter&&(this._filter=e.filter),"function"==typeof e.compare?this._compare=e.compare:"string"==typeof e.compare&&i.compares[e.compare]&&(this._compare=i.compares[e.compare]),this._unique=!!e.unique,e.resume&&t?t.forEach(function(t,e){this.push(t)},this):t&&this.insert.apply(this,t)};n.create=function(t,e){return new n(t,e)},n.prototype=new Array,n.prototype.constructor=Array.prototype.constructor,n.prototype.insertOne=function(t){var e=this.bsearch(t);return this._unique&&null!=this.key(t,e)?!1:this._filter(t,e)?(this.splice(e+1,0,t),e+1):!1},n.prototype.insert=function(){return Array.prototype.map.call(arguments,function(t){return this.insertOne(t)},this)},n.prototype.remove=function(t){return this.splice(t,1),this},n.prototype.bsearch=function(t){if(!this.length)return-1;for(var e,r=0,n=this.length;n-r>1;){e=Math.floor((r+n)/2);var i=this[e],o=this._compare(t,i);if(0==o)return e;o>0?r=e:n=e}return 0==r&&this._compare(this[0],t)>0?-1:r},n.prototype.key=function(t,e){null==e&&(e=this.bsearch(t));var r=e;if(-1==r||this._compare(this[r],t)<0)return r+1=1&&0==this._compare(this[r-1],t);)r--;return r},n.prototype.keys=function(t,e){var r=[];null==e&&(e=this.bsearch(t));for(var n=e;n>=0&&0==this._compare(this[n],t);)r.push(n),n--;var i=this.length;for(n=e+1;i>n&&0==this._compare(this[n],t);)r.push(n),n++;return r.length?r:null},n.prototype.unique=function(t){if(t)return this.filter(function(t,e){return 0==e||0!=this._compare(this[e-1],t)},this);var e=0;return this.map(function(t,r){return 0==r||0!=this._compare(this[r-1],t)?null:r-e++},this).forEach(function(t){null!=t&&this.remove(t)},this),this},n.prototype.toArray=function(){return this.slice()},n.prototype._filter=function(t,e){return!0},n.compares={number:function(t,e){var r=t-e;return r>0?1:0==r?0:-1},string:function(t,e){return t>e?1:t==e?0:-1}},n.prototype._compare=n.compares.string,t.exports=n},function(t,e,r){"use strict";function n(t){var e=new s.Variable(t.targetPos);return e.node=t,e}function i(t,e){if(t.length>0){e=o.extend(u,e),t.forEach(function(t,e){t.targetPos=t.parent?t.parent.currentPos:t.idealPos,t.index=e}),t.sort(function(t,e){var r=t.targetPos-e.targetPos;if(0!==r)return r;var n=t.isStub()-e.isStub();return 0!==n?n:t.index-e.index});for(var r=t.map(n),i=[],a=1;at;++t)this.ps.addVariable(this.vars[t]);this.posn=this.ps.getPosn()},t.prototype.compute_lm=function(t,e,r){var n=this,i=t.dfdv();return t.visitNeighbours(e,function(e,o){var s=n.compute_lm(o,t,r);o===e.right?(i+=s*e.left.scale,e.lm=s):(i+=s*e.right.scale,e.lm=-s),r(e)}),i/t.scale},t.prototype.populateSplitBlock=function(t,e){var r=this;t.visitNeighbours(e,function(e,n){n.offset=t.offset+(n===e.right?e.gap:-e.gap),r.addVariable(n),r.populateSplitBlock(n,t)})},t.prototype.traverse=function(t,e,r,n){var i=this;void 0===r&&(r=this.vars[0]),void 0===n&&(n=null),r.visitNeighbours(n,function(n,o){e.push(t(n)),i.traverse(t,e,o,r)})},t.prototype.findMinLM=function(){var t=null;return this.compute_lm(this.vars[0],null,function(e){!e.equality&&(null===t||e.lmn;++n){var o=t.vars[n];o.offset+=r,this.addVariable(o)}this.posn=this.ps.getPosn()},t.prototype.cost=function(){for(var t=0,e=this.vars.length;e--;){var r=this.vars[e],n=r.position()-r.desiredPosition;t+=n*n*r.weight}return t},t}();r.Block=s;var u=function(){function t(t){this.vs=t;var e=t.length;for(this.list=new Array(e);e--;){var r=new s(t[e]);this.list[e]=r,r.blockInd=e}}return t.prototype.cost=function(){for(var t=0,e=this.list.length;e--;)t+=this.list[e].cost();return t},t.prototype.insert=function(t){t.blockInd=this.list.length,this.list.push(t)},t.prototype.remove=function(t){var e=this.list.length-1,r=this.list[e];this.list.length=e,t!==r&&(this.list[t.blockInd]=r,r.blockInd=t.blockInd)},t.prototype.merge=function(t){var e=t.left.block,r=t.right.block,n=t.right.offset-t.left.offset-t.gap;e.vars.lengths;++s){var u=n[s];if(!u.unsatisfiable){var a=u.slack();if((u.equality||e>a)&&(e=a,r=u,o=s,u.equality))break}}return o!==i&&(e=0?this.inactive.push(e):this.bs.merge(e)}}},t.prototype.solve=function(){this.satisfy();for(var t=Number.MAX_VALUE,e=this.bs.cost();Math.abs(t-e)>1e-4;)this.satisfy(),t=e,e=this.bs.cost();return e},t.LAGRANGIAN_TOLERANCE=-1e-4,t.ZERO_UPPERBOUND=-1e-10,t}();r.Solver=a,t.exports=r},function(t,e,r){"use strict";function n(t){this.options=c.extend({layerGap:60,nodeHeight:10,direction:"down"},t)}function i(t){return"L "+t.join(" ")}function o(t){return"M "+t.join(" ")}function s(t,e,r){return"C "+t.join(" ")+" "+e.join(" ")+" "+r.join(" ")}function u(t,e){var r=(t[1]+e[1])/2;return s([t[0],r],[e[0],r],e)}function a(t,e){var r=(t[0]+e[0])/2;return s([r,t[1]],[r,e[1]],e)}var c=r(4);n.lineTo=i,n.moveTo=o,n.curveTo=s,n.vCurveBetween=u,n.hCurveBetween=a,n.prototype.getWaypoints=function(t){var e=this.options,r=e.direction,n=t.getPathFromRoot(),i=e.nodeHeight+e.layerGap;return"left"===r?[[[0,n[0].idealPos]]].concat(n.map(function(t,r){var n=i*(r+1)*-1;return[[n+e.nodeHeight,t.currentPos],[n,t.currentPos]]})):"right"===r?[[[0,n[0].idealPos]]].concat(n.map(function(t,r){var n=i*(r+1);return[[n-e.nodeHeight,t.currentPos],[n,t.currentPos]]})):"up"===r?[[[n[0].idealPos,0]]].concat(n.map(function(t,r){var n=i*(r+1)*-1;return[[t.currentPos,n+e.nodeHeight],[t.currentPos,n]]})):[[[n[0].idealPos,0]]].concat(n.map(function(t,r){var n=i*(r+1);return[[t.currentPos,n-e.nodeHeight],[t.currentPos,n]]}))},n.prototype.layout=function(t){var e=this.options,r=e.layerGap+e.nodeHeight;switch(e.direction){case"left":t.forEach(function(t){var n=t.getLayerIndex()*r+e.layerGap;t.x=-n-e.nodeHeight,t.y=t.currentPos,t.dx=e.nodeHeight,t.dy=t.width});break;case"right":t.forEach(function(t){var n=t.getLayerIndex()*r+e.layerGap;t.x=n,t.y=t.currentPos,t.dx=e.nodeHeight,t.dy=t.width});break;case"up":t.forEach(function(t){var n=t.getLayerIndex()*r+e.layerGap;t.x=t.currentPos,t.y=-n-e.nodeHeight,t.dx=t.width,t.dy=e.nodeHeight});break;default:case"down":t.forEach(function(t){var n=t.getLayerIndex()*r+e.layerGap;t.x=t.currentPos,t.y=n,t.dx=t.width,t.dy=e.nodeHeight})}return t},n.prototype.generatePath=function(t){var e=this.options,r=e.direction,n=this.getWaypoints(t,r),s=[o(n[0][0])];return"left"===r||"right"===r?n.reduce(function(t,e,r){return s.push(a(t[t.length-1],e[0])),r=this.currentPos-e&&t<=this.currentPos+e}},{key:"positionBefore",value:function(t){var e=arguments.length<=1||void 0===arguments[1]?0:arguments[1];return t.currentLeft()-this.width/2-e}},{key:"positionAfter",value:function(t){var e=arguments.length<=1||void 0===arguments[1]?0:arguments[1];return t.currentRight()+this.width/2+e}},{key:"currentRight",value:function(){return this.currentPos+this.width/2}},{key:"currentLeft",value:function(){return this.currentPos-this.width/2}},{key:"idealRight",value:function(){return this.idealPos+this.width/2}},{key:"idealLeft",value:function(){return this.idealPos-this.width/2}},{key:"createStub",value:function(e){var r=new t(this.idealPos,e,this.data);return r.currentPos=this.currentPos,r.child=this,this.parent=r,r}},{key:"removeStub",value:function(){return this.parent&&(this.parent.child=null,this.parent=null),this}},{key:"isStub",value:function(){return!!this.child}},{key:"getPathToRoot",value:function(){for(var t=[],e=this;e;)t.push(e),e=e.parent;return t}},{key:"getPathFromRoot",value:function(){return this.getPathToRoot().reverse()}},{key:"getPathToRootLength",value:function(){for(var t=0,e=this;e;){var r=e.parent?e.parent.currentPos:e.idealPos;t+=Math.abs(e.currentPos-r),e=e.parent}return t}},{key:"getRoot",value:function(){for(var t=this,e=this;e;)t=e,e=e.parent;return t}},{key:"getLayerIndex",value:function(){return this.layerIndex}},{key:"clone",value:function(){var e=new t(this.idealPos,this.width,this.data);return e.currentPos=this.currentPos,e.layerIndex=this.layerIndex,e}}]),t}();t.exports=i},function(t,e,r){"use strict";var n=r(3),i=r(4),o=r(8),s={nodeSpacing:3,minPos:0,maxPos:null,algorithm:"overlap",removeOverlap:!0,density:.85,stubWidth:1},u=function(t){var e={},r=i.extend({},s),u=new n,a=[],c=null;return e.nodes=function(t){return arguments.length?(a=t,c=[t],e):a},e.getLayers=function(){return c},e.options=function(t){if(!arguments.length)return r;r=i.extend(r,t);var o=i.pick(r,Object.keys(n.DEFAULT_OPTIONS));return i.isDefined(r.minPos)&&i.isDefined(r.maxPos)?o.layerWidth=r.maxPos-r.minPos:o.layerWidth=null,u.options(o),e},e.options(t),e.compute=function(){var t=i.pick(r,Object.keys(o.DEFAULT_OPTIONS));return a.forEach(function(t){t.removeStub()}),c=u.distribute(a),c.map(function(e,n){e.forEach(function(t){t.layerIndex=n}),r.removeOverlap&&o(e,t)}),e},e.start=function(){console.log("[warning] force.start() is deprecated. Please use force.compute() instead.")},e};u.DEFAULT_OPTIONS=s,t.exports=u},function(t,e,r){"use strict";var n=r(4),i=r(6),o={algorithm:"overlap",layerWidth:1e3,density:.75,nodeSpacing:3,stubWidth:1},s=function(t){var e={};t=n.extend({},o,t),e.options=function(r){return arguments.length?(t=n.extend(t,r),e):t},e.computeRequiredWidth=function(e){return n.sum(e,function(e){return e.width+t.nodeSpacing})-t.nodeSpacing},e.maxWidthPerLayer=function(){return t.density*t.layerWidth},e.needToSplit=function(t){return e.estimateRequiredLayers(t)>1},e.estimateRequiredLayers=function(r){return t.layerWidth?Math.ceil(e.computeRequiredWidth(r)/e.maxWidthPerLayer()):1};var r={simple:function(r){for(var n=e.estimateRequiredLayers(r),i=[],o=0;n>o;o++)i.push([]);return r.forEach(function(e,r){var o=r%n;i[o].push(e);for(var s=e,u=o-1;u>=0;u--)s=s.createStub(t.stubWidth),i[u].push(s)}),i},roundRobin:function(t){var e=[];return e},overlap:function(r){for(var n=[],i=e.maxWidthPerLayer(),o=r.concat(),s=e.computeRequiredWidth(o);s>i;){e.countIdealOverlaps(o);var u=o.concat(),a=s;for(o=[];u.length>2&&a>i;){u.sort(function(t,e){return e.overlapCount-t.overlapCount});var c=u.shift();a-=c.width,a+=t.stubWidth,c.overlaps.forEach(function(t){t.overlapCount--}),o.push(c)}n.push(u),s=e.computeRequiredWidth(o)}o.length>0&&n.push(o);for(var h=n.length-1;h>=1;h--)for(var l=n[h],f=0;f=0;v--)d=d.createStub(t.stubWidth),n[v].push(d)}return n}};return e.countIdealOverlaps=function(e){var r=new i(t.layerWidth/2);return e.forEach(function(t){r.add([t.idealLeft(),t.idealRight(),t])}),e.forEach(function(t){var e=r.search(t.idealLeft(),t.idealRight());t.overlaps=e.map(function(t){return t.data[2]}),t.overlapCount=e.length}),e},e.distribute=function(i){if(!i||0===i.length)return[];if("none"==t.algorithm||!n.isDefined(t.algorithm))return[i];if(!e.needToSplit(i))return[i];if(i=i.concat().sort(function(t,e){return t.idealPos-e.idealPos}),"function"==typeof t.algorithm)return t.algorithm(i,t);if(r.hasOwnProperty(t.algorithm))return r[t.algorithm](i);throw"Unknown algorithm: "+t.algorithm},e};s.DEFAULT_OPTIONS=o,t.exports=s},function(t,e,r){"use strict";var n={isDefined:function(t){return null!==t&&void 0!==t},last:function(t){return t.length>0?t[t.length-1]:null},pick:function(t,e){return e.reduce(function(e,r){return e[r]=t[r],e},{})},sum:function(t,e){return t.map(e).reduce(function(t,e){return t+e},0)},functor:function(t){return"function"==typeof t?t:function(){return t}}};n.extend=r(5),t.exports=n},function(t,e){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol?"symbol":typeof t},n=Object.prototype.hasOwnProperty,i=Object.prototype.toString,o=function(t){return"function"==typeof Array.isArray?Array.isArray(t):"[object Array]"===i.call(t)},s=function(t){if(!t||"[object Object]"!==i.call(t))return!1;var e=n.call(t,"constructor"),r=t.constructor&&t.constructor.prototype&&n.call(t.constructor.prototype,"isPrototypeOf");if(t.constructor&&!e&&!r)return!1;var o;for(o in t);return void 0===o||n.call(t,o)};t.exports=function u(){var t,e,n,i,a,c,h=arguments[0],l=1,f=arguments.length,p=!1;for("boolean"==typeof h?(p=h,h=arguments[1]||{},l=2):("object"!==("undefined"==typeof h?"undefined":r(h))&&"function"!=typeof h||null==h)&&(h={});f>l;++l)if(t=arguments[l],null!=t)for(e in t)n=h[e],i=t[e],h!==i&&(p&&i&&(s(i)||(a=o(i)))?(a?(a=!1,c=n&&o(n)?n:[]):c=n&&s(n)?n:{},h[e]=u(p,c,i)):void 0!==i&&(h[e]=i));return h}},function(t,e,r){"use strict";function n(t,e){if(e||(e={}),this.startKey=e.startKey||0,this.endKey=e.endKey||1,this.intervalHash={},this.pointTree=new c({compare:function(t,e){if(null==t)return-1;if(null==e)return 1;var r=t[0]-e[0];return r>0?1:0==r?0:-1}}),this._autoIncrement=0,!t||"number"!=typeof t)throw new Error("you must specify center index as the 2nd argument.");this.root=new u(t,this)}function i(t,e){return e.end>1,this)),i.call(this,t.left,e)):t.idx>1,this)),i.call(this,t.right,e)):t.insert(e)}function o(t,e,r){return t?et.idx?(t.ends.every(function(t){var n=t.end>=e;return n&&r.push(t.result()),n}),o.call(this,t.right,e,r)):void t.starts.map(function(t){r.push(t.result())}):void 0}function s(t,e,r){if(0>=e-t)throw new Error("end must be greater than start. start: "+t+", end: "+e);var n={},i=[];o.call(this,this.root,t+e>>1,i,!0),i.forEach(function(t){n[t.id]=!0});for(var s=this.pointTree.bsearch([t,null]),u=this.pointTree;s>=0&&u[s][0]==t;)s--;var a=this.pointTree.bsearch([e,null]);if(a>=0){for(var c=u.length-1;c>=a&&u[a][0]<=e;)a++;u.slice(s+1,a).forEach(function(t){var e=t[1];n[e]=!0},this),Object.keys(n).forEach(function(n){var i=this.intervalHash[n];r.push(i.result(t,e))},this)}}function u(t){this.idx=t,this.starts=new c({compare:function(t,e){if(null==t)return-1;if(null==e)return 1;var r=t.start-e.start;return r>0?1:0==r?0:-1}}),this.ends=new c({compare:function(t,e){if(null==t)return-1;if(null==e)return 1;var r=t.end-e.end;return 0>r?1:0==r?0:-1}})}function a(t,e,r,n){if(this.id=e,this.start=t[r],this.end=t[n],this.data=t,"number"!=typeof this.start||"number"!=typeof this.end)throw new Error("start, end must be number. start: "+this.start+", end: "+this.end);if(this.start>=this.end)throw new Error("start must be smaller than end. start: "+this.start+", end: "+this.end)}var c=r(7);n.prototype.add=function(t,e){if(this.intervalHash[e])throw new Error("id "+e+" is already registered.");if(void 0==e){for(;this.intervalHash[this._autoIncrement];)this._autoIncrement++;e=this._autoIncrement}var r=new a(t,e,this.startKey,this.endKey);this.pointTree.insert([r.start,e]),this.pointTree.insert([r.end,e]),this.intervalHash[e]=r,this._autoIncrement++,i.call(this,this.root,r)},n.prototype.search=function(t,e){var r=[];if("number"!=typeof t)throw new Error(t+": invalid input");if(void 0==e)o.call(this,this.root,t,r);else{if("number"!=typeof e)throw new Error(t+","+e+": invalid input");s.call(this,t,e,r)}return r},n.prototype.remove=function(t){},u.prototype.insert=function(t){this.starts.insert(t),this.ends.insert(t)},a.prototype.result=function(t,e){var r={id:this.id,data:this.data};if("number"==typeof t&&"number"==typeof e){var n=Math.max(this.start,t),i=Math.min(this.end,e),o=i-n;r.rate1=o/(e-t),r.rate2=o/(this.end-this.start)}return r},t.exports=n},function(t,e){"use strict";var r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol?"symbol":typeof t},n=function i(){var t=null,e={},n=arguments;["0","1"].forEach(function(i){var o=n[i];Array.isArray(o)?t=o:o&&"object"==("undefined"==typeof o?"undefined":r(o))&&(e=o)}),"function"==typeof e.filter&&(this._filter=e.filter),"function"==typeof e.compare?this._compare=e.compare:"string"==typeof e.compare&&i.compares[e.compare]&&(this._compare=i.compares[e.compare]),this._unique=!!e.unique,e.resume&&t?t.forEach(function(t,e){this.push(t)},this):t&&this.insert.apply(this,t)};n.create=function(t,e){return new n(t,e)},n.prototype=new Array,n.prototype.constructor=Array.prototype.constructor,n.prototype.insertOne=function(t){var e=this.bsearch(t);return this._unique&&null!=this.key(t,e)?!1:this._filter(t,e)?(this.splice(e+1,0,t),e+1):!1},n.prototype.insert=function(){return Array.prototype.map.call(arguments,function(t){return this.insertOne(t)},this)},n.prototype.remove=function(t){return this.splice(t,1),this},n.prototype.bsearch=function(t){if(!this.length)return-1;for(var e,r=0,n=this.length;n-r>1;){e=Math.floor((r+n)/2);var i=this[e],o=this._compare(t,i);if(0==o)return e;o>0?r=e:n=e}return 0==r&&this._compare(this[0],t)>0?-1:r},n.prototype.key=function(t,e){null==e&&(e=this.bsearch(t));var r=e;if(-1==r||this._compare(this[r],t)<0)return r+1=1&&0==this._compare(this[r-1],t);)r--;return r},n.prototype.keys=function(t,e){var r=[];null==e&&(e=this.bsearch(t));for(var n=e;n>=0&&0==this._compare(this[n],t);)r.push(n),n--;var i=this.length;for(n=e+1;i>n&&0==this._compare(this[n],t);)r.push(n),n++;return r.length?r:null},n.prototype.unique=function(t){if(t)return this.filter(function(t,e){return 0==e||0!=this._compare(this[e-1],t)},this);var e=0;return this.map(function(t,r){return 0==r||0!=this._compare(this[r-1],t)?null:r-e++},this).forEach(function(t){null!=t&&this.remove(t)},this),this},n.prototype.toArray=function(){return this.slice()},n.prototype._filter=function(t,e){return!0},n.compares={number:function(t,e){var r=t-e;return r>0?1:0==r?0:-1},string:function(t,e){return t>e?1:t==e?0:-1}},n.prototype._compare=n.compares.string,t.exports=n},function(t,e,r){"use strict";function n(t){var e=new s.Variable(t.targetPos);return e.node=t,e}function i(t,e){if(t.length>0){e=o.extend(u,e),t.forEach(function(t,e){t.targetPos=t.parent?t.parent.currentPos:t.idealPos,t.index=e}),t.sort(function(t,e){var r=t.targetPos-e.targetPos;if(0!==r)return r;var n=t.isStub()-e.isStub();return 0!==n?n:t.index-e.index});for(var r=t.map(n),i=[],a=1;at;++t)this.ps.addVariable(this.vars[t]);this.posn=this.ps.getPosn()},t.prototype.compute_lm=function(t,e,r){var n=this,i=t.dfdv();return t.visitNeighbours(e,function(e,o){var s=n.compute_lm(o,t,r);o===e.right?(i+=s*e.left.scale,e.lm=s):(i+=s*e.right.scale,e.lm=-s),r(e)}),i/t.scale},t.prototype.populateSplitBlock=function(t,e){var r=this;t.visitNeighbours(e,function(e,n){n.offset=t.offset+(n===e.right?e.gap:-e.gap),r.addVariable(n),r.populateSplitBlock(n,t)})},t.prototype.traverse=function(t,e,r,n){var i=this;void 0===r&&(r=this.vars[0]),void 0===n&&(n=null),r.visitNeighbours(n,function(n,o){e.push(t(n)),i.traverse(t,e,o,r)})},t.prototype.findMinLM=function(){var t=null;return this.compute_lm(this.vars[0],null,function(e){!e.equality&&(null===t||e.lmn;++n){var o=t.vars[n];o.offset+=r,this.addVariable(o)}this.posn=this.ps.getPosn()},t.prototype.cost=function(){for(var t=0,e=this.vars.length;e--;){var r=this.vars[e],n=r.position()-r.desiredPosition;t+=n*n*r.weight}return t},t}();r.Block=s;var u=function(){function t(t){this.vs=t;var e=t.length;for(this.list=new Array(e);e--;){var r=new s(t[e]);this.list[e]=r,r.blockInd=e}}return t.prototype.cost=function(){for(var t=0,e=this.list.length;e--;)t+=this.list[e].cost();return t},t.prototype.insert=function(t){t.blockInd=this.list.length,this.list.push(t)},t.prototype.remove=function(t){var e=this.list.length-1,r=this.list[e];this.list.length=e,t!==r&&(this.list[t.blockInd]=r,r.blockInd=t.blockInd)},t.prototype.merge=function(t){var e=t.left.block,r=t.right.block,n=t.right.offset-t.left.offset-t.gap;e.vars.lengths;++s){var u=n[s];if(!u.unsatisfiable){var a=u.slack();if((u.equality||e>a)&&(e=a,r=u,o=s,u.equality))break}}return o!==i&&(e=0?this.inactive.push(e):this.bs.merge(e)}}},t.prototype.solve=function(){this.satisfy();for(var t=Number.MAX_VALUE,e=this.bs.cost();Math.abs(t-e)>1e-4;)this.satisfy(),t=e,e=this.bs.cost();return e},t.LAGRANGIAN_TOLERANCE=-1e-4,t.ZERO_UPPERBOUND=-1e-10,t}();r.Solver=a,t.exports=r},function(t,e,r){"use strict";function n(t){this.options=c.extend({layerGap:60,nodeHeight:h,direction:"down"},t)}function i(t){return"L "+t.join(" ")}function o(t){return"M "+t.join(" ")}function s(t,e,r){return"C "+t.join(" ")+" "+e.join(" ")+" "+r.join(" ")}function u(t,e){var r=(t[1]+e[1])/2;return s([t[0],r],[e[0],r],e)}function a(t,e){var r=(t[0]+e[0])/2;return s([r,t[1]],[r,e[1]],e)}var c=r(4),h=10;n.lineTo=i,n.moveTo=o,n.curveTo=s,n.vCurveBetween=u,n.hCurveBetween=a,n.prototype.getWaypoints=function(t){var e=this.options,r=c.functor(e.nodeHeight)(t),n=e.direction,i=t.getPathFromRoot(),o=r+e.layerGap;return"left"===n?[[[0,i[0].idealPos]]].concat(i.map(function(t,e){var n=o*(e+1)*-1;return[[n+r,t.currentPos],[n,t.currentPos]]})):"right"===n?[[[0,i[0].idealPos]]].concat(i.map(function(t,e){var n=o*(e+1);return[[n-r,t.currentPos],[n,t.currentPos]]})):"up"===n?[[[i[0].idealPos,0]]].concat(i.map(function(t,e){var n=o*(e+1)*-1;return[[t.currentPos,n+r],[t.currentPos,n]]})):[[[i[0].idealPos,0]]].concat(i.map(function(t,e){var n=o*(e+1);return[[t.currentPos,n-r],[t.currentPos,n]]}))},n.prototype.layout=function(t){var e=this.options,r=c.functor(e.nodeHeight);if("function"==typeof e.nodeHeight){var n=[];t.forEach(function(t,r){n[r]=e.layerGap+e.nodeHeight(t)})}var i=e.layerGap+e.nodeHeight;switch(e.direction){case"left":t.forEach(function(t,o){var s=0;s=n?t.getLayerIndex()*n[o]+e.layerGap:t.getLayerIndex()*i+e.layerGap,t.x=-s-r(t),t.y=t.currentPos,t.dx=r(t),t.dy=t.width});break;case"right":t.forEach(function(t,o){var s=0;s=n?t.getLayerIndex()*n[o]+e.layerGap:t.getLayerIndex()*i+e.layerGap,t.x=s,t.y=t.currentPos,t.dx=r(t),t.dy=t.width});break;case"up":t.forEach(function(t,o){var s=0;s=n?t.getLayerIndex()*n[o]+e.layerGap:t.getLayerIndex()*i+e.layerGap,t.x=t.currentPos,t.y=-s-r(t),t.dx=t.width,t.dy=r(t)});break;default:case"down":t.forEach(function(t,o){var s=0;s=n?t.getLayerIndex()*n[o]+e.layerGap:t.getLayerIndex()*i+e.layerGap,t.x=t.currentPos,t.y=s,t.dx=t.width,t.dy=r(t)})}return t},n.prototype.generatePath=function(t){var e=this.options,r=e.direction,n=this.getWaypoints(t,r),s=[o(n[0][0])];return"left"===r||"right"===r?n.reduce(function(t,e,r){return s.push(a(t[t.length-1],e[0])),rLabels should be beautiful. left | right | with text (v) | - with text (h) + with text (h) | + with flex height

Please diff --git a/examples/basic_left.html b/examples/basic_left.html index ea86c79..df73fad 100644 --- a/examples/basic_left.html +++ b/examples/basic_left.html @@ -27,7 +27,8 @@

Labels should be beautiful.

left | right | with text (v) | - with text (h) + with text (h) | + with flex height

Please diff --git a/examples/basic_right.html b/examples/basic_right.html index a6740a6..90c845f 100644 --- a/examples/basic_right.html +++ b/examples/basic_right.html @@ -27,7 +27,8 @@

Labels should be beautiful.

left | right | with text (v) | - with text (h) + with text (h) | + with flex height

Please diff --git a/examples/basic_up.html b/examples/basic_up.html index 938a002..b5a9ba0 100644 --- a/examples/basic_up.html +++ b/examples/basic_up.html @@ -27,7 +27,8 @@

Labels should be beautiful.

left | right | with text (v) | - with text (h) + with text (h) | + with flex height

Please diff --git a/examples/with_flex_height.html b/examples/with_flex_height.html new file mode 100644 index 0000000..374d154 --- /dev/null +++ b/examples/with_flex_height.html @@ -0,0 +1,212 @@ + + + + + + Labella.js + + + + + + +

+

+ + Labella.js + +

+

Labels should be beautiful.

+
+ +
+

+ See examples:   + up | + down | + left | + right | + with text (v) | + with text (h) | + with flex height +

+

You can calculate the height of each node separately based on the content you are about to show.

+

+ Please + view source + to see how it was implemented. +

+ +
+ +
+
+
+ + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/with_text.html b/examples/with_text.html index 3a9a19a..efd1a07 100644 --- a/examples/with_text.html +++ b/examples/with_text.html @@ -27,7 +27,8 @@

Labels should be beautiful.

left | right | with text (v) | - with text (h) + with text (h) | + with flex height

Please diff --git a/examples/with_text2.html b/examples/with_text2.html index d51534a..999413f 100644 --- a/examples/with_text2.html +++ b/examples/with_text2.html @@ -27,7 +27,8 @@

Labels should be beautiful.

left | right | with text (v) | - with text (h) + with text (h) | + with flex height

Please diff --git a/src/core/helper.js b/src/core/helper.js index 3bd614b..3db5e8d 100644 --- a/src/core/helper.js +++ b/src/core/helper.js @@ -16,6 +16,13 @@ const helper = { sum(array, accessor){ return array.map(accessor) .reduce(((prev, current) => prev + current), 0); + }, + functor(v) { + return typeof v === "function" + ? v + : function() { + return v; + }; } }; diff --git a/src/core/helper.spec.js b/src/core/helper.spec.js index 6032890..9d955cb 100644 --- a/src/core/helper.spec.js +++ b/src/core/helper.spec.js @@ -46,4 +46,13 @@ describe('helper', function(){ }); }); + describe('#functor(nodeHeight)', function(){ + it('should always return a function', function(){ + var result = helper.functor(10); + expect(typeof result).toEqual('function'); + var result2 = helper.functor(function(){return 10;}); + expect(typeof result2).toEqual('function'); + }); + }); + }); \ No newline at end of file diff --git a/src/core/renderer.js b/src/core/renderer.js index c53d1e0..a190ded 100644 --- a/src/core/renderer.js +++ b/src/core/renderer.js @@ -1,9 +1,11 @@ const helper = require('./helper.js'); +const DEFAULT_NODE_HEIGHT = 10; + function Renderer(options){ this.options = helper.extend({ layerGap: 60, - nodeHeight: 10, + nodeHeight: DEFAULT_NODE_HEIGHT, direction: 'down' }, options); } @@ -46,16 +48,17 @@ Renderer.hCurveBetween = hCurveBetween; Renderer.prototype.getWaypoints = function(node){ var options = this.options; + var nodeHeight = helper.functor(options.nodeHeight)(node); var direction = options.direction; var hops = node.getPathFromRoot(); - var gap = options.nodeHeight + options.layerGap; + var gap = nodeHeight + options.layerGap; if(direction==='left'){ return [[[0, hops[0].idealPos]]].concat(hops.map(function(hop, level){ var xPos = gap * (level+1) * -1; return [ - [xPos + options.nodeHeight, hop.currentPos], + [xPos + nodeHeight, hop.currentPos], [xPos, hop.currentPos] ]; })); @@ -64,7 +67,7 @@ Renderer.prototype.getWaypoints = function(node){ return [[[0, hops[0].idealPos]]].concat(hops.map(function(hop, level){ var xPos = gap * (level+1); return [ - [xPos - options.nodeHeight, hop.currentPos], + [xPos - nodeHeight, hop.currentPos], [xPos, hop.currentPos] ]; })); @@ -73,7 +76,7 @@ Renderer.prototype.getWaypoints = function(node){ return [[[hops[0].idealPos, 0]]].concat(hops.map(function(hop, level){ var yPos = gap * (level+1) * -1; return [ - [hop.currentPos, yPos + options.nodeHeight], + [hop.currentPos, yPos + nodeHeight], [hop.currentPos, yPos] ]; })); @@ -82,7 +85,7 @@ Renderer.prototype.getWaypoints = function(node){ return [[[hops[0].idealPos, 0]]].concat(hops.map(function(hop, level){ var yPos = gap * (level+1); return [ - [hop.currentPos, yPos - options.nodeHeight], + [hop.currentPos, yPos - nodeHeight], [hop.currentPos, yPos] ]; })); @@ -92,44 +95,76 @@ Renderer.prototype.getWaypoints = function(node){ Renderer.prototype.layout = function(nodes){ var options = this.options; + var nodeHeightFn = helper.functor(options.nodeHeight); + if(typeof options.nodeHeight === 'function'){ + var gaps = []; + nodes.forEach(function(node, index){ + gaps[index] = options.layerGap + options.nodeHeight(node); + }); + } + var gap = options.layerGap + options.nodeHeight; switch(options.direction){ case 'left': - nodes.forEach(function(node){ - var pos = node.getLayerIndex() * gap + options.layerGap; - node.x = -pos - options.nodeHeight; + nodes.forEach(function(node, index){ + var pos = 0; + if(gaps){ //if the nodeHeight is a function + pos = node.getLayerIndex() * gaps[index] + options.layerGap; + } + else{ + pos = node.getLayerIndex() * gap + options.layerGap; + } + node.x = -pos - nodeHeightFn(node); node.y = node.currentPos; - node.dx = options.nodeHeight; + node.dx = nodeHeightFn(node); node.dy = node.width; }); break; case 'right': - nodes.forEach(function(node){ - var pos = node.getLayerIndex() * gap + options.layerGap; + nodes.forEach(function(node, index){ + var pos = 0; + if(gaps){ //if the nodeHeight is a function + pos = node.getLayerIndex() * gaps[index] + options.layerGap; + } + else{ + pos = node.getLayerIndex() * gap + options.layerGap; + } node.x = pos; node.y = node.currentPos; - node.dx = options.nodeHeight; + node.dx = nodeHeightFn(node); node.dy = node.width; }); break; case 'up': - nodes.forEach(function(node){ - var pos = node.getLayerIndex() * gap + options.layerGap; + nodes.forEach(function(node, index){ + var pos = 0; + if(gaps){ //if the nodeHeight is a function + pos = node.getLayerIndex() * gaps[index] + options.layerGap; + } + else{ + pos = node.getLayerIndex() * gap + options.layerGap; + } node.x = node.currentPos; - node.y = -pos - options.nodeHeight; + node.y = -pos - nodeHeightFn(node); node.dx = node.width; - node.dy = options.nodeHeight; + node.dy = nodeHeightFn(node); }); break; default: case 'down': - nodes.forEach(function(node){ - var pos = node.getLayerIndex() * gap + options.layerGap; + nodes.forEach(function(node, index){ + var pos = 0; + if(gaps){ //if the nodeHeight is a function + pos = node.getLayerIndex() * gaps[index] + options.layerGap; + } + else{ + pos = node.getLayerIndex() * gap + options.layerGap; + } node.x = node.currentPos; node.y = pos; node.dx = node.width; - node.dy = options.nodeHeight; + node.dy = nodeHeightFn(node); }); break; } diff --git a/src/core/renderer.spec.js b/src/core/renderer.spec.js index c649c53..c2a7b89 100644 --- a/src/core/renderer.spec.js +++ b/src/core/renderer.spec.js @@ -39,37 +39,77 @@ describe('Renderer', function(){ var node = new Node(1,10); var stub1 = node.createStub(); stub1.currentPos = 10; - it('for left direction', function(){ - var r = new Renderer({ - layerGap: 20, - nodeHeight: 10, - direction: 'left' + describe('left direction', function(){ + it('nodeHeight as number', function(){ + var r = new Renderer({ + layerGap: 20, + nodeHeight: 10, + direction: 'left' + }); + expect(r.getWaypoints(node)).toEqual([ [ [ 0, 1 ] ], [ [ -20, 10 ], [ -30, 10 ] ], [ [ -50, 1 ], [ -60, 1 ] ] ]); + }); + it('nodeHeight as function', function(){ + var r = new Renderer({ + layerGap: 20, + nodeHeight: function(nodeData){return 10;}, + direction: 'left' + }); + expect(r.getWaypoints(node)).toEqual([ [ [ 0, 1 ] ], [ [ -20, 10 ], [ -30, 10 ] ], [ [ -50, 1 ], [ -60, 1 ] ] ]); }); - expect(r.getWaypoints(node)).toEqual([ [ [ 0, 1 ] ], [ [ -20, 10 ], [ -30, 10 ] ], [ [ -50, 1 ], [ -60, 1 ] ] ]); }); - it('for right direction', function(){ - var r = new Renderer({ - layerGap: 20, - nodeHeight: 10, - direction: 'right' + describe('right direction', function(){ + it('nodeHeight as number', function(){ + var r = new Renderer({ + layerGap: 20, + nodeHeight: 10, + direction: 'right' + }); + expect(r.getWaypoints(node)).toEqual([ [ [ 0, 1 ] ], [ [ 20, 10 ], [ 30, 10 ] ], [ [ 50, 1 ], [ 60, 1 ] ] ]); + }); + it('nodeHeight as function', function(){ + var r = new Renderer({ + layerGap: 20, + nodeHeight: function(nodeData){return 10;}, + direction: 'right' + }); + expect(r.getWaypoints(node)).toEqual([ [ [ 0, 1 ] ], [ [ 20, 10 ], [ 30, 10 ] ], [ [ 50, 1 ], [ 60, 1 ] ] ]); }); - expect(r.getWaypoints(node)).toEqual([ [ [ 0, 1 ] ], [ [ 20, 10 ], [ 30, 10 ] ], [ [ 50, 1 ], [ 60, 1 ] ] ]); }); - it('for up direction', function(){ - var r = new Renderer({ - layerGap: 20, - nodeHeight: 10, - direction: 'up' + describe('up direction', function(){ + it('nodeHeight as a number', function(){ + var r = new Renderer({ + layerGap: 20, + nodeHeight: 10, + direction: 'up' + }); + expect(r.getWaypoints(node)).toEqual([ [ [ 1, 0 ] ], [ [ 10, -20 ], [ 10, -30 ] ], [ [ 1, -50 ], [ 1, -60 ] ] ]); + }); + it('nodeHeight as a function', function(){ + var r = new Renderer({ + layerGap: 20, + nodeHeight: function(nodeData){return 10;}, + direction: 'up' + }); + expect(r.getWaypoints(node)).toEqual([ [ [ 1, 0 ] ], [ [ 10, -20 ], [ 10, -30 ] ], [ [ 1, -50 ], [ 1, -60 ] ] ]); }); - expect(r.getWaypoints(node)).toEqual([ [ [ 1, 0 ] ], [ [ 10, -20 ], [ 10, -30 ] ], [ [ 1, -50 ], [ 1, -60 ] ] ]); }); - it('for down direction', function(){ - var r = new Renderer({ - layerGap: 20, - nodeHeight: 10, - direction: 'down' + describe('down direction', function(){ + it('nodeHeight as a number', function(){ + var r = new Renderer({ + layerGap: 20, + nodeHeight: 10, + direction: 'down' + }); + expect(r.getWaypoints(node)).toEqual([ [ [ 1, 0 ] ], [ [ 10, 20 ], [ 10, 30 ] ], [ [ 1, 50 ], [ 1, 60 ] ] ]); + }); + it('nodeHeight as a function', function(){ + var r = new Renderer({ + layerGap: 20, + nodeHeight: function(nodeData){return 10;}, + direction: 'down' + }); + expect(r.getWaypoints(node)).toEqual([ [ [ 1, 0 ] ], [ [ 10, 20 ], [ 10, 30 ] ], [ [ 1, 50 ], [ 1, 60 ] ] ]); }); - expect(r.getWaypoints(node)).toEqual([ [ [ 1, 0 ] ], [ [ 10, 20 ], [ 10, 30 ] ], [ [ 1, 50 ], [ 1, 60 ] ] ]); }); }); });