我正在构建一个动态表单系统,它将自动组装一个 HTML 表单并通过使用单个 form.js 文件使其具有交互性,该文件将适用于系统内构建的所有表单。我已经完成了表单系统,并且在大多数情况下 form.js 已经完成,除了嵌套 div 的错误。
一点背景:如果需要,我会发布我正在测试的表格,但我认为这足以解释我的需求。我正在使用一种将问题依赖项放在 div 中的表单,以便如果问题得到回答,则依赖项将显示出来。为了更好地理解这是如何工作的,表单系统允许无限嵌套依赖项。如果问题 1 有一个依赖问题,并且该依赖有一个依赖,而问题 2 有一个依赖,它看起来像:
Question 1:
-> Dependency Question 1-1
-> Dependency Question 1-1-1
Question 2
-> Dependency Question 2-1
依赖项的每个部分都进入自己的包含 div 以进行样式和组织:
<form>
<!-- Other elements (not div) mainly form input, labels, and fieldsets-->
<div id="dep-1" class="dependency">
<!-- Other elements (not div) mainly form input, labels, and fieldsets-->
<div id="dep-1-2" class="dependency">
<!-- Other elements (not div) mainly form input, labels, and fieldsets-->
<div id="dep-2-1" class="dependency">
<!-- Other elements (not div) mainly form input, labels, and fieldsets-->
</div>
</div>
</div>
</form>
id 只是为了展示,它们是由表单系统自动生成的。
我的问题:我的每件事都按照我想要的方式工作,或者我是这么想的。我在使用主 js 文件来控制所有表单时遇到的唯一问题是嵌套的 div。在表单加载时,我使用 jQuery 禁用所有依赖项以防止表单提交它们。问题是当我重新打开它们时。我想要的功能仅适用于我所在的依赖项 div,只为该 div 启用 :input,而不是在子 div 中。目前,父 div 中的所有子 div :input 都已启用。我尝试了多种方法来防止它进入儿童 div 并在 Google 和 SO 上花费超过 2 个小时。仍然没有运气......所以我在这里寻求你的帮助!
用于此的 form.js 代码
function _toggleDependencyContainer(id, result) {
if (result === true) {
// Allow only input of parent dependency div, not children dependency divs
$('#'+id).find(':input').each(function() { // **THIS LINE IS THE ISSUE!!**
$(this).removeAttr("disabled");
});
$('#'+id).slideDown();
} else {
// Disable all children input through all child divs
$('#'+id).slideUp().find(':input').each(function() {
$(this).attr("disabled", "disabled")
});
}
}
function _toggleElementDependencies(element) {
if (element.type === undefined) {
console.log('element.type is undefined');
return;
}
// Get the dependency ID and result then toggle
switch(element.type.toLowerCase()) {
case 'select':
case 'select-one':
case 'select-multiple':
$("#"+element.id+" option").each(function () {
var id = element.id+'-'+this.value+'-dep';
var result = this.selected;
if (id === undefined || id == null) {
return;
}
_toggleDependencyContainer(id, result);
});
return;
break;
case 'radio':
case 'checkbox':
var id = element.id+'-dep';
var result = $(element).is(':checked');
break;
case 'file':
case 'password':
case 'text':
case 'textarea':
var id = element.id+'-dep';
var result = ( $.trim( $(element).val() ) ) ? true : false;
break;
default:
return;
break;
}
if (id === undefined || id == null) {
return;
}
_toggleDependencyContainer(id, result);
}
$(document).ready(function() {
$('.dependency').hide(); // hide all dependencies
//
// Scan page for forms
// Loop through each form and process the elements to toggle dependencies
$('form').each(function(i) {
// Find all the input elements
$('#'+this.id).find(':input').not(':disabled').each(function(i) {
_toggleElementDependencies(this);
});
});
// Monitor form elements to toggle dependencies
$(':input').blur(function() {
_toggleElementDependencies(this);
});
$(':radio, :checkbox').click(function() {
$('input[name="'+this.name+'"]').each(function(i) {
_toggleElementDependencies(this);
});
});
$('select').change(function() {
_toggleElementDependencies(this);
});
});
我希望一些 jQuery 大师能给我我缺少的片段。我尝试使用 .not() 选择器,但我认为我为子 div 使用了错误的标识符。我试过了:
$('#'+id).not('div>div').find(':input').each(...);
$('#'+id).not('div:first').find(':input').each(...);
$('#'+id).not('div:first-chil').find(':input').each(...);
$('#'+id).not('div').find(':input').each(...);
还有更多,但我想我错过了一些简单的东西..
编辑 我正在添加我用来帮助理解布局的表单
<form method="post" action="/_projects/newForm/" id="test" name="test">
<fieldset>
<legend>One</legend><label for="first-name">First Name <span class="required-icon">*</span></label>
<input type="text" value="test" class="required" title="First Name" id="first-name" name="first_name">
<div class="dependency" id="first-name-dep" style="display: block;">
<label for="first-name2">First Name 2</label>
<input type="text" title="First Name 2" id="first-name2" name="first_name2">
<div class="dependency" id="first-name2-dep" style="display: none;">
<label for="first-name3">First Name 3</label>
<textarea title="First Name 3" id="first-name3" name="first_name3" disabled="disabled"></textarea>
</div>
</div>
<label for="last-name">Last Name</label>
<input type="text" title="Last Name" id="last-name" name="last_name">
<label for="last-name2">Last Name2</label>
<input type="text" title="Last Name2" id="last-name2" name="last_name2">
<label for="radio-test">Radio Test <span class="required-icon">*</span></label>
<fieldset class="options-cage" id="options-cage-radio-test">
<label for="radio-test-1">
<input type="radio" class="required" title="Yes" value="1" name="radio_test" id="radio-test-1">
Yes
</label>
<label for="radio-test-2">
<input type="radio" class="required" title="No" checked="checked" value="2" name="radio_test" id="radio-test-2">
No
</label>
</fieldset>
<div class="dependency" id="radio-test-1-dep" style="display: block;">
<label for="radio-dep">Radio Dep <span class="required-icon">*</span></label>
<input type="text" class="required" title="Radio Dep" id="radio-dep" name="radio_dep">
<div class="dependency" id="radio-dep-dep" style="display: none;">
<label for="radio-dep2">Radio Dep 2</label>
<input type="text" title="Radio Dep 2" id="radio-dep2" name="radio_dep2" disabled="disabled">
<div class="dependency" id="radio-dep2-dep" style="display: none;">
<label for="radio-dep3">Radio Dep 3 <span class="required-icon">*</span></label>
<fieldset class="options-cage" id="options-cage-radio-dep3">
<label for="radio-dep3-1">
<input type="radio" class="required" title="Yes" value="1" name="radio_dep3" id="radio-dep3-1" disabled="disabled"> Yes</label>
<label for="radio-dep3-2">
<input type="radio" class="required" title="No" checked="checked" value="2" name="radio_dep3" id="radio-dep3-2" disabled="disabled"> No</label>
</fieldset>
<div class="dependency" id="radio-dep3-1-dep" style="display: none;">
<label for="radio-dep4">Radio Dep 4 <span class="required-icon">*</span></label>
<input type="text" class="required" title="Radio Dep 4" id="radio-dep4" name="radio_dep4" disabled="disabled">
<div class="dependency" id="radio-dep4-dep" style="display: none;">
<label for="radio-dep5">Radio Dep 5</label>
<input type="text" title="Radio Dep 5" id="radio-dep5" name="radio_dep5" disabled="disabled">
<div class="dependency" id="radio-dep5-dep" style="display: none;">
<label for="radio-dep6">Radio Dep 6 <span class="required-icon">*</span></label>
<fieldset class="options-cage" id="options-cage-radio-dep6">
<label for="radio-dep6-1">
<input type="checkbox" class="required" title="Yes" value="1" name="radio_dep6" id="radio-dep6-1" disabled="disabled">
Yes
</label>
<label for="radio-dep6-2">
<input type="checkbox" class="required" title="No" checked="checked" value="2" name="radio_dep6" id="radio-dep6-2" disabled="disabled">
No
</label>
</fieldset>
</div>
</div>
</div>
</div>
</div>
</div>
</fieldset>
<fieldset>
<legend>Two</legend><label for="last-name3">Last Name3</label>
<input type="text" title="Last Name3" id="last-name3" name="last_name3">
<label for="checkbox-test">Checkbox Test <span class="required-icon">*</span></label>
<fieldset class="options-cage" id="options-cage-checkbox-test">
<label for="checkbox-test-10">
<input type="checkbox" class="required" title="Yup" value="10" name="checkbox_test[]" id="checkbox-test-10"> Yup</label>
<label for="checkbox-test-12">
<input type="checkbox" class="required" title="Nope" checked="checked" value="12" name="checkbox_test[]" id="checkbox-test-12"> Nope</label>
</fieldset>
<label for="select-test">Select Test <span class="required-icon">*</span></label>
<select title="Select Test" id="select-test" name="select_test" class="input-select required">
<option value="">- Please Select</option>
<option value="1">one</option>
<option value="2">two</option>
</select>
</fieldset>
<fieldset>
<input type="hidden" value="test" id="formID" name="formID">
<input type="hidden" value="dd7c7fae86db8988669231b67ce637138aa6c180" id="csrf" name="csrf">
<input type="submit" value="Submit">
<input type="reset" title="Reset the form?" value="Reset">
</fieldset>
</form>