jquery - 在 AJAX 表单提交中使用 jquery 数据选择器识别哪个类发出请求
问题描述
我有一系列组,每个组都包含项目列表。我在数量字段中添加了递减/递增按钮,并希望它可以通过 AJAX 工作。
输入字段之一的示例 html 是
<div class="ContentCell list_product_qty_wrapper nbr nbt">
<input type="text" name="cartlist_quantity" value="1" size="4" class="cart_input_1881" />
<input type="hidden" name="products_id" value="1881" />
<input type="hidden" name="cartlist_group_id" value="1" />
</div>
将递增/递减按钮添加到输入字段并启动 AJAX 调用的完整脚本是
// Add Increment/Decrement buttons
function add_quantity_buttons(element, vertical) {
quantity_input = jQuery(element);
quantity_input.attr('min', '0').attr('inputmode', 'numeric').attr('pattern', '[0-9]*').addClass('inc_dec_quantity_field').wrap('<div class="quantity_field_wrapper clearfix"></div>');
if (jQuery('.device-xs').is(':visible')) {
quantity_input.attr('type', 'number');
} else {
quantity_input.attr('type', 'text');
}
quantity_input.before('<a href="#decrease_quantity" class="quantity_dec_button">-</a>').after('<a href = "#increase_quantity" class = "quantity_inc_button" > + </a>');
}
// Handle quantity buttons
// Increment/Decrement button functionality
function increment_decrement_quantity(element, value) {
$(document.body).on('click', element, function(e) {
e.preventDefault();
quantity = $(this).parent().find(('input'));
quantity_value = parseInt(quantity.val(), 10);
quantity_multiple = undefined;
if (quantity.data('multiple') !== undefined && (quantity.data('multiple') > 0 || quantity.data('multiple') < 0)) {
quantity_multiple = parseInt(quantity.data('multiple'), 10);
if (value < 0) {
quantity_multiple = quantity_multiple * -1;
}
}
if (quantity_multiple !== undefined && (quantity_multiple > 0 || quantity_multiple < 0)) {
quantity_value = Math.floor(quantity_value / quantity_multiple) * quantity_multiple;
value = quantity_multiple;
} else {
value = parseInt(value, 10);
}
// Validate quantity and increment/decrement value
if (value > 0 || value < 0 && quantity_value > 0) {
quantity.val(quantity_value + value).trigger('change');
}
});
}
// Remove number type and add quantity change buttons
add_quantity_buttons('#listContentsDisplay input[name^="cartlist_quantity"]', true);
// Decrement button
increment_decrement_quantity('.quantity_dec_button', -1);
// Increment button
increment_decrement_quantity('.quantity_inc_button', +1);
// Quantity input validation
var ajax_called = false;
$(document.body).on('propertychange change click keyup input paste blur', '.inc_dec_quantity_field', function(e) {
character_code = !e.charCode ? e.which : e.charCode;
quantity_value = $(this).val();
leading_zero_plus_regexp = /^(0[0-9]|\+[\+,0-9]).*$/;
// When input goes out of focus validate quantity value
if (e.type == 'blur' && (quantity_value == '' || isNaN(quantity_value / 1) == true || isNaN(quantity_value / 1) == false && quantity_value <= 0)) {
$(this).val('0');
} else {
// Check for numeric value and allow backspace, delete, left and right arrows
if ((isNaN(quantity_value / 1) == false && quantity_value > 0) || (character_code != undefined && (character_code == 39 || character_code == 37 || character_code == 8 || character_code == 46))) {
// Correct value
// Make sure the quantity is integer
if (quantity_value != '' && isNaN(quantity_value / 1) == false && (quantity_value != parseInt(quantity_value, 10) || leading_zero_plus_regexp.test(quantity_value))) {
$(this).val(parseInt(quantity_value, 10));
}
} else if (character_code != undefined) {
// Incorrect value
$(this).val('0');
} else if (quantity_value != '' && isNaN(quantity_value / 1) == false && (quantity_value != parseInt(quantity_value, 10) || leading_zero_plus_regexp.test(quantity_value))) {
// Make sure the quantity is integer
$(this).val(parseInt(quantity_value, 10));
}
}
// AJAX update quantity
//if (e.type != 'click' && $(e.target).parent().parent().hasClass('list_product_qty_wrapper') && !ajax_called) {
//if (e.type != 'click' && $(e.target).parent().parent().hasClass('list_product_qty_wrapper[data-groupid="' + jQuery(this).data("groupid") + '"]') && !ajax_called) {
// if (e.type != 'click' && $(e.target).parent().parent().data('groupid') == jQuery(this).data("groupid") && !ajax_called) { changed to this after suggestion from Ivan (SO)
if (e.type != 'click' && $(e.target).data('groupid') == jQuery(this).data("groupid") && !ajax_called) { // Ivan (SO) suggestion didn't give an 'OK' in console log. Removing .parent().parent(), it does give an ok, but still only submits the last group to AJAX update
console.log('OK');
call_delay(function() {
var form = $('form[name="cartlist"]');
ajax_called = true;
$.ajax({
type: form.attr('method'),
url: form.attr('action'),
data: form.serialize()
}).success(function(data) {
if ($('#cartlistDefault').length && $(data).find('#cartlistDefault').length) {
$('#cartlistDefault').replaceWith($(data).find('#cartlistDefault'));
// Remove number type and add quantity change buttons
add_quantity_buttons('#listContentsDisplay input[name^="cartlist_quantity"]', true);
// Replace classes missing after AJAX callback
$('select').addClass('select_caret_icon form-control');
if ($('input[type="submit"].cssButton').length > 0) {
$('input[type="submit"].cssButton').attr("data-btn", "btn btn-md");
}
}
ajax_called = false;
}).fail(function(data) {
ajax_called = false;
});
}, 300);
}
});
我的问题是增量仅适用于while
循环中生成的最后一个组。
根据我昨天提出的一个问题(多个复选框来触发 js 脚本),我在识别请求来自哪个组时遇到了类似的问题,我在这里尝试了相同的方法,
更换
<div class="ContentCell list_product_qty_wrapper nbr nbt">
和
<div class="ContentCell list_product_qty_wrapper nbr nbt" data-groupid="1">
在脚本中,替换
if (e.type != 'click' && $(e.target).parent().parent().hasClass('list_product_qty_wrapper') && !ajax_called) {
和
if (e.type != 'click' && $(e.target).parent().parent().hasClass('list_product_qty_wrapper[data-groupid="' + jQuery(this).data("groupid") + '"]') && !ajax_called) {
但是,在这样做之后,没有一个增量按钮会触发 AJAX 进程。
这个小提琴https://jsfiddle.net/8h4gzmu3/显示了输入字段和增量/减量的样子,并且按钮在单击时确实会更新数量,一旦AJAX调用完成,第一个和第二个输入不是更新。只有最后一个是。
显然我还没有完全掌握使用数据选择器的概念。
我哪里做错了?
解决方案
因为您正在使用 hasClass 来查看类而不是属性,而在 html 中您正在添加 data-groupid 作为属性
如果父数据组ID相同,您可以尝试这个应该工作
if (e.type != 'click' && $(e.target).parent().parent().data('groupid') == jQuery(this).data("groupid") && !ajax_called) {
更新
您可以按照此逻辑来执行此操作,为按钮和当前输入添加相同的 groupid,然后在 if statment 中将它们相互匹配。
这是匹配当前输入的示例,如果您更改输入 groupid 与按钮 groupid 不同,如果 statment 将为 FALSE 并且您不会获得控制台日志
// Add Increment/Decrement buttons
function add_quantity_buttons(element, vertical) {
quantity_input = jQuery(element);
quantity_input.attr('min', '0').attr('inputmode', 'numeric').attr('pattern', '[0-9]*').addClass('inc_dec_quantity_field').wrap('<div class="quantity_field_wrapper clearfix"></div>');
if (jQuery('.device-xs').is(':visible')) {
quantity_input.attr('type', 'number');
} else {
quantity_input.attr('type', 'text');
}
quantity_input.before('<a href="#decrease_quantity" data-group-id="1" class="quantity_dec_button">-</a>').after('<a href = "#increase_quantity" data-groupid="1" class = "quantity_inc_button" > + </a>');
}
// Handle quantity buttons
// Increment/Decrement button functionality
function increment_decrement_quantity(element, value) {
$(document.body).on('click', element, function(e) {
e.preventDefault();
quantity = $(this).parent().find(('input'));
quantity_value = parseInt(quantity.val(), 10);
quantity_multiple = undefined;
if (quantity.data('multiple') !== undefined && (quantity.data('multiple') > 0 || quantity.data('multiple') < 0)) {
quantity_multiple = parseInt(quantity.data('multiple'), 10);
if (value < 0) {
quantity_multiple = quantity_multiple * -1;
}
}
if (quantity_multiple !== undefined && (quantity_multiple > 0 || quantity_multiple < 0)) {
quantity_value = Math.floor(quantity_value / quantity_multiple) * quantity_multiple;
value = quantity_multiple;
} else {
value = parseInt(value, 10);
}
// Validate quantity and increment/decrement value
if (value > 0 || value < 0 && quantity_value > 0) {
quantity.val(quantity_value + value).trigger('change');
}
});
}
// Remove number type and add quantity change buttons
add_quantity_buttons('.ContentCell input[name^="cartlist_quantity"]', true);
// Decrement button
increment_decrement_quantity('.quantity_dec_button', -1);
// Increment button
increment_decrement_quantity('.quantity_inc_button', +1);
// Quantity input validation
var ajax_called = false;
$(document.body).on('propertychange change click keyup input paste blur', '.inc_dec_quantity_field', function(e) {
character_code = !e.charCode ? e.which : e.charCode;
quantity_value = $(this).val();
leading_zero_plus_regexp = /^(0[0-9]|\+[\+,0-9]).*$/;
// When input goes out of focus validate quantity value
if (e.type == 'blur' && (quantity_value == '' || isNaN(quantity_value / 1) == true || isNaN(quantity_value / 1) == false && quantity_value <= 0)) {
$(this).val('0');
} else {
// Check for numeric value and allow backspace, delete, left and right arrows
if ((isNaN(quantity_value / 1) == false && quantity_value > 0) || (character_code != undefined && (character_code == 39 || character_code == 37 || character_code == 8 || character_code == 46))) {
// Correct value
// Make sure the quantity is integer
if (quantity_value != '' && isNaN(quantity_value / 1) == false && (quantity_value != parseInt(quantity_value, 10) || leading_zero_plus_regexp.test(quantity_value))) {
$(this).val(parseInt(quantity_value, 10));
}
} else if (character_code != undefined) {
// Incorrect value
$(this).val('0');
} else if (quantity_value != '' && isNaN(quantity_value / 1) == false && (quantity_value != parseInt(quantity_value, 10) || leading_zero_plus_regexp.test(quantity_value))) {
// Make sure the quantity is integer
$(this).val(parseInt(quantity_value, 10));
}
}
// AJAX update quantity
//if (e.type != 'click' && $(e.target).parent().parent().hasClass('list_product_qty_wrapper') && !ajax_called) {
//if (e.type != 'click' && $(e.target).parent().parent().hasClass('list_product_qty_wrapper[data-groupid="' + jQuery(this).data("groupid") + '"]') && !ajax_called) {
// if (e.type != 'click' && $(e.target).parent().parent().data('groupid') == jQuery(this).data("groupid") && !ajax_called) { changed to this after suggestion from Ivan (SO)
if (e.type != 'click' && $('.quantity_inc_button').data("groupid") == $(e.target).data('groupid') && !ajax_called) { // Ivan (SO) suggestion didn't give an 'OK' in console log. Removing .parent().parent(), it does give an ok, but still only submits the last group to AJAX update
console.log('input groupid: ' + $(e.target).data('groupid'));
console.log('button groupid: ' + $('.quantity_inc_button').data("groupid"));
console.log('OK')
// call_delay(function() {
// var form = $('form[name="cartlist"]');
// ajax_called = true;
// $.ajax({
// type: form.attr('method'),
// url: form.attr('action'),
// data: form.serialize()
// }).success(function(data) {
// if ($('#cartlistDefault').length && $(data).find('#cartlistDefault').length) {
// $('#cartlistDefault').replaceWith($(data).find('#cartlistDefault'));
// Remove number type and add quantity change buttons
// add_quantity_buttons('#listContentsDisplay input[name^="cartlist_quantity"]', true);
// Replace classes missing after AJAX callback
// $('select').addClass('select_caret_icon form-control');
// if ($('input[type="submit"].cssButton').length > 0) {
// $('input[type="submit"].cssButton').attr("data-btn", "btn btn-md");
// }
// }
// ajax_called = false;
// }).fail(function(data) {
// ajax_called = false;
// });
// }, 300);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="ContentCell list_product_qty_wrapper nbr nbt">
<input type="text" name="cartlist_quantity" data-groupid="1" value="1" size="4" class="cart_input_1881" />
<input type="hidden" name="products_id" value="1881" />
<input type="hidden" name="cartlist_group_id" value="1" />
</div>
推荐阅读
- node.js - 将修饰符与 Objection.js 关系映射一起使用
- azure - Azure 存储异地冗余解决方案,同时实现读取和写入的高可用性
- android - Andorid:用向外的曲线画一个圆
- r - 将 Rmarkdown 渲染到 R 包外的目录
- r - 在 R 中创建 Nexus 文件
- r - 在 plot.title 中使用 element_markdown() 后,单个空格显示为双空格
- c++ - 模板参数推导如何在转发引用上起作用?
- spring-boot - 未找到服务提供者 Spring Boot
- c++ - C++ 20:std::array 作为非类型模板参数重新洗牌元素
- azure-devops - 将 SonarQube 添加到 Azure DevOps 存储库时管道失败