1

I want to avoid duplicate drop on mxgraph canvas.

let say I have dragged Pipe on canvas 2nd time it should not allow it be dragged on canvas.

Question: how to avoid duplicate drop on canvas

Here is my working code drag with duplicate allowed

Drag and Drop

var graph = {};

function initCanvas() {

  //This function is called onload of body itself and it will make the mxgraph canvas
  graph = new mxGraph(document.getElementById('graph-wrapper'));
  graph.htmlLabels = true;
  graph.cellsEditable = false;

  // render as HTML node always. You probably won't want that in real world though
  graph.convertValueToString = function(cell) {
    return cell.value;
  }

  const createDropHandler = function (cells, allowSplit) {
    return function (graph, evt, target, x, y) {
      const select = graph.importCells(cells, x, y, target);
      graph.setSelectionCells(select);
    };
  };

  const createDragPreview = function (width, height) {
    var elt = document.createElement('div');
    elt.style.border = '1px dashed black';
    elt.style.width = width + 'px';
    elt.style.height = height + 'px';
    return elt;
  };

  const createDragSource = function (elt, dropHandler, preview) {
    return mxUtils.makeDraggable(elt, graph, dropHandler, preview, 0, 0, graph.autoscroll, true, true);
  };

  const createItem = (id) => {

    const elt = document.getElementById(id);
    const width = elt.clientWidth;
    const height = elt.clientHeight;

    const cell = new mxCell('', new mxGeometry(0, 0, width, height), 'fillColor=none;strokeColor=none');
    cell.vertex = true;
    graph.model.setValue(cell, elt);

    const cells = [cell];

    const bounds = new mxRectangle(0, 0, width, height);
    createDragSource(elt, createDropHandler(cells, true, false, bounds), createDragPreview(width, height), cells, bounds);
  };


  createItem("shape_1");
  createItem("shape_2");
  createItem("shape_3");
}
#graph-wrapper {
  background: #333;
  width: 100%;
  height: 528px;
 }
<html>

<head>
    <title>Toolbar example for mxGraph</title>

    <script type="text/javascript">
        mxBasePath = 'https://jgraph.github.io/mxgraph/javascript/src';
    </script>
    <script src="https://jgraph.github.io/mxgraph/javascript/src/js/mxClient.js"></script>
    <script src="./app.js"></script>
</head>

<body onload="initCanvas()">
    <h4>Drag same box 2 times on the canvas. see duplicate is allowed</h4>

    <div>
        <div id="shape_1"
            style="width: 100px; height: 100px; border-radius: 50%; background: red; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center;">
            Pipe
        </div>

        <div draggable="true" id="shape_2"
            style="width: 100px; height: 100px; border-radius: 5%; background: orange; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center;">
            Team
        </div>
        
        <div draggable="true" id="shape_3"
            style="width: 100px; height: 64px; background: #009688; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center; border-radius: 207px; flex-direction: column;">
            <div> <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
                    <path d="M0 0h24v24H0V0z" fill="none" />
                    <path
                        d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z" />
                </svg></div>
            <div>Info</div>
        </div>
    </div>

    <div id="graph-wrapper">

    </div>
</body>

</html>
Alireza Ahmadi
  • 8,579
  • 5
  • 15
  • 42
Learner
  • 61
  • 2
  • 21

2 Answers2

1

You just need check all current cells value of maxgarph in createDropHandler. So get all cells by graph.getModel().cells and then check to see if the cells you want to add exists or not:

let allcells = graph.getModel().cells;
for (var i in allcells)
    if (allcells[i].value && (allcells[i].value.id == cells[0].value.id))
        return;

var graph = {};

function initCanvas() {
    //This function is called onload of body itself and it will make the mxgraph canvas
    graph = new mxGraph(document.getElementById('graph-wrapper'));
    graph.htmlLabels = true;
    graph.cellsEditable = false;

    // render as HTML node always. You probably won't want that in real world though
    graph.convertValueToString = function (cell) {
        return cell.value;
    }

    const createDropHandler = function (cells, allowSplit) {
        return function (graph, evt, target, x, y) {
            debugger
            let allcells = graph.getModel().cells;
            for (var i in allcells)
                if (allcells[i].value && (allcells[i].value.id == cells[0].value.id))
                    return;
            const select = graph.importCells(cells, x, y, target);
            graph.setSelectionCells(select);
        };
    };

    const createDragPreview = function (width, height) {
        var elt = document.createElement('div');
        elt.style.border = '1px dashed black';
        elt.style.width = width + 'px';
        elt.style.height = height + 'px';
        return elt;
    };

    const createDragSource = function (elt, dropHandler, preview) {
        return mxUtils.makeDraggable(elt, graph, dropHandler, preview, 0, 0, graph.autoscroll, true, true);
    };

    const createItem = (id) => {
        const elt = document.getElementById(id);
        const width = elt.clientWidth;
        const height = elt.clientHeight;

        const cell = new mxCell('', new mxGeometry(0, 0, width, height), 'fillColor=none;strokeColor=none');
        cell.vertex = true;
        graph.model.setValue(cell, elt);

        const cells = [cell];

        const bounds = new mxRectangle(0, 0, width, height);
        createDragSource(elt, createDropHandler(cells, true, false, bounds), createDragPreview(width, height), cells, bounds);
    };


    createItem("shape_1");
    createItem("shape_2");
    createItem("shape_3");
}
<html>

<head>
    <title>Toolbar example for mxGraph</title>

    <script type="text/javascript">
        mxBasePath = 'https://jgraph.github.io/mxgraph/javascript/src';
    </script>
    <script src="https://jgraph.github.io/mxgraph/javascript/src/js/mxClient.js"></script>
    <script src="./app.js"></script>
    <style>
        #graph-wrapper {
            background: #333;
            width: 100%;
            height: 528px;
        }
    </style>
</head>

<body onload="initCanvas()">
    <h4>Drag same box 2 times on the canvas. see duplicate is allowed</h4>

    <div>
        <div id="shape_1"
             style="width: 100px; height: 100px; border-radius: 50%; background: red; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center;">
            Pipe
        </div>

        <div draggable="true" id="shape_2"
             style="width: 100px; height: 100px; border-radius: 5%; background: orange; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center;">
            Team
        </div>

        <div draggable="true" id="shape_3"
             style="width: 100px; height: 64px; background: #009688; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center; border-radius: 207px; flex-direction: column;">
            <div>
                <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
                    <path d="M0 0h24v24H0V0z" fill="none" />
                    <path d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z" />
                </svg>
            </div>
            <div>Info</div>
        </div>
    </div>

    <div id="graph-wrapper">

    </div>
Alireza Ahmadi
  • 8,579
  • 5
  • 15
  • 42
0

First of all, I don't have any idea about mxgraph. To solve your problem I made some research on documentation of the library and I didn't find any tips.

I used the basics of the Javascript to achieve this and I didn't touch any of your main code and flow. I just add the draggable_status to graph element on createDropHandler function.

When you drag once, the below code add a status to the object and you can't drag anymore just adding a simple control.

graph.draggable_status = false;

To control, should be in the same function - const createDropHandler = function (cells, allowSplit)

if(graph.draggable_status != false){
  const select = graph.importCells(cells, x, y, target);
  graph.setSelectionCells(select);
  graph.draggable_status = false;
}

The full code snippet is here;

var graph = {};

function initCanvas() {

  //This function is called onload of body itself and it will make the mxgraph canvas
  graph = new mxGraph(document.getElementById('graph-wrapper'));
  graph.htmlLabels = true;
  graph.cellsEditable = false;

  // render as HTML node always. You probably won't want that in real world though
  graph.convertValueToString = function(cell) {
    return cell.value;
  }

  const createDropHandler = function (cells, allowSplit) {
    return function (graph, evt, target, x, y) {
      if(graph.draggable_status != false){
        const select = graph.importCells(cells, x, y, target);
        graph.setSelectionCells(select);
        graph.draggable_status = false;
      }
    };
  };

  const createDragPreview = function (width, height) {
    var elt = document.createElement('div');
    elt.style.border = '1px dashed black';
    elt.style.width = width + 'px';
    elt.style.height = height + 'px';
    return elt;
  };

  const createDragSource = function (elt, dropHandler, preview) {
    return mxUtils.makeDraggable(elt, graph, dropHandler, preview, 0, 0, graph.autoscroll, true, true);
  };

  const createItem = (id) => {

    const elt = document.getElementById(id);
    const width = elt.clientWidth;
    const height = elt.clientHeight;

    const cell = new mxCell('', new mxGeometry(0, 0, width, height), 'fillColor=none;strokeColor=none');
    cell.vertex = true;
    graph.model.setValue(cell, elt);

    const cells = [cell];

    const bounds = new mxRectangle(0, 0, width, height);
    createDragSource(elt, createDropHandler(cells, true, false, bounds), createDragPreview(width, height), cells, bounds);
  };


  createItem("shape_1");
  createItem("shape_2");
  createItem("shape_3");
}
#graph-wrapper {
  background: #333;
  width: 100%;
  height: 528px;
 }
<html>

<head>
    <title>Toolbar example for mxGraph</title>

    <script type="text/javascript">
        mxBasePath = 'https://jgraph.github.io/mxgraph/javascript/src';
    </script>
    <script src="https://jgraph.github.io/mxgraph/javascript/src/js/mxClient.js"></script>
    <script src="./app.js"></script>
</head>

<body onload="initCanvas()">
    <h4>Drag same box 2 times on the canvas. see duplicate is allowed</h4>

    <div>
        <div id="shape_1"
            style="width: 100px; height: 100px; border-radius: 50%; background: red; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center;">
            Pipe
        </div>

        <div draggable="true" id="shape_2"
            style="width: 100px; height: 100px; border-radius: 5%; background: orange; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center;">
            Team
        </div>
        
        <div draggable="true" id="shape_3"
            style="width: 100px; height: 64px; background: #009688; display: inline-flex; text-align: center; color: #fff; align-items: center; justify-content: center; border-radius: 207px; flex-direction: column;">
            <div> <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
                    <path d="M0 0h24v24H0V0z" fill="none" />
                    <path
                        d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z" />
                </svg></div>
            <div>Info</div>
        </div>
    </div>

    <div id="graph-wrapper">

    </div>
</body>

</html>
oguzhancerit
  • 1,436
  • 1
  • 16
  • 27