【发布时间】:2021-04-19 21:00:18
【问题描述】:
我正在尝试创建一个站点,该站点在包含最多 2 个输入的表中具有任意数量的行。我希望输入的组合是唯一的。也就是说,如果我们有以下元素
<select><option value='0'>None</option><option value='1'>1</option><option value='2'>2</option><option value='3'>3</option></select>
<select><option value='0'>None</option><option value='4'>4</option><option value='5'>5</option><option value='6'>6</option></select>
那么两者的任意组合都可以使用0-1次。所以,如果 1 和 4 在一行中使用,如果再次选择 1,则不应允许选择 4。这也应该在另一个方向上起作用。如果选择了 4,则不应允许再次选择 1。
用户可以随时添加或删除行,因此每次更改元素时都必须执行这些检查。
其他信息
- 选择元素的内容是由数据库生成的,它们不是静态的。
- 它们将始终具有包含整数的“值”属性。
- 我在 'masters' div 中保留一份未更改的选择元素的副本,这些元素用于向表中添加更多行(以及 PHP 从数据库中转储选项的位置)。当点击“添加”按钮时,这些“母版”会被克隆并添加进去。
- 每个允许的值为0,但只允许一次。这是唯一保证会出现在两个选择元素中的选项
我尝试过的事情
-
检测更改事件并尝试调整所有选择元素以强制执行唯一性,但我无法完全破解这一点。我很确定这是要走的路,但我正在努力实现它。
-
尝试在添加行时删除可能的重复项,但在至少做出一个选择之前,您无法确定什么是重复项。
-
删除与另一行组合重复的任何行,但这不能按预期工作,并且无论如何都不是用户友好的(这是下面示例中的当前实现)。
不起作用的东西
-
How to select only Unique combinations of select dropdowns in table row(非常相似,但没有可行的解决方案)
-
Prevent Multiple Selections of Same Value(选择元素不包含相同的项)
额外挑战
另一半是如果数据库中没有项目/活动,项目列和/或活动列可能会被隐藏。在这种情况下,默认值为 0,但它极大地改变了页面的预期行为并添加了一堆边缘情况。我把它排除在主要问题之外,因为我认为它会增加太多混乱,但这是我需要处理的其他事情。但是,此功能仅次于上述主要问题。
最小可重现示例:
您应该能够将其直接复制并粘贴到 .html 文件中进行实验。我留下了一些样式,以便更容易理解需要什么。
jQuery.fn.outerHTML = function() {
return jQuery('<div />').append(this.eq(0).clone()).html();
};
var projects = $("#projectsMaster");
var activities = $("#activitiesMaster");
var numRows = 0;
$(document).ready(function() {
$(".entryTable").on("click", ".deleteButton", function() {
if (numRows > 0) {
var row = $(this).closest("tr");
row.remove();
numRows--;
}
});
$(".entryTable").on('change', 'select', function() {
enforceUniqueProjectsActivities(this)
});
});
function enforceUniqueProjectsActivities(select) {
var usedCombos = new Array();
$(".entryTable").find(".dataRow").each(function() {
var activity = $(this).find(".activity").find("select").val();
if (!activity) {
activity = 0;
}
if (!project) {
project = 0;
}
var project = $(this).find(".project").find("select").val();
usedCombos.push(project + "," + activity);
});
//I was planning on going through each row and removing duplicates, but this isnt very user-friendly.
$(".entryTable").find(".dataRow").each(function() {
var activity = $(this).find(".activity").find("select").val();
if (!activity) {
activity = 0;
}
var project = $(this).find(".project").find("select").val();
if (!project) {
project = 0;
}
for (var i = 0; i < usedCombos.length; i++) {
if (i === $(this).index() - 1) {
continue;
}
if (project === usedCombos[i].split(",")[0] && activity === usedCombos[i].split(",")[1]) {
$(this).remove();
}
}
});
}
function addRow() {
numRows++;
var newRow = "<tr class='dataRow' '" +
"'><td class='project'>" + projects.clone().outerHTML() + "</td><td class='activity'>" + activities.clone().outerHTML() +
"</td><td><button class='deleteButton'>Delete</button></td></tr>";
$(".entryTable").find('tr:last').prev().after(newRow);
}
.entryTable {
margin: auto;
width: 95%;
border: 1px solid black;
border-collapse: collapse;
}
.entryTable input,
select {
width: 100%;
font-size: 18px;
}
.entryTable tr {
border-bottom: 1px solid black;
border-color: black
}
.entryTable td {
text-align: center;
padding: 10px;
border-right: 1px solid black;
}
#addRow {
background-color: darkgray
}
.masters {
display: none;
}
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<div class="masters">
<select id="projectsMaster">
<option value='0'>None</option>
<option value='1'>1</option>
<option value='2'>2</option>
<option value='3'>3</option>
</select>
<select id="activitiesMaster">
<option value='0'>None</option>
<option value='4'>4</option>
<option value='5'>5</option>
<option value='6'>6</option>
</select>
</div>
<br/>
<table class="entryTable" id-">
<tr>
<th>Project</th>
<th>Activity</th>
<th></th>
</tr>
<tr id="addRow">
<td></td>
<td></td>
<td style='text-align: center'><button onclick="addRow()">Add</button></td>
</tr>
</table>
【问题讨论】:
标签: javascript html jquery