@dualbox/editor 1.0.55 → 1.0.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17225,7 +17225,7 @@ class History {
17225
17225
  // execute the callback and save the history as 1 change
17226
17226
  batch(cb) {
17227
17227
  this.ignore(cb);
17228
- this.save();
17228
+ return this.save();
17229
17229
  }
17230
17230
 
17231
17231
  ignore(cb) {
@@ -42811,6 +42811,13 @@ class GraphModel {
42811
42811
  }
42812
42812
  }
42813
42813
 
42814
+ batch(cb) {
42815
+ var diff = this.history.batch(cb);
42816
+ if (this.onChangeCb) {
42817
+ this.onChangeCb(diff);
42818
+ }
42819
+ }
42820
+
42814
42821
  setWindow(name) {
42815
42822
  var newWindows = [];
42816
42823
  lodash.each(this.data.windows, (w) => {
@@ -44370,7 +44377,7 @@ class GraphNode {
44370
44377
  }
44371
44378
 
44372
44379
  rename(newId) {
44373
- this.m.history.batch(() => {
44380
+ this.m.batch(() => {
44374
44381
  // change the target name according to type (ex: if input: "size" -> "in-size")
44375
44382
  var newGraphId;
44376
44383
  if (this.isInput()) {
@@ -45796,7 +45803,7 @@ var script = {
45796
45803
 
45797
45804
  if( self.$parent.selector.isMultipleSelectionActive() ) {
45798
45805
  // We just dropped a bunch of divs, ajust all their positions
45799
- self.view.m.history.batch(() => {
45806
+ self.view.m.batch(() => {
45800
45807
  self.$parent.selector.each(div => {
45801
45808
  var pos = self.$parent.jsPlumbInstance.getPosition(div);
45802
45809
  view.m.getNode($(div).attr('id')).setPosition(pos);
@@ -46447,7 +46454,7 @@ __vue_render__._withStripped = true;
46447
46454
  /* style */
46448
46455
  const __vue_inject_styles__ = function (inject) {
46449
46456
  if (!inject) return
46450
- inject("data-v-4e3d5666_0", { source: "\n.card-ui {\n background-color: #bff2ca!important;\n}\n.card-loop {\n /* background-color: #e5e8ea!important; */\n border: 5px double #dddddd;\n border-width: 4px;\n}\n.card-input {\n background-color: #f5d76e!important;\n}\n.card-output {\n background-color: #ffb3a7!important;\n}\n.box-inputs {\n float: left;\n padding-left: 2px;\n padding-right: 5px;\n vertical-align: top;\n text-align: left;\n}\n.box-outputs {\n float: right;\n padding-left: 5px;\n padding-right: 2px;\n vertical-align: top;\n text-align: right;\n}\n.dualbox-graph-canvas .card, .card-node {\n /*border: 1px solid #dddddd;*/\n box-shadow: 1px 1px 5px #716f6f;\n opacity: 1;\n cursor: pointer;\n z-index: 20;\n position: absolute;\n\n -webkit-transition: -webkit-box-shadow 0.15s ease-in;\n -moz-transition: -moz-box-shadow 0.15s ease-in;\n -o-transition: -o-box-shadow 0.15s ease-in;\n transition: box-shadow 0.15s ease-in;\n\n color: #4d4d4d;\n user-select: none;\n padding: 0px 8px 0px 8px;\n overflow:hidden;\n background-color: #fff;\n -moz-border-radius: 3px;\n border-radius:3px;\n font-size: 14px;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n}\n.card-node .card-top {\n padding-top: 2px;\n}\n.card-node .card-bottom {\n padding-bottom: 2px;\n text-align: center;\n line-height: 14px;\n white-space: nowrap;\n}\n.card-node hr {\n margin-top: 2px;\n margin-bottom: 2px;\n border-color: rgba(0,0,0,0.1);\n margin-left: -8px;\n margin-right: -8px;\n}\n.card-node:hover {\n border-color: #80b2fc;\n box-shadow: 1px 1px 10px #80b2fc;\n}\n.card-node.selected, .card-node.selected:hover {\n border-color: #0066ff;\n box-shadow: 1px 1px 10px #0066ff;\n}\n.card-node-incomplete {\n box-shadow: 1px 1px 5px #dd6666 !important;\n}\n.input-not-resolvable {\n color: #dd6666!important;\n}\n.card-node .title {\n vertical-align:top;\n font-weight: bold;\n}\n.card-node .subtitle {\n color:#929292;\n font-size: 11px;\n font-style: italic;\n vertical-align:center;\n font-family: tahoma, sans-serif;\n}\n.card-node .input {\n font-size: 13px;\n color: #8c8c8c;\n}\n.card-node .output {\n font-size: 13px;\n color: #8c8c8c;\n text-align:right;\n}\n.card-node .jtk-endpoint.active svg circle {\n /* fill: #99ff33 */\n stroke: #59b300;\n}\n.point {\n /* display: inline-block; */\n display: none;\n position: relative;\n top: 3px;\n margin-right: 5px;\n margin-left: 5px;\n}\n.dualbox-io {\n overflow: visible;\n margin-left: -8px;\n margin-right: -8px;\n}\n.box-inputs {\n display: flex;\n justify-content: space-between;\n position: relative;\n padding: 0;\n pointer-events: none;\n}\n.types {\n color: #6c757d!important;\n opacity: 0.7;\n pointer-events: none;\n}\n.box-inputs .types {\n display: inline-block;\n}\n.box-inputs .name {\n display: inline-block;\n}\n.box-inputs .type {\n display: block;\n text-align: right;\n}\n.box-inputs .point {\n display: block;\n}\n.box-inputs .name {\n display: block;\n}\n.box-outputs {\n display: flex;\n justify-content: center;\n position: relative;\n padding: 0;\n pointer-events: none;\n}\n.box-outputs .types {\n display: inline-block;\n}\n.box-outputs .point {\n display: inline-block;\n}\n.box-outputs .name {\n display: inline-block;\n}\n.box-outputs .type {\n display: block;\n text-align: left;\n}\n.box-outputs .point {\n display: block;\n}\n.box-outputs .name {\n display: block;\n}\nspan.feedback {\n font-weight: bold;\n}\n.event-dock {\n background-color: rgb(136, 137, 138);\n background-color: #a6a6a6;\n width: calc(100% + 18px);\n height: 12px;\n z-index: 3!important;\n}\n.event-dock-top {\n margin-left: -9px;\n margin-right: -9px;\n margin-top: -3px;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n margin-bottom: 4px;\n}\n.event-dock-bottom {\n margin-left: -9px;\n margin-right: -9px;\n margin-bottom: -3px;\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px;\n margin-top: 4px;\n height: 11px; /* shorter because of box-shadow */\n}\n.event-label {\n z-index: 21;\n padding-left: 15px;\n transform: rotate(-90deg) translate(0%, -50%)!important;\n transform-origin: 0% 0%;\n color: #6c757d!important;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n font-size: 14px;\n opacity: 0.7;\n cursor: pointer;\n}\n.transparent {\n opacity: 0.3!important;\n}\n.card-node {\n position: relative;\n}\n.card-comment {\n position: absolute;\n top: 0;\n right: 0;\n margin-top: -22px;\n color: #f4ad42!important;\n}\n.card-problem {\n position: absolute;\n top: 0;\n left: 0;\n margin-top: -22px;\n color: red!important;\n}\n.card-snapshot {\n}\n.card-snapshot-idle {\n border: 2px solid gray!important;\n box-shadow: 1px 1px 5px gray!important;\n opacity: 0.7!important;\n}\n.card-snapshot-computing {\n border: 2px solid darkgreen!important;\n box-shadow: 1px 1px 5px darkgreen!important;\n opacity: 1!important;\n}\n.card-snapshot-awaiting-data {\n border: 2px solid blue!important;\n box-shadow: 1px 1px 5px blue!important;\n opacity: 0.7!important;\n}\n.card-snapshot-ready {\n border: 2px solid lightgreen!important;\n box-shadow: 1px 1px 5px lightgreen!important;\n opacity: 1!important;\n}\n.card-status {\n position: absolute;\n bottom: 0;\n right: 0;\n left: 0;\n margin-bottom: -26px;\n color: #f4ad42!important;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n font-weight: bold;\n text-align: center;\n}\n.card-status-idle {\n color: gray!important;\n min-width: 85px;\n}\n.card-status-computing {\n color: darkgreen!important;\n min-width: 110px;\n}\n.card-status-awaiting-data {\n color: blue!important;\n min-width: 85px;\n}\n.card-status-ready {\n color: lightgreen!important;\n min-width: 85px;\n}\n.btn-snapshot-details {\n position: relative;\n margin-top: -2px;\n color: inherit;\n}\nspan.name {\n overflow-wrap: normal;\n}\n", map: {"version":3,"sources":["/home/seb/dev/dualbox/editor/js/src/v/templates/graphNode.vue"],"names":[],"mappings":";AACA;IACA,mCAAA;AACA;AAEA;IACA,yCAAA;IACA,0BAAA;IACA,iBAAA;AACA;AAEA;IACA,mCAAA;AACA;AAEA;IACA,mCAAA;AACA;AAEA;IACA,WAAA;IACA,iBAAA;IACA,kBAAA;IACA,mBAAA;IACA,gBAAA;AACA;AAEA;IACA,YAAA;IACA,iBAAA;IACA,kBAAA;IACA,mBAAA;IACA,iBAAA;AACA;AAEA;IACA,6BAAA;IACA,+BAAA;IACA,UAAA;IACA,eAAA;IACA,WAAA;IACA,kBAAA;;IAEA,oDAAA;IACA,8CAAA;IACA,0CAAA;IACA,oCAAA;;IAEA,cAAA;IACA,iBAAA;IACA,wBAAA;IACA,eAAA;IACA,sBAAA;IACA,uBAAA;IACA,iBAAA;IACA,eAAA;IACA,2DAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,mBAAA;IACA,kBAAA;IACA,iBAAA;IACA,mBAAA;AACA;AAEA;IACA,eAAA;IACA,kBAAA;IACA,6BAAA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,qBAAA;IACA,gCAAA;AACA;AAEA;IACA,qBAAA;IACA,gCAAA;AACA;AAEA;IACA,0CAAA;AACA;AAEA;IACA,wBAAA;AACA;AAEA;IACA,kBAAA;IACA,iBAAA;AACA;AAEA;IACA,aAAA;IACA,eAAA;IACA,kBAAA;IACA,qBAAA;IACA,+BAAA;AACA;AAEA;IACA,eAAA;IACA,cAAA;AACA;AAEA;IACA,eAAA;IACA,cAAA;IACA,gBAAA;AACA;AAEA;IACA,kBAAA;IACA,eAAA;AACA;AAEA;IACA,2BAAA;IACA,aAAA;IACA,kBAAA;IACA,QAAA;IACA,iBAAA;IACA,gBAAA;AACA;AAEA;IACA,iBAAA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,aAAA;IACA,8BAAA;IACA,kBAAA;IACA,UAAA;IACA,oBAAA;AACA;AAEA;IACA,wBAAA;IACA,YAAA;IACA,oBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,cAAA;IACA,iBAAA;AACA;AAEA;IACA,cAAA;AACA;AAEA;IACA,cAAA;AACA;AAEA;IACA,aAAA;IACA,uBAAA;IACA,kBAAA;IACA,UAAA;IACA,oBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,cAAA;IACA,gBAAA;AACA;AAEA;IACA,cAAA;AACA;AAEA;IACA,cAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,oCAAA;IACA,2BAAA;IACA,wBAAA;IACA,YAAA;IACA,oBAAA;AACA;AAEA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,2BAAA;IACA,4BAAA;IACA,kBAAA;AACA;AAEA;IACA,iBAAA;IACA,kBAAA;IACA,mBAAA;IACA,8BAAA;IACA,+BAAA;IACA,eAAA;IACA,YAAA,EAAA,kCAAA;AACA;AAEA;IACA,WAAA;IACA,kBAAA;IACA,uDAAA;IACA,uBAAA;IACA,wBAAA;IACA,2DAAA;IACA,eAAA;IACA,YAAA;IACA,eAAA;AACA;AAEA;IACA,sBAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,kBAAA;IACA,MAAA;IACA,QAAA;IACA,iBAAA;IACA,wBAAA;AACA;AAEA;IACA,kBAAA;IACA,MAAA;IACA,OAAA;IACA,iBAAA;IACA,oBAAA;AACA;AAEA;AAEA;AAEA;IACA,gCAAA;IACA,sCAAA;IACA,sBAAA;AACA;AAEA;IACA,qCAAA;IACA,2CAAA;IACA,oBAAA;AACA;AAEA;IACA,gCAAA;IACA,sCAAA;IACA,sBAAA;AACA;AAEA;IACA,sCAAA;IACA,4CAAA;IACA,oBAAA;AACA;AAEA;IACA,kBAAA;IACA,SAAA;IACA,QAAA;IACA,OAAA;IACA,oBAAA;IACA,wBAAA;IACA,2DAAA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,qBAAA;IACA,eAAA;AACA;AAEA;IACA,0BAAA;IACA,gBAAA;AACA;AAEA;IACA,qBAAA;IACA,eAAA;AACA;AAEA;IACA,2BAAA;IACA,eAAA;AACA;AAEA;IACA,kBAAA;IACA,gBAAA;IACA,cAAA;AACA;AAEA;IACA,qBAAA;AACA","file":"graphNode.vue","sourcesContent":["<style>\n.card-ui {\n background-color: #bff2ca!important;\n}\n\n.card-loop {\n /* background-color: #e5e8ea!important; */\n border: 5px double #dddddd;\n border-width: 4px;\n}\n\n.card-input {\n background-color: #f5d76e!important;\n}\n\n.card-output {\n background-color: #ffb3a7!important;\n}\n\n.box-inputs {\n float: left;\n padding-left: 2px;\n padding-right: 5px;\n vertical-align: top;\n text-align: left;\n}\n\n.box-outputs {\n float: right;\n padding-left: 5px;\n padding-right: 2px;\n vertical-align: top;\n text-align: right;\n}\n\n.dualbox-graph-canvas .card, .card-node {\n /*border: 1px solid #dddddd;*/\n box-shadow: 1px 1px 5px #716f6f;\n opacity: 1;\n cursor: pointer;\n z-index: 20;\n position: absolute;\n\n -webkit-transition: -webkit-box-shadow 0.15s ease-in;\n -moz-transition: -moz-box-shadow 0.15s ease-in;\n -o-transition: -o-box-shadow 0.15s ease-in;\n transition: box-shadow 0.15s ease-in;\n\n color: #4d4d4d;\n user-select: none;\n padding: 0px 8px 0px 8px;\n overflow:hidden;\n background-color: #fff;\n -moz-border-radius: 3px;\n border-radius:3px;\n font-size: 14px;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n}\n\n.card-node .card-top {\n padding-top: 2px;\n}\n\n.card-node .card-bottom {\n padding-bottom: 2px;\n text-align: center;\n line-height: 14px;\n white-space: nowrap;\n}\n\n.card-node hr {\n margin-top: 2px;\n margin-bottom: 2px;\n border-color: rgba(0,0,0,0.1);\n margin-left: -8px;\n margin-right: -8px;\n}\n\n.card-node:hover {\n border-color: #80b2fc;\n box-shadow: 1px 1px 10px #80b2fc;\n}\n\n.card-node.selected, .card-node.selected:hover {\n border-color: #0066ff;\n box-shadow: 1px 1px 10px #0066ff;\n}\n\n.card-node-incomplete {\n box-shadow: 1px 1px 5px #dd6666 !important;\n}\n\n.input-not-resolvable {\n color: #dd6666!important;\n}\n\n.card-node .title {\n vertical-align:top;\n font-weight: bold;\n}\n\n.card-node .subtitle {\n color:#929292;\n font-size: 11px;\n font-style: italic;\n vertical-align:center;\n font-family: tahoma, sans-serif;\n}\n\n.card-node .input {\n font-size: 13px;\n color: #8c8c8c;\n}\n\n.card-node .output {\n font-size: 13px;\n color: #8c8c8c;\n text-align:right;\n}\n\n.card-node .jtk-endpoint.active svg circle {\n /* fill: #99ff33 */\n stroke: #59b300;\n}\n\n.point {\n /* display: inline-block; */\n display: none;\n position: relative;\n top: 3px;\n margin-right: 5px;\n margin-left: 5px;\n}\n\n.dualbox-io {\n overflow: visible;\n margin-left: -8px;\n margin-right: -8px;\n}\n\n.box-inputs {\n display: flex;\n justify-content: space-between;\n position: relative;\n padding: 0;\n pointer-events: none;\n}\n\n.types {\n color: #6c757d!important;\n opacity: 0.7;\n pointer-events: none;\n}\n\n.box-inputs .types {\n display: inline-block;\n}\n\n.box-inputs .name {\n display: inline-block;\n}\n\n.box-inputs .type {\n display: block;\n text-align: right;\n}\n\n.box-inputs .point {\n display: block;\n}\n\n.box-inputs .name {\n display: block;\n}\n\n.box-outputs {\n display: flex;\n justify-content: center;\n position: relative;\n padding: 0;\n pointer-events: none;\n}\n\n.box-outputs .types {\n display: inline-block;\n}\n\n.box-outputs .point {\n display: inline-block;\n}\n\n.box-outputs .name {\n display: inline-block;\n}\n\n.box-outputs .type {\n display: block;\n text-align: left;\n}\n\n.box-outputs .point {\n display: block;\n}\n\n.box-outputs .name {\n display: block;\n}\n\nspan.feedback {\n font-weight: bold;\n}\n\n.event-dock {\n background-color: rgb(136, 137, 138);\n background-color: #a6a6a6;\n width: calc(100% + 18px);\n height: 12px;\n z-index: 3!important;\n}\n\n.event-dock-top {\n margin-left: -9px;\n margin-right: -9px;\n margin-top: -3px;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n margin-bottom: 4px;\n}\n\n.event-dock-bottom {\n margin-left: -9px;\n margin-right: -9px;\n margin-bottom: -3px;\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px;\n margin-top: 4px;\n height: 11px; /* shorter because of box-shadow */\n}\n\n.event-label {\n z-index: 21;\n padding-left: 15px;\n transform: rotate(-90deg) translate(0%, -50%)!important;\n transform-origin: 0% 0%;\n color: #6c757d!important;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n font-size: 14px;\n opacity: 0.7;\n cursor: pointer;\n}\n\n.transparent {\n opacity: 0.3!important;\n}\n\n.card-node {\n position: relative;\n}\n\n.card-comment {\n position: absolute;\n top: 0;\n right: 0;\n margin-top: -22px;\n color: #f4ad42!important;\n}\n\n.card-problem {\n position: absolute;\n top: 0;\n left: 0;\n margin-top: -22px;\n color: red!important;\n}\n\n.card-snapshot {\n\n}\n\n.card-snapshot-idle {\n border: 2px solid gray!important;\n box-shadow: 1px 1px 5px gray!important;\n opacity: 0.7!important;\n}\n\n.card-snapshot-computing {\n border: 2px solid darkgreen!important;\n box-shadow: 1px 1px 5px darkgreen!important;\n opacity: 1!important;\n}\n\n.card-snapshot-awaiting-data {\n border: 2px solid blue!important;\n box-shadow: 1px 1px 5px blue!important;\n opacity: 0.7!important;\n}\n\n.card-snapshot-ready {\n border: 2px solid lightgreen!important;\n box-shadow: 1px 1px 5px lightgreen!important;\n opacity: 1!important;\n}\n\n.card-status {\n position: absolute;\n bottom: 0;\n right: 0;\n left: 0;\n margin-bottom: -26px;\n color: #f4ad42!important;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n font-weight: bold;\n text-align: center;\n}\n\n.card-status-idle {\n color: gray!important;\n min-width: 85px;\n}\n\n.card-status-computing {\n color: darkgreen!important;\n min-width: 110px;\n}\n\n.card-status-awaiting-data {\n color: blue!important;\n min-width: 85px;\n}\n\n.card-status-ready {\n color: lightgreen!important;\n min-width: 85px;\n}\n\n.btn-snapshot-details {\n position: relative;\n margin-top: -2px;\n color: inherit;\n}\n\nspan.name {\n overflow-wrap: normal;\n}\n</style>\n\n<template>\n <div class=\"jtk-node card card-node contextmenu\" v-bind:class=\"{ 'card-loop': n.hasLoop(), 'card-ui': n.isUI(), 'card-metanode': n.isMetanode(), 'card-input': n.isInput(), 'card-output': n.isOutput(), 'card-snapshot': n.hasSnapshot(), 'card-snapshot-idle': n.hasSnapshot() && n.isSnapshotStatus(0), 'card-snapshot-computing': n.hasSnapshot() && n.isSnapshotStatus(1), 'card-snapshot-awaiting-data': n.hasSnapshot() && n.isSnapshotStatus(2), 'card-snapshot-ready': n.hasSnapshot() && n.isSnapshotStatus(3) }\" v-bind:id=\"getId()\" v-bind:data-id=\"getId()\" v-bind:data-name=\"pkg.name\" style=\"overflow: visible;\">\n <div v-if=\"n.hasComment()\">\n <div class=\"card-comment\" data-toggle=\"tooltip\" data-placement=\"top\" :title=\"n.getComment()\">\n <i class=\"fas fa-comment-alt\" data-container=\"body\"></i>\n </div>\n </div>\n\n <div v-if=\"n.hasSnapshot()\">\n <div class=\"card-status\">\n <div v-if=\"n.isSnapshotStatus(0)\">\n <div class=\"card-status-idle\">\n <span>IDLE</span>\n <button class=\"btn btn-editor-xs btn-outline-secondary btn-outline-discrete btn-snapshot-details d-inline-block\" data-id=\"getId()\" v-on:click=\"openSnapshotDetails\"><i class=\"fas fa-info-circle\"></i></button>\n </div>\n </div>\n\n <div v-if=\"n.isSnapshotStatus(1)\">\n <div class=\"card-status-computing\">\n <span>COMPUTING</span>\n <button class=\"btn btn-editor-xs btn-outline-secondary btn-outline-discrete btn-snapshot-details d-inline-block\" data-id=\"getId()\" v-on:click=\"openSnapshotDetails\"><i class=\"fas fa-info-circle\"></i></button>\n </div>\n </div>\n\n <div v-if=\"n.isSnapshotStatus(2)\">\n <div class=\"card-status-awaiting-data\">\n <span>WAITING</span>\n <button class=\"btn btn-editor-xs btn-outline-secondary btn-outline-discrete btn-snapshot-details d-inline-block\" data-id=\"getId()\" v-on:click=\"openSnapshotDetails\"><i class=\"fas fa-info-circle\"></i></button>\n </div>\n </div>\n\n <div v-if=\"n.isSnapshotStatus(3)\">\n <div class=\"card-status-ready\">\n <span>READY</span>\n <button class=\"btn btn-editor-xs btn-outline-secondary btn-outline-discrete btn-snapshot-details d-inline-block\" data-id=\"getId()\" v-on:click=\"openSnapshotDetails\"><i class=\"fas fa-info-circle\"></i></button>\n </div>\n </div>\n </div>\n </div>\n\n <div v-if=\"!example && n.isUI() && !n.isOnAPanel()\">\n <div class=\"card-problem\">\n <i class=\"fas fa-exclamation-circle\" data-container=\"body\" data-toggle=\"popover\" data-placement=\"top\" data-content=\"This UI is not set in a panel. It won't have any effect. Go to the Interface tab to add it to a panel.\"></i>\n </div>\n </div>\n\n <div class=\"card-top\">\n <div class=\"d-flex\">\n <span class=\"title\" style=\"white-space: nowrap; margin-right: 5px;\">\n <span v-if=\"n.isMetanode()\" class=\"badge badge-secondary\"><b>META</b></span>\n {{n.graphId}}\n <i v-if=\"n.isParallel()\" class=\"fas fa-server\" style=\"color: orange;\" title=\"this module is computed in a web worker\"></i>\n </span>\n\n <div class=\"ml-auto\">\n <button class=\"btn btn-outline-secondary btn-outline-discrete btn-editor-xs btn-settings\" v-on:click=\"openNodeSettings\"><i class=\"fas fa-cog\"></i></button>\n </div>\n </div>\n </div>\n <div v-if=\"!n.isInput() && !n.isOutput()\" class=\"card-center\">\n <hr style=\"margin-bottom: 5px;\"/>\n <div class=\"dualbox-io\" style=\"overflow: visible;\">\n <div class=\"inputs\" style=\"display: inline-block; float: left;\">\n <div class=\"box-inputs\">\n <div class=\"types\">\n <span class=\"type\" v-for=\"key in getVisibleInputs()\" v-bind:data-key=\"key\">\n {{ n.getInputType(key) }}\n </span>\n </div>\n <div class=\"points\">\n <div class=\"point\" v-for=\"key in getVisibleInputs()\" v-bind:data-key=\"key\" v-bind:data-type=\"n.getInputDef(key).type\" v-html=\"point\"></div>\n </div>\n <div class=\"names\">\n <span class=\"name\" v-for=\"key in getVisibleInputs()\" :class=\"{'feedback': n.isFeedbackTarget(key), 'input-not-resolvable': !example && !n.isInputResolvable(key) }\" v-bind:data-input=\"key\">\n <span v-if=\"n.hasIterator(key)\">&lt;{{key}}&gt;</span>\n <span v-else>{{key}}</span>\n <small v-if=\"!n.isInputConst(key)\" data-toggle=\"tooltip\" data-trigger=\"hover\" title=\"this value will be cloned at execution time\"><i class=\"fas fa-clone transparent\"></i></small>\n </span>\n </div>\n </div>\n </div>\n <div class=\"outputs\" style=\"display: inline-block; float: right\">\n <div class=\"box-outputs\">\n <div class=\"names\">\n <span class=\"name\" v-for=\"key in getVisibleOutputs()\" v-bind:class=\"{feedback: n.isFeedbackTarget(key)}\" v-bind:data-output=\"key\">\n <span v-if=\"n.hasLoop() && n.hasFeedback(key)\">{{key}}</span>\n <span v-else-if=\"n.hasLoop() && !n.hasFeedback(key)\" v-html='\"&lt;\"+key+\"&gt;\"'></span>\n <span v-else>{{key}}</span>\n\n <span v-if=\"n.hasCacheActivated()\">\n &nbsp;<i class=\"fa fa-hdd\" title=\"This module has cache activated\"></i>\n </span>\n </span>\n </div>\n <div class=\"points\">\n <div class=\"point\" v-for=\"key in getVisibleOutputs()\" v-bind:data-key=\"key\" v-bind:data-type=\"n.getOutputDef(key).type\" v-html=\"point\"></div>\n </div>\n <div class=\"types\">\n <span class=\"type\" v-for=\"key in getVisibleOutputs()\" v-bind:data-key=\"key\">\n {{ n.getOutputType(key) }}\n </span>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <hr style=\"margin-top: 5px;\"/>\n <div class=\"card-bottom\">\n <span class=\"subtitle\">{{ shortName }}</span>\n\n <div v-if=\"n.isMetanode()\" class=\"d-inline-block\">\n <button class=\"btn btn-outline-secondary btn-outline-discrete btn-editor-xs btn-enter-metanode\" v-on:click=\"enterMetanode\"><i class=\"fas fa-sign-in-alt\"></i></button>\n </div>\n\n <!--\n <div v-if=\"n.isUI()\" class=\"event-dock event-dock-bottom\"></div>\n -->\n </div>\n </div>\n</template>\n\n<script>\nimport ContextMenu from '../ContextMenu';\nimport _ from 'lodash';\nimport dbutils from '../../m/DualboxUtils';\n\n// fix inputs types and output types position relatively to the div\n$.fn.fixCardDisplay = function() {\n var offsetPoint = 12;\n var offsetBorder = parseInt($(this).css(\"border-top-width\"));\n\n if( $(this).find('.box-inputs').height() === 0 && $(this).find('.box-outputs').height() === 0 ) {\n // if this card has no input/output, remove the card center\n $(this).find('.card-center').remove();\n }\n else {\n // else, adjust the input/output display for endpoints\n // 1) translate inputs by the right amount of pixels to have the circle on the line\n var boxInputs = $(this).find('.box-inputs');\n\n // fix css names width\n var namesDiv = boxInputs.find('.names');\n namesDiv.css('width', (namesDiv.width()+1) + 'px');\n\n // translate inputs to the left\n var translateLeft = boxInputs.find('.types').width() + offsetPoint + offsetBorder/2;\n $(this).find('.box-inputs').css('transform', 'translateX(-' + translateLeft + 'px)');\n\n // adjust inputs main div width\n $(this).find('.inputs').width( $(this).find('.inputs').width() - translateLeft + 10 /* margin */ );\n\n\n // 2) translate outputs by the right amount of pixels to have the circle on the line\n var boxOutputs = $(this).find('.box-outputs');\n\n // fix css names with\n var namesDiv = boxOutputs.find('.names');\n namesDiv.css('width', (namesDiv.width() + 1) + 'px');\n\n // translate inputs to the right\n var translateRight = boxOutputs.find('.types').width() + offsetPoint + offsetBorder/2;\n $(this).find('.box-outputs').css('transform', 'translateX(' + translateRight + 'px)');\n\n // adjust output main div width\n $(this).find('.outputs').width( $(this).find('.outputs').width() - translateRight + 10 /* margin */ );\n\n // fix io width\n //$('.dualbox-io').css('width', (($(this).find('.inputs').width() + $(this).find('.outputs').width()) + \"px\"));\n }\n}\n\n// take the current width and add it as a css property\n$.fn.fixWidth = function() {\n var width = $(this).width();\n width += parseInt($(this).css('padding-right'));\n width += parseInt($(this).css('padding-left'));\n width += parseInt($(this).css('border-left-width'));\n width += parseInt($(this).css('border-right-width'));\n $(this).css('width', width + 'px');\n}\n\n// find position of element relative to an ancestor matching selector\n$.fn.positionFrom = function( selector ) {\n var ancestor = $(this).closest(selector);\n var offset = $(this).offset();\n var ancestorOffset = ancestor.offset();\n return {\n top: offset.top - ancestorOffset.top,\n left: offset.left - ancestorOffset.left,\n }\n}\n\nexport default {\n props: [\n \"id\", // the module id\n \"pkg\", // the module package.json\n \"n\", // the GraphNode object (from model)\n \"example\", // true if this vue is used as an example display (no need to connect)\n \"displayEvents\", // true if events should be displayed\n ],\n data: function () {\n return {\n shortName: \"\",\n point: '<svg width=\"14\" height=\"14\" pointer-events=\"all\" position=\"absolute\" version=\"1.1\" xmlns=\"http://www.w3.org/1999/xhtml\"><circle cx=\"7\" cy=\"7\" r=\"5\" version=\"1.1\" xmlns=\"http://www.w3.org/1999/xhtml\" fill=\"#ffffff\" stroke=\"#727272\" style=\"\" stroke-width=\"2\"></circle></svg>',\n }\n },\n beforeUpdate: function() {\n //console.log('[UPDATING] ' + this.n.getUniqId());\n },\n destroyed: function() {\n //console.log('[DESTROYED] ' + this.n.getUniqId());\n },\n created: function() {\n this.initialized = false;\n this.view = window.dualboxEditor.v;\n\n //console.log('[CREATED] ' + this.n.getUniqId());\n // We compute the shortname of our box\n if( this.n.isInput() || this.n.isOutput() ) {\n this.shortName = this.n.getType();\n }\n else {\n this.shortName = dbutils.shortName(this.pkg.name);\n }\n },\n mounted: async function() {\n //console.log('[MOUNTED] ' + this.n.getUniqId());\n var div = $(this.$el);\n div.fixCardDisplay();\n div.ready(() => {\n //if( !this.example ) {\n div.fixWidth();\n //}\n });\n this.activateTooltip();\n return await this.initialize();\n },\n beforeUpdate: function() {\n this.deactivateTooltip();\n },\n updated: async function() {\n //console.log('[UPDATED] ' + this.n.getUniqId());\n\n // we reset jsPlumb before app update (in graph.vue)\n // so we need to initialize again\n this.assignContextMenu();\n\n $(this.$el).fixCardDisplay();\n $(this.$el).ready(()=>{\n $(this.$el).fixWidth();\n this.activateTooltip();\n });\n return await this.initialize();\n },\n activate: function() {\n this.activateTooltip();\n },\n deactivate: function() {\n this.deactivateTooltip();\n },\n methods: {\n getId: function() {\n // if this is an example graphNode, change our \"id\" to \"id-junk\"\n // to avoid connection jsplumb conflicts with the real node\n return this.example ? this.id + '-junk' : this.id;\n },\n\n activateTooltip: function() {\n $(this.$el).find('[data-toggle=\"tooltip\"]').tooltip();\n },\n\n deactivateTooltip: function() {\n $(this.$el).find('[data-toggle=\"tooltip\"]').tooltip(\"dispose\");\n },\n\n initialize: async function() {\n var self = this;\n var div = $(this.$el);\n var id = this.getId();\n var view = this.view;\n\n this.initialized = false;\n\n if( !this.example ) {\n // if we have a position, set it\n var def = this.n.getDef();\n var position = _.get(def, [\"graph\", \"position\"]);\n if( position ) {\n var jsPlumbElement = self.$parent.jsPlumbInstance.getElement(id);\n self.$parent.jsPlumbInstance.setPosition(jsPlumbElement, position);\n }\n\n // This needs to be registered before draggable\n div.on('mousedown', function(e) {\n // if this div is not selected already, deselect the other divs\n if( !self.$parent.selector.isSelected(this) ) {\n self.$parent.selector.deselect();\n }\n });\n\n await this.initializeJsPlumb();\n\n div.click(function(e) {\n if( e.ctrlKey ) {\n view.selector.toggleSelection(this);\n }\n });\n\n this.assignContextMenu();\n }\n\n return new Promise(resolve => {\n div.ready(() => {\n //console.log('[INITIALIZED] ' + this.n.getUniqId());\n this.initialized = true;\n resolve();\n });\n });\n },\n\n initializeJsPlumb: function() {\n var self = this;\n var div = $(this.$el);\n var id = this.getId();\n var view = this.view;\n\n if( !this.example ) {\n // If this node was never initialized in this jsplumb instance, do it\n if( !_.get(this.$parent.jsPlumbInstance, [\"initializedNodes\", id]) ) {\n _.set(this.$parent.jsPlumbInstance, [\"initializedNodes\", id], true); // initialized\n\n if( this.n.isInput() || this.n.isOutput() ) {\n var type = \"*\";\n var input = \"value\";\n var output = \"value\";\n var offsetTop = $(div).find('.card-top').height() + 12 /* hr size */ - 3;\n\n var uuid = [ id, \"input\", input].join('#');\n var ep = this.$parent.jsPlumbInstance.addEndpoint(id, {\n isSource : false,\n isTarget : true,\n uuid : uuid,\n anchor : [0,0,-1,0,0,offsetTop],\n maxConnections : 1,\n parameters : {\n type: \"data\",\n target : {\n id : id,\n input : output\n }\n }\n }, this.$parent.style.inputEndpoint);\n\n // add data to the endpoint div so we can identify it easier\n $(ep.canvas).attr('data-node', id);\n $(ep.canvas).attr('data-type', 'input');\n $(ep.canvas).attr('data-input', input);\n\n // bind tooltip\n $(ep.canvas).attr('data-toggle', \"tooltip\");\n $(ep.canvas).attr('data-trigger', \"hover\");\n $(ep.canvas).attr('data-placement', \"left\");\n $(ep.canvas).attr('data-html', \"true\");\n var inputType = view.m.getNode(id).getInputType(\"value\");\n $(ep.canvas).attr('title', \"Type: <b>\" + inputType + \"</b>\");\n $(ep.canvas).tooltip();\n\n // bind context menu to the endpoint\n $(ep.canvas).addClass('capture-right-click');\n $(ep.canvas).ready(function() {\n var menu = new ContextMenu(\".jtk-endpoint-anchor[data-node='\"+id.trim()+\"'][data-input='\" + input + \"']\", [\n {\n name: 'Create input for here',\n fn: () => {\n view.c.createInputFromConnection(id, input);\n }\n },\n ]);\n });\n\n var uuid = [ id, \"output\", output].join('#');\n var ep = this.$parent.jsPlumbInstance.addEndpoint(id, {\n isSource : true,\n isTarget : false,\n uuid : uuid,\n anchor : [1,0,1,0,0,offsetTop],\n parameters : {\n type: \"data\",\n source : {\n id : id,\n output : output\n }\n }\n }, this.$parent.style.outputEndpoint);\n\n // add data to the endpoint div so we can identify it easier\n $(ep.canvas).attr('data-node', id);\n $(ep.canvas).attr('data-type', \"output\");\n $(ep.canvas).attr('data-output', output);\n\n // bind tooltip\n $(ep.canvas).attr('data-toggle', \"tooltip\");\n $(ep.canvas).attr('data-trigger', \"hover\");\n $(ep.canvas).attr('data-placement', \"right\");\n $(ep.canvas).attr('data-html', \"true\");\n var outputType = view.m.getNode(id).getOutputType(\"value\");\n $(ep.canvas).attr('title', \"Type: <b>\" + outputType + \"</b>\");\n $(ep.canvas).tooltip();\n\n // bind context menu to the endpoint\n $(ep.canvas).addClass('capture-right-click');\n $(ep.canvas).ready(function() {\n var menu = new ContextMenu(\".jtk-endpoint-anchor[data-node='\"+id.trim()+\"'][data-output='\" + output.trim() + \"']\", [\n {\n name: 'Create output for here',\n fn: () => {\n view.c.createOutputFromConnection(id, output);\n }\n },\n ]);\n });\n }\n else {\n // add input endoints\n div.find('.box-inputs').find('.point').each( function(index) {\n $(this).css('visibility', 'hidden').css('opacity', '0'); // replaced by jsPlumb point\n\n var input = div.find('.box-inputs').find('.name').eq(index).attr('data-input').trim();\n var type = view.m.getNode(id).getInputType(input);\n\n var offsetTop = $(this).positionFrom('.card').top + $(this).height()/2 - 3;\n var uuid = [ id, \"input\", $(this).data('key')].join('#');\n var ep = self.$parent.jsPlumbInstance.addEndpoint(id, {\n isSource : false,\n isTarget : true,\n uuid : uuid,\n anchor : [0,0,-1,0,0,offsetTop],\n maxConnections : 1,\n parameters : {\n type: \"data\",\n target : {\n id : id,\n input : $(this).data('key')\n }\n }\n }, self.$parent.style.inputEndpoint);\n\n // add data to the endpoint div so we can identify it easier\n $(ep.canvas).attr('data-node', id);\n $(ep.canvas).attr('data-type', 'input');\n $(ep.canvas).attr('data-input', input);\n\n // bind tooltip\n $(ep.canvas).attr('data-toggle', \"tooltip\");\n $(ep.canvas).attr('data-trigger', \"hover\");\n $(ep.canvas).attr('data-placement', \"left\");\n $(ep.canvas).attr('data-html', \"true\");\n $(ep.canvas).attr('title', \"Type: <b>\" + type + \"</b>\");\n $(ep.canvas).tooltip();\n\n // bind context menu to the endpoint\n $(ep.canvas).addClass('capture-right-click');\n $(ep.canvas).ready(function() {\n var menu = new ContextMenu(\".jtk-endpoint-anchor[data-node='\"+id.trim()+\"'][data-input='\" + input.trim() + \"']\", [\n {\n name: 'Create input for here',\n fn: () => {\n view.c.createInputFromConnection(id, input);\n }\n },\n ]);\n });\n });\n\n // add output endpoints\n div.find('.box-outputs').find('.point').each( function(index) {\n $(this).css('visibility', 'hidden').css('opacity', '0'); // replaced by jsPlumb point\n\n var output = div.find('.box-outputs').find('.name').eq(index).attr('data-output').trim();\n var type = view.m.getNode(id).getOutputType(output);\n\n var offsetTop = $(this).positionFrom('.card').top + $(this).height()/2 - 3;\n var uuid = [ id, \"output\", $(this).data('key')].join('#');\n var ep = self.$parent.jsPlumbInstance.addEndpoint(id, {\n isSource : true,\n isTarget : false,\n uuid : uuid,\n anchor : [1,0,1,0,0,offsetTop],\n parameters : {\n type: \"data\",\n source : {\n id : id,\n output : $(this).data('key')\n }\n }\n }, self.$parent.style.outputEndpoint);\n\n // add data to the endpoint div so we can identify it easier\n $(ep.canvas).attr('data-node', id);\n $(ep.canvas).attr('data-type', \"output\");\n $(ep.canvas).attr('data-output', output);\n\n // bind tooltip\n $(ep.canvas).attr('data-toggle', \"tooltip\");\n $(ep.canvas).attr('data-trigger', \"hover\");\n $(ep.canvas).attr('data-placement', \"right\");\n $(ep.canvas).attr('data-html', \"true\");\n $(ep.canvas).attr('title', \"Type: <b>\" + type + \"</b>\");\n $(ep.canvas).tooltip();\n\n // bind context menu to the endpoint\n $(ep.canvas).addClass('capture-right-click');\n $(ep.canvas).ready(function() {\n var menu = new ContextMenu(\".jtk-endpoint-anchor[data-node='\"+id.trim()+\"'][data-output='\" + output.trim() + \"']\", [\n {\n name: 'Create output for here',\n fn: () => {\n view.c.createOutputFromConnection(id, output);\n }\n },\n ]);\n });\n });\n\n if( this.n.isUI() && this.displayEvents ) {\n // Make this a target for events\n this.$parent.jsPlumbInstance.makeTarget(id, {\n isSource:false,\n isTarget:true,\n uniqueEndpoint: false,\n anchor:\"Continuous\",\n uuid: id + \"#event-in\",\n paintStyle:{ fill:\"green\", radius: 3, stroke: \"#727272\", strokeWidth: 1 },\n parameters: {\n type: \"event\",\n target: { \"id\" : id }\n },\n }, self.$parent.style.eventEndpoint);\n\n // Create an enpoint to create a new event\n var ep = this.$parent.jsPlumbInstance.addEndpoint(id, {\n isSource : true,\n isTarget : false,\n uuid : id + \"#event-out\",\n anchor : [1, 1, 0, 1, 0, -10],\n parameters : {\n type: \"event\",\n source: { \"id\" : id }\n },\n paintStyle:{ fill:\"green\", radius: 3, stroke: \"#727272\", strokeWidth: 1 },\n }, this.$parent.style.eventEndpoint);\n\n // Add overlay here so we don't mess with splitConnection\n ep.addOverlay([\"PlainArrow\", { width:15, length:15, location:1, id:\"arrow\" }]);\n\n $(ep.canvas).attr('data-toggle', \"tooltip\");\n $(ep.canvas).attr('data-trigger', \"hover\");\n $(ep.canvas).attr('data-placement', \"bottom\");\n $(ep.canvas).attr('data-html', \"true\");\n $(ep.canvas).attr('title', \"Connect from here ito add an event that will be triggered when this box is done computing.\");\n $(ep.canvas).tooltip();\n }\n }\n\n // Make the div draggable\n this.$parent.jsPlumbInstance.draggable(div, {\n //containment:true, // not allowed outside of container div\n drag: function(e) {\n // TODO: bug. After a repaint(), jsPlumb seems to be broken (connections dont follow on div drag)\n // It doesn't occur on jsPlumb.reset() instead of creating another instance on beforeUpdate(),\n // (as it should be), but we can't do that, because JsPlumb is broken on zoom otherwise...\n // One of thoses problem may be fixed later by updating jsPlumb...\n // Note: this \"fix\" may affect performances on drag, maybe a setTimeout will do\n //self.$parent.jsPlumbInstance.repaintEverything();\n self.$parent.jsPlumbInstance.repaint(id);\n },\n stop: function(e) {\n // resize the canvas if necessary\n self.$parent.canvasSizeHandler.debouncedResize();\n\n if( self.$parent.selector.isMultipleSelectionActive() ) {\n // We just dropped a bunch of divs, ajust all their positions\n self.view.m.history.batch(() => {\n self.$parent.selector.each(div => {\n var pos = self.$parent.jsPlumbInstance.getPosition(div);\n view.m.getNode($(div).attr('id')).setPosition(pos);\n });\n });\n }\n else {\n // We just dropped this one, set the new position in the graph model\n var el = self.$parent.jsPlumbInstance.getElement(id);\n $(el).ready(function() {\n var pos = self.$parent.jsPlumbInstance.getPosition(el);\n view.m.getNode(id).setPosition(pos);\n });\n }\n }\n });\n }\n }\n\n return new Promise((resolve) => this.$parent.jsPlumbInstance.ready(resolve));\n },\n\n assignContextMenu: function() {\n var id = this.getId();\n\n // Create a contextmenu for the div\n var contextOptions = [\n {\n name: 'Remove this box',\n fn: () => {\n this.view.c.removeBox(id);\n }\n }\n ];\n if( this.n.isModule() || this.n.isUI() ) {\n contextOptions.push({\n name: 'Duplicate this box',\n fn: () => {\n this.view.c.duplicateBox(id);\n }\n });\n }\n var nodeMenu = new ContextMenu(\"#\" + id, contextOptions);\n },\n\n htmlentities: function( s ) {\n return this.view.utils.htmlentities(s);\n },\n\n getVisibleInputs: function() {\n return this.n.getInputsNames().filter((inputName) => {\n return this.n.isInputVisible(inputName);\n })\n },\n\n getVisibleOutputs: function() {\n return this.n.getOutputsNames().filter((outputName) => {\n return this.n.isOutputVisible(outputName);\n })\n },\n\n enterMetanode: function(e) {\n e.preventDefault();\n e.stopPropagation();\n\n this.view.c.enterMetanode(this.id);\n },\n\n openNodeSettings: function(e) {\n e.preventDefault();\n e.stopPropagation();\n this.view.openBoxSettings(this.id);\n },\n\n openSnapshotDetails: function(e) {\n e.preventDefault();\n e.stopPropagation();\n this.view.openDebug(this.id);\n }\n },\n watch: {\n 'app': {\n handler: () => {\n console.log('graphVue.app changed');\n },\n deep: true\n }\n }\n}\n\n</script>\n"]}, media: undefined });
46457
+ inject("data-v-1aee1868_0", { source: "\n.card-ui {\n background-color: #bff2ca!important;\n}\n.card-loop {\n /* background-color: #e5e8ea!important; */\n border: 5px double #dddddd;\n border-width: 4px;\n}\n.card-input {\n background-color: #f5d76e!important;\n}\n.card-output {\n background-color: #ffb3a7!important;\n}\n.box-inputs {\n float: left;\n padding-left: 2px;\n padding-right: 5px;\n vertical-align: top;\n text-align: left;\n}\n.box-outputs {\n float: right;\n padding-left: 5px;\n padding-right: 2px;\n vertical-align: top;\n text-align: right;\n}\n.dualbox-graph-canvas .card, .card-node {\n /*border: 1px solid #dddddd;*/\n box-shadow: 1px 1px 5px #716f6f;\n opacity: 1;\n cursor: pointer;\n z-index: 20;\n position: absolute;\n\n -webkit-transition: -webkit-box-shadow 0.15s ease-in;\n -moz-transition: -moz-box-shadow 0.15s ease-in;\n -o-transition: -o-box-shadow 0.15s ease-in;\n transition: box-shadow 0.15s ease-in;\n\n color: #4d4d4d;\n user-select: none;\n padding: 0px 8px 0px 8px;\n overflow:hidden;\n background-color: #fff;\n -moz-border-radius: 3px;\n border-radius:3px;\n font-size: 14px;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n}\n.card-node .card-top {\n padding-top: 2px;\n}\n.card-node .card-bottom {\n padding-bottom: 2px;\n text-align: center;\n line-height: 14px;\n white-space: nowrap;\n}\n.card-node hr {\n margin-top: 2px;\n margin-bottom: 2px;\n border-color: rgba(0,0,0,0.1);\n margin-left: -8px;\n margin-right: -8px;\n}\n.card-node:hover {\n border-color: #80b2fc;\n box-shadow: 1px 1px 10px #80b2fc;\n}\n.card-node.selected, .card-node.selected:hover {\n border-color: #0066ff;\n box-shadow: 1px 1px 10px #0066ff;\n}\n.card-node-incomplete {\n box-shadow: 1px 1px 5px #dd6666 !important;\n}\n.input-not-resolvable {\n color: #dd6666!important;\n}\n.card-node .title {\n vertical-align:top;\n font-weight: bold;\n}\n.card-node .subtitle {\n color:#929292;\n font-size: 11px;\n font-style: italic;\n vertical-align:center;\n font-family: tahoma, sans-serif;\n}\n.card-node .input {\n font-size: 13px;\n color: #8c8c8c;\n}\n.card-node .output {\n font-size: 13px;\n color: #8c8c8c;\n text-align:right;\n}\n.card-node .jtk-endpoint.active svg circle {\n /* fill: #99ff33 */\n stroke: #59b300;\n}\n.point {\n /* display: inline-block; */\n display: none;\n position: relative;\n top: 3px;\n margin-right: 5px;\n margin-left: 5px;\n}\n.dualbox-io {\n overflow: visible;\n margin-left: -8px;\n margin-right: -8px;\n}\n.box-inputs {\n display: flex;\n justify-content: space-between;\n position: relative;\n padding: 0;\n pointer-events: none;\n}\n.types {\n color: #6c757d!important;\n opacity: 0.7;\n pointer-events: none;\n}\n.box-inputs .types {\n display: inline-block;\n}\n.box-inputs .name {\n display: inline-block;\n}\n.box-inputs .type {\n display: block;\n text-align: right;\n}\n.box-inputs .point {\n display: block;\n}\n.box-inputs .name {\n display: block;\n}\n.box-outputs {\n display: flex;\n justify-content: center;\n position: relative;\n padding: 0;\n pointer-events: none;\n}\n.box-outputs .types {\n display: inline-block;\n}\n.box-outputs .point {\n display: inline-block;\n}\n.box-outputs .name {\n display: inline-block;\n}\n.box-outputs .type {\n display: block;\n text-align: left;\n}\n.box-outputs .point {\n display: block;\n}\n.box-outputs .name {\n display: block;\n}\nspan.feedback {\n font-weight: bold;\n}\n.event-dock {\n background-color: rgb(136, 137, 138);\n background-color: #a6a6a6;\n width: calc(100% + 18px);\n height: 12px;\n z-index: 3!important;\n}\n.event-dock-top {\n margin-left: -9px;\n margin-right: -9px;\n margin-top: -3px;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n margin-bottom: 4px;\n}\n.event-dock-bottom {\n margin-left: -9px;\n margin-right: -9px;\n margin-bottom: -3px;\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px;\n margin-top: 4px;\n height: 11px; /* shorter because of box-shadow */\n}\n.event-label {\n z-index: 21;\n padding-left: 15px;\n transform: rotate(-90deg) translate(0%, -50%)!important;\n transform-origin: 0% 0%;\n color: #6c757d!important;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n font-size: 14px;\n opacity: 0.7;\n cursor: pointer;\n}\n.transparent {\n opacity: 0.3!important;\n}\n.card-node {\n position: relative;\n}\n.card-comment {\n position: absolute;\n top: 0;\n right: 0;\n margin-top: -22px;\n color: #f4ad42!important;\n}\n.card-problem {\n position: absolute;\n top: 0;\n left: 0;\n margin-top: -22px;\n color: red!important;\n}\n.card-snapshot {\n}\n.card-snapshot-idle {\n border: 2px solid gray!important;\n box-shadow: 1px 1px 5px gray!important;\n opacity: 0.7!important;\n}\n.card-snapshot-computing {\n border: 2px solid darkgreen!important;\n box-shadow: 1px 1px 5px darkgreen!important;\n opacity: 1!important;\n}\n.card-snapshot-awaiting-data {\n border: 2px solid blue!important;\n box-shadow: 1px 1px 5px blue!important;\n opacity: 0.7!important;\n}\n.card-snapshot-ready {\n border: 2px solid lightgreen!important;\n box-shadow: 1px 1px 5px lightgreen!important;\n opacity: 1!important;\n}\n.card-status {\n position: absolute;\n bottom: 0;\n right: 0;\n left: 0;\n margin-bottom: -26px;\n color: #f4ad42!important;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n font-weight: bold;\n text-align: center;\n}\n.card-status-idle {\n color: gray!important;\n min-width: 85px;\n}\n.card-status-computing {\n color: darkgreen!important;\n min-width: 110px;\n}\n.card-status-awaiting-data {\n color: blue!important;\n min-width: 85px;\n}\n.card-status-ready {\n color: lightgreen!important;\n min-width: 85px;\n}\n.btn-snapshot-details {\n position: relative;\n margin-top: -2px;\n color: inherit;\n}\nspan.name {\n overflow-wrap: normal;\n}\n", map: {"version":3,"sources":["/home/seb/dev/dualbox/editor/js/src/v/templates/graphNode.vue"],"names":[],"mappings":";AACA;IACA,mCAAA;AACA;AAEA;IACA,yCAAA;IACA,0BAAA;IACA,iBAAA;AACA;AAEA;IACA,mCAAA;AACA;AAEA;IACA,mCAAA;AACA;AAEA;IACA,WAAA;IACA,iBAAA;IACA,kBAAA;IACA,mBAAA;IACA,gBAAA;AACA;AAEA;IACA,YAAA;IACA,iBAAA;IACA,kBAAA;IACA,mBAAA;IACA,iBAAA;AACA;AAEA;IACA,6BAAA;IACA,+BAAA;IACA,UAAA;IACA,eAAA;IACA,WAAA;IACA,kBAAA;;IAEA,oDAAA;IACA,8CAAA;IACA,0CAAA;IACA,oCAAA;;IAEA,cAAA;IACA,iBAAA;IACA,wBAAA;IACA,eAAA;IACA,sBAAA;IACA,uBAAA;IACA,iBAAA;IACA,eAAA;IACA,2DAAA;AACA;AAEA;IACA,gBAAA;AACA;AAEA;IACA,mBAAA;IACA,kBAAA;IACA,iBAAA;IACA,mBAAA;AACA;AAEA;IACA,eAAA;IACA,kBAAA;IACA,6BAAA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,qBAAA;IACA,gCAAA;AACA;AAEA;IACA,qBAAA;IACA,gCAAA;AACA;AAEA;IACA,0CAAA;AACA;AAEA;IACA,wBAAA;AACA;AAEA;IACA,kBAAA;IACA,iBAAA;AACA;AAEA;IACA,aAAA;IACA,eAAA;IACA,kBAAA;IACA,qBAAA;IACA,+BAAA;AACA;AAEA;IACA,eAAA;IACA,cAAA;AACA;AAEA;IACA,eAAA;IACA,cAAA;IACA,gBAAA;AACA;AAEA;IACA,kBAAA;IACA,eAAA;AACA;AAEA;IACA,2BAAA;IACA,aAAA;IACA,kBAAA;IACA,QAAA;IACA,iBAAA;IACA,gBAAA;AACA;AAEA;IACA,iBAAA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,aAAA;IACA,8BAAA;IACA,kBAAA;IACA,UAAA;IACA,oBAAA;AACA;AAEA;IACA,wBAAA;IACA,YAAA;IACA,oBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,cAAA;IACA,iBAAA;AACA;AAEA;IACA,cAAA;AACA;AAEA;IACA,cAAA;AACA;AAEA;IACA,aAAA;IACA,uBAAA;IACA,kBAAA;IACA,UAAA;IACA,oBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,qBAAA;AACA;AAEA;IACA,cAAA;IACA,gBAAA;AACA;AAEA;IACA,cAAA;AACA;AAEA;IACA,cAAA;AACA;AAEA;IACA,iBAAA;AACA;AAEA;IACA,oCAAA;IACA,2BAAA;IACA,wBAAA;IACA,YAAA;IACA,oBAAA;AACA;AAEA;IACA,iBAAA;IACA,kBAAA;IACA,gBAAA;IACA,2BAAA;IACA,4BAAA;IACA,kBAAA;AACA;AAEA;IACA,iBAAA;IACA,kBAAA;IACA,mBAAA;IACA,8BAAA;IACA,+BAAA;IACA,eAAA;IACA,YAAA,EAAA,kCAAA;AACA;AAEA;IACA,WAAA;IACA,kBAAA;IACA,uDAAA;IACA,uBAAA;IACA,wBAAA;IACA,2DAAA;IACA,eAAA;IACA,YAAA;IACA,eAAA;AACA;AAEA;IACA,sBAAA;AACA;AAEA;IACA,kBAAA;AACA;AAEA;IACA,kBAAA;IACA,MAAA;IACA,QAAA;IACA,iBAAA;IACA,wBAAA;AACA;AAEA;IACA,kBAAA;IACA,MAAA;IACA,OAAA;IACA,iBAAA;IACA,oBAAA;AACA;AAEA;AAEA;AAEA;IACA,gCAAA;IACA,sCAAA;IACA,sBAAA;AACA;AAEA;IACA,qCAAA;IACA,2CAAA;IACA,oBAAA;AACA;AAEA;IACA,gCAAA;IACA,sCAAA;IACA,sBAAA;AACA;AAEA;IACA,sCAAA;IACA,4CAAA;IACA,oBAAA;AACA;AAEA;IACA,kBAAA;IACA,SAAA;IACA,QAAA;IACA,OAAA;IACA,oBAAA;IACA,wBAAA;IACA,2DAAA;IACA,iBAAA;IACA,kBAAA;AACA;AAEA;IACA,qBAAA;IACA,eAAA;AACA;AAEA;IACA,0BAAA;IACA,gBAAA;AACA;AAEA;IACA,qBAAA;IACA,eAAA;AACA;AAEA;IACA,2BAAA;IACA,eAAA;AACA;AAEA;IACA,kBAAA;IACA,gBAAA;IACA,cAAA;AACA;AAEA;IACA,qBAAA;AACA","file":"graphNode.vue","sourcesContent":["<style>\n.card-ui {\n background-color: #bff2ca!important;\n}\n\n.card-loop {\n /* background-color: #e5e8ea!important; */\n border: 5px double #dddddd;\n border-width: 4px;\n}\n\n.card-input {\n background-color: #f5d76e!important;\n}\n\n.card-output {\n background-color: #ffb3a7!important;\n}\n\n.box-inputs {\n float: left;\n padding-left: 2px;\n padding-right: 5px;\n vertical-align: top;\n text-align: left;\n}\n\n.box-outputs {\n float: right;\n padding-left: 5px;\n padding-right: 2px;\n vertical-align: top;\n text-align: right;\n}\n\n.dualbox-graph-canvas .card, .card-node {\n /*border: 1px solid #dddddd;*/\n box-shadow: 1px 1px 5px #716f6f;\n opacity: 1;\n cursor: pointer;\n z-index: 20;\n position: absolute;\n\n -webkit-transition: -webkit-box-shadow 0.15s ease-in;\n -moz-transition: -moz-box-shadow 0.15s ease-in;\n -o-transition: -o-box-shadow 0.15s ease-in;\n transition: box-shadow 0.15s ease-in;\n\n color: #4d4d4d;\n user-select: none;\n padding: 0px 8px 0px 8px;\n overflow:hidden;\n background-color: #fff;\n -moz-border-radius: 3px;\n border-radius:3px;\n font-size: 14px;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n}\n\n.card-node .card-top {\n padding-top: 2px;\n}\n\n.card-node .card-bottom {\n padding-bottom: 2px;\n text-align: center;\n line-height: 14px;\n white-space: nowrap;\n}\n\n.card-node hr {\n margin-top: 2px;\n margin-bottom: 2px;\n border-color: rgba(0,0,0,0.1);\n margin-left: -8px;\n margin-right: -8px;\n}\n\n.card-node:hover {\n border-color: #80b2fc;\n box-shadow: 1px 1px 10px #80b2fc;\n}\n\n.card-node.selected, .card-node.selected:hover {\n border-color: #0066ff;\n box-shadow: 1px 1px 10px #0066ff;\n}\n\n.card-node-incomplete {\n box-shadow: 1px 1px 5px #dd6666 !important;\n}\n\n.input-not-resolvable {\n color: #dd6666!important;\n}\n\n.card-node .title {\n vertical-align:top;\n font-weight: bold;\n}\n\n.card-node .subtitle {\n color:#929292;\n font-size: 11px;\n font-style: italic;\n vertical-align:center;\n font-family: tahoma, sans-serif;\n}\n\n.card-node .input {\n font-size: 13px;\n color: #8c8c8c;\n}\n\n.card-node .output {\n font-size: 13px;\n color: #8c8c8c;\n text-align:right;\n}\n\n.card-node .jtk-endpoint.active svg circle {\n /* fill: #99ff33 */\n stroke: #59b300;\n}\n\n.point {\n /* display: inline-block; */\n display: none;\n position: relative;\n top: 3px;\n margin-right: 5px;\n margin-left: 5px;\n}\n\n.dualbox-io {\n overflow: visible;\n margin-left: -8px;\n margin-right: -8px;\n}\n\n.box-inputs {\n display: flex;\n justify-content: space-between;\n position: relative;\n padding: 0;\n pointer-events: none;\n}\n\n.types {\n color: #6c757d!important;\n opacity: 0.7;\n pointer-events: none;\n}\n\n.box-inputs .types {\n display: inline-block;\n}\n\n.box-inputs .name {\n display: inline-block;\n}\n\n.box-inputs .type {\n display: block;\n text-align: right;\n}\n\n.box-inputs .point {\n display: block;\n}\n\n.box-inputs .name {\n display: block;\n}\n\n.box-outputs {\n display: flex;\n justify-content: center;\n position: relative;\n padding: 0;\n pointer-events: none;\n}\n\n.box-outputs .types {\n display: inline-block;\n}\n\n.box-outputs .point {\n display: inline-block;\n}\n\n.box-outputs .name {\n display: inline-block;\n}\n\n.box-outputs .type {\n display: block;\n text-align: left;\n}\n\n.box-outputs .point {\n display: block;\n}\n\n.box-outputs .name {\n display: block;\n}\n\nspan.feedback {\n font-weight: bold;\n}\n\n.event-dock {\n background-color: rgb(136, 137, 138);\n background-color: #a6a6a6;\n width: calc(100% + 18px);\n height: 12px;\n z-index: 3!important;\n}\n\n.event-dock-top {\n margin-left: -9px;\n margin-right: -9px;\n margin-top: -3px;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n margin-bottom: 4px;\n}\n\n.event-dock-bottom {\n margin-left: -9px;\n margin-right: -9px;\n margin-bottom: -3px;\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px;\n margin-top: 4px;\n height: 11px; /* shorter because of box-shadow */\n}\n\n.event-label {\n z-index: 21;\n padding-left: 15px;\n transform: rotate(-90deg) translate(0%, -50%)!important;\n transform-origin: 0% 0%;\n color: #6c757d!important;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n font-size: 14px;\n opacity: 0.7;\n cursor: pointer;\n}\n\n.transparent {\n opacity: 0.3!important;\n}\n\n.card-node {\n position: relative;\n}\n\n.card-comment {\n position: absolute;\n top: 0;\n right: 0;\n margin-top: -22px;\n color: #f4ad42!important;\n}\n\n.card-problem {\n position: absolute;\n top: 0;\n left: 0;\n margin-top: -22px;\n color: red!important;\n}\n\n.card-snapshot {\n\n}\n\n.card-snapshot-idle {\n border: 2px solid gray!important;\n box-shadow: 1px 1px 5px gray!important;\n opacity: 0.7!important;\n}\n\n.card-snapshot-computing {\n border: 2px solid darkgreen!important;\n box-shadow: 1px 1px 5px darkgreen!important;\n opacity: 1!important;\n}\n\n.card-snapshot-awaiting-data {\n border: 2px solid blue!important;\n box-shadow: 1px 1px 5px blue!important;\n opacity: 0.7!important;\n}\n\n.card-snapshot-ready {\n border: 2px solid lightgreen!important;\n box-shadow: 1px 1px 5px lightgreen!important;\n opacity: 1!important;\n}\n\n.card-status {\n position: absolute;\n bottom: 0;\n right: 0;\n left: 0;\n margin-bottom: -26px;\n color: #f4ad42!important;\n font-family: \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n font-weight: bold;\n text-align: center;\n}\n\n.card-status-idle {\n color: gray!important;\n min-width: 85px;\n}\n\n.card-status-computing {\n color: darkgreen!important;\n min-width: 110px;\n}\n\n.card-status-awaiting-data {\n color: blue!important;\n min-width: 85px;\n}\n\n.card-status-ready {\n color: lightgreen!important;\n min-width: 85px;\n}\n\n.btn-snapshot-details {\n position: relative;\n margin-top: -2px;\n color: inherit;\n}\n\nspan.name {\n overflow-wrap: normal;\n}\n</style>\n\n<template>\n <div class=\"jtk-node card card-node contextmenu\" v-bind:class=\"{ 'card-loop': n.hasLoop(), 'card-ui': n.isUI(), 'card-metanode': n.isMetanode(), 'card-input': n.isInput(), 'card-output': n.isOutput(), 'card-snapshot': n.hasSnapshot(), 'card-snapshot-idle': n.hasSnapshot() && n.isSnapshotStatus(0), 'card-snapshot-computing': n.hasSnapshot() && n.isSnapshotStatus(1), 'card-snapshot-awaiting-data': n.hasSnapshot() && n.isSnapshotStatus(2), 'card-snapshot-ready': n.hasSnapshot() && n.isSnapshotStatus(3) }\" v-bind:id=\"getId()\" v-bind:data-id=\"getId()\" v-bind:data-name=\"pkg.name\" style=\"overflow: visible;\">\n <div v-if=\"n.hasComment()\">\n <div class=\"card-comment\" data-toggle=\"tooltip\" data-placement=\"top\" :title=\"n.getComment()\">\n <i class=\"fas fa-comment-alt\" data-container=\"body\"></i>\n </div>\n </div>\n\n <div v-if=\"n.hasSnapshot()\">\n <div class=\"card-status\">\n <div v-if=\"n.isSnapshotStatus(0)\">\n <div class=\"card-status-idle\">\n <span>IDLE</span>\n <button class=\"btn btn-editor-xs btn-outline-secondary btn-outline-discrete btn-snapshot-details d-inline-block\" data-id=\"getId()\" v-on:click=\"openSnapshotDetails\"><i class=\"fas fa-info-circle\"></i></button>\n </div>\n </div>\n\n <div v-if=\"n.isSnapshotStatus(1)\">\n <div class=\"card-status-computing\">\n <span>COMPUTING</span>\n <button class=\"btn btn-editor-xs btn-outline-secondary btn-outline-discrete btn-snapshot-details d-inline-block\" data-id=\"getId()\" v-on:click=\"openSnapshotDetails\"><i class=\"fas fa-info-circle\"></i></button>\n </div>\n </div>\n\n <div v-if=\"n.isSnapshotStatus(2)\">\n <div class=\"card-status-awaiting-data\">\n <span>WAITING</span>\n <button class=\"btn btn-editor-xs btn-outline-secondary btn-outline-discrete btn-snapshot-details d-inline-block\" data-id=\"getId()\" v-on:click=\"openSnapshotDetails\"><i class=\"fas fa-info-circle\"></i></button>\n </div>\n </div>\n\n <div v-if=\"n.isSnapshotStatus(3)\">\n <div class=\"card-status-ready\">\n <span>READY</span>\n <button class=\"btn btn-editor-xs btn-outline-secondary btn-outline-discrete btn-snapshot-details d-inline-block\" data-id=\"getId()\" v-on:click=\"openSnapshotDetails\"><i class=\"fas fa-info-circle\"></i></button>\n </div>\n </div>\n </div>\n </div>\n\n <div v-if=\"!example && n.isUI() && !n.isOnAPanel()\">\n <div class=\"card-problem\">\n <i class=\"fas fa-exclamation-circle\" data-container=\"body\" data-toggle=\"popover\" data-placement=\"top\" data-content=\"This UI is not set in a panel. It won't have any effect. Go to the Interface tab to add it to a panel.\"></i>\n </div>\n </div>\n\n <div class=\"card-top\">\n <div class=\"d-flex\">\n <span class=\"title\" style=\"white-space: nowrap; margin-right: 5px;\">\n <span v-if=\"n.isMetanode()\" class=\"badge badge-secondary\"><b>META</b></span>\n {{n.graphId}}\n <i v-if=\"n.isParallel()\" class=\"fas fa-server\" style=\"color: orange;\" title=\"this module is computed in a web worker\"></i>\n </span>\n\n <div class=\"ml-auto\">\n <button class=\"btn btn-outline-secondary btn-outline-discrete btn-editor-xs btn-settings\" v-on:click=\"openNodeSettings\"><i class=\"fas fa-cog\"></i></button>\n </div>\n </div>\n </div>\n <div v-if=\"!n.isInput() && !n.isOutput()\" class=\"card-center\">\n <hr style=\"margin-bottom: 5px;\"/>\n <div class=\"dualbox-io\" style=\"overflow: visible;\">\n <div class=\"inputs\" style=\"display: inline-block; float: left;\">\n <div class=\"box-inputs\">\n <div class=\"types\">\n <span class=\"type\" v-for=\"key in getVisibleInputs()\" v-bind:data-key=\"key\">\n {{ n.getInputType(key) }}\n </span>\n </div>\n <div class=\"points\">\n <div class=\"point\" v-for=\"key in getVisibleInputs()\" v-bind:data-key=\"key\" v-bind:data-type=\"n.getInputDef(key).type\" v-html=\"point\"></div>\n </div>\n <div class=\"names\">\n <span class=\"name\" v-for=\"key in getVisibleInputs()\" :class=\"{'feedback': n.isFeedbackTarget(key), 'input-not-resolvable': !example && !n.isInputResolvable(key) }\" v-bind:data-input=\"key\">\n <span v-if=\"n.hasIterator(key)\">&lt;{{key}}&gt;</span>\n <span v-else>{{key}}</span>\n <small v-if=\"!n.isInputConst(key)\" data-toggle=\"tooltip\" data-trigger=\"hover\" title=\"this value will be cloned at execution time\"><i class=\"fas fa-clone transparent\"></i></small>\n </span>\n </div>\n </div>\n </div>\n <div class=\"outputs\" style=\"display: inline-block; float: right\">\n <div class=\"box-outputs\">\n <div class=\"names\">\n <span class=\"name\" v-for=\"key in getVisibleOutputs()\" v-bind:class=\"{feedback: n.isFeedbackTarget(key)}\" v-bind:data-output=\"key\">\n <span v-if=\"n.hasLoop() && n.hasFeedback(key)\">{{key}}</span>\n <span v-else-if=\"n.hasLoop() && !n.hasFeedback(key)\" v-html='\"&lt;\"+key+\"&gt;\"'></span>\n <span v-else>{{key}}</span>\n\n <span v-if=\"n.hasCacheActivated()\">\n &nbsp;<i class=\"fa fa-hdd\" title=\"This module has cache activated\"></i>\n </span>\n </span>\n </div>\n <div class=\"points\">\n <div class=\"point\" v-for=\"key in getVisibleOutputs()\" v-bind:data-key=\"key\" v-bind:data-type=\"n.getOutputDef(key).type\" v-html=\"point\"></div>\n </div>\n <div class=\"types\">\n <span class=\"type\" v-for=\"key in getVisibleOutputs()\" v-bind:data-key=\"key\">\n {{ n.getOutputType(key) }}\n </span>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <hr style=\"margin-top: 5px;\"/>\n <div class=\"card-bottom\">\n <span class=\"subtitle\">{{ shortName }}</span>\n\n <div v-if=\"n.isMetanode()\" class=\"d-inline-block\">\n <button class=\"btn btn-outline-secondary btn-outline-discrete btn-editor-xs btn-enter-metanode\" v-on:click=\"enterMetanode\"><i class=\"fas fa-sign-in-alt\"></i></button>\n </div>\n\n <!--\n <div v-if=\"n.isUI()\" class=\"event-dock event-dock-bottom\"></div>\n -->\n </div>\n </div>\n</template>\n\n<script>\nimport ContextMenu from '../ContextMenu';\nimport _ from 'lodash';\nimport dbutils from '../../m/DualboxUtils';\n\n// fix inputs types and output types position relatively to the div\n$.fn.fixCardDisplay = function() {\n var offsetPoint = 12;\n var offsetBorder = parseInt($(this).css(\"border-top-width\"));\n\n if( $(this).find('.box-inputs').height() === 0 && $(this).find('.box-outputs').height() === 0 ) {\n // if this card has no input/output, remove the card center\n $(this).find('.card-center').remove();\n }\n else {\n // else, adjust the input/output display for endpoints\n // 1) translate inputs by the right amount of pixels to have the circle on the line\n var boxInputs = $(this).find('.box-inputs');\n\n // fix css names width\n var namesDiv = boxInputs.find('.names');\n namesDiv.css('width', (namesDiv.width()+1) + 'px');\n\n // translate inputs to the left\n var translateLeft = boxInputs.find('.types').width() + offsetPoint + offsetBorder/2;\n $(this).find('.box-inputs').css('transform', 'translateX(-' + translateLeft + 'px)');\n\n // adjust inputs main div width\n $(this).find('.inputs').width( $(this).find('.inputs').width() - translateLeft + 10 /* margin */ );\n\n\n // 2) translate outputs by the right amount of pixels to have the circle on the line\n var boxOutputs = $(this).find('.box-outputs');\n\n // fix css names with\n var namesDiv = boxOutputs.find('.names');\n namesDiv.css('width', (namesDiv.width() + 1) + 'px');\n\n // translate inputs to the right\n var translateRight = boxOutputs.find('.types').width() + offsetPoint + offsetBorder/2;\n $(this).find('.box-outputs').css('transform', 'translateX(' + translateRight + 'px)');\n\n // adjust output main div width\n $(this).find('.outputs').width( $(this).find('.outputs').width() - translateRight + 10 /* margin */ );\n\n // fix io width\n //$('.dualbox-io').css('width', (($(this).find('.inputs').width() + $(this).find('.outputs').width()) + \"px\"));\n }\n}\n\n// take the current width and add it as a css property\n$.fn.fixWidth = function() {\n var width = $(this).width();\n width += parseInt($(this).css('padding-right'));\n width += parseInt($(this).css('padding-left'));\n width += parseInt($(this).css('border-left-width'));\n width += parseInt($(this).css('border-right-width'));\n $(this).css('width', width + 'px');\n}\n\n// find position of element relative to an ancestor matching selector\n$.fn.positionFrom = function( selector ) {\n var ancestor = $(this).closest(selector);\n var offset = $(this).offset();\n var ancestorOffset = ancestor.offset();\n return {\n top: offset.top - ancestorOffset.top,\n left: offset.left - ancestorOffset.left,\n }\n}\n\nexport default {\n props: [\n \"id\", // the module id\n \"pkg\", // the module package.json\n \"n\", // the GraphNode object (from model)\n \"example\", // true if this vue is used as an example display (no need to connect)\n \"displayEvents\", // true if events should be displayed\n ],\n data: function () {\n return {\n shortName: \"\",\n point: '<svg width=\"14\" height=\"14\" pointer-events=\"all\" position=\"absolute\" version=\"1.1\" xmlns=\"http://www.w3.org/1999/xhtml\"><circle cx=\"7\" cy=\"7\" r=\"5\" version=\"1.1\" xmlns=\"http://www.w3.org/1999/xhtml\" fill=\"#ffffff\" stroke=\"#727272\" style=\"\" stroke-width=\"2\"></circle></svg>',\n }\n },\n beforeUpdate: function() {\n //console.log('[UPDATING] ' + this.n.getUniqId());\n },\n destroyed: function() {\n //console.log('[DESTROYED] ' + this.n.getUniqId());\n },\n created: function() {\n this.initialized = false;\n this.view = window.dualboxEditor.v;\n\n //console.log('[CREATED] ' + this.n.getUniqId());\n // We compute the shortname of our box\n if( this.n.isInput() || this.n.isOutput() ) {\n this.shortName = this.n.getType();\n }\n else {\n this.shortName = dbutils.shortName(this.pkg.name);\n }\n },\n mounted: async function() {\n //console.log('[MOUNTED] ' + this.n.getUniqId());\n var div = $(this.$el);\n div.fixCardDisplay();\n div.ready(() => {\n //if( !this.example ) {\n div.fixWidth();\n //}\n });\n this.activateTooltip();\n return await this.initialize();\n },\n beforeUpdate: function() {\n this.deactivateTooltip();\n },\n updated: async function() {\n //console.log('[UPDATED] ' + this.n.getUniqId());\n\n // we reset jsPlumb before app update (in graph.vue)\n // so we need to initialize again\n this.assignContextMenu();\n\n $(this.$el).fixCardDisplay();\n $(this.$el).ready(()=>{\n $(this.$el).fixWidth();\n this.activateTooltip();\n });\n return await this.initialize();\n },\n activate: function() {\n this.activateTooltip();\n },\n deactivate: function() {\n this.deactivateTooltip();\n },\n methods: {\n getId: function() {\n // if this is an example graphNode, change our \"id\" to \"id-junk\"\n // to avoid connection jsplumb conflicts with the real node\n return this.example ? this.id + '-junk' : this.id;\n },\n\n activateTooltip: function() {\n $(this.$el).find('[data-toggle=\"tooltip\"]').tooltip();\n },\n\n deactivateTooltip: function() {\n $(this.$el).find('[data-toggle=\"tooltip\"]').tooltip(\"dispose\");\n },\n\n initialize: async function() {\n var self = this;\n var div = $(this.$el);\n var id = this.getId();\n var view = this.view;\n\n this.initialized = false;\n\n if( !this.example ) {\n // if we have a position, set it\n var def = this.n.getDef();\n var position = _.get(def, [\"graph\", \"position\"]);\n if( position ) {\n var jsPlumbElement = self.$parent.jsPlumbInstance.getElement(id);\n self.$parent.jsPlumbInstance.setPosition(jsPlumbElement, position);\n }\n\n // This needs to be registered before draggable\n div.on('mousedown', function(e) {\n // if this div is not selected already, deselect the other divs\n if( !self.$parent.selector.isSelected(this) ) {\n self.$parent.selector.deselect();\n }\n });\n\n await this.initializeJsPlumb();\n\n div.click(function(e) {\n if( e.ctrlKey ) {\n view.selector.toggleSelection(this);\n }\n });\n\n this.assignContextMenu();\n }\n\n return new Promise(resolve => {\n div.ready(() => {\n //console.log('[INITIALIZED] ' + this.n.getUniqId());\n this.initialized = true;\n resolve();\n });\n });\n },\n\n initializeJsPlumb: function() {\n var self = this;\n var div = $(this.$el);\n var id = this.getId();\n var view = this.view;\n\n if( !this.example ) {\n // If this node was never initialized in this jsplumb instance, do it\n if( !_.get(this.$parent.jsPlumbInstance, [\"initializedNodes\", id]) ) {\n _.set(this.$parent.jsPlumbInstance, [\"initializedNodes\", id], true); // initialized\n\n if( this.n.isInput() || this.n.isOutput() ) {\n var type = \"*\";\n var input = \"value\";\n var output = \"value\";\n var offsetTop = $(div).find('.card-top').height() + 12 /* hr size */ - 3;\n\n var uuid = [ id, \"input\", input].join('#');\n var ep = this.$parent.jsPlumbInstance.addEndpoint(id, {\n isSource : false,\n isTarget : true,\n uuid : uuid,\n anchor : [0,0,-1,0,0,offsetTop],\n maxConnections : 1,\n parameters : {\n type: \"data\",\n target : {\n id : id,\n input : output\n }\n }\n }, this.$parent.style.inputEndpoint);\n\n // add data to the endpoint div so we can identify it easier\n $(ep.canvas).attr('data-node', id);\n $(ep.canvas).attr('data-type', 'input');\n $(ep.canvas).attr('data-input', input);\n\n // bind tooltip\n $(ep.canvas).attr('data-toggle', \"tooltip\");\n $(ep.canvas).attr('data-trigger', \"hover\");\n $(ep.canvas).attr('data-placement', \"left\");\n $(ep.canvas).attr('data-html', \"true\");\n var inputType = view.m.getNode(id).getInputType(\"value\");\n $(ep.canvas).attr('title', \"Type: <b>\" + inputType + \"</b>\");\n $(ep.canvas).tooltip();\n\n // bind context menu to the endpoint\n $(ep.canvas).addClass('capture-right-click');\n $(ep.canvas).ready(function() {\n var menu = new ContextMenu(\".jtk-endpoint-anchor[data-node='\"+id.trim()+\"'][data-input='\" + input + \"']\", [\n {\n name: 'Create input for here',\n fn: () => {\n view.c.createInputFromConnection(id, input);\n }\n },\n ]);\n });\n\n var uuid = [ id, \"output\", output].join('#');\n var ep = this.$parent.jsPlumbInstance.addEndpoint(id, {\n isSource : true,\n isTarget : false,\n uuid : uuid,\n anchor : [1,0,1,0,0,offsetTop],\n parameters : {\n type: \"data\",\n source : {\n id : id,\n output : output\n }\n }\n }, this.$parent.style.outputEndpoint);\n\n // add data to the endpoint div so we can identify it easier\n $(ep.canvas).attr('data-node', id);\n $(ep.canvas).attr('data-type', \"output\");\n $(ep.canvas).attr('data-output', output);\n\n // bind tooltip\n $(ep.canvas).attr('data-toggle', \"tooltip\");\n $(ep.canvas).attr('data-trigger', \"hover\");\n $(ep.canvas).attr('data-placement', \"right\");\n $(ep.canvas).attr('data-html', \"true\");\n var outputType = view.m.getNode(id).getOutputType(\"value\");\n $(ep.canvas).attr('title', \"Type: <b>\" + outputType + \"</b>\");\n $(ep.canvas).tooltip();\n\n // bind context menu to the endpoint\n $(ep.canvas).addClass('capture-right-click');\n $(ep.canvas).ready(function() {\n var menu = new ContextMenu(\".jtk-endpoint-anchor[data-node='\"+id.trim()+\"'][data-output='\" + output.trim() + \"']\", [\n {\n name: 'Create output for here',\n fn: () => {\n view.c.createOutputFromConnection(id, output);\n }\n },\n ]);\n });\n }\n else {\n // add input endoints\n div.find('.box-inputs').find('.point').each( function(index) {\n $(this).css('visibility', 'hidden').css('opacity', '0'); // replaced by jsPlumb point\n\n var input = div.find('.box-inputs').find('.name').eq(index).attr('data-input').trim();\n var type = view.m.getNode(id).getInputType(input);\n\n var offsetTop = $(this).positionFrom('.card').top + $(this).height()/2 - 3;\n var uuid = [ id, \"input\", $(this).data('key')].join('#');\n var ep = self.$parent.jsPlumbInstance.addEndpoint(id, {\n isSource : false,\n isTarget : true,\n uuid : uuid,\n anchor : [0,0,-1,0,0,offsetTop],\n maxConnections : 1,\n parameters : {\n type: \"data\",\n target : {\n id : id,\n input : $(this).data('key')\n }\n }\n }, self.$parent.style.inputEndpoint);\n\n // add data to the endpoint div so we can identify it easier\n $(ep.canvas).attr('data-node', id);\n $(ep.canvas).attr('data-type', 'input');\n $(ep.canvas).attr('data-input', input);\n\n // bind tooltip\n $(ep.canvas).attr('data-toggle', \"tooltip\");\n $(ep.canvas).attr('data-trigger', \"hover\");\n $(ep.canvas).attr('data-placement', \"left\");\n $(ep.canvas).attr('data-html', \"true\");\n $(ep.canvas).attr('title', \"Type: <b>\" + type + \"</b>\");\n $(ep.canvas).tooltip();\n\n // bind context menu to the endpoint\n $(ep.canvas).addClass('capture-right-click');\n $(ep.canvas).ready(function() {\n var menu = new ContextMenu(\".jtk-endpoint-anchor[data-node='\"+id.trim()+\"'][data-input='\" + input.trim() + \"']\", [\n {\n name: 'Create input for here',\n fn: () => {\n view.c.createInputFromConnection(id, input);\n }\n },\n ]);\n });\n });\n\n // add output endpoints\n div.find('.box-outputs').find('.point').each( function(index) {\n $(this).css('visibility', 'hidden').css('opacity', '0'); // replaced by jsPlumb point\n\n var output = div.find('.box-outputs').find('.name').eq(index).attr('data-output').trim();\n var type = view.m.getNode(id).getOutputType(output);\n\n var offsetTop = $(this).positionFrom('.card').top + $(this).height()/2 - 3;\n var uuid = [ id, \"output\", $(this).data('key')].join('#');\n var ep = self.$parent.jsPlumbInstance.addEndpoint(id, {\n isSource : true,\n isTarget : false,\n uuid : uuid,\n anchor : [1,0,1,0,0,offsetTop],\n parameters : {\n type: \"data\",\n source : {\n id : id,\n output : $(this).data('key')\n }\n }\n }, self.$parent.style.outputEndpoint);\n\n // add data to the endpoint div so we can identify it easier\n $(ep.canvas).attr('data-node', id);\n $(ep.canvas).attr('data-type', \"output\");\n $(ep.canvas).attr('data-output', output);\n\n // bind tooltip\n $(ep.canvas).attr('data-toggle', \"tooltip\");\n $(ep.canvas).attr('data-trigger', \"hover\");\n $(ep.canvas).attr('data-placement', \"right\");\n $(ep.canvas).attr('data-html', \"true\");\n $(ep.canvas).attr('title', \"Type: <b>\" + type + \"</b>\");\n $(ep.canvas).tooltip();\n\n // bind context menu to the endpoint\n $(ep.canvas).addClass('capture-right-click');\n $(ep.canvas).ready(function() {\n var menu = new ContextMenu(\".jtk-endpoint-anchor[data-node='\"+id.trim()+\"'][data-output='\" + output.trim() + \"']\", [\n {\n name: 'Create output for here',\n fn: () => {\n view.c.createOutputFromConnection(id, output);\n }\n },\n ]);\n });\n });\n\n if( this.n.isUI() && this.displayEvents ) {\n // Make this a target for events\n this.$parent.jsPlumbInstance.makeTarget(id, {\n isSource:false,\n isTarget:true,\n uniqueEndpoint: false,\n anchor:\"Continuous\",\n uuid: id + \"#event-in\",\n paintStyle:{ fill:\"green\", radius: 3, stroke: \"#727272\", strokeWidth: 1 },\n parameters: {\n type: \"event\",\n target: { \"id\" : id }\n },\n }, self.$parent.style.eventEndpoint);\n\n // Create an enpoint to create a new event\n var ep = this.$parent.jsPlumbInstance.addEndpoint(id, {\n isSource : true,\n isTarget : false,\n uuid : id + \"#event-out\",\n anchor : [1, 1, 0, 1, 0, -10],\n parameters : {\n type: \"event\",\n source: { \"id\" : id }\n },\n paintStyle:{ fill:\"green\", radius: 3, stroke: \"#727272\", strokeWidth: 1 },\n }, this.$parent.style.eventEndpoint);\n\n // Add overlay here so we don't mess with splitConnection\n ep.addOverlay([\"PlainArrow\", { width:15, length:15, location:1, id:\"arrow\" }]);\n\n $(ep.canvas).attr('data-toggle', \"tooltip\");\n $(ep.canvas).attr('data-trigger', \"hover\");\n $(ep.canvas).attr('data-placement', \"bottom\");\n $(ep.canvas).attr('data-html', \"true\");\n $(ep.canvas).attr('title', \"Connect from here ito add an event that will be triggered when this box is done computing.\");\n $(ep.canvas).tooltip();\n }\n }\n\n // Make the div draggable\n this.$parent.jsPlumbInstance.draggable(div, {\n //containment:true, // not allowed outside of container div\n drag: function(e) {\n // TODO: bug. After a repaint(), jsPlumb seems to be broken (connections dont follow on div drag)\n // It doesn't occur on jsPlumb.reset() instead of creating another instance on beforeUpdate(),\n // (as it should be), but we can't do that, because JsPlumb is broken on zoom otherwise...\n // One of thoses problem may be fixed later by updating jsPlumb...\n // Note: this \"fix\" may affect performances on drag, maybe a setTimeout will do\n //self.$parent.jsPlumbInstance.repaintEverything();\n self.$parent.jsPlumbInstance.repaint(id);\n },\n stop: function(e) {\n // resize the canvas if necessary\n self.$parent.canvasSizeHandler.debouncedResize();\n\n if( self.$parent.selector.isMultipleSelectionActive() ) {\n // We just dropped a bunch of divs, ajust all their positions\n self.view.m.batch(() => {\n self.$parent.selector.each(div => {\n var pos = self.$parent.jsPlumbInstance.getPosition(div);\n view.m.getNode($(div).attr('id')).setPosition(pos);\n });\n });\n }\n else {\n // We just dropped this one, set the new position in the graph model\n var el = self.$parent.jsPlumbInstance.getElement(id);\n $(el).ready(function() {\n var pos = self.$parent.jsPlumbInstance.getPosition(el);\n view.m.getNode(id).setPosition(pos);\n });\n }\n }\n });\n }\n }\n\n return new Promise((resolve) => this.$parent.jsPlumbInstance.ready(resolve));\n },\n\n assignContextMenu: function() {\n var id = this.getId();\n\n // Create a contextmenu for the div\n var contextOptions = [\n {\n name: 'Remove this box',\n fn: () => {\n this.view.c.removeBox(id);\n }\n }\n ];\n if( this.n.isModule() || this.n.isUI() ) {\n contextOptions.push({\n name: 'Duplicate this box',\n fn: () => {\n this.view.c.duplicateBox(id);\n }\n });\n }\n var nodeMenu = new ContextMenu(\"#\" + id, contextOptions);\n },\n\n htmlentities: function( s ) {\n return this.view.utils.htmlentities(s);\n },\n\n getVisibleInputs: function() {\n return this.n.getInputsNames().filter((inputName) => {\n return this.n.isInputVisible(inputName);\n })\n },\n\n getVisibleOutputs: function() {\n return this.n.getOutputsNames().filter((outputName) => {\n return this.n.isOutputVisible(outputName);\n })\n },\n\n enterMetanode: function(e) {\n e.preventDefault();\n e.stopPropagation();\n\n this.view.c.enterMetanode(this.id);\n },\n\n openNodeSettings: function(e) {\n e.preventDefault();\n e.stopPropagation();\n this.view.openBoxSettings(this.id);\n },\n\n openSnapshotDetails: function(e) {\n e.preventDefault();\n e.stopPropagation();\n this.view.openDebug(this.id);\n }\n },\n watch: {\n 'app': {\n handler: () => {\n console.log('graphVue.app changed');\n },\n deep: true\n }\n }\n}\n\n</script>\n"]}, media: undefined });
46451
46458
 
46452
46459
  };
46453
46460
  /* scoped */
@@ -47099,11 +47106,11 @@ class Translater {
47099
47106
  */
47100
47107
 
47101
47108
  var editorView = null;
47102
- $.fn.savePosition = function( selector ) {
47109
+ $.fn.savePosition = function(selector) {
47103
47110
  var id = $(this).attr('id');
47104
- if( id ) {
47111
+ if (id) {
47105
47112
  var jsPlumbElement = editorView.jsPlumbInstance.getElement(id);
47106
- if( jsPlumbElement ) {
47113
+ if (jsPlumbElement) {
47107
47114
  var pos = editorView.jsPlumbInstance.getPosition(jsPlumbElement);
47108
47115
  editorView.view.m.getNode(id).setPosition(pos);
47109
47116
  }
@@ -47114,7 +47121,7 @@ class CanvasSizeHandler {
47114
47121
  constructor(parent, canvas) {
47115
47122
  this.parent = editorView = parent;
47116
47123
  this.canvas = canvas;
47117
- this.minWidth = this.width = this.canvas.width();
47124
+ this.minWidth = this.width = this.canvas.width();
47118
47125
  this.minHeight = this.height = this.canvas.height();
47119
47126
 
47120
47127
  // arbitrary: number of pixels to expand/shrink the canvas for 1 step
@@ -47128,41 +47135,41 @@ class CanvasSizeHandler {
47128
47135
  this.z = 0; // current zoom
47129
47136
  }
47130
47137
 
47131
- refreshZoom( z ) {
47138
+ refreshZoom(z) {
47132
47139
  this.z = z;
47133
47140
  }
47134
47141
 
47135
47142
  // set the current width and height to the new canvas
47136
47143
  apply() {
47137
47144
  var offset = this.canvas.offset();
47138
- var oldWidth = this.canvas.width();
47145
+ var oldWidth = this.canvas.width();
47139
47146
  var oldHeight = this.canvas.height();
47140
47147
 
47141
- if( oldWidth !== this.width ) {
47148
+ if (oldWidth !== this.width) {
47142
47149
  console.log('setting canvas width: %s -> %s', this.canvas.width(), this.width);
47143
47150
  this.canvas.width(this.width);
47144
47151
  }
47145
- if( oldHeight !== this.height ) {
47152
+ if (oldHeight !== this.height) {
47146
47153
  console.log('setting canvas height: %s -> %s', this.canvas.height(), this.height);
47147
47154
  this.canvas.height(this.height);
47148
47155
  }
47149
47156
 
47150
47157
  // If we are in a zoomed state, we need to update the transform-origin so we stay at the same position
47151
- if( this.z !== 1 ) {
47152
- // transform-origin is defined in % in the debugger, but for some reason, jquery seems to give us offset when
47158
+ if (this.z !== 1) {
47159
+ // transform-origin is defined in % in the debugger, but for some reason, jquery seems to give us offset when
47153
47160
  // we integrate it
47154
47161
  var oldTO = this.canvas.css('transform-origin');
47155
47162
  var oldTOX = parseFloat(oldTO);
47156
47163
  var oldTOY = parseFloat(oldTO.split(' ')[1]);
47157
47164
  var newTOX = oldTOX; // init thoses at the old value
47158
- var newTOY = oldTOY;
47165
+ var newTOY = oldTOY;
47159
47166
 
47160
- if( oldWidth !== this.width ) {
47167
+ if (oldWidth !== this.width) {
47161
47168
  var xRatioChange = this.width / oldWidth;
47162
47169
  var newTOX = oldTOX * xRatioChange;
47163
47170
  }
47164
47171
 
47165
- if( oldHeight !== this.height ) {
47172
+ if (oldHeight !== this.height) {
47166
47173
  var yRatioChange = this.height / oldHeight;
47167
47174
  var newTOY = oldTOY * yRatioChange;
47168
47175
  }
@@ -47178,21 +47185,21 @@ class CanvasSizeHandler {
47178
47185
  // dont trigger save
47179
47186
  this.parent.view.m.history.ignore(() => {
47180
47187
  // refresh zoom value, zoom affects width, height and offset calculations
47181
- this.refreshZoom( this.parent.zoomer.getZoom() );
47188
+ this.refreshZoom(this.parent.zoomer.getZoom());
47182
47189
 
47183
47190
  // find the coord of the 2d box bounding all divs
47184
47191
  var most = {
47185
- top: +Infinity,
47192
+ top: +Infinity,
47186
47193
  bottom: -Infinity,
47187
- left: +Infinity,
47188
- right: -Infinity
47194
+ left: +Infinity,
47195
+ right: -Infinity
47189
47196
  };
47190
47197
  this.canvas.find('.card').each(function() {
47191
47198
  var rect = this.getBoundingClientRect();
47192
- if( rect.top < most.top ) most.top = Math.floor(rect.top);
47193
- if( rect.bottom > most.bottom ) most.bottom = Math.ceil(rect.bottom);
47194
- if( rect.left < most.left ) most.left = Math.floor(rect.left);
47195
- if( rect.right > most.right ) most.right = Math.ceil(rect.right);
47199
+ if (rect.top < most.top) most.top = Math.floor(rect.top);
47200
+ if (rect.bottom > most.bottom) most.bottom = Math.ceil(rect.bottom);
47201
+ if (rect.left < most.left) most.left = Math.floor(rect.left);
47202
+ if (rect.right > most.right) most.right = Math.ceil(rect.right);
47196
47203
  });
47197
47204
 
47198
47205
  // compare to the canvas coord
@@ -47200,24 +47207,24 @@ class CanvasSizeHandler {
47200
47207
  var tresholdAdapted = this.treshold * this.z;
47201
47208
 
47202
47209
  var r = {
47203
- top: ((canvasRect.top + tresholdAdapted) - most.top) / this.z,
47210
+ top: ((canvasRect.top + tresholdAdapted) - most.top) / this.z,
47204
47211
  bottom: (most.bottom - (canvasRect.bottom - tresholdAdapted)) / this.z,
47205
- left: ((canvasRect.left + tresholdAdapted) - most.left) / this.z,
47206
- right: (most.right - (canvasRect.right - tresholdAdapted)) / this.z
47212
+ left: ((canvasRect.left + tresholdAdapted) - most.left) / this.z,
47213
+ right: (most.right - (canvasRect.right - tresholdAdapted)) / this.z
47207
47214
  };
47208
47215
 
47209
47216
  // avoid to resize for some pixel roundup
47210
- if( Math.abs(r.top) > 2 || Math.abs(r.left) > 2 || Math.abs(r.bottom) > 2 || Math.abs(r.right) > 2 ) {
47217
+ if (Math.abs(r.top) > 2 || Math.abs(r.left) > 2 || Math.abs(r.bottom) > 2 || Math.abs(r.right) > 2) {
47211
47218
  // resize width and height
47212
47219
  this.width += r.left + r.right;
47213
47220
  this.height += r.top + r.bottom;
47214
- if( this.width < this.minWidth ) this.width = this.minWidth;
47215
- if( this.height < this.minHeight ) this.height = this.minHeight;
47221
+ if (this.width < this.minWidth) this.width = this.minWidth;
47222
+ if (this.height < this.minHeight) this.height = this.minHeight;
47216
47223
  this.apply();
47217
47224
 
47218
47225
  // if we're expanding to the top or shrinking back, move the non-selected divs
47219
47226
  // in the opposite direction
47220
- if( r.top > 0 || (r.top < 0 && this.height > this.minHeight) ) {
47227
+ if (r.top > 0 || (r.top < 0 && this.height > this.minHeight)) {
47221
47228
  // move the non-selected divs to the bottom
47222
47229
  this.canvas.find('.card:not(.selected)').each(function() {
47223
47230
  var offset = $(this).offset();
@@ -47233,7 +47240,7 @@ class CanvasSizeHandler {
47233
47240
  }
47234
47241
 
47235
47242
  // same for left
47236
- if( r.left > 0 || (r.left < 0 && this.width > this.minWidth) ) {
47243
+ if (r.left > 0 || (r.left < 0 && this.width > this.minWidth)) {
47237
47244
  // move the non-selected divs to the right
47238
47245
  this.canvas.find('.card:not(.selected)').each(function() {
47239
47246
  var offset = $(this).offset();
@@ -87787,24 +87794,24 @@ class Merger {
87787
87794
 
87788
87795
  this.nodes = [];
87789
87796
  lodash.each(ids, (id) => {
87790
- this.nodes.push( this.m.getNode(id) );
87797
+ this.nodes.push(this.m.getNode(id));
87791
87798
  });
87792
87799
 
87793
87800
  this.id = null;
87794
87801
 
87795
87802
  // links from and to outside
87796
87803
  this.inboundLinksFromOutside = [];
87797
- this.outboundLinksToOutside = [];
87804
+ this.outboundLinksToOutside = [];
87798
87805
  }
87799
87806
 
87800
87807
  // merge all divs into a metabox
87801
87808
  // ids: array of ids from the boxes to be merged
87802
87809
  // metaboxName: name of the new metabox
87803
87810
  // metaboxDesc: description of the new metabox
87804
- merge( metaboxName, metaboxDesc ) {
87811
+ merge(metaboxName, metaboxDesc) {
87805
87812
  this.def.desc = metaboxDesc;
87806
87813
 
87807
- this.m.history.batch( () => {
87814
+ this.m.batch(() => {
87808
87815
  // 0. create a new ID for our metanode
87809
87816
  this.id = metaboxName + '-' + utils.randomString(8);
87810
87817
 
@@ -87828,16 +87835,16 @@ class Merger {
87828
87835
 
87829
87836
  // 5. Our metanode definition is ready, add it to the app
87830
87837
  this.m.data.app.metanodes = this.m.data.app.metanodes || {};
87831
- this.m.data.app.metanodes[ metaboxName ] = this.def;
87838
+ this.m.data.app.metanodes[metaboxName] = this.def;
87832
87839
 
87833
87840
  // 6. Create a new node from this def
87834
87841
  this.m.data.app.modules[this.id] = {
87835
- "module" : metaboxName,
87842
+ "module": metaboxName,
87836
87843
  "version": "*",
87837
- "graph" : {
87838
- "position" : {
87839
- top : (bbox.top + bbox.bottom) / 2,
87840
- left : (bbox.left + bbox.right) / 2
87844
+ "graph": {
87845
+ "position": {
87846
+ top: (bbox.top + bbox.bottom) / 2,
87847
+ left: (bbox.left + bbox.right) / 2
87841
87848
  }
87842
87849
  }
87843
87850
  };
@@ -87849,13 +87856,13 @@ class Merger {
87849
87856
  }
87850
87857
 
87851
87858
  _debug() {
87852
- console.log( this.def );
87859
+ console.log(this.def);
87853
87860
  }
87854
87861
 
87855
- _isInMetanode( id ) {
87862
+ _isInMetanode(id) {
87856
87863
  var inGroup = false;
87857
- lodash.each( this.nodes, (node) => {
87858
- if( node.id === id ) {
87864
+ lodash.each(this.nodes, (node) => {
87865
+ if (node.id === id) {
87859
87866
  inGroup = true;
87860
87867
  return false; // eol
87861
87868
  }
@@ -87865,36 +87872,35 @@ class Merger {
87865
87872
 
87866
87873
  // find the links from and to outside the metanode
87867
87874
  _collectAndDetachExternalLinks() {
87868
- lodash.each( this.nodes, (node) => {
87875
+ lodash.each(this.nodes, (node) => {
87869
87876
  var links = node.getInboundLinks();
87870
- lodash.each( links, (link) => {
87871
- if( !this._isInMetanode(link.sourceId) ) {
87877
+ lodash.each(links, (link) => {
87878
+ if (!this._isInMetanode(link.sourceId)) {
87872
87879
  link.detach(); // we don't need this link anymore
87873
- this.inboundLinksFromOutside.push( link );
87880
+ this.inboundLinksFromOutside.push(link);
87874
87881
  }
87875
87882
  });
87876
87883
 
87877
87884
  var links = node.getOutboundLinks();
87878
- lodash.each( links, (link) => {
87879
- if( !this._isInMetanode(link.targetId) ) {
87885
+ lodash.each(links, (link) => {
87886
+ if (!this._isInMetanode(link.targetId)) {
87880
87887
  link.detach();
87881
- this.outboundLinksToOutside.push( link );
87888
+ this.outboundLinksToOutside.push(link);
87882
87889
  }
87883
87890
  });
87884
87891
  });
87885
87892
  }
87886
87893
 
87887
87894
  // transform "cond" into "cond2", or "cond3" if cond2 is taken, etc.
87888
- _nextName( type, name ) {
87895
+ _nextName(type, name) {
87889
87896
  // find the appropriate number end (that is not taken already)
87890
87897
  var ending = 2;
87891
- if( type == "input" ) {
87892
- while( this.def.input[ name + "-" + ending ] ) ending++;
87893
- }
87894
- else {
87895
- while( this.def.output[ name + "-" + ending ] ) ending++;
87898
+ if (type == "input") {
87899
+ while (this.def.input[name + "-" + ending]) ending++;
87900
+ } else {
87901
+ while (this.def.output[name + "-" + ending]) ending++;
87896
87902
  }
87897
- return name+"-"+ending;
87903
+ return name + "-" + ending;
87898
87904
  }
87899
87905
 
87900
87906
  // find and create the metabox inputs
@@ -87907,7 +87913,7 @@ class Merger {
87907
87913
  var getInputNameForThisLink = function(l) {
87908
87914
  var r = null;
87909
87915
  lodash.each(inputToLinks, (link, inputName) => {
87910
- if( link.sourceId == l.sourceId && link.sourceOutput == l.sourceOutput ) {
87916
+ if (link.sourceId == l.sourceId && link.sourceOutput == l.sourceOutput) {
87911
87917
  r = inputName;
87912
87918
  return false;
87913
87919
  }
@@ -87921,7 +87927,7 @@ class Merger {
87921
87927
 
87922
87928
  // get the original input name, rename if necessary
87923
87929
  var inputName = link.targetInput;
87924
- if( this.def.input[inputName] ) {
87930
+ if (this.def.input[inputName]) {
87925
87931
 
87926
87932
  // check if an input for this source has already been created
87927
87933
  // otherwise, create a new one
@@ -87929,8 +87935,8 @@ class Merger {
87929
87935
  inputName = lookupInputName ? lookupInputName : this._nextName("input", inputName);
87930
87936
  }
87931
87937
 
87932
- this.def.input[ inputName ] = {
87933
- type: targetNode.getInputType( link.targetInput ),
87938
+ this.def.input[inputName] = {
87939
+ type: targetNode.getInputType(link.targetInput),
87934
87940
  graph: {
87935
87941
  position: this._computeInputSmartPosition(index)
87936
87942
  }
@@ -87942,7 +87948,7 @@ class Merger {
87942
87948
  link.nextTargetInput = inputName;
87943
87949
 
87944
87950
  // save our link in the dictionary
87945
- inputToLinks[ inputName ] = link;
87951
+ inputToLinks[inputName] = link;
87946
87952
  });
87947
87953
  }
87948
87954
 
@@ -87953,13 +87959,13 @@ class Merger {
87953
87959
  var sourceNode = link.getSourceNode();
87954
87960
 
87955
87961
  var outputName = link.sourceOutput;
87956
- if( this.def.output[ outputName ] ) {
87962
+ if (this.def.output[outputName]) {
87957
87963
  // check if the source of the output is the same as this link
87958
87964
  var outputLink = this.def.output[outputName].link;
87959
87965
  var sourceId = lodash.keys(outputLink)[0];
87960
87966
  var sourceOutput = outputLink[sourceId];
87961
87967
 
87962
- if( !(link.sourceId == sourceId && link.sourceOutput == sourceOutput) ) {
87968
+ if (!(link.sourceId == sourceId && link.sourceOutput == sourceOutput)) {
87963
87969
  // the output already exists. we need to create another one.
87964
87970
  outputName = this._nextName("output", outputName);
87965
87971
  }
@@ -87967,8 +87973,8 @@ class Merger {
87967
87973
 
87968
87974
  var l = {};
87969
87975
  l[link.sourceId] = link.sourceOutput;
87970
- this.def.output[ outputName ] = {
87971
- type: sourceNode.getOutputType( link.sourceOutput ),
87976
+ this.def.output[outputName] = {
87977
+ type: sourceNode.getOutputType(link.sourceOutput),
87972
87978
  graph: {
87973
87979
  position: this._computeOutputSmartPosition(index)
87974
87980
  },
@@ -87988,15 +87994,15 @@ class Merger {
87988
87994
  var left = Number.MAX_SAFE_INTEGER;
87989
87995
  lodash.each(this.nodes, (node) => {
87990
87996
  var pos = node.getPosition();
87991
- if( pos.top < top ) top = pos.top;
87992
- if( pos.left < left ) left = pos.left;
87997
+ if (pos.top < top) top = pos.top;
87998
+ if (pos.left < left) left = pos.left;
87993
87999
  });
87994
88000
 
87995
88001
  // we want to put theses node to 50px top and 50px left, so compute the diff
87996
88002
  var topdiff = top - 50;
87997
88003
  var leftdiff = left - 250;
87998
- if( topdiff < 0 ) topdiff = 0;
87999
- if( leftdiff < 0 ) leftdiff = 0;
88004
+ if (topdiff < 0) topdiff = 0;
88005
+ if (leftdiff < 0) leftdiff = 0;
88000
88006
 
88001
88007
  // reposition all nodes
88002
88008
  lodash.each(this.nodes, (node) => {
@@ -88010,18 +88016,18 @@ class Merger {
88010
88016
  _moveNodes() {
88011
88017
  // move the nodes into the Metamodule def
88012
88018
  lodash.each(this.nodes, (node) => {
88013
- if( node.isMetanode() ) {
88019
+ if (node.isMetanode()) {
88014
88020
  // move the metanode definition too
88015
- this.def.metanodes[ node.def.module ] = node.getMetanodeDefinition();
88021
+ this.def.metanodes[node.def.module] = node.getMetanodeDefinition();
88016
88022
  }
88017
88023
 
88018
88024
  // move the node module definition (preserving the links between metabox's node)
88019
- this.def.modules[node.id] = this.m.data.app.modules[ node.id ];
88025
+ this.def.modules[node.id] = this.m.data.app.modules[node.id];
88020
88026
  delete this.m.data.app.modules[node.id];
88021
88027
 
88022
- if( node.isMetanode() ) {
88028
+ if (node.isMetanode()) {
88023
88029
  // if the metanode isn't still in use in the main app, remove def from here
88024
- if( !this.m.isMetanodeUsed(node.def.module) ) {
88030
+ if (!this.m.isMetanodeUsed(node.def.module)) {
88025
88031
  delete this.m.data.app.metanodes[node.def.module];
88026
88032
  }
88027
88033
  }
@@ -88031,7 +88037,7 @@ class Merger {
88031
88037
  _bindInputs() {
88032
88038
  lodash.each(this.inboundLinksFromOutside, (link) => {
88033
88039
  // we created an input with the same name, bind it to it
88034
- this.def.modules[link.targetId].links[link.targetInput] = { "input" : link.nextTargetInput };
88040
+ this.def.modules[link.targetId].links[link.targetInput] = { "input": link.nextTargetInput };
88035
88041
  });
88036
88042
  }
88037
88043
 
@@ -88063,18 +88069,18 @@ class Merger {
88063
88069
  // compute the bbox of all divs beeing merged, position the new div in the middle
88064
88070
  _computeBbox() {
88065
88071
  var most = {
88066
- top: +Infinity,
88072
+ top: +Infinity,
88067
88073
  bottom: -Infinity,
88068
- left: +Infinity,
88069
- right: -Infinity
88074
+ left: +Infinity,
88075
+ right: -Infinity
88070
88076
  };
88071
88077
 
88072
- lodash.each( this.nodes, (node) => {
88078
+ lodash.each(this.nodes, (node) => {
88073
88079
  var pos = node.getPosition();
88074
- if( pos.top < most.top ) most.top = pos.top;
88075
- if( pos.top > most.bottom ) most.bottom = pos.top;
88076
- if( pos.left < most.left ) most.left = pos.left;
88077
- if( pos.left > most.right ) most.right = pos.left;
88080
+ if (pos.top < most.top) most.top = pos.top;
88081
+ if (pos.top > most.bottom) most.bottom = pos.top;
88082
+ if (pos.left < most.left) most.left = pos.left;
88083
+ if (pos.left > most.right) most.right = pos.left;
88078
88084
  });
88079
88085
 
88080
88086
  return most;
@@ -88083,11 +88089,11 @@ class Merger {
88083
88089
  _getPositioningValues() {
88084
88090
  // todo: get a better system with the real bbox
88085
88091
  return {
88086
- width : 100,
88087
- height : 80,
88088
- hMargin : 80,
88089
- vMargin : 20,
88090
- divAvgWidth : 150
88092
+ width: 100,
88093
+ height: 80,
88094
+ hMargin: 80,
88095
+ vMargin: 20,
88096
+ divAvgWidth: 150
88091
88097
  }
88092
88098
  }
88093
88099