我想使用拖动来选择功能,而不是选择屏幕上的一个正方形区域,然后选择该正方形内的任何内容,我想选择我最初的选择和我释放点击之间的任何元素。
这是最好的视觉解释。我不想这样做:
相反,我想这样做:
我想使用拖动来选择功能,而不是选择屏幕上的一个正方形区域,然后选择该正方形内的任何内容,我想选择我最初的选择和我释放点击之间的任何元素。
这是最好的视觉解释。我不想这样做:
相反,我想这样做:
如果您的框位于列表结构(ul 或 ol)内,您可以检测鼠标拖过的第一个和最后一个框,并使用它们的标识符作为第一个和最后一个索引来遍历集合,以便在必要时突出显示。
After the previous failed attempt I've now come up with a working solution. It would appear that jQuery UI selectable is not suitable, as it uses that rectangular selection, so I've had to roll my own.
In the example below (see jsFiddle for full code), the selectable elements are a.date
. These elements should have position: relative
set.
Firstly, I append a child element with class .drag-proxy
. This is positioned absolutely, and covers the same area as the child. It's got no content so it sits transparently above.
These proxy elements are made draggable and droppable.
When the element is dragged and dropped onto another element, it is moved back to its starting point (so that subsequent selections work).
Then we cycle through all the proxy elements, indentifying the elements in the selection range, and then setting a class on the parent a.date
element.
$(function() {
$('a.date').each(function() {
$(this).append('<a href="' + $(this).attr('href') + '" class="drag-proxy" id="proxy_' + $(this).attr('id') + '"></a>');
});
var $currentlyDragged;
$('.drag-proxy').draggable({
start: function() {
$currentlyDragged = $(this);
},
// Once drag has finished, return the drag-proxy to its original position
stop: function() {
$(this).css('top', 0).css('left', 0);
$currentlyDragged = null;
}
});
$('.drag-proxy').droppable({
over: function(e, ui) {
var from_id = $currentlyDragged.attr('id');
var to_id = $(this).attr('id');
$('.date').removeClass('selected');
var started = selecting = false;
$('.drag-proxy').each(function() {
var $this = $(this);
var this_id = $this.attr('id');
if (started === false && (this_id == from_id || this_id == to_id)) {
selecting = true;
}
if (selecting) {
$this.parent().addClass('selected');
if (started === true && (this_id == from_id || this_id == to_id)) {
selecting = false;
}
}
if (started === false && (this_id == from_id || this_id == to_id)) {
started = true;
}
});
},
drop: function(e, ui) {
// do whatever you need to do once selection ends
}
});
});
See the jsFiddle for the full example.
请注意 - 这个答案是不正确的,但我将其保留,因为它显示了 jQuery UI 可选可以做的程度,以及为什么它不起作用。请参阅已接受的答案以获取自定义滚动的有效解决方案。
感谢 Frédéric Hamidi 提供指向该论坛主题的指针,我已经解决了这个问题,如下所示。我在问题中没有提到的额外要求是可选元素必须位于多个容器中(最终这将是日历中的日期,包含在各个月份中)。
给定以下 HTML:
<div id="selectable">
<div>
<span id="a1">1</span>
<span id="a2">2</span>
<span id="a3">3</span>
<span id="a4">4</span>
<span id="a5">5</span>
<span id="a6">6</span>
<span id="a7">7</span>
<span id="a8">8</span>
<span id="a9">9</span>
<span id="a10">10</span>
</div>
<div>
<span id="b1">1</span>
<span id="b2">2</span>
<span id="b3">3</span>
<span id="b4">4</span>
<span id="b5">5</span>
<span id="b6">6</span>
<span id="b7">7</span>
<span id="b8">8</span>
<span id="b9">9</span>
<span id="b10">10</span>
</div>
</div>
然后这个javascript解决了它。请注意,链接的帖子使用slice(start, end)
,但由于我的多个容器要求,我不能这样做。所以我用 , 遍历了所有可排序的元素,并根据我们是否到达第一个元素和尚未到达最后一个元素进行each()
切换。selecting
我设置filter: 'span'
是为了防止其他子元素#selectable
变得可选。
$(function() {
var rangeSelecting = function(event, ui) {
var start = $(".ui-selecting", this).first();
var end = $(".ui-selecting", this).last();
var selecting = false;
$(this).find('span').removeClass("range-selecting").each(function() {
var $this = $(this);
var this_id = $this.attr('id');
if (start.attr('id') === this_id) selecting = true;
if (selecting) $this.addClass('range-selecting');
if (end.attr('id') === this_id) selecting = false;
});
}
$("#selectable").selectable({
filter: 'span',
selecting: rangeSelecting,
unselecting: rangeSelecting,
stop: function(event, ui) { $(".range-selecting", this).addClass("ui-selected").removeClass("range-selecting"); }
});
});</p>
有关工作示例,请参阅此jsfiddle 。