动态插入新行后增加和更新总数中的值
Increment and update value in the total number after insert new rows dynamically
编辑:我已经用答案更新了代码。
我有一个运行良好的增量函数。然而:
1.我想根据其中一个跨度中可用的总数设置一些限制。比如10。所以递增不能超过10。#DONE
- 另一个问题是我计划有多行,在保存之前我想确保如果我们计算每一行的增量,它也不应该超过 10。如果它动态地减少总数(跨度)会很好。
我正在使用“添加”按钮动态添加行,如何才能添加实际使用当前功能的新闻行?我的行只是克隆第一行并且禁用了增量功能。
document.addEventListener('DOMContentLoaded', async function() {
document.querySelector('#addlocationdest').addEventListener('click', add);
});
function add() {
var x = 1;
var container = document.getElementById('destination');
var detail = document.getElementById('row');
var clone = detail.cloneNode(true);
clone.id = "destination" + x;
x++;
container.appendChild(clone);
}
window.addEventListener("load", () => {
let elTotalQuantity = document.querySelector("#totalqty");
let totalQuantity = parseInt(elTotalQuantity.innerHTML);
function getSumOfRows() {
let sum = 0;
for (let input of document.querySelectorAll("form .row > input.quantity"))
sum += parseInt(input.value);
return sum;
}
for (let row of document.querySelectorAll("form .row")) {
let input = row.querySelector("input");
row.querySelector(".increment").addEventListener("click", () => {
if (getSumOfRows() >= totalQuantity) return;
input.value++;
elTotalQuantity.innerHTML = totalQuantity - getSumOfRows();
});
row.querySelector(".decrement").addEventListener("click", () => {
if (input.value <= 0) return;
input.value--;
elTotalQuantity.innerHTML = totalQuantity - getSumOfRows();
});
}
});
<div id="location" class="hide">
<div class="title">Transfer details</div><br>
<div class="line padded-s">Total Quantity: <span>10</span></div>
<br>
<form>
<label>New Total Quantity at this location: <span id="totalqty">10</span></label>
<br>
<div id="destination">
<div id="row" class="row">
<button type="button" class="decrement">-</button>
<input type="text" class="quantity" value="0" readonly/>
<button type="button" class="increment">+</button>
<a>Location: </a>
<input type="text" class="location" value="0" readonly/>
</div>
</div>
</form>
<label>Total being transfer: <p id="total-sum"></p></label>
<br>
<button type="button" id="addlocationdest">ADD</button>
<button type="button" id="removelocationdest">REMOVE</button>
</div>
QuerySelector 仅 select 第一次出现,因此您还没有真正向第二个“行”添加侦听器。您应该使用 querySelectorAll,但不要使用唯一 ID,而是使用 类.
<input class="increment" type="button" value="+" />
现在您可以使用document.querySelectorAll(".increment")
获取数组中的所有元素。
您可以使用parentElement
在DOM中遍历。通过知道您单击了哪个按钮,您可以遍历到表单元素,然后 select 第一个子元素 - 这是一个输入。一种更动态的方法是使用 querySelector
到 select 输入,以防将来 HTML 发生变化。无论如何,这就是你如何根据按钮在 DOM.
中的位置知道要操作哪个输入
我添加了两个全局变量,totalSum
和maxSum
。 maxSum 是从您的 span 元素(我为其分配了一个唯一 ID)中获取的。 totalSum 确保所有输入的总和不超过 maxSum.
您有一些重复的代码,所以我将其重构为一个新方法:changeValue
.
总而言之,我认为代码不言自明。
哦,这段代码没有考虑到用户可以更改输入中的值。我会把它留给你在每个文本输入上使用“oninput”侦听器来解决。
var totalSum = 0; // 3
var maxSum = 0
var totalSumElement = null;
document.addEventListener('DOMContentLoaded', async function() {
totalSumElement = document.getElementById('total-sum');
maxSum = document.getElementById('max-sum').innerText;
var incrementElements = document.querySelectorAll('.increment'); // 1
var decrementElements = document.querySelectorAll('.decrement');
addListener('click', incrementElements, incrementValue);
addListener('click', decrementElements, decrementValue);
});
function addListener(type, elementArr, func) {
for (element of elementArr) {
element.addEventListener(type, func);
}
}
function withinRange(newValue) {
var maxReached = newValue > maxSum; // 3
var zeroReached = newValue < 0;
return !maxReached && !zeroReached;
}
function changeValue(event, change) { // 4
if (withinRange(totalSum + change)) {
let parent = event.currentTarget.parentElement; // 2
let input = parent.children[0];
let value = parseInt(input.value) || 0;
if (withinRange(value + change)) {
input.value = value + change;
totalSum = totalSum + change;
}
}
totalSumElement.textContent = `Total: ${totalSum}`;
}
function incrementValue(event) {
changeValue(event, 1);
}
function decrementValue(event) {
changeValue(event, -1);
}
#totalqty {
padding-bottom: 1rem;
}
<div id="totalqty" class="line padded-s">Total Quantity: <span id="max-sum">10</span></div>
<form>
<input type="text" value="0" />
<input class="increment" type="button" value="+" />
<input class="decrement" type="button" value="-" />
</form>
<form>
<input type="text" value="0" />
<input class="increment" type="button" value="+" />
<input class="decrement" type="button" value="-" />
</form>
<p id="total-sum"></p>
序言
只要总量固定在 script-execution 的开头,就可以了。否则,最好将实际允许的总量保存为一个属性,并使用 MutationObserver. That way you can update your max. value in your code dynamically, when the total quantity-attribute changes. You can define custom attributes 观察它,将它们命名为“data-*”,其中“*”是自定义名称。
您的问题的解决方案
您在多个元素上使用相同的 ID。你的意思是类,所以把id="increment"
改成class="increment"
,decrement
也是一样。
因为我们不想用按钮输入东西,而是想给它们添加监听器,所以我认为实际使用 <button>
会更好。在表单中,按钮充当type="submit"
,这是我们不想要的,因此我们需要将其更改为type="button"
。
由于行数和总数实际上是属于一起的,所以将它们一起放在一个 <form>
-元素中更为明智。但是,您仍然可以使用 <div>
.
将按钮和输入分组为一行
现在关于行值的 in-/decrementing 和总数量:
- 将允许的总量保存在一个变量中
- 将event-listener添加到相应的按钮
- 如果操作有效,更改行的值
- 更新总数量为
totalQuantity - getSumOfRows()
为了动态添加新行,我们创建并设置了这样一个元素,并将其附加到表单中。请参阅下面的 appendNewRow()
-函数。
旁注
我已将 readonly
属性添加到 input-fields 以便您无法通过键盘输入数字。
window.addEventListener("load", () => {
let elTotalQuantity = document.querySelector("#totalqty");
let totalQuantity = parseInt(elTotalQuantity.innerHTML);
function getSumOfRows() {
let sum = 0;
for (let input of document.querySelectorAll("form .row > input.quantity"))
sum += parseInt(input.value);
return sum;
}
function updateTotalQuantity() {
elTotalQuantity.innerHTML = totalQuantity - getSumOfRows();
}
function appendNewRow() {
let row = document.createElement("div");
row.classList.add("row");
let child;
// input.quantity
let input = document.createElement("input");
input.classList.add("quantity");
input.value = "0";
input.setAttribute("readonly", "");
input.setAttribute("type", "text");
row.append(input);
// button.increment
child = document.createElement("button");
child.classList.add("increment");
child.innerHTML = "+";
child.setAttribute("type", "button");
child.addEventListener("click", () => {
if (getSumOfRows() >= totalQuantity) return;
input.value++;
updateTotalQuantity();
});
row.append(child);
// button.increment
child = document.createElement("button");
child.classList.add("decrement");
child.innerHTML = "-";
child.setAttribute("type", "button");
child.addEventListener("click", () => {
if (input.value <= 0) return;
input.value--;
updateTotalQuantity();
});
row.append(child);
// button.remove-row
child = document.createElement("button");
child.classList.add("remove-row");
child.innerHTML = "Remove";
child.setAttribute("type", "button");
child.addEventListener("click", () => {
row.remove();
updateTotalQuantity();
});
row.append(child);
document.querySelector("form .rows").append(row);
}
document.querySelector("form .add-row").addEventListener("click", () => appendNewRow());
appendNewRow();
});
<form>
<label>Total Quantity: <span id="totalqty">10</span></label>
<br>
<div class="rows">
</div>
<button type="button" class="add-row">Add new row</button>
</form>
编辑:我已经用答案更新了代码。
我有一个运行良好的增量函数。然而:
1.我想根据其中一个跨度中可用的总数设置一些限制。比如10。所以递增不能超过10。#DONE
- 另一个问题是我计划有多行,在保存之前我想确保如果我们计算每一行的增量,它也不应该超过 10。如果它动态地减少总数(跨度)会很好。
我正在使用“添加”按钮动态添加行,如何才能添加实际使用当前功能的新闻行?我的行只是克隆第一行并且禁用了增量功能。
document.addEventListener('DOMContentLoaded', async function() {
document.querySelector('#addlocationdest').addEventListener('click', add);
});
function add() {
var x = 1;
var container = document.getElementById('destination');
var detail = document.getElementById('row');
var clone = detail.cloneNode(true);
clone.id = "destination" + x;
x++;
container.appendChild(clone);
}
window.addEventListener("load", () => {
let elTotalQuantity = document.querySelector("#totalqty");
let totalQuantity = parseInt(elTotalQuantity.innerHTML);
function getSumOfRows() {
let sum = 0;
for (let input of document.querySelectorAll("form .row > input.quantity"))
sum += parseInt(input.value);
return sum;
}
for (let row of document.querySelectorAll("form .row")) {
let input = row.querySelector("input");
row.querySelector(".increment").addEventListener("click", () => {
if (getSumOfRows() >= totalQuantity) return;
input.value++;
elTotalQuantity.innerHTML = totalQuantity - getSumOfRows();
});
row.querySelector(".decrement").addEventListener("click", () => {
if (input.value <= 0) return;
input.value--;
elTotalQuantity.innerHTML = totalQuantity - getSumOfRows();
});
}
});
<div id="location" class="hide">
<div class="title">Transfer details</div><br>
<div class="line padded-s">Total Quantity: <span>10</span></div>
<br>
<form>
<label>New Total Quantity at this location: <span id="totalqty">10</span></label>
<br>
<div id="destination">
<div id="row" class="row">
<button type="button" class="decrement">-</button>
<input type="text" class="quantity" value="0" readonly/>
<button type="button" class="increment">+</button>
<a>Location: </a>
<input type="text" class="location" value="0" readonly/>
</div>
</div>
</form>
<label>Total being transfer: <p id="total-sum"></p></label>
<br>
<button type="button" id="addlocationdest">ADD</button>
<button type="button" id="removelocationdest">REMOVE</button>
</div>
QuerySelector 仅 select 第一次出现,因此您还没有真正向第二个“行”添加侦听器。您应该使用 querySelectorAll,但不要使用唯一 ID,而是使用 类.
<input class="increment" type="button" value="+" />
现在您可以使用
document.querySelectorAll(".increment")
获取数组中的所有元素。您可以使用
中的位置知道要操作哪个输入parentElement
在DOM中遍历。通过知道您单击了哪个按钮,您可以遍历到表单元素,然后 select 第一个子元素 - 这是一个输入。一种更动态的方法是使用querySelector
到 select 输入,以防将来 HTML 发生变化。无论如何,这就是你如何根据按钮在 DOM.我添加了两个全局变量,
totalSum
和maxSum
。 maxSum 是从您的 span 元素(我为其分配了一个唯一 ID)中获取的。 totalSum 确保所有输入的总和不超过 maxSum.您有一些重复的代码,所以我将其重构为一个新方法:
changeValue
.
总而言之,我认为代码不言自明。
哦,这段代码没有考虑到用户可以更改输入中的值。我会把它留给你在每个文本输入上使用“oninput”侦听器来解决。
var totalSum = 0; // 3
var maxSum = 0
var totalSumElement = null;
document.addEventListener('DOMContentLoaded', async function() {
totalSumElement = document.getElementById('total-sum');
maxSum = document.getElementById('max-sum').innerText;
var incrementElements = document.querySelectorAll('.increment'); // 1
var decrementElements = document.querySelectorAll('.decrement');
addListener('click', incrementElements, incrementValue);
addListener('click', decrementElements, decrementValue);
});
function addListener(type, elementArr, func) {
for (element of elementArr) {
element.addEventListener(type, func);
}
}
function withinRange(newValue) {
var maxReached = newValue > maxSum; // 3
var zeroReached = newValue < 0;
return !maxReached && !zeroReached;
}
function changeValue(event, change) { // 4
if (withinRange(totalSum + change)) {
let parent = event.currentTarget.parentElement; // 2
let input = parent.children[0];
let value = parseInt(input.value) || 0;
if (withinRange(value + change)) {
input.value = value + change;
totalSum = totalSum + change;
}
}
totalSumElement.textContent = `Total: ${totalSum}`;
}
function incrementValue(event) {
changeValue(event, 1);
}
function decrementValue(event) {
changeValue(event, -1);
}
#totalqty {
padding-bottom: 1rem;
}
<div id="totalqty" class="line padded-s">Total Quantity: <span id="max-sum">10</span></div>
<form>
<input type="text" value="0" />
<input class="increment" type="button" value="+" />
<input class="decrement" type="button" value="-" />
</form>
<form>
<input type="text" value="0" />
<input class="increment" type="button" value="+" />
<input class="decrement" type="button" value="-" />
</form>
<p id="total-sum"></p>
序言
只要总量固定在 script-execution 的开头,就可以了。否则,最好将实际允许的总量保存为一个属性,并使用 MutationObserver. That way you can update your max. value in your code dynamically, when the total quantity-attribute changes. You can define custom attributes 观察它,将它们命名为“data-*”,其中“*”是自定义名称。
您的问题的解决方案
您在多个元素上使用相同的 ID。你的意思是类,所以把id="increment"
改成class="increment"
,decrement
也是一样。
因为我们不想用按钮输入东西,而是想给它们添加监听器,所以我认为实际使用 <button>
会更好。在表单中,按钮充当type="submit"
,这是我们不想要的,因此我们需要将其更改为type="button"
。
由于行数和总数实际上是属于一起的,所以将它们一起放在一个 <form>
-元素中更为明智。但是,您仍然可以使用 <div>
.
现在关于行值的 in-/decrementing 和总数量:
- 将允许的总量保存在一个变量中
- 将event-listener添加到相应的按钮
- 如果操作有效,更改行的值
- 更新总数量为
totalQuantity - getSumOfRows()
为了动态添加新行,我们创建并设置了这样一个元素,并将其附加到表单中。请参阅下面的 appendNewRow()
-函数。
旁注
我已将 readonly
属性添加到 input-fields 以便您无法通过键盘输入数字。
window.addEventListener("load", () => {
let elTotalQuantity = document.querySelector("#totalqty");
let totalQuantity = parseInt(elTotalQuantity.innerHTML);
function getSumOfRows() {
let sum = 0;
for (let input of document.querySelectorAll("form .row > input.quantity"))
sum += parseInt(input.value);
return sum;
}
function updateTotalQuantity() {
elTotalQuantity.innerHTML = totalQuantity - getSumOfRows();
}
function appendNewRow() {
let row = document.createElement("div");
row.classList.add("row");
let child;
// input.quantity
let input = document.createElement("input");
input.classList.add("quantity");
input.value = "0";
input.setAttribute("readonly", "");
input.setAttribute("type", "text");
row.append(input);
// button.increment
child = document.createElement("button");
child.classList.add("increment");
child.innerHTML = "+";
child.setAttribute("type", "button");
child.addEventListener("click", () => {
if (getSumOfRows() >= totalQuantity) return;
input.value++;
updateTotalQuantity();
});
row.append(child);
// button.increment
child = document.createElement("button");
child.classList.add("decrement");
child.innerHTML = "-";
child.setAttribute("type", "button");
child.addEventListener("click", () => {
if (input.value <= 0) return;
input.value--;
updateTotalQuantity();
});
row.append(child);
// button.remove-row
child = document.createElement("button");
child.classList.add("remove-row");
child.innerHTML = "Remove";
child.setAttribute("type", "button");
child.addEventListener("click", () => {
row.remove();
updateTotalQuantity();
});
row.append(child);
document.querySelector("form .rows").append(row);
}
document.querySelector("form .add-row").addEventListener("click", () => appendNewRow());
appendNewRow();
});
<form>
<label>Total Quantity: <span id="totalqty">10</span></label>
<br>
<div class="rows">
</div>
<button type="button" class="add-row">Add new row</button>
</form>