我正在创建一个非常基本的购物车。
它具有相关的下拉菜单和一个按钮"Add more products"
,将在同一下拉菜单中再添加一行。
有2个下拉菜单第2个菜单必须保持disabled
,直到在第1个菜单中选择了一个选项。输入的数量必须为disabled
,直到在第二个菜单中选择了一个选项。 Add more products
启用的数量为添加
我正在使用cloneNode()
为新行添加代码。
由于它仅在我每次单击"Add more products"
的{{1}}按钮时才创建克隆一次,因此有效
我正在使用最后添加的行来创建新的new_products();
添加了新行,但是问题是第二个菜单,并且此行中输入的数量已经为Clone
。
请尝试使用Vanilla(纯)JavaScript提供解决方案。
编辑1: 我来了一半。
在添加克隆之前,我尝试访问那些元素并更改enabled
属性值。
在disabled
中:
function new_products()
但这仅适用于第二个下拉菜单。
它不适用于数量var order = document.getElementById('order_now');
var product = document.getElementsByClassName('product');
var clone = product[no_of_products-1].cloneNode(true);
clone.getElementsByClassName('second_select')[0].disabled=true;
clone.getElementsByClassName('add_btn')[0].disabled=true;
控制。
代码段:
input
var productsByCategory = {
A: ["Select sub-product", "CNC 1", "CNC 2", "CNC 3", "CNC 4"],
B: ["Select sub-product", "LASER 1", "LASER 2", "LASER 3", "LASER 4"],
C: ["Select sub-product", "RUBBER 1", "RUBBER 2", "RUBBER 3", "RUBBER 4", "RUBBER 5"],
D: ["Select sub-product", "PRECISION 1", "PRECISION 2", "PRECISION 3"]
}
var valuesByCategory = {
A: ["", "A1", "A2", "A3", "A4"],
B: ["", "B1", "B2", "B3", "B4"],
C: ["", "C1", "C2", "C3", "C4", "C5"],
D: ["", "D1", "D2", "D3"]
}
var no_of_products = 1;
function dropdown() {
var select = document.getElementsByClassName('first_select');
var selected = select[no_of_products - 1].value;
var target = document.getElementsByClassName('second_select');
var targetLength = target[no_of_products - 1].length
/*console.log("Length"+target.length);*/
for (var i = targetLength; i >= 0; i--) {
/*console.log(i);*/
target[no_of_products - 1].remove(i);
}
if (selected == 0) {
var option = document.createElement("option");
option.text = "Select Product first";
option.value = "";
target[no_of_products - 1].add(option);
target[no_of_products - 1].disabled = true;
}
if (selected == 1) {
for (var i in productsByCategory['A']) {
var option = document.createElement("option"); //If this is outside the lopp then only last option gets included.
option.text = productsByCategory['A'][i];
option.value = valuesByCategory['A'][i];
target[no_of_products - 1].add(option);
target[no_of_products - 1].disabled = false;
}
} else if (selected == 2) {
for (var i in productsByCategory['B']) {
var option = document.createElement("option");
option.text = productsByCategory['B'][i];
option.value = valuesByCategory['B'][i];
target[no_of_products - 1].add(option);
target[no_of_products - 1].disabled = false;
}
} else if (selected == 3) {
for (var i in productsByCategory['C']) {
var option = document.createElement("option");
option.text = productsByCategory['C'][i];
option.value = valuesByCategory['C'][i];
target[no_of_products - 1].add(option);
target[no_of_products - 1].disabled = false;
}
} else {
for (var i in productsByCategory['D']) {
var option = document.createElement("option");
option.text = productsByCategory['D'][i];
option.value = valuesByCategory['D'][i];
target[no_of_products - 1].add(option);
target[no_of_products - 1].disabled = false;
}
}
}
function dropdown2() {
var select = document.getElementsByClassName('second_select');
var selected = select[no_of_products - 1].value;
/*console.log(selected);*/
var submit = document.getElementsByClassName('s_btn');
submit[no_of_products - 1].disabled = false;
var add = document.getElementById('add_button');
add.disabled = false;
}
function new_products() {
var order = document.getElementById('order_now');
var product = document.getElementsByClassName('product');
var clone = product[no_of_products - 1].cloneNode(true);
clone.getElementsByClassName('second_select')[0].disabled = true;
clone.getElementsByClassName('add_btn')[0].disabled = true;
var add = document.getElementById('add_button');
product[no_of_products - 1].removeChild(add);
/*console.log(clone);*/
order.appendChild(clone);
no_of_products += 1;
}
body {
height: 100vh;
margin: 0px;
overflow-y: auto;
font-family: 'Roboto';
}
#clear {
clear: both;
}
.content {
display: flex;
background-color: white;
height: auto;
margin-top: 0px;
font-family: 'Roboto';
z-index: -1;
min-height: 88%;
}
.link-contents {
position: relative;
display: block;
float: left;
left: 0px;
width: 100%;
}
.option-links {
display: block;
font-size: 30px;
cursor: pointer;
}
#op1 {
background-color: #cccccc;
}
select,
button,
input {
position: relative;
top: 5em;
display: block;
width: 12em;
height: 2em;
}
button {
width: 8em;
}
.first_select {
position: relative;
float: left;
left: 10%;
}
.second_select {
position: relative;
float: left;
left: 20%;
}
.s_btn {
position: relative;
float: left;
left: 30%;
}
.add_btn {
float: left;
top: 6em;
width: 10em;
left: 5em;
}
.footer {
display: block;
max-height: 4%;
}
.option-contents {
display: none;
}
#order_now {
display: block;
}
答案 0 :(得分:2)
要在每次单击“添加更多产品” div.product
时附加button.add_btn
的克隆,您需要创建一个全局变量,该变量包含div.product
的克隆会在页面加载时显示(我的意思是div.product
的{{1}},select.second_select
和input.s_btn
最初被禁用),然后是{{1 }},我们将创建一个新的button.add_btn
元素,为它提供一个button.add_btn
类,然后将div
附加到product
,然后使用{克隆元素的{1}}属性,并将其分配给新创建的div
。
一些评论和建议
我将在答案的末尾添加一个可运行的代码段,但在此之前,我想告诉您一些要点:
您正在使用div#order_now
,这不是明智的选择,您应该使用innerHTML
方法。使用div
方法,您可以同时附加多个事件(当然,当这些事件共享相同的处理逻辑时),也可以将任意数量的处理程序附加到同一事件(唯一的问题是客户端内存和性能问题)。 inline event listeners
方法的另一个重要功能是final参数,该参数控制侦听器对冒泡事件的反应,使用内联事件时没有等效项。
Learn more关于
addEventListener
方法Learn more关于
addEventListener
。
为使动态创建的元素不受事件(例如addEventListener
元素上的'change'事件)的捕获,我们需要将事件附加到addEventListener
上并检查应该执行哪个处理程序函数。换句话说,我们将使用events bubbling
。
Learn more关于
select
,该Stackoverflow帖子可能会对您有所帮助。
在我的回答中,您代码中的某些变量将不再用作document
变量,而其他变量(希望您会注意到它们)。
我从Event Delegqtion
删除了所有多余的Event Delegation
s属性,特别是在no_of_products
,ID
和button
s上元素,因为input
在页面中必须唯一。另外,我删除了所有内联事件处理程序,因为我们将使用select
方法。
正如我所说,内联事件处理程序将由div.product
方法替换,并且某些变量不再有用,要检查应执行哪个处理程序功能,我们将依靠{ {1}}的{{1}}属性,以查看哪个元素是当前事件的目标,因此我们将知道应该执行哪个处理程序函数。
Learn more关于
ID
。
要允许对我们的代码进行更多控制(特别是处理函数),将使用addEventListener
关键字引用当前事件的目标(像这样,不需要addEventListener
变量,因为当每个元素是当前事件的目标时,将使用Event
关键字来引用每个元素,即使动态创建的元素也将受到支持。即:在target
函数中,Event.target
表示单击的{ {1}}元素)。为此,我们将在处理程序函数上使用this
方法,该方法允许我们指定处理程序函数中的no_of_products
关键字所引用的元素。
Learn more关于
this
方法。
话虽如此,下面是一个可运行的代码片段,用于说明:
new_products
this
button.add_btn
此Stackoverflow帖子可能会帮助您learn more了解
call
和this
。
希望我进一步推动了你。
答案 1 :(得分:1)
不幸的是,您在代码中必须犯很多错误。因此,我将仅描述重要的错误:
id
属性在完整的HTML页面中必须是唯一的。如果克隆某个元素并且它具有id属性,则必须创建一个新的id。而且因为您希望从按钮中删除id
属性,所以我为您做了。element.disable
禁用元素。大多数浏览器都支持它,但这不是标准。如果您看到Element
和Node
的文档,那么您将发现它们没有此属性。某些浏览器不支持。在这种情况下,请使用Element.setAttribute()
和Element.removeAttribute()
函数。float: left
,请不要使用它。在您的情况下,您不需要它,因为您有inline-block
个元素。我也更改了很多CSS代码。addEventListener
方法而不是内联事件侦听器,但是在您的情况下,这是有争议的,因此,我不使用addEventListener
–这样您就可以更好地理解我的代码。但是我在您的函数中添加了一个参数–请注意。我编写了新代码,以便您没有任何类型的错误。享受吧!
完整的解决方案
var productsByCategory =
{
A: ["Select sub-product", "CNC 1", "CNC 2", "CNC 3", "CNC 4"],
B: ["Select sub-product", "LASER 1", "LASER 2", "LASER 3", "LASER 4"],
C: ["Select sub-product", "RUBBER 1", "RUBBER 2", "RUBBER 3", "RUBBER 4", "RUBBER 5"],
D: ["Select sub-product", "PRECISION 1", "PRECISION 2", "PRECISION 3"]
};
var valuesByCategory =
{
A: ["", "A1", "A2", "A3", "A4"],
B: ["", "B1", "B2", "B3", "B4"],
C: ["", "C1", "C2", "C3", "C4", "C5"],
D: ["", "D1", "D2", "D3"]
};
//var no_of_products = 1; //WE DO NOT NEED IT
function selectHelper(category, targetObj)
{
for(var i in productsByCategory[category])
{
var option = document.createElement("option");
option.text = productsByCategory[category][i];
option.value = valuesByCategory[category][i];
targetObj.add(option);
}
setEnabled(targetObj);
}
function dropdown(obj)
{
var selected = obj.value,
//second select:
target = obj.nextElementSibling;
for(var i = target.length; i--; )
target.remove(i);
if(selected == 0)
{
var option = document.createElement("option");
option.text = "Select Product first";
option.value = "";
target.add(option);
setDisabled(target);
//set disabled input field:
setDisabled(target.nextElementSibling)
}
else
{
if(selected == 1)
selectHelper('A', target);
else if(selected == 2)
selectHelper('B', target);
else if(selected == 3)
selectHelper('C', target);
else
selectHelper('D', target)
}
}
function dropdown2(obj)
{
setEnabled(obj.nextElementSibling);
setEnabled(document.getElementsByClassName('add_btn')[0]);
}
function new_products()
{
var allProducts = document.getElementsByClassName('product');
lastProduct = allProducts[allProducts.length - 1],
clone = lastProduct.cloneNode(true);
setDisabled(clone.getElementsByClassName('second_select')[0]);
//set disabled input field:
setDisabled(clone.getElementsByClassName('s_btn')[0]);
setDisabled(document.getElementsByClassName('add_btn')[0]);
//may be "insertBefore" is weird, but we do here insert new product after the last product:
document.getElementById('order_now').insertBefore(clone, lastProduct.nextSibling);
}
function setDisabled(obj)
{
obj.setAttribute("disabled", "disabled");
}
function setEnabled(obj)
{
obj.removeAttribute("disabled");
}
body
{
height: 100vh;
margin: 0px;
overflow-y: auto;
font-family: 'Roboto';
}
.content
{
background-color: white;
height: auto;
margin-top: 0px;
z-index: -1;
min-height: 88%;
}
.link-contents
{
position: relative;
left: 0px;
width: 100%;
}
.option-links
{
display: block;
font-size: 30px;
cursor: pointer;
}
#op1 {background-color: #cccccc}
select, button, input
{
position: relative;
top: 5em;
width: 12em;
height: 2em;
}
button {width: 8em}
.first_select
{
position: relative;
left: 10%;
}
.second_select
{
position: relative;
left: 20%;
}
.s_btn
{
position: relative;
left: 30%;
}
.add_btn
{
top: 6em;
width: 10em;
}
.footer
{
display: block;
max-height: 4%;
}
.option-contents {display: none}
#order_now {display: block}
<link href='https://fonts.googleapis.com/css?family=Roboto' rel='stylesheet'>
<link rel="stylesheet" type="text/css" href="profile.css">
<div class="content">
<div class="link-contents">
<div class="option-contents" id="order_now">
<div class="product">
<select class="first_select" onchange="dropdown(this)">
<option value="0">Select</option>
<option value="1">CNS</option>
<option value="2">Laser Cut</option>
<option value="3">Rubber roller</option>
<option value="4">Fixture</option>
</select>
<select class="second_select" onchange="dropdown2(this)" disabled>
<option>Select Product first</option>
</select>
<input class="s_btn" type="number" min='1' value="1" disabled />
</div>
<center><button class="add_btn" onclick="new_products()" disabled>Add more products</button></center>
</div>
</div>
</div>
<div class="footer">A big thank you to all of you.</div>