【问题标题】:HTML5 UL LI DraggableHTML5 UL LI 可拖动
【发布时间】:2012-09-02 04:21:03
【问题描述】:

我有一个无序列表:

  • 列表项 1
  • 列表项 2
  • 列表项 3
  • 列表项 4
  • 列表项 5

使用此代码实现:

<ul>
  <li>List item 1</li>
  <li>List item 2</li>
  <li>List item 3</li>
  <li>List item 4</li>
  <li>List item 5</li>
</ul>

现在,我希望它是可拖动的。例如,如果我将“List item 5”向上拖动,我可以将它放在“List item 2”和“List item 3”之间,它会变成第三个。

我想在没有 jQuery 的情况下做到这一点,只需简单的 Javascript。另外,我想使用原生 HTML5 draggable="true"。任何帮助将不胜感激。

【问题讨论】:

    标签: html drag-and-drop html-lists draggable


    【解决方案1】:

    此代码将解决您的问题。使用MDN 重做示例 试试这个jsfiddle.net

    HTML 5

    <ul>
      <li class="dropzone" id='0' draggable="true">List item 1</li>
      <li class="dropzone" id='1' draggable="true">List item 2</li>
      <li class="dropzone" id='2' draggable="true">List item 3</li>
      <li class="dropzone" id='3' draggable="true">List item 4</li>
      <li class="dropzone" id='4' draggable="true">List item 5</li>
    </ul>
    

    纯 JS

    let dragged;
    let id;
    let index;
    let indexDrop;
    let list;
    
      document.addEventListener("dragstart", ({target}) => {
          dragged = target;
          id = target.id;
          list = target.parentNode.children;
          for(let i = 0; i < list.length; i += 1) {
            if(list[i] === dragged){
              index = i;
            }
          }
      });
    
      document.addEventListener("dragover", (event) => {
          event.preventDefault();
      });
    
      document.addEventListener("drop", ({target}) => {
       if(target.className == "dropzone" && target.id !== id) {
           dragged.remove( dragged );
          for(let i = 0; i < list.length; i += 1) {
            if(list[i] === target){
              indexDrop = i;
            }
          }
          console.log(index, indexDrop);
          if(index > indexDrop) {
            target.before( dragged );
          } else {
           target.after( dragged );
          }
        }
      });
    

    【讨论】:

    • 只有代码的答案通常被认为是低质量的。您应该考虑添加说明此代码解决问题的原因和方式。
    【解决方案2】:
    <ul id="parent">
    
        <li class="parent">List item 1</li>
    
        <li class="parent">List item 2</li>
    
        <li class="parent">List item 3</li>
    
        <li class="parent">List item 4</li>
    
        <li class="parent">List item 5</li>
    </ul>
    

    试试这个js

        var dragSrcEl = null;
    
        function handleDragStart(e) {
            // Target (this) element is the source node.
            this.style.opacity = '0.4';
    
            dragSrcEl = this;
    
            e.dataTransfer.effectAllowed = 'move';
            e.dataTransfer.setData('text/html', this.innerHTML);
        }
    
        function handleDragOver(e) {
            if (e.preventDefault) {
                e.preventDefault(); // Necessary. Allows us to drop.
            }
    
            e.dataTransfer.dropEffect = 'move';  // See the section on the DataTransfer object.
    
            return false;
        }
    
        function handleDragEnter(e) {
            // this / e.target is the current hover target.
            this.classList.add('over');
        }
    
        function handleDragLeave(e) {
            this.classList.remove('over');  // this / e.target is previous target element.
        }
    
        function handleDrop(e) {
            // this/e.target is current target element.
    
            if (e.stopPropagation) {
                e.stopPropagation(); // Stops some browsers from redirecting.
            }
    
            // Don't do anything if dropping the same column we're dragging.
            if (dragSrcEl != this) {
                // Set the source column's HTML to the HTML of the column we dropped on.
                dragSrcEl.innerHTML = this.innerHTML;
                this.innerHTML = e.dataTransfer.getData('text/html');
            }
    
            return false;
        }
    
        function handleDragEnd(e) {
            // this/e.target is the source node.
    
            [].forEach.call(cols, function (col) {
                col.classList.remove('over');
            });
        }
    
        var cols = document.querySelectorAll('#parent .parent');
        [].forEach.call(cols, function (col) {
            col.addEventListener('dragstart', handleDragStart, false);
            col.addEventListener('dragenter', handleDragEnter, false)
            col.addEventListener('dragover', handleDragOver, false);
            col.addEventListener('dragleave', handleDragLeave, false);
            col.addEventListener('drop', handleDrop, false);
            col.addEventListener('dragend', handleDragEnd, false);
        });
    

    【讨论】:

    • 我看到它是一个类似的例子,但有实时代码平台。如果有人需要,请参考。 codepen.io/retrofuturistic/pen/tlbHE
    • @FredricCliver 谢谢你的例子。是否可以添加自动滚动?当我们到达屏幕边界时它不会滚动(在 safari 上)。
    【解决方案3】:

    如果你用 Firefox 进行测试,注意它还需要在拖动操作中发送一些数据:

    function handleDragStart(e) {
      e.dataTransfer.effectAllowed = 'move';
      e.dataTransfer.setData('text/html', e.target.innerHTML);
    }
    
    myLi.addEventListener('dragstart', handleDragStart, false);
    

    否则,您将看不到被拖动内容的幻影...

    【讨论】:

      【解决方案4】:

      属性“draggable”只允许拖动元素。您需要实现 DnD 侦听器并实现 drop 事件以进行所需的更改。

      你会在这个例子中找到你想要解决的同样的问题:http://www.html5rocks.com/en/tutorials/dnd/basics/

      在示例中,他们为 A、B 和 C 列实现拖放。用户可以通过 DnD 更改顺序。

      【讨论】:

        【解决方案5】:

        只需将 draggable="true" 添加到您的 li 元素即可。

        <ol ondragstart="">
        <li draggable="true" data-value="data1">List Item 1</li>
        <li draggable="true" data-value="data2">List Item 2</li>
        <li draggable="true" data-value="data3">List Item 3</li>
        </ol>
        

        【讨论】:

        • 这只给出了拖拽的外观。当您释放点击时,它会弹回。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-11-20
        • 2016-09-01
        • 2012-10-20
        • 2014-10-20
        • 2018-11-10
        • 2013-04-06
        • 2012-08-25
        相关资源
        最近更新 更多