使用 JQuery Multisortable 加过滤列表
Using JQuery Multisortable plus filtering a list
那么,问题来了...
我有两个列表。我希望用户能够从左侧的一个列表中拖动以在右侧构建一个新列表,但也想让他们能够过滤左侧列表。左边的列表可能很长,所以我也希望他们能够多 select 和拖动。
对于多select我正在使用jQuery multisortable
这里 jsFiddle 展示了我正在努力实现的目标。
最终目标是为构建的列表构建逗号分隔的字符串。如果您在“a”上过滤列表,multiselect 结果,您会看到所有列表项都被拖到正确的列表中 - 甚至是被过滤器隐藏的过滤项目之间的那些 - 如何做我绕过这个?
感谢任何帮助!
以下示例使用 Bootstrap 4
编辑:查看 DOM 我可以看到 JQuery 过滤器在 SHIFT 键用于多个 select 项,因此尝试添加选项...
items: '> li:not("multiselectable-shift")'
...对于可排序的,仍然没有快乐。使用 control 键或 meta kay 都可以,只是 shift 键有问题。
<script>
jQuery(function($) {
$('ul.connectedSortable').multisortable({
selectedClass: 'highlight'
});
$('ul#sortable1').sortable({
connectWith: 'ul#sortable2',
update: function() {
callListIds = "";
$("ul#sortable2 li").each(function() {
callListIds += $(this).attr("id") + ",";
})
callListIds = callListIds.replace(/,\s*$/, "");
$("#listIdResult").html(callListIds);
}
});
$('ul#sortable2').sortable({
connectWith: 'ul#sortable1',
update: function() {
callListIds = "";
$("ul#sortable2 li").each(function() {
callListIds += $(this).attr("id") + ",";
})
callListIds = callListIds.replace(/,\s*$/, "");
$("#listIdResult").html(callListIds);
}
});
});
// Search field
$(document).ready(function() {
$("#search").on("keyup", function() {
var value = $(this).val().toLowerCase();
$("#sortable1 li").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
}); </script>
.highlight {
background-color: #AABFF3;
}
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet" />
<script src="https://rawgithub.com/shvetsgroup/jquery.multisortable/master/src/jquery.multisortable.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" />
<style>
.highlight { background-color: #AABFF3; }
</style>
</head>
<body>
<input type="hidden" name="callListIds" id="callListIds" value="">
<div class="d-flex justify-content-center w-90 mx-auto d-block pt-5">
<div class="container w-40 float-left">
<input type="search" class="form-control" name="search" id="search" placeholder="search...">
<ul id="sortable1" class="connectedSortable list-group" style="min-height:100%">
<li id="ls1" class="list-group-item w-100 p-1">ABC</li>
<li id="ls2" class="list-group-item w-100 p-1">DEF</li>
<li id="ls3" class="list-group-item w-100 p-1">AGH</li>
<li id="ls4" class="list-group-item w-100 p-1">HIJ</li>
<li id="ls5" class="list-group-item w-100 p-1">KLM</li>
<li id="ls6" class="list-group-item w-100 p-1">AOP</li>
</ul>
</div>
<div class="container w-40 float-right border ml-1">
<ul id="sortable2" class="connectedSortable list-group" style="min-height:100%">
</ul>
</div>
</div>
<p class="p-2 text-center">Resulting comma delimited String:
<span id="listIdResult"></span></p>
</body
基本上,代码中存在逻辑问题 [https://github.com/shvetsgroup/jquery.multisortable/blob/master/src/jquery.multisortable.js 44-56]:
if (e.shiftKey) {
var last_shift_range = parent.find('.multiselectable-shift');
last_shift_range.removeClass(options.selectedClass).removeClass('multiselectable-shift');
var shift_range;
if (prevIndex < myIndex) {
shift_range = item.prevUntil('.multiselectable-previous').add(prev).add(item);
}
else if (prevIndex > myIndex) {
shift_range = item.nextUntil('.multiselectable-previous').add(prev).add(item);
}
shift_range.addClass(options.selectedClass).addClass('multiselectable-shift');
}
基本上,它在创建范围时忽略了 items
选项。所以当你这样配置时:
$(el).multiselect({
items: "li:visible"
});
Shift 单击事件将创建一个范围并包括所有列表项,无论它们是否可见。我尝试了一些解决方法并将 Fiddle 改进为:
https://jsfiddle.net/Twisty/sjg5u1ty/56/
JavaScript
jQuery(function($) {
$.fn.filterList = function(t) {
console.log("Filter For:", t);
$("> li", this).each(function(i, el) {
$(el).toggle($(el).text().toLowerCase().indexOf(t.toLowerCase()) > -1);
});
$(this).multisortable("option", "items", "> li:visible").multisortable("refresh");
}
function listToString(el) {
return $(el).sortable("toArray").toString();
}
$('ul.sortable').multisortable({
selectedClass: 'highlight'
}).sortable({
connectWith: ".sortable",
update: function(e, ui) {
$("#listIdResult").html(listToString(this));
}
});
$("#search").on("input", function(e) {
$("#sort-1").filterList($(this).val());
});
});
理论上,这应该有效,但实际上无效。过滤列表后,它应该更新选项并刷新可以选择的内容。我不确定这可以用预设的插件“修复”,因为它已经 7 年没有更新了,我怀疑是否会有修复。
可能有更好的答案,但我现在没有。如果我遇到任何问题,将调查并更新此答案。
那么,问题来了...
我有两个列表。我希望用户能够从左侧的一个列表中拖动以在右侧构建一个新列表,但也想让他们能够过滤左侧列表。左边的列表可能很长,所以我也希望他们能够多 select 和拖动。
对于多select我正在使用jQuery multisortable
这里 jsFiddle 展示了我正在努力实现的目标。
最终目标是为构建的列表构建逗号分隔的字符串。如果您在“a”上过滤列表,multiselect 结果,您会看到所有列表项都被拖到正确的列表中 - 甚至是被过滤器隐藏的过滤项目之间的那些 - 如何做我绕过这个?
感谢任何帮助!
以下示例使用 Bootstrap 4
编辑:查看 DOM 我可以看到 JQuery 过滤器在 SHIFT 键用于多个 select 项,因此尝试添加选项...
items: '> li:not("multiselectable-shift")'
...对于可排序的,仍然没有快乐。使用 control 键或 meta kay 都可以,只是 shift 键有问题。
<script>
jQuery(function($) {
$('ul.connectedSortable').multisortable({
selectedClass: 'highlight'
});
$('ul#sortable1').sortable({
connectWith: 'ul#sortable2',
update: function() {
callListIds = "";
$("ul#sortable2 li").each(function() {
callListIds += $(this).attr("id") + ",";
})
callListIds = callListIds.replace(/,\s*$/, "");
$("#listIdResult").html(callListIds);
}
});
$('ul#sortable2').sortable({
connectWith: 'ul#sortable1',
update: function() {
callListIds = "";
$("ul#sortable2 li").each(function() {
callListIds += $(this).attr("id") + ",";
})
callListIds = callListIds.replace(/,\s*$/, "");
$("#listIdResult").html(callListIds);
}
});
});
// Search field
$(document).ready(function() {
$("#search").on("keyup", function() {
var value = $(this).val().toLowerCase();
$("#sortable1 li").filter(function() {
$(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
}); </script>
.highlight {
background-color: #AABFF3;
}
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet" />
<script src="https://rawgithub.com/shvetsgroup/jquery.multisortable/master/src/jquery.multisortable.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" />
<style>
.highlight { background-color: #AABFF3; }
</style>
</head>
<body>
<input type="hidden" name="callListIds" id="callListIds" value="">
<div class="d-flex justify-content-center w-90 mx-auto d-block pt-5">
<div class="container w-40 float-left">
<input type="search" class="form-control" name="search" id="search" placeholder="search...">
<ul id="sortable1" class="connectedSortable list-group" style="min-height:100%">
<li id="ls1" class="list-group-item w-100 p-1">ABC</li>
<li id="ls2" class="list-group-item w-100 p-1">DEF</li>
<li id="ls3" class="list-group-item w-100 p-1">AGH</li>
<li id="ls4" class="list-group-item w-100 p-1">HIJ</li>
<li id="ls5" class="list-group-item w-100 p-1">KLM</li>
<li id="ls6" class="list-group-item w-100 p-1">AOP</li>
</ul>
</div>
<div class="container w-40 float-right border ml-1">
<ul id="sortable2" class="connectedSortable list-group" style="min-height:100%">
</ul>
</div>
</div>
<p class="p-2 text-center">Resulting comma delimited String:
<span id="listIdResult"></span></p>
</body
基本上,代码中存在逻辑问题 [https://github.com/shvetsgroup/jquery.multisortable/blob/master/src/jquery.multisortable.js 44-56]:
if (e.shiftKey) {
var last_shift_range = parent.find('.multiselectable-shift');
last_shift_range.removeClass(options.selectedClass).removeClass('multiselectable-shift');
var shift_range;
if (prevIndex < myIndex) {
shift_range = item.prevUntil('.multiselectable-previous').add(prev).add(item);
}
else if (prevIndex > myIndex) {
shift_range = item.nextUntil('.multiselectable-previous').add(prev).add(item);
}
shift_range.addClass(options.selectedClass).addClass('multiselectable-shift');
}
基本上,它在创建范围时忽略了 items
选项。所以当你这样配置时:
$(el).multiselect({
items: "li:visible"
});
Shift 单击事件将创建一个范围并包括所有列表项,无论它们是否可见。我尝试了一些解决方法并将 Fiddle 改进为:
https://jsfiddle.net/Twisty/sjg5u1ty/56/
JavaScript
jQuery(function($) {
$.fn.filterList = function(t) {
console.log("Filter For:", t);
$("> li", this).each(function(i, el) {
$(el).toggle($(el).text().toLowerCase().indexOf(t.toLowerCase()) > -1);
});
$(this).multisortable("option", "items", "> li:visible").multisortable("refresh");
}
function listToString(el) {
return $(el).sortable("toArray").toString();
}
$('ul.sortable').multisortable({
selectedClass: 'highlight'
}).sortable({
connectWith: ".sortable",
update: function(e, ui) {
$("#listIdResult").html(listToString(this));
}
});
$("#search").on("input", function(e) {
$("#sort-1").filterList($(this).val());
});
});
理论上,这应该有效,但实际上无效。过滤列表后,它应该更新选项并刷新可以选择的内容。我不确定这可以用预设的插件“修复”,因为它已经 7 年没有更新了,我怀疑是否会有修复。
可能有更好的答案,但我现在没有。如果我遇到任何问题,将调查并更新此答案。