我不是那里最热门的jQuery家伙,而且我试图在下面的代码中删除重复的工作。虽然性能开销可能很小并且可以忽略不计 - 但这更像是一个不想写几次做同样事情的糟糕代码的情况。
基本上我有一个简单的发票表单,用户也可以添加多个项目。
表单最初有4个输入:项目名称,项目价格,项目数量和总计
用户可以为第二个(或第三个,第四个,第五个等等)项添加额外的一行输入
price
和quantity
字段的现有javascript已经运行,因此不会将侦听器附加到新添加的输入行。目前,我已经删除了一些可怕的东西,在添加新的输入行后,我将一个事件监听器重新附加到所有输入字段。
我觉得很酷,如果你对你的工作质量不感到骄傲,但如果发票是20个项目,我真的需要在已经拥有的19行上添加第20项行循环附加的侦听器,再次附加它们,然后将侦听器附加到新行。我希望不会。
我已经设法定位新添加的输入行来擦除克隆输入中的值 - 所以我想只是定位新的输入字段并附加听众 - 但是我是得到正确的两个和八个因为理想情况下我喜欢这样做
我目前正在做的事情是什么感觉怪诞
下面的代码,让你嘲笑,然后希望对我表示同情并提供一个更简洁的解决方案,或者至少建议如何编写我自己更好的版本。
/** 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);
});
});
因此,通过利用事件委托,事件在dom上传播(或冒泡) - 谢谢你们!在新的父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[]
?
在这里大声思考,我想如果我捕获事件并遍历所有输入,直到我发现与该事件被触发的元素匹配的元素,然后我可以获取名为{{的下一个表单输入1}}并更新它? - 让我们去检查一下。
所以我可以捕捉到这个事件 - 快乐的日子:)
invoice_total[]
因此,我仍然不知道我已更新了哪些event.currentTarget.attributes.name.nodeValue == 'item_qty[]'
元素,因此我不知道要更新哪个item_qty[]
元素。
答案 0 :(得分:3)
你想要包装元素
<div>
<input />
<input />
</div>
$('div').on('change', 'input', function(){
// your magic here
});
这将适用于现在在场的两个人,以及新的元素。为什么?简单地说:
您将事件绑定到存在的元素。你创建一个新的,改变它,但从未将事件绑定到新元素。事件在树上冒泡,没有什么可以抓住它。
我的代码doest绑定到元素本身,告诉它在input
上听取它的变化。新的元素进来,你改变它们,没有任何事情发生,所以它在树上冒泡
这是最大的区别:这次我们告诉现有元素现在做点什么。