I am cloning the following div in my jsp:
<div id="row" class="">
<div class="form-group">
<div class="control-label">
<label for="name"><b> Select Name: </b></label>
</div>
<div class="control-label">
<select class="form-control" name="names" id="names">
<option value="" disabled="disabled" label="Select a name"></option>
<option value="1">Bradley</option>
<option value="2">Anderson</option>
<option value="3">Sonya</option>
</select>
</div>
<div class="control-label">
<label for="ranks"><b> Rank : </b></label>
<input type="text" value="1" name="rank" id="rank" readonly="">
</div>
</div>
</div>
I am executing the cloning in javascript:
var i = 0;
function duplicate() {
var original = document.getElementById('row');
var clone = original.cloneNode(true);
clone.id = "row" + ++i;
if(!document.getElementById('row3')){
original.parentNode.insertBefore(clone, document.getElementById('nextDiv')); //nextDiv not shown in jsp for simplification
}
}
How do I access the value of "rank" so that every time the div is cloned, the value increments by 1?
Basically I want something like clone.getElementById('rank') though I know that's not right syntax. I tried clone.setAttribute('rank', i++) but the setAttribute only accesses the attributes of the div and not the child node in the div. Is there a simpler way to do this?
Try using Array.prototype.forEach() , for loop, Element.children to increment id, for, value properties of cloned element .control-label elements child nodes . Note, for attributes at label elements should correspond to id of select , input elements; added "s" at for="names" , for="ranks" label elements
var i = 0;
function duplicate() {
var original = document.getElementById('row');
var clone = original.cloneNode(true);
clone.id = "row" + ++i;
Array.prototype.forEach.call(clone.querySelectorAll(".control-label")
, function(el, index) {
for (var j = 0; j < el.children.length; j++) {
// increment `id`
if (el.children[j].id !== "") {
el.children[j].id = el.children[j].id + i;
}
// increment `for` attribute
if (el.children[j].htmlFor !== "") {
el.children[j].htmlFor = el.children[j].htmlFor + i;
}
// increment `#ranks`-n `value`
if (el.children[j].name === "ranks") {
el.children[j].value = 1 + Number(el.children[j].value)
}
}
})
if (!document.getElementById('row3')) {
original.parentNode.insertBefore(clone,
// nextDiv not shown in jsp for simplification
document.getElementById('nextDiv'));
}
}
duplicate()
<div id="row" class="">
<div class="form-group">
<div class="control-label">
<label for="names"><b> Select Name: </b>
</label>
</div>
<div class="control-label">
<select class="form-control" name="names" id="names">
<option value="" disabled="disabled" label="Select a name"></option>
<option value="1">Bradley</option>
<option value="2">Anderson</option>
<option value="3">Sonya</option>
</select>
</div>
<div class="control-label">
<label for="ranks"><b> Rank : </b>
</label>
<input type="text" value="1" name="ranks" id="ranks" readonly="">
</div>
</div>
</div>
<div id="nextDiv"></div>
Related
I want to show dynamic select option.
<div id="residential" >
<input type="radio" value="apartment" id="type_apartment" name="type" >
<label for="type_apartment" class="radio-inline"> Apartment/Flat </label>
<input type="radio" value="bachelor" id="type_bachelor" name="type">
<label for="type_bachelor" class="radio-inline"> Bechelor </label>
</div>
<!-- this will show when apartment select -->
<div class="form-group " id="tenant-flat">
<select id="tenant-type" class="form-control" name="tenant">
<option value="">Anyone</option>
<option value="family">Family</option>
<option value="bechelor" >Bechelor</option>
</select>
</div>
<!-- this will show when bechelor is select -->
<div class="form-group " id="tenant">
<select id="tenant-type" class="form-control" name="tenant">
<option value="">Anyone</option>
<option value="student">Student</option>
<option value="job_holder" >Job Holder</option>
</select>
</div>
This select option will store value in the same table name "tenant". But if use name="tenant" in two div, it's not storing the right value. So I think, if the options show dynamically then it should work. But how can I do that? Is there another solution?
I might do it like this instead, setting an array based on the selected button, and then populating the select element with that array, making sure to clear the select element each time.
function radio_click() {
// Get elements
var select = document.getElementById("select-occupant");
var apt = document.getElementById("type_apartment");
// Reset options
select.options.length = 0;
// Set option array based on selected
if (apt.checked == true) {
var options = {
ValueA : 'Anyone',
ValueB : 'Family',
ValueC : 'Bachelor'
};
} else {
var options = {
ValueA : 'Anyone',
ValueB : 'Student',
ValueC : 'Job Holder'
};
}
// Set options in select
for(index in options) {
select.options[select.options.length] = new Option(options[index], index);
}
}
<div id="residential" >
<input type="radio" value="apartment" id="type_apartment" name="type" checked=true onclick="radio_click()">
<label for="type_apartment" class="radio-inline"> Apartment/Flat </label>
<input type="radio" value="bachelor" id="type_bachelor" name="type" onclick="radio_click()">
<label for="type_bachelor" class="radio-inline"> Bechelor </label>
</div>
<!-- this is the only one needed now -->
<div class="form-group ">
<select class="form-control" name="tenant" id="select-occupant">
<option value="">Anyone</option>
<option value="family">Family</option>
<option value="bechelor" >Bechelor</option>
</select>
</div>
I'm trying to change the value of my input box by changing two different select options.
The first select box is product_type with two different data attributes on the options: data-price and data-price_c.
The second Select box pay_type is to selecting between data-price or data-price_c, to update the value of lprice.
This is what I've tried:
var sp = document.getElementById('select_product');
var lp = document.getElementById('lprice');
var count = document.getElementById('count');
var fp = document.getElementById('price');
var pt = document.getElementById('paytype');
var selected_type = pt.options[pt.selectedIndex];
sp.onchange = function(){
var selected = sp.options[sp.selectedIndex];
if (selected_type === 1){
lp.value = selected.getAttribute('data-price');
} else {
lp.value = selected.getAttribute('data-price_c');
}
fp.value = "";
};
sp.onchange();
count.onchange = function(){
fp.value = lp.value * count.value;
}
<div>
<label for="select_product">Select Product</label>
<select name="product_id" id="select_product" onchange="update();">
<option value="1" data-price="10000" data-price_c="11000">Product 1</option>
<option value="2" data-price="20000" data-price_c="21000">Product 2</option>
<option value="3" data-price="30000" data-price_c="31000">Product 3</option>
</select>
</div>
<div>
<label for="paytype">Pay type:</label>
<select name="paytype" id="paytype">
<option value="1">Cash</option>
<option value="2">Dept</option>
</select>
</div>
<div>
<label for="lprice">Single Price:</label>
<input type="text" name="lprice" id="lprice" class="form-control" tabindex="1" readonly/>
</div>
<div>
<label for="count">Count:</label>
<input type="number" name="count" id="count" class="form-control" tabindex="1" />
</div>
<div>
<label for="price">Full Price:</label>
<input type="text" name="price" id="price" class="form-control" tabindex="1" readonly/>
</div>
I hope I understated you correctly what needs to be done from code and explanation:
Your first problem was that you had your selected_type outside of you onchange function so it wasn't getting the changed options onchange.
Second is that you where trying to compare values 1 & 2 with element without actually extracting those values from element (missing .value on selected_type)
I assumed you will need to update the values on your Pay type change too as well as Select Product, so there is nit trick to wrap both HTML selects into one div in this case div id="wrapper" and that will listen on both selects and call function if any of them are changed. So now you call it on wrapper.onchange.
I would also advise to put your calculation fp.value = lp.value * count.value; inside this function to update total price on change of any of those elements so I wrapped your Count: into wrapper div.
Hope this helps.
var sp = document.getElementById('select_product');
var lp = document.getElementById('lprice');
var count = document.getElementById('count');
var fp = document.getElementById('price');
var pt = document.getElementById('paytype');
var wrapper=document.getElementById('wrapper');
wrapper.onchange = function(){
var selected = sp.options[sp.selectedIndex];
var selected_type = pt.options[pt.selectedIndex].value;
if (selected_type === "1"){
lp.value = selected.getAttribute('data-price');
}
if (selected_type === "2"){
lp.value = selected.getAttribute('data-price_c');
}
fp.value = "";
fp.value = lp.value * count.value;
};
wrapper.onchange();
<div id="wrapper">
<div>
<label for="select_product">Select Product</label>
<select name="product_id" id="select_product" >
<option value="1" data-price="10000" data-price_c="11000">Product 1</option>
<option value="2" data-price="20000" data-price_c="21000">Product 2</option>
<option value="3" data-price="30000" data-price_c="31000">Product 3</option>
</select>
</div>
<div>
<label for="paytype">Pay type:</label>
<select name="paytype" id="paytype">
<option value="1">Cash</option>
<option value="2">Dept</option>
</select>
</div>
<div>
<label for="lprice">Single Price:</label>
<input type="text" name="lprice" id="lprice" class="form-control" tabindex="1" readonly/>
</div>
<div>
<label for="count">Count:</label>
<input type="number" name="count" id="count" class="form-control" tabindex="1" />
</div>
</div>
<div>
<label for="price">Full Price:</label>
<input type="text" name="price" id="price" class="form-control" tabindex="1" readonly/>
</div>
presently stuck in situation. trying to create a form where one can dynamically add and remove div elements where necessary,so far have been a to DYNAMICALLY ADD, problem is if i try to REMOVE div,only the last created gets to delete whilst others remain(excluding the parent div)KINDLY ASSIST.
<!doctype html>
<html lang="en">
<head>
</head>
<body>
<div id="box">
<div id='div' style="background: #99CCFF; height: 100px; width:300px" >
<p>Degree Level: <select id="dropdown">
<option value="Doctorate Degree">Doctorate Degree</option>
<option value="Masters">Masters</option>
<option value="Bachelors Degree">Bachelors Degree</option>
<option value="SSCE">SSCE</option>
</select></p>
<label for="firstname">School Name</label>
<input type="text" placeholder="Your Role"">
<label for="from">From</label>
<input type="text" id="from" name="from">
<br>
<label for="to">to</label>
<input type="text" id="to" name="to">
</div>
</div>
<div>
<button id="submit1">Add new div</button>
<input type="button" value="Remove Element"
onClick="removeElement('box','div');">
</div>
</body>
<script>
var box = document.getElementById('box'),
template = box.getElementsByTagName('div'),
template = template[0];
var counter = 1;
submit1.onclick = function () {
var new_field = template.cloneNode(true);
new_field.id = new_field.id + counter++
console.log(new_field.id)
box.appendChild(new_field);
return false;
};
</script>
<script>
function removeElement(boxDiv, divDiv){
if (divDiv == boxDiv) {
alert("The parent div cannot be removed.");
}
else if (document.getElementById(divDiv)) {
var div = document.getElementById(divDiv);
var box = document.getElementById(boxDiv);
box.removeChild(div);
}
else {
alert("Child div has already been removed or does not exist.");
return false;
}
}
You are passing the string div to your remove element function which will only remove the first div.
You can find all the children elements and then remove the last child
Building on your previous code, see the snippet below
var box = document.getElementById('box'),
template = box.getElementsByTagName('div'),
template = template[0];
console.log(template);
var counter = 1;
submit1=document.getElementById("submit1");
submit1.onclick = function () {
var new_field = template.cloneNode(true);
new_field.id = new_field.id + counter++
console.log(new_field.id)
box.appendChild(new_field);
return false;
};
function removeElement(boxDiv){
var box = document.getElementById(boxDiv);
if(box.children){
console.log(box.children);
box.children[box.children.length-1].outerHTML="";
}
}
<div id="box">
<div id='div' style="background: #99CCFF; height: 100px; width:300px" >
<p>Degree Level: <select id="dropdown">
<option value="Doctorate Degree">Doctorate Degree</option>
<option value="Masters">Masters</option>
<option value="Bachelors Degree">Bachelors Degree</option>
<option value="SSCE">SSCE</option>
</select></p>
<label for="firstname">School Name</label>
<input type="text" placeholder="Your Role"">
<label for="from">From</label>
<input type="text" id="from" name="from">
<br>
<label for="to">to</label>
<input type="text" id="to" name="to">
</div>
</div>
<div>
<button id="submit1">Add new div</button>
<input type="button" value="Remove Element"
onClick="removeElement('box');">
</div>
It might be because js thinks you're only selecting the last one when doing
var div = document.getElementById(divDiv);
Try doing a loop until document.getElementById(divDiv) is undefined
jQuery(function() {
var currentCount = 0;
jQuery('#addMoreEmail').click(function() {
currentCount = cloning('#MoreEmailDetails', '#MoreEmails', currentCount);
return false;
});
function cloning(from, to, counter) {
var clone = $(from).clone();
//console.log(clone);
counter++;
// Replace the input attributes:
clone.find(':input').each(function() {
var name = jQuery(this).attr('name').replace(0, counter);
var id = jQuery(this).attr('id').replace(0, counter);
jQuery(this).attr({
'name': name,
'id': id
}).val();
});
// Replace the label for attribute:
clone.find('label').each(function() {
var newFor = jQuery(this).attr('for').replace(0, counter);
jQuery(this).attr('for', newFor);
});
// Replace the text between html tags:
clone = clone.html().replace(1, counter);
jQuery(to).before(clone);
return counter;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="MoreEmailDetails">
<div class="form-group users">
<input type="text" required="required" id="LeadEmailDetail0FirstName" value="" name="data[LeadEmailDetail][0][first_name]">
<label for="LeadEmailDetail0FirstName">First Name</label>
<input type="text" id="LeadEmailDetail0LastName" value="" name="data[LeadEmailDetail][0][last_name]">
<label for="LeadEmailDetail0FirstName">First Name</label>
<select id="LeadEmailDetail0CountryId" class="select-replace select2-offscreen" name="data[LeadEmailDetail][0][country_id]" tabindex="-1" title="Country">
<option value="">Choose a country</option>
<option value="2">SOUTHEASTERN EUROPE</option>
</select>
<label for="LeadEmailDetail0CountryId">Country</label>
<input type="checkbox" id="LeadEmailDetail0PrimaryEmail" value="1" name="data[LeadEmailDetail][0][primary_email]">
<label for="LeadEmailDetail0PrimaryEmail">Primary Email</label>
</div ">
</div">
<div id="MoreEmails"></div>
<input type="submit" value="Add More" id="addMoreEmail">
In above code input type text and checkbox working fine (adding dynamic fields after click add more) but i m getting below error in case select option
TypeError: jQuery(...).attr(...) is undefined
You need to add a null check for jQuery(this).attr('name')) . JSFIDDLE
Following is the modified JS code block.
clone.find(':input').each(function() {
if(jQuery(this).attr('name')) {
var name = jQuery(this).attr('name').replace(0, counter);
var id = jQuery(this).attr('id').replace(0, counter);
jQuery(this).attr({
'name': name,
'id': id
}).val(); }
});
I am still attempting to create blank fields that users can add on the fly. I am attempting to clone the following hidden template but I can't get it to add.
My HTML
<div class="_100">
<fieldset id="FieldBlank">
<div id="readroot" class="hidden">
<div class="_100">
<div class="_50"> QA Sample ID:<input type="text" id="QASampleID" name="QASampleID"></div>
<div class="_50" data-role="controlgroup" data-mini="true" data-type="horizontal">
<label>Collection Method</label><br />
<input type="radio" id="radGrab1" value="Grab" name="Collection1" />
<label for="radGrab1">Grab</label>
<input type="radio" id="radEWI1" value="EWI" name="Collection1" />
<label for="radEWI1">EWI</label></div>
</div>
<div class="_100">
<div class="_40">
<label class="analysis-label" for="analysis">Analyte:</label>
<select class="analysis" id="analysis" name="analysis" data-iconpos="left" data-icon="grid">
<option>Select</option>
<option value = "TN">TN</option>
<option value = "TP,NO2+3">TP,NO2+3</option>
</select></div>
<div class="_30">
<label class="preserve-label" for="preserve">Preserved</label>
<select class="select_preserve" id="preserve" name="preserve" data-iconpos="left" data-icon="grid">
<option>Select</option>
<option value = "HNO3">HNO₃</option>
<option value = "H2SO4">H₂SO₄</option>
</select></div>
<div class="_30">
<label class="cool-label" for="cool">Cooled</label>
<select class="select_cool" id="cool" name="cool" data-iconpos="left" data-icon="grid">
<option>Select</option>
<option value = "Ice">Ice</option>
<option value = "Frozen">Frozen</option>
<option value = "None">None</option>
</select></div>
</div>
</div>
</fieldset>
</div>
<button type="button" data-theme="b" data-icon="plus" id="moreFields" onclick="moreFields()">ADD FIELD BLANK</button>
<hr /><div id="writeroot"> </div>
My javascript
var counter = 0;
function moreFields() {
counter++;
var newFields = document.getElementById('readroot').cloneNode(true);
newFields.id = '';
newFields.style.display = 'block';
var newField = newFields.childNodes;
for (var i = 0; i < newField.length; i++) {
var theName = newField[i].name
if (theName)
newField[i].name = theName + counter;
}
var insertHere = document.getElementById('writeroot');
insertHere.parentNode.insertBefore(newFields,insertHere);
}
I just cannot get it to work! Is it because this script is not jquery? It doesn't seem to be because it is hidden because when I unhide it the button still doesn't work to add the clones? I am so pulling my hair out right now. I need you help!
Have you tried something like:
$("#readroot input").clone().appendTo("body"); // Or wherever you want to append them to
And, yeah, don't hide stuff manually. Use jQuery's toggle function instead:
$("#readroot").toggle(); // Or hide()