Drawflow - Simple flow library πŸ–₯οΈπŸ–±οΈ

Overview

npm npm npm bundle size GitHub license Twitter URL

Drawflow

Demo

Simple flow library.

Drawflow allows you to create data flows easily and quickly.

Installing only a javascript library and with four lines of code.

⭐ LIVE DEMO

🎨 THEME EDIT GENERATOR

Table of contents

Features

  • Drag Nodes
  • Multiple Inputs / Outputs
  • Multiple connections
  • Delete Nodes and Connections
  • Add/Delete inputs/outputs
  • Reroute connections
  • Data sync on Nodes
  • Zoom in / out
  • Clear data module
  • Support modules
  • Editor mode edit, fixed or view
  • Import / Export data
  • Events
  • Mobile support
  • Vanilla javascript (No dependencies)
  • NPM
  • Vue Support component nodes && Nuxt

Installation

Download or clone repository and copy the dist folder, CDN option Or npm.

Clone

git clone https://github.com/jerosoler/Drawflow.git

CDN

<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jerosoler/Drawflow/dist/drawflow.min.css">
<script src="https://cdn.jsdelivr.net/gh/jerosoler/Drawflow/dist/drawflow.min.js"></script>
# or
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/drawflow.min.css" />
<script src="https://unpkg.com/[email protected]/dist/drawflow.min.js"></script>

NPM

npm i drawflow

Typescript

External package. More info #119

npm install -D @types/drawflow

Import

import Drawflow from 'drawflow'
import styleDrawflow from 'drawflow/dist/drawflow.min.css'

Require

var Drawflow = require('drawflow')
var styleDrawflow = require('drawflow/dist/drawflow.min.css')

Create the parent element of drawflow.

<div id="drawflow"></div>

Running

Start drawflow.

var id = document.getElementById("drawflow");
const editor = new Drawflow(id);
editor.start();
Parameter Type Description
id Object Name of module
render Object It's for Vue.
parent Object It's for Vue. The parent Instance

For vue 2 example.

import Vue from 'vue'

// Pass render Vue
this.editor = new Drawflow(id, Vue, this);

For vue 3 example.

import { h, getCurrentInstance, render } from 'vue'
const Vue = { version: 3, h, render };

this.editor = new Drawflow(id, Vue);
// Pass render Vue 3 Instance
const internalInstance = getCurrentInstance()
editor.value = new Drawflow(id, Vue, internalInstance.appContext.app._context);

Nuxt

Add to nuxt.config.js file

build: {
    transpile: ['drawflow'],
    ...
  }

Mouse and Keys

  • del key to remove element.
  • Right click to show remove options (Mobile long press).
  • Left click press to move editor or node selected.
  • Ctrl + Mouse Wheel Zoom in/out (Mobile pinch).

Editor

You can change the editor to fixed type to block. Only editor can be moved. You can put it before start.

editor.editor_mode = 'edit'; // Default
editor.editor_mode = 'fixed'; // Only scroll

You can also adjust the zoom values.

editor.zoom_max = 1.6;
editor.zoom_min = 0.5;
editor.zoom_value = 0.1;

Editor options

Parameter Type Default Description
reroute Boolean false Active reroute
reroute_fix_curvature Boolean false Fix adding points
curvature Number 0.5 Curvature
reroute_curvature_start_end Number 0.5 Curvature reroute first point and las point
reroute_curvature Number 0.5 Curvature reroute
reroute_width Number 6 Width of reroute
line_path Number 5 Width of line
force_first_input Boolean false Force the first input to drop the connection on top of the node
editor_mode Text edit edit for edit, fixed for nodes fixed but their input fields available, view for view only
zoom Number 1 Default zoom
zoom_max Number 1.6 Default zoom max
zoom_min Number 0.5 Default zoom min
zoom_value Number 0.1 Default zoom value update
zoom_last_value Number 1 Default zoom last value
draggable_inputs Boolean true Drag nodes on click inputs
useuuid Boolean false Use UUID as node ID instead of integer index. Only affect newly created nodes, do not affect imported nodes

Reroute

Active reroute connections. Use before start or import.

editor.reroute = true;

Create point with double click on line connection. Double click on point for remove.

Modules

Separate your flows in different editors.

editor.addModule('nameNewModule');
editor.changeModule('nameNewModule');
editor.removeModule('nameModule');
// Default Module is Home
editor.changeModule('Home');

RemovedModule if it is in the same module redirects to the Home module

Nodes

Adding a node is simple.

editor.addNode(name, inputs, outputs, posx, posy, class, data, html);
Parameter Type Description
name text Name of module
inputs number Number of de inputs
outputs number Number of de outputs
pos_x number Position on start node left
pos_y number Position on start node top
class text Added classname to de node. Multiple classnames separated by space
data json Data passed to node
html text HTML drawn on node or name of register node.
typenode boolean & text Default false, true for Object HTML, vue for vue

You can use the attribute df-* in inputs, textarea or select to synchronize with the node data and contenteditable.

Atrributs multiples parents support df-*-*...

Node example

