/
buzzmap.min.js
9 lines (9 loc) · 10.4 KB
/
buzzmap.min.js
1
2
3
4
5
6
7
8
9
// +---------------------------------------------------------------------+ \\
// ¦ Buzzmap 2.0.0 - mindmaps with ease ¦ \\
// +---------------------------------------------------------------------¦ \\
// ¦ Copyright (c) 2011 Marcel Klehr ¦ \\
// ¦ Copyright (c) 2008-2010 Kenneth Kufluk (http://kenneth.kufluk.com) ¦ \\
// ¦ Copyright (c) 2011 Jerome Etienne (http://jetienne.com) ¦ \\
// ¦ Licensed under the MIT (X11) license. ¦ \\
// +---------------------------------------------------------------------+ \\
(function(c){function k(a,b,e){this.obj=a;this.start=b;this.end=e}var j=function(){};j.prototype={bind:function(a,b){this._events=this._events||{};this._events[a]=this._events[a]||[];this._events[a].push(b)},unbind:function(a,b){this._events=this._events||{};a in this._events!==!1&&this._events[a].splice(this._events[a].indexOf(b),1)},trigger:function(a){this._events=this._events||{};if(a in this._events!==!1)for(var b=0;b<this._events[a].length;b++)this._events[a][b].apply(this,Array.prototype.slice.call(arguments,1))}};j.mixin=function(a){for(var b=["bind","unbind","trigger"],e=0;e<b.length;e++)a.prototype[b[e]]=j.prototype[b[e]]};k.prototype.updatePosition=function(){if(this.start.visible&&this.end.visible)this.strokeStyle=this.obj.options.lineColor,this.strokeWidth=this.obj.options.lineWidth,this.strokeOpacity=this.obj.options.lineOpacity,this.obj.canvas.path("M"+this.start.x+" "+this.start.y+"L"+this.end.x+" "+this.end.y).attr({stroke:this.strokeStyle,opacity:this.strokeOpacity,"stroke-width":this.strokeWidth})};var h=function(a,b,e){var g=this;this.obj=a;this.parent=b;this.children=[];this.y=this.x=1;this.dy=this.dx=0;this.hasPosition=this.dragging=this.editing=this.visible=!1;this.el=c("<div></div>");this.el.css("position","absolute");this.el.addClass("node");this.obj.el.append(this.el);this.el.hide();this.label(e);this.parent?(this.parent.children.push(this),this.parent.parent?this.obj.lines[this.obj.lines.length]=new k(a,this,b):(this.el.addClass("active"),this.el.addClass("root"))):this.el.addClass("active");this.el.mouseup(function(){if(g.dragging==!0||g.editing==!0)return!0;if(g.obj.options.editable!==!0)return g.toggleChildren(),!0;window.setTimeout(function(){if(g.editing==!0)return!0;g.toggleChildren()},250);return!0});this.el.draggable({cancel:":input,option,button,a",start:function(){g.dragging=!0},drag:function(){g.obj.trigger("ondrag",g);g.obj.animate()},stop:function(){g.dragging=!1}});this.obj.options.editable===!0&&this.el.dblclick(function(a){g.edit();a.preventDefault()})};h.prototype.toggleChildren=function(){return this.children.length>0&&this.parent.parent?(this.el.toggleClass("active"),this.obj.animate(),!1):!0};h.prototype.label=function(a){typeof a!=="undefined"&&this.el.html(c(a));return c(":eq(0)",this.el).html()};h.prototype.serialize=function(){var a='{"label":"'+c(this.el).html().replace(/"/g,'\\"')+'","children":[',b=0;c.each(this.children,function(){b++;b>1&&(a+=",");a+=this.serialize()});return a+"]}"};h.prototype.edit=function(){var a=this;a.editing=!0;var b=a.obj.options.minSpeed;a.obj.options.minSpeed=0.35>b?0.35:b;var e=this.label();this.label("");var g=function(){a.label("<span>"+e+"</span>");a.editing=!1;a.obj.options.minSpeed=b;a.obj.animate()},f=c('<input class="edit-field" type="text" />').val(e);f.keyup(function(d){d=d.which;if(d===27)g();else if(d===13)d=f.val(),a.label("<span>"+d+"</span>"),a.obj.trigger("onchange",a,a.obj.serialize()),a.editing=!1,a.obj.options.minSpeed=b,a.obj.animate();return!0});f.appendTo(a.el).focus().select();c('<button class="edit-button">+</button>').click(function(){a.el.addClass("active");g();a.obj.addNode(a).edit();return!1}).appendTo(a.el);c('<button class="edit-button">x</button>').click(function(){g();a.removeNode();a.obj.animate();return!1}).appendTo(a.el);return!1};h.prototype.removeNode=function(){this.obj.trigger("onremove",this);for(var a=0;a<this.children.length;a++)this.children[a].removeNode();this.parent&&this.parent.children.splice(this.parent.children.indexOf(this),1);this.obj.nodes.splice(this.obj.nodes.indexOf(this),1);var b=this.obj.lines;this.obj.lines=[];for(a=0;a<b.length;a++)b[a].start===this||b[a].end===this||this.obj.lines.push(b[a]);c(this.el).remove();this.obj.trigger("onchange",this,this.obj.serialize());this.obj.animate()};h.prototype.findEquilibrium=function(){for(var a=!this.parent?!0:this.display(),b=0;b<this.children.length;b++)if(this.children[b].visible||this.el.hasClass("active"))a=this.children[b].findEquilibrium()&&a;return a};h.prototype.hide=function(){this.obj.trigger("onhide",this);this.el.removeClass("active");this.el.hide();this.hasPosition=this.visible=!1};h.prototype.show=function(){this.el.show();this.visible=!0;this.obj.trigger("onshow",this)};h.prototype.setPosition=function(a,b){this.x=a;this.y=b;this.el.css("left",a+"px");this.el.css("top",b+"px");this.hasPosition=!0};h.prototype.display=function(){this.visible?this.parent.el.hasClass("active")||this.hide():(this.parent.parent===null||this.parent.el.hasClass("active"))&&this.show();if(!this.visible)return!0;if(!this.hasPosition){if(this.parent.parent!==null)var a=parseInt(this.parent.el.css("left")),b=parseInt(this.parent.el.css("top"));else a=this.obj.width/2,b=this.obj.height/2;this.setPosition(a,b)}var e=Math.PI*2/this.children.length,g=this;c.each(this.children,function(a){if(!this.visible){var b=a*e,a=100*Math.cos(b)+g.x,b=100*Math.sin(b)+g.y;this.setPosition(a,b)}});return this.updatePosition()};h.prototype.updatePosition=function(){if(c(this.el).hasClass("ui-draggable-dragging"))return this.x=parseInt(this.el.css("left"))+c(this.el).width()/2-this.obj.offset.left,this.y=parseInt(this.el.css("top"))+c(this.el).height()/2-this.obj.offset.top,this.dy=this.dx=0,!1;var a=this.getForceVector();this.dx+=a.x*this.obj.options.acceleration;this.dy+=a.y*this.obj.options.acceleration;this.dx*=this.obj.options.damping;this.dy*=this.obj.options.damping;if(Math.abs(this.dx)<this.obj.options.minSpeed)this.dx=0;if(Math.abs(this.dy)<this.obj.options.minSpeed)this.dy=0;if(Math.abs(this.dx)+Math.abs(this.dy)==0)return!0;this.x+=this.dx*this.obj.options.acceleration;this.y+=this.dy*this.obj.options.acceleration;this.x=Math.min(this.obj.width,Math.max(1,this.x));this.y=Math.min(this.obj.height,Math.max(1,this.y));var a=this.obj.offset.left+this.x-c(this.el).width()/2,b=this.obj.offset.top+this.y-c(this.el).height()/2-10;this.el.css("left",a+"px");this.el.css("top",b+"px");return!1};h.prototype.getForceVector=function(){for(var a=0,b=0,e=this.obj.nodes,g=this.obj.lines,f=0;f<e.length;f++)if(e[f]!==this&&(!this.obj.options.showSublines||e[f].hasPosition)&&e[f].visible){var d=e[f].x-this.x,c=e[f].y-this.y,h=d/Math.abs(d);Math.abs(c);var i=Math.sqrt(d*d+c*c),c=Math.atan(c/d);d===0&&(c=Math.PI/2,h=0);d=this.obj.options.repulse*500/(i*i);Math.abs(i)<500&&(a+=-d*Math.cos(c)*h,b+=-d*Math.sin(c)*h)}f=this.x+this.el.width();d=this.obj.options.wallRepulse*500/(f*f);a+=Math.min(2,d);f=this.obj.width-f;d=-(this.obj.options.wallRepulse*500)/(f*f);a+=Math.max(-2,d);d=this.obj.options.wallRepulse*500/(this.y*this.y);b+=Math.min(2,d);f=this.obj.height-this.y;d=-(this.obj.options.wallRepulse*500)/(f*f);b+=Math.max(-2,d);for(f=0;f<g.length;f++){e=null;if(g[f].start===this)e=g[f].end;else if(g[f].end===this)e=g[f].start;else continue;e.visible&&(d=e.x-this.x,c=e.y-this.y,i=Math.sqrt(d*d+c*c),h=d/Math.abs(d),c=Math.atan(c/d),d==0&&(c=Math.PI/2,h=0),d=this.obj.options.attract*i/1E4,Math.abs(i)>0&&(a+=d*Math.cos(c)*h,b+=d*Math.sin(c)*h))}Math.abs(a)>this.obj.options.maxForce&&(a=this.obj.options.maxForce*(a/Math.abs(a)));Math.abs(b)>this.obj.options.maxForce&&(b=this.obj.options.maxForce*(b/Math.abs(b)));return{x:a,y:b}};var i=function(a,b){var e=this;this.el=c(a);this.el[0].buzzmap=this;this.el.addClass("buzzmap");this.nodes=[];this.lines=[];this.parseOptions(b);this.moveTimer=0;this.stopMovement=this.editing=this.moving=!1;this.fps=0;window.setInterval(function(){var a=e.fps*2;e.fps=0;e.trigger("fps",a)},500);c(window).resize(function(){e.animate()});this.root=this.nodes[0]=new h(this,null,"<span>Buzzmap</span>")};j.mixin(i);i.prototype.createCanvas=function(){this.height=this.el.height();this.width=this.el.width();this.canvas?this.canvas.setSize(this.width,this.height):this.canvas=Raphael(this.el[0],this.width,this.height);this.offset=this.el.css("position")=="relative"?{top:0,left:0}:this.el.offset()};i.prototype.addNode=function(a,b){var c=this.nodes[this.nodes.length]=new h(this,a,b);this.animate();return c};i.prototype.serialize=function(){return this.root.serialize()};i.prototype.animate=function(){var a=this;if(a.options.animationTimeout!=0)clearTimeout(a.moveTimer),a.moveTimer=setTimeout(function(){a.stopMovement=!0},a.options.animationTimeout*1E3);if(!a.moving)a.createCanvas(),a.moving=!0,a.stopMovement=!1,a.animateLoop()};i.prototype.animateLoop=function(){var a=this;this.canvas.clear();for(var b=0;b<this.lines.length;b++)this.lines[b].updatePosition();this.root.findEquilibrium()||this.stopMovement?this.moving=!1:window.setTimeout(function(){a.fps++;a.animateLoop()},1E3/a.options.maxFps)};i.prototype.parseOptions=function(a){this.options=c.extend({structure:null,editable:!1,onchange:function(){},ondrag:function(){},onshow:function(){},onhide:function(){},onremove:function(){},fps:function(){},attract:5,repulse:5,wallRepulse:0.5,maxForce:0.25,damping:0.9,acceleration:5,lineWidth:"5px",lineColor:"#FFF",lineOpacity:0.3,minSpeed:0.2,animationTimeout:5},a);this.bind("onchange",this.options.onchange);this.bind("ondrag",this.options.ondrag);this.bind("onshow",this.options.onshow);this.bind("onhide",this.options.onhide);this.bind("onremove",this.options.onremove);this.bind("fps",this.options.fps)};c.fn.buzzmap=function(a){var b=new i(this[0],a);if(!b.options.structure)return b;a=c(b.options.structure).filter("ul");if(a.length>0){var e=function(){var a=c(this).parents("li").get(0),a=!a?b.root:a.buzznode;this.buzznode=b.addNode(a,c("div:eq(0)",this).html());c(this).hide();c(">ul>li",this).each(e)};c(">li",a).each(e)}if(typeof b.options.structure!=="string")throw Error("Couldn`t interpret the passed structure");try{var g=JSON.parse(b.options.structure),f=function(a,d){c.each(d,function(c,d){if(d.label&&d.children){var e=b.addNode(a,decodeURI(d.label));f(e,d.children)}})};f(b.root,g.children)}catch(d){throw Error("Couldn`t interpret the passed structure");}c('<style type="text/css"></style>').text(".ui-draggable{position:absolute !important;}").appendTo("head");b.animate();return b}})(jQuery);