Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
257 views
in Technique[技术] by (71.8m points)

html - Insert place holder between two div element using javascript Drag and Drop

I am trying to make my own custom drag and drop with html and Javascript drag and drop I have prepared a snippet:

/* draggable element */
var tempParentContainer = '';
var placeholder = document.createElement('div');
placeholder.className = 'drag-state-placeholder';

function enableDragDrop(containerClass, draggableClass) {
  let tempElem = document.querySelectorAll(draggableClass);
  tempElem.forEach(item => {
    item.addEventListener('dragstart', dragStart);
  });
  let tempContainer = document.querySelectorAll(containerClass);
  tempContainer.forEach(box => {
    box.addEventListener('dragenter', dragEnter)
    box.addEventListener('dragover', dragOver);
    box.addEventListener('dragleave', dragLeave);
    box.addEventListener('drop', drop);
  });
}

function dragStart(e) {
  tempParentContainer = e.target.parentNode;
  e.dataTransfer.setData('text/plain', e.target.id);
  setTimeout(() => {
    e.target.classList.add('hide');
    placeholder.style.height = e.target.clientHeight + 'px';
    tempParentContainer.appendChild(placeholder);
  }, 0);
  dragSrcEl = this;
  e.dataTransfer.effectAllowed = 'move';
}

function dragEnter(e) {
  e.preventDefault();
}

function dragOver(e) {
  e.preventDefault();
  e.currentTarget.appendChild(placeholder);

}

function dragLeave(e) {
  e.preventDefault();
}

function drop(e) {
  placeholder.remove();

  // get the draggable element
  const id = e.dataTransfer.getData('text/plain');
  const draggable = document.getElementById(id);

  // add it to the drop target
  e.currentTarget.appendChild(draggable);

  // display the draggable element
  draggable.classList.remove('hide');

}
.view_container {
  width: 100%;
}

.data-container {
  transform: scale(1);
  width: fit-content;
  background: rgb(255, 255, 255);
  display: flex;
  flex: 0 0 100%;
  height: 100%;
  min-width: 1px;
  overflow: auto;
  position: relative;
  margin: 0 10px;
  transform-origin: left top;
  transition: 0.3s;
}

.table-main {
  position: relative;
  border-collapse: separate;
  display: table;
  white-space: normal;
  width: 100%;
}

.table-head {
  display: table-header-group;
  vertical-align: middle;
}

.table-tr {
  display: table-row;
  vertical-align: inherit;
  height: 100%;
}

.table-body {
  display: table-row-group;
  vertical-align: middle;
}

.table-th {
  min-width: 330px;
  background-color: #607d8b;
  color: #fff;
  border-right: 2px solid rgb(255, 255, 255);
  border-bottom: 0px solid rgb(255, 255, 255);
  z-index: 3;
  padding: 0;
  height: 30px;
  line-height: 30px;
  vertical-align: top;
  display: table-cell;
  padding: 10px;
}

.table-td {
  display: table-cell;
  vertical-align: top;
  border-bottom: 4px solid rgb(255, 255, 255);
  border-right: 4px solid rgb(255, 255, 255);
  padding: 10px;
  min-height: 153px;
  background-color: rgb(243, 243, 243);
  min-width: 301px;
  max-width: 301px;
}

.drag-state-placeholder {
  background-color: #fbf9ed;
  border: 1px dashed rgb(177, 147, 59) !important;
}

.resourceDropLi {
  border: 1px solid #e7e7e7;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>

<body>
  <div class="view_container">
    <div class="data-container" id="board-container">
      <div class="table-main h-100">
        <div class="table-head">
          <div class="table-tr" id="laneContainer">
            <div class="table-th">
              <label>first</label>
            </div>
            <div class="table-th">
              <label>Second</label>
            </div>
            <div class="table-th">
              <label>third</label>
            </div>
            <div class="table-th">
              <label>fourth</label>
            </div>
            <div class="table-th">
              <label>fifth</label>
            </div>
            <div class="table-th">
              <label>sixth</label>
            </div>
            <div class="table-th">
              <label>seventh</label>
            </div>
            <div class="table-th">
              <label>eirght</label>
            </div>
          </div>
        </div>
        <div class="table-body" id="storyContainer">
          <div class="table-td ui-sortable">
            <div class="resourceDragDrop" draggable="true">
              <p>
                item f1
              </p>
            </div>
            <div class="resourceDragDrop" draggable="true">
              <p>
                item f2
              </p>
            </div>
            <div class="resourceDragDrop" draggable="true">
              <p>
                item f3
              </p>
            </div>
            <div class="resourceDragDrop" draggable="true">
              <p>
                item f4
              </p>
            </div>
          </div>
          <div class="table-td ui-sortable">
            <div class="resourceDragDrop" draggable="true">
              <p>
                item s1
              </p>
            </div>
            <div class="resourceDragDrop" draggable="true">
              <p>
                item s2
              </p>
            </div>
            <div class="resourceDragDrop" draggable="true">
              <p>
                item s3
              </p>
            </div>
          </div>
          <div class="table-td ui-sortable">
            <div class="resourceDragDrop" draggable="true">
              <p>
                item t1
              </p>
            </div>
            <div class="resourceDragDrop" draggable="true">
              <p>
                item t2
              </p>
            </div>
          </div>
          <div class="table-td ui-sortable">
            <div class="resourceDragDrop" draggable="true">
              <p>
                item f1
              </p>
            </div>
          </div>
          <div class="table-td ui-sortable">
            <div class="resourceDragDrop" draggable="true">
              <p>
                item fi1
              </p>
            </div>
            <div class="resourceDragDrop" draggable="true">
              <p>
                item fi2
              </p>
            </div>
            <div class="resourceDragDrop" draggable="true">
              <p>
                item fi3
              </p>
            </div>
            <div class="resourceDragDrop" draggable="true">
              <p>
                item fi4
              </p>
            </div>
            <div class="resourceDragDrop" draggable="true">
              <p>
                item fi5
              </p>
            </div>
          </div>
          <div class="table-td ui-sortable">
            <div class="resourceDragDrop" draggable="true">
              <p>
                item s1
              </p>
            </div>
          </div>
          <div class="table-td ui-sortable">
            <div class="resourceDragDrop" draggable="true">
              <p>
                item sev1
              </p>
            </div>
          </div>
          <div class="table-td ui-sortable">
            <div class="resourceDragDrop" draggable="true">
              <p>
                item e1
              </p>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</body>
<script type="text/javascript">
  $(document).ready(function() {
    enableDragDrop('.table-td', '.resourceDragDrop');
  });
</script>

</html>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I think the problem is that you only have 1 element with the ability to accept a drop: the container. That element cannot "tell" any more granular position than you've already done.

You should enable the singular items to handle dragover and/or drop, and create a rule, like: if the element is dropped on another element, then it goes before that element; if it's dropped on the container, then it goes at the end. This rule handles all positions in your list.

function dragStart({
  originalEvent: e
}) {
  e.dataTransfer.setData("text/plain", e.target.id)
  e.dataTransfer.effectAllowed = 'move'
}

jQuery(document).ready(function($) {
  $('.draggable').on('dragstart', dragStart);
  $('.droppable').on('dragover', function(e) {
    e.preventDefault()
    $(this).css('background', 'rgba(0, 0, 0, 0.25)')
  })
  $('.droppable').on('dragenter', function(e) {
    e.preventDefault()
    $(this).css('background', 'rgba(0, 0, 0, 0.25)')
  })
  $('.droppable').on('dragleave', function(e) {
    e.preventDefault()
    $(this).css('background', 'white')
  })
  $('.droppable').on('drop', function(e) {
    // stop propagation so you don't trigger drop more than once
    // if the drop zone is inside another drop zone
    e.stopPropagation()
    const draggedId = e.originalEvent.dataTransfer.getData("text")

    // here's the rule I wrote: if it's a column, then
    // the dragged item is appended, if it's not a column
    // then the dragged item is inserted before
    // the item it's dropped on
    if (!$(e.target).hasClass('column')) {
      $(e.target).before($(`#${ draggedId }`))
      $(this).parent().css('background', 'white')
    } else {
      $(e.target).append($(`#${ draggedId }`))
    }
    $(this).css('background', 'white')

  })
});
#container {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: space-around;
  background: white;
}

.column {
  border: 1px solid black;
  display: flex;
  flex-direction: column;
  padding: 8px 16px;
}

.draggable {
  border: 1px solid black;
  padding: 8px 16px;
  display: block;
  background: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container">
  <div class="column droppable">
    <div id="left-1" class="draggable droppable" draggable="true">
      left 1
    </div>
    <div id="left-2" class="draggable droppable" draggable="true">
      left 2
    </div>
  </div>
  <div class="column droppable">
    <div id="center-1" class="draggable droppable" draggable="true">
      center 1
    </div>
    <div id="center-2" class="draggable droppable" draggable="true">
      center 2
    </div>
  </div>
  <div class="column droppable">
    <div id="right-1" class="draggable droppable" draggable="true">
      right 1
    </div>
    <div id="right-2" class="draggable droppable" draggable="true">
      right 2
    </div>
  </div>
</div>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...