只下降到看到的元素

我有以下内容:

我正在尝试将其设置为当您拖动项目时,它只会被删除到您可以看到的div元素,并且不会被覆盖。

所以我使用了这个js:

$(".draggable").draggable({ helper: "clone" }) $("#bottom, .draggable").droppable({ drop: function(event, ui) { var $this = $(this), $dragged = $(ui.draggable); $this.append($dragged.clone()); }, hoverClass: "dragHover" })​ 

但它会丢弃两个地方的元素,即使只有一个掉落区域可见!

我如何修复它以便不会发生这种情况?

小提琴: http : //jsfiddle.net/maniator/Wp4LU/


额外的信息, 无需小提琴重新创建页面:

HTML:

  
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet

CSS:

 .draggable { border: 1px solid green; background: white; padding: 5px; } .dragHover{ background: blue; } #top { height: 500px; overflow-y: scroll; } #bottom { height: 150px; overflow-y: scroll; border: red solid 4px; } 

尝试使用accept函数进行设置。 工作演示。

 $("#bottom, .draggable").droppable({ drop: function(event, ui) { var $this = $(this), $dragged = $(ui.draggable); $this.append($dragged.clone()); }, accept: function () { var $this = $(this), divTop= $("#top"); if ($this.is(".draggable")) { return $this.offset().top < divTop.offset().top + divTop.height() ; } return true; }, hoverClass: "dragHover" })​;​ 

如果我找对你 – 这个应该解决你的问题 – http://jsfiddle.net/Wp4LU/60/你也可以编写自定义接受functionhttp://jqueryui.com/demos/droppable/#option-accept

码:

 var draggableList = $('#top'); $(".draggable").draggable({ helper: "clone" }); $("#bottom, .draggable").droppable({ drop: function(event, ui) { var $this = $(this), $dragged = $(ui.draggable); if ($this.hasClass("draggable")) { if ($this.position().top >= draggableList.height() || $this.position().top + $this.outerHeight() >= draggableList.height()) return; } $this.append($dragged.clone()); }, hoverClass: "dragHover" })​;​ 

根据源代码(jquery.ui.droppable.js),drop操作将搜索每个符合条件的dropable,并将drop函数应用于与其相交的每一个:

 drop: function(draggable, event) { var dropped = false; $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { if(!this.options) return; if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) dropped = this._drop.call(this, event) || dropped; 

(旧版本的最后一个“OR”条件被反转,所以它只适用于一个droppable。使用jQuery 1.5.2 / jQuery UI 1.8.9尝试你的小提琴,并看到它只下降到一个元素,虽然“错误的“一个…”

目前在$.ui.intersect函数中实现的每个容差模式只考虑(x,y)坐标:

 switch (toleranceMode) { case 'fit': return (l <= x1 && x2 <= r && t <= y1 && y2 <= b); break; case 'intersect': return (l < x1 + (draggable.helperProportions.width / 2) // Right Half && x2 - (draggable.helperProportions.width / 2) < r // Left Half && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half break; ... 

因此,除非有人添加z-index感知容差模式,否则您唯一的选择是以某种方式解决问题。 我建议先将每个可放置的候选者添加到一个集合中,当它下降时,只选择与屏幕“最接近”的那个:

 $("#bottom, .draggable").droppable({ over: function(event, ui) { if ( !ui.draggable.data("drop-candidates") ) ui.draggable.data("drop-candidates",[]); ui.draggable.data("drop-candidates").push(this); }, out: function(event, ui) { var that = this, candidates = ui.draggable.data("drop-candidates") || []; ui.draggable.data("drop-candidates", $.grep(candidates, function(e) { return e != that; }); }, drop: function(event, ui) { var $this = $(this), $dragged = $(ui.draggable); var candidates = $.data("drop-candidates").sort(closestToScreen); if ( candidates[0] == this ) $this.append($dragged.clone()); }, hoverClass: "dragHover" })​ 

现在,实现closestToScreen比较器是棘手的部分。 W3C CSS规范描述了渲染引擎应该如何对要绘制的元素进行排序,但到目前为止我还无法找到访问这些信息的简单方法。 我也在这里问过这个问题 ,也许有人会找到一个好方法。


PS如果修改jQuery UI源一个选项,你可以尝试使用document.getElementFromPoint实现z-index感知容差模式,因为这个问题的答案表明:

 var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width, y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height; switch (toleranceMode) { ... case 'z-index-aware': return document.elementFromPoint(x1,y1) == droppable; break; 

(这将确保只有可拖动的左上角正下方的元素才会被视为“足够好”作为放置目标 - 不理想,但比我们到目前为止更好;类似的解决方案可以适用于使用改为鼠标指针坐标)

并且,不,你不能将此方法与之前提供的解决方法一起使用:在发生丢弃的那一刻, 拖动帮助器是最接近屏幕的元素...( 编辑:噢哦!如果作为容差模式实现,出于同样的原因......)

如果您只想放置元素,可以看到您可以更改选择器:

 $(".draggable:visible").draggable({ helper: "clone" }); $("#bottom, .draggable:visible").droppable({ drop: function(event, ui) { var $this = $(this), $dragged = $(ui.draggable); $this.append($dragged.clone()); }, hoverClass: "dragHover" })​; 

或者当你隐藏一个元素时,用其他东西改变它的’可拖动类。