├── .gitignore ├── README.md ├── app.js ├── css ├── app.css ├── jsplumbtoolkit-defaults.css ├── jsplumbtoolkit-demo.css └── main.css ├── data └── data.json ├── index.html ├── js ├── angular.js ├── jquery.min.js ├── jsplumbtoolkit-angular-1.x.js ├── jsplumbtoolkit.js ├── jsplumbtoolkit_hacked.js └── syntax-highlighter.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vscode 3 | .idea -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 此demo来源于官网中 [AngularJS1.x 版流程图](https://jsplumbtoolkit.com/demos/toolkit/angular-1.x/index.html), [jsPlumb](https://jsplumbtoolkit.com/) 提供了社区版(免费)和 toolkit 版(收费). 2 | 3 | ## Install 4 | ```shell 5 | git clone https://github.com/gosongs/test_js_plumb.git 6 | cd test_js_plumb 7 | npm install 8 | ``` 9 | 10 | ## 注意: 11 | + 示例代码中需要引用 `data.json` 中的数据, 不要直接打开 `index.html`, 可以通过 `http-server` 启动一个 http 服务; 12 | ```shell 13 | sudo npm install -g http-server 14 | cd test_js_plumb 15 | http-server 16 | # open browser: http://127.0.0.1:8080 17 | ``` 18 | + jsPlumb 本身不依赖于jquery、bootstrap、font-awesome, 只作为演示需要; 19 | + 此项目使用到的 jsPlumb 库强行移除了版权检测的代码, 挺有意思的加密方法, 并写了一篇文章分析一下: [破解 jsPlumb toolkit版](https://gosongs.github.io/2017/06/20/hack-js-plumb/); 20 | + **[鼓励大家使用正版, 尊重知识产权](https://jsplumbtoolkit.com/purchase)**; 21 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | var app = angular.module('app', ['$jsPlumb']); 2 | 3 | app.directive('start', function (jsPlumbFactory) { 4 | return jsPlumbFactory.node({ 5 | templateUrl: "start_template.tpl", 6 | link: function (scope, element) { 7 | element.addClass("flowchart-object flowchart-start"); 8 | } 9 | }); 10 | }); 11 | 12 | app.directive('question', function (jsPlumbFactory) { 13 | return jsPlumbFactory.node({ 14 | inherit: ["removeNode", "editNode"], 15 | templateUrl: "question_template.tpl", 16 | link: function (scope, element) { 17 | element.addClass("flowchart-object flowchart-question"); 18 | } 19 | }); 20 | }); 21 | 22 | app.directive('action', function (jsPlumbFactory) { 23 | return jsPlumbFactory.node({ 24 | inherit: ["removeNode", "editNode"], 25 | templateUrl: "action_template.tpl", 26 | link: function (scope, element) { 27 | element.addClass("flowchart-object flowchart-action"); 28 | } 29 | }); 30 | }); 31 | 32 | app.directive('output', function (jsPlumbFactory) { 33 | return jsPlumbFactory.node({ 34 | inherit: ["removeNode", "editNode"], 35 | templateUrl: "output_template.tpl", 36 | link: function (scope, element) { 37 | element.addClass("flowchart-object flowchart-output"); 38 | } 39 | }); 40 | }); 41 | 42 | 43 | app.controller("DemoController", function ($log, $scope, jsPlumbService) { 44 | var ctrl = this; 45 | 46 | // toolkit id 47 | var toolkitId = "flowchartToolkit"; 48 | var toolkit; 49 | 50 | window.jsps = jsPlumbService; 51 | window.ctrl = this; 52 | 53 | // ---------------------------- operations on nodes, edges --------------------------------------------------------- 54 | 55 | var _editLabel = function (edge) { 56 | jsPlumbToolkit.Dialogs.show({ 57 | id: "dlgText", 58 | data: { 59 | text: edge.data.label || "" 60 | }, 61 | onOK: function (data) { 62 | toolkit.updateEdge(edge, { label: data.text }); 63 | } 64 | }); 65 | }; 66 | 67 | // ---------------------------- / operations on nodes, edges --------------------------------------------------------- 68 | 69 | // 70 | // scope contains 71 | // jtk - the toolkit 72 | // surface - the surface 73 | // 74 | // element is the DOM element into which the toolkit was rendered 75 | // 76 | this.init = function (scope, element, attrs) { 77 | 78 | toolkit = scope.toolkit; 79 | 80 | toolkit.load({ 81 | url: "data/data.json" 82 | }); 83 | 84 | // -------------- configure buttons -------------------------------- 85 | 86 | var controls = element[0].querySelector(".controls"); 87 | 88 | // pan mode/select mode 89 | jsPlumb.on(controls, "tap", "[mode]", function () { 90 | scope.surface.setMode(this.getAttribute("mode")); 91 | }); 92 | 93 | // on home button click, zoom content to fit. 94 | jsPlumb.on(controls, "tap", "[reset]", function () { 95 | scope.toolkit.clearSelection(); 96 | scope.surface.zoomToFit(); 97 | }); 98 | 99 | // configure Drawing tools. This is an optional include. 100 | new jsPlumbToolkit.DrawingTools({ 101 | renderer: scope.surface 102 | }); 103 | 104 | // initialize dialogs 105 | jsPlumbToolkit.Dialogs.initialize({ 106 | selector: ".dlg" 107 | }); 108 | 109 | // 110 | // any operation that caused a data update (and would have caused an autosave), fires a dataUpdated event. 111 | // 112 | new jsPlumbSyntaxHighlighter(toolkit, ".jtk-demo-dataset"); 113 | }; 114 | 115 | // ----------------------------- data for the app ---------------------------------------------------------- 116 | 117 | $scope.nodeTypes = [ 118 | { label: "Question", type: "question" }, 119 | { label: "Action", type: "action" }, 120 | { label: "Output", type: "output" } 121 | ]; 122 | 123 | $scope.removeNode = function (node) { 124 | var info = this.surface.getObjectInfo(node); 125 | jsPlumbToolkit.Dialogs.show({ 126 | id: "dlgConfirm", 127 | data: { 128 | msg: "Delete '" + info.obj.data.text + "'" 129 | }, 130 | onOK: function () { 131 | toolkit.removeNode(info.obj); 132 | } 133 | }); 134 | }; 135 | 136 | $scope.editNode = function (node) { 137 | // getObjectInfo is a method that takes some DOM element (this function's `this` is 138 | // set to the element that fired the event) and returns the toolkit data object that 139 | // relates to the element. it ascends through parent nodes until it finds a node that is 140 | // registered with the toolkit. 141 | var info = this.surface.getObjectInfo(node); 142 | jsPlumbToolkit.Dialogs.show({ 143 | id: "dlgText", 144 | data: info.obj.data, 145 | title: "Edit " + info.obj.type + " name", 146 | onOK: function (data) { 147 | if (data.text && data.text.length > 2) { 148 | // if name is at least 2 chars long, update the underlying data and 149 | // update the UI. 150 | toolkit.updateNode(info.obj, data); 151 | } 152 | } 153 | }); 154 | }; 155 | 156 | // -------------------------------- render parameters --------------------------------------------------- 157 | 158 | this.typeExtractor = function (el) { 159 | return el.getAttribute("jtk-node-type"); 160 | }; 161 | 162 | /** 163 | * This is wired into the jsplumb-palette, and called whenever a new node is dropped onto the surface. 164 | * @param node 165 | */ 166 | this.onDrop = function (node) { 167 | console.log("A node was dropped: " + node.id); 168 | }; 169 | 170 | var nodeDimensions = { 171 | question: { w: 120, h: 120 }, 172 | action: { w: 120, h: 70 }, 173 | start: { w: 50, h: 50 }, 174 | output: { w: 120, h: 70 } 175 | }; 176 | 177 | this.toolkitParams = { 178 | nodeFactory: function (type, data, callback) { 179 | jsPlumbToolkit.Dialogs.show({ 180 | id: "dlgText", 181 | title: "Enter " + type + " name:", 182 | onOK: function (d) { 183 | data.text = d.text; 184 | // if the user entered a name... 185 | if (data.text) { 186 | // and it was at least 2 chars 187 | if (data.text.length >= 2) { 188 | // set width and height. 189 | jsPlumb.extend(data, nodeDimensions[type]); 190 | // set an id and continue. 191 | data.id = jsPlumbToolkitUtil.uuid(); 192 | callback(data); 193 | } 194 | else 195 | // else advise the user. 196 | alert(type + " names must be at least 2 characters!"); 197 | } 198 | // else...do not proceed. 199 | } 200 | }); 201 | }, 202 | beforeStartConnect: function (node, edgeType) { 203 | return { label: "..." }; 204 | } 205 | }; 206 | 207 | this.renderParams = { 208 | view: { 209 | nodes: { 210 | "start": { template: "start" }, 211 | "selectable": { 212 | events: { 213 | tap: function (params) { 214 | toolkit.toggleSelection(params.node); 215 | } 216 | } 217 | }, 218 | "question": { 219 | parent: "selectable", 220 | template: "question" 221 | }, 222 | "action": { 223 | parent: "selectable", 224 | template: "action" 225 | }, 226 | "output": { 227 | parent: "selectable", 228 | template: "output" 229 | } 230 | }, 231 | // There are two edge types defined - 'yes' and 'no', sharing a common 232 | // parent. 233 | edges: { 234 | "default": { 235 | anchor: "AutoDefault", 236 | endpoint: "Blank", 237 | connector: ["Flowchart", { cornerRadius: 5 }], 238 | paintStyle: { strokeWidth: 2, stroke: "#f76258", outlineWidth: 3, outlineStroke: "transparent" }, // paint style for this edge type. 239 | hoverPaintStyle: { strokeWidth: 2, stroke: "rgb(67,67,67)" }, // hover paint style for this edge type. 240 | events: { 241 | "dblclick": function (params) { 242 | jsPlumbToolkit.Dialogs.show({ 243 | id: "dlgConfirm", 244 | data: { 245 | msg: "Delete Edge" 246 | }, 247 | onOK: function () { 248 | toolkit.removeEdge(params.edge); 249 | } 250 | }); 251 | } 252 | }, 253 | overlays: [ 254 | ["Arrow", { location: 1, width: 10, length: 10 }], 255 | ["Arrow", { location: 0.3, width: 10, length: 10 }] 256 | ] 257 | }, 258 | "connection": { 259 | parent: "default", 260 | overlays: [ 261 | [ 262 | "Label", { 263 | label: "${label}", 264 | events: { 265 | click: function (params) { 266 | _editLabel(params.edge); 267 | } 268 | } 269 | } 270 | ] 271 | ] 272 | } 273 | }, 274 | 275 | ports: { 276 | "start": { 277 | endpoint: "Blank", 278 | anchor: "Continuous", 279 | uniqueEndpoint: true, 280 | edgeType: "default" 281 | }, 282 | "source": { 283 | endpoint: "Blank", 284 | paintStyle: { fill: "#84acb3" }, 285 | anchor: "AutoDefault", 286 | maxConnections: -1, 287 | edgeType: "connection" 288 | }, 289 | "target": { 290 | maxConnections: -1, 291 | endpoint: "Blank", 292 | anchor: "AutoDefault", 293 | paintStyle: { fill: "#84acb3" }, 294 | isTarget: true 295 | } 296 | } 297 | }, 298 | // Layout the nodes using an absolute layout 299 | layout: { 300 | type: "Absolute" 301 | }, 302 | events: { 303 | canvasClick: function (e) { 304 | toolkit.clearSelection(); 305 | }, 306 | edgeAdded: function (params) { 307 | if (params.addedByMouse) { 308 | _editLabel(params.edge); 309 | } 310 | }, 311 | // listener for mode change on renderer. 312 | modeChanged: function (mode) { 313 | var controls = document.querySelector(".controls"); 314 | jsPlumb.removeClass(controls.querySelectorAll("[mode]"), "selected-mode"); 315 | jsPlumb.addClass(controls.querySelectorAll("[mode='" + mode + "']"), "selected-mode"); 316 | }, 317 | click: function (e) { 318 | alert(e) 319 | } 320 | }, 321 | consumeRightClick: false, 322 | dragOptions: { 323 | filter: ".jtk-draw-handle, .node-action, .node-action i" 324 | } 325 | }; 326 | }); -------------------------------------------------------------------------------- /css/app.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* ------------------------ dialogs ----------------------------*/ 4 | 5 | /* ----------------------- drag/drop interactions -------------- */ 6 | .drop-hover { 7 | background-color: #FCCCCC !important; 8 | } 9 | 10 | /* ----------------------- node styles ------------------------- */ 11 | 12 | .flowchart-object { 13 | position: absolute; 14 | text-align: center; 15 | font-size: 12px; 16 | opacity: 0.8; 17 | z-index: 10; 18 | background: none; 19 | box-shadow: none; 20 | border: none; 21 | border-radius: 0; 22 | min-width: 0; 23 | min-height: 0; 24 | } 25 | 26 | .flowchart-object svg { 27 | position: absolute; 28 | stroke: none; 29 | fill: #f00; 30 | left: 0px; 31 | top: 0px; 32 | } 33 | 34 | .flowchart-object text { 35 | stroke: none; 36 | fill: #f7ebca; 37 | font-family: "Open Sans", sans-serif; 38 | font-size: 14px; 39 | font-weight: normal; 40 | 41 | } 42 | 43 | .flowchart-object .node-action { 44 | display: none; 45 | position: absolute; 46 | top: 24px; 47 | cursor: pointer; 48 | color: white; 49 | z-index: 10000; 50 | } 51 | 52 | .flowchart-object .node-action:hover { 53 | color: #ff8000; 54 | } 55 | 56 | .flowchart-object .node-edit { 57 | left: 50%; 58 | margin-left: -20px; 59 | } 60 | 61 | .flowchart-object .node-delete { 62 | left: 50%; 63 | margin-left: 10px; 64 | } 65 | 66 | .flowchart-object.jtk-surface-selected-element .node-action { 67 | display: block; 68 | } 69 | 70 | .outer { 71 | fill:gray; 72 | opacity:0.3; 73 | } 74 | 75 | .flowchart-object:hover .outer { 76 | opacity:0.7; 77 | } 78 | 79 | .inner { 80 | cursor:move !important; 81 | } -------------------------------------------------------------------------------- /css/jsplumbtoolkit-defaults.css: -------------------------------------------------------------------------------- 1 | /* 2 | Default styles for jsPlumb Toolkit 3 | 4 | Copyright 2017 https://jsplumbtoolkit.com 5 | */ 6 | 7 | /* --------------------------------------------------------------------------------------------- */ 8 | /* --- SURFACE WIDGET -------------------------------------------------------------------------- */ 9 | /* --------------------------------------------------------------------------------------------- */ 10 | 11 | /* 12 | Assigned to every Node managed by an instance of the Toolkit. They are required to be positioned absolute, to 13 | enable dragging to work properly. 14 | */ 15 | .jtk-node { 16 | position: absolute; 17 | } 18 | 19 | /* 20 | Assigned to every Group managed by an instance of the Toolkit. They are required to be positioned absolute, to 21 | enable dragging to work properly. We set overflow:visible on Group elements too, as a drag outside of the bounds 22 | is automatically reverted anyway, and without overflow:visible you cannot drag a node to some other element. You can 23 | also drag a node out of the element's viewport and if you drop it you can never get it back. 24 | */ 25 | .jtk-group { 26 | position: absolute; 27 | overflow: visible; 28 | } 29 | 30 | /* 31 | 32 | This is the attribute used to mark which part of a Group DOM element should contain the child Nodes. We mark it 33 | as having `position:relative` so that the absolute positioned Nodes are drawn correctly. 34 | */ 35 | [jtk-group-content] { 36 | position:relative; 37 | } 38 | 39 | /* 40 | This style was created in response to this Chrome bug: 41 | http://stackoverflow.com/questions/13758215/artifacts-when-css-scaled-in-chrome 42 | 43 | Basically it's about how sometimes there can be artefacts left on screen when the user drags an element. It seems 44 | the issue has been fixed in more recent versions of Chrome, but the style is left here in case you come across 45 | the problem. 46 | */ 47 | .jtk-node.jtk-drag { 48 | /*-webkit-backface-visibility: hidden;*/ 49 | } 50 | 51 | /* 52 | Assigned to an element that is the `Container` in a `render` call. 53 | Elements that are acting as Surface widgets should have overflow:hidden set to prevent libs from 54 | scrolling them during drag (we don't want scrollbars; we have an infinite canvas). Position is set to 55 | `relative` as this is the parent for nodes, which are positioned absolute (and for absolute positioning 56 | to work, you need to ensure the parent node has `position:relative`). This style also sets some default 57 | values for the cursor - using a `grab` cursor where supported. 58 | */ 59 | .jtk-surface { 60 | overflow: hidden !important; 61 | position: relative; 62 | cursor: move; 63 | cursor: -moz-grab; 64 | cursor: -webkit-grab; 65 | 66 | /* 67 | For IE10+. As discussed on this page: 68 | 69 | https://msdn.microsoft.com/en-us/library/ie/jj583807(v=vs.85).aspx 70 | 71 | Microsoft have very helpfully implemented default behaviours for a bunch of touch events and 72 | then consumed the events so you don't have to be bothered by them. They've "done a lot of research" 73 | about this stuff and put together a really great default experience for everyone in the entire world. 74 | */ 75 | touch-action:none; 76 | 77 | /* 78 | Another Chrome issue that appears to have been fixed in later versions 79 | http://stackoverflow.com/questions/15464055/css-transition-effect-makes-image-blurry-moves-image-1px-in-chrome 80 | */ 81 | /* 82 | -webkit-backface-visibility: hidden; 83 | -webkit-transform: translateZ(0) scale(1.0, 1.0); 84 | */ 85 | } 86 | 87 | /* 88 | Assigned to the surface when it is being panned. The default is to change the cursor (in browsers that support 89 | a `grabbing` cursor), and to disable text selection. 90 | */ 91 | .jtk-surface-panning { 92 | cursor: -moz-grabbing; 93 | cursor: -webkit-grabbing; 94 | -webkit-touch-callout: none; 95 | -webkit-user-select: none; 96 | -khtml-user-select: none; 97 | -moz-user-select: none; 98 | -ms-user-select: none; 99 | user-select: none; 100 | } 101 | 102 | /* 103 | The work area in a surface renderer. 104 | */ 105 | .jtk-surface-canvas { 106 | overflow: visible !important; 107 | } 108 | 109 | /* 110 | For IE10+. Discussed above in the .jtk-surface styles. This one is specific to elements that are configured 111 | to be droppable on a Surface via its `registerDroppableNodes` method. 112 | */ 113 | .jtk-surface-droppable-node { 114 | touch-action:none; 115 | } 116 | 117 | /* 118 | Assigned to a Surface widget when panning is disabled (and therefore the app is relying on scrollbars when the content overflows). 119 | */ 120 | .jtk-surface-nopan { 121 | overflow: scroll !important; 122 | cursor:default; 123 | } 124 | 125 | /* 126 | Assigned to tile images in a tiled background 127 | */ 128 | .jtk-surface-tile { 129 | border:none; 130 | outline:none; 131 | margin:0; 132 | -webkit-transition: opacity .3s ease .15s; 133 | -moz-transition: opacity .3s ease .15s; 134 | -o-transition: opacity .3s ease .15s; 135 | -ms-transition: opacity .3s ease .15s; 136 | transition: opacity .3s ease .15s; 137 | } 138 | 139 | /* 140 | Assigned to the element used for node select with the mouse ("lasso"). 141 | */ 142 | .jtk-lasso { 143 | border: 2px solid rgb(49, 119, 184); 144 | background-color: WhiteSmoke; 145 | opacity: 0.5; 146 | display: none; 147 | z-index: 20000; 148 | position: absolute; 149 | } 150 | 151 | /* 152 | This class is added to the document body on lasso drag start and removed at the end of lasso dragging. Its purpose 153 | is to switch off text selection on all elements while the user is dragging the lasso. 154 | */ 155 | .jtk-lasso-select-defeat * { 156 | -webkit-touch-callout: none; 157 | -webkit-user-select: none; 158 | -khtml-user-select: none; 159 | -moz-user-select: none; 160 | -ms-user-select: none; 161 | user-select: none; 162 | } 163 | 164 | /** 165 | Added to the lasso mask when it is operating in 'inverted' mode, ie. the excluded parts of the UI are covered, rather 166 | than the normal mode in which the selected parts of the UI are covered. 167 | */ 168 | .jtk-lasso-mask { 169 | position:fixed; 170 | z-index:20000; 171 | display:none; 172 | opacity:0.5; 173 | background-color: #07234E; 174 | top:0; 175 | bottom:0; 176 | left:0; 177 | right:0; 178 | } 179 | 180 | /* 181 | Assigned to some element that has been selected (either via lasso or programmatically). 182 | */ 183 | .jtk-surface-selected-element { 184 | border: 2px dashed #f76258 !important; 185 | } 186 | 187 | /* 188 | Assigned to all pan buttons in a surface widget. 189 | */ 190 | .jtk-surface-pan { 191 | background-color: Azure; 192 | opacity: 0.4; 193 | text-align: center; 194 | cursor: pointer; 195 | z-index: 2; 196 | -webkit-transition: background-color 0.15s ease-in; 197 | -moz-transition: background-color 0.15s ease-in; 198 | -o-transition: background-color 0.15s ease-in; 199 | transition: background-color 0.15s ease-in; 200 | } 201 | 202 | /* 203 | Specific styles for the top and bottom pan buttons. 204 | Top/bottom are 100% width and 20px high by default 205 | */ 206 | .jtk-surface-pan-top, .jtk-surface-pan-bottom { 207 | width: 100%; 208 | height: 20px; 209 | } 210 | 211 | /* 212 | Hover styles for all pan buttons. 213 | On hover, change color, background color, font weight and opacity. 214 | */ 215 | .jtk-surface-pan-top:hover, .jtk-surface-pan-bottom:hover, .jtk-surface-pan-left:hover, .jtk-surface-pan-right:hover { 216 | opacity: 0.6; 217 | background-color: rgb(49, 119, 184); 218 | color: white; 219 | font-weight: bold; 220 | } 221 | 222 | /* 223 | Specific styles for the left and right pan buttons. 224 | Left/right pan buttons are 100% height and 20px wide 225 | */ 226 | .jtk-surface-pan-left, .jtk-surface-pan-right { 227 | width: 20px; 228 | height: 100%; 229 | line-height: 40; 230 | } 231 | 232 | 233 | /* 234 | Assigned to a pan button when the user is pressing it. 235 | */ 236 | .jtk-surface-pan-active, .jtk-surface-pan-active:hover { 237 | background-color: #f76258; 238 | } 239 | 240 | /* --------------------------------------------------------------------------------------------- */ 241 | /* --- MINIVIEW WIDGET ------------------------------------------------------------------------- */ 242 | /* --------------------------------------------------------------------------------------------- */ 243 | 244 | /* 245 | Assigned to an element that is acting as a Miniview. 246 | As with Surface, Miniview elements should have overflow:hidden set to prevent 247 | libs from scrolling them during drag. This style also provides a default width/height for a miniview, 248 | which you may wish to override. 249 | */ 250 | .jtk-miniview { 251 | overflow: hidden !important; 252 | width: 125px; 253 | height: 125px; 254 | position: relative; 255 | background-color: #B2C9CD; 256 | border: 1px solid #E2E6CD; 257 | border-radius: 4px; 258 | opacity: 0.8; 259 | } 260 | 261 | /* 262 | Assigned to the element that shows the size of the related viewport in a Miniview widget, and which can be dragged to 263 | move the surface. 264 | */ 265 | .jtk-miniview-panner { 266 | border: 5px dotted WhiteSmoke; 267 | opacity: 0.4; 268 | background-color: rgb(79, 111, 126); 269 | cursor: move; 270 | cursor: -moz-grab; 271 | cursor: -webkit-grab; 272 | } 273 | 274 | /* 275 | Assigned to the miniview's panner when it is being dragged. 276 | */ 277 | .jtk-miniview-panning { 278 | cursor: -moz-grabbing; 279 | cursor: -webkit-grabbing; 280 | } 281 | 282 | /* 283 | Added to all elements displayed in a miniview. 284 | */ 285 | .jtk-miniview-element { 286 | background-color: rgb(96, 122, 134); 287 | position: absolute; 288 | } 289 | 290 | /* 291 | Added to Group elements displayed in a miniview 292 | */ 293 | .jtk-miniview-group-element { 294 | background: transparent; 295 | border: 2px solid rgb(96,122,134); 296 | } 297 | 298 | /* 299 | Assigned to the collapse/expand miniview button 300 | */ 301 | .jtk-miniview-collapse { 302 | color: whiteSmoke; 303 | position: absolute; 304 | font-size: 18px; 305 | top: -1px; 306 | right: 3px; 307 | cursor: pointer; 308 | font-weight: bold; 309 | } 310 | 311 | /* 312 | The '-' symbol when the miniview is expanded 313 | */ 314 | .jtk-miniview-collapse:before { 315 | content: "\2012"; 316 | } 317 | 318 | /* 319 | Assigned to the miniview element when it is collapsed. 320 | */ 321 | .jtk-miniview-collapsed { 322 | background-color: #449ea6; 323 | border-radius: 4px; 324 | height: 22px; 325 | margin-right: 0; 326 | padding: 4px; 327 | width: 21px; 328 | } 329 | 330 | /* 331 | Hide all children of the miniview (except the expand button) when it is collapsed so you don't see anything 332 | poking through under the + icon. 333 | */ 334 | .jtk-miniview-collapsed .jtk-miniview-element, .jtk-miniview-collapsed .jtk-miniview-panner { 335 | visibility: hidden; 336 | } 337 | 338 | /* 339 | The '+' symbol when the miniview is collapsed. 340 | */ 341 | .jtk-miniview-collapsed .jtk-miniview-collapse:before { 342 | content: "+"; 343 | } 344 | 345 | /* 346 | Hover state for the collapse/expand icon. 347 | */ 348 | .jtk-miniview-collapse:hover { 349 | color: #E4F013; 350 | } 351 | 352 | /* ------------------------------------------------------------------------------------------- */ 353 | /* --- DIALOGS --------------------------------------------------------------------------------*/ 354 | /* ------------------------------------------------------------------------------------------- */ 355 | 356 | /* 357 | This is the element that acts as the dialog underlay - the modal "mask". Note the high z-index default 358 | set here (and note also the overlay style below has a z-index with a value higher by one). 359 | */ 360 | .jtk-dialog-underlay { 361 | left: 0; 362 | right: 0; 363 | top: 0; 364 | bottom: 0; 365 | position: fixed; 366 | z-index: 100000; 367 | opacity: 0.8; 368 | background-color: #CCC; 369 | display: none; 370 | } 371 | 372 | /* 373 | This is the element that acts as the parent for dialog content. 374 | */ 375 | .jtk-dialog-overlay { 376 | position: fixed; 377 | z-index: 100001; 378 | display: none; 379 | background-color: white; 380 | font-family: "Open Sans", sans-serif; 381 | padding: 7px; 382 | box-shadow: 0 0 5px gray; 383 | overflow: hidden; 384 | } 385 | 386 | .jtk-dialog-overlay-x { 387 | max-height:0; 388 | transition: max-height 0.5s ease-in; 389 | -moz-transition: max-height 0.5s ease-in; 390 | -ms-transition: max-height 0.5s ease-in; 391 | -o-transition: max-height 0.5s ease-in; 392 | -webkit-transition: max-height 0.5s ease-in; 393 | } 394 | 395 | .jtk-dialog-overlay-y { 396 | max-width:0; 397 | transition: max-width 0.5s ease-in; 398 | -moz-transition: max-width 0.5s ease-in; 399 | -ms-transition: max-width 0.5s ease-in; 400 | -o-transition: max-width 0.5s ease-in; 401 | -webkit-transition: max-width 0.5s ease-in; 402 | } 403 | 404 | .jtk-dialog-overlay-top { 405 | top:20px; 406 | } 407 | 408 | .jtk-dialog-overlay-bottom { 409 | bottom:20px; 410 | } 411 | 412 | .jtk-dialog-overlay-left { 413 | left:20px; 414 | } 415 | 416 | .jtk-dialog-overlay-right { 417 | right:20px; 418 | } 419 | 420 | .jtk-dialog-overlay-x.jtk-dialog-overlay-visible { 421 | max-height:1000px; 422 | } 423 | 424 | .jtk-dialog-overlay-y.jtk-dialog-overlay-visible { 425 | max-width:1000px; 426 | } 427 | 428 | /* 429 | The element containing buttons in a dialog. 430 | */ 431 | .jtk-dialog-buttons { 432 | text-align: right; 433 | margin-top: 5px; 434 | } 435 | 436 | /* 437 | An individual button in a dialog. 438 | */ 439 | .jtk-dialog-button { 440 | border: none; 441 | cursor: pointer; 442 | margin-right: 5px; 443 | min-width: 56px; 444 | background-color: white; 445 | outline: 1px solid #ccc; 446 | } 447 | 448 | /* 449 | Hover style for an individual button in a dialog. 450 | */ 451 | .jtk-dialog-button:hover { 452 | color: white; 453 | background-color: #234b5e; 454 | } 455 | 456 | /* 457 | The titlebar of a dialog. 458 | */ 459 | .jtk-dialog-title { 460 | text-align: left; 461 | font-size: 14px; 462 | margin-bottom: 9px; 463 | } 464 | 465 | .jtk-dialog-content { 466 | font-size:12px; 467 | text-align:left; 468 | min-width:250px; 469 | margin: 0 14px; 470 | } 471 | 472 | .jtk-dialog-content ul { 473 | width:100%; 474 | padding-left:0; 475 | } 476 | 477 | .jtk-dialog-content label { 478 | cursor: pointer; 479 | font-weight: inherit; 480 | } 481 | 482 | .jtk-dialog-overlay input, .jtk-dialog-overlay textarea { 483 | background-color: #FFF; 484 | border: 1px solid #CCC; 485 | color: #333; 486 | font-size: 14px; 487 | font-style: normal; 488 | outline: none; 489 | padding: 6px 4px; 490 | margin-right: 6px; 491 | } 492 | 493 | .jtk-dialog-overlay input:focus, .jtk-dialog-overlay textarea:focus { 494 | background-color: #cbeae1; 495 | border: 1px solid #83b8a8; 496 | color: #333; 497 | font-size: 14px; 498 | font-style: normal; 499 | outline: none; 500 | } 501 | 502 | /* -------------------------------------------------------------------------------------------- */ 503 | /* --- DRAWING TOOLS -------------------------------------------------------------------------- */ 504 | /* -------------------------------------------------------------------------------------------- */ 505 | 506 | /* 507 | Assigned to the element that is drawn around some other element when a drawing operation is taking place. 508 | */ 509 | .jtk-draw-skeleton { 510 | position: absolute; 511 | left: 0; 512 | right: 0; 513 | top: 0; 514 | bottom: 0; 515 | outline: 2px solid #84acb3; 516 | opacity: 0.8; 517 | } 518 | 519 | /* 520 | Assigned to every handle (top left, top right, bottom left, bottom right, center) in a draw skeleton. 521 | */ 522 | .jtk-draw-handle { 523 | position: absolute; 524 | width: 7px; 525 | height: 7px; 526 | background-color: #84acb3; 527 | } 528 | 529 | /* 530 | Assigned to the top left handle in a draw skeleton 531 | */ 532 | .jtk-draw-handle-tl { 533 | left: 0; 534 | top: 0; 535 | cursor: nw-resize; 536 | } 537 | 538 | /* 539 | Assigned to the top right handle in a draw skeleton 540 | */ 541 | .jtk-draw-handle-tr { 542 | right: 0; 543 | top: 0; 544 | cursor: ne-resize; 545 | } 546 | 547 | /* 548 | Assigned to the bottom left handle in a draw skeleton 549 | */ 550 | .jtk-draw-handle-bl { 551 | left: 0; 552 | bottom: 0; 553 | cursor: sw-resize; 554 | } 555 | 556 | /* 557 | Assigned to the bottom right handle in a draw skeleton 558 | */ 559 | .jtk-draw-handle-br { 560 | bottom: 0; 561 | right: 0; 562 | cursor: se-resize; 563 | } 564 | 565 | /* 566 | Assigned to the center handle in a draw skeleton (the handle by which the element may be dragged). This is 567 | not visible by defaut; enable if you need it. 568 | */ 569 | .jtk-draw-drag { 570 | display:none; 571 | position: absolute; 572 | left: 50%; 573 | top: 50%; 574 | margin-left: -10px; 575 | margin-top: -10px; 576 | width: 20px; 577 | height: 20px; 578 | background-color: #84acb3; 579 | cursor: move; 580 | } 581 | 582 | /* 583 | This class is added to the document body on drag resize start and removed at the end of resizing. Its purpose 584 | is to switch off text selection on all elements while the user is resizing an element. 585 | */ 586 | .jtk-drag-select-defeat * { 587 | -webkit-touch-callout: none; 588 | -webkit-user-select: none; 589 | -khtml-user-select: none; 590 | -moz-user-select: none; 591 | -ms-user-select: none; 592 | user-select: none; 593 | } 594 | 595 | .jtk-bezier-handle { 596 | width:15px; 597 | height:15px; 598 | border-radius:50%; 599 | background-color:darkcyan; 600 | cursor:move; 601 | z-index:10; 602 | } 603 | 604 | .jtk-bezier-handle-secondary { 605 | cursor:default; 606 | background-color:lightgreen; 607 | } 608 | 609 | .jtk-bezier-handle-secondary-source { 610 | background-color: lavenderblush; 611 | } 612 | 613 | .jtk-bezier-guideline { 614 | position:absolute; 615 | } 616 | 617 | .jtk-bezier-guideline path { 618 | stroke:darkcyan; 619 | stroke-linewidth:3; 620 | } 621 | 622 | .jtk-connection-edit path { 623 | stroke-dasharray:2 2; 624 | } 625 | -------------------------------------------------------------------------------- /css/jsplumbtoolkit-demo.css: -------------------------------------------------------------------------------- 1 | /* ---------------------------------------------------------------------------------------------------- */ 2 | /* --- page structure --------------------------------------------------------------------------------- */ 3 | /* ---------------------------------------------------------------------------------------------------- */ 4 | 5 | body { 6 | background-color: #FFF; 7 | color: #434343; 8 | font-family: "Lato", sans-serif; 9 | font-size: 14px; 10 | font-weight: 400; 11 | height: 100%; 12 | padding: 0; 13 | } 14 | 15 | .jtk-bootstrap { 16 | min-height:100vh; 17 | display:flex; 18 | flex-direction: column; 19 | } 20 | 21 | .jtk-bootstrap .jtk-page-container { 22 | display:flex; 23 | width:100vw; 24 | justify-content: center; 25 | flex:1; 26 | } 27 | 28 | .jtk-bootstrap .jtk-container { 29 | width: 60%; 30 | max-width:800px; 31 | } 32 | 33 | .jtk-bootstrap-wide .jtk-container { 34 | width: 100%; 35 | max-width:1187px; 36 | padding: 10px; 37 | } 38 | 39 | .jtk-demo-main { 40 | position: relative; 41 | } 42 | 43 | .jtk-demo-main .description { 44 | font-size: 13px; 45 | margin-top: 25px; 46 | padding: 13px; 47 | margin-bottom: 22px; 48 | background-color: #f4f5ef; 49 | } 50 | 51 | .jtk-demo-main .description li { 52 | list-style-type: disc !important; 53 | } 54 | 55 | .jtk-demo-canvas { 56 | height:550px; 57 | max-height:700px; 58 | border:1px solid #CCC; 59 | background-color:white; 60 | display: flex; 61 | } 62 | 63 | .canvas-wide { 64 | margin-left:0; 65 | } 66 | 67 | .miniview { 68 | position: absolute; 69 | top: 25px; 70 | right: 25px; 71 | z-index: 100; 72 | } 73 | 74 | 75 | .jtk-demo-dataset { 76 | text-align: left; 77 | max-height: 600px; 78 | overflow: auto; 79 | } 80 | 81 | .demo-title { 82 | float:left; 83 | font-size:18px; 84 | } 85 | 86 | .controls { 87 | top: 25px; 88 | color: #FFF; 89 | margin-right: 10px; 90 | position: absolute; 91 | left: 25px; 92 | z-index: 1; 93 | } 94 | 95 | .controls i { 96 | background-color: #3E7E9C; 97 | border-radius: 4px; 98 | cursor: pointer; 99 | margin-right: 0; 100 | padding: 4px; 101 | } 102 | 103 | li { 104 | list-style-type: none; 105 | } 106 | 107 | /* ------------------------ node palette -------------------- */ 108 | 109 | .sidebar { 110 | margin:0; 111 | padding:0; 112 | padding-top: 7px; 113 | padding-right: 10px; 114 | width:150px; 115 | float:left; 116 | text-align:center; 117 | height: 550px; 118 | background-color: #84acb3; 119 | } 120 | 121 | .sidebar ul li { 122 | background-color: #234b5e; 123 | border-radius: 11px; 124 | color: #f7ebca; 125 | cursor: move; 126 | margin-bottom: 10px; 127 | margin-left: 6px; 128 | padding: 8px; 129 | width:128px; 130 | } 131 | 132 | .sidebar ul { 133 | width:100%; 134 | padding:0; 135 | } 136 | 137 | .sidebar ul li:hover { 138 | background-color: #577a8b; 139 | } 140 | 141 | .sidebar i { 142 | float:left; 143 | } 144 | 145 | @media (max-width: 600px) { 146 | .sidebar { 147 | float:none; 148 | height: 55px; 149 | width: 100%; 150 | padding-top:0; 151 | } 152 | 153 | .sidebar ul li { 154 | display:inline-block; 155 | margin-top: 7px; 156 | width:67px; 157 | } 158 | .jtk-demo-canvas { 159 | margin-left: 0; 160 | margin-top:10px; 161 | height:364px; 162 | } 163 | } 164 | 165 | /* ---------------------------------------------------------------------------------------------------- */ 166 | /* --- jsPlumb setup ---------------------------------------------------------------------------------- */ 167 | /* ---------------------------------------------------------------------------------------------------- */ 168 | 169 | .jtk-connector { 170 | z-index:9; 171 | } 172 | 173 | .jtk-endpoint { 174 | z-index:12; 175 | opacity:0.8; 176 | cursor:pointer; 177 | } 178 | 179 | .jtk-overlay { 180 | background-color: white; 181 | color: #434343; 182 | font-weight: 400; 183 | padding: 4px; 184 | z-index:10; 185 | 186 | } 187 | 188 | .jtk-overlay.jtk-hover { 189 | color: #434343; 190 | } 191 | 192 | path { 193 | cursor:pointer; 194 | } 195 | 196 | .delete { 197 | padding: 2px; 198 | cursor: pointer; 199 | float: left; 200 | font-size: 10px; 201 | line-height: 20px; 202 | } 203 | 204 | .add, .edit { 205 | cursor: pointer; 206 | float:right; 207 | font-size: 10px; 208 | line-height: 20px; 209 | margin-right:2px; 210 | padding: 2px; 211 | } 212 | 213 | .edit:hover { 214 | color: #ff8000; 215 | } 216 | 217 | .selected-mode { 218 | color:#E4F013; 219 | } 220 | 221 | .connect { 222 | width:10px; 223 | height:10px; 224 | background-color:#f76258; 225 | position:absolute; 226 | bottom: 13px; 227 | right: 5px; 228 | } 229 | 230 | /* header styles */ 231 | 232 | .demo-links { 233 | position: fixed; 234 | right: 0; 235 | top: 57px; 236 | font-size: 11px; 237 | background-color: white; 238 | opacity: 0.8; 239 | padding-right: 10px; 240 | padding-left: 5px; 241 | text-transform: uppercase; 242 | z-index:100001; 243 | } 244 | 245 | .demo-links div { 246 | display:inline; 247 | margin-right:7px; 248 | margin-left:7px; 249 | } 250 | 251 | .demo-links i { 252 | padding:4px; 253 | } 254 | 255 | /* 256 | .navbar-top { 257 | background-color: #3c565d; 258 | border:none; 259 | font-size: 14px; 260 | font-weight: 700; 261 | } 262 | 263 | .navbar-nav > li > a { 264 | border: none; 265 | color: #FFF; 266 | padding: 6px 10px; 267 | text-decoration: none; 268 | } 269 | 270 | .social-nav { 271 | color: #FFF; 272 | float: right; 273 | font-size: 22px; 274 | } 275 | 276 | .nav > li > a:hover, .nav > li > a:focus { 277 | background-color: transparent; 278 | color: #cdcc73; 279 | text-decoration: none; 280 | } 281 | */ 282 | 283 | 284 | 285 | -------------------------------------------------------------------------------- /css/main.css: -------------------------------------------------------------------------------- 1 | @font-face{font-family:'ico-jsplumb';src:url("/fonts/ico-jsplumb.eot?-oqkwhs");src:url("/fonts/ico-jsplumb.eot?#iefix-oqkwhs") format("embedded-opentype"),url("/fonts/ico-jsplumb.woff?-oqkwhs") format("woff"),url("/fonts/ico-jsplumb.ttf?-oqkwhs") format("truetype"),url("/fonts/ico-jsplumb.svg?-oqkwhs#ico-jsplumb") format("svg");font-weight:normal;font-style:normal}[class^="icon-"],[class*=" icon-"]{font-family:'ico-jsplumb';speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1}.icon-license:before{content:"\e604"}.icon-source:before{content:"\e605"}.icon-support:before{content:"\e606"}.icon-facebook:before{content:"\e600"}.icon-twitter:before{content:"\e601"}.icon-github:before{content:"\e602"}.icon-linkedin:before{content:"\e603"}.icon-cross:before{content:"\ea0f"}.icon-checkmark:before{content:"\ea10"}*,*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility}html{padding:0;margin:0}body{background-color:#FFF;color:#434343;font-family:"Lato",sans-serif;font-size:14px;font-weight:400;height:100%;padding:0}@media only screen and (max-width: 320px){body{margin-top:51px}}.clear-padding{padding:0}.full-width{width:100%}.blank-left-padding{padding:0 0 0 83px}.full-width-container{padding:40px 0;width:100%}@media only screen and (max-width: 320px){.full-width-container{padding:30px 0}}.padding-top-page{padding-top:92px}@media only screen and (max-width: 320px){.padding-top-page{padding-top:10px}}.center-block{display:table}.pos-relative{position:relative}@media only screen and (max-width: 320px){.mobile-center{text-align:center}}.bg-sepia{background-color:#f4f5ef}.color-white{color:#FFF !important}.divider-10{padding-top:10px}.divider-20{padding-top:20px}.divider-30{padding-top:30px}.divider-45{padding-top:45px}.big-title{color:#58775d;font-size:56px;font-weight:400;margin-bottom:20px}@media only screen and (max-width: 320px){.big-title{font-size:32px;margin-bottom:10px}}.high-title{color:#696b60;font-size:34px;font-weight:400;line-height:1.2em;margin-bottom:20px}@media only screen and (max-width: 320px){.high-title{font-size:32px;margin-bottom:10px}}.prod-title{color:#696b60;font-size:32px;font-weight:400;line-height:1.2em;margin-bottom:20px}@media only screen and (max-width: 320px){.prod-title{font-size:32px;margin-bottom:10px}}.title-white{color:#FFF;font-size:32px;font-weight:400;line-height:1.2em}@media only screen and (max-width: 320px){.title-white{font-size:32px;margin-bottom:10px}}.title{color:#434343;font-size:25px;font-weight:400;margin-bottom:10px}@media only screen and (max-width: 320px){.title{font-size:18px;margin-bottom:6px}}.big-lead{color:#FFF;font-size:25px;font-weight:400;margin-bottom:20px}@media only screen and (max-width: 320px){.big-lead{font-size:18px;margin-bottom:10px}}.lead{color:#434343;font-size:18px;font-weight:400;margin-bottom:0}@media only screen and (max-width: 320px){.lead{font-size:14px}}.apidoc-jsplumb-logo{display:none}.btn-big-download a{border-radius:0;color:#FFF;display:inline-block;font-size:16px;font-weight:400;margin:0;padding:10px 20px;text-decoration:none;background-color:#3c565d}.btn-big-download a:hover:not(:disabled),.btn-big-download a:active:not(:disabled),.btn-big-download a:focus:not(:disabled){color:#FFF;cursor:pointer;background-color:#1c3035}.btn-download a{border-radius:0;color:#FFF;display:inline-block;font-size:16px;font-weight:400;margin:0;padding:10px 20px;text-decoration:none;background-color:#3c565d}.btn-download a:hover:not(:disabled),.btn-download a:active:not(:disabled),.btn-download a:focus:not(:disabled){color:#FFF;cursor:pointer;background-color:#1c3035}.demo-highlight{background:url("/img/back-green.jpg") repeat-x center}.logo-jsplumb img{padding-bottom:16px;max-width:100%}@media only screen and (max-width: 320px){.logo-jsplumb img{max-width:63%}}@media only screen and (min-width: 769px) and (max-width: 1023px){.logo-jsplumb img{max-width:63%}}.browser-window{position:relative}.browser-window .browser-dropdown-menu{position:absolute;top:10px;width:100%}.browser-window table{width:100%}.browser-window td.corners{height:56px;width:53px}.browser-window td.center-top{background:url("/img/browser-window-top-center.png") repeat-x;width:100%}.browser-window td.center{background-color:#FFF}.browser-window .jsplumb-demo-container{padding:10px}.download-container{text-align:right}@media only screen and (max-width: 320px){.download-container{text-align:center}}.background-blue{background:url("/img/back-blue.jpg") repeat-x center}.background-dark-green{background:url("/img/back-dark-green.jpg") repeat}.btn-drop{color:#FFF;font-weight:700;padding:10px 20px 8px 20px;background-color:#6dadcc;cursor:pointer;width:100%}.btn-drop:hover,.btn-drop:focus,.btn-drop:active,.open .dropdown-toggle.btn-drop{color:#FFF;border:none;background-color:#3491be;text-decoration:none}.btn-dropmenu{-webkit-box-shadow:none;background-color:#6dadcc;border-radius:0;border:none;box-shadow:none;color:#FFF;margin-top:1px !important;padding:10px 0;width:100%}.btn-dropmenu>li>a{color:#FFF;border:none;padding:10px 20px}.btn-dropmenu>li>a:hover{background-color:#3c9cca;color:#FFF}.row #main{height:400px;margin-top:25px}.row .jtk-demo-dataset{display:none}.navbar-top{background-color:#3c565d;border-color:none;width:100vw}@media only screen and (max-width: 320px){.navbar-top{background-color:#3c565d}}.navbar-brand{height:56px}.nav-wrapper{margin-top:10px}.navbar-header a{border:none}.navbar-nav>li>a{border:none;color:#FFF;padding:6px 10px;text-decoration:none}.navbar-nav>li>a.active{border:none;color:#cdcc73;padding:6px 10px;text-decoration:none;cursor:default}.navbar-nav>li:last-child>a{color:#FFF;padding:6px 0 6px 10px;text-decoration:none}.navbar-nav>li:last-child>a.active{border:none;color:#cdcc73;padding:6px 10px;text-decoration:none;cursor:default}.nav{float:left}@media only screen and (max-width: 320px){.nav{float:left;margin-top:10px}}@media only screen and (min-width: 321px) and (max-width: 768px){.nav{float:left}}.nav>li>a:hover,.nav>li>a:focus{background-color:transparent;color:#cdcc73;text-decoration:none}.navbar-toggle .icon-bar{background-color:#FFF}.social-nav{color:#FFF;margin-right:25px;font-size:22px}.social-nav .link{cursor:pointer;border:none;color:#FFF;margin-left:10px;text-decoration:none}.social-nav .link:hover,.social-nav .link:focus,.social-nav .link:active{color:#cdcc73;border:none;text-decoration:none}.breadcrumbs{height:20px;top:63px;position:fixed;z-index:1030;font-size:11px;padding-left:2%;background-color:aliceblue;text-transform:uppercase;width:100%;padding-top:3px}.breadcrumbs a{color:#629f8d;text-decoration:none}.breadcrumbs a:hover,.breadcrumbs a:focus{color:#434343;text-decoration:underline}.breadcrumbs .crumbs{float:left}.breadcrumbs .demo-nav{display:inline-block;float:right;margin-right:2%}@media (max-width: 490px){.crumbs{display:none}.breadcrumbs{text-align:center}.demo-nav{float:none !important;margin-left:auto;margin-right:auto !important}}.jtk-header{background-color:#3c565d;width:100vw;display:flex;align-items:center;position:fixed;top:0;z-index:3}.jtk-header .jtk-nav{display:flex;margin-left:auto;margin-right:25px}.jtk-header .jtk-nav div{margin-right:20px}.jtk-header .jtk-nav div a{color:white;cursor:pointer}.jtk-header .jtk-nav div a:hover,.jtk-header .jtk-nav div a:focus,.jtk-header .jtk-nav div a:active{color:#cdcc73;border:none;text-decoration:none}.jtk-logo{padding:15px 15px}.jtk-footer{padding:40px 0;display:flex;justify-content:center}.jtk-footer .jtk-container{font-size:12px;display:flex;align-items:center}.jtk-footer .jtk-container a,.jtk-footer .jtk-container a:visited{cursor:pointer;color:#a0b8b7;text-decoration:none}.jtk-footer .jtk-container a:hover,.jtk-footer .jtk-container a:visited:hover{color:#cdcc73}.jtk-footer .jtk-container .jtk-copyright{color:#a0b8b7;margin-left:auto;display:flex;flex-direction:column;flex-grow:1}.jtk-footer .jtk-container .jtk-links{display:flex}.jtk-footer .jtk-container .social-nav{margin-left:50px}.jtk-footer .jtk-container .social-nav a,.jtk-footer .jtk-container .social-nav a:visited{color:#a0b8b7}.footer .copyright{font-size:12px;color:#a0b8b7}.footer .copyright a{border:none;color:#FFF;text-decoration:none}.footer .copyright a:hover{color:#cdcc73;text-decoration:none}ul.navbar-footer{padding:4px 0 0 10px}@media only screen and (max-width: 320px){ul.navbar-footer{padding:6px 0 0 0}}.navbar-footer>li{float:left;font-size:14px;list-style-type:none}.navbar-footer>li>a{border:none;color:#FFF;padding:6px 6px 0 0;text-decoration:none}.navbar-footer>li>a:hover{color:#cdcc73;text-decoration:none}.footer .social-nav{float:right;font-size:22px}@media only screen and (max-width: 320px){.footer .social-nav{float:left;margin-top:10px}}.footer .social-nav .link{border:none;color:#a0b8b7;margin-left:10px;text-decoration:none}@media only screen and (max-width: 320px){.footer .social-nav .link{margin-left:0}}.footer .social-nav .link:hover,.footer .social-nav .link:focus,.footer .social-nav .link:active{color:#cdcc73;border:none;text-decoration:none}.clear-footer{width:100%;clear:both}body.ff .clear-footer{margin-bottom:95px}body.ff .footer-wrapper{position:fixed;width:100%;bottom:0;left:0}pre.license{padding:15px;word-break:normal;word-wrap:normal;white-space:pre-wrap}.license-wrapper,.privacy{margin-top:50px;text-align:left;width:75%;margin-left:auto;margin-right:auto;padding:15px}.privacy{font-size:80px}.community-demo .demo{height:650px;position:relative;overflow:auto;background-color:white;border-radius:3px;max-width:1000px;margin-left:auto;margin-right:auto;border:1px solid #CCC;margin-top:73px;width:90%}.product-matrix-container{width:100%;font-size:15px}.product-matrix-container .high-title{font-size:28px}.product-matrix-container tr:nth-child(odd) td{background-color:#FBFBFB;border-bottom:1px solid #CFD0C9}.product-matrix-container tr:nth-child(even) td{background-color:#E9EBDD;border-bottom:1px solid #CFD0C9}.product-matrix-container td{border-left:1px solid #CFD0C9}.product-matrix-container th{border-bottom:1px solid #CFD0C9}.product-matrix-container th,.product-matrix-container td{padding:10px}.product-matrix-container a{color:#629f8d;text-decoration:none}.product-matrix-container table{width:100%;border:1px solid #CFD0C9;font-size:90%}.product-matrix-container table table{border:none}.product-matrix-container table table th,.product-matrix-container table table td,.product-matrix-container table table tr{border:none}.license-type .icon{color:#a0b8b7;font-size:59px;margin-left:15px}.license-type.divider{padding-bottom:20px;margin-bottom:10px;margin-left:auto;margin-right:auto}.license-type .divider-color{border-bottom:1px solid #CFD0C9;background-color:#f4f5ef}.license-type .price-table .title{color:#696b60;font-size:34px;font-weight:400;line-height:1.2em;margin-bottom:8px}@media only screen and (max-width: 320px){.license-type .price-table .title{font-size:32px;margin-bottom:4px}}.license-type .price-table .sub-title{color:#696b60;font-size:25px;font-weight:400;line-height:1.2em;margin-left:29px;display:inline-block;margin-top:5px}@media only screen and (max-width: 320px){.license-type .price-table .sub-title{font-size:25px;margin-bottom:4px}}.license-type .price-table .total-title{color:#696b60;font-size:22px;font-weight:400;line-height:1.2em;text-align:right}@media only screen and (max-width: 320px){.license-type .price-table .total-title{font-size:22px}}.license-type .price-table table{margin-top:20px}.license-type .price-table .label{color:#434343;display:block;font-size:15px;font-weight:400;padding:0;text-align:left;white-space:normal;margin-bottom:10px;line-height:1.3em;width:150px}.license-type .price-table .a-price{width:80px}.license-type .price-table .price{font-size:15px;font-weight:700;padding-left:10px;text-align:right}.license-type .price-table .check-price{padding-left:10px;width:22px}.license-type .price-table .total-price{font-size:18px;font-weight:700;padding-left:10px;padding-right:20px;text-align:right;width:22px}.license-type .btn-buy{margin-top:38px}.license-type .notes{color:#8DA3A2;font-style:italic;padding-top:40px;padding-left:20px}@media only screen and (max-width: 320px){.license-type .notes{padding-top:0;padding-left:72px}}@media only screen and (min-width: 321px) and (max-width: 768px){.license-type .notes{padding-top:0;padding-left:72px}}@media only screen and (min-width: 769px) and (max-width: 1023px){.license-type .notes{padding-top:0;padding-left:72px}}.license-type button{background:none;border:none}.payment-container{width:80%;max-width:1000px;margin-right:auto;margin-left:auto;margin-top:50px}.item-packager *{font-size:12px}.item-packager table{margin:auto}.package-form{margin:auto}.payment-form input:focus{background-color:#cbeae1}.payment-form-inner{overflow:hidden;-webkit-transition:height 0.5s linear;-moz-transition:height 0.5s linear;-ms-transition:height 0.5s linear;-o-transition:height 0.5s linear;transition:height 0.5s linear}.jtk-payment-form label{display:block}.jtk-payment-form label span{font-size:12px;color:cadetblue}.error{color:red;font-size:11px}.txtInv{width:450px;height:300px}.formMessage{min-height:36px;font-size:12px}.formMessage.error{color:red}.formMessage .wait{width:36px;height:36px;float:left;margin-right:10px;display:none}.invoice-details table{border:1px solid #456;border-collapse:collapse;width:100%;border:1px solid #CFD0C9}.invoice-details table th,.invoice-details table td{padding:10px;text-align:center}.invoice-details table td.item{text-align:right}.invoice-details td{border-left:1px solid #CFD0C9}.invoice-details tr:nth-child(even) td{background-color:#E9EBDD;border-bottom:1px solid #CFD0C9}.colTotal{font-weight:bold;text-align:right !important}.payment-form input{font-size:16px}.payment-form button{background:none;border:none}pre{outline:1px solid #ccc;padding:5px;margin:0}.string{color:green}.number{color:darkorange}.boolean{color:blue}.null{color:magenta}.key{color:red}.blog-content .w{position:absolute;background-color:white;box-shadow:0px 0px 2px black;text-align:center;width:50px;height:50px;border-radius:3px;cursor:pointer}.blog-content .demo{height:340px;margin-top:15px;margin-bottom:15px}.blog-content ._jsPlumb_overlay.label{color:black}.blog-content .highlight{margin-top:15px;margin-bottom:15px}.blog-content h3{margin-top:25px}.blog-content h4,.blog-content h5,.blog-content h6{margin-top:20px;font-weight:bold}.blog-content h4{font-size:18px}.contact-form{width:80%;max-width:700px;margin-left:auto;padding-bottom:25px;margin-right:auto}.contact-form button{background:none;border:none} 2 | /*# sourceMappingURL=main.css.map */ 3 | -------------------------------------------------------------------------------- /data/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": [ 3 | { 4 | "id": "start", 5 | "type": "start", 6 | "text": "Start", 7 | "left": 50, 8 | "top": 50, 9 | "w": 100, 10 | "h": 70 11 | }, 12 | { 13 | "id": "question1", 14 | "type": "question", 15 | "text": "Do Something?", 16 | "left": 279, 17 | "top": 102, 18 | "w": 150, 19 | "h": 150 20 | }, 21 | { 22 | "id": "decide", 23 | "type": "action", 24 | "text": "Make Decision", 25 | "left": 660, 26 | "top": 187, 27 | "w": 120, 28 | "h": 120 29 | }, 30 | { 31 | "id": "something", 32 | "type": "output", 33 | "text": "Do Something", 34 | "left": 827, 35 | "top": 414, 36 | "w": 120, 37 | "h": 50 38 | }, 39 | { 40 | "id": "question2", 41 | "type": "question", 42 | "text": "Do Nothing?", 43 | "left": 74, 44 | "top": 330, 45 | "w": 150, 46 | "h": 150 47 | }, 48 | { 49 | "id": "nothing", 50 | "type": "output", 51 | "text": "Do Nothing", 52 | "left": 433, 53 | "top": 558, 54 | "w": 100, 55 | "h": 50 56 | } 57 | ], 58 | "edges": [ 59 | { 60 | "source": "start", 61 | "target": "question1", 62 | "data": {} 63 | }, 64 | { 65 | "source": "question1", 66 | "target": "decide", 67 | "data": { 68 | "label": "yes", 69 | "type": "connection" 70 | } 71 | }, 72 | { 73 | "source": "question1", 74 | "target": "question2", 75 | "data": { 76 | "label": "no", 77 | "type": "connection" 78 | } 79 | }, 80 | { 81 | "source": "decide", 82 | "target": "nothing", 83 | "data": { 84 | "label": "Can't Decide", 85 | "type": "connection" 86 | } 87 | }, 88 | { 89 | "source": "decide", 90 | "target": "something", 91 | "data": { 92 | "label": "Decision Made", 93 | "type": "connection" 94 | } 95 | }, 96 | { 97 | "source": "question2", 98 | "target": "decide", 99 | "data": { 100 | "label": "no", 101 | "type": "connection" 102 | } 103 | }, 104 | { 105 | "source": "question2", 106 | "target": "nothing", 107 | "data": { 108 | "label": "yes", 109 | "type": "connection" 110 | } 111 | } 112 | ], 113 | "ports": [], 114 | "groups": [] 115 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |