1

Based on what was suggested earlier in my other question, I'm using a modified version of the suggestion to animate a drag movement. I'm aware the dragging part can be done using the html5 draggable attribute, but it has many limitations and side effects which I'm trying to avoid.

(function() {
    let targets = document.querySelectorAll('.draggable');
    let offsetX;
    let offsetY;
    Array.prototype.map.call(targets, (target) => {
        target.isMouseDown = false;
        target.initialOffsetLeft = target.offsetLeft;
        target.initialOffsetTop = target.offsetTop;
        target.addEventListener('mousedown', (e) => {
            if (e.buttons === 1) {
                target.style.zIndex = 10000
                target.style.position = 'relative';
                target.isMouseDown = true;
                offsetX = target.initialOffsetLeft + e.offsetX;
                offsetY = target.initialOffsetTop + e.offsetY;
            }
        });
        document.addEventListener('mouseup', (e) => {
            e.preventDefault();
            target.style.zIndex = null
            target.isMouseDown = false;
            target.style.left = 0 + 'px';
            target.style.top = 0 + 'px';
        });
        document.addEventListener('mousemove', (e) => {
            e.preventDefault();
            if (target.isMouseDown) {
                target.style.left = e.pageX - offsetX + 'px';
                target.style.top = e.pageY - offsetY + 'px';
            }
        });
    });
})();
 

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: 'Roboto', sans-serif
}

.draggable {
    display: flex;
    padding: 10px 12px;
    margin-bottom: 11px;
    border-radius: 5px;
    margin-right: 5px;
    background-color: #000000;
    cursor: grab;
    flex-grow:1;
    color: #ffffff;
    border: 1px solid #6c757d;
}

.group.card {
    margin-top: 30px;
    background-color: #000000;
    margin-right: 2%;
    margin-left: 2%;
    border: 1px solid #6c757d;
}
 

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet"/>
<div class="group card">
    <div class="card-body">
        <div class="draggable">
            Lorem ipsum dolor sit amet 1
        </div>
        <div class="draggable">
            Lorem ipsum dolor sit amet 2
        </div>
        <div class="draggable">
            Lorem ipsum dolor sit amet 3
        </div>
    </div>
</div>

As demonstrated in the snippet above, whenever any of the .draggable elements is dragged, it shifts to the bottom and right. I noticed this stops happening when doing any of: removing bootstrap or removing all margins from the below:

.group.card {
    /*margin-top: 30px;*/
    background-color: #000000;
    /*margin-right: 2%;*/
    /*margin-left: 2%;*/
    border: 1px solid #6c757d;
}

By doing so, the drag works as intended. Why is this happening and how to fix?

nlblack323
  • 155
  • 1
  • 10

1 Answers1

1

Create your own class name

This avoids overriding a bootstrap class. Here I have named your class "my-card-group".

(function() {
  let targets = document.querySelectorAll('.draggable');
  let offsetX;
  let offsetY;
  targets.forEach ((target) => {
    target.isMouseDown = false;
    target.initialOffsetLeft = target.offsetLeft;
    target.initialOffsetTop = target.offsetTop;
    target.addEventListener('mousedown', (e) => {
      if (e.buttons === 1) {
        target.style.zIndex = 10000
        target.style.position = 'relative';
        target.isMouseDown = true;
        offsetX = target.initialOffsetLeft + e.offsetX;
        offsetY = target.initialOffsetTop + e.offsetY;
      }
    });
    document.addEventListener('mouseup', (e) => {
      e.preventDefault();
      target.style.zIndex = null
      target.isMouseDown = false;
      target.style.left = 0 + 'px';
      target.style.top = 0 + 'px';
    });
    document.addEventListener('mousemove', (e) => {
      e.preventDefault();
      if (target.isMouseDown) {
        target.style.left = e.pageX - offsetX + 'px';
        target.style.top = e.pageY - offsetY + 'px';
      }
    });
  });
})();
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Roboto', sans-serif
}

.draggable {
  display: flex;
  padding: 10px 12px;
  margin-top: 0px;
  margin-left: 0px;
  margin-bottom: 11px;
  border-radius: 5px;
  margin-right: 5px;
  background-color: #000000;
  cursor: grab;
  flex-grow: 1;
  color: #ffffff;
  border: 1px solid #6c757d;
}

.my-card-group {
  margin-top: 30px;
  background-color: #000000;
  margin-right: 2%;
  margin-left: 2%;
  border: 1px solid #6c757d;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<div class="card group">
  <div class="my-card-group">
    <div class="card-body">
      <div class="draggable">
        Lorem ipsum dolor sit amet 1
      </div>
      <div class="draggable">
        Lorem ipsum dolor sit amet 2
      </div>
      <div class="draggable">
        Lorem ipsum dolor sit amet 3
      </div>
    </div>
  </div>
</div>
ProfDFrancis
  • 8,816
  • 1
  • 17
  • 26
  • what happens when a bootstrap class is overridden? – nlblack323 Apr 09 '23 at 04:36
  • Because the bootstrap class might contain multiple features that are (a) unknown to you and therefore difficult to debug (as you have seen), and (b) may change between versions, creating problems for you later. – ProfDFrancis Apr 09 '23 at 04:40
  • Why use `Array.prototype.map` at all if you're just throwing away the result? – Unmitigated Apr 09 '23 at 04:44
  • @ProfDFrancis The problem with this approach is the loss of bootstrap provided functionality which means I'll probably have to reinvent the card class. – nlblack323 Apr 09 '23 at 04:49
  • Oh, if you need that put the card class at another level, e.g. in an enclosing DIV. I have updated to do that. – ProfDFrancis Apr 09 '23 at 04:50
  • @Unmitigated no particular reason, it can be replaced with a for loop that does the same thing. – nlblack323 Apr 09 '23 at 04:51
  • @Unmitigated is quite right - here one should avoid `.map`, which gives the reader (future you!) an incorrect hint as to the purpose of the loop. It makes them think you are intending to return a result (perhaps with no side effects), when in fact you intend quite the opposite - side effects with no result. I have updated. – ProfDFrancis Apr 09 '23 at 04:54