当在"单选按钮"上设置下拉框时添加了另一个问题,所有应该将输入元素附加到各自的.q_ div 的.addrad按钮仅将元素附加到最后一个.q_ div(如上所述)这个JSFiddle的第25行).每个添加按钮都应将克隆的输入元素仅附加到这些按钮所属的div.我应该为.addrad上的click事件的选择器添加一个变量吗?如果我不需要变量,选择器应该是什么样的?我很感激有关如何解决这个问题的任何信息和见解.
JQuery(在JSFiddle上找到的其余项目):
$(document).ready(function () {
var clonedForm = $('form').clone();
var counter = 1;
var counter1 = 1;
var clone = $('#mp_0 div[name^="answer"]');
var clone1 = $('#checkbox_0 div').children().clone();
var clone2 = $('#radio_0 div').children().clone();
var clone3 = $('#choose_0 div').children().clone();
var newqid = $('#content form').length;
$('.removecb').hide();
$('.removeq').hide();
$('.removerad').hide();
$('.removechoose').hide();
$(document).on("click", ".addrad", function(e) {
var idx = $(this).siblings('div[id^="radio_"] div').find('.radio:last').length;
var newRad = $(clone2).clone();
counter++;
$('div[id^="radio_"] div input[type="text"]:last').attr('name', 'radio_'+counter);
$('.removerad').show();
$('[id^="radio_"]:last div').append(newRad);
e.preventDefault();
});
$(document).on("click", ".removerad", function(e) {
if (counter !=1) {
$('input[type="radio"]:last').remove();
$('input[name^="radio_"]:last').remove();
counter--;
}
if (counter == 1) {
$('.removerad').hide();
}
if (counter < 1) {
counter = 1;
}
e.preventDefault();
});
$(document).on("click", ".nextq", function () {
var newForm = $(clonedForm).clone();
counter = 1;
counter1++;
$('.done, .nextq, .removeAnswer, .removeq').hide();
$('#content').append('<hr>');
$('#content').append(newForm);
$('[class^="q_"]:last b.qnum').empty().append(counter1 + '. ')
$(newForm).children(".group").hide();
$(newForm).children("#text").show();
$('form:last').find('.select_0').attr('class', 'select_' + newqid);
$('[class^="q_"]:last').attr('class', 'q_' + newqid);
$('form:last').find('#mp_0').attr('id', 'mp_' + newqid);
$('form:last').find('#checkbox_0').attr('id', 'checkbox_' + newqid);
$('form:last').find('.done:last, .nextq:last, .removeq:last').show();
return false;
});
$(document).on("click", ".removeq", function (e) {
var newqid = $('form:last[name^="question"]:last').index() - 1;
counter1--;
$('hr:last').remove();
$('form[name^="question"]:last').remove()
$('[class^="q_"]:last input, [class^="q_"]:last textarea, [class^="q_"]:last select, [class^="q_"]:last button, [class^="q_"]:last option').prop('disabled', false);
$('form:last').find('.done, .nextq, .removeq').show();
newqid -1;
$('[type="checkbox"]').prop('disabled', true);
e.preventDefault();
if (counter1 == 1) {
$('.removeq').hide();
}
});
$('.group').hide();
$('#text').show();
$(document).on("change", "select", function () {
counter = 1;
$(this).parent().parent().siblings('.group').hide();
$(this).parent().parent().siblings('[id^="' + $(this).val() + '"]:last, [class^="' + $(this).val() + '"]').fadeIn();
});
});
Run Code Online (Sandbox Code Playgroud)
这是一个古老的背景问题.当构建可以包含重复部分的复杂接口时,最好提出一种设计,将每个部分视为整个实体 - 在内部表示和管理每个新部分的可创建js/dom对象 - 然后您有一个中心"上下文"存在this.这样,您只需在需要时实例化这些对象,并将它们作为一个整体添加到页面中.你会发现它让生活变得更轻松.
遗憾的是,对于许多JavaScript项目,您没有看到这一点.主要是因为事物是以思想的速度构建的,因为JS具有高度的草图性.你所看到的是你所拥有的,它是一些基于上下文的jQuery,一些基于全局的jQuery,一些基于id的选择器,一些全局变量和一些存储的dom对象的混合.上下文的混合 - 这是一个阅读,理解和扩展的难题.
我建议你修改你的方法,并设计一个对象来表示要创建即每个部分RadioButtonSection,TextSection,MultipleChoiceSection等等.每个对象将负责以本地方式创建,管理和删除它自己的子部分.本地化我的意思是依赖于class选择器,$(this)或存储的DOM元素this,而不是使用ids,全局jQuery选择器,全局变量或特定的DOM结构.
var RadioButtonSection = {
create: function(){
var obj = Object.create(this);
obj.element = $('<div class="radio-button-section" />');
return obj;
},
addRadio: function(){
this.element.find('.radio-list').append('<input type="radio" />');
/// ... and so on
return this;
},
removeRadio: function(){
/// ... and so on
return this;
},
addToPage: function( target ){
$(target).append( this.element );
return this;
},
removeFromPage: function(){
this.element.remove();
return this;
}
};
Run Code Online (Sandbox Code Playgroud)
更好的原因是你划分代码,这使得它更容易阅读,你将页面的每个新部分视为一个连贯的对象(而不是一些元素),也意味着你可以开始概括和重用功能.
例如,要创建新的单选按钮区域,只需调用:
var rbs = RadioButtonSection.create();
rbs.addToPage( /* target-element-or-selector-here */ );
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用此对象来管理新区域.此对象添加到页面的任何GUI元素都应在本地工作,因此您不必担心创建或销毁的数量.
如果您更喜欢这种prototype方法,则可以使用此模型:
var RadioButtonSection = function(){
if ( this instanceof RadioButtonSection ) {
this.element = $('<div class="radio-button-section" />');
}
else {
return new RadioButtonSection();
}
};
RadioButtonSection.prototype.addRadio = function(){
this.element.find('.radio-list').append('<input type="radio" />');
/// ... and so on
return this;
};
RadioButtonSection.prototype.removeRadio = function(){
/// ... and so on
return this;
};
RadioButtonSection.prototype.addToPage = function( target ){
$(target).append( this.element );
return this;
};
RadioButtonSection.prototype.removeFromPage = function(){
this.element.remove();
return this;
};
Run Code Online (Sandbox Code Playgroud)
你会用它:
var rbs = new RadioButtonSection()
.addToPage( /* target-element-or-selector-here */ )
;
Run Code Online (Sandbox Code Playgroud)
如果没有上述内容 - 因为它意味着大量的重做 - 你至少应该设计你的函数和事件监听器来尊重当前的jQuery托管 - DOM上下文,即$(this)从中解决.这样您就不会遇到现在的问题.
下面是使用单击按钮作为上下文重写您的函数的示例.
$(document).on("click", ".addrad", function(e) {
counter++;
e.preventDefault();
var context = $(this);
var group = context.closest('.group');
var insert = group.find('div:first');
var newRad = $(clone2).clone();
newRad.find('input[type="text"]:last').attr('name', 'radio_'+counter);
group.find('.removerad').show();
insert.append(newRad);
});
Run Code Online (Sandbox Code Playgroud)
例如,我已经使用了$('.removerad')全局选择器并将其替换为group.find('.removerad').show();只能找到本地删除按钮,而不是在页面范围内找到所有选择器.在构建复杂的JavaScript UI(本地而非全局)时,您始终需要思考这个问题.
使用这种"本地"方法,您可以通过提供任何包装<div>特定的分组类来使事情变得更容易,这样您就不必依赖于这样的事情,.find('div:first')因为如果您修改GUI,这很容易破坏.
在你重写方法以使用基于本地上下文的思维之前,你会发现你会弹出许多其他奇怪的错误,因为你的代码混合了本地和全局的行为.
关于'radio_' + counter不工作的好处.我没有发现你的代码在其他地方执行以下操作:
var clone2 = $('#radio_0 div').children().clone();
Run Code Online (Sandbox Code Playgroud)
这会newRad以一种意想不到的方式影响jQuery集合..find()被设计为从父母一直到他们的孩子,但该.children()方法将返回一个单独的元素列表,与他们的父关系分开.
所以计数器代码的一个修复就是使用.filter():
newRad.filter('input[type="text"]:last').attr('name', 'radio_'+counter);
Run Code Online (Sandbox Code Playgroud)
但也许更好的是修改var clone2使用:
var clone2 = $('#radio_0 div').clone();
Run Code Online (Sandbox Code Playgroud)
..并插入输入及其包装div,并继续使用.find().这引出了我的下一个问题.
而不是使用类似的东西:
group.closest('[type="radio"]:last').remove()
Run Code Online (Sandbox Code Playgroud)
每当插入多个元素时,最好使用HTML的强大功能并给它们一个包装器.然后,您可以通过删除包装器将它们全部删除.我建议你修改clone2我上面所说的,给包装div一个类,然后将其作为删除目标.
如果你这样做,那就意味着你还必须修改插入输入的方式,因此包装Div会一个接一个地插入,如下所示:
insert.after(newRad);
Run Code Online (Sandbox Code Playgroud)
是的,全球counter会给你带来麻烦.在这些情况下,您最好使用jQuery和DOM的强大功能来跟踪您的计数.例如 - 取自您的.addrad方法:
e.preventDefault();
var context = $(this);
var group = context.closest('.group');
var items = group.find('div'); // it might be best to give these DIVs a class
var insert = items.filter(':last');
var newRad = $(clone2).clone();
group.find('.removerad').show();
insert.after(newRad);
newRad.find('input[type="text"]:last').attr('name', 'radio_' + items.length);
Run Code Online (Sandbox Code Playgroud)
在上面的代码片段中,我使用items集合的长度来计算用于新无线电的数字.您也可以为删除功能执行类似的操作.这比手动计数器更好的原因是因为DOM会跟踪你,如果其他代码是 - 无论出于什么原因 - 删除一个项目; 您的计数会自动更正,因为每次都会重新计算.
为了方便起见,我radio-items在这里添加一个类:
<div id="radio_0" class="group">
<div class="radio-items">
<input disabled="disabled" type="radio" />
<input class="radio" name="radio_0" type="text" />
</div>
<button type="button" class="addrad">Toevoegen</button>
<button type="button" class="removerad">Verwijderen</button>
</div>
Run Code Online (Sandbox Code Playgroud)
然后找出radio-items有多少,在任何时候,你可以运行:
group.find('.radio-items').length
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
174 次 |
| 最近记录: |