Skip to content

Instantly share code, notes, and snippets.

@ariutta
Last active August 29, 2015 13:56
Show Gist options
  • Select an option

  • Save ariutta/9257167 to your computer and use it in GitHub Desktop.

Select an option

Save ariutta/9257167 to your computer and use it in GitHub Desktop.
d3-drag-examples
.jsondiffpatch-annotated-delta {
font-family: 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', Monaco, Courier, monospace;
font-size: 12px;
margin: 0;
padding: 0 0 0 12px;
display: inline-block;
}
.jsondiffpatch-annotated-delta pre {
font-family: 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', Monaco, Courier, monospace;
font-size: 12px;
margin: 0;
padding: 0;
display: inline-block;
}
.jsondiffpatch-annotated-delta td {
margin: 0;
padding: 0;
}
.jsondiffpatch-annotated-delta td pre:hover {
font-weight: bold;
}
td.jsondiffpatch-delta-note {
font-style: italic;
padding-left: 10px;
}
.jsondiffpatch-delta-note > div {
margin: 0;
padding: 0;
}
.jsondiffpatch-delta-note pre {
font-style: normal;
}
.jsondiffpatch-annotated-delta .jsondiffpatch-delta-note {
color: #777;
}
.jsondiffpatch-annotated-delta tr:hover {
background: #ffc;
}
.jsondiffpatch-annotated-delta tr:hover > td.jsondiffpatch-delta-note {
color: black;
}
.jsondiffpatch-error {
background: red;
color: white;
font-weight: bold;
}
!function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var t;"undefined"!=typeof window?t=window:"undefined"!=typeof global?t=global:"undefined"!=typeof self&&(t=self),t.jsondiffpatch=e()}}(function(){return function e(t,r,i){function n(s,f){if(!r[s]){if(!t[s]){var l="function"==typeof require&&require;if(!f&&l)return l(s,!0);if(o)return o(s,!0);throw new Error("Cannot find module '"+s+"'")}var a=r[s]={exports:{}};t[s][0].call(a.exports,function(e){var r=t[s][1][e];return n(r?r:e)},a,a.exports,e,t,r,i)}return r[s].exports}for(var o="function"==typeof require&&require,s=0;s<i.length;s++)n(i[s]);return n}({1:[function(e,t){var r=t.exports={};r.nextTick=function(){var e="undefined"!=typeof window&&window.setImmediate,t="undefined"!=typeof window&&window.postMessage&&window.addEventListener;if(e)return function(e){return window.setImmediate(e)};if(t){var r=[];return window.addEventListener("message",function(e){var t=e.source;if((t===window||null===t)&&"process-tick"===e.data&&(e.stopPropagation(),r.length>0)){var i=r.shift();i()}},!0),function(e){r.push(e),window.postMessage("process-tick","*")}}return function(e){setTimeout(e,0)}}(),r.title="browser",r.browser=!0,r.env={},r.argv=[],r.binding=function(){throw new Error("process.binding is not supported")},r.cwd=function(){return"/"},r.chdir=function(){throw new Error("process.chdir is not supported")}},{}],2:[function(e,t,r){var i=e("../pipe").Pipe,n=function(){};n.prototype.setResult=function(e){return this.result=e,this.hasResult=!0,this},n.prototype.exit=function(){return this.exiting=!0,this},n.prototype.switchTo=function(e,t){return"string"==typeof e||e instanceof i?this.nextPipe=e:(this.next=e,t&&(this.nextPipe=t)),this},n.prototype.push=function(e,t){return e.parent=this,"undefined"!=typeof t&&(e.childName=t),e.root=this.root||this,e.options=e.options||this.options,this.children?(this.children[this.children.length-1].next=e,this.children.push(e)):(this.children=[e],this.nextAfterChildren=this.next||null,this.next=e),e.next=this,this},r.Context=n},{"../pipe":15}],3:[function(e,t,r){var i=e("./context").Context,n=function(e,t){this.left=e,this.right=t,this.pipe="diff"};n.prototype=new i,r.DiffContext=n},{"./context":2}],4:[function(e,t,r){var i=e("./context").Context,n=function(e,t){this.left=e,this.delta=t,this.pipe="patch"};n.prototype=new i,r.PatchContext=n},{"./context":2}],5:[function(e,t,r){var i=e("./context").Context,n=function(e){this.delta=e,this.pipe="reverse"};n.prototype=new i,r.ReverseContext=n},{"./context":2}],6:[function(e,t){t.exports=function(e,t){var r;return"string"==typeof t&&(r=/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)(Z|([+\-])(\d{2}):(\d{2}))$/.exec(t))?new Date(Date.UTC(+r[1],+r[2]-1,+r[3],+r[4],+r[5],+r[6])):t}},{}],7:[function(e,t,r){var i=e("./processor").Processor,n=e("./pipe").Pipe,o=e("./contexts/diff").DiffContext,s=e("./contexts/patch").PatchContext,f=e("./contexts/reverse").ReverseContext,l=e("./filters/trivial"),a=e("./filters/nested"),c=e("./filters/arrays"),u=e("./filters/dates"),h=e("./filters/texts"),p=function(e){this.processor=new i(e),this.processor.pipe(new n("diff").append(a.collectChildrenDiffFilter,l.diffFilter,u.diffFilter,h.diffFilter,a.objectsDiffFilter,c.diffFilter).shouldHaveResult()),this.processor.pipe(new n("patch").append(a.collectChildrenPatchFilter,c.collectChildrenPatchFilter,l.patchFilter,h.patchFilter,a.patchFilter,c.patchFilter).shouldHaveResult()),this.processor.pipe(new n("reverse").append(a.collectChildrenReverseFilter,c.collectChildrenReverseFilter,l.reverseFilter,h.reverseFilter,a.reverseFilter,c.reverseFilter).shouldHaveResult())};p.prototype.options=function(){return this.processor.options.apply(this.processor,arguments)},p.prototype.diff=function(e,t){return this.processor.process(new o(e,t))},p.prototype.patch=function(e,t){return this.processor.process(new s(e,t))},p.prototype.reverse=function(e){return this.processor.process(new f(e))},p.prototype.unpatch=function(e,t){return this.patch(e,this.reverse(t))},r.DiffPatcher=p},{"./contexts/diff":3,"./contexts/patch":4,"./contexts/reverse":5,"./filters/arrays":9,"./filters/dates":10,"./filters/nested":12,"./filters/texts":13,"./filters/trivial":14,"./pipe":15,"./processor":16}],8:[function(e,t,r){(function(t){var i=e("./diffpatcher").DiffPatcher;r.DiffPatcher=i,r.create=function(e){return new i(e)},r.dateReviver=e("./date-reviver");var n;r.diff=function(){return n||(n=new i),n.diff.apply(n,arguments)},r.patch=function(){return n||(n=new i),n.patch.apply(n,arguments)},r.unpatch=function(){return n||(n=new i),n.unpatch.apply(n,arguments)},r.reverse=function(){return n||(n=new i),n.reverse.apply(n,arguments)};var o="undefined"!=typeof t&&"string"==typeof t.execPath;if(o){var s=e("./formatters/index");r.formatters=s,r.console=s.console}else r.homepage="https://github.com/benjamine/jsondiffpatch",r.version="0.1.4"}).call(this,e("/home/sheila/proj/JsonDiffPatch/node_modules/gulp-browserify/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))},{"./date-reviver":6,"./diffpatcher":7,"/home/sheila/proj/JsonDiffPatch/node_modules/gulp-browserify/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":1}],9:[function(e,t,r){var i=e("../contexts/diff").DiffContext,n=e("../contexts/patch").PatchContext,o=e("../contexts/reverse").ReverseContext,s=e("./lcs"),f=3,l="function"==typeof Array.isArray?Array.isArray:function(e){return e instanceof Array},a="function"==typeof Array.prototype.indexOf?function(e,t){return e.indexOf(t)}:function(e,t){for(var r=e.length,i=0;r>i;i++)if(e[i]===t)return i;return-1},c=function(e){if(e.leftIsArray){for(var t,r,n,o,l=e.options&&e.options.objectHash,c=function(e,t,r,i,n){var o=e[r],s=t[i];if(o===s)return!0;if("object"!=typeof o||"object"!=typeof s)return!1;if(!l)return!1;var f,a;return"number"==typeof r?(n.hashCache1=n.hashCache1||[],f=n.hashCache1[r],"undefined"==typeof f&&(n.hashCache1[r]=f=l(o,r))):f=l(o),"undefined"==typeof f?!1:("number"==typeof i?(n.hashCache2=n.hashCache2||[],a=n.hashCache2[i],"undefined"==typeof a&&(n.hashCache2[i]=a=l(s,i))):a=l(s),"undefined"==typeof a?!1:f===a)},u={},h=0,p=0,d=e.left,v=e.right,y=d.length,x=v.length;y>h&&x>h&&c(d,v,h,h,u);)t=h,o=new i(e.left[t],e.right[t]),e.push(o,t),h++;for(;y>p+h&&x>p+h&&c(d,v,y-1-p,x-1-p,u);)r=y-1-p,n=x-1-p,o=new i(e.left[r],e.right[n]),e.push(o,n),p++;var g;if(h+p===y){if(y===x)return void e.setResult(void 0).exit();for(g=g||{_t:"a"},t=h;x-p>t;t++)g[t]=[v[t]];return void e.setResult(g).exit()}if(h+p===x){for(g=g||{_t:"a"},t=h;y-p>t;t++)g["_"+t]=[d[t],0,0];return void e.setResult(g).exit()}u={};var m=d.slice(h,y-p),w=v.slice(h,x-p),C=s.get(m,w,c,u),_=[];for(g=g||{_t:"a"},t=h;y-p>t;t++)a(C.indices1,t-h)<0&&(g["_"+t]=[d[t],0,0],_.push(t));var R=!0;e.options&&e.options.arrays&&e.options.arrays.detectMove===!1&&(R=!1);var b=!1;e.options&&e.options.arrays&&e.options.arrays.includeValueOnMove&&(b=!0);var F=_.length;for(t=h;x-p>t;t++){var N=a(C.indices2,t-h);if(0>N){var A=!1;if(R&&F>0)for(r=0;F>r;r++)if(c(m,w,_[r]-h,t-h,u)){g["_"+_[r]].splice(1,2,t,f),b||(g["_"+_[r]][0]=""),r=_[r],n=t,o=new i(e.left[r],e.right[n]),e.push(o,n),_.splice(r,1),A=!0;break}A||(g[t]=[v[t]])}else r=C.indices1[N]+h,n=C.indices2[N]+h,o=new i(e.left[r],e.right[n]),e.push(o,n)}e.setResult(g).exit()}};c.filterName="arrays";var u={numerically:function(e,t){return e-t},numericallyBy:function(e){return function(t,r){return t[e]-r[e]}}},h=function(e){if(e.nested&&"a"===e.delta._t){var t,r,i=e.delta,o=e.left,s=[],l=[],a=[];for(t in i)if("_t"!==t)if("_"===t[0]){if(0!==i[t][2]&&i[t][2]!==f)throw new Error("only removal or move can be applied at original array indices, invalid diff type: "+i[t][2]);s.push(parseInt(t.slice(1),10))}else 1===i[t].length?l.push({index:parseInt(t,10),value:i[t][0]}):a.push({index:parseInt(t,10),delta:i[t]});for(s=s.sort(u.numerically),t=s.length-1;t>=0;t--){r=s[t];var c=i["_"+r],h=o.splice(r,1)[0];c[2]===f&&l.push({index:c[1],value:h})}l=l.sort(u.numericallyBy("index"));var p=l.length;for(t=0;p>t;t++){var d=l[t];o.splice(d.index,0,d.value)}var v,y=a.length;if(y>0)for(t=0;y>t;t++){var x=a[t];v=new n(e.left[x.index],x.delta),e.push(v,x.index)}return e.children?void e.exit():void e.setResult(e.left).exit()}};h.filterName="arrays";var p=function(e){if(e&&e.children&&"a"===e.delta._t){for(var t,r=e.children.length,i=0;r>i;i++)t=e.children[i],e.left[t.childName]=t.result;e.setResult(e.left).exit()}};p.filterName="arraysCollectChildren";var d=function(e){if(!e.nested)return void(e.delta[2]===f&&(e.newName="_"+e.delta[1],e.setResult([e.delta[0],parseInt(e.childName.substr(1),10),f]).exit()));if("a"===e.delta._t){var t,r;for(t in e.delta)"_t"!==t&&(r=new o(e.delta[t]),e.push(r,t));e.exit()}};d.filterName="arrays";var v=function(e,t,r){var i=t;if("string"==typeof t&&"_"===t[0])i=parseInt(t.substr(1),10);else{var n="_"+t;if(l(r)&&0===r[2])i=n;else for(var o in e){var s=e[o];l(s)&&s[2]===f&&s[1].toString()===t&&(i=o.substr(1))}}return i},y=function(e){if(e&&e.children&&"a"===e.delta._t){for(var t,r=e.children.length,i={_t:"a"},n=0;r>n;n++){t=e.children[n];var o=t.newName;"undefined"==typeof o&&(o=v(e.delta,t.childName,t.result)),i[o]!==t.result&&(i[o]=t.result)}e.setResult(i).exit()}};y.filterName="arraysCollectChildren",r.diffFilter=c,r.patchFilter=h,r.collectChildrenPatchFilter=p,r.reverseFilter=d,r.collectChildrenReverseFilter=y},{"../contexts/diff":3,"../contexts/patch":4,"../contexts/reverse":5,"./lcs":11}],10:[function(e,t,r){var i=function(e){e.left instanceof Date?(e.setResult(e.right instanceof Date?e.left.getTime()!==e.right.getTime()?[e.left,e.right]:void 0:[e.left,e.right]),e.exit()):e.right instanceof Date&&e.setResult([e.left,e.right]).exit()};i.filterName="dates",r.diffFilter=i},{}],11:[function(e,t,r){var i=function(e,t,r,i){return e[r]===t[i]},n=function(e,t,r,i){var n,o,s=e.length,f=t.length,l=[s+1];for(n=0;s+1>n;n++)for(l[n]=[f+1],o=0;f+1>o;o++)l[n][o]=0;for(l.match=r,n=1;s+1>n;n++)for(o=1;f+1>o;o++)l[n][o]=r(e,t,n-1,o-1,i)?l[n-1][o-1]+1:Math.max(l[n-1][o],l[n][o-1]);return l},o=function(e,t,r,i,n,s){if(0===i||0===n)return{sequence:[],indices1:[],indices2:[]};if(e.match(t,r,i-1,n-1,s)){var f=o(e,t,r,i-1,n-1,s);return f.sequence.push(t[i-1]),f.indices1.push(i-1),f.indices2.push(n-1),f}return e[i][n-1]>e[i-1][n]?o(e,t,r,i,n-1,s):o(e,t,r,i-1,n,s)},s=function(e,t,r,s){s=s||{};var f=n(e,t,r||i,s),l=o(f,e,t,e.length,t.length,s);return"string"==typeof e&&"string"==typeof t&&(l.sequence=l.sequence.join("")),l};r.get=s},{}],12:[function(e,t,r){var i=e("../contexts/diff").DiffContext,n=e("../contexts/patch").PatchContext,o=e("../contexts/reverse").ReverseContext,s=function(e){if(e&&e.children){for(var t,r=e.children.length,i=e.result,n=0;r>n;n++)t=e.children[n],"undefined"!=typeof t.result&&(i=i||{},i[t.childName]=t.result);i&&e.leftIsArray&&(i._t="a"),e.setResult(i).exit()}};s.filterName="collectChildren";var f=function(e){if(!e.leftIsArray&&"object"===e.leftType){var t,r;for(t in e.left)r=new i(e.left[t],e.right[t]),e.push(r,t);for(t in e.right)"undefined"==typeof e.left[t]&&(r=new i(void 0,e.right[t]),e.push(r,t));return e.children&&0!==e.children.length?void e.exit():void e.setResult(void 0).exit()}};f.filterName="objects";var l=function(e){if(e.nested&&!e.delta._t){var t,r;for(t in e.delta)r=new n(e.left[t],e.delta[t]),e.push(r,t);e.exit()}};l.filterName="objects";var a=function(e){if(e&&e.children&&!e.delta._t){for(var t,r=e.children.length,i=0;r>i;i++)t=e.children[i],e.left[t.childName]!==t.result&&(e.left[t.childName]=t.result);e.setResult(e.left).exit()}};a.filterName="collectChildren";var c=function(e){if(e.nested&&!e.delta._t){var t,r;for(t in e.delta)r=new o(e.delta[t]),e.push(r,t);e.exit()}};c.filterName="objects";var u=function(e){if(e&&e.children&&!e.delta._t){for(var t,r=e.children.length,i={},n=0;r>n;n++)t=e.children[n],i[t.childName]!==t.result&&(i[t.childName]=t.result);e.setResult(i).exit()}};u.filterName="collectChildren",r.collectChildrenDiffFilter=s,r.objectsDiffFilter=f,r.patchFilter=l,r.collectChildrenPatchFilter=a,r.reverseFilter=c,r.collectChildrenReverseFilter=u},{"../contexts/diff":3,"../contexts/patch":4,"../contexts/reverse":5}],13:[function(e,t,r){var i=2,n=60,o=null,s=function(){if(!o){var t;if("undefined"!=typeof diff_match_patch)t=new diff_match_patch;else if("function"==typeof e){var r=e("../../external/diff_match_patch_uncompressed");t=new r.diff_match_patch}if(!t){var i=new Error("text diff_match_patch library not found");throw i.diff_match_patch_not_found=!0,i}o={diff:function(e,r){return t.patch_toText(t.patch_make(e,r))},patch:function(e,r){for(var i=t.patch_apply(t.patch_fromText(r),e),n=0;n<i[1].length;n++)if(!i[1][n]){var o=new Error("text patch failed");o.textPatchFailed=!0}return i[0]}}}return o},f=function(e){if("string"===e.leftType){var t=e.options&&e.options.textDiff&&e.options.textDiff.minLength||n;if(e.left.length<t||e.right.length<t)return void e.setResult([e.left,e.right]).exit();var r=s().diff;e.setResult([r(e.left,e.right),0,i]).exit()}};f.filterName="texts";var l=function(e){if(!e.nested&&e.delta[2]===i){var t=s().patch;e.setResult(t(e.left,e.delta[0])).exit()}};l.filterName="texts";var a=function(e){var t,r,i,n,o,s,f,l,a=null,c=/^@@ +\-(\d+),(\d+) +\+(\d+),(\d+) +@@$/;for(i=e.split("\n"),t=0,r=i.length;r>t;t++){n=i[t];var u=n.slice(0,1);"@"===u?(a=c.exec(n),s=t,f=null,l=null,i[s]="@@ -"+a[3]+","+a[4]+" +"+a[1]+","+a[2]+" @@"):"+"===u?(f=t,i[t]="-"+i[t].slice(1),"+"===i[t-1].slice(0,1)&&(o=i[t],i[t]=i[t-1],i[t-1]=o)):"-"===u&&(l=t,i[t]="+"+i[t].slice(1))}return i.join("\n")},c=function(e){e.nested||e.delta[2]===i&&e.setResult([a(e.delta[0]),0,i]).exit()};c.filterName="texts",r.diffFilter=f,r.patchFilter=l,r.reverseFilter=c},{}],14:[function(e,t,r){var i="function"==typeof Array.isArray?Array.isArray:function(e){return e instanceof Array},n=function(e){if(e.left===e.right)return void e.setResult(void 0).exit();if("undefined"==typeof e.left){if("function"==typeof e.right)throw new Error("functions are not supported");return void e.setResult([e.right]).exit()}if("undefined"==typeof e.right)return void e.setResult([e.left,0,0]).exit();if("function"==typeof e.left||"function"==typeof e.right)throw new Error("functions are not supported");return e.leftType=null===e.left?"null":typeof e.left,e.rightType=null===e.right?"null":typeof e.right,e.leftType!==e.rightType?void e.setResult([e.left,e.right]).exit():"boolean"===e.leftType||"number"===e.leftType?void e.setResult([e.left,e.right]).exit():("object"===e.leftType&&(e.leftIsArray=i(e.left)),"object"===e.rightType&&(e.rightIsArray=i(e.right)),e.leftIsArray!==e.rightIsArray?void e.setResult([e.left,e.right]).exit():void 0)};n.filterName="trivial";var o=function(e){return"undefined"==typeof e.delta?void e.setResult(e.left).exit():(e.nested=!i(e.delta),e.nested?void 0:1===e.delta.length?void e.setResult(e.delta[0]).exit():2===e.delta.length?void e.setResult(e.delta[1]).exit():3===e.delta.length&&0===e.delta[2]?void e.setResult(void 0).exit():void 0)};o.filterName="trivial";var s=function(e){return"undefined"==typeof e.delta?void e.setResult(e.delta).exit():(e.nested=!i(e.delta),e.nested?void 0:1===e.delta.length?void e.setResult([e.delta[0],0,0]).exit():2===e.delta.length?void e.setResult([e.delta[1],e.delta[0]]).exit():3===e.delta.length&&0===e.delta[2]?void e.setResult([e.delta[0]]).exit():void 0)};s.filterName="trivial",r.diffFilter=n,r.patchFilter=o,r.reverseFilter=s},{}],15:[function(e,t,r){var i=function(e){this.name=e,this.filters=[]};i.prototype.process=function(e){if(!this.processor)throw new Error("add this pipe to a processor before using it");for(var t=this.debug,r=this.filters.length,i=e,n=0;r>n;n++){var o=this.filters[n];if(t&&this.log("filter: "+o.filterName),o(i),"object"==typeof i&&i.exiting){i.exiting=!1;break}}!i.next&&this.resultCheck&&this.resultCheck(i)},i.prototype.log=function(e){console.log("[jsondiffpatch] "+this.name+" pipe, "+e)},i.prototype.append=function(){return this.filters.push.apply(this.filters,arguments),this},i.prototype.prepend=function(){return this.filters.unshift.apply(this.filters,arguments),this},i.prototype.indexOf=function(e){if(!e)throw new Error("a filter name is required");for(var t=0;t<this.filters.length;t++){var r=this.filters[t];if(r.filterName===e)return t}throw new Error("filter not found: "+e)},i.prototype.list=function(){for(var e=[],t=0;t<this.filters.length;t++){var r=this.filters[t];e.push(r.filterName)}return e},i.prototype.after=function(e){var t=this.indexOf(e),r=Array.prototype.slice.call(arguments,1);if(!r.length)throw new Error("a filter is required");return r.unshift(t+1,0),Array.prototype.splice.apply(this.filters,r),this},i.prototype.before=function(e){var t=this.indexOf(e),r=Array.prototype.slice.call(arguments,1);if(!r.length)throw new Error("a filter is required");return r.unshift(t,0),Array.prototype.splice.apply(this.filters,r),this},i.prototype.clear=function(){return this.filters.length=0,this},i.prototype.shouldHaveResult=function(e){if(e===!1)return void(this.resultCheck=null);if(!this.resultCheck){var t=this;return this.resultCheck=function(e){if(!e.hasResult){console.log(e);var r=new Error(t.name+" failed");throw r.noResult=!0,r}},this}},r.Pipe=i},{}],16:[function(e,t,r){var i=function(e){this.selfOptions=e,this.pipes={}};i.prototype.options=function(e){return e&&(this.selfOptions=e),this.selfOptions},i.prototype.pipe=function(e,t){if("string"==typeof e){if("undefined"==typeof t)return this.pipes[e];this.pipes[e]=t}if(e&&e.name){if(t=e,t.processor===this)return t;this.pipes[t.name]=t}return t.processor=this,t},i.prototype.process=function(e,t){var r=e;r.options=this.options();for(var i,n,o=t||e.pipe||"default";o;)"undefined"!=typeof r.nextAfterChildren&&(r.next=r.nextAfterChildren,r.nextAfterChildren=null),"string"==typeof o&&(o=this.pipe(o)),o.process(r),n=r,i=o,o=null,r&&r.next&&(r=r.next,o=n.nextPipe||r.pipe||i);return r.hasResult?r.result:void 0},r.Processor=i},{}]},{},[8])(8)});
#!/usr/bin/env node
var util = require('util'),
http = require('http'),
fs = require('fs'),
url = require('url'),
events = require('events');
var DEFAULT_PORT = 8000;
function main(argv) {
new HttpServer({
'GET': createServlet(StaticServlet),
'HEAD': createServlet(StaticServlet)
}).start(Number(argv[2]) || DEFAULT_PORT);
}
function escapeHtml(value) {
return value.toString().
replace('<', '&lt;').
replace('>', '&gt;').
replace('"', '&quot;');
}
function createServlet(Class) {
var servlet = new Class();
return servlet.handleRequest.bind(servlet);
}
/**
* An Http server implementation that uses a map of methods to decide
* action routing.
*
* @param {Object} Map of method => Handler function
*/
function HttpServer(handlers) {
this.handlers = handlers;
this.server = http.createServer(this.handleRequest_.bind(this));
}
HttpServer.prototype.start = function(port) {
this.port = port;
this.server.listen(port);
util.puts('Http Server running at http://localhost:' + port + '/');
};
HttpServer.prototype.parseUrl_ = function(urlString) {
var parsed = url.parse(urlString);
parsed.pathname = url.resolve('/', parsed.pathname);
return url.parse(url.format(parsed), true);
};
HttpServer.prototype.handleRequest_ = function(req, res) {
var logEntry = req.method + ' ' + req.url;
if (req.headers['user-agent']) {
logEntry += ' ' + req.headers['user-agent'];
}
util.puts(logEntry);
req.url = this.parseUrl_(req.url);
var handler = this.handlers[req.method];
if (!handler) {
res.writeHead(501);
res.end();
} else {
handler.call(this, req, res);
}
};
/**
* Handles static content.
*/
function StaticServlet() {}
StaticServlet.MimeMap = {
'txt': 'text/plain',
'html': 'text/html',
'css': 'text/css',
'xml': 'application/xml',
'json': 'application/json',
'js': 'application/javascript',
'jpg': 'image/jpeg',
'jpeg': 'image/jpeg',
'gif': 'image/gif',
'png': 'image/png',
'svg': 'image/svg+xml'
};
StaticServlet.prototype.handleRequest = function(req, res) {
var self = this;
var path = ('./' + req.url.pathname).replace('//','/').replace(/%(..)/g, function(match, hex){
return String.fromCharCode(parseInt(hex, 16));
});
var parts = path.split('/');
if (parts[parts.length-1].charAt(0) === '.')
return self.sendForbidden_(req, res, path);
fs.stat(path, function(err, stat) {
if (err)
return self.sendMissing_(req, res, path);
if (stat.isDirectory())
return self.sendDirectory_(req, res, path);
return self.sendFile_(req, res, path);
});
}
StaticServlet.prototype.sendError_ = function(req, res, error) {
res.writeHead(500, {
'Content-Type': 'text/html'
});
res.write('<!doctype html>\n');
res.write('<title>Internal Server Error</title>\n');
res.write('<h1>Internal Server Error</h1>');
res.write('<pre>' + escapeHtml(util.inspect(error)) + '</pre>');
util.puts('500 Internal Server Error');
util.puts(util.inspect(error));
};
StaticServlet.prototype.sendMissing_ = function(req, res, path) {
path = path.substring(1);
res.writeHead(404, {
'Content-Type': 'text/html'
});
res.write('<!doctype html>\n');
res.write('<title>404 Not Found</title>\n');
res.write('<h1>Not Found</h1>');
res.write(
'<p>The requested URL ' +
escapeHtml(path) +
' was not found on this server.</p>'
);
res.end();
util.puts('404 Not Found: ' + path);
};
StaticServlet.prototype.sendForbidden_ = function(req, res, path) {
path = path.substring(1);
res.writeHead(403, {
'Content-Type': 'text/html'
});
res.write('<!doctype html>\n');
res.write('<title>403 Forbidden</title>\n');
res.write('<h1>Forbidden</h1>');
res.write(
'<p>You do not have permission to access ' +
escapeHtml(path) + ' on this server.</p>'
);
res.end();
util.puts('403 Forbidden: ' + path);
};
StaticServlet.prototype.sendRedirect_ = function(req, res, redirectUrl) {
res.writeHead(301, {
'Content-Type': 'text/html',
'Location': redirectUrl
});
res.write('<!doctype html>\n');
res.write('<title>301 Moved Permanently</title>\n');
res.write('<h1>Moved Permanently</h1>');
res.write(
'<p>The document has moved <a href="' +
redirectUrl +
'">here</a>.</p>'
);
res.end();
util.puts('301 Moved Permanently: ' + redirectUrl);
};
StaticServlet.prototype.sendFile_ = function(req, res, path) {
var self = this;
var file = fs.createReadStream(path);
res.writeHead(200, {
'Content-Type': StaticServlet.
MimeMap[path.split('.').pop()] || 'text/plain'
});
if (req.method === 'HEAD') {
res.end();
} else {
file.on('data', res.write.bind(res));
file.on('close', function() {
res.end();
});
file.on('error', function(error) {
self.sendError_(req, res, error);
});
}
};
StaticServlet.prototype.sendDirectory_ = function(req, res, path) {
var self = this;
if (path.match(/[^\/]$/)) {
req.url.pathname += '/';
var redirectUrl = url.format(url.parse(url.format(req.url)));
return self.sendRedirect_(req, res, redirectUrl);
}
fs.readdir(path, function(err, files) {
if (err)
return self.sendError_(req, res, error);
if (!files.length)
return self.writeDirectoryIndex_(req, res, path, []);
var remaining = files.length;
files.forEach(function(fileName, index) {
fs.stat(path + '/' + fileName, function(err, stat) {
if (err)
return self.sendError_(req, res, err);
if (stat.isDirectory()) {
files[index] = fileName + '/';
}
if (!(--remaining))
return self.writeDirectoryIndex_(req, res, path, files);
});
});
});
};
StaticServlet.prototype.writeDirectoryIndex_ = function(req, res, path, files) {
path = path.substring(1);
res.writeHead(200, {
'Content-Type': 'text/html'
});
if (req.method === 'HEAD') {
res.end();
return;
}
res.write('<!doctype html>\n');
res.write('<title>' + escapeHtml(path) + '</title>\n');
res.write('<style>\n');
res.write(' ol { list-style-type: none; font-size: 1.2em; }\n');
res.write('</style>\n');
res.write('<h1>Directory: ' + escapeHtml(path) + '</h1>');
res.write('<ol>');
files.forEach(function(fileName) {
if (fileName.charAt(0) !== '.') {
res.write('<li><a href="' +
escapeHtml(fileName) + '">' +
escapeHtml(fileName) + '</a></li>');
}
});
res.write('</ol>');
res.end();
};
// Must be last,
main(process.argv);
var dragUpdate = function() {
'use strict';
var dragging = false, viewport, originalDiagramData, currentDiagramData, selectedPoint, dragSegment, selectedEdge, selectedEdgeElement, dragPointX, dragPointY;
var init = function() {
d3.json('input.json', function(json) {
originalDiagramData = json;
var originalDiagramDataString = JSON.stringify(originalDiagramData, null, '\t');
d3.select('#original-json').text(originalDiagramDataString);
currentDiagramData = JSON.parse(JSON.stringify(originalDiagramData));
var svg = d3.select('#diagram').append('svg')
.attr('width', 900)
.attr('height', 900)
.attr('style', 'border:1px solid black');
var defs = svg.append('defs');
var arrowMarker = defs.append('marker')
.attr('id', 'shape-library-markers-arrow-svg-end-default')
.attr('preserveAspectRatio', 'none')
.attr('viewBox', '0 0 12 12')
.attr('markerWidth', '12')
.attr('markerHeight', '12')
.attr('markerUnits', 'strokeWidth')
.attr('orient', 'auto')
.attr('refX', '12')
.attr('refY', '6');
var arrowMarkerShapeContainer = arrowMarker.append('g')
.attr('id', 'g-src-shape-library-markers-arrow-svg-end-default')
.attr('transform', 'rotate(180, 6, 6)');
arrowMarkerShapeContainer.append('rect')
.attr('stroke', 'none')
.attr('x', '0')
.attr('y', '5.4')
.attr('width', '2')
.attr('height', '1.2');
arrowMarkerShapeContainer.append('polygon')
.attr('stroke-width', '0')
.attr('points', '12,11 0,6 12,1');
viewport = svg.selectAll('#viewport')
.data([currentDiagramData.viewport])
.enter()
.append('g')
.attr('id', 'viewport');
renderAll();
});
};
var jsondiff = function(left, right) {
var instance = jsondiffpatch.create({
objectHash: function(obj) {
return obj._id || obj.id || obj.name || JSON.stringify(obj);
}
});
var delta = instance.diff(left, right);
document.getElementById('visual').innerHTML = jsondiffpatch.formatters.html.format(delta, left);
if (!!delta) {
jsondiffpatch.formatters.html.hideUnchanged();
}
};
var drag = d3.behavior.drag()
.on("dragstart", function(d) {
dragging = true;
dragPointX = d3.event.sourceEvent.x;
dragPointY = d3.event.sourceEvent.y;
})
.on("drag", dragmove)
.on("dragend", function(d) {
dragging = false;
selectedEdge.attr('d', function(d) {
return calculatePathData(d).d;
});
currentDiagramData.viewport = d3.select('#viewport').datum();
d3.select('svg').attr('class',null);
renderAll();
});
function renderDiagramEdgeData(edgeElement, d) {
var edgeElementLength = edgeElement.getTotalLength(),
anchorPoint,
anchorPoints = {},
elementToUpdate,
pointsToUpdate,
pointToUpdate;
if (d.hasOwnProperty('anchors')) {
d.anchors.forEach(function(anchor) {
anchorPoints[anchor.id] = edgeElement.getPointAtLength(edgeElementLength * anchor.position);
});
d.hasAnchoredDependencies.forEach(function(elementId) {
elementToUpdate = currentDiagramData.viewport.filter(function(element) {
return element.id === elementId;
})[0];
pointsToUpdate = elementToUpdate.points.filter(function(point) {
return point.hasOwnProperty('anchor');
});
pointsToUpdate.forEach(function(pointToUpdate) {
anchorPoint = anchorPoints[pointToUpdate.anchor];
if (!!anchorPoint) {
pointToUpdate.x = anchorPoint.x;
pointToUpdate.y = anchorPoint.y;
}
});
var nextEdge = d3.select('#' + elementId);
var nextEdgeElement = nextEdge[0][0];
renderDiagramEdgeData(nextEdgeElement, elementToUpdate);
});
}
renderDiagram();
}
function dragmove(d) {
dragPointX = d3.event.x;
dragPointY = d3.event.y;
dragSegment.x = dragPointX;
dragSegment.y = dragPointY;
selectedPoint.x = dragPointX;
selectedPoint.y = dragPointY;
currentDiagramData.viewport = d3.select('#viewport').datum();
renderDiagramEdgeData(selectedEdgeElement, d);
}
var getDragSegment = function(d, selectedDragHandleIdentity) {
selectedEdge = d3.select('#' + d.id);
selectedEdgeElement = selectedEdge[0][0];
var numberOfItems = selectedEdgeElement.pathSegList.numberOfItems;
if (selectedDragHandleIdentity === 'target') {
selectedPoint = d.points[d.points.length - 1];
dragSegment = selectedEdgeElement.pathSegList.getItem(numberOfItems - 1);
}
else {
selectedPoint = d.points[0];
dragSegment = selectedEdgeElement.pathSegList.getItem(0);
}
};
var calculatePathData = function(d) {
var firstPathSegString,
pathData = {};
if (d.hasOwnProperty('points')) {
d.points.map(function(point, index) {
var targetEdge, targetEdgeElement, targetEdgeElementLength, anchor, anchorPoint;
if (!point.hasOwnProperty('x')) {
targetEdge = d3.select('#' + point.element);
targetEdgeElement = targetEdge[0][0];
targetEdgeElementLength = targetEdgeElement.getTotalLength();
anchor = targetEdge.datum().anchors.filter(function(anchor) {return anchor.id === point.anchor;})[0];
anchorPoint = targetEdgeElement.getPointAtLength(targetEdgeElementLength * anchor.position);
point.x = anchorPoint.x;
point.y = anchorPoint.y;
}
if (index > 0) {
d += ' L ' + point.x + ' ' + point.y;
}
else {
d = firstPathSegString = 'M ' + point.x + ' ' + point.y;
}
});
}
pathData.d = d;
pathData.firstPathSegString = firstPathSegString;
return pathData;
};
var renderDiagram = function(callback){
var renderableTypeToSvgElementMappings = {
'node':'rect',
'edge':'path'
};
var elements = viewport.selectAll('.element')
.data(function(d) {
return d;
})
.attr('id', function(d) {
return d.id;
})
.attr('class', function(d) {
var cssClassString = 'element ' + d.renderableType;
return cssClassString;
});
elements.enter()
.append(function(d) {
var childElementName = renderableTypeToSvgElementMappings[d.renderableType];
var child = document.createElementNS('http://www.w3.org/2000/svg', childElementName);
return child;
})
.attr('id', function(d) {
return d.id;
})
.attr('class', function(d) {
var cssClassString = 'element ' + d.renderableType;
return cssClassString;
});
elements.attr({
style: function(d) { return d.style; },
x: function(d) { return d.x; },
y: function(d) { return d.y; },
width: function(d) { return d.width; },
height: function(d) { return d.height; },
d: function(d) {
return calculatePathData(d).d;
},
'marker-end': function(d) { return 'url(#shape-library-markers-arrow-svg-end-default)'; }
});
elements.exit().remove();
if (!!callback) {
callback(elements);
}
};
var renderAll = function() {
renderDiagram(function(elements) {
elements.each(function(d){
var element = d3.select(this);
var sourceHandle, sourceHandleUpdated, targetHandle, targetHandleUpdated, sourcePoint, targetPoint, points;
if (d.renderableType === 'edge') {
var edge = d3.select('#' + d.id);
var edgeElement = edge[0][0];
var edgeLength = edgeElement.getTotalLength();
var distanceAlongEdge = Math.min(12, edgeLength/3);
points = d.points;
sourcePoint = points[0];
targetPoint = points[points.length - 1];
sourceHandle = viewport.selectAll('#' + d.id + '-source-handle')
.data([ d ])
.enter()
.append('path')
.attr('id', d.id + '-source-handle');
// TODO Do I need to use this format of defining the sourceHandle again or can I somehow
// reuse the definition above? Same for the targetHandle.
sourceHandleUpdated = d3.select('#' + d.id + '-source-handle')
.attr('d', function(d) {
var firstPoint = d.points[0];
var point0 = edgeElement.getPointAtLength(0);
var point1 = edgeElement.getPointAtLength(distanceAlongEdge);
return 'M ' + point0.x + ' ' + point0.y + ' L ' + point1.x + ' ' + point1.y;
})
.attr('class', 'drag-handle')
.on('mouseover', function(d) {
d3.select(this).attr('class','drag-handle grab');
})
.on('mousedown', function(d) {
getDragSegment(d, 'source');
d3.select('#' + d.id).attr('class', 'element edge-selected');
d3.select('svg').attr('class', 'grabbing');
d3.select(this).attr('class','drag-handle grabbing');
})
.on('mouseup', function(d) {
d3.select('#' + d.id).attr('class', 'element edge');
d3.select('svg').attr('class',null);
d3.select(this).attr('class','drag-handle');
})
.call(drag);
targetHandle = viewport.selectAll('#' + d.id + '-target-handle')
.data([ d ])
.enter()
.append('path')
.attr('id', d.id + '-target-handle');
targetHandleUpdated = d3.select('#' + d.id + '-target-handle')
.attr('d', function(d) {
var lastPoint = d.points[d.points.length - 1];
var point0 = edgeElement.getPointAtLength(edgeLength);
var point1 = edgeElement.getPointAtLength(edgeLength - distanceAlongEdge);
return 'M ' + point0.x + ' ' + point0.y + ' L ' + point1.x + ' ' + point1.y;
})
.attr('class', 'drag-handle')
.on('mouseover', function(d) {
d3.select(this).attr('class','drag-handle grab');
})
.on('mousedown', function(d) {
getDragSegment(d, 'target');
d3.select('#' + d.id).attr('class', 'element edge-selected');
d3.select('svg').attr('class', 'grabbing');
d3.select(this).attr('class','drag-handle grabbing');
})
.on('mouseup', function(d) {
d3.select('#' + d.id).attr('class', 'element edge');
d3.select('svg').attr('class',null);
d3.select(this).attr('class','drag-handle');
})
.call(drag);
}
});
});
var currentDiagramDataString = JSON.stringify(currentDiagramData, null, '\t');
d3.select('#current-json').text(currentDiagramDataString);
jsondiff(originalDiagramData, currentDiagramData);
};
return {
init:init
};
}();
<!DOCTYPE html>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<body>
<div id="diagram"></div>
<p>
Input:
</p>
<p id="input">
</p>
<p>
Output:
</p>
<p id="output">
</p>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script>
'use strict';
var dragging = false;
var diagramData = {
viewport:[
{
id: 'id123',
renderableType: 'node',
x: 50,
y: 50,
width: 80,
height: 20,
style: 'stroke: blue; fill: white;'
},
{
id: 'id234',
renderableType: 'node',
x: 200,
y: 50,
width: 80,
height: 20,
style: 'stroke: blue; fill: white;'
},
{
id: 'id345',
renderableType: 'edge',
points:[
{
x: 130,
y: 60
},
{
x: 200,
y: 60
}
],
anchors: [
{
id: 'id567',
position: 0.3
}
],
hasAnchoredDependencies: [
'id456'
],
style: 'stroke: black; stroke-width: 1; fill:yellow;'
},
{
id: 'id456',
renderableType: 'edge',
points:[
{
x: 165,
y: 20
},
{
element: 'id345',
anchor: 'id567'
}
],
style: 'stroke: black; stroke-width: 1; fill:yellow;'
}
]
};
var inputJsonString = JSON.stringify(diagramData);
d3.select('#input').text(inputJsonString);
var dragSegment, selectedPoint;
var drag = d3.behavior.drag()
.on("dragstart", function(d) {
dragging = true;
var dragPointX = d3.event.sourceEvent.x,
dragPointY = d3.event.sourceEvent.y;
var edge = d3.select(this);
edge.attr('d', function(d) {
return calculatePathData(d).d;
});
var edgeElement = edge[0][0];
var numberOfItems = edgeElement.pathSegList.numberOfItems;
var sourcePoint = d.points[0];
var sourcePointX = sourcePoint.x;
var sourcePointY = sourcePoint.y;
var dragPointToSourcePointDistance = Math.sqrt(Math.pow((dragPointX - sourcePointX),2) + Math.pow((dragPointY - sourcePointY),2));
var targetPoint = d.points[d.points.length - 1];
var targetPointX = targetPoint.x;
var targetPointY = targetPoint.y;
var dragPointToTargetPointDistance = Math.sqrt(Math.pow((dragPointX - targetPointX),2) + Math.pow((dragPointY - targetPointY),2));
if (dragPointToTargetPointDistance < dragPointToSourcePointDistance) {
selectedPoint = targetPoint;
dragSegment = edgeElement.pathSegList.getItem(0);
}
else {
selectedPoint = sourcePoint;
dragSegment = edgeElement.pathSegList.getItem(numberOfItems - 1);
}
})
.on("drag", dragmove)
.on("dragend", function(d) {
dragging = false;
var thisElement = d3.select(this);
thisElement.attr('d', function(d) {
return calculatePathData(d).d;
});
diagramData.viewport = d3.select('#viewport').datum();
var outputJsonString = JSON.stringify(diagramData);
d3.select('#output').text(outputJsonString);
update();
});
function dragmove(d) {
var dragPointX = d3.event.x,
dragPointY = d3.event.y;
dragSegment.x = dragPointX;
dragSegment.y = dragPointY;
selectedPoint.x = dragPointX;
selectedPoint.y = dragPointY;
var edgeElement = this,
thisEdgeElementLength = edgeElement.getTotalLength(),
anchorPoint,
anchorPoints = {},
elementToUpdate,
pointsToUpdate,
pointToUpdate;
diagramData.viewport = d3.select('#viewport').datum();
if (d.hasOwnProperty('anchors')) {
d.anchors.forEach(function(anchor) {
anchorPoints[anchor.id] = edgeElement.getPointAtLength(thisEdgeElementLength * anchor.position);
});
d.hasAnchoredDependencies.forEach(function(elementId) {
elementToUpdate = diagramData.viewport.filter(function(element) {
return element.id === elementId;
})[0];
pointsToUpdate = elementToUpdate.points.filter(function(point) {
return point.hasOwnProperty('anchor');
});
pointsToUpdate.forEach(function(pointToUpdate) {
anchorPoint = anchorPoints[pointToUpdate.anchor];
if (!!anchorPoint) {
pointToUpdate.x = anchorPoint.x;
pointToUpdate.y = anchorPoint.y;
}
});
});
}
update();
}
var svg = d3.select('#diagram').append('svg')
.attr('width', 400)
.attr('height', 200)
.attr('style', 'border:1px solid black');
var viewport = svg.selectAll('#viewport')
.data([diagramData.viewport])
.enter()
.append('g')
.attr('id', 'viewport');
var calculatePathData = function(d) {
var d,
firstPathSegString,
pathData = {};
if (d.hasOwnProperty('points')) {
d.points.map(function(point, index) {
var targetEdge, targetEdgeElement, targetEdgeElementLength, anchor, anchorPoint;
if (!point.hasOwnProperty('x')) {
targetEdge = d3.select('#' + point.element);
targetEdgeElement = targetEdge[0][0];
targetEdgeElementLength = targetEdgeElement.getTotalLength();
anchor = targetEdge.datum().anchors.filter(function(anchor) {return anchor.id === point.anchor;})[0];
anchorPoint = targetEdgeElement.getPointAtLength(targetEdgeElementLength * anchor.position);
point.x = anchorPoint.x;
point.y = anchorPoint.y;
}
if (index > 0) {
d += ' L ' + point.x + ' ' + point.y;
}
else {
d = firstPathSegString = 'M ' + point.x + ' ' + point.y;
}
});
}
pathData.d = d;
pathData.firstPathSegString = firstPathSegString;
return pathData;
};
var update = function(){
// this is a circle
//var dragHandlePathShapeString = ' m -7, 0 a 7,7 0 1,0 14,0 a 7,7 0 1,0 -14,0 l 14,0 l -7,0 l 0,-7 l 0,14 l 0,-7';
// this is a square
var dragHandlePathShapeString = ' m 3,0 l 0,3 l -6,0 l 0,-6 l 6,0 l 0,3 m -3,0';
var renderableTypeToSvgElementMappings = {
'node':'rect',
'edge':'path'
};
var elements = viewport.selectAll('.element')
.data(function(d) {
return d;
})
.attr('id', function(d) {
return d.id;
})
.attr('class', 'element');
elements.enter()
.append(function(d) {
var childElementName = renderableTypeToSvgElementMappings[d.renderableType];
var child = document.createElementNS('http://www.w3.org/2000/svg', childElementName);
return child;
})
.attr('id', function(d) {
return d.id;
})
.attr('class', 'element');
elements.attr({
style: function(d) { return d.style; },
x: function(d) { return d.x; },
y: function(d) { return d.y; },
width: function(d) { return d.width; },
height: function(d) { return d.height; },
d: function(d) {
return calculatePathData(d).d;
}
})
.on('mouseover', function(d) {
if (!dragging) {
var pathData = calculatePathData(d);
self.mypd = pathData;
var thisElement = d3.select(this);
thisElement.attr('d', function(d) {
var pathDataStringWithoutFirstPathSeg = pathData.d.slice(pathData.firstPathSegString.length,pathData.d.length);
var result = pathData.firstPathSegString + dragHandlePathShapeString + pathDataStringWithoutFirstPathSeg + ' ' + dragHandlePathShapeString;
return result;
});
}
})
.on('mouseout', function(d) {
if (!dragging) {
var thisElement = d3.select(this);
thisElement.attr('d', function(d) {
return calculatePathData(d).d;
});
}
})
.call(drag);
elements.exit().remove();
};
update();
</script>
</body>
</html>
!function(t){if("object"==typeof exports)module.exports=t();else if("function"==typeof define&&define.amd)define(t);else{var e;"undefined"!=typeof window?e=window:"undefined"!=typeof global?e=global:"undefined"!=typeof self&&(e=self),(e.jsondiffpatch||(e.jsondiffpatch={})).formatters=t()}}(function(){return function t(e,o,n){function r(a,f){if(!o[a]){if(!e[a]){var d="function"==typeof require&&require;if(!f&&d)return d(a,!0);if(i)return i(a,!0);throw new Error("Cannot find module '"+a+"'")}var s=o[a]={exports:{}};e[a][0].call(s.exports,function(t){var o=e[a][1][t];return r(o?o:t)},s,s.exports,t,e,o,n)}return o[a].exports}for(var i="function"==typeof require&&require,a=0;a<n.length;a++)r(n[a]);return r}({1:[function(t,e){var o=e.exports={};o.nextTick=function(){var t="undefined"!=typeof window&&window.setImmediate,e="undefined"!=typeof window&&window.postMessage&&window.addEventListener;if(t)return function(t){return window.setImmediate(t)};if(e){var o=[];return window.addEventListener("message",function(t){var e=t.source;if((e===window||null===e)&&"process-tick"===t.data&&(t.stopPropagation(),o.length>0)){var n=o.shift();n()}},!0),function(t){o.push(t),window.postMessage("process-tick","*")}}return function(t){setTimeout(t,0)}}(),o.title="browser",o.browser=!0,o.env={},o.argv=[],o.binding=function(){throw new Error("process.binding is not supported")},o.cwd=function(){return"/"},o.chdir=function(){throw new Error("process.chdir is not supported")}},{}],2:[function(t,e,o){var n=t("./base"),r=n.BaseFormatter,i=function(){this.includeMoveDestinations=!1};i.prototype=new r,i.prototype.prepareContext=function(t){r.prototype.prepareContext.call(this,t),t.indent=function(t){this.indentLevel=(this.indentLevel||0)+("undefined"==typeof t?1:t),this.indentPad=new Array(this.indentLevel+1).join("&nbsp;&nbsp;")},t.row=function(e,o){t.out('<tr><td style="white-space: nowrap;"><pre class="jsondiffpatch-annotated-indent" style="display: inline-block">'),t.out(t.indentPad),t.out('</pre><pre style="display: inline-block">'),t.out(e),t.out('</pre></td><td class="jsondiffpatch-delta-note"><div>'),t.out(o),t.out("</div></td></tr>")}},i.prototype.typeFormattterErrorFormatter=function(t,e){t.row("",'<pre class="jsondiffpatch-error">'+e+"</pre>")},i.prototype.formatTextDiffString=function(t,e){var o=this.parseTextDiff(e);t.out('<ul class="jsondiffpatch-textdiff">');for(var n=0,r=o.length;r>n;n++){var i=o[n];t.out('<li><div class="jsondiffpatch-textdiff-location"><span class="jsondiffpatch-textdiff-line-number">'+i.location.line+'</span><span class="jsondiffpatch-textdiff-char">'+i.location.chr+'</span></div><div class="jsondiffpatch-textdiff-line">');for(var a=i.pieces,f=0,d=a.length;d>f;f++){var s=a[f];t.out('<span class="jsondiffpatch-textdiff-'+s.type+'">'+s.text+"</span>")}t.out("</div></li>")}t.out("</ul>")},i.prototype.rootBegin=function(t,e,o){t.out('<table class="jsondiffpatch-annotated-delta">'),"node"===e&&(t.row("{"),t.indent()),"array"===o&&t.row('"_t": "a",',"Array delta (member names indicate array indices)")},i.prototype.rootEnd=function(t,e){"node"===e&&(t.indent(-1),t.row("}")),t.out("</table>")},i.prototype.nodeBegin=function(t,e,o,n,r){t.row("&quot;"+e+"&quot;: {"),"node"===n&&t.indent(),"array"===r&&t.row('"_t": "a",',"Array delta (member names indicate array indices)")},i.prototype.nodeEnd=function(t,e,o,n,r,i){"node"===n&&t.indent(-1),t.row("}"+(i?"":","))},i.prototype.format_unchanged=function(){},i.prototype.format_movedestination=function(){},i.prototype.format_node=function(t,e,o){this.formatDeltaChildren(t,e,o)};var a=function(t){return'<pre style="display:inline-block">&quot;'+t+"&quot;</pre>"},f={added:function(t,e,o,n){var r=" <pre>([newValue])</pre>";return"undefined"==typeof n?"new value"+r:"number"==typeof n?"insert at index "+n+r:"add property "+a(n)+r},modified:function(t,e,o,n){var r=" <pre>([previousValue, newValue])</pre>";return"undefined"==typeof n?"modify value"+r:"number"==typeof n?"modify at index "+n+r:"modify property "+a(n)+r},deleted:function(t,e,o,n){var r=" <pre>([previousValue, 0, 0])</pre>";return"undefined"==typeof n?"delete value"+r:"number"==typeof n?"remove index "+n+r:"delete property "+a(n)+r},moved:function(t,e,o,n){return'move from <span title="(position to remove at original state)">index '+n+'</span> to <span title="(position to insert at final state)">index '+t[1]+"</span>"},textdiff:function(t,e,o,n){var r="undefined"==typeof n?"":"number"==typeof n?" at index "+n:" at property "+a(n);return"text diff"+r+', format is <a href="https://code.google.com/p/google-diff-match-patch/wiki/Unidiff">a variation of Unidiff</a>'}},d=function(t,e){var o=this.getDeltaType(e),n=f[o],r=n&&n.apply(n,Array.prototype.slice.call(arguments,1)),i=JSON.stringify(e,null,2);"textdiff"===o&&(i=i.split("\\n").join('\\n"+\n "')),t.indent(),t.row(i,r),t.indent(-1)};i.prototype.format_added=d,i.prototype.format_modified=d,i.prototype.format_deleted=d,i.prototype.format_moved=d,i.prototype.format_textdiff=d,o.AnnotatedFormatter=i;var s;o.format=function(t,e){return s||(s=new i),s.format(t,e)}},{"./base":3}],3:[function(t,e,o){var n="function"==typeof Array.isArray?Array.isArray:function(t){return t instanceof Array},r="function"==typeof Object.keys?function(t){return Object.keys(t)}:function(t){var e=[];for(var o in t)t.hasOwnProperty(o)&&e.push(o);return e},i=function(t){return"_"===t.substr(0,1)?t.slice(1):t},a=function(t){return"_t"===t?-1:"_"===t.substr(0,1)?parseInt(t.slice(1),10):parseInt(t,10)+.1},f=function(t,e){return a(t)-a(e)},d=function(){};d.prototype.format=function(t,e){var o={};return this.prepareContext(o),this.recurse(o,t,e),this.finalize(o)},d.prototype.prepareContext=function(t){t.buffer=[],t.out=function(){this.buffer.push.apply(this.buffer,arguments)}},d.prototype.typeFormattterNotFound=function(t,e){throw new Error("cannot format delta type: "+e)},d.prototype.typeFormattterErrorFormatter=function(t,e){return e.toString()},d.prototype.finalize=function(t){return n(t.buffer)?t.buffer.join(""):void 0},d.prototype.recurse=function(t,e,o,n,r,i,a){if("undefined"==typeof e&&"undefined"==typeof n)return void 0;var f=this.getDeltaType(e,i),d="node"===f?"a"===e._t?"array":"object":"";"undefined"!=typeof n?this.nodeBegin(t,n,r,f,d,a):this.rootBegin(t,f,d);var s;try{s=this["format_"+f]||this.typeFormattterNotFound(t,f),s.call(this,t,e,o,n,r,i)}catch(p){this.typeFormattterErrorFormatter(t,p,e,o,n,r,i),"undefined"!=typeof console&&console.error&&console.error(p.stack)}"undefined"!=typeof n?this.nodeEnd(t,n,r,f,d,a):this.rootEnd(t,f,d)},d.prototype.formatDeltaChildren=function(t,e,o){var n=this;this.forEachDeltaKey(e,o,function(r,i,a,f){n.recurse(t,e[r],o?o[i]:void 0,r,i,a,f)})},d.prototype.forEachDeltaKey=function(t,e,o){var a,d=r(t),s="a"===t._t,p={};if("undefined"!=typeof e)for(a in e)"undefined"!=typeof t[a]||s&&"undefined"!=typeof t["_"+a]||d.push(a);for(a in t){var u=t[a];n(u)&&3===u[2]&&(p[u[1].toString()]=u[0],this.includeMoveDestinations!==!1&&"undefined"==typeof e&&"undefined"==typeof t[u[1]]&&d.push(u[1].toString()))}s?d.sort(f):d.sort();for(var c=0,l=d.length;l>c;c++){var h=d[c];if(!s||"_t"!==h){var y=s?"number"==typeof h?h:parseInt(i(h),10):h,v=c===l-1;o(h,y,p[y],v)}}},d.prototype.getDeltaType=function(t,e){if("undefined"==typeof t)return"undefined"!=typeof e?"movedestination":"unchanged";if(n(t)){if(1===t.length)return"added";if(2===t.length)return"modified";if(3===t.length&&0===t[2])return"deleted";if(3===t.length&&2===t[2])return"textdiff";if(3===t.length&&3===t[2])return"moved"}else if("object"==typeof t)return"node";return"unknown"},d.prototype.parseTextDiff=function(t){for(var e=[],o=t.split("\n@@ "),n=0,r=o.length;r>n;n++){var i=o[n],a={pieces:[]},f=/^(?:@@ )?[-+]?(\d+),(\d+)/.exec(i).slice(1);a.location={line:f[0],chr:f[1]};for(var d=i.split("\n").slice(1),s=0,p=d.length;p>s;s++){var u=d[s];if(u.length){var c={type:"context"};"+"===u.substr(0,1)?c.type="added":"-"===u.substr(0,1)&&(c.type="deleted"),c.text=u.slice(1),a.pieces.push(c)}}e.push(a)}return e},o.BaseFormatter=d},{}],4:[function(t,e,o){(function(e){o.html=t("./html"),o.annotated=t("./annotated");var n="undefined"!=typeof e&&"string"==typeof e.execPath;n&&(o.console=t("./console"))}).call(this,t("/home/sheila/proj/JsonDiffPatch/node_modules/gulp-browserify/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))},{"./annotated":2,"./html":5,"/home/sheila/proj/JsonDiffPatch/node_modules/gulp-browserify/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":1}],5:[function(t,e,o){var n=t("./base"),r=n.BaseFormatter,i=function(){};i.prototype=new r,i.prototype.typeFormattterErrorFormatter=function(t,e){t.out('<pre class="jsondiffpatch-error">'+e+"</pre>")},i.prototype.formatValue=function(t,e){t.out("<pre>"+JSON.stringify(e,null,2)+"</pre>")},i.prototype.formatTextDiffString=function(t,e){var o=this.parseTextDiff(e);t.out('<ul class="jsondiffpatch-textdiff">');for(var n=0,r=o.length;r>n;n++){var i=o[n];t.out('<li><div class="jsondiffpatch-textdiff-location"><span class="jsondiffpatch-textdiff-line-number">'+i.location.line+'</span><span class="jsondiffpatch-textdiff-char">'+i.location.chr+'</span></div><div class="jsondiffpatch-textdiff-line">');for(var a=i.pieces,f=0,d=a.length;d>f;f++){var s=a[f];t.out('<span class="jsondiffpatch-textdiff-'+s.type+'">'+s.text+"</span>")}t.out("</div></li>")}t.out("</ul>")};var a=function(t){t=t||document;var e=function(t){return t.textContent||t.innerText},o=function(t,e,o){for(var n=t.querySelectorAll(e),r=0,i=n.length;i>r;r++)o(n[r])},n=function(t,e){for(var o=0,n=t.children.length;n>o;o++)e(t.children[o],o)};o(t,".jsondiffpatch-arrow",function(t){var o=t.parentNode,r=t.children[0],i=r.children[1];r.style.display="none";var a,f=e(o.querySelector(".jsondiffpatch-moved-destination")),d=o.parentNode;if(n(d,function(t){t.getAttribute("data-key")===f&&(a=t)}),a)try{var s=a.offsetTop-o.offsetTop;r.setAttribute("height",Math.abs(s)+6),t.style.top=-8+(s>0?0:s)+"px";var p=s>0?"M30,0 Q-10,"+Math.round(s/2)+" 26,"+(s-4):"M30,"+-s+" Q-10,"+Math.round(-s/2)+" 26,4";i.setAttribute("d",p),r.style.display=""}catch(u){return}})};i.prototype.rootBegin=function(t,e,o){var n="jsondiffpatch-"+e+(o?" jsondiffpatch-child-node-type-"+o:"");t.out('<div class="jsondiffpatch-delta '+n+'">')},i.prototype.rootEnd=function(t){t.out("</div>"+(t.hasArrows?'<script type="text/javascript">setTimeout('+a.toString()+",10);</script>":""))},i.prototype.nodeBegin=function(t,e,o,n,r){var i="jsondiffpatch-"+n+(r?" jsondiffpatch-child-node-type-"+r:"");t.out('<li class="'+i+'" data-key="'+o+'"><div class="jsondiffpatch-property-name">'+o+"</div>")},i.prototype.nodeEnd=function(t){t.out("</li>")},i.prototype.format_unchanged=function(t,e,o){"undefined"!=typeof o&&(t.out('<div class="jsondiffpatch-value">'),this.formatValue(t,o),t.out("</div>"))},i.prototype.format_movedestination=function(t,e,o){"undefined"!=typeof o&&(t.out('<div class="jsondiffpatch-value">'),this.formatValue(t,o),t.out("</div>"))},i.prototype.format_node=function(t,e,o){var n="a"===e._t?"array":"object";t.out('<ul class="jsondiffpatch-node jsondiffpatch-node-type-'+n+'">'),this.formatDeltaChildren(t,e,o),t.out("</ul>")},i.prototype.format_added=function(t,e){t.out('<div class="jsondiffpatch-value">'),this.formatValue(t,e[0]),t.out("</div>")},i.prototype.format_modified=function(t,e){t.out('<div class="jsondiffpatch-value jsondiffpatch-left-value">'),this.formatValue(t,e[0]),t.out('</div><div class="jsondiffpatch-value jsondiffpatch-right-value">'),this.formatValue(t,e[1]),t.out("</div>")},i.prototype.format_deleted=function(t,e){t.out('<div class="jsondiffpatch-value">'),this.formatValue(t,e[0]),t.out("</div>")},i.prototype.format_moved=function(t,e){t.out('<div class="jsondiffpatch-value">'),this.formatValue(t,e[0]),t.out('</div><div class="jsondiffpatch-moved-destination">'+e[1]+"</div>"),t.out('<div class="jsondiffpatch-arrow" style="position: relative; left: -34px;"> <svg width="30" height="60" style="position: absolute; display: none;"> <defs> <marker id="markerArrow" markerWidth="8" markerHeight="8" refx="2" refy="4" orient="auto" markerUnits="userSpaceOnUse"> <path d="M1,1 L1,7 L7,4 L1,1" style="fill: #339;" /> </marker> </defs> <path d="M30,0 Q-10,25 26,50" style="stroke: #88f; stroke-width: 2px; fill: none; stroke-opacity: 0.5; marker-end: url(#markerArrow);"></path> </svg> </div>'),t.hasArrows=!0},i.prototype.format_textdiff=function(t,e){t.out('<div class="jsondiffpatch-value">'),this.formatTextDiffString(t,e[0]),t.out("</div>")};var f=function(t,e,o){var n=e||document.body,r="jsondiffpatch-unchanged-",i={showing:r+"showing",hiding:r+"hiding",visible:r+"visible",hidden:r+"hidden"},f=n.classList;if(f){if(!o)return f.remove(i.showing),f.remove(i.hiding),f.remove(i.visible),f.remove(i.hidden),void(t===!1&&f.add(i.hidden));t===!1?(f.remove(i.showing),f.add(i.visible),setTimeout(function(){f.add(i.hiding)},10)):(f.remove(i.hiding),f.add(i.showing),f.remove(i.hidden));var d=setInterval(function(){a(n)},100);setTimeout(function(){f.remove(i.showing),f.remove(i.hiding),t===!1?(f.add(i.hidden),f.remove(i.visible)):(f.add(i.visible),f.remove(i.hidden)),setTimeout(function(){f.remove(i.visible),clearInterval(d)},o+400)},o)}},d=function(t,e){return f(!1,t,e)};o.HtmlFormatter=i,o.showUnchanged=f,o.hideUnchanged=d;var s;o.format=function(t,e){return s||(s=new i),s.format(t,e)}},{"./base":3}]},{},[4])(4)});
.jsondiffpatch-delta {
font-family: 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', Monaco, Courier, monospace;
font-size: 12px;
margin: 0;
padding: 0 0 0 12px;
display: inline-block;
}
.jsondiffpatch-delta pre {
font-family: 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', Monaco, Courier, monospace;
font-size: 12px;
margin: 0;
padding: 0;
display: inline-block;
}
ul.jsondiffpatch-delta {
list-style-type: none;
padding: 0 0 0 20px;
margin: 0;
}
.jsondiffpatch-delta ul {
list-style-type: none;
padding: 0 0 0 20px;
margin: 0;
}
.jsondiffpatch-added .jsondiffpatch-property-name,
.jsondiffpatch-added .jsondiffpatch-value pre,
.jsondiffpatch-modified .jsondiffpatch-right-value,
.jsondiffpatch-textdiff-added
{
background: #bbffbb;
}
.jsondiffpatch-deleted .jsondiffpatch-property-name,
.jsondiffpatch-deleted pre,
.jsondiffpatch-modified .jsondiffpatch-left-value pre,
.jsondiffpatch-textdiff-deleted
{
background: #ffbbbb;
text-decoration: line-through;
}
.jsondiffpatch-unchanged, .jsondiffpatch-movedestination {
color: gray;
}
.jsondiffpatch-unchanged, .jsondiffpatch-movedestination > .jsondiffpatch-value {
transition: all 0.5s;
-webkit-transition: all 0.5s;
overflow-y: hidden;
}
.jsondiffpatch-unchanged-showing .jsondiffpatch-unchanged,
.jsondiffpatch-unchanged-showing .jsondiffpatch-movedestination > .jsondiffpatch-value {
max-height: 100px;
}
.jsondiffpatch-unchanged-hidden .jsondiffpatch-unchanged,
.jsondiffpatch-unchanged-hidden .jsondiffpatch-movedestination > .jsondiffpatch-value {
max-height: 0;
}
.jsondiffpatch-unchanged-hiding .jsondiffpatch-movedestination > .jsondiffpatch-value,
.jsondiffpatch-unchanged-hidden .jsondiffpatch-movedestination > .jsondiffpatch-value {
display: block;
}
.jsondiffpatch-unchanged-visible .jsondiffpatch-unchanged,
.jsondiffpatch-unchanged-visible .jsondiffpatch-movedestination > .jsondiffpatch-value {
max-height: 100px;
}
.jsondiffpatch-unchanged-hiding .jsondiffpatch-unchanged,
.jsondiffpatch-unchanged-hiding .jsondiffpatch-movedestination > .jsondiffpatch-value {
max-height: 0;
}
.jsondiffpatch-unchanged-showing .jsondiffpatch-arrow,
.jsondiffpatch-unchanged-hiding .jsondiffpatch-arrow {
display: none;
}
.jsondiffpatch-value {
display: inline-block;
}
.jsondiffpatch-property-name {
display: inline-block;
padding-right: 5px;
vertical-align: top;
}
.jsondiffpatch-property-name:after {
content: ': ';
}
.jsondiffpatch-child-node-type-array > .jsondiffpatch-property-name:after {
content: ': [';
}
.jsondiffpatch-child-node-type-array:after {
content: '],';
}
div.jsondiffpatch-child-node-type-array:before {
content: '[';
}
div.jsondiffpatch-child-node-type-array:after {
content: ']';
}
.jsondiffpatch-child-node-type-object > .jsondiffpatch-property-name:after {
content: ': {';
}
.jsondiffpatch-child-node-type-object:after {
content: '},';
}
div.jsondiffpatch-child-node-type-object:before {
content: '{';
}
div.jsondiffpatch-child-node-type-object:after {
content: '}';
}
.jsondiffpatch-value pre:after {
content: ',';
}
li:last-child > .jsondiffpatch-value pre:after,
.jsondiffpatch-modified > .jsondiffpatch-left-value pre:after
{
content: '';
}
.jsondiffpatch-modified .jsondiffpatch-value {
display: inline-block;
}
.jsondiffpatch-modified .jsondiffpatch-right-value {
margin-left: 5px;
}
.jsondiffpatch-moved .jsondiffpatch-value {
display: none;
}
.jsondiffpatch-moved .jsondiffpatch-moved-destination {
display: inline-block;
background: #ffffbb;
color: #888;
}
.jsondiffpatch-moved .jsondiffpatch-moved-destination:before {
content: ' => ';
}
ul.jsondiffpatch-textdiff {
padding: 0;
}
.jsondiffpatch-textdiff-location {
color: #bbb;
display: inline-block;
min-width: 60px;
}
.jsondiffpatch-textdiff-line {
display: inline-block;
}
.jsondiffpatch-textdiff-line-number:after {
content: ',';
}
.jsondiffpatch-error {
background: red;
color: white;
font-weight: bold;
}
<!DOCTYPE html>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<style>
body {
font: 10px sans-serif;
}
/*
.drag-handle {
fill: transparent;
fill-opacity: 1;
stroke: transparent;
stroke-width: 0;
}
*/
.drag-handle {
fill: transparent;
stroke: transparent;
}
.drag-handle:hover, .drag-handle-active {
fill: yellow;
fill-opacity: 0.8;
stroke: orange;
stroke-width: 0.5px;
cursor: -moz-grab;
cursor: -webkit-grab;
cursor: grab;
}
.drag-handle-inactive {
fill: gray;
fill-opacity: 0.2;
stroke: gray;
stroke-opacity: 0.5;
stroke-width: 0.5px;
}
.grab, .edge {
cursor: -moz-grab;
cursor: -webkit-grab;
cursor: grab;
}
.grabbing, .edge-selected {
cursor: -moz-grabbing;
cursor: -webkit-grabbing;
cursor: grabbing;
}
</style>
<body>
<div id="diagram"></div>
<p>
Input:
</p>
<p id="input">
</p>
<p>
Output:
</p>
<p id="output">
</p>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script>
'use strict';
var dragging = false;
var diagramData = {
viewport:[
{
id: 'id123',
renderableType: 'node',
x: 50,
y: 50,
width: 80,
height: 20,
style: 'stroke: blue; fill: white;'
},
{
id: 'id234',
renderableType: 'node',
x: 200,
y: 50,
width: 80,
height: 20,
style: 'stroke: blue; fill: white;'
},
{
id: 'id345',
renderableType: 'edge',
points:[
{
x: 130,
y: 60
},
{
x: 200,
y: 60
}
],
anchors: [
{
id: 'id567',
position: 0.3
}
],
hasAnchoredDependencies: [
'id456'
],
style: 'stroke: black; stroke-width: 1; fill:yellow;'
},
{
id: 'id456',
renderableType: 'edge',
points:[
{
x: 165,
y: 20
},
{
element: 'id345',
anchor: 'id567'
}
],
style: 'stroke: black; stroke-width: 1; fill:yellow;'
}
]
};
var inputJsonString = JSON.stringify(diagramData);
d3.select('#input').text(inputJsonString);
var dragSegment, selectedPoint, selectedEdge, selectedEdgeElement, dragPointX, dragPointY, nearerDragHandle, fartherDragHandle;
var getNearestDragHandleIdentity = function(d, dragPointX, dragPointY) {
var nearerDragHandleIdentity;
selectedEdge = d3.select('#' + d.id);
selectedEdgeElement = selectedEdge[0][0];
var numberOfItems = selectedEdgeElement.pathSegList.numberOfItems;
var sourcePoint = d.points[0];
var sourcePointX = sourcePoint.x;
var sourcePointY = sourcePoint.y;
var dragPointToSourcePointDistance = Math.sqrt(Math.pow((dragPointX - sourcePointX),2) + Math.pow((dragPointY - sourcePointY),2));
var targetPoint = d.points[d.points.length - 1];
var targetPointX = targetPoint.x;
var targetPointY = targetPoint.y;
var dragPointToTargetPointDistance = Math.sqrt(Math.pow((dragPointX - targetPointX),2) + Math.pow((dragPointY - targetPointY),2));
if (dragPointToTargetPointDistance < dragPointToSourcePointDistance) {
selectedPoint = targetPoint;
dragSegment = selectedEdgeElement.pathSegList.getItem(0);
nearerDragHandleIdentity = 'target';
}
else {
selectedPoint = sourcePoint;
dragSegment = selectedEdgeElement.pathSegList.getItem(numberOfItems - 1);
nearerDragHandleIdentity = 'source';
}
return nearerDragHandleIdentity;
};
var drag = d3.behavior.drag()
.on("dragstart", function(d) {
nearerDragHandle.attr('class', 'drag-handle');
fartherDragHandle.attr('class', 'drag-handle');
dragging = true;
dragPointX = d3.event.sourceEvent.x;
dragPointY = d3.event.sourceEvent.y;
var dragHandleIdentities = getNearestDragHandleIdentity(d, dragPointX, dragPointY);
})
.on("drag", dragmove)
.on("dragend", function(d) {
dragging = false;
console.log('this');
console.log(this);
console.log('this');
console.log(this);
/*
var dragHandle = d3.select(this)
.attr('cx', dragPointX)
.attr('cy', dragPointY);
//*/
selectedEdge.attr('d', function(d) {
return calculatePathData(d).d;
});
diagramData.viewport = d3.select('#viewport').datum();
var outputJsonString = JSON.stringify(diagramData);
d3.select('#output').text(outputJsonString);
d3.select('svg').attr('class',null);
init();
});
function dragmove(d) {
dragPointX = d3.event.x;
dragPointY = d3.event.y;
dragSegment.x = dragPointX;
dragSegment.y = dragPointY;
selectedPoint.x = dragPointX;
selectedPoint.y = dragPointY;
var selectedEdgeElementLength = selectedEdgeElement.getTotalLength(),
//selectedEdgeElementLength = selectedEdgeElement.getTotalLength() - 185.9791717529297,
anchorPoint,
anchorPoints = {},
elementToUpdate,
pointsToUpdate,
pointToUpdate;
diagramData.viewport = d3.select('#viewport').datum();
if (d.hasOwnProperty('anchors')) {
d.anchors.forEach(function(anchor) {
anchorPoints[anchor.id] = selectedEdgeElement.getPointAtLength(selectedEdgeElementLength * anchor.position);
});
d.hasAnchoredDependencies.forEach(function(elementId) {
elementToUpdate = diagramData.viewport.filter(function(element) {
return element.id === elementId;
})[0];
pointsToUpdate = elementToUpdate.points.filter(function(point) {
return point.hasOwnProperty('anchor');
});
pointsToUpdate.forEach(function(pointToUpdate) {
anchorPoint = anchorPoints[pointToUpdate.anchor];
if (!!anchorPoint) {
pointToUpdate.x = anchorPoint.x;
pointToUpdate.y = anchorPoint.y;
}
});
});
}
update();
}
var svg = d3.select('#diagram').append('svg')
.attr('width', 400)
.attr('height', 200)
.attr('style', 'border:1px solid black');
var viewport = svg.selectAll('#viewport')
.data([diagramData.viewport])
.enter()
.append('g')
.attr('id', 'viewport');
var calculatePathData = function(d) {
var d,
firstPathSegString,
pathData = {};
if (d.hasOwnProperty('points')) {
d.points.map(function(point, index) {
var targetEdge, targetEdgeElement, targetEdgeElementLength, anchor, anchorPoint;
if (!point.hasOwnProperty('x')) {
targetEdge = d3.select('#' + point.element);
targetEdgeElement = targetEdge[0][0];
targetEdgeElementLength = targetEdgeElement.getTotalLength();
anchor = targetEdge.datum().anchors.filter(function(anchor) {return anchor.id === point.anchor;})[0];
anchorPoint = targetEdgeElement.getPointAtLength(targetEdgeElementLength * anchor.position);
point.x = anchorPoint.x;
point.y = anchorPoint.y;
}
if (index > 0) {
d += ' L ' + point.x + ' ' + point.y;
}
else {
d = firstPathSegString = 'M ' + point.x + ' ' + point.y;
}
});
}
pathData.d = d;
pathData.firstPathSegString = firstPathSegString;
return pathData;
};
var update = function(callback){
var renderableTypeToSvgElementMappings = {
'node':'rect',
'edge':'path'
};
var elements = viewport.selectAll('.element')
.data(function(d) {
return d;
})
.attr('id', function(d) {
return d.id;
})
.attr('class', function(d) {
var cssClassString = 'element ' + d.renderableType;
if (dragging) {
cssClassString += ' grabbing';
}
return cssClassString;
});
elements.enter()
.append(function(d) {
var childElementName = renderableTypeToSvgElementMappings[d.renderableType];
var child = document.createElementNS('http://www.w3.org/2000/svg', childElementName);
return child;
})
.attr('id', function(d) {
return d.id;
})
.attr('class', function(d) {
var cssClassString = 'element ' + d.renderableType;
if (dragging) {
cssClassString += ' grabbing';
}
return cssClassString;
})
.on('mouseover', function(d) {
if (!dragging) {
nearerDragHandle = d3.select('#' + d.id + '-' + nearerDragHandleIdentity + '-handle')
if (!!nearerDragHandle[0][0]) {
nearerDragHandle.attr('class', 'drag-handle');
fartherDragHandle.attr('class', 'drag-handle');
}
var pathData = calculatePathData(d);
self.mypd = pathData;
console.log(d3.event);
var nearerDragHandleIdentity = getNearestDragHandleIdentity(d, d3.event.x, d3.event.y);
console.log(nearerDragHandleIdentity);
nearerDragHandle = d3.select('#' + d.id + '-' + nearerDragHandleIdentity + '-handle')
.attr('class', 'drag-handle-active');
var fartherDragHandleIdentity;
// TODO refactor this for maintability
if (nearerDragHandleIdentity === 'source') {
fartherDragHandleIdentity = 'target';
}
else {
fartherDragHandleIdentity = 'source';
}
fartherDragHandle = d3.select('#' + d.id + '-' + fartherDragHandleIdentity + '-handle')
.attr('class', 'drag-handle-inactive');
}
})
.on('mousedown', function(d) {
selectedEdge.attr('class', 'element edge-selected');
nearerDragHandle.attr('class', 'grabbing');
d3.select('svg').attr('class', 'grabbing');
})
.on('mouseup', function(d) {
d3.select('svg').attr('class',null);
})
.on('mouseout', function(d) {
if (!dragging) {
window.setTimeout(function() {
d3.select('#' + d.id + '-source-handle').attr('class', 'drag-handle');
d3.select('#' + d.id + '-target-handle').attr('class', 'drag-handle');
}, 400);
}
})
.call(drag);
elements.attr({
style: function(d) {
var styleString = d.style,
firstPoint, lastPoint, xDistance, yDistance;
//* this makes the cursor a double-headed arrow to indicate that the user can move an edge end point
// removing this code sends us back to using the grabbing cursor on hover
// we could also look at using the single-headed arrows
if (d.renderableType === 'edge') {
firstPoint = d.points[0];
lastPoint = d.points[d.points.length - 1];
xDistance = Math.abs(lastPoint.x - firstPoint.x);
yDistance = Math.abs(lastPoint.y - firstPoint.y);
if (yDistance > xDistance) {
styleString += 'cursor: ns-resize';
}
else {
styleString += 'cursor: ew-resize';
}
}
//*/
return styleString;
},
x: function(d) { return d.x; },
y: function(d) { return d.y; },
width: function(d) { return d.width; },
height: function(d) { return d.height; },
d: function(d) {
return calculatePathData(d).d;
}
});
elements.exit().remove();
if (!!callback) {
callback(elements);
};
};
var init = function() {
var viewport = d3.select('#viewport');
update(function(elements) {
elements.each(function(d){
console.log(this);
console.log(d);
var element = d3.select(this);
var sourceHandle, sourceHandle2, targetHandle, targetHandle2, sourcePoint, targetPoint, points;
if (d.renderableType === 'edge') {
console.log('edge');
points = d.points;
sourcePoint = points[0];
targetPoint = points[points.length - 1];
sourceHandle = viewport.selectAll('#' + d.id + '-source-handle')
.data([ d ])
.enter()
.append('circle')
.attr('id', d.id + '-source-handle')
sourceHandle2 = d3.select('#' + d.id + '-source-handle')
.attr('cx', sourcePoint.x)
.attr('cy', sourcePoint.y)
.attr('r', 4)
.attr('class', 'drag-handle')
.on('mousedown', function(d) {
d3.select('#' + d.id).attr('class', 'element edge-selected');
console.log(d3.select('#' + d.id));
d3.select('svg').attr('class', 'grabbing');
d3.select(this).attr('class','drag-handle grabbing');
})
.on('mouseup', function(d) {
d3.select('#' + d.id).attr('class', 'element edge');
d3.select('svg').attr('class',null);
d3.select(this).attr('class','drag-handle');
})
.call(drag);
targetHandle = viewport.selectAll('#' + d.id + '-target-handle')
.data([ d ])
.enter()
.append('circle')
.attr('id', d.id + '-target-handle');
targetHandle2 = d3.select('#' + d.id + '-target-handle')
.attr('cx', targetPoint.x)
.attr('cy', targetPoint.y)
.attr('r', 4)
.attr('class', 'drag-handle')
.on('mousedown', function(d) {
d3.select('#' + d.id).attr('class', 'element edge');
d3.select('svg').attr('class', 'grabbing');
d3.select(this).attr('class','drag-handle grabbing');
})
.on('mouseup', function(d) {
d3.select('#' + d.id).attr('class', 'element edge');
d3.select('svg').attr('class',null);
d3.select(this).attr('class','drag-handle');
})
.call(drag);
}
});
});
};
init();
</script>
</body>
</html>
<!DOCTYPE html>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<style>
body {
font: 10px sans-serif;
}
/*
.drag-handle {
fill: transparent;
fill-opacity: 1;
stroke: transparent;
stroke-width: 0;
}
*/
.drag-handle {
fill: transparent;
stroke: transparent;
}
.drag-handle:hover, .drag-handle-active {
fill: yellow;
fill-opacity: 0.8;
stroke: orange;
stroke-width: 0.5px;
}
.drag-handle-inactive {
fill: gray;
fill-opacity: 0.2;
stroke: gray;
stroke-opacity: 0.5;
stroke-width: 0.5px;
}
.grab, .edge {
cursor: -moz-grab;
cursor: -webkit-grab;
cursor: grab;
}
.grabbing, .edge-selected {
cursor: -moz-grabbing;
cursor: -webkit-grabbing;
cursor: grabbing;
}
</style>
<body>
<div id="diagram"></div>
<p>
Input:
</p>
<p id="input">
</p>
<p>
Output:
</p>
<p id="output">
</p>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script>
'use strict';
var dragging = false;
var diagramData = {
viewport:[
{
id: 'id123',
renderableType: 'node',
x: 50,
y: 50,
width: 80,
height: 20,
style: 'stroke: blue; fill: white;'
},
{
id: 'id234',
renderableType: 'node',
x: 200,
y: 50,
width: 80,
height: 20,
style: 'stroke: blue; fill: white;'
},
{
id: 'id345',
renderableType: 'edge',
points:[
{
x: 130,
y: 60
},
{
x: 200,
y: 60
}
],
anchors: [
{
id: 'id567',
position: 0.3
}
],
hasAnchoredDependencies: [
'id456'
],
style: 'stroke: black; stroke-width: 1; fill:yellow;'
},
{
id: 'id456',
renderableType: 'edge',
points:[
{
x: 165,
y: 20
},
{
element: 'id345',
anchor: 'id567'
}
],
style: 'stroke: black; stroke-width: 1; fill:yellow;'
}
]
};
var inputJsonString = JSON.stringify(diagramData);
d3.select('#input').text(inputJsonString);
var dragSegment, selectedPoint, selectedEdge, selectedEdgeElement, dragPointX, dragPointY, nearerDragHandle, fartherDragHandle;
var getNearestDragHandleIdentity = function(d, dragPointX, dragPointY) {
var nearerDragHandleIdentity;
selectedEdge = d3.select('#' + d.id);
selectedEdgeElement = selectedEdge[0][0];
var numberOfItems = selectedEdgeElement.pathSegList.numberOfItems;
var sourcePoint = d.points[0];
var sourcePointX = sourcePoint.x;
var sourcePointY = sourcePoint.y;
var dragPointToSourcePointDistance = Math.sqrt(Math.pow((dragPointX - sourcePointX),2) + Math.pow((dragPointY - sourcePointY),2));
var targetPoint = d.points[d.points.length - 1];
var targetPointX = targetPoint.x;
var targetPointY = targetPoint.y;
var dragPointToTargetPointDistance = Math.sqrt(Math.pow((dragPointX - targetPointX),2) + Math.pow((dragPointY - targetPointY),2));
if (dragPointToTargetPointDistance < dragPointToSourcePointDistance) {
selectedPoint = targetPoint;
dragSegment = selectedEdgeElement.pathSegList.getItem(0);
nearerDragHandleIdentity = 'target';
}
else {
selectedPoint = sourcePoint;
dragSegment = selectedEdgeElement.pathSegList.getItem(numberOfItems - 1);
nearerDragHandleIdentity = 'source';
}
return nearerDragHandleIdentity;
};
var drag = d3.behavior.drag()
.on("dragstart", function(d) {
nearerDragHandle.attr('class', 'drag-handle');
fartherDragHandle.attr('class', 'drag-handle');
dragging = true;
dragPointX = d3.event.sourceEvent.x;
dragPointY = d3.event.sourceEvent.y;
var dragHandleIdentities = getNearestDragHandleIdentity(d, dragPointX, dragPointY);
})
.on("drag", dragmove)
.on("dragend", function(d) {
dragging = false;
console.log('this');
console.log(this);
console.log('this');
console.log(this);
/*
var dragHandle = d3.select(this)
.attr('cx', dragPointX)
.attr('cy', dragPointY);
//*/
selectedEdge.attr('d', function(d) {
return calculatePathData(d).d;
});
diagramData.viewport = d3.select('#viewport').datum();
var outputJsonString = JSON.stringify(diagramData);
d3.select('#output').text(outputJsonString);
d3.select('svg').attr('class',null);
init();
});
function dragmove(d) {
dragPointX = d3.event.x;
dragPointY = d3.event.y;
dragSegment.x = dragPointX;
dragSegment.y = dragPointY;
selectedPoint.x = dragPointX;
selectedPoint.y = dragPointY;
var selectedEdgeElementLength = selectedEdgeElement.getTotalLength(),
//selectedEdgeElementLength = selectedEdgeElement.getTotalLength() - 185.9791717529297,
anchorPoint,
anchorPoints = {},
elementToUpdate,
pointsToUpdate,
pointToUpdate;
diagramData.viewport = d3.select('#viewport').datum();
if (d.hasOwnProperty('anchors')) {
d.anchors.forEach(function(anchor) {
anchorPoints[anchor.id] = selectedEdgeElement.getPointAtLength(selectedEdgeElementLength * anchor.position);
});
d.hasAnchoredDependencies.forEach(function(elementId) {
elementToUpdate = diagramData.viewport.filter(function(element) {
return element.id === elementId;
})[0];
pointsToUpdate = elementToUpdate.points.filter(function(point) {
return point.hasOwnProperty('anchor');
});
pointsToUpdate.forEach(function(pointToUpdate) {
anchorPoint = anchorPoints[pointToUpdate.anchor];
if (!!anchorPoint) {
pointToUpdate.x = anchorPoint.x;
pointToUpdate.y = anchorPoint.y;
}
});
});
}
update();
}
var svg = d3.select('#diagram').append('svg')
.attr('width', 400)
.attr('height', 200)
.attr('style', 'border:1px solid black');
var viewport = svg.selectAll('#viewport')
.data([diagramData.viewport])
.enter()
.append('g')
.attr('id', 'viewport');
var calculatePathData = function(d) {
var d,
firstPathSegString,
pathData = {};
if (d.hasOwnProperty('points')) {
d.points.map(function(point, index) {
var targetEdge, targetEdgeElement, targetEdgeElementLength, anchor, anchorPoint;
if (!point.hasOwnProperty('x')) {
targetEdge = d3.select('#' + point.element);
targetEdgeElement = targetEdge[0][0];
targetEdgeElementLength = targetEdgeElement.getTotalLength();
anchor = targetEdge.datum().anchors.filter(function(anchor) {return anchor.id === point.anchor;})[0];
anchorPoint = targetEdgeElement.getPointAtLength(targetEdgeElementLength * anchor.position);
point.x = anchorPoint.x;
point.y = anchorPoint.y;
}
if (index > 0) {
d += ' L ' + point.x + ' ' + point.y;
}
else {
d = firstPathSegString = 'M ' + point.x + ' ' + point.y;
}
});
}
pathData.d = d;
pathData.firstPathSegString = firstPathSegString;
return pathData;
};
var update = function(callback){
var renderableTypeToSvgElementMappings = {
'node':'rect',
'edge':'path'
};
var elements = viewport.selectAll('.element')
.data(function(d) {
return d;
})
.attr('id', function(d) {
return d.id;
})
.attr('class', function(d) {
var cssClassString = 'element ' + d.renderableType;
if (dragging) {
cssClassString += ' grabbing';
}
return cssClassString;
});
elements.enter()
.append(function(d) {
var childElementName = renderableTypeToSvgElementMappings[d.renderableType];
var child = document.createElementNS('http://www.w3.org/2000/svg', childElementName);
return child;
})
.attr('id', function(d) {
return d.id;
})
.attr('class', function(d) {
var cssClassString = 'element ' + d.renderableType;
if (dragging) {
cssClassString += ' grabbing';
}
return cssClassString;
})
.on('mouseover', function(d) {
if (!dragging) {
nearerDragHandle = d3.select('#' + d.id + '-' + nearerDragHandleIdentity + '-handle')
if (!!nearerDragHandle[0][0]) {
nearerDragHandle.attr('class', 'drag-handle');
fartherDragHandle.attr('class', 'drag-handle');
}
var pathData = calculatePathData(d);
self.mypd = pathData;
console.log(d3.event);
var nearerDragHandleIdentity = getNearestDragHandleIdentity(d, d3.event.x, d3.event.y);
console.log(nearerDragHandleIdentity);
nearerDragHandle = d3.select('#' + d.id + '-' + nearerDragHandleIdentity + '-handle')
.attr('class', 'drag-handle-active grab');
var fartherDragHandleIdentity;
// TODO refactor this for maintability
if (nearerDragHandleIdentity === 'source') {
fartherDragHandleIdentity = 'target';
}
else {
fartherDragHandleIdentity = 'source';
}
fartherDragHandle = d3.select('#' + d.id + '-' + fartherDragHandleIdentity + '-handle')
.attr('class', 'drag-handle-inactive');
}
})
.on('mousedown', function(d) {
selectedEdge.attr('class', 'element edge-selected');
nearerDragHandle.attr('class', 'grabbing');
d3.select('svg').attr('class', 'grabbing');
})
.on('mouseup', function(d) {
d3.select('svg').attr('class',null);
})
.on('mouseout', function(d) {
if (!dragging) {
window.setTimeout(function() {
d3.select('#' + d.id + '-source-handle').attr('class', 'drag-handle');
d3.select('#' + d.id + '-target-handle').attr('class', 'drag-handle');
}, 400);
}
})
.call(drag);
elements.attr({
style: function(d) {
var styleString = d.style,
firstPoint, lastPoint, xDistance, yDistance;
/* this makes the cursor a double-headed arrow to indicate that the user can move an edge end point
// removing this code sends us back to using the grabbing cursor on hover
// we could also look at using the single-headed arrows
if (d.renderableType === 'edge') {
firstPoint = d.points[0];
lastPoint = d.points[d.points.length - 1];
xDistance = Math.abs(lastPoint.x - firstPoint.x);
yDistance = Math.abs(lastPoint.y - firstPoint.y);
if (yDistance > xDistance) {
styleString += 'cursor: ns-resize';
}
else {
styleString += 'cursor: ew-resize';
}
}
//*/
return styleString;
},
x: function(d) { return d.x; },
y: function(d) { return d.y; },
width: function(d) { return d.width; },
height: function(d) { return d.height; },
d: function(d) {
return calculatePathData(d).d;
}
});
elements.exit().remove();
if (!!callback) {
callback(elements);
};
};
var init = function() {
var viewport = d3.select('#viewport');
update(function(elements) {
elements.each(function(d){
console.log(this);
console.log(d);
var element = d3.select(this);
var sourceHandle, sourceHandle2, targetHandle, targetHandle2, sourcePoint, targetPoint, points;
if (d.renderableType === 'edge') {
console.log('edge');
points = d.points;
sourcePoint = points[0];
targetPoint = points[points.length - 1];
sourceHandle = viewport.selectAll('#' + d.id + '-source-handle')
.data([ d ])
.enter()
.append('circle')
.attr('id', d.id + '-source-handle')
sourceHandle2 = d3.select('#' + d.id + '-source-handle')
.attr('cx', sourcePoint.x)
.attr('cy', sourcePoint.y)
.attr('r', 4)
.attr('class', 'drag-handle')
.on('mousedown', function(d) {
d3.select('#' + d.id).attr('class', 'element edge-selected');
console.log(d3.select('#' + d.id));
d3.select('svg').attr('class', 'grabbing');
d3.select(this).attr('class','drag-handle grabbing');
})
.on('mouseup', function(d) {
d3.select('#' + d.id).attr('class', 'element edge');
d3.select('svg').attr('class',null);
d3.select(this).attr('class','drag-handle');
})
.call(drag);
targetHandle = viewport.selectAll('#' + d.id + '-target-handle')
.data([ d ])
.enter()
.append('circle')
.attr('id', d.id + '-target-handle');
targetHandle2 = d3.select('#' + d.id + '-target-handle')
.attr('cx', targetPoint.x)
.attr('cy', targetPoint.y)
.attr('r', 4)
.attr('class', 'drag-handle')
.on('mousedown', function(d) {
d3.select('#' + d.id).attr('class', 'element edge');
d3.select('svg').attr('class', 'grabbing');
d3.select(this).attr('class','drag-handle grabbing');
})
.on('mouseup', function(d) {
d3.select('#' + d.id).attr('class', 'element edge');
d3.select('svg').attr('class',null);
d3.select(this).attr('class','drag-handle');
})
.call(drag);
}
});
});
};
init();
</script>
</body>
</html>
<!DOCTYPE html>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<style>
body {
font: 10px sans-serif;
}
/*
.drag-handle {
fill: transparent;
fill-opacity: 1;
stroke: transparent;
stroke-width: 0;
}
*/
.drag-handle {
fill: transparent;
stroke: orange;
stroke-width: 5px;
}
.drag-handle:hover {
fill: transparent;
stroke: green;
stroke-width: 10px;
}
.grab {
cursor: -moz-grab;
cursor: -webkit-grab;
cursor: grab;
}
.grabbing {
cursor: -moz-grabbing;
cursor: -webkit-grabbing;
cursor: grabbing;
}
</style>
<body>
<div id="diagram"></div>
<p>
Input:
</p>
<p id="input">
</p>
<p>
Output:
</p>
<p id="output">
</p>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script>
'use strict';
var dragging = false;
var diagramData = {
viewport:[
{
id: 'id123',
renderableType: 'node',
x: 50,
y: 50,
width: 80,
height: 20,
style: 'stroke: blue; fill: white;'
},
{
id: 'id234',
renderableType: 'node',
x: 200,
y: 50,
width: 80,
height: 20,
style: 'stroke: blue; fill: white;'
},
{
id: 'id345',
renderableType: 'edge',
points:[
{
x: 130,
y: 60
},
{
x: 200,
y: 60
}
],
anchors: [
{
id: 'id567',
position: 0.3
}
],
hasAnchoredDependencies: [
'id456'
],
style: 'stroke: black; stroke-width: 1; fill:yellow;'
},
{
id: 'id456',
renderableType: 'edge',
points:[
{
x: 165,
y: 20
},
{
element: 'id345',
anchor: 'id567'
}
],
style: 'stroke: black; stroke-width: 1; fill:yellow;'
}
]
};
var inputJsonString = JSON.stringify(diagramData);
d3.select('#input').text(inputJsonString);
var dragSegment, selectedPoint, selectedEdge, selectedEdgeElement, dragPointX, dragPointY, nearerDragHandle, fartherDragHandle;
var getNearestDragHandleIdentity = function(d, dragPointX, dragPointY) {
var nearerDragHandleIdentity;
selectedEdge = d3.select('#' + d.id);
selectedEdgeElement = selectedEdge[0][0];
var numberOfItems = selectedEdgeElement.pathSegList.numberOfItems;
var sourcePoint = d.points[0];
var sourcePointX = sourcePoint.x;
var sourcePointY = sourcePoint.y;
var dragPointToSourcePointDistance = Math.sqrt(Math.pow((dragPointX - sourcePointX),2) + Math.pow((dragPointY - sourcePointY),2));
var targetPoint = d.points[d.points.length - 1];
var targetPointX = targetPoint.x;
var targetPointY = targetPoint.y;
var dragPointToTargetPointDistance = Math.sqrt(Math.pow((dragPointX - targetPointX),2) + Math.pow((dragPointY - targetPointY),2));
if (dragPointToTargetPointDistance < dragPointToSourcePointDistance) {
selectedPoint = targetPoint;
dragSegment = selectedEdgeElement.pathSegList.getItem(0);
nearerDragHandleIdentity = 'target';
}
else {
selectedPoint = sourcePoint;
dragSegment = selectedEdgeElement.pathSegList.getItem(numberOfItems - 1);
nearerDragHandleIdentity = 'source';
}
return nearerDragHandleIdentity;
};
var drag = d3.behavior.drag()
.on("dragstart", function(d) {
dragging = true;
dragPointX = d3.event.sourceEvent.x;
dragPointY = d3.event.sourceEvent.y;
var dragHandleIdentities = getNearestDragHandleIdentity(d, dragPointX, dragPointY);
})
.on("drag", dragmove)
.on("dragend", function(d) {
dragging = false;
console.log('this');
console.log(this);
console.log('this');
console.log(this);
/*
var dragHandle = d3.select(this)
.attr('cx', dragPointX)
.attr('cy', dragPointY);
//*/
selectedEdge.attr('d', function(d) {
return calculatePathData(d).d;
});
diagramData.viewport = d3.select('#viewport').datum();
var outputJsonString = JSON.stringify(diagramData);
d3.select('#output').text(outputJsonString);
d3.select('svg').attr('class',null);
init();
});
function dragmove(d) {
dragPointX = d3.event.x;
dragPointY = d3.event.y;
dragSegment.x = dragPointX;
dragSegment.y = dragPointY;
selectedPoint.x = dragPointX;
selectedPoint.y = dragPointY;
var selectedEdgeElementLength = selectedEdgeElement.getTotalLength(),
//selectedEdgeElementLength = selectedEdgeElement.getTotalLength() - 185.9791717529297,
anchorPoint,
anchorPoints = {},
elementToUpdate,
pointsToUpdate,
pointToUpdate;
diagramData.viewport = d3.select('#viewport').datum();
if (d.hasOwnProperty('anchors')) {
d.anchors.forEach(function(anchor) {
anchorPoints[anchor.id] = selectedEdgeElement.getPointAtLength(selectedEdgeElementLength * anchor.position);
});
d.hasAnchoredDependencies.forEach(function(elementId) {
elementToUpdate = diagramData.viewport.filter(function(element) {
return element.id === elementId;
})[0];
pointsToUpdate = elementToUpdate.points.filter(function(point) {
return point.hasOwnProperty('anchor');
});
pointsToUpdate.forEach(function(pointToUpdate) {
anchorPoint = anchorPoints[pointToUpdate.anchor];
if (!!anchorPoint) {
pointToUpdate.x = anchorPoint.x;
pointToUpdate.y = anchorPoint.y;
}
});
});
}
update();
}
var svg = d3.select('#diagram').append('svg')
.attr('width', 400)
.attr('height', 200)
.attr('style', 'border:1px solid black');
var viewport = svg.selectAll('#viewport')
.data([diagramData.viewport])
.enter()
.append('g')
.attr('id', 'viewport');
var calculatePathData = function(d) {
var d,
firstPathSegString,
pathData = {};
if (d.hasOwnProperty('points')) {
d.points.map(function(point, index) {
var targetEdge, targetEdgeElement, targetEdgeElementLength, anchor, anchorPoint;
if (!point.hasOwnProperty('x')) {
targetEdge = d3.select('#' + point.element);
targetEdgeElement = targetEdge[0][0];
targetEdgeElementLength = targetEdgeElement.getTotalLength();
anchor = targetEdge.datum().anchors.filter(function(anchor) {return anchor.id === point.anchor;})[0];
anchorPoint = targetEdgeElement.getPointAtLength(targetEdgeElementLength * anchor.position);
point.x = anchorPoint.x;
point.y = anchorPoint.y;
}
if (index > 0) {
d += ' L ' + point.x + ' ' + point.y;
}
else {
d = firstPathSegString = 'M ' + point.x + ' ' + point.y;
}
});
}
pathData.d = d;
pathData.firstPathSegString = firstPathSegString;
return pathData;
};
var update = function(callback){
var renderableTypeToSvgElementMappings = {
'node':'rect',
'edge':'path'
};
var elements = viewport.selectAll('.element')
.data(function(d) {
return d;
})
.attr('id', function(d) {
return d.id;
})
.attr('class', function(d) {
var cssClassString = 'element ' + d.renderableType;
return cssClassString;
});
elements.enter()
.append(function(d) {
var childElementName = renderableTypeToSvgElementMappings[d.renderableType];
var child = document.createElementNS('http://www.w3.org/2000/svg', childElementName);
return child;
})
.attr('id', function(d) {
return d.id;
})
.attr('class', function(d) {
var cssClassString = 'element ' + d.renderableType;
return cssClassString;
});
elements.attr({
style: function(d) {
var styleString = d.style,
firstPoint, lastPoint, xDistance, yDistance;
/* this makes the cursor a double-headed arrow to indicate that the user can move an edge end point
// removing this code sends us back to using the grabbing cursor on hover
// we could also look at using the single-headed arrows
if (d.renderableType === 'edge') {
firstPoint = d.points[0];
lastPoint = d.points[d.points.length - 1];
xDistance = Math.abs(lastPoint.x - firstPoint.x);
yDistance = Math.abs(lastPoint.y - firstPoint.y);
if (yDistance > xDistance) {
styleString += 'cursor: ns-resize';
}
else {
styleString += 'cursor: ew-resize';
}
}
//*/
return styleString;
},
x: function(d) { return d.x; },
y: function(d) { return d.y; },
width: function(d) { return d.width; },
height: function(d) { return d.height; },
d: function(d) {
return calculatePathData(d).d;
}
});
elements.exit().remove();
if (!!callback) {
callback(elements);
};
};
var init = function() {
var viewport = d3.select('#viewport');
update(function(elements) {
elements.each(function(d){
console.log(this);
console.log(d);
var element = d3.select(this);
var sourceHandle, sourceHandle2, targetHandle, targetHandle2, sourcePoint, targetPoint, points;
if (d.renderableType === 'edge') {
console.log('edge');
var edge = d3.select('#' + d.id);
var edgeElement = edge[0][0];
var edgeLength = edgeElement.getTotalLength();
var distanceAlongEdge = Math.min(15, edgeLength/3);
points = d.points;
sourcePoint = points[0];
targetPoint = points[points.length - 1];
sourceHandle = viewport.selectAll('#' + d.id + '-source-handle')
.data([ d ])
.enter()
.append('path')
.attr('id', d.id + '-source-handle')
sourceHandle2 = d3.select('#' + d.id + '-source-handle')
.attr('d', function(d) {
var firstPoint = d.points[0];
var point0 = edgeElement.getPointAtLength(0);
var point1 = edgeElement.getPointAtLength(distanceAlongEdge);
return 'M ' + point0.x + ' ' + point0.y + ' L ' + point1.x + ' ' + point1.y;
})
.attr('class', 'drag-handle')
.on('mouseover', function(d) {
d3.select(this).attr('class','drag-handle grab');
})
.on('mousedown', function(d) {
console.log(d3.select('#' + d.id));
d3.select('#' + d.id).attr('class', 'element edge-selected');
d3.select('svg').attr('class', 'grabbing');
d3.select(this).attr('class','drag-handle grabbing');
})
.on('mouseup', function(d) {
d3.select('#' + d.id).attr('class', 'element edge');
d3.select('svg').attr('class',null);
d3.select(this).attr('class','drag-handle');
})
.call(drag);
targetHandle = viewport.selectAll('#' + d.id + '-target-handle')
.data([ d ])
.enter()
.append('path')
.attr('id', d.id + '-target-handle');
targetHandle2 = d3.select('#' + d.id + '-target-handle')
.attr('d', function(d) {
var lastPoint = d.points[d.points.length - 1];
var point0 = edgeElement.getPointAtLength(edgeLength);
var point1 = edgeElement.getPointAtLength(edgeLength - distanceAlongEdge);
return 'M ' + point0.x + ' ' + point0.y + ' L ' + point1.x + ' ' + point1.y;
})
.attr('class', 'drag-handle')
.on('mouseover', function(d) {
d3.select(this).attr('class','drag-handle grab');
})
.on('mousedown', function(d) {
d3.select('#' + d.id).attr('class', 'element edge-selected');
d3.select('svg').attr('class', 'grabbing');
d3.select(this).attr('class','drag-handle grabbing');
})
.on('mouseup', function(d) {
d3.select('#' + d.id).attr('class', 'element edge');
d3.select('svg').attr('class',null);
d3.select(this).attr('class','drag-handle');
})
.call(drag);
}
});
});
};
init();
</script>
</body>
</html>
<!DOCTYPE html>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<link rel="stylesheet" href="html.css" />
<link rel="stylesheet" href="annotated.css" />
<style>
body {
font: 10px sans-serif;
}
.drag-handle {
fill: transparent;
stroke: transparent;
stroke-width: 10px;
}
.drag-handle:hover {
fill: transparent;
stroke: transparent;
stroke-width: 15px;
}
.grab {
cursor: -moz-grab;
cursor: -webkit-grab;
cursor: grab;
}
.grabbing {
cursor: -moz-grabbing;
cursor: -webkit-grabbing;
cursor: grabbing;
}
</style>
<body>
<h1>D3 Drag and Update Example</h1>
<h2>Independent, Invisible Drag Handles with Real Pathway Data</h2>
<div id="diagram"></div>
<div id="original" style="float:left">
<p>Input</p>
<textarea name="textarea" id="original-json" rows="1000" cols="50">Write something here</textarea>
</div>
<div id="current" style="float:left">
<p>Current</p>
<textarea name="textarea" id="current-json" rows="1000" cols="50"></textarea>
</div>
<div id="diff" style="float:left">
<p>Diff</p>
<div id="visual"></div>
</div>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="bundle.min.js"></script>
<script src="formatters.min.js"></script>
<script src="drag-update.js"></script>
<script>
window.onload = function() {
dragUpdate.init();
}
</script>
</body>
{
"viewport": [
{
"height": 21,
"id": "fbf",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61,
"x": 128.74774509060222,
"y": 125.66666666666669
},
{
"height": 21,
"id": "b69",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 51.49997456868482,
"x": 348.0000254313152,
"y": 150.5
},
{
"height": 21,
"id": "e28",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61,
"x": 396.1666666666667,
"y": 184.66666666666666
},
{
"height": 21,
"id": "d4e",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61,
"x": 664,
"y": 141.83333333333334
},
{
"height": 21,
"id": "cc2",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61,
"x": 159.16666666666666,
"y": 315.3333333333333
},
{
"height": 21,
"id": "b8d",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61,
"x": 446,
"y": 317.8333333333333
},
{
"height": 21,
"id": "e9a",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61,
"x": 287.5000254313151,
"y": 314.8333333333333
},
{
"height": 21,
"id": "d70",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61,
"x": 358.99999999999994,
"y": 343.4833272298177
},
{
"height": 21,
"id": "daf",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61,
"x": 207.33333333333334,
"y": 397.9833272298177
},
{
"height": 21,
"id": "f52",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61,
"x": 281.33333333333303,
"y": 435.83333333333314
},
{
"height": 21,
"id": "cb6",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61,
"x": 303.33333333333354,
"y": 493.5
},
{
"height": 21,
"id": "a40",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61,
"x": 305.33333333333354,
"y": 605.3333333333334
},
{
"height": 21,
"id": "a69",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61,
"x": 525.1666666666669,
"y": 447.1666666666669
},
{
"height": 21,
"id": "a7f",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61,
"x": 468.16666666666674,
"y": 536
},
{
"height": 21,
"id": "ab1",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61.00000000000008,
"x": 630.6666666666666,
"y": 422.83333333333354
},
{
"height": 21,
"id": "e7e",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61.00000000000008,
"x": 630.6666666666666,
"y": 402.83333333333354
},
{
"height": 21,
"id": "a92",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61,
"x": 690.6666666666666,
"y": 402.83333333333354
},
{
"height": 21,
"id": "aa0",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61.00000000000008,
"x": 690.6666666666666,
"y": 422.83333333333354
},
{
"height": 21,
"id": "ba4",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61,
"x": 525.1666666666669,
"y": 427.1666666666669
},
{
"height": 20,
"id": "a2a",
"renderableType": "node",
"style": "stroke: #0000ff; fill:#ffffff;",
"width": 94.33333333333333,
"x": 268.3333435058594,
"y": 218.49999491373697
},
{
"height": 20,
"id": "e91",
"renderableType": "node",
"style": "stroke: #0000ff; fill:#ffffff;",
"width": 70.16666666666663,
"x": 280.83333333333337,
"y": 104.33333333333333
},
{
"height": 20,
"id": "e98",
"renderableType": "node",
"style": "stroke: #0000ff; fill:#ffffff;",
"width": 69.33333333333333,
"x": 197.16666666666669,
"y": 623.6666666666666
},
{
"height": 21,
"id": "cb32b",
"renderableType": "node",
"style": "stroke: #0000ff; fill:#ffffff;",
"width": 66,
"x": 50.24774572638509,
"y": 71
},
{
"height": 21,
"id": "bfc36",
"renderableType": "node",
"style": "stroke: #0000ff; fill:#ffffff;",
"width": 46,
"x": 127,
"y": 94
},
{
"height": 21,
"id": "ba1b2",
"renderableType": "node",
"style": "stroke: #0000ff; fill:#ffffff;",
"width": 86,
"x": 470,
"y": 218
},
{
"height": 21,
"id": "e00d0",
"renderableType": "node",
"style": "stroke: #0000ff; fill:#ffffff;",
"width": 56,
"x": 410.5,
"y": 113.5
},
{
"height": 21,
"id": "aceb7",
"renderableType": "node",
"style": "stroke: #0000ff; fill:#ffffff;",
"width": 75.5,
"x": 559,
"y": 194
},
{
"height": 21,
"id": "fc934",
"renderableType": "node",
"style": "stroke: #0000ff; fill:#ffffff;",
"width": 81,
"x": 654.5,
"y": 218
},
{
"height": 21,
"id": "ef70b",
"renderableType": "node",
"style": "stroke: #0000ff; fill:#ffffff;",
"width": 33.016666666666666,
"x": 134.48333333333335,
"y": 361.48333333333335
},
{
"height": 21,
"id": "cea19",
"renderableType": "node",
"style": "stroke: #0000ff; fill:#ffffff;",
"width": 33.016666666666666,
"x": 298.99167989095054,
"y": 361.48333333333335
},
{
"height": 21,
"id": "b20a2",
"renderableType": "node",
"style": "stroke: #0000ff; fill:#ffffff;",
"width": 33.016666666666666,
"x": 414.48333333333335,
"y": 382.48333333333335
},
{
"height": 21,
"id": "d8ba4",
"renderableType": "node",
"style": "stroke: #0000ff; fill:#ffffff;",
"width": 33.016666666666666,
"x": 385.98333333333335,
"y": 446.48333333333335
},
{
"height": 21,
"id": "bb1eb",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61,
"x": 125.33333333333348,
"y": 554.9999999999997
},
{
"height": 21,
"id": "a658e",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61,
"x": 125.33333333333348,
"y": 574.9999999999997
},
{
"height": 21,
"id": "a8000",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61,
"x": 413.1666666666668,
"y": 605.333333333334
},
{
"height": 20,
"id": "a2188",
"renderableType": "node",
"style": "stroke: #0000ff; fill:#ffffff;",
"width": 69.33333333333333,
"x": 508.6666666666667,
"y": 621.6666666666666
},
{
"height": 21,
"id": "ccc26",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61.00000000000008,
"x": 630.6666666666666,
"y": 442.83333333333354
},
{
"height": 21,
"id": "ae20e",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61.00000000000008,
"x": 690.6666666666666,
"y": 442.83333333333354
},
{
"height": 21,
"id": "fdc15",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 50,
"x": 572.25,
"y": 314
},
{
"height": 21,
"id": "b209b",
"renderableType": "node",
"style": "stroke: #0000ff; fill:#ffffff;",
"width": 47,
"x": 582.5,
"y": 95.5
},
{
"height": 21,
"id": "d7db1",
"renderableType": "node",
"style": "stroke: #0000ff; fill:#ffffff;",
"width": 69,
"x": 48.74774572638509,
"y": 174
},
{
"height": 21,
"id": "a2c50",
"renderableType": "node",
"style": "stroke: #0000ff; fill:#ffffff;",
"width": 68,
"x": 127,
"y": 218
},
{
"height": 21,
"id": "e9de6",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 51.75225427361491,
"x": 40.24774572638509,
"y": 245
},
{
"height": 21,
"id": "d8c9e",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 44,
"x": 202,
"y": 181
},
{
"height": 21,
"id": "a47e8",
"renderableType": "node",
"style": "stroke: #0000ff; fill:#ffffff;",
"width": 54.75,
"x": 497.75,
"y": 113.75
},
{
"height": 21,
"id": "f1bbc",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 103,
"x": 430.5,
"y": 75.5
},
{
"height": 21,
"id": "ea69f",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 50,
"x": 572.25,
"y": 294
},
{
"height": 20,
"id": "d2a61",
"renderableType": "node",
"style": "stroke: #0000ff; fill:#ffffff;",
"width": 69.33333333333333,
"x": 359.1666666666667,
"y": 541.1666666666666
},
{
"height": 21,
"id": "bbbff",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 61,
"x": 525.1666666666669,
"y": 467.16666666666697
},
{
"height": 21,
"id": "d07b8",
"renderableType": "node",
"style": "stroke: #0000ff; fill:#ffffff;",
"width": 81,
"x": 556,
"y": 519
},
{
"height": 21,
"id": "a990e",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 81,
"x": 348.17550402772156,
"y": 665.7912447684622
},
{
"height": 21,
"id": "d71f9",
"renderableType": "node",
"style": "stroke: #000000; fill:#ffffff;",
"width": 81,
"x": 348.17550402772156,
"y": 685.7912447684621
},
{
"id": "b5913",
"renderableType": "edge",
"hasAnchoredDependencies": [
"c1688"
],
"anchors": [
{
"id": "a2c25",
"position": "0.532258064516129"
}
],
"points": [
{
"x": 82.74774572638509,
"y": 91
},
{
"x": 82.74774572638509,
"y": 174
}
],
"style": "stroke: #008040;"
},
{
"id": "b1c07",
"renderableType": "edge",
"points": [
{
"x": 127,
"y": 104
},
{
"x": 109.70007311442089,
"y": 135.46407922232476,
"anchor": "ebe5a",
"element": "c1688"
}
],
"style": "stroke: #ff0000;"
},
{
"id": "f6437",
"renderableType": "edge",
"hasAnchoredDependencies": [
"id4aefea78"
],
"anchors": [
{
"id": "a4d13",
"position": "0.6010452755119678"
}
],
"points": [
{
"x": 315.000010172526,
"y": 218.49999491373697
},
{
"x": 315.4166666666667,
"y": 123.33333333333333
}
],
"style": "stroke: #008040;"
},
{
"id": "d65e1",
"renderableType": "edge",
"hasAnchoredDependencies": [
"id561097a3"
],
"anchors": [
{
"id": "c907c",
"position": "0.5984615016237494"
}
],
"points": [
{
"x": 361.66667683919263,
"y": 227.99999491373697
},
{
"x": 470,
"y": 228
}
],
"style": "stroke: #008040;"
},
{
"id": "f3edf",
"renderableType": "edge",
"hasAnchoredDependencies": [
"id740045bc"
],
"anchors": [
{
"id": "e76f1",
"position": "0.5095694152942244"
}
],
"points": [
{
"x": 465.5,
"y": 123.5
},
{
"x": 497.75,
"y": 123.75
}
],
"style": "stroke: #008040;"
},
{
"id": "d870f",
"renderableType": "edge",
"hasAnchoredDependencies": [
"idb248dd5c",
"id52ac424a",
"idb3964d3f"
],
"anchors": [
{
"id": "edbc5",
"position": "0.4"
}
],
"points": [
{
"x": 605.5,
"y": 115.5
},
{
"x": 674.5,
"y": 218
}
],
"style": "stroke: #008040;"
},
{
"id": "b61b3",
"renderableType": "edge",
"points": [
{
"x": 315.00001322428386,
"y": 361.48333333333335
},
{
"x": 315.000010172526,
"y": 237.49999491373697
}
],
"style": "stroke: #008040;"
},
{
"id": "e011c",
"renderableType": "edge",
"points": [
{
"x": 150.49166666666667,
"y": 361.48333333333335
},
{
"x": 291.6666768391927,
"y": 237.49999491373697
}
],
"style": "stroke: #008000;"
},
{
"id": "bb407",
"renderableType": "edge",
"hasAnchoredDependencies": [
"idb92332b0"
],
"anchors": [
{
"id": "ec3e3",
"position": "0.46638477808330747"
}
],
"points": [
{
"x": 298.99167989095054,
"y": 371.48333333333335
},
{
"x": 166.5,
"y": 371.48333333333335
}
],
"style": "stroke: #008000;"
},
{
"id": "b2711",
"renderableType": "edge",
"hasAnchoredDependencies": [
"id3adcd55e"
],
"anchors": [
{
"id": "d552e",
"position": "0.4"
}
],
"points": [
{
"x": 414.48333333333335,
"y": 392.48333333333335
},
{
"x": 331.0083465576172,
"y": 371.48333333333335
}
],
"style": "stroke: #008000;"
},
{
"id": "d0da5",
"renderableType": "edge",
"hasAnchoredDependencies": [
"id54146f13"
],
"anchors": [
{
"id": "f7c1d",
"position": "0.4"
}
],
"points": [
{
"x": 393.9875,
"y": 446.48333333333335
},
{
"x": 323.0041798909505,
"y": 381.48333333333335
}
],
"style": "stroke: #008000;"
},
{
"id": "e790f",
"renderableType": "edge",
"points": [
{
"x": 422.4875,
"y": 402.48333333333335
},
{
"x": 409.99583333333334,
"y": 446.48333333333335
}
],
"style": "stroke: #008000;"
},
{
"id": "ba6c7",
"renderableType": "edge",
"hasAnchoredDependencies": [
"id64bad4e5"
],
"anchors": [
{
"id": "f13ee",
"position": "0.701099450276439"
}
],
"points": [
{
"x": 556,
"y": 529
},
{
"x": 409.99583333333334,
"y": 466.48333333333335
}
],
"style": "stroke: #008000;"
},
{
"id": "a82d3",
"renderableType": "edge",
"hasAnchoredDependencies": [
"id7a2680f1"
],
"anchors": [
{
"id": "b11b2",
"position": "0.4"
}
],
"points": [
{
"x": 418,
"y": 456.48333333333335
},
{
"x": 556,
"y": 529
}
],
"style": "stroke: #008000;"
},
{
"id": "c1688",
"renderableType": "edge",
"hasAnchoredDependencies": [
"b1c07"
],
"anchors": [
{
"id": "ebe5a",
"position": "0.41407983129230874"
}
],
"points": [
{
"x": 128.74774509060222,
"y": 135.66666666666669
},
{
"x": 82.74774572638509,
"y": 135.17741935483872,
"anchor": "a2c25",
"element": "b5913"
}
],
"style": "stroke: #000000;"
},
{
"id": "b4769",
"renderableType": "edge",
"points": [
{
"x": 350.33333333333354,
"y": 605.3333333333334
},
{
"x": 376.25000000000006,
"y": 560.1666666666666
}
],
"style": "stroke: #000000;"
},
{
"id": "id6a4e25b5",
"renderableType": "edge",
"points": [
{
"x": 433,
"y": 604.75
},
{
"x": 393.33333333333337,
"y": 560.1666666666666
}
],
"style": "stroke: #000000;"
},
{
"id": "id2abec5f6",
"renderableType": "edge",
"hasAnchoredDependencies": [
"id208b4fc4"
],
"anchors": [
{
"id": "aebc6",
"position": "0.49763813984634164"
}
],
"points": [
{
"x": 393.33333333333337,
"y": 541.1666666666666
},
{
"x": 393.9875,
"y": 466.48333333333335
}
],
"style": "stroke: #006600;"
},
{
"id": "id129bdce0",
"renderableType": "edge",
"points": [
{
"x": 418,
"y": 456.48333333333335
},
{
"x": 338.3333435058593,
"y": 237.49999491373697
}
],
"style": "stroke: #006600;"
},
{
"id": "idba67fe43",
"renderableType": "edge",
"hasAnchoredDependencies": [
"id5e009fa2"
],
"anchors": [
{
"id": "fef65",
"position": "0.4929575239801747"
}
],
"points": [
{
"x": 82.74774572638509,
"y": 194
},
{
"x": 127,
"y": 228
}
],
"style": "stroke: #006600;"
},
{
"id": "id5e009fa2",
"renderableType": "edge",
"points": [
{
"x": 78.31193643159628,
"y": 245
},
{
"x": 96.86430236148772,
"y": 219.71972515639618,
"anchor": "fef65",
"element": "idba67fe43"
}
],
"style": "stroke: #000000;"
},
{
"id": "ide4c980d3",
"renderableType": "edge",
"hasAnchoredDependencies": [
"idb782318c"
],
"anchors": [
{
"id": "f144f",
"position": "0.4"
}
],
"points": [
{
"x": 194,
"y": 228
},
{
"x": 268.3333435058594,
"y": 227.99999491373697
}
],
"style": "stroke: #006600;"
},
{
"id": "idb782318c",
"renderableType": "edge",
"points": [
{
"x": 223.5,
"y": 201
},
{
"x": 223.73333740234375,
"y": 227.9999979654948,
"anchor": "f144f",
"element": "ide4c980d3"
}
],
"style": "stroke: #000000;"
},
{
"id": "id4aefea78",
"renderableType": "edge",
"points": [
{
"x": 348.0000254313152,
"y": 160.5
},
{
"x": 315.25043958984065,
"y": 161.30052258458906,
"anchor": "a4d13",
"element": "f6437"
}
],
"style": "stroke: #000000;"
},
{
"id": "id561097a3",
"renderableType": "edge",
"points": [
{
"x": 426.1666666666667,
"y": 204.66666666666666
},
{
"x": 426.5000000939003,
"y": 227.9999979576696,
"anchor": "c907c",
"element": "d65e1"
}
],
"style": "stroke: #000000;"
},
{
"id": "id740045bc",
"renderableType": "edge",
"points": [
{
"x": 481.5,
"y": 95.5
},
{
"x": 481.93361364323874,
"y": 123.62739235382355,
"anchor": "e76f1",
"element": "f3edf"
}
],
"style": "stroke: #000000;"
},
{
"id": "idb248dd5c",
"renderableType": "edge",
"points": [
{
"x": 664,
"y": 151.83333333333334
},
{
"x": 633.1,
"y": 156.5,
"anchor": "edbc5",
"element": "d870f"
}
],
"style": "stroke: #000000;"
},
{
"id": "id52ac424a",
"renderableType": "edge",
"points": [
{
"x": 538.0625,
"y": 133.75
},
{
"x": 633.1,
"y": 156.5,
"anchor": "edbc5",
"element": "d870f"
}
],
"style": "stroke: #006633;"
},
{
"id": "idb3964d3f",
"renderableType": "edge",
"points": [
{
"x": 633.1,
"y": 156.5,
"anchor": "edbc5",
"element": "d870f"
},
{
"x": 614.875,
"y": 194
}
],
"style": "stroke: #006633;"
},
{
"id": "id208b4fc4",
"renderableType": "edge",
"points": [
{
"x": 363.33333333333354,
"y": 503.5
},
{
"x": 393.6588716164828,
"y": 504.0013915891424,
"anchor": "aebc6",
"element": "id2abec5f6"
}
],
"style": "stroke: #000000;"
},
{
"id": "id54146f13",
"renderableType": "edge",
"points": [
{
"x": 341.33333333333303,
"y": 445.83333333333314
},
{
"x": 365.5941719563802,
"y": 420.48333333333335,
"anchor": "f7c1d",
"element": "d0da5"
}
],
"style": "stroke: #000000;"
},
{
"id": "id3adcd55e",
"renderableType": "edge",
"points": [
{
"x": 388.99999999999994,
"y": 363.4833272298177
},
{
"x": 381.09333862304686,
"y": 384.08333333333337,
"anchor": "d552e",
"element": "b2711"
}
],
"style": "stroke: #000000;"
},
{
"id": "idb92332b0",
"renderableType": "edge",
"points": [
{
"x": 237.33333333333337,
"y": 397.9833272298177
},
{
"x": 237.19957716712497,
"y": 371.48333333333335,
"anchor": "ec3e3",
"element": "bb407"
}
],
"style": "stroke: #006633;"
},
{
"id": "id7a2680f1",
"renderableType": "edge",
"points": [
{
"x": 513.1666666666669,
"y": 457.16666666666697
},
{
"x": 473.2,
"y": 485.49,
"anchor": "b11b2",
"element": "a82d3"
}
],
"style": "stroke: #000000;"
},
{
"id": "id64bad4e5",
"renderableType": "edge",
"points": [
{
"x": 468.16666666666674,
"y": 546
},
{
"x": 439.6880504456605,
"y": 505.82823846118526,
"anchor": "f13ee",
"element": "ba6c7"
}
],
"style": "stroke: #000000;"
},
{
"id": "id3ee32f14",
"renderableType": "edge",
"points": [
{
"x": 388.17550402772156,
"y": 657.7912447684621
},
{
"x": 350.33333333333354,
"y": 625.3333333333334
}
],
"style": "stroke: #000000;"
},
{
"id": "id3976b167-9266-4125-8c83-739b1b86f34a",
"renderableType": "edge",
"points": [
{
"x": 555,
"y": 228
},
{
"x": 596.75,
"y": 282
}
],
"style": "stroke: #000000;"
},
{
"id": "ida81c40a5-026e-4e39-a9a6-694b8533f105",
"renderableType": "edge",
"points": [
{
"x": 214.25,
"y": 623.6666666666666
},
{
"x": 193.33333333333348,
"y": 574.9999999999997
}
],
"style": "stroke: #000000;"
},
{
"id": "id834a20bc-e8fc-44d4-8b60-6913b1dd1465",
"renderableType": "edge",
"points": [
{
"x": 508.66666666666674,
"y": 631.1666666666666
},
{
"x": 458.1666666666668,
"y": 625.333333333334
}
],
"style": "stroke: #000000;"
},
{
"id": "d9a19",
"renderableType": "edge",
"points": [
{
"x": 388.17550402772156,
"y": 657.7912447684621
},
{
"x": 428.1666666666668,
"y": 625.333333333334
}
],
"style": "stroke: #000000;"
},
{
"id": "d6e4f",
"renderableType": "edge",
"points": [
{
"x": 596.25,
"y": 214
},
{
"x": 596.75,
"y": 282
}
],
"style": "stroke: #000000;"
},
{
"id": "cd80c",
"renderableType": "edge",
"points": [
{
"x": 654.5,
"y": 228
},
{
"x": 596.75,
"y": 282
}
],
"style": "stroke: #000000;"
}
]
}
// TODO this code is terrible and hacky. It's just a quick data-munge, not anything worth keeping.
var newExample = {viewport:[]};
myPathway.DataNode.forEach(function(DataNode){
var newElement = {};
newElement.height = DataNode.height;
newElement.id = DataNode.id;
newElement.renderableType = 'node';
newElement.style = "stroke: " + DataNode.borderColor + "; fill:" + DataNode.backgroundColor + ";";
newElement.width = DataNode.width;
newElement.x = DataNode.x;
newElement.y = DataNode.y;
newExample.viewport.push(newElement);
});
myPathway.Interaction.forEach(function(Interaction){
var newElement = {};
newElement.id = Interaction.id;
newElement.renderableType = 'edge';
if (Interaction.hasOwnProperty('Anchor')) {
newElement.hasAnchoredDependencies = [];
newElement.anchors = Interaction.Anchor.map(function(anchor){
var dependencies = myPathway.Interaction.filter(function(interaction){
return interaction.Point.filter(function(point){return anchor.id === point.hasReference;}).length > 0;
});
console.log('Interaction');
console.log(Interaction);
console.log('dependencies');
console.log(dependencies);
if (dependencies.length > 0) {
var dependencyIds = dependencies.map(function(dependency){
return dependency.id;
});
newElement.hasAnchoredDependencies = newElement.hasAnchoredDependencies.concat(dependencyIds);
}
var newAnchor = {};
newAnchor.id = anchor.id;
newAnchor.position = anchor.anchorPosition;
return newAnchor;
});
}
newElement.points = [];
Interaction.Point.forEach(function(point, index){
if (index === 0 || (index === Interaction.Point.length - 1)) {
var newPoint = {};
newPoint.x = point.x;
newPoint.y = point.y;
if (point.hasOwnProperty('hasReference')) {
var references = myPathway.elements.filter(function(element){return element.GraphId === point.hasReference;});
if (references.length === 0) {
newPoint.anchor = point.hasReference;
newPoint.element = myPathway.Interaction.filter(function(interaction){
if (interaction.hasOwnProperty('Anchor')) {
return interaction.Anchor.filter(function(anchor) {return anchor.id === point.hasReference;}).length > 0;
}
})[0].id;
}
}
newElement.points.push(newPoint);
}
});
var strokeColor = Interaction.stroke || '000000';
newElement.style = "stroke: #" + strokeColor + ";";
newExample.viewport.push(newElement);
});
JSON.stringify(newExample);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment