@dualbox/editor 1.0.1 → 1.0.3
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.
- package/js/src/GraphEditor.js +159 -0
- package/js/src/c/GraphController.js +646 -0
- package/js/src/libs/CodeMirror.js +8 -0
- package/js/src/libs/fontawesome.js +1 -0
- package/js/src/libs/jsoneditor.css +2 -0
- package/js/src/libs/jsoneditor.js +4 -0
- package/js/src/m/DualboxUtils.js +35 -0
- package/js/src/m/GraphModel.js +2167 -0
- package/js/src/m/History.js +94 -0
- package/js/src/m/Merger.js +357 -0
- package/js/src/v/AppManager.js +61 -0
- package/js/src/v/CanvasSizeHandler.js +136 -0
- package/js/src/v/ContextMenu.css +45 -0
- package/js/src/v/ContextMenu.js +239 -0
- package/js/src/v/GraphView.js +928 -0
- package/js/src/v/PlumbStyle.js +254 -0
- package/js/src/v/Selector.js +239 -0
- package/js/src/v/TemplateManager.js +79 -0
- package/js/src/v/Translater.js +174 -0
- package/js/src/v/Utils.js +7 -0
- package/js/src/v/Zoomer.js +201 -0
- package/js/src/v/templates/addNode.css +45 -0
- package/js/src/v/templates/addNode.html +62 -0
- package/js/src/v/templates/addNode.js +34 -0
- package/js/src/v/templates/debugNodeInfos.css +5 -0
- package/js/src/v/templates/debugNodeInfos.html +336 -0
- package/js/src/v/templates/debugNodeInfos.js +31 -0
- package/js/src/v/templates/editMainSettings.css +67 -0
- package/js/src/v/templates/editMainSettings.html +265 -0
- package/js/src/v/templates/editMainSettings.js +240 -0
- package/js/src/v/templates/editNodeSettings.css +86 -0
- package/js/src/v/templates/editNodeSettings.html +539 -0
- package/js/src/v/templates/editNodeSettings.js +356 -0
- package/js/src/v/templates/graphNode.css +333 -0
- package/js/src/v/templates/graphNode.html +227 -0
- package/js/src/v/templates/graphNode.js +412 -0
- package/js/src/v/templates/main.css +353 -0
- package/js/src/v/templates/main.html +149 -0
- package/js/src/v/templates/main.js +511 -0
- package/js/src/v/templates/searchResults.css +50 -0
- package/js/src/v/templates/searchResults.html +46 -0
- package/js/src/v/templates/searchResults.js +176 -0
- package/package.json +3 -2
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
@{ var utils = require('../../m/DualboxUtils') }
|
|
2
|
+
|
|
3
|
+
@!(data)
|
|
4
|
+
@{ var id = data.example ? data.id + "-junk" : data.id; }
|
|
5
|
+
<div class="jtk-node card card-node @cardColor(data.id) @cardLoop(data.id) @cardSnapshot(data.id) contextmenu" id="@(id)" data-id="@(data.id)" data-name="@(data.pkg.name)" style="overflow: visible;">
|
|
6
|
+
@if( data.n.hasComment() ) {
|
|
7
|
+
<div class="card-comment">
|
|
8
|
+
<i class="fas fa-comment-alt" data-container="body" data-toggle="popover" data-placement="top" data-content="@(data.n.getComment())"></i>
|
|
9
|
+
</div>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@if( data.n.hasSnapshot() ) {
|
|
13
|
+
<div class="card-status">
|
|
14
|
+
@if( data.n.isSnapshotStatus(0) ) {
|
|
15
|
+
<div class="card-status-idle">
|
|
16
|
+
<span>IDLE</span>
|
|
17
|
+
<button class="btn btn-xs btn-outline-secondary btn-outline-discrete btn-snapshot-details d-inline-block" data-id="@(data.id)"><i class="fas fa-info-circle"></i></button>
|
|
18
|
+
</div>
|
|
19
|
+
}
|
|
20
|
+
@if( data.n.isSnapshotStatus(1) ) {
|
|
21
|
+
<div class="card-status-computing">
|
|
22
|
+
<span>COMPUTING</span>
|
|
23
|
+
<button class="btn btn-xs btn-outline-secondary btn-outline-discrete btn-snapshot-details d-inline-block" data-id="@(data.id)"><i class="fas fa-info-circle"></i></button>
|
|
24
|
+
</div>
|
|
25
|
+
}
|
|
26
|
+
@if( data.n.isSnapshotStatus(2) ) {
|
|
27
|
+
<div class="card-status-awaiting-data">
|
|
28
|
+
<span>WAITING</span>
|
|
29
|
+
<button class="btn btn-xs btn-outline-secondary btn-outline-discrete btn-snapshot-details d-inline-block" data-id="@(data.id)"><i class="fas fa-info-circle"></i></button>
|
|
30
|
+
</div>
|
|
31
|
+
}
|
|
32
|
+
@if( data.n.isSnapshotStatus(3) ) {
|
|
33
|
+
<div class="card-status-ready">
|
|
34
|
+
<span>READY</span>
|
|
35
|
+
<button class="btn btn-xs btn-outline-secondary btn-outline-discrete btn-snapshot-details d-inline-block" data-id="@(data.id)"><i class="fas fa-info-circle"></i></button>
|
|
36
|
+
</div>
|
|
37
|
+
}
|
|
38
|
+
</div>
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@if( !data.example && data.n.isUI() && !data.n.isOnAPanel() ) {
|
|
42
|
+
<div class="card-problem">
|
|
43
|
+
<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>
|
|
44
|
+
</div>
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
<div class="card-top">
|
|
48
|
+
<div class="d-flex">
|
|
49
|
+
<span class="title" style="white-space: nowrap; margin-right: 5px;">
|
|
50
|
+
@if( data.n.isMetanode() ) { <span class="badge badge-secondary"><b>META</b></span> }
|
|
51
|
+
@(data.n.graphId)
|
|
52
|
+
@if( data.n.isParallel() ) { <i class="fas fa-server" style="color: orange;" title="this module is computed in a web worker"></i> }
|
|
53
|
+
</span>
|
|
54
|
+
|
|
55
|
+
<div class="ml-auto">
|
|
56
|
+
<button class="btn btn-outline-secondary btn-outline-discrete btn-xs btn-settings"><i class="fas fa-cog"></i></button>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
@if( !data.n.isInput() && !data.n.isOutput() ) {
|
|
61
|
+
<div class="card-center">
|
|
62
|
+
<hr style="margin-bottom: 5px;"/>
|
|
63
|
+
<div class="dualbox-io" style="overflow: visible;">
|
|
64
|
+
<div class="inputs" style="display: inline-block; float: left;">
|
|
65
|
+
<div class="box-inputs">
|
|
66
|
+
@{var keys = data.n.getInputsNames(); }
|
|
67
|
+
@if( keys && keys.length > 0 ) {
|
|
68
|
+
<div class="types">
|
|
69
|
+
@* Build types *@
|
|
70
|
+
@for(var i=0; i<keys.length; i++) {
|
|
71
|
+
@{var key = keys[i] }
|
|
72
|
+
@{var inputDesc = data.n.getInputDef(key); }
|
|
73
|
+
@if( data.n.isInputVisible(key) ) {
|
|
74
|
+
<span class="type" data-key="@key">@( data.utils.htmlentities(data.n.getInputType(key)) )</span>
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<div class="points">
|
|
80
|
+
@* Build points *@
|
|
81
|
+
@for(var i=0; i<keys.length; i++) {
|
|
82
|
+
@{var key = keys[i] }
|
|
83
|
+
@{var inputDesc = data.n.getInputDef(key); }
|
|
84
|
+
@if( data.n.isInputVisible(key) ) {
|
|
85
|
+
<div class="point" data-key="@key" data-type="@(inputDesc.type)">@point()</div>
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
</div>
|
|
89
|
+
<div class="names">
|
|
90
|
+
@* Build names *@
|
|
91
|
+
@for(var i=0; i<keys.length; i++) {
|
|
92
|
+
@{var key = keys[i] }
|
|
93
|
+
@{var inputDesc = data.n.getInputDesc(key); }
|
|
94
|
+
@if( data.n.isInputVisible(key) ) {
|
|
95
|
+
<span class="name @if(data.n.isFeedbackTarget(key)){feedback}" data-input="@(key)">
|
|
96
|
+
@if( data.n.hasIterator(key) ) {
|
|
97
|
+
<@(key)>
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
@(key)
|
|
101
|
+
}
|
|
102
|
+
@if( !data.n.isInputConst(key) ) {
|
|
103
|
+
<small><i class="fas fa-clone transparent"></i></small>
|
|
104
|
+
}
|
|
105
|
+
</span>
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
</div>
|
|
109
|
+
}
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
<div class="outputs" style="display: inline-block; float: right">
|
|
113
|
+
<div class="box-outputs">
|
|
114
|
+
@{var keys = data.n.getOutputsNames() }
|
|
115
|
+
@if( keys && keys.length > 0 ) {
|
|
116
|
+
<div class="names">
|
|
117
|
+
@* Build names *@
|
|
118
|
+
@for(var i=0; i<keys.length; i++) {
|
|
119
|
+
@{var key = keys[i] }
|
|
120
|
+
@if( data.n.isOutputVisible(key) ) {
|
|
121
|
+
<span class="name @if(data.n.hasFeedback(key)){feedback}" data-output="@(key)">
|
|
122
|
+
@if( data.n.hasLoop() ) {
|
|
123
|
+
@if( data.n.hasFeedback(key) ) {
|
|
124
|
+
@(key)
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
<@(key)>
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
@(key)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@if( data.n.hasCacheActivated() ) {
|
|
135
|
+
<i class="fa fa-hdd" title="This module has cache activated"></i>
|
|
136
|
+
}
|
|
137
|
+
</span>
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
<div class="points">
|
|
143
|
+
@* Build points *@
|
|
144
|
+
@for(var i=0; i<keys.length; i++) {
|
|
145
|
+
@{var key = keys[i] }
|
|
146
|
+
@{var outputDesc = data.n.getOutputDef(key); }
|
|
147
|
+
@if( data.n.isOutputVisible(key) ) {
|
|
148
|
+
<div class="point" data-key="@key" data-type="@(outputDesc.type)">@point()</div>
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
</div>
|
|
152
|
+
|
|
153
|
+
<div class="types">
|
|
154
|
+
@* Build types *@
|
|
155
|
+
@for(var i=0; i<keys.length; i++) {
|
|
156
|
+
@{var key = keys[i] }
|
|
157
|
+
@{var outputDesc = data.n.getOutputDef(key); }
|
|
158
|
+
@if( data.n.isOutputVisible(key) ) {
|
|
159
|
+
<span class="type" data-key="@key">@( data.utils.htmlentities(data.n.getOutputType(key)) )</span>
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
</div>
|
|
163
|
+
}
|
|
164
|
+
</div>
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
}
|
|
169
|
+
<hr style="margin-top: 5px;"/>
|
|
170
|
+
<div class="card-bottom">
|
|
171
|
+
<span class="subtitle">@( data.utils.htmlentities(shortname(data.id, data.pkg.name)) )</span>
|
|
172
|
+
@if( data.n.isMetanode() ) {
|
|
173
|
+
<div class="d-inline-block">
|
|
174
|
+
<button class="btn btn-outline-secondary btn-outline-discrete btn-xs btn-enter-metanode"><i class="fas fa-sign-in-alt"></i></button>
|
|
175
|
+
</div>
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
<!--
|
|
179
|
+
@if( data.n.isUI() ) {
|
|
180
|
+
<div class="event-dock event-dock-bottom"></div>
|
|
181
|
+
}
|
|
182
|
+
-->
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
|
|
186
|
+
@function cardColor( id ) {
|
|
187
|
+
@if( data.n.isUI() ) { card-ui }
|
|
188
|
+
else if( data.n.isMetanode() ) { card-metanode }
|
|
189
|
+
else if( data.n.isInput() ) { card-input }
|
|
190
|
+
else if( data.n.isOutput() ) { card-output }
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
@function cardLoop( id ) {
|
|
194
|
+
@if( data.n.hasLoop() ) { card-loop }
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
@function cardSnapshot(id) {
|
|
198
|
+
@if( data.n.hasSnapshot() ) {
|
|
199
|
+
card-snapshot
|
|
200
|
+
@if( data.n.isSnapshotStatus(0) ) {
|
|
201
|
+
card-snapshot-idle
|
|
202
|
+
}
|
|
203
|
+
@if( data.n.isSnapshotStatus(1) ) {
|
|
204
|
+
card-snapshot-computing
|
|
205
|
+
}
|
|
206
|
+
@if( data.n.isSnapshotStatus(2) ) {
|
|
207
|
+
card-snapshot-awaiting-data
|
|
208
|
+
}
|
|
209
|
+
@if( data.n.isSnapshotStatus(3) ) {
|
|
210
|
+
card-snapshot-ready
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
@function shortname( id, pkgName ) {
|
|
216
|
+
@if( data.n.isInput() || data.n.isOutput() ) {
|
|
217
|
+
@( data.n.getType() )
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
@{ var shortname = utils.shortName(pkgName) }
|
|
221
|
+
@(shortname)
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
@function point() {
|
|
226
|
+
<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>
|
|
227
|
+
}
|
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
const ContextMenu = require('../ContextMenu');
|
|
2
|
+
const _ = require('lodash');
|
|
3
|
+
|
|
4
|
+
// fix inputs types and output types position relatively to the div
|
|
5
|
+
$.fn.fixCardDisplay = function() {
|
|
6
|
+
var offsetPoint = 12;
|
|
7
|
+
var offsetBorder = parseInt($(this).css("border-top-width"));
|
|
8
|
+
|
|
9
|
+
if( $(this).find('.box-inputs').height() === 0 && $(this).find('.box-outputs').height() === 0 ) {
|
|
10
|
+
// if this card has no input/output, remove the card center
|
|
11
|
+
$(this).find('.card-center').remove();
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
// else, adjust the input/output display for endpoints
|
|
15
|
+
// 1) translate inputs by the right amount of pixels to have the circle on the line
|
|
16
|
+
var boxInputs = $(this).find('.box-inputs');
|
|
17
|
+
|
|
18
|
+
// fix css names width
|
|
19
|
+
var namesDiv = boxInputs.find('.names');
|
|
20
|
+
namesDiv.css('width', (namesDiv.width()+1) + 'px');
|
|
21
|
+
|
|
22
|
+
// translate inputs to the left
|
|
23
|
+
var translateLeft = boxInputs.find('.types').width() + offsetPoint + offsetBorder/2;
|
|
24
|
+
$(this).find('.box-inputs').css('transform', 'translateX(-' + translateLeft + 'px)');
|
|
25
|
+
|
|
26
|
+
// adjust inputs main div width
|
|
27
|
+
$(this).find('.inputs').width( $(this).find('.inputs').width() - translateLeft + 10 /* margin */ );
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
// 2) translate outputs by the right amount of pixels to have the circle on the line
|
|
31
|
+
var boxOutputs = $(this).find('.box-outputs');
|
|
32
|
+
|
|
33
|
+
// fix css names with
|
|
34
|
+
var namesDiv = boxOutputs.find('.names');
|
|
35
|
+
namesDiv.css('width', (namesDiv.width() + 1) + 'px');
|
|
36
|
+
|
|
37
|
+
// translate inputs to the right
|
|
38
|
+
var translateRight = boxOutputs.find('.types').width() + offsetPoint + offsetBorder/2;
|
|
39
|
+
$(this).find('.box-outputs').css('transform', 'translateX(' + translateRight + 'px)');
|
|
40
|
+
|
|
41
|
+
// adjust output main div width
|
|
42
|
+
$(this).find('.outputs').width( $(this).find('.outputs').width() - translateRight + 10 /* margin */ );
|
|
43
|
+
|
|
44
|
+
// fix io width
|
|
45
|
+
//$('.dualbox-io').css('width', (($(this).find('.inputs').width() + $(this).find('.outputs').width()) + "px"));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// take the current width and add it as a css property
|
|
50
|
+
$.fn.fixWidth = function() {
|
|
51
|
+
var width = $(this).width();
|
|
52
|
+
width += parseInt($(this).css('padding-right'));
|
|
53
|
+
width += parseInt($(this).css('padding-left'));
|
|
54
|
+
width += parseInt($(this).css('border-left-width'));
|
|
55
|
+
width += parseInt($(this).css('border-right-width'));
|
|
56
|
+
$(this).css('width', width + 'px');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// find position of element relative to an ancestor matching selector
|
|
60
|
+
$.fn.positionFrom = function( selector ) {
|
|
61
|
+
var ancestor = $(this).closest(selector);
|
|
62
|
+
var offset = $(this).offset();
|
|
63
|
+
var ancestorOffset = ancestor.offset();
|
|
64
|
+
return {
|
|
65
|
+
top: offset.top - ancestorOffset.top,
|
|
66
|
+
left: offset.left - ancestorOffset.left,
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
var editorView = null;
|
|
71
|
+
$.fn.savePosition = function( selector ) {
|
|
72
|
+
var id = $(this).attr('id');
|
|
73
|
+
if( id ) {
|
|
74
|
+
var jsPlumbElement = editorView.jsPlumbInstance.getElement(id);
|
|
75
|
+
if( jsPlumbElement ) {
|
|
76
|
+
var pos = editorView.jsPlumbInstance.getPosition(jsPlumbElement);
|
|
77
|
+
editorView.m.getNode(id).setPosition(pos);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
var TemplateBinds = function(view, div, data) {
|
|
83
|
+
editorView = view;
|
|
84
|
+
|
|
85
|
+
var id = $(div).attr('id');
|
|
86
|
+
var jsPlumbInstance = view.jsPlumbInstance;
|
|
87
|
+
|
|
88
|
+
div.fixCardDisplay();
|
|
89
|
+
div.ready(function() {
|
|
90
|
+
// div resize must be completed before jsplumb touches it
|
|
91
|
+
div.fixWidth();
|
|
92
|
+
|
|
93
|
+
if( !data.example ) {
|
|
94
|
+
// if we have a position, set it
|
|
95
|
+
var position = data && data.def && data.def.graph && data.def.graph.position;
|
|
96
|
+
if( position ) {
|
|
97
|
+
var jsPlumbElement = jsPlumbInstance.getElement(id);
|
|
98
|
+
jsPlumbInstance.setPosition(jsPlumbElement, position);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// This needs to be registered before draggable
|
|
102
|
+
div.on('mousedown', function(e) {
|
|
103
|
+
// if this div is not selected already, deselect the other divs
|
|
104
|
+
if( !view.selector.isSelected(this) ) {
|
|
105
|
+
view.selector.deselect();
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Make the div draggable
|
|
110
|
+
jsPlumbInstance.draggable(div, {
|
|
111
|
+
//containment:true, // not allowed outside of container div
|
|
112
|
+
drag: function(e) {
|
|
113
|
+
},
|
|
114
|
+
stop: function(e) {
|
|
115
|
+
// resize the canvas if necessary
|
|
116
|
+
view.canvasSizeHandler.debouncedResize();
|
|
117
|
+
|
|
118
|
+
// set the new position in the graph model
|
|
119
|
+
var el = jsPlumbInstance.getElement(id);
|
|
120
|
+
$(el).ready(function() {
|
|
121
|
+
var pos = jsPlumbInstance.getPosition(el);
|
|
122
|
+
view.m.getNode(id).setPosition(pos);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
if( data.n.isInput() || data.n.isOutput() ) {
|
|
128
|
+
var type = "*";
|
|
129
|
+
var input = output = "value";
|
|
130
|
+
var offsetTop = $(div).find('.card-top').height() + 12 /* hr size */ - 3;
|
|
131
|
+
|
|
132
|
+
var uuid = [ id, "input", input].join('#');
|
|
133
|
+
var ep = jsPlumbInstance.addEndpoint(id, {
|
|
134
|
+
isSource : false,
|
|
135
|
+
isTarget : true,
|
|
136
|
+
uuid : uuid,
|
|
137
|
+
anchor : [0,0,-1,0,0,offsetTop],
|
|
138
|
+
maxConnections : 1,
|
|
139
|
+
parameters : {
|
|
140
|
+
type: "data",
|
|
141
|
+
target : {
|
|
142
|
+
id : id,
|
|
143
|
+
input : output
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}, view.style.inputEndpoint);
|
|
147
|
+
|
|
148
|
+
// add data to the endpoint div so we can identify it easier
|
|
149
|
+
$(ep.canvas).attr('data-node', id);
|
|
150
|
+
$(ep.canvas).attr('data-type', 'input');
|
|
151
|
+
$(ep.canvas).attr('data-input', input);
|
|
152
|
+
|
|
153
|
+
// bind tooltip
|
|
154
|
+
$(ep.canvas).attr('data-toggle', "tooltip");
|
|
155
|
+
$(ep.canvas).attr('data-trigger', "hover");
|
|
156
|
+
$(ep.canvas).attr('data-placement', "left");
|
|
157
|
+
$(ep.canvas).attr('data-html', "true");
|
|
158
|
+
var inputType = view.m.getNode(id).getInputType("value");
|
|
159
|
+
$(ep.canvas).attr('title', "Type: <b>" + inputType + "</b>");
|
|
160
|
+
$(ep.canvas).tooltip();
|
|
161
|
+
|
|
162
|
+
// bind context menu to the endpoint
|
|
163
|
+
$(ep.canvas).addClass('capture-right-click');
|
|
164
|
+
$(ep.canvas).ready(function() {
|
|
165
|
+
var menu = new ContextMenu(".jsplumb-endpoint-anchor[data-node='"+id.trim()+"'][data-input='" + input + "']", [
|
|
166
|
+
{
|
|
167
|
+
name: 'Create input for here',
|
|
168
|
+
fn: () => {
|
|
169
|
+
view.c.createInputFromConnection(id, input);
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
]);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
var uuid = [ id, "output", output].join('#');
|
|
176
|
+
var ep = jsPlumbInstance.addEndpoint(id, {
|
|
177
|
+
isSource : true,
|
|
178
|
+
isTarget : false,
|
|
179
|
+
uuid : uuid,
|
|
180
|
+
anchor : [1,0,1,0,0,offsetTop],
|
|
181
|
+
parameters : {
|
|
182
|
+
type: "data",
|
|
183
|
+
source : {
|
|
184
|
+
id : id,
|
|
185
|
+
output : output
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}, view.style.outputEndpoint);
|
|
189
|
+
|
|
190
|
+
// add data to the endpoint div so we can identify it easier
|
|
191
|
+
$(ep.canvas).attr('data-node', id);
|
|
192
|
+
$(ep.canvas).attr('data-type', "output");
|
|
193
|
+
$(ep.canvas).attr('data-output', output);
|
|
194
|
+
|
|
195
|
+
// bind tooltip
|
|
196
|
+
$(ep.canvas).attr('data-toggle', "tooltip");
|
|
197
|
+
$(ep.canvas).attr('data-trigger', "hover");
|
|
198
|
+
$(ep.canvas).attr('data-placement', "right");
|
|
199
|
+
$(ep.canvas).attr('data-html', "true");
|
|
200
|
+
var outputType = view.m.getNode(id).getOutputType("value");
|
|
201
|
+
$(ep.canvas).attr('title', "Type: <b>" + outputType + "</b>");
|
|
202
|
+
$(ep.canvas).tooltip();
|
|
203
|
+
|
|
204
|
+
// bind context menu to the endpoint
|
|
205
|
+
$(ep.canvas).addClass('capture-right-click');
|
|
206
|
+
$(ep.canvas).ready(function() {
|
|
207
|
+
var menu = new ContextMenu(".jsplumb-endpoint-anchor[data-node='"+id.trim()+"'][data-output='" + output.trim() + "']", [
|
|
208
|
+
{
|
|
209
|
+
name: 'Create output for here',
|
|
210
|
+
fn: () => {
|
|
211
|
+
view.c.createOutputFromConnection(id, output);
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
]);
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
// add input endoints
|
|
219
|
+
div.find('.box-inputs').find('.point').each( function(index) {
|
|
220
|
+
$(this).css('visibility', 'hidden').css('opacity', '0'); // replaced by jsPlumb point
|
|
221
|
+
|
|
222
|
+
var input = div.find('.box-inputs').find('.name').eq(index).attr('data-input').trim();
|
|
223
|
+
var type = view.m.getNode(id).getInputType(input);
|
|
224
|
+
|
|
225
|
+
var offsetTop = $(this).positionFrom('.card').top + $(this).height()/2 - 3;
|
|
226
|
+
var uuid = [ id, "input", $(this).data('key')].join('#');
|
|
227
|
+
var ep = jsPlumbInstance.addEndpoint(id, {
|
|
228
|
+
isSource : false,
|
|
229
|
+
isTarget : true,
|
|
230
|
+
uuid : uuid,
|
|
231
|
+
anchor : [0,0,-1,0,0,offsetTop],
|
|
232
|
+
maxConnections : 1,
|
|
233
|
+
parameters : {
|
|
234
|
+
type: "data",
|
|
235
|
+
target : {
|
|
236
|
+
id : id,
|
|
237
|
+
input : $(this).data('key')
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}, view.style.inputEndpoint);
|
|
241
|
+
|
|
242
|
+
// add data to the endpoint div so we can identify it easier
|
|
243
|
+
$(ep.canvas).attr('data-node', id);
|
|
244
|
+
$(ep.canvas).attr('data-type', 'input');
|
|
245
|
+
$(ep.canvas).attr('data-input', input);
|
|
246
|
+
|
|
247
|
+
// bind tooltip
|
|
248
|
+
$(ep.canvas).attr('data-toggle', "tooltip");
|
|
249
|
+
$(ep.canvas).attr('data-trigger', "hover");
|
|
250
|
+
$(ep.canvas).attr('data-placement', "left");
|
|
251
|
+
$(ep.canvas).attr('data-html', "true");
|
|
252
|
+
$(ep.canvas).attr('title', "Type: <b>" + type + "</b>");
|
|
253
|
+
$(ep.canvas).tooltip();
|
|
254
|
+
|
|
255
|
+
// bind context menu to the endpoint
|
|
256
|
+
$(ep.canvas).addClass('capture-right-click');
|
|
257
|
+
$(ep.canvas).ready(function() {
|
|
258
|
+
var menu = new ContextMenu(".jsplumb-endpoint-anchor[data-node='"+id.trim()+"'][data-input='" + input.trim() + "']", [
|
|
259
|
+
{
|
|
260
|
+
name: 'Create input for here',
|
|
261
|
+
fn: () => {
|
|
262
|
+
view.c.createInputFromConnection(id, input);
|
|
263
|
+
}
|
|
264
|
+
},
|
|
265
|
+
]);
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
// add output endpoints
|
|
270
|
+
div.find('.box-outputs').find('.point').each( function(index) {
|
|
271
|
+
$(this).css('visibility', 'hidden').css('opacity', '0'); // replaced by jsPlumb point
|
|
272
|
+
|
|
273
|
+
var output = div.find('.box-outputs').find('.name').eq(index).attr('data-output').trim();
|
|
274
|
+
var type = view.m.getNode(id).getOutputType(output);
|
|
275
|
+
|
|
276
|
+
var offsetTop = $(this).positionFrom('.card').top + $(this).height()/2 - 3;
|
|
277
|
+
var uuid = [ id, "output", $(this).data('key')].join('#');
|
|
278
|
+
var ep = jsPlumbInstance.addEndpoint(id, {
|
|
279
|
+
isSource : true,
|
|
280
|
+
isTarget : false,
|
|
281
|
+
uuid : uuid,
|
|
282
|
+
anchor : [1,0,1,0,0,offsetTop],
|
|
283
|
+
parameters : {
|
|
284
|
+
type: "data",
|
|
285
|
+
source : {
|
|
286
|
+
id : id,
|
|
287
|
+
output : $(this).data('key')
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}, view.style.outputEndpoint);
|
|
291
|
+
|
|
292
|
+
// add data to the endpoint div so we can identify it easier
|
|
293
|
+
$(ep.canvas).attr('data-node', id);
|
|
294
|
+
$(ep.canvas).attr('data-type', "output");
|
|
295
|
+
$(ep.canvas).attr('data-output', output);
|
|
296
|
+
|
|
297
|
+
// bind tooltip
|
|
298
|
+
$(ep.canvas).attr('data-toggle', "tooltip");
|
|
299
|
+
$(ep.canvas).attr('data-trigger', "hover");
|
|
300
|
+
$(ep.canvas).attr('data-placement', "right");
|
|
301
|
+
$(ep.canvas).attr('data-html', "true");
|
|
302
|
+
$(ep.canvas).attr('title', "Type: <b>" + type + "</b>");
|
|
303
|
+
$(ep.canvas).tooltip();
|
|
304
|
+
|
|
305
|
+
// bind context menu to the endpoint
|
|
306
|
+
$(ep.canvas).addClass('capture-right-click');
|
|
307
|
+
$(ep.canvas).ready(function() {
|
|
308
|
+
var menu = new ContextMenu(".jsplumb-endpoint-anchor[data-node='"+id.trim()+"'][data-output='" + output.trim() + "']", [
|
|
309
|
+
{
|
|
310
|
+
name: 'Create output for here',
|
|
311
|
+
fn: () => {
|
|
312
|
+
view.c.createOutputFromConnection(id, output);
|
|
313
|
+
}
|
|
314
|
+
},
|
|
315
|
+
]);
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
if( data.n.isUI() && view.showEvents ) {
|
|
320
|
+
// Make this a target for events
|
|
321
|
+
view.jsPlumbInstance.makeTarget(id, {
|
|
322
|
+
isSource:false,
|
|
323
|
+
isTarget:true,
|
|
324
|
+
uniqueEndpoint: false,
|
|
325
|
+
anchor:"Continuous",
|
|
326
|
+
uuid: id + "#event-in",
|
|
327
|
+
paintStyle:{ fill:"green" },
|
|
328
|
+
parameters: {
|
|
329
|
+
type: "event",
|
|
330
|
+
target: { "id" : id }
|
|
331
|
+
},
|
|
332
|
+
}, view.style.eventEndpoint);
|
|
333
|
+
|
|
334
|
+
// Create an enpoint to create a new event
|
|
335
|
+
var ep = jsPlumbInstance.addEndpoint(id, {
|
|
336
|
+
isSource : true,
|
|
337
|
+
isTarget : false,
|
|
338
|
+
uuid : id + "#event-out",
|
|
339
|
+
anchor : [1, 1, 0, 1, 0, -10],
|
|
340
|
+
parameters : {
|
|
341
|
+
type: "event",
|
|
342
|
+
source: { "id" : id }
|
|
343
|
+
},
|
|
344
|
+
}, view.style.eventEndpoint);
|
|
345
|
+
|
|
346
|
+
// Add overlay here so we don't mess with splitConnection
|
|
347
|
+
ep.addOverlay(["PlainArrow", { width:15, length:15, location:1, id:"arrow" }]);
|
|
348
|
+
|
|
349
|
+
$(ep.canvas).attr('data-toggle', "tooltip");
|
|
350
|
+
$(ep.canvas).attr('data-trigger', "hover");
|
|
351
|
+
$(ep.canvas).attr('data-placement', "bottom");
|
|
352
|
+
$(ep.canvas).attr('data-html', "true");
|
|
353
|
+
$(ep.canvas).attr('title', "Connect from here ito add an event that will be triggered when this box is done computing.");
|
|
354
|
+
$(ep.canvas).tooltip();
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// enter metanode button
|
|
359
|
+
div.find('.btn-enter-metanode').click(function(e) {
|
|
360
|
+
e.preventDefault();
|
|
361
|
+
e.stopPropagation();
|
|
362
|
+
|
|
363
|
+
var nodeId = $(this).closest('.card').attr('id');
|
|
364
|
+
view.c.enterMetanode(nodeId);
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
// settings button
|
|
368
|
+
div.find('.btn-settings').click(function(e) {
|
|
369
|
+
e.preventDefault();
|
|
370
|
+
e.stopPropagation();
|
|
371
|
+
view.openBoxSettings(div.attr('id'));
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
// snapshot details button
|
|
375
|
+
div.find('.btn-snapshot-details').click(function(e) {
|
|
376
|
+
e.preventDefault();
|
|
377
|
+
e.stopPropagation();
|
|
378
|
+
view.openDebug(div.attr('id'));
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
div.click(function(e) {
|
|
382
|
+
if( e.ctrlKey ) {
|
|
383
|
+
view.selector.toggleSelection(this);
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
// enable tooltips
|
|
388
|
+
div.find('[data-toggle="popover"]').popover();
|
|
389
|
+
|
|
390
|
+
// Create a contextmenu for the div
|
|
391
|
+
var contextOptions = [
|
|
392
|
+
{
|
|
393
|
+
name: 'Remove this box',
|
|
394
|
+
fn: () => {
|
|
395
|
+
view.c.removeBox(id);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
];
|
|
399
|
+
if( data.n.isModule() || data.n.isUI() ) {
|
|
400
|
+
contextOptions.push({
|
|
401
|
+
name: 'Duplicate this box',
|
|
402
|
+
fn: () => {
|
|
403
|
+
view.c.duplicateBox(id);
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
var nodeMenu = new ContextMenu("#" + id, contextOptions);
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
module.exports = TemplateBinds;
|