2010-06-22 138 views
3

请参阅代码here on jsbin.我基本上试图创建一系列开关。每个填充的红色方块都可以上下拖动。底部的红色轮廓是放置区域。当一个正方形被拖过一个有资格接受它的放置区时,放置区应该变成粉红色。jQuery拖/放范围问题

这个代码有两个问题。其中之一是,虽然触发器的运动被限制在y轴上,但它们仍然可以落在任何放置区域上。点击并拖动切换按钮并滑动底部行,即使切换保持原位,您也会看到拖放区变成粉红色。

这导致第二个问题。为了解决这个问题,我尝试使用范围选项,该选项将拖放组合起来。拖动只能放在具有相同范围的拖放区域上。在上面的例子中,添加范围的行被注释掉了。每个拖放的范围都是“默认”。

如果您取消注释这两行(如果您是jsbin的新手,请单击右上角的标签,然后在更改后单击预览),您会看到,不是将每个拖动限制到一个拖放区域,而是可以不再落在任何拖放区域。回调函数永远不会触发。

为了方便起见,这里是实施例的一部分的javascript:

$(document).ready(function() { 
    var draggables = $('div.dragMe'), 
    droppables = $('div.dropMe'); 

    draggables.draggable(
    { 
     axis: 'y', 
     containment: 'parent' 
    }); 

    droppables.droppable(
    { 
     hoverClass: 'dropped', 
     drop: dropCallBack 
    }); 

    draggables.each(function(index) { 
     //$(this).draggable('option', 'scope', ''+index); 
     //droppables.eq(index).droppable('option', 'scope', ''+index); 

     $(this).text($(this).draggable('option', 'scope')) 
     droppables.eq(index).text(droppables.eq(index).droppable('option', 'scope')); 
    }); 

    function dropCallBack(e, ui) { 
     alert('Dropped!'); 
    } 
}); 
+0

我不想给防解决方案,但你有没有考虑,而不是拖放,只是触发与开关mouseDown'.mousedown(function)'事件?在我看来,它的可用性更好(作为最小wtf的路径),并与移动设备相处得更好。 – 2010-06-22 21:40:11

+0

有时反解决方案是最好的解决方案!好点子。如果我得到这个工作,我总是可以做到这一点。最初的想法是尝试设计一些使用物理类比进行交互的导航元素。当它们被释放时,开关应当“卡扣”到位,就好像有一个制动器,只是还没有写入那个零件。 – jasongetsdown 2010-06-22 21:59:07

回答

9

经由选项功能设置一个可投放的scope选项时有jQuery中的一个错误。 jQuery维护一个包含所有已注册排序的数组(现在让我们称它为S),其中每个键都是一个特定的作用域。将可拖动元素拖放到可拖放元素中时,jQuery将检查可拖动元素的范围属性,并检查您尝试拖动的拖放元素是否存在于S[scope]中。如果不是,则意味着您要拖入的拖放与拖动不在同一范围内。

问题是,当您通过执行.droppable('option', 'scope', ...)更改范围选项时,数组S未更新。其他所有内容(就我所见)已正确更新(实际jQuery对象的选项属性等),导致在通过.droppable('option', 'scope')获取范围选项时返回“正确”结果。

我发现了一些其他人有相同的问题,没有解决方案出现了,这个问题出现了,当我搜索解决方案("jquery droppable scope option"),所以我认为它可能是有用的,直到它提供一个临时解决方案是固定的。我做了一个扩展功能,对于可能与其他选项的冲突没有很好的测试,但至少这是一个开始。 $.ui.ddmanager.droppables是我以前称为S的数组。

jQuery.fn.extend({ 

    setDroppableScope: function(scope) { 
     return this.each(function() { 
      var currentScope = $(this).droppable("option","scope"); 
      if (typeof currentScope == "object" && currentScope[0] == this) return true; //continue if this is not droppable 

      //Remove from current scope and add to new scope 
      var i, droppableArrayObject; 
      for(i = 0; i < $.ui.ddmanager.droppables[currentScope].length; i++) { 
       var ui_element = $.ui.ddmanager.droppables[currentScope][i].element[0]; 

       if (this == ui_element) { 
        //Remove from old scope position in jQuery's internal array 
        droppableArrayObject = $.ui.ddmanager.droppables[currentScope].splice(i,1)[0]; 
        //Add to new scope 
        $.ui.ddmanager.droppables[scope] = $.ui.ddmanager.droppables[scope] || []; 
        $.ui.ddmanager.droppables[scope].push(droppableArrayObject); 
        //Update the original way via jQuery 
        $(this).droppable("option","scope",scope); 
        break; 
       } 
      } 
     }); 
    } 
}); 

你的例子,然后像

draggables.each(function(index) { 
    $(this).draggable('option', 'scope', ''+index); 
    droppables.eq(index).setDroppableScope(''+index); 

    $(this).text($(this).draggable('option', 'scope')) 
    droppables.eq(index).text(droppables.eq(index).droppable('option', 'scope')); 
}); 

Here's the updated jsbin

+1

平反!表现完全如预期。感谢您深入了解一个狡猾的错误,并提供代码来修复它。正如你所说,它报告了正确的范围,但后来就表示不在乎! – jasongetsdown 2010-06-23 14:14:03

+0

这是2013年,这个错误仍然存​​在:( – pckben 2013-08-29 19:00:00