var html = `
<div><input type="text" df-name></div>
`;
var data = { "name": '' };

editor.addNode('github', 0, 1, 150, 300, 'github', data, html);

Register Node

it's possible register nodes for reuse.

var html = document.createElement("div");
html.innerHTML =  "Hello Drawflow!!";
editor.registerNode('test', html);
// Use
editor.addNode('github', 0, 1, 150, 300, 'github', data, 'test', true);

// For vue
import component from '~/components/testcomponent.vue'
editor.registerNode('name', component, props, options);
// Use for vue
editor.addNode('github', 0, 1, 150, 300, 'github', data, 'name', 'vue');
Parameter Type Description
name text Name of module registered.
html text HTML to drawn or vue component.
props json Only for vue. Props of component. Not Required
options json Only for vue. Options of component. Not Required

Methods

Other available functions.

Mehtod Description
zoom_in() Increment zoom +0.1
zoom_out() Decrement zoom -0.1
getNodeFromId(id) Get Info of node. Ex: id: 5
getNodesFromName(name) Return Array of nodes id. Ex: name: telegram
removeNodeId(id) Remove node. Ex id: node-x
updateNodeDataFromId Update data element. Ex: 5, { name: 'Drawflow' }
addNodeInput(id) Add input to node. Ex id: 5
addNodeOutput(id) Add output to node. Ex id: 5
removeNodeInput(id, input_class) Remove input to node. Ex id: 5, input_2
removeNodeOutput(id, output_class) Remove output to node. Ex id: 5, output_2
addConnection(id_output, id_input, output_class, input_class) Add connection. Ex: 15,16,'output_1','input_1'
removeSingleConnection(id_output, id_input, output_class, input_class) Remove connection. Ex: 15,16,'output_1','input_1'
updateConnectionNodes(id) Update connections position from Node Ex id: node-x
removeConnectionNodeId(id) Remove node connections. Ex id: node-x
getModuleFromNodeId(id) Get name of module where is the id. Ex id: 5
clearModuleSelected() Clear data of module selected
clear() Clear all data of all modules and modules remove.

Methods example

editor.removeNodeId('node-4');

Events

You can detect events that are happening.

List of available events:

Event Return Description
nodeCreated id id of Node
nodeRemoved id id of Node
nodeDataChanged id id of Node df-* attributes changed.
nodeSelected id id of Node
nodeUnselected true Unselect node
nodeMoved id id of Node
connectionStart { output_id, output_class } id of nodes and output selected
connectionCancel true Connection Cancel
connectionCreated { output_id, input_id, output_class, input_class } id's of nodes and output/input selected
connectionRemoved { output_id, input_id, output_class, input_class } id's of nodes and output/input selected
connectionSelected { output_id, input_id, output_class, input_class } id's of nodes and output/input selected
connectionUnselected true Unselect connection
addReroute id id of Node output
removeReroute id id of Node output
rerouteMoved id id of Node output
moduleCreated name name of Module
moduleChanged name name of Module
moduleRemoved name name of Module
click event Click event
clickEnd event Once the click changes have been made
contextmenu event Click second button mouse event
mouseMove { x, y } Position
mouseUp event MouseUp Event
keydown event Keydown event
zoom zoom_level Level of zoom
translate { x, y } Position translate editor
import import Finish import
export data Data export

Events example

editor.on('nodeCreated', function(id) {
  console.log("Node created " + id);
})

Export / Import

You can export and import your data.

var exportdata = editor.export();
editor.import(exportdata);

Export example

Example of exported data:

{
    "drawflow": {
        "Home": {
            "data": {}
        },
        "Other": {
            "data": {
                "16": {
                    "id": 16,
                    "name": "facebook",
                    "data": {},
                    "class": "facebook",
                    "html": "\n        
\n          
 Facebook Message
\n        
\n        ",
                    "inputs": {},
                    "outputs": {
                        "output_1": {
                            "connections": [
                                {
                                    "node": "17",
                                    "output": "input_1"
                                }
                            ]
                        }
                    },
                    "pos_x": 226,
                    "pos_y": 138
                },
                "17": {
                    "id": 17,
                    "name": "log",
                    "data": {},
                    "class": "log",
                    "html": "\n            
\n              
 Save log file
\n            
\n            ",
                    "inputs": {
                        "input_1": {
                            "connections": [
                                {
                                    "node": "16",
                                    "input": "output_1"
                                }
                            ]
                        }
                    },
                    "outputs": {},
                    "pos_x": 690,
                    "pos_y": 129
                }
            }
        }
    }
}

Example

View the complete example in folder docs.
There is also an example how to use Drawflow in a custom element. (based on LitElement).

License

MIT License

Comments
  • Can this be implemented with Livewire

    Can this be implemented with Livewire

    Hi,

    Trying to implement Drawflow in my Laravel+Livewire project.

    Unable to get the desired results. In fact failing at the first attempt. I am sure I have missed a step or not doing it right. Could you show how its done or can it actually be done in a Livewire project.

    Was planning to integrate Alpine JS later on to replace the vue code. But that is at a later stage. Currently just trying to get a mindmap functionality with Drawflow.

    I have included the drawflow.min.css in my app.scss and drawflow.min.js in my app.js

    Used the CDN links in my layouts.app in the head <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jerosoler/Drawflow/dist/drawflow.min.css">

    in the body <script src="https://cdn.jsdelivr.net/gh/jerosoler/Drawflow/dist/drawflow.min.js"></script>

    Created the blade file as this:

    
    @extends('layouts.app')
    
    @section('content')
        <section class="section">
            <div class="section-header">
                <h1 class="text-truncate">MindMap</h1>
            </div>
            <div class="section-body">
                <div class="row">
                    <div class="drawflow col-3 mh-100 bg-primary text-white px-2 py-4">
                        <div class="drag-drawflow" draggable="true" ondragstart="drag(event)" data-node="facebook">
                            <i class="fab fa-facebook"></i><span> Facebook</span>
                        </div>
                    </div>
    
                    <div class="col-9 mh-100 bg-success text-black px-4 py-4">
                        <div id="drawflow" ondrop="drop(event)" ondragover="allowDrop(event)">
                            test
                        </div>
                    </div>
                </div>
            </div>
    
    
            <script>
                var id = document.getElementById("drawflow");
            const editor = new Drawflow(facebook);
            editor.reroute = true;
            editor.drawflow = {"drawflow":{"Home":{"data":{"1":{"id":1,"name":"welcome","data":{},"class":"welcome","html":"\n    <div>\n      <div class=\"title-box\">πŸ‘ Welcome!!</div>\n      <div class=\"box\">\n        <p>Simple flow library <b>demo</b>\n        <a href=\"https://github.com/jerosoler/Drawflow\" target=\"_blank\">Drawflow</a> by <b>Jero Soler</b></p><br>\n\n        <p>Multiple input / outputs<br>\n           Data sync nodes<br>\n           Import / export<br>\n           Modules support<br>\n           Simple use<br>\n           Type: Fixed or Edit<br>\n           Events: view console<br>\n           Pure Javascript<br>\n        </p>\n        <br>\n        <p><b><u>Shortkeys:</u></b></p>\n        <p>🎹 <b>Delete</b> for remove selected<br>\n        πŸ’  Mouse Left Click == Move<br>\n        ❌ Mouse Right == Delete Option<br>\n        πŸ” Ctrl + Wheel == Zoom<br>\n        πŸ“± Mobile support<br>\n        ...</p>\n      </div>\n    </div>\n    ","typenode": false, "inputs":{},"outputs":{},"pos_x":50,"pos_y":50},"2":{"id":2,"name":"slack","data":{},"class":"slack","html":"\n          <div>\n            <div class=\"title-box\"><i class=\"fab fa-slack\"></i> Slack chat message</div>\n          </div>\n          ","typenode": false, "inputs":{"input_1":{"connections":[{"node":"7","input":"output_1"}]}},"outputs":{},"pos_x":1028,"pos_y":87},"3":{"id":3,"name":"telegram","data":{"channel":"channel_2"},"class":"telegram","html":"\n          <div>\n            <div class=\"title-box\"><i class=\"fab fa-telegram-plane\"></i> Telegram bot</div>\n            <div class=\"box\">\n              <p>Send to telegram</p>\n              <p>select channel</p>\n              <select df-channel>\n                <option value=\"channel_1\">Channel 1</option>\n                <option value=\"channel_2\">Channel 2</option>\n                <option value=\"channel_3\">Channel 3</option>\n                <option value=\"channel_4\">Channel 4</option>\n              </select>\n            </div>\n          </div>\n          ","typenode": false, "inputs":{"input_1":{"connections":[{"node":"7","input":"output_1"}]}},"outputs":{},"pos_x":1032,"pos_y":184},"4":{"id":4,"name":"email","data":{},"class":"email","html":"\n            <div>\n              <div class=\"title-box\"><i class=\"fas fa-at\"></i> Send Email </div>\n            </div>\n            ","typenode": false, "inputs":{"input_1":{"connections":[{"node":"5","input":"output_1"}]}},"outputs":{},"pos_x":1033,"pos_y":439},"5":{"id":5,"name":"template","data":{"template":"Write your template"},"class":"template","html":"\n            <div>\n              <div class=\"title-box\"><i class=\"fas fa-code\"></i> Template</div>\n              <div class=\"box\">\n                Ger Vars\n                <textarea df-template></textarea>\n                Output template with vars\n              </div>\n            </div>\n            ","typenode": false, "inputs":{"input_1":{"connections":[{"node":"6","input":"output_1"}]}},"outputs":{"output_1":{"connections":[{"node":"4","output":"input_1"},{"node":"11","output":"input_1"}]}},"pos_x":607,"pos_y":304},"6":{"id":6,"name":"github","data":{"name":"https://github.com/jerosoler/Drawflow"},"class":"github","html":"\n          <div>\n            <div class=\"title-box\"><i class=\"fab fa-github \"></i> Github Stars</div>\n            <div class=\"box\">\n              <p>Enter repository url</p>\n            <input type=\"text\" df-name>\n            </div>\n          </div>\n          ","typenode": false, "inputs":{},"outputs":{"output_1":{"connections":[{"node":"5","output":"input_1"}]}},"pos_x":341,"pos_y":191},"7":{"id":7,"name":"facebook","data":{},"class":"facebook","html":"\n        <div>\n          <div class=\"title-box\"><i class=\"fab fa-facebook\"></i> Facebook Message</div>\n        </div>\n        ","typenode": false, "inputs":{},"outputs":{"output_1":{"connections":[{"node":"2","output":"input_1"},{"node":"3","output":"input_1"},{"node":"11","output":"input_1"}]}},"pos_x":347,"pos_y":87},"11":{"id":11,"name":"log","data":{},"class":"log","html":"\n            <div>\n              <div class=\"title-box\"><i class=\"fas fa-file-signature\"></i> Save log file </div>\n            </div>\n            ","typenode": false, "inputs":{"input_1":{"connections":[{"node":"5","input":"output_1"},{"node":"7","input":"output_1"}]}},"outputs":{},"pos_x":1031,"pos_y":363}}},"Other":{"data":{"8":{"id":8,"name":"personalized","data":{},"class":"personalized","html":"\n            <div>\n              Personalized\n            </div>\n            ","typenode": false, "inputs":{"input_1":{"connections":[{"node":"12","input":"output_1"},{"node":"12","input":"output_2"},{"node":"12","input":"output_3"},{"node":"12","input":"output_4"}]}},"outputs":{"output_1":{"connections":[{"node":"9","output":"input_1"}]}},"pos_x":764,"pos_y":227},"9":{"id":9,"name":"dbclick","data":{"name":"Hello World!!"},"class":"dbclick","html":"\n            <div>\n            <div class=\"title-box\"><i class=\"fas fa-mouse\"></i> Db Click</div>\n              <div class=\"box dbclickbox\" ondblclick=\"showpopup(event)\">\n                Db Click here\n                <div class=\"modal\" style=\"display:none\">\n                  <div class=\"modal-content\">\n                    <span class=\"close\" onclick=\"closemodal(event)\">&times;</span>\n                    Change your variable {name} !\n                    <input type=\"text\" df-name>\n                  </div>\n\n                </div>\n              </div>\n            </div>\n            ","typenode": false, "inputs":{"input_1":{"connections":[{"node":"8","input":"output_1"}]}},"outputs":{"output_1":{"connections":[{"node":"12","output":"input_2"}]}},"pos_x":209,"pos_y":38},"12":{"id":12,"name":"multiple","data":{},"class":"multiple","html":"\n            <div>\n              <div class=\"box\">\n                Multiple!\n              </div>\n            </div>\n            ","typenode": false, "inputs":{"input_1":{"connections":[]},"input_2":{"connections":[{"node":"9","input":"output_1"}]},"input_3":{"connections":[]}},"outputs":{"output_1":{"connections":[{"node":"8","output":"input_1"}]},"output_2":{"connections":[{"node":"8","output":"input_1"}]},"output_3":{"connections":[{"node":"8","output":"input_1"}]},"output_4":{"connections":[{"node":"8","output":"input_1"}]}},"pos_x":179,"pos_y":272}}}}}
            editor.start();
    
            /* DRAG EVENT */
    
            /* Mouse and Touch Actions */
    
            var elements = document.getElementsByClassName('drag-drawflow');
            for (var i = 0; i < elements.length; i++) {
            elements[i].addEventListener('touchend', drop, false);
            elements[i].addEventListener('touchmove', positionMobile, false);
            elements[i].addEventListener('touchstart', drag, false );
            }
    
            var mobile_item_selec = '';
            var mobile_last_move = null;
            function positionMobile(ev) {
            mobile_last_move = event;
            }
    
            function allowDrop(ev) {
            ev.preventDefault();
            }
    
            function drag(ev) {
            if (ev.type === "touchstart") {
                mobile_item_selec = ev.target.closest(".drag-drawflow").getAttribute('data-node');
            } else {
            ev.dataTransfer.setData("node", ev.target.getAttribute('data-node'));
            }
            }
    
            function drop(ev) {
            if (ev.type === "touchend") {
                var parentdrawflow = document.elementFromPoint( mobile_last_move.touches[0].clientX, mobile_last_move.touches[0].clientY).closest("#drawflow");
                if(parentdrawflow != null) {
                addNodeToDrawFlow(mobile_item_selec, mobile_last_move.touches[0].clientX, mobile_last_move.touches[0].clientY);
                }
                mobile_item_selec = '';
            } else {
                ev.preventDefault();
                var data = ev.dataTransfer.getData("node");
                addNodeToDrawFlow(data, ev.clientX, ev.clientY);
            }
    
            }
    
            function addNodeToDrawFlow(name, pos_x, pos_y) {
            if(editor.editor_mode === 'fixed') {
                return false;
            }
            pos_x = pos_x * ( editor.precanvas.clientWidth / (editor.precanvas.clientWidth * editor.zoom)) - (editor.precanvas.getBoundingClientRect().x * ( editor.precanvas.clientWidth / (editor.precanvas.clientWidth * editor.zoom)));
            pos_y = pos_y * ( editor.precanvas.clientHeight / (editor.precanvas.clientHeight * editor.zoom)) - (editor.precanvas.getBoundingClientRect().y * ( editor.precanvas.clientHeight / (editor.precanvas.clientHeight * editor.zoom)));
    
            switch (name) {
                    case 'facebook':
                    var facebook = `
                    <div>
                      <div class="title-box"><i class="fab fa-facebook"></i> Facebook Message</div>
                    </div>
                    `;
                      editor.addNode('facebook', 0,  1, pos_x, pos_y, 'facebook', {}, facebook );
                      break;
                    case 'slack':
                      var slackchat = `
                      <div>
                        <div class="title-box"><i class="fab fa-slack"></i> Slack chat message</div>
                      </div>
                      `
                      editor.addNode('slack', 1, 0, pos_x, pos_y, 'slack', {}, slackchat );
                      break;
                    case 'github':
                      var githubtemplate = `
                      <div>
                        <div class="title-box"><i class="fab fa-github "></i> Github Stars</div>
                        <div class="box">
                          <p>Enter repository url</p>
                        <input type="text" df-name>
                        </div>
                      </div>
                      `;
                      editor.addNode('github', 0, 1, pos_x, pos_y, 'github', { "name": ''}, githubtemplate );
                      break;
                    case 'telegram':
                      var telegrambot = `
                      <div>
                        <div class="title-box"><i class="fab fa-telegram-plane"></i> Telegram bot</div>
                        <div class="box">
                          <p>Send to telegram</p>
                          <p>select channel</p>
                          <select df-channel>
                            <option value="channel_1">Channel 1</option>
                            <option value="channel_2">Channel 2</option>
                            <option value="channel_3">Channel 3</option>
                            <option value="channel_4">Channel 4</option>
                          </select>
                        </div>
                      </div>
                      `;
                      editor.addNode('telegram', 1, 0, pos_x, pos_y, 'telegram', { "channel": 'channel_3'}, telegrambot );
                      break;
                    case 'aws':
                      var aws = `
                      <div>
                        <div class="title-box"><i class="fab fa-aws"></i> Aws Save </div>
                        <div class="box">
                          <p>Save in aws</p>
                          <input type="text" df-db-dbname placeholder="DB name"><br><br>
                          <input type="text" df-db-key placeholder="DB key">
                          <p>Output Log</p>
                        </div>
                      </div>
                      `;
                      editor.addNode('aws', 1, 1, pos_x, pos_y, 'aws', { "db": { "dbname": '', "key": '' }}, aws );
                      break;
                    case 'log':
                        var log = `
                        <div>
                          <div class="title-box"><i class="fas fa-file-signature"></i> Save log file </div>
                        </div>
                        `;
                        editor.addNode('log', 1, 0, pos_x, pos_y, 'log', {}, log );
                        break;
                      case 'google':
                        var google =
                        <div>
                          <div class="title-box"><i class="fab fa-google-drive"></i> Google Drive save </div>
                        </div>
                        ;
                        editor.addNode('google', 1, 0, pos_x, pos_y, 'google', {}, google );
                        break;
                      case 'email':
                        var email = 
                        <div>
                          <div class="title-box"><i class="fas fa-at"></i> Send Email </div>
                        </div>
                        ;
                        editor.addNode('email', 1, 0, pos_x, pos_y, 'email', {}, email );
                        break;
    
                      case 'template':
                        var template =
                        <div>
                          <div class="title-box"><i class="fas fa-code"></i> Template</div>
                          <div class="box">
                            Ger Vars
                            <textarea df-template></textarea>
                            Output template with vars
                          </div>
                        </div>
                        ;
                        editor.addNode('template', 1, 1, pos_x, pos_y, 'template', { "template": 'Write your template'}, template );
                        break;
                      case 'multiple':
                        var multiple =
                        <div>
                          <div class="box">
                            Multiple!
                          </div>
                        </div>
                        ;
                        editor.addNode('multiple', 3, 4, pos_x, pos_y, 'multiple', {}, multiple );
                        break;
                      case 'personalized':
                        var personalized =
                        <div>
                          Personalized
                        </div>
                        ;
                        editor.addNode('personalized', 1, 1, pos_x, pos_y, 'personalized', {}, personalized );
                        break;
                      case 'dbclick':
                        var dbclick = `
                        <div>
                        <div class="title-box"><i class="fas fa-mouse"></i> Db Click</div>
                          <div class="box dbclickbox" ondblclick="showpopup(event)">
                            Db Click here
                            <div class="modal" style="display:none">
                              <div class="modal-content">
                                <span class="close" onclick="closemodal(event)">&times;</span>
                                Change your variable {name} !
                                <input type="text" df-name>
                              </div>
    
                            </div>
                          </div>
                        </div>
                        `;
                        editor.addNode('dbclick', 1, 1, pos_x, pos_y, 'dbclick', { name: ''}, dbclick );
                        break;
    
                    default:
                }
            }
    
            </script>
        </section>
    @endsection
    
    

    This is the Console error that I get in Firefox Uncaught ReferenceError: Drawflow is not defined <anonymous> http://127.0.0.1:8000/mindmap:112

    Get this error on launching the page

    And, get this error on trying to drag

    Uncaught ReferenceError: drag is not defined
        ondragstart http://127.0.0.1:8000/mindmap:1
    
    question 
    opened by h6585 21
  • Lines not showing on import data

    Lines not showing on import data

    Hi @jerosoler , primally thanks for your library.

    My problem happens after the import the data, only after moving the node the lines showing.

    Before: image

    After: image

    I took a test with the function updateConnectionNodes, but not resolve the problem

    My code:

    var exportdata = JSON.stringify(this.dados.flow)
        exportdata = JSON.parse(exportdata)
        this.editor.import(exportdata)
        this.editor.on('import', function() {
                this.editor.updateConnectionNodes('node-6')
                this.editor.updateConnectionNodes('node-7')
                this.editor.updateConnectionNodes('node-8')
                this.editor.updateConnectionNodes('node-9')
                this.editor.updateConnectionNodes('node-10')
      })
    

    You can help me please?

    question 
    opened by PedroCDLoureiro 17
  • Error during import

    Error during import

    https://github.com/jerosoler/Drawflow/blob/9d98a71c38d89ab700376af205b9e593627fe81a/src/drawflow.js#L1415

    Hi Jero, I'm trying to import drawflow data i saved in current storage (Vuex) but I'm getting this error (screenshot attached):

    Uncaught TypeError: Cannot read property 'options' of undefined

    Screenshot 2020-10-26 at 18 23 31

    If it could be useful, I'm not using options during nodes creation (I tried to set it to empty object or null, but it gave me same error). Any help? Could it be e bug?

    Vue 
    opened by cage81 17
  • Give node id as per your choice

    Give node id as per your choice

    In editor.addNode() function, we can pass name, input, output, position x, position y, class, and html. How we can pass node id and give node id according to our choice?

    question 
    opened by ishpreetkaurwebner 16
  • Initial Straight Lines with Vertical Points

    Initial Straight Lines with Vertical Points

    Hi @jerosoler ,

    it's me again πŸ˜„ I implemented a solution with vertical points and straight lines. Which works fine. Unfortunately when the Flowchart is imported, before I move the nodes, the Connections still start inside the node, instead of at the top and bottom.

    In the attached picture you can see the following scenario:

    • I moved the top two nodes, so the lines look just like they're supposed to (coming out of the top circle of the center node)
    • I haven't moved the bottom nodes, and you can see, the connections are in the middle of the center node instead of the bottom circle

    image

    Code for straight lines:

    this.editor.curvature = 0
          this.editor.reroute_curvature_start_end = 0
          this.editor.reroute_curvature = 0
          this.editor.createCurvature = function (
            start_pos_x: number,
            start_pos_y: number,
            end_pos_x: number,
            end_pos_y: number
          ) {
            var center_y = (end_pos_y - start_pos_y) / 2 + start_pos_y
            return (
              ' M ' +
              start_pos_x +
              ' ' +
              start_pos_y +
              ' L ' +
              start_pos_x +
              ' ' +
              center_y +
              ' L ' +
              end_pos_x +
              ' ' +
              center_y +
              ' L ' +
              end_pos_x +
              ' ' +
              end_pos_y
            )
          }
    

    How can I have the lines correct, as soon as the nodes/connections are imported? I don't wan't to move every node, each time I enter a flowchart?

    Thanks in advance as always πŸ˜„

    question 
    opened by SilasNiewierra 15
  • Can't use i18n inside Node Component

    Can't use i18n inside Node Component

    Hi @jerosoler , I'm desperately trying to get vuei18n to work. I have a simple workflow:

    Editor.vue

    ...
     // Register nodes
    const nodeProps = (key) => ({
      step: stepTemplates[key],
      toggleDetails: this.toggleNodeDetails,
      editor: this.editor,
    })
    
    Object.keys(stepTemplates).forEach((key) => {
      this.editor.registerNode(key, Step, nodeProps(key))
    })
    ...
    

    Step.vue

    <template>
      <div class="header d-flex align-center">
        <img :src="step.icon" height="32" />
        <div class="ml-2 title text-h5 font-weight-medium">
          {{ $t(step.title) }}
        </div>
      </div>
      <div class="mt-4">
        <trigger-step
          :toggleDetails="toggleDetails"
          :editor="editor"
        />
      </div>
    </template>
    

    TriggerStep.vue

    <template>
      <div class="mt-4">
        <div class="d-flex">
          <p>{{ $t('steps.trigger.desc') }}</p>
          <div class="ml-1" @click="toggleDetails">
            <input
              class="dynamic-field"
              disabled
              :value="node.eventname"
              :placeholder="$t('steps.trigger.placeholderEventName')"
            />
          </div>
        </div>
      </div>
    </template>
    

    What I expected to happen: The Step is displayed in the editor correctly with the string in the .json file.

    What happens: TypeError: _ctx.$t is not a function

    Vue 
    opened by SilasNiewierra 15
  • Create Typescript definition

    Create Typescript definition

    Hello,

    I'm currently working to add the typescript definition for the package :)

    I created a PR in the DefinitelyTyped repository. To be merge, the PR need to be reviewed by another person.

    Can someone do this review ? Here is the link to the PR : https://github.com/DefinitelyTyped/DefinitelyTyped/pull/51271/files

    Also if someone want to be a co-owner of the PR (not sure how this really works) but it says that is a good idea because multiple person would be able to update the typing.

    Thank you

    opened by BobBDE 15
  • dynamically added html is not included in the export data

    dynamically added html is not included in the export data

    HI @jerosoler , found another issue..if i dynamically add any html into any node and later if i export, the dynamically added html is not present in the html of the export

    opened by MehbubRashid 15
  • this.drawflow.drawflow is undefined when trying to import file

    this.drawflow.drawflow is undefined when trying to import file

    i've exported the file using the editor.export() method.

    Then, when i try to load that file, it displays me the error and doesn't load the nodes.

    Captura de pantalla 2022-07-09 132204

    This is the data i'm trying to import:

    { "drawflow": { "Home": { "data": { "1": { "id": 1, "name": "Number", "data": { "Number": 0 }, "class": "Number", "html": "Number", "typenode": "vue", "inputs": {}, "outputs": { "output_1": { "connections": [] } }, "pos_x": -1445.183349609375, "pos_y": 115 }, "2": { "id": 2, "name": "Number", "data": { "Number": 0 }, "class": "Number", "html": "Number", "typenode": "vue", "inputs": {}, "outputs": { "output_1": { "connections": [] } }, "pos_x": -1349.183349609375, "pos_y": 391 }, "3": { "id": 3, "name": "Sub", "data": { "Number1": 0, "Number2": 0, "Result": 0 }, "class": "Sub", "html": "Sub", "typenode": "vue", "inputs": { "input_1": { "connections": [] }, "input_2": { "connections": [] } }, "outputs": { "output_1": { "connections": [] } }, "pos_x": -924.183349609375, "pos_y": 276 } } } } }

    question Vue 
    opened by danielpc12 14
  • New modes, or how to adjust

    New modes, or how to adjust "fixed" mode

    Hi, still in love with your library. It's great to work with, and now I got another question πŸ˜„

    Once a user "activates" the flowchart, I would like to set the mode to fixed. But the user should still be able to move the entire diagram around. So the only thing that should change is, once the flowchart is active, the user should not be able to:

    • add new nodes
    • delete nodes
    • add connections
    • delete connections

    Is there a way to adjust the fixed mode, so the user is still able to move the nodes around? In case something looks cluttered and he wants to make it more visually appealing.

    Thanks

    question 
    opened by SilasNiewierra 14
  • Can we preserve output- class of output bubbles?

    Can we preserve output- class of output bubbles?

    Suppose, I have 6 output bubbles with class names output_1, output_2, .... output_6. I removes one output bubble having class output_4 with method editor.removeNodeOutput(), it renames all bubble outputs like output_1, output_2, output_3, output_4, output_5. I would like to have output classes as: output_1, output_2, output_3, output_5, output_6. output_4 is removed, so it should not be there in sequence.

    When we remove any node, then node classes are not renamed. In same way, can output bubbles' classes can be preserved?

    question 
    opened by ishpreetkaurwebner 14
  • Remover Node Output

    Remover Node Output

    How can I remove Node Output, without having to remove it in sequence

    Eg: I have [output_1, output_2, output_3] if i remove it in sequence it works

    if by chance I want to remove output_2 and then output_3 gives error

    erro

    question 
    opened by cewebdesigner 1
  • Reload default diagrams when adding a new module

    Reload default diagrams when adding a new module

    Hi Jero

    I'm trying to implement to reload the default loaded diagrams that I setup whenever a user wants to add a new module. Below is the picture showing the default diagrams loaded. image

    Here is when a user adds a new module. image

    And this what it looks after adding a new module. image

    I'm looking for implementations (if you have any) that can reload the default diagrams whenever a user adds a new module.

    Thank you!

    question 
    opened by angelostiffy 2
  • Allow drop is not defined

    Allow drop is not defined

    Hi, I have JSON value which added to variable and assigned to dataTOImport. I am able to retrieve the data but unable to drag and drop event and modify it. thanks message.txt

    question 
    opened by mithunsidd 1
  • Check currently how many nodes are there in the canvas

    Check currently how many nodes are there in the canvas

    I have dynamic popup on each nodes. So I need to drag one node and on double click need to fill the pop up. If I don't fill the popup the dragging of next node must be restricted. If there any provision to check how many nodes are there in the canvas before I am dragging the next node.

    question 
    opened by Ashvi213 2
Releases(0.0.59)
Owner
Jero Soler
πŸ’» Developer & Maker πŸ€–
Jero Soler
Simple rich text editor (contentEditable) for jQuery UI

Hallo - contentEditable for jQuery UI Hallo is a very simple in-place rich text editor for web pages. It uses jQuery UI and the HTML5 contentEditable

Henri Bergius 2.4k Dec 17, 2022
A modern, simple and elegant WYSIWYG rich text editor.

jQuery-Notebook A simple, clean and elegant WYSIWYG rich text editor for web aplications Note: Check out the fully functional demo and examples here.

Raphael Cruzeiro 1.7k Dec 12, 2022
Simple, beautiful wysiwyg editor

This repo is no longer maintained. bootstrap3-wysiwyg is much better Overview Bootstrap-wysihtml5 is a javascript plugin that makes it easy to create

James Hollingworth 4.2k Dec 30, 2022
Super simple WYSIWYG editor

Summernote Super simple WYSIWYG Editor. Summernote Summernote is a JavaScript library that helps you create WYSIWYG editors online. Home page: https:/

Summernote 11k Jan 7, 2023
A simple, beautiful, and embeddable JavaScript Markdown editor. Delightful editing for beginners and experts alike. Features built-in autosaving and spell checking.

SimpleMDE - Markdown Editor A drop-in JavaScript textarea replacement for writing beautiful and understandable Markdown. The WYSIWYG-esque editor allo

Sparksuite 9.3k Jan 4, 2023
Customize your README.md file with ready-to-use sections in a simple way with the web editor

myreadme Customize your README.md file with ready-to-use sections in a simple way with the web editor Docker version Docker Hub docker run -p 7000:300

Nelson HernΓ‘ndez 7 Jul 25, 2022
The world's #1 JavaScript library for rich text editing. Available for React, Vue and Angular

TinyMCE TinyMCE is the world's most advanced open source core rich text editor. Trusted by millions of developers, and used by some of the world's lar

Tiny 12.4k Jan 4, 2023
A JS library for building WYSIWYG editors for HTML content.

For information on the ContentTools 2.x roadmap please view the: Roadmap repo ContentTools A JS library for building WYSIWYG editors for HTML content.

getme 3.9k Jan 8, 2023
ppo is a super small and useful utils library for JavaScript 🐝🐜

Overview Every frontend developer has written his own utils library, and we often write methods that are easily forgotten and highly used. ppo is a su

anonymous namespace 105 Jul 21, 2022
A simple NEXT.js app that lists NFTs within a contract address from a Buildable Flow.

NFT Marketplace Demo This is a basic Next.js app for listing NFTs in a given contract address. The purpose of this repository is to showcase the simpl

Buildable 16 Dec 12, 2022
An async control-flow library that makes stepping through logic easy.

Step A simple control-flow library for node.JS that makes parallel execution, serial execution, and error handling painless. How to install Simply cop

Tim Caswell 2.2k Dec 22, 2022
A basic React/NextJS project showing how to use the Flow Client Library (FCL)

How to use the Flow Client Library (FCL) with SvelteKit Everything you need to build a SvelteKit project with the Flow Client Library (FCL). For a Sve

Andrea Muttoni 19 Sep 24, 2022
:surfer: Asynchronous flow control with a functional taste to it

Asynchronous flow control with a functional taste to it Ξ» aims to stay small and simple, while powerful. Inspired by async and lodash. Methods are imp

NicolΓ‘s Bevacqua 763 Jan 4, 2023
The ultimate generator based flow-control goodness for nodejs (supports thunks, promises, etc)

co Generator based control flow goodness for nodejs and the browser, using promises, letting you write non-blocking code in a nice-ish way. Co v4 co@4

TJ Holowaychuk 11.8k Jan 2, 2023
Callback-free control flow for Node using ES6 generators.

suspend Generator-based control-flow for Node enabling asynchronous code without callbacks, transpiling, or selling your soul. Suspend is designed to

Jeremy Martin 550 Jul 9, 2022
Flow control and error handling for Node.js

NOTE: This project is deprecated and no longer being actively developed or maintained. See Issue #50 for details. StrongLoop zone library Overview The

StrongLoop and IBM API Connect 280 Feb 18, 2022
CryptoDappy is the fastest way to get started with Flow.

Demo application (testnet) Learning hub (start learning here) What's CryptoDappy? CryptoDappy is the fastest way to get started with blockchain develo

Benjamin Ebner 91 Aug 18, 2022
One-page checkout flow

Medusa Express Medusa is an open-source headless commerce engine that enables developers to create amazing digital commerce experiences. Built with Me

Medusa 49 Oct 11, 2022
Marquee is a VS Code extension designed to naturally integrate with your development flow, so that you will no longer lose track of your thoughts while you're coding

Marquee Stay organized with minimal context switching, all inside your Visual Studio Code. Marquee is a VS Code extension designed to naturally integr

stateful 60 Dec 13, 2022
A Flow-based programming language for universal applications.

Hlang A Flow-based programming language for universal applications. Hlang aims to make programming easier, faster and more comfortable. It avoids codi

HSET 5 Dec 25, 2022