【问题标题】:dragend, dragenter, and dragleave firing off immediately when I drag当我拖动时,dragend、dragenter 和 dragleave 立即触发
【发布时间】:2012-12-21 15:24:11
【问题描述】:

我正在尝试制作一个可以通过拖放重新定位的元素列表。第一个元素 Box 1 在 100% 的时间里都能正常工作。有时第二个盒子可以工作,但其他盒子都不能按预期工作。一旦您开始拖动它们,它们似乎会立即触发所有拖动事件。

如果重要的话,我正在使用最新的 Chrome (v23)。

var $questionItems = $('.question-item');

$questionItems
  .on('dragstart', startDrag)
  .on('dragend', removeDropSpaces)
  .on('dragenter', toggleDropStyles)
  .on('dragleave', toggleDropStyles);


function startDrag(){
  console.log('dragging...');
  addDropSpaces();
}

function toggleDropStyles(){
  $(this).toggleClass('drag-over');
  console.log(this);
}


function addDropSpaces(){
  $questionItems.after('<div class="empty-drop-target"></div>');
  console.log('drop spaces added');
}

function removeDropSpaces(){
  $('.empty-drop-target').remove();
  console.log('drop spaces removed');
}

这是 HTML:

<div class="question-item" draggable="true">Box 1: Milk was a bad choice.</div>
<div class="question-item" draggable="true">Box 2: I'm Ron Burgundy?</div>
<div class="question-item" draggable="true">Box 3: You ate the entire wheel of cheese?</div>
<div class="question-item" draggable="true">Box 4: Scotch scotch scotch</div>

这是我的代码的 jsFiddle:http://jsfiddle.net/zGSpP/5/

【问题讨论】:

  • 你在使用 jquery 可拖动对象吗?您在哪里通过element.draggable(); 将元素初始化为可拖动的?
  • 真的很奇怪。您应该使用 JQueryUI 小部件事件作为解决方法:jqueryui.com/draggable
  • jbabey:HTML5 属性 'draggable=true'

标签: javascript jquery html drag-and-drop draggable


【解决方案1】:

刚刚遇到这个问题 - 这是一个 Chrome 错误,您不能在 dragStart 事件中操作 DOM,否则 dragEnd 会立即触发。我的解决方案原来是 - 使用 setTimeout() 并在你超时的函数内操作 DOM。

【讨论】:

  • 这对我有用。此外,我在一个页面变体上为我工作了相同的代码,但在另一个页面变体上没有,它们之间的唯一区别是被操纵元素的父元素在失败的情况下没有呈现(被隐藏)。
【解决方案2】:

【讨论】:

  • Chrome 32 中仍然出现此错误。
  • 在 Chrome 47 中似乎仍然遇到这个问题。
  • Chrome 55.0.2883.87 中仍然存在
  • 仍然在 Chrome 62 中:/
  • 链接的错误被标记为WontFix,因为自 2015 年以来无法重现。提交一个在 CodePen 或 jsFiddle 中重现的新错误可能是个好主意。
【解决方案3】:

不确定这是否是一个错误,但我认为当您在 dragstart 处理程序中更改 DOM 时问题就出现了。我认为第一个框起作用的原因与它的位置在 DOM 中的其他框之前以及当您更改 DOM 时,第一个框的位置(?)不受影响和拖放事件有关可靠地点火。

您需要对代码进行一些重构,并在 dragenter 事件处理程序中添加 dropSpaces。不过,您需要更改 addDropSpaces 方法以适应它会被多次调用的事实。

【讨论】:

    【解决方案4】:

    使用 jQuery 让生活更轻松。这正是你描述的你想要的,使用 jQueryUI。

    http://jqueryui.com/draggable/#sortable

    允许排序。代码:

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>jQuery UI Draggable + Sortable</title>
        <link rel="stylesheet" href="http://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css" />
        <script src="http://code.jquery.com/jquery-1.8.3.js"></script>
        <script src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
        <link rel="stylesheet" href="/resources/demos/style.css" />
        <style>
        ul { list-style-type: none; margin: 0; padding: 0; margin-bottom: 10px; }
        li { margin: 5px; padding: 5px; width: 150px; }
        </style>
        <script>
        $(function() {
            $( "#sortable" ).sortable({
                revert: true
            });
            $( "#draggable" ).draggable({
                connectToSortable: "#sortable",
                helper: "clone",
                revert: "invalid"
            });
            $( "ul, li" ).disableSelection();
        });
        </script>
    </head>
    <body> 
    <ul>
        <li id="draggable" class="ui-state-highlight">Drag me down</li>
    </ul>
    
    <ul id="sortable">
        <li class="ui-state-default">Item 1</li>
        <li class="ui-state-default">Item 2</li>
        <li class="ui-state-default">Item 3</li>
        <li class="ui-state-default">Item 4</li>
        <li class="ui-state-default">Item 5</li>
    </ul>
    
    </body>
    </html> 
    

    另见:http://jqueryui.com/sortable/

    尝试手动添加事件,很长的路要走,比如:

    $questionItems[0].on('dragstart', startDrag); 
    $questionItems[0].on('dragend', removeDropSpaces) 
    $questionItems[0].on('dragenter', toggleDropStyles) 
    $questionItems[0].on('dragleave', toggleDropStyles); 
    $questionItems[1].on('dragstart', startDrag); 
    $questionItems[1].on('dragend', removeDropSpaces) 
    $questionItems[1].on('dragenter', toggleDropStyles)     
    $questionItems[1].on('dragleave', toggleDropStyles); 
    

    等等。只是为了看看效果?

    【讨论】:

    • 我真的需要做的不仅仅是对列表进行排序,例如当一个项目被拖到另一个项目的顶部时,它们会被分组。
    • 你仍然可以,你只需通过 jQuery 来处理事件。 $( ".selector" ).on( "拖动", function( event, ui ) {} );和 $( ".selector" ).on( "dragstart", function( event, ui ) {} );它有回调,所以你仍然可以使用你已经构建的函数。
    • 另外,您是否尝试过手动将每个 .on() 添加到每个单个框项?只是为了看看效果?
    • 类似 $questionItems[0].on('dragstart', startDrag); $questionItems[0].on('dragend', removeDropSpaces) $questionItems[0].on('dragenter', toggleDropStyles) $questionItems[0].on('dragleave', toggleDropStyles); $questionItems[1].on('dragstart', startDrag); $questionItems[1].on('dragend', removeDropSpaces) $questionItems[1].on('dragenter', toggleDropStyles) $questionItems[1].on('dragleave', toggleDropStyles);等等只是为了看看效果?
    • 是的,我要试试 jQ UI 的可排序。在这一点上,我只想让它工作。很高兴知道我也可以参与这些活动。谢谢。
    【解决方案5】:

    改变这个功能

    function addDropSpaces()
    {
      $(this).after('<div class="empty-drop-target"></div>');
    }
    

    在您的版本中,您在每个 $questionItems 之后添加该 div。

    【讨论】:

    • 目标是在每个box后面加空格
    • 这似乎与错误有关,但我确实希望在每个 .question-item 之后注入 div,而不仅仅是当前的。
    【解决方案6】:

    您需要防止“事件”冒泡,以免引发其他事件。见https://developer.mozilla.org/en-US/docs/DOM/event.stopPropagation

    对于 startDrag、toggleDropStyles、removeDropSpaces 函数,你可以这样写:

    function startDrag(ev) {
       ev.stopPropagation();
       ... your code here ...
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-07
    • 2011-02-07
    • 1970-01-01
    • 1970-01-01
    • 2014-05-25
    • 2015-05-03
    • 1970-01-01
    相关资源
    最近更新 更多