"editable"
Bootstrap 3.0.0 Snippet by evarevirus

<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"> <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script> <script src="//code.jquery.com/jquery-1.11.1.min.js"></script> <!------ Include the above in your HEAD tag ----------> <!DOCTYPE html><html lang='en' class=''> <head><script src='//production-assets.codepen.io/assets/editor/live/console_runner-079c09a0e3b9ff743e39ee2d5637b9216b3545af0de366d4b9aad9dc87e26bfd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/events_runner-73716630c22bbc8cff4bd0f07b135f00a0bdc5d14629260c3ec49e5606f98fdd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/css_live_reload_init-2c0dc5167d60a5af3ee189d570b1835129687ea2a61bee3513dee3a50c115a77.js'></script><meta charset='UTF-8'><meta name="robots" content="noindex"><link rel="shortcut icon" type="image/x-icon" href="//production-assets.codepen.io/assets/favicon/favicon-8ea04875e70c4b0bb41da869e81236e54394d63638a1ef12fa558a4a835f1164.ico" /><link rel="mask-icon" type="" href="//production-assets.codepen.io/assets/favicon/logo-pin-f2d2b6d2c61838f7e76325261b7195c27224080bc099486ddd6dccb469b8e8e6.svg" color="#111" /><link rel="canonical" href="https://codepen.io/yurigor/pen/vXYomB?depth=everything&order=popularity&page=4&q=editable&show_forks=false" /> <style class="cp-pen-styles">.container { background-color: black; color: #00BFFF; position: absolute; bottom: 0; left: 0; right: 0; top: 0; } .panzoom { position: absolute; width: 500px; height: 250px; background-color: rgba(0, 0, 255, 0.1); left: 50px; top: 20px; overflow: visible; border: 5px dotted rgba(204, 204, 204, 0.1); } .diagram { position: absolute; } .item { cursor: pointer; position: absolute; overflow: hidden; white-space: nowrap; border: 1px solid #004c66; padding: 8px; border-radius: 3px; background-color: rgba(0, 191, 255, 0.2); } .item:hover { border: 1px solid #00BFFF; } .jsplumb-connector path { stroke: #00BFFF; } .hint { position: absolute; color: grey; left: 100%; top: -24px; white-space: nowrap; font-size: 14px; } .hint h4 { margin-left: 15px; } .hint a { margin-left: 25px; color: red; text-decoration: none; } .hint a:hover { text-decoration: underline; } .hint li a { margin-left: 0; color: #00BFFF; } </style></head><body> <div class="container"> <div class="panzoom"> <div class="diagram"> <div id="i0" class="item">Root!</div> <div id="i1" class="item">Child 1</div> <div id="i11" class="item">Child 1.1</div> <div id="i12" class="item">Child 1.2</div> <div id="i2" class="item">Child 2</div> <div id="i21" class="item">Child 2.1</div> <div id="i3" class="item">Child 3</div> </div> <div class="hint"> <h4>Hint</h4> <ul> <li>Drag and drop empty space to pan</li> <li>Nodes are also draggable</li> <li>Mouse wheel to pan up/down</li> <li>Shift+Mouse wheel to pan left/right</li> <li>Ctrl+Mouse wheel to zoom in/out</li> </ul> <h4>Used</h4> <ul> <li><a href="https://jsplumbtoolkit.com/community/doc/home.html">jsPlumb Community Edition</a></li> <li><a href="https://github.com/timmywil/jquery.panzoom">jQuery Panzoom plugin</a><br>My <a href="https://github.com/YuriGor/jquery.panzoom/tree/ignoreChildrensEvents">branch</a> used, to avoid children's events conflict, see discussion <a href="https://github.com/timmywil/jquery.panzoom/issues/299">here</a> for details.</li> <li><a href="https://github.com/cpettitt/dagre">Dagre for initial auto-layout</a></li> <li><a href="https://jqueryui.com/draggable/">jQueryUI Draggable for dragging nodes</a></li> </ul> <a target="_blank" href="http://yurigor.com/pan-zoom-jsplumb-dagrejs-jqueryui-draggable/">See my blog for details</a> </div> </div> </div> <script src='//production-assets.codepen.io/assets/common/stopExecutionOnTimeout-b2a7b3fe212eaa732349046d8416e00a9dec26eb7fd347590fbced3ab38af52e.js'></script><script src='https://code.jquery.com/jquery-2.2.4.min.js'></script><script src='https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js'></script><script src='https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.12.0/lodash.min.js'></script><script src='https://cdnjs.cloudflare.com/ajax/libs/jsPlumb/2.0.7/jsPlumb.min.js'></script><script src='https://cdn.rawgit.com/cpettitt/dagre/e66c29b8/dist/dagre.min.js'></script><script src='https://cdn.rawgit.com/YuriGor/jquery.panzoom/ignoreChildrensEvents/dist/jquery.panzoom.min.js'></script> <script >var minScale = 0.4; var maxScale = 2; var incScale = 0.1; var plumb = null; var $container = $(".container"); $diagram = $container.find(".diagram"); var $panzoom = null; var links = [ { from: "i0", to: "i1" }, { from: "i1", to: "i11" }, { from: "i1", to: "i12" }, { from: "i0", to: "i2" }, { from: "i2", to: "i21" }, { from: "i0", to: "i3" }, ]; jsPlumb.ready(function() { plumb = jsPlumb.getInstance({ PaintStyle: { strokeWidth: 1 }, Anchors: [["Left","Right","Bottom"], ["Top","Bottom"]], Container: $diagram, }); _.each(links,function(link){ plumb.connect({ source:link.from, target:link.to, connector: [ "Flowchart", { cornerRadius: 3, stub:16 } ], endpoints:["Blank","Blank"], overlays:[["Arrow",{location:1,width:10, length:10}]], }); }); var dg = new dagre.graphlib.Graph(); dg.setGraph({nodesep:30,ranksep:30,marginx:50,marginy:50}); dg.setDefaultEdgeLabel(function() { return {}; }); $container.find(".item").each( function(idx, node) { var $n = $(node); var box = { width : Math.round($n.outerWidth()), height : Math.round($n.outerHeight()) }; dg.setNode($n.attr('id'), box); } ); plumb.getAllConnections() .forEach(function(edge) {dg.setEdge(edge.source.id,edge.target.id);}); dagre.layout(dg); var graphInfo = dg.graph(); dg.nodes().forEach( function(n) { var node = dg.node(n); var top = Math.round(node.y-node.height/2)+'px'; var left = Math.round(node.x-node.width/2)+'px'; $('#' + n).css({left:left,top:top}); }); plumb.repaintEverything(); _.defer(function(){ $panzoom = $container.find('.panzoom').panzoom({ minScale: minScale, maxScale: maxScale, increment: incScale, cursor: "", ignoreChildrensEvents:true, }).on("panzoomstart",function(e,pz,ev){ $panzoom.css("cursor","move"); }) .on("panzoomend",function(e,pz){ $panzoom.css("cursor",""); }); $panzoom.parent() .on('mousewheel.focal', function( e ) { if(e.ctrlKey||e.originalEvent.ctrlKey) { e.preventDefault(); var delta = e.delta || e.originalEvent.wheelDelta; var zoomOut = delta ? delta < 0 : e.originalEvent.deltaY > 0; $panzoom.panzoom('zoom', zoomOut, { animate: true, exponential: false, }); }else{ e.preventDefault(); var deltaY = e.deltaY || e.originalEvent.wheelDeltaY || (-e.originalEvent.deltaY); var deltaX = e.deltaX || e.originalEvent.wheelDeltaX || (-e.originalEvent.deltaX); $panzoom.panzoom("pan",deltaX/2,deltaY/2,{ animate: true, relative: true, }); } }) .on("mousedown touchstart",function(ev){ var matrix = $container.find(".panzoom").panzoom("getMatrix"); var offsetX = matrix[4]; var offsetY = matrix[5]; var dragstart = {x:ev.pageX,y:ev.pageY,dx:offsetX,dy:offsetY}; $(ev.target).css("cursor","move"); $(this).data('dragstart', dragstart); }) .on("mousemove touchmove", function(ev){ var dragstart = $(this).data('dragstart'); if(dragstart) { var deltaX = dragstart.x-ev.pageX; var deltaY = dragstart.y-ev.pageY; var matrix = $container.find(".panzoom").panzoom("getMatrix"); matrix[4] = parseInt(dragstart.dx)-deltaX; matrix[5] = parseInt(dragstart.dy)-deltaY; $container.find(".panzoom").panzoom("setMatrix",matrix); } }) .on("mouseup touchend touchcancel", function(ev){ $(this).data('dragstart',null); $(ev.target).css("cursor",""); }); }); var currentScale = 1; $container.find(".diagram .item").draggable({ start: function(e){ var pz = $container.find(".panzoom"); currentScale = pz.panzoom("getMatrix")[0]; $(this).css("cursor","move"); pz.panzoom("disable"); }, drag:function(e,ui){ ui.position.left = ui.position.left/currentScale; ui.position.top = ui.position.top/currentScale; if($(this).hasClass("jsplumb-connected")) { plumb.repaint($(this).attr('id'),ui.position); } }, stop: function(e,ui){ var nodeId = $(this).attr('id'); if($(this).hasClass("jsplumb-connected")) { plumb.repaint(nodeId,ui.position); } $(this).css("cursor",""); $container.find(".panzoom").panzoom("enable"); } }); }); //# sourceURL=pen.js </script> </body></html>

Related: See More


Questions / Comments: