2

I'm setting up a view where table rows can be dragged to another table inside another div. While dragging a row, I highlight the droppable area by changing the background color. However, when dragging an element over elements within the droppable div, the background color glitches in and out.

I've reproduced it in JSFiddle (link) with the following code:

function dragOver(ev) {
  document.getElementById('table1-wrapper').style.backgroundColor = 'gray';
}
  
function dragLeave(ev) {
  document.getElementById('table1-wrapper').style.backgroundColor = null;
}
.table-wrapper {
  border: 1px solid black;
}
<h3>
Drag item from some stuff 2 to some stuff 1
</h3>

<div id="table1-wrapper" class="table-wrapper" ondragover="dragOver(event)" ondragleave="dragLeave(event)">
  <table >
    <tbody>
      <tr draggable="true">
        <td>some stuff 1</td>
      </tr>
      <tr draggable="true">
        <td>some stuff 1</td>
      </tr>
      <tr draggable="true">
        <td>some stuff 1</td>
      </tr>
    </tbody>
  </table>
</div>

<div id="table2-wrapper" class="table-wrapper" ondragover="dragOver(event)" ondragleave="dragLeave(event)">
  <table >
    <tbody>
      <tr draggable="true">
        <td>some stuff 2</td>
      </tr>
      <tr draggable="true">
        <td>some stuff 2</td>
      </tr>
      <tr draggable="true">
        <td>some stuff 2</td>
      </tr>
    </tbody>
  </table>
</div>

Any ideas on how to fix the glitchiness?

Sercan
  • 4,739
  • 3
  • 17
  • 36
ruttergod
  • 167
  • 9
  • 1
    I spent some time looking at this issue. It looks like this problem is caused by there being some areas that are not `table-wrapper` rather inside table wrapper, and those areas will not bubble the `ondragover` event. I think a non-jquery solution would require some different logic, like using the `dragstart` event to create an overlay on the dropareas that cover the whole element, and therefore register any `ondragover` event – async await Dec 16 '21 at 03:27
  • I looked into this some more today and found this question: https://stackoverflow.com/questions/7110353/html5-dragleave-fired-when-hovering-a-child-element One of the answers in that made me try updating my fiddle's CSS with `#table1-wrapper * { pointer-events: none; }` It seems to fix it :) – ruttergod Dec 16 '21 at 16:13

2 Answers2

2

A faster and easier solution can be obtained using jQuery. All you have to do is adapt the jQuery code in the example below by including it in your own code.

$(function () {
    $("#managers, #workers").sortable({
            connectWith: "ul",
            placeholder: "placeholder",
            delay: 150
        })
        .disableSelection()
        .dblclick(function (e) {
            var item = e.target;

            if (e.currentTarget.id === 'managers') {
                //move from all to user
                $(item).fadeOut('fast', function () {
                    $(item).appendTo($('#workers')).fadeIn('slow');
                });
            } else {
                //move from user to all
                $(item).fadeOut('fast', function () {
                    $(item).appendTo($('#managers')).fadeIn('slow');
                });
            }
        });
});
.user-container {
    width: 330px;
}
.right {
    float: right;
}
.left {
    float: left;
}
p {
    clear: both;
    padding-top: 1em;
}
.group-list {
    list-style-type: none;
    margin: 0;
    padding: 0;
    margin-right: 10px;
    background: #eee;
    padding: 5px;
    width: 143px;
    min-height: 1.5em;
    font-size: 0.85em;
}
.group-list li {
    margin: 5px;
    padding: 5px;
    font-size: 1.2em;
    width: 120px;
}
.group-list li.placeholder {
    height: 1.2em
}
.user {
    border: 1px solid #bbb;
    background-color: #fafafa;
    cursor: move;
}
.user.ui-sortable-helper {
    opacity: 0.5;
}
.placeholder {
    border: 1px solid orange;
    background-color: #fffffd;
}
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title> Dashboard </title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="style.css">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js"></script>
</head>
<body>
    <div class="user-container">
        <div class="left">
            <label>Manager</label>
            <ul id="managers" class="group-list">
                <li class="user">Thomas</li>
                <li class="user">John</li>
                <li class="user">George</li>
            </ul>
        </div>

        <div class="right">
            <label>Workers</label>
            <ul id="workers" class="group-list">
                <li class="user">Steven</li>
                <li class="user">Jasmine</li>
            </ul>
        </div>
    </div>
    <script src="main.js"></script>
</body>
</html>
Sercan
  • 4,739
  • 3
  • 17
  • 36
1

So I just found this question. Using one of the answers there, I was able to get what I was trying to do by adding this to my fiddle's CSS:

#table1-wrapper * {
  pointer-events: none;
}

Check out the updated fiddle here.

ruttergod
  • 167
  • 9