背景
从长远来看,我并不是最炙手可热的jQuery人,我试图去掉下面代码中重复的工作。虽然性能开销可能很小,而且可以忽略不计--但这更像是不想编写糟糕的代码,并多次执行相同的操作。
基本上,我有一个简单的发票表格,用户也可以添加多个项目。
该表单最初有4个输入:项目名称、项目价格、项目数量和总数。
问题-部分解决(见更新)
用户可以为第二行(或第三行、第四行、第五行等)添加额外的输入行。项目
price
和quantity
字段的现有javascript已经运行,因此不会将侦听器附加到新添加的输入行。解决办法?
目前,我已经散列了一些可怕的东西,在添加了新的输入行之后,我重新将一个事件侦听器附加到所有输入字段。
这很酷--我想,如果您对工作的质量并不感到骄傲,但是如果发票是20项,那么我确实需要在已附加监听器的19行上添加第20项行循环,然后再将它们附加到新行。我希望不会。
我已经成功地锁定了新添加的输入行,以便从克隆的输入中删除值--所以我想只针对新的输入字段并附加侦听器--但是我得到了正确的2和8,因为理想情况下,我希望这样做
我现在所做的让人觉得奇怪的是
下面的代码,让你嘲笑,然后希望同情我,并提供一个更简洁的解决方案,或至少就如何编写我自己更好的版本提出建议。
/** Add additional item lines */
$('#add-item').click(function(e){
e.preventDefault();
/** clone first line and insert it */
$('.input-row:first').clone().insertAfter('.input-row:last');
/** clear the newly inserted inputs of values */
$(':input', '.input-row:last').val("");
/** ensure all item price and qty inputs have events attached to their change value */
$('input[name="item_qty[]"],input[name="item_price[]"]').on("change",function () {
var $container = $(this).closest('.form-group');
qty = Number($('input[name="item_qty[]"]',$container).val())||0,
price = Number($('input[name="item_price[]"]',$container).val())||0;
$('input[name="item_total[]"]',$container).val(qty * price);
$('input[name="item_total[]"]',$container).change();
});
/** Sum inputs for invoice total */
$('input[name="item_total[]"').change(function() {
var total = 0;
$.each($("[name='item_total[]']"), function(index, value) {
total += parseFloat($(this).val());
});
$("#total").val(total);
});
});
更新
因此,通过使用事件委托,事件传播(或气泡)在这个领域-谢谢各位!我已经在新父div变更中的任何时候重新计算发票总数
<div id="invoice-items">
<input name /> <input quantity /> <input price /> <input total />
<input name /> <input quantity /> <input price /> <input total />
<input name /> <input quantity /> <input price /> <input total />
...
</div>
/** if any input rows change update the invoice total */
$('#invoice-items').on('change', 'input', function(event){
var total = 0;
$.each($("[name='item_total[]']"), function(index, value) {
total += parseFloat($(this).val());
});
$("#total").val(total);
});
剩下的问题是..。
我仍然停留在如何更新<input total />
以反映对该特定行的更改上。我猜,在我的新jQuery片段中的某个地方,我需要确定哪个字段更改了,并更新了同一行的总计?
这就是我当前如何将更改侦听器附加到第一行/现有的输入行,以填充行总数
/** calculate item total */
$('input[name="item_qty[]"],input[name="item_price[]"]').on("change", function () {
var $container = $(this).closest('.form-group');
qty = Number($('input[name="item_qty[]"]',$container).val())||0,
price = Number($('input[name="item_price[]"]',$container).val())||0;
$('input[name="item_total[]"]',$container).val(qty * price);
$('input[name="item_total[]"]',$container).change();
});
我想我仍然需要一些方法来在添加了一行之后运行这段代码,或者遵循更干净的事件委派路线--某种方式只针对发生更改事件的行的item_total[]
?也许我可以捕获触发变更事件的元素的特定索引,并且只更新索引处的item_total[]
?
只要在这里大声思考,我想如果我捕获事件并循环所有输入,直到找到与事件激发的元素相匹配的元素,我就可以获取下一个名为invoice_total[]
的表单输入并更新它?-让我们检查一下。
更新
这样我就能捕捉到那些快乐的日子:)
event.currentTarget.attributes.name.nodeValue == 'item_qty[]'
因此,我仍然不知道我更新了哪些item_qty[]
元素,因此我也不知道要更新哪个item_total[]
元素。
伙计们,有什么建议吗?
发布于 2014-10-26 13:20:19
您想要使用包装元素
<div>
<input />
<input />
</div>
$('div').on('change', 'input', function(){
// your magic here
});
这将适用于两个现在在那里的人,以及新的元素。为什么?简单地说:
将事件绑定到存在的元素。您可以创建一个新元素,更改它,但永远不要将事件绑定到新元素。这件事从树上冒出来,什么也抓不到。
我的代码绑定到元素本身,您告诉它在input
上侦听其中的更改。新的元素进来了,你改变了它们,什么也没有发生,所以它在树上冒出气泡。
这是一个很大的区别:这一次我们让现有的元素现在就做些什么。
https://stackoverflow.com/questions/26578057
复制相似问题