在jQuery UI Selectable中启用Shift-Multiselect

24

我想通过按住shift键来启用jQuery UI选择表格中的多选功能。

如果在鼠标单击时按下shift键,我应该执行以下操作:

  • 获取最顶部已选元素
  • 获取单击的元素
  • 选择它们之间的所有元素

但是我找不到一种干净的方法来实现这个功能...

目前,在可选择配置中,我有以下内容:

start: function(e)
        {
            var oTarget = jQuery(e.target);
            if(!oTarget.is('tr')) oTarget = oTarget.parents('tr');
        }

所以,oTarget 是被点击的元素(而 e.currentTarget 是整个表格),但现在怎么办?我该如何找到已经选择了哪些元素,以一种可以告诉我点击的元素是否在已选元素之上或之下的方式,并选择它们之间的所有内容?

我现在是这样解决的,添加到可选择元素中:

jQuery(table).mousedown(function(e)
    {
        //Enable multiselect with shift key
        if(e.shiftKey)
        {
            var oTarget = jQuery(e.target);
            if(!oTarget.is('.ui-selectee')) oTarget = oTarget.parents('.ui-selectee');

            var iNew = jQuery(e.currentTarget).find('.ui-selectee').index(oTarget);
            var iCurrent = jQuery(e.currentTarget).find('.ui-selectee').index(jQuery(e.currentTarget).find('.ui-selected'));

            if (iCurrent < iNew) {
                iHold = iNew;
                iNew = iCurrent;
                iCurrent = iHold;
            }

            if(iNew != '-1')
            {
                jQuery(e.currentTarget).find('.ui-selected').removeClass('ui-selected');
                for (i=iNew;i<=iCurrent;i++) {
                    jQuery(e.currentTarget).find('.ui-selectee').eq(i).addClass('ui-selected');
                }
                e.stopImmediatePropagation();
                e.stopPropagation();
                e.preventDefault();
                return false;
            }
        }
    }).selectable(...)
3个回答

30

你可以像这样不使用插件来完成:

var prev = -1; // here we will store index of previous selection
$('tbody').selectable({
    selecting: function(e, ui) { // on select
        var curr = $(ui.selecting.tagName, e.target).index(ui.selecting); // get selecting item index
        if(e.shiftKey && prev > -1) { // if shift key was pressed and there is previous - select them all
            $(ui.selecting.tagName, e.target).slice(Math.min(prev, curr), 1 + Math.max(prev, curr)).addClass('ui-selected');
            prev = -1; // and reset prev
        } else {
            prev = curr; // othervise just save prev
        }
    }
});

这里是实时演示:http://jsfiddle.net/mac2000/DJFaL/1/embedded/result/


这是一个非常干净和基本的实现,我很喜欢它。通过添加一些额外的检查,也可以轻松地将其扩展为多重选择(使用 shift-click 部分多次)。谢谢! - arvidkahl
1
如果您曾经在表格中“拖动”第一个选择,那么它会表现出一些奇怪的行为。拖动会导致事件发生在td而不是tr上,因此索引会变成一个更高的值。 - Matt
1
可选择事件对 tdtr 都会触发,因此您可以在 ui.selected.tagName === 'TD' 上返回。 - Matt
5
你好!我发现了这个内容,如果将 prev 设置为 0 并且不重置它(删除 prev = -1; 这行),会使它更像“文件系统”,即允许重复多选,如果你向已选择的元素进行 shift-select 操作,则会取消选择,并且在没有选择任何元素时从头开始选择。我没看到任何缺点,所以也许对某些人很有用。 - valepu
1
很棒的解决方案,结合@valepu的建议使其更加完美! - greg

13

我为此功能编写了一个简单的插件。它不依赖于jQuery UI Selectable插件,据我所知,可以很好地与其一起使用。

您可以在这里找到插件代码和简单示例:http://jsfiddle.net/bMgpc/170/

下面将编写简单的描述。

基本用法:

$('ul').multiSelect();

如果你按住"Ctrl"或"Command键",那么你可以逐个选择/取消选择元素。

ul - 包含要选择的内部元素的父元素。

有许多选项可用:

  • keepSelection - true|false - 相当重要的标志。如果设置为true(默认值),则如果您单击已选元素上,则选择不会被清除(就像在带有多个prop的情况下一样)
  • multiselect - true|false - 如果为false,则只能选择一个元素
  • selected - 'selected' - 将添加到选定元素中的类
  • filter: - ' > *' - 我们要选择哪些元素
  • unselectOn - false|'selector' - 如果设置,则如果单击设置选择器,则选择将被删除
  • start: false|function - 开始时的回调函数
  • stop: false|function - 停止时的回调函数
  • unselecting: false|function - 在设置了 "unselectOn" 选项后单击时的回调函数

这是一个开发版本的插件,因此请小心使用。


谢谢,我没有直接使用它,但是我可以从源代码中得到所需的工作思路。 :) - bardiir
@bardiir,这是最好的方法。当我编写这段代码时,我有非常具体的想法,所以为了您自己的目的重新编写它是最好的选择。 - Kane Cohen

5
在查找使用jQuery UI的Selectable功能时,我无法找到解决此问题的方案。因此,我编写了一个解决方案。它基本上利用Selectable的选中/取消选中回调来管理DOM状态,同时仍然遵循标准Selectable API的回调。它支持以下用例:
  • 单击列表中的一个元素(也可以使用shift +单击、cntl +单击或单击+拖动)
  • Shift +单击列表中的另一个元素
  • 两个端点之间的所有元素都变为选定状态

表格的用法:

$('table').shiftSelectable({filter: 'tr'});

几点说明:(1)目前只支持兄弟元素;(2)它会将配置选项传递给表格示例和可选择方法,如您所见;(3)我很喜欢underscore.js,因此即使对于这个项目来说它并非必需品,也使用了它。如果您不想使用这个很棒的库,可以随意更换它的简单检查和扩展。不,我与underscore.js没有关联。:)

表格示例

列表示例

希望对其他人有所帮助!干杯。

这对我非常有效。唯一缺少的是“拖动选择范围”框,它在jquery-ui#selectable上确实显示出来。但我相信这很容易解决。谢谢! - JeanMertz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接