I have a dropdownlist with values. On a click of a button a unordered list gets appended with an <li> with details from the selected item in the dropdown list.
The <li> has an <a> tag in it which will remove the <li> from the <ul>.
I need to repopulate the dropdown list with the item removed from the <ul> when the <li> is removed.
Any ideas?
UPDATE:
Thanks for all your help. Here is my whole implementation:
<script type="text/javascript">
$(function() {
$("#sortable").sortable({
placeholder: 'ui-state-highlight'
});
$("#sortable").disableSelection();
$('#btnAdd').click(function() {
if (validate()) {
//Remove no data <li> tag if it exists!
$("#nodata").remove();
$("#sortable").append("<li class='ui-state-default' id='" + $("#ContentList option:selected").val() + "-" + $("#Title").val() + "'>" + $("#ContentList option:selected").text() + "<a href='#' title='Delete' class='itemDelete'>x</a></li>");
$("#ContentList option:selected").hide();
$('#ContentList').attr('selectedIndex', 0);
$("#Title").val("");
}
});
$('#btnSave').click(function() {
$('#dataarray').val($('#sortable').sortable('toArray'));
});
$('.itemDelete').live("click", function() {
var id = $(this).parent().get(0).id;
$(this).parent().remove();
var value = id.toString().substring(0, id.toString().indexOf('-', 0));
if ($("option[value='" + value + "']").length > 0) {
$("option[value='" + value + "']").show();
}
else {
var lowered = value.toString().toLowerCase().replace("_", " ");
lowered = ToTitleCase(lowered);
$("#ContentList").append("<option value='" + value + "'>" + lowered + "</option>");
}
});
});
function validate() {
...
}
function ToTitleCase(input)
{
var A = input.split(' '), B = [];
for (var i = 0; A[i] !== undefined; i++) {
B[B.length] = A[i].substr(0, 1).toUpperCase() + A[i].substr(1);
}
return B.join(' ');
}
</script>
<form ...>
<div class="divContent">
<div class="required">
<label for="ContentList">Available Sections:</label>
<select id="ContentList" name="ContentList">
<option value="">Please Select</option>
<option value="CHAN TEST">Chan Test</option>
<option value="TEST_TOP">Test Top</option>
</select>
<span id="val_ContentList" style="display: none;">*</span>
</div>
<div class="required">
<label for="ID">Title:</label>
<input class="inputText" id="Title" maxlength="100" name="Title" value="" type="text">
<span id="val_Title" style="display: none;">*</span>
</div>
<input value="Add Section" id="btnAdd" class="button" type="button">
</div>
<ul id="sortable">
<li class="ui-state-default" id="nodata">No WebPage Contents Currently Saved!</li>
</ul>
<div>
<input type="submit" value="Save" id="btnSave" class="button"/>
</div>
<input type="hidden" id="dataarray" name="dArray" />
</form>
You've acknowledged that you know very little about jQuery, so let's look at some of this piece by piece. This snippets will give you the information you need to construct your solution.
Adding click-events is relatively easy:
$("#myButton").click(function(){
/* code here */
});
Removing elements is also pretty simple:
$("#badThing").remove();
The thing about .remove() though is that you can add it elsewhere after removing it:
$("#badThing").remove().appendTo("#someBox");
That moves #badThing from wherever it was, to the inside of #someBox.
You can add new list items with the append method:
$("#myList").append("<li>My New Item</li>");
You can get the selected item of a drop-down like this:
var item = $("#myDropDown option:selected");
Related
So I want to create a function that will let me add/remove an element in the HTML, I'm already done with the "add" part that increments the id value onchange (example: id=tag1, id=tag2, etc). My problem is on the "remove" part, I don't know how to put an incremental value inside onclick=remove_tag(). Here's my code
function update() {
var selObj = document.getElementById("skill_tags");
var selVal = selObj.options[selObj.selectedIndex].text;
let counter = 0;
document.getElementById("textarea").innerHTML += "<div class='tags_inline' id='tag'><li class='list-inline-item'><span class='badge badge-dark'>" + selVal + "<button class='fa fa-times-circle text-white' id='delete' onclick=remove_tag('tag"+ counter +"');></button></span></li></div>";
$("#textarea div").each(function(i){this.id = "tag" + (i + 1)})
}
function remove_tag(id) {
document.getElementById(id).innerHTML = "";
}
What I want to do is to make my onclick on the button to be (onclick="remove_tag1", onclick="remove_tag2", onclick="remove_tag3", etc). Sorry for the question, still a newbie in JavaScript. Thanks for the help. Here's an image https://pasteboard.co/k7hb7cVHSQHj.png
<div class="resume-skill-item">
<h5>
<ul class="list-inline">
<div align="right">
<select id="skill_tags" onchange="update()">
<option selected="true" disabled="disabled">*Select All That Applies</option>
<option value="mechanic">Mechanic</option>
<option value="appliance_repairer">Appliance Repairer</option>
<option value="carpenter">Carpenter</option>
<option value="plumber">Plumber</option>
<option value="technician">Technician</option>
</select>
</div>
</ul>
<div id="textarea" class="large-single-textarea">
</div>
</h5>
</div>
```
You can use data attribute on delete button to keep reference on added items when you want to delete them.
function update(e) {
var selObj = document.getElementById("skill_tags");
var selVal = selObj.options[selObj.selectedIndex].text;
let counter = 0;
document.getElementById("textarea").innerHTML +=
`<div class="tags_inline" id="${e.value}"><li class="list-inline-item"><span class="badge badge-dark">"${selVal}"<button data-select-id="${e.value}" class="fa fa-times-circle text-white" id="delete" onclick=remove_tag(this) >remove</button></span></li></div>`;
}
function remove_tag(e) {
document.getElementById(e.dataset["selectId"]).remove();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="resume-skill-item">
<h5>
<ul class="list-inline">
<div align="right">
<select id="skill_tags" onchange="update(this)">
<option selected="true" disabled="disabled">*Select All That Applies</option>
<option value="mechanic">Mechanic</option>
<option value="appliance_repairer">Appliance Repairer</option>
<option value="carpenter">Carpenter</option>
<option value="plumber">Plumber</option>
<option value="technician">Technician</option>
</select>
</div>
</ul>
<div id="textarea" class="large-single-textarea">
</div>
</h5>
</div>
You can do it by sending the element itself thru args to the remove_tag function:
function update() {
var selObj = document.getElementById("skill_tags");
var selVal = selObj.options[selObj.selectedIndex].text;
//add tag with a remove_tag(this) onclick action
document.getElementById("textarea").innerHTML +=
"<div class='tags_inline' id='tag'><li class='list-inline-item'><span class='badge badge-dark'>" + selVal +
"<button class='fa fa-times-circle text-white' id='delete' onclick=remove_tag(this);></button></span></li></div>";
}
Then by DOM tree we can access and remove the element.
The DOM tree for this looks like div > li > span > button
The click event is triggered on the button so the function will look like this:
function remove_tag(element) {
//Here we grab the node that tag is on at the DOM tree
let tag = element.parentNode.parentNode;
//Same with the father div
let div = tag.parentNode;
//Then from that div we remove the selected element
div.removeChild(tag);
}
I recommend you to read more about the DOM
Hello I'm trying to rest the ID attribute of a set of text boxes when the delete button is pressed.
What I want to do is that when the delete button is pressed read the existing textboxes and rest there id's because when I delete items the ID's of the existing once keep the old ID values I want to rest this to match the error number value.
Working jsFiddle
//Add and remove function for the error text boxes
$(document).ready(function() {
$(document).on('click', '.addRow', function() {
var div = $("<div />"),
btnId = $("#stValue").val(); //Breaks the number from the ID using .match
// btnId = $(this).data("bid").match(/\d+/);//Breaks the number from the ID using .match
div.html(copy()); //Creates a new div container
$('.error-Column').append(div); //Insert all the HTML into the new div
$('#addRow_' + btnId).prop("disabled", true); //Disables the add button once clicked.
resetErrorNo(); //Calls the reset function
});
//Remove the text filed from the list and resets the error number
$(document).on('click', '.delRow', function() {
if (confirm('Your sure you want to remove this?')) {
var btnId = $("#stValue").val(), //Read the value of stValue
btnId2 = btnId - 1; //Deduct 1 from the value to get the last ID
for (var i = 0; i < btnId; i++) {
$('.addRow').attr('id', 'addRow_' + i);
}
//Enables the 1st add button if the value equals 1
if (btnId2 === 1) {
$('#addRow_' + btnId2).prop('disabled', false);
} else {
$('#addRow_' + btnId).prop('disabled', false);
}
$(this).parent().remove(); //Remove the text row from the list.
resetErrorNo(); //Calls the reset function
}
});
});
//Reset the entire error count number index
function resetErrorNo() {
$(".errorCount").each(function(index, _this) {
$(this).val(index + 1);
$("#stValue").val(index + 1);
});
}
//HTML function which will be called by the button click event for the add button
function copy() {
var stNum = document.getElementById("stValue"),
genNum = (document.getElementById("stValue").value - 1) + 2;
// stNum.value = genNum;
// language=HTML
return '<input class="errorCount" size="1" value="' + genNum + '" style="margin-left: 2%" readonly/>\n' +
'<select class="errorName" style="margin-left: 6%">\n' +
'<option selected disabled>----- Select Error -----</option>\n' +
'</select>\n' +
'<input type="button" class="addRow" id="addRow_' + genNum + '" data-bid="addRow_' + genNum + '" value="Add" />\n' +
'<input type="button" class="delRow" id="delRow_' + genNum + '" data-bid="delRow_' + genNum + '" value="Delete"/><br />'
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="jType-container">
<div id="error-Add-Container">
<div id="error-Column-Headings">
Error Number<span style="margin-left: 8%">Error Name</span>
</div>
<div class="error-Column">
<input class="errorCount" size="1" value="1" style="margin-left: 2%" />
<input type="hidden" value="1" id="stValue" />
<select class="errorName" style="margin-left: 6%">
<option selected disabled>----- Select Error -----</option>
</select>
<input type="button" data-bid="addRow_1" id="addRow_1" class="addRow" value="Add" />
</div>
</div>
</div>
UPDATE: I used the answer given by #Rory McCrossan and made some tweaks to get I wanted and ended up with the below code which is what I wanted to do in the first place.
// Add and remove function for the error text boxes
$(document).ready(function() {
$(document).on('click', '.addRow', function() {
var $clone = $('.error-Column .error-container:first').clone().appendTo('.error-Column');
$clone.find('select').val('');
// $clone.find('input').val('');
$('.addRow').prop('disabled', true).filter(':last').prop('disabled', false);
resetErrorNo();
}).on('click', '.delRow', function() {
var $btn = $(this);
if (confirm('Your sure you want to remove this?')) {
$btn.closest('.error-container').remove();
$('.addRow').prop('disabled', true).filter(':last').prop('disabled', false);
resetErrorNo();
}
});
});
//Reset the entire error count number index
function resetErrorNo() {
$(".errorCount").each(function(index, _this) {
$(this).val(index + 1);
});
}
/*----- All the styling for the error input area start -----*/
#error-Column-Headings span {
margin-left: 8%;
}
.errorCount {
margin-left: 2%;
}
.errorName {
margin-left: 6%;
}
.error-Column .error-container:nth-child(1) .delRow {
display: none;
}
.error-Column .error-container:nth-child(1) .delRow {
display: none;
}
/*----- All the styling for the error input area end -----*/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="jType-container">
<div id="error-Add-Container">
<div id="error-Column-Headings">
Error Number<span>Error Name</span>
</div>
<div class="error-Column">
<div class="error-container">
<input class="errorCount" size="1" value="1" style="margin-left: 2%" />
<select class="errorName">
<option selected disabled value="">----- Select Error -----</option>
</select>
<input type="button" class="addRow" value="Add" />
<input type="button" class="delRow" value="Delete" />
</div>
</div>
</div>
hope this helps some one in the future.
Incremental id attributes are an anti-pattern which leads to a lot of unnecessary maintenance work - as you've discovered.
You can make your code much more DRY, not to mention more simple by simply cloning each row and using DOM traversal to find elements related to the buttons and add/delete them as needed. Try this:
//Add and remove function for the error text boxes
$(document).ready(function() {
$(document).on('click', '.addRow', function() {
var $clone = $('.error-Column .error-container:first').clone().appendTo('.error-Column');
$clone.find('select').val('');
$('.addRow').prop('disabled', true).filter(':last').prop('disabled', false);
}).on('click', '.delRow', function() {
var $btn = $(this);
if (confirm('Your sure you want to remove this?')) {
$btn.closest('.error-container').remove();
$('.addRow').prop('disabled', true).filter(':last').prop('disabled', false);
}
});
});
#error-Column-Headings span {
margin-left: 8%;
}
.errorCount {
margin-left: 2%;
}
.errorName {
margin-left: 6%;
}
.error-Column .error-container:nth-child(1) .delRow {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="jType-container">
<div id="error-Add-Container">
<div id="error-Column-Headings">
Error Number <span>Error Name</span>
</div>
<div class="error-Column">
<div class="error-container">
<select class="errorName">
<option selected disabled value="">----- Select Error -----</option>
</select>
<input type="button" class="addRow" value="Add" />
<input type="button" class="delRow" value="Delete" />
</div>
</div>
</div>
</div>
I'm creating a set of textboxes and some drop downs using jQuery. The add function is working with out any issues.
My problem is with the delete function function works nicely as long as the user deletes one after the other but if the user delete from some where else the number sequence get messed up. Which breaks the 1,2,3,4 ... etc and sets the number which was deleted last.
As an example if the user deletes number 4 out of 7 errors the functions sets the last number as 4 when the user clicks the add button the next number generated will be 5 not the correct last number. I want to rest the rest of the numbers when something get removed from the middle.
I'm storing the last number in a hidden filed called stValue which is getting reset when deleting.
My problem is here I can't get my head around to think of way to reset this when deleting from some where else and then reset the entire error number row numbers when something get removed from the middle. Can you guys help me with this below is my code.
jsFiddle will help to understand better
JQuery:
//Add and remove function for the error text boxes
$(document).ready(function () {
$(document).on('click','.addRow',function () {
var div = $("<div />"),
btnId = $(this).data("bid").match(/\d+/);//Breaks the number from the ID using .match
div.html(copy()); //Creates a new div container
$('.error-Column').append(div); //Insert all the HTML into the new div
$('#addRow_'+btnId).prop("disabled", true);//Disables the add button once clicked.
});
//Remove the text filed from the list and resets the error number
$(document).on('click', '.delRow', function () {
var //btnId = $(this).data("bid").match(/\d+/),//Breaks the number from the ID using .match
maxNoList = $('input[class="addRow"]').length,
errNoList = maxNoList - 1;
alert(errNoList);
//btnId = btnId - 1; //Calculates the ID number of the previous button
$('#addRow_'+errNoList).prop('disabled',false);// Enables the previous add button
$('#stValue').val(errNoList); //Set the value of stValue when removing the text filed
//So the error numbers will be generated accordingly when Add is clicked again.
$(this).parent().remove(); //Remove the text row from the list.
});
});
//HTML function which will be called by the button click event for the add button
function copy() {
var stNum = document.getElementById("stValue"),
genNum = (document.getElementById("stValue").value - 1)+2;
stNum.value = genNum;
// language=HTML
return '<input class="errorCount" size="1" value="'+genNum+'" style="margin-left: 2%" readonly/>\n' +
'<select class="errorName" style="margin-left: 6%">\n' +
'<option selected disabled>----- Select Error -----</option>\n' +
'</select>\n' +
'<input type="button" class="addRow" id="addRow_'+genNum+'" data-bid="addRow_'+genNum+'" value="Add" />\n' +
'<input type="button" class="delRow" id="delRow_'+genNum+'" data-bid="delRow_'+genNum+'" value="Delete"/><br />'
}
HTML:
<div id="jType-container">
<div id="error-Add-Container">
<div id="error-Column-Headings">
Error Number<span style="margin-left: 8%">Error Name</span>
</div>
<div class="error-Column">
<input class="errorCount" size="1" value="1" style="margin-left: 2%"/>
<input type="hidden" value="1" id="stValue"/>
<select class="errorName" style="margin-left: 6%">
<option selected disabled>----- Select Error -----</option>
</select>
<input type="button" data-bid="addRow_1" id="addRow_1" class="addRow" value="Add"/>
</div>
</div>
</div>
**UPDATE:**Completely changed the code now it's much more simpler adding the solved answer here so it might help some one in the future.
//Add and remove function for the error text boxes
$(document).ready(function() {
$(document).on('click', '.addRow', function() {
var div = $("<div />"),
btnId = $(this).data("bid").match(/\d+/); //Breaks the number from the ID using .match
div.html(copy()); //Creates a new div container
$('.error-Column').append(div); //Insert all the HTML into the new div
$('#addRow_' + btnId).prop("disabled", true); //Disables the add button once clicked.
});
//Remove the text filed from the list and resets the error number
$(document).on('click', '.delRow', function() {
var btnId = $("#stValue").val(); //Read the value of stValue
btnId = btnId - 1; //Deduct 1 from the value to get the last ID
//Enables the 1st add button if the value equals 1
if (btnId === 1) {
$('#addRow_' + btnId).prop('disabled', false);
}
$(this).parent().remove(); //Remove the text row from the list.
resetErrorNo(); //Calls the reset function
});
});
//Reset the entire error count number index
function resetErrorNo() {
$(".errorCount").each(function(index, _this) {
$(this).val(index + 1);
$("#stValue").val(index + 1);
});
}
//HTML function which will be called by the button click event for the add button
function copy() {
var stNum = document.getElementById("stValue"),
genNum = (document.getElementById("stValue").value - 1) + 2;
stNum.value = genNum;
// language=HTML
return '<input class="errorCount" size="1" value="' + genNum + '" style="margin-left: 2%" readonly/>\n' +
'<select class="errorName" style="margin-left: 6%">\n' +
'<option selected disabled>----- Select Error -----</option>\n' +
'</select>\n' +
'<input type="button" class="addRow" id="addRow_' + genNum + '" data-bid="addRow_' + genNum + '" value="Add" />\n' +
'<input type="button" class="delRow" id="delRow_' + genNum + '" data-bid="delRow_' + genNum + '" value="Delete"/><br />'
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="jType-container">
<div id="error-Add-Container">
<div id="error-Column-Headings">
Error Number<span style="margin-left: 8%">Error Name</span>
</div>
<div class="error-Column">
<input class="errorCount" size="1" value="1" style="margin-left: 2%" />
<input type="hidden" value="1" id="stValue" />
<select class="errorName" style="margin-left: 6%">
<option selected disabled>----- Select Error -----</option>
</select>
<input type="button" data-bid="addRow_1" id="addRow_1" class="addRow" value="Add" />
</div>
</div>
</div>
Try with whenever, you delete any row, update all input with new number.
$(".errorCount").each(function(index, _this) {
$(this).val(index + 1);
});
Full Code
//Add and remove function for the error text boxes
$(document).ready(function() {
$(document).on('click', '.addRow', function() {
var div = $("<div />"),
btnId = $(this).data("bid").match(/\d+/); //Breaks the number from the ID using .match
div.html(copy()); //Creates a new div container
$('.error-Column').append(div); //Insert all the HTML into the new div
$('#addRow_' + btnId).prop("disabled", true); //Disables the add button once clicked.
});
//Remove the text filed from the list and resets the error number
$(document).on('click', '.delRow', function() {
var //btnId = $(this).data("bid").match(/\d+/),//Breaks the number from the ID using .match
maxNoList = $('input[class="addRow"]').length,
errNoList = maxNoList - 1;
//btnId = btnId - 1; //Calculates the ID number of the previous button
$('#addRow_' + errNoList).prop('disabled', false); // Enables the previous add button
$('#stValue').val(errNoList); //Set the value of stValue when removing the text filed
//So the error numbers will be generated accordingly when Add is clicked again.
$(this).parent().remove(); //Remove the text row from the list.
rearrange();
});
});
function rearrange() {
$(".errorCount").each(function(index, _this) {
$(this).val(index + 1);
});
}
//HTML function which will be called by the button click event for the add button
function copy() {
var stNum = document.getElementById("stValue"),
genNum = (document.getElementById("stValue").value - 1) + 2;
stNum.value = genNum;
// language=HTML
return '<input class="errorCount" size="1" value="' + genNum + '" style="margin-left: 2%" readonly/>\n' +
'<select class="errorName" style="margin-left: 6%">\n' +
'<option selected disabled>----- Select Error -----</option>\n' +
'</select>\n' +
'<input type="button" class="addRow" id="addRow_' + genNum + '" data-bid="addRow_' + genNum + '" value="Add" />\n' +
'<input type="button" class="delRow" id="delRow_' + genNum + '" data-bid="delRow_' + genNum + '" value="Delete"/><br />'
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="jType-container">
<div id="error-Add-Container">
<div id="error-Column-Headings">
Error Number<span style="margin-left: 8%">Error Name</span>
</div>
<div class="error-Column">
<input class="errorCount" size="1" value="1" style="margin-left: 2%" />
<input type="hidden" value="1" id="stValue" />
<select class="errorName" style="margin-left: 6%">
<option selected disabled>----- Select Error -----</option>
</select>
<input type="button" data-bid="addRow_1" id="addRow_1" class="addRow" value="Add" />
</div>
</div>
</div>
I have a form which has certain elements in it. I want to get all the elements inside the form regardless of their depth.
This is my test code
$(document).ready(function(){
//script.init(markchaining);
$('#checkbutton').click(function(){
$('#saveForm :input').each(function(key){
if($(this).is('select'))
{
var id = $(this).attr('id');
console.log('id is '+id);
$(this).trigger('change');
console.log('if-> Element name is '+$(this).attr('name'));
}
else
{
console.log('else-> Element name is '+$(this).attr('name'));
}
});
});
});
function addRow(ele,name)
{
var id = ele.id;
$('#'+id+'').closest('tr').after('<tr><td class="label-cell">New Row</td><td><input type="text" name="'+name+'" /></td></tr>');
}
My Problem
I also have dynamic elements which will be created on certain select change events during the iteration. I want to get these dynamically created elements as I iterate through my form.
I am not able to access the "New Row" element which gets created dynamically on clicking the 'check' button
This is my complete test code
Just added a count variable to distinguish the names on console. https://jsfiddle.net/ztpjacyu/
$(document).ready(function() {
//script.init(markchaining);
$('#checkbutton').click(function() {
$('#saveForm :input').each(function(key) {
if ($(this).is('select')) {
var id = $(this).attr('id');
console.log('id is ' + id);
$(this).trigger('change');
console.log('if-> Element name is ' + $(this).attr('name'));
} else {
console.log('else-> Element name is ' + $(this).attr('name'));
}
});
});
//Clicked twice to show you the console
$('#checkbutton').click();
$('#checkbutton').click();
});
var count = 0;
function addRow(ele, name) {
var id = ele.id;
$('#' + id + '').closest('tr').after('<tr><td class="label-cell">New Row</td><td><input type="text" name="' + name + ++count + '" /></td></tr>');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<form name="mainform" id="saveForm" action="#">
<!--##GENERAL##-->
<input type="button" name="checkbutton" id="checkbutton" value="Check" /> <- Moved here so that you can see the console
<div id="fromuser">
<table width="100%" id="userTable">
<tr id="ReportNameRow">
<td class="label-cell">Report Name :</td>
<td>
<input type="text" name="CustomReportName" id="CustomReportName" />
</td>
</tr>
<tr id="ReportNamrRow">
<td class="label-cell">* Saved Report Name :</td>
<td>
<select name="rname" id="rname" onChange="addRow(this,'MYID');">
<option value="">---Select---</option>
<option value="Cash_Position">Cash Position</option>
<option value="Detail_Report">Detail Report</option>
<option value="FCCS/FBPS_Detail_Report">FCCS/FBPS Detail Report</option>
<option value="Reconciliation_Report">Reconciliation Report</option>
<option value="Statement_Report">Statement Report</option>
<option value="CustomReport">Enter Custom Report Name</option>
</select>
</td>
</tr>
<input type="hidden" name="hiddenid" value="I am hidden" id="hiddenid" />
<tr id="submit">
<td class="label-cell"></td>
<td>
<input type="submit" name="submitbutton" id="submitbutton" value="Submit" />
</td>
</tr>
</table>
</div>
</form>
Update
if you want the element to be there before you execute your each , you can do this : https://jsfiddle.net/jbrt3Led/
$('#checkbutton').click(function() {
$("#rname").trigger('change');
$('#saveForm :input').each(function(key) {
if ($(this).is('select')) {
var id = $(this).attr('id');
console.log('id is ' + id);
console.log('if-> Element name is ' + $(this).attr('name'));
} else {
console.log('else-> Element name is ' + $(this).attr('name'));
}
});
});
I have a block of form elements which I would like to clone and increment their ID's using jQuery clone method. I have tried a number of examples but a lot of them only clone a single field.
My block is structured as such:
<div id="clonedInput1" class="clonedInput">
<div>
<div>
<label for="txtCategory" class="">Learning category <span class="requiredField">*</span></label>
<select class="" name="txtCategory[]" id="category1">
<option value="">Please select</option>
</select>
</div>
<div>
<label for="txtSubCategory" class="">Sub-category <span class="requiredField">*</span></label>
<select class="" name="txtSubCategory[]" id="subcategory1">
<option value="">Please select category</option>
</select>
</div>
<div>
<label for="txtSubSubCategory">Sub-sub-category <span class="requiredField">*</span></label>
<select name="txtSubSubCategory[]" id="subsubcategory1">
<option value="">Please select sub-category</option>
</select>
</div>
</div>
Obviously elements are lined up a lot better but you get the idea.
I would like to keep the id structure i.e. category1, subcategory1 etc as I use these to dynamically display select options based on the parent selection so if its possible to have each cloned block like category1/category2/category3 etc that would be great.
HTML
<div id="clonedInput1" class="clonedInput">
<div>
<label for="txtCategory" class="">Learning category <span class="requiredField">*</span></label>
<select class="" name="txtCategory[]" id="category1">
<option value="">Please select</option>
</select>
</div>
<div>
<label for="txtSubCategory" class="">Sub-category <span class="requiredField">*</span></label>
<select class="" name="txtSubCategory[]" id="subcategory1">
<option value="">Please select category</option>
</select>
</div>
<div>
<label for="txtSubSubCategory">Sub-sub-category <span class="requiredField">*</span></label>
<select name="txtSubSubCategory[]" id="subsubcategory1">
<option value="">Please select sub-category</option>
</select>
</div>
<div class="actions">
<button class="clone">Clone</button>
<button class="remove">Remove</button>
</div>
</div>
JavaScript - Jquery v1.7 and earlier
var regex = /^(.+?)(\d+)$/i;
var cloneIndex = $(".clonedInput").length;
$("button.clone").live("click", function(){
$(this).parents(".clonedInput").clone()
.appendTo("body")
.attr("id", "clonedInput" + cloneIndex)
.find("*").each(function() {
var id = this.id || "";
var match = id.match(regex) || [];
if (match.length == 3) {
this.id = match[1] + (cloneIndex);
}
});
cloneIndex++;
});
There is only one silly part :) .attr("id", "clonedInput" + $(".clonedInput").length) but it works ;)
JAvascript - JQuery recent (supporting .on())
var regex = /^(.+?)(\d+)$/i;
var cloneIndex = $(".clonedInput").length;
function clone(){
$(this).parents(".clonedInput").clone()
.appendTo("body")
.attr("id", "clonedInput" + cloneIndex)
.find("*")
.each(function() {
var id = this.id || "";
var match = id.match(regex) || [];
if (match.length == 3) {
this.id = match[1] + (cloneIndex);
}
})
.on('click', 'button.clone', clone)
.on('click', 'button.remove', remove);
cloneIndex++;
}
function remove(){
$(this).parents(".clonedInput").remove();
}
$("button.clone").on("click", clone);
$("button.remove").on("click", remove);
working example here
Another option would be to use a recursive function:
// Accepts an element and a function
function childRecursive(element, func){
// Applies that function to the given element.
func(element);
var children = element.children();
if (children.length > 0) {
children.each(function (){
// Applies that function to all children recursively
childRecursive($(this), func);
});
}
}
Then you can make a function or three for setting the attributes and values of your yet-to-be-cloned form fields:
// Expects format to be xxx-#[-xxxx] (e.g. item-1 or item-1-name)
function getNewAttr(str, newNum){
// Split on -
var arr = str.split('-');
// Change the 1 to wherever the incremented value is in your id
arr[1] = newNum;
// Smash it back together and return
return arr.join('-');
}
// Written with Twitter Bootstrap form field structure in mind
// Checks for id, name, and for attributes.
function setCloneAttr(element, value){
// Check to see if the element has an id attribute
if (element.attr('id') !== undefined){
// If so, increment it
element.attr('id', getNewAttr(element.attr('id'),value));
} else { /*If for some reason you want to handle an else, here you go*/ }
// Do the same with name...
if(element.attr('name') !== undefined){
element.attr('name', getNewAttr(element.attr('name'),value));
} else {}
// And don't forget to show some love to your labels.
if (element.attr('for') !== undefined){
element.attr('for', getNewAttr(element.attr('for'),value));
} else {}
}
// Sets an element's value to ''
function clearCloneValues(element){
if (element.attr('value') !== undefined){
element.val('');
}
}
Then add some markup:
<div id="items">
<input type="hidden" id="itemCounter" name="itemCounter" value="0">
<div class="item">
<div class="control-group">
<label class="control-label" for="item-0-name">Item Name</label>
<div class="controls">
<input type="text" name="item-0-name" id="item-0-name" class="input-large">
</div>
</div><!-- .control-group-->
<div class="control-group">
<label for="item-0-description" class="control-label">Item Description</label>
<div class="controls">
<input type="text" name="item-0-description" id="item-0-description" class="input-large">
</div>
</div><!-- .control-group-->
</div><!-- .item -->
</div><!-- #items -->
<input type="button" value="Add Item" id="addItem">
And then all you need is some jQuery goodness to pull it all together:
$(document).ready(function(){
$('#addItem').click(function(){
//increment the value of our counter
$('#itemCounter').val(Number($('#allergyCounter').val()) + 1);
//clone the first .item element
var newItem = $('div.item').first().clone();
//recursively set our id, name, and for attributes properly
childRecursive(newItem,
// Remember, the recursive function expects to be able to pass in
// one parameter, the element.
function(e){
setCloneAttr(e, $('#itemCounter').val());
});
// Clear the values recursively
childRecursive(newItem,
function(e){
clearCloneValues(e);
}
);
// Finally, add the new div.item to the end
newItem.appendTo($('#items'));
});
});
Obviously, you don't necessarily need to use recursion to get everything if you know going in exactly what things you need to clone and change. However, these functions allow you to reuse them for any size of nested structure with as many fields as you want so long as they're all named with the right pattern.
There's a working jsFiddle here.
Clone the main element, strip the id number from it.
In the new element replace every instance of that id number in every element id you want incremented with the new id number.
Ok, here's a quicky code here.
Basically, this part is the most important:
(parseInt(/test(\d+)/.exec($(this).attr('id'))[1], 10)+1
It parses the current id (using RegEx to strip the number from the string) and increases it by 1. In your case instead of 'test', you should put 'clonedInput' and also not only increase the value of the main element id, but the three from the inside as well (category, subcategory and subsubcategory). This should be easy once you have the new id.
Hope this helps. :)
Add data attribute to the input to get the field name, increment the value with variable.
html :
<td>
<input type="text" data-origin="field" name="field" id="field" required="" >
<div role="button" onclick='InsertFormRow($(this).closest("tr"),"tableID","formID");' id="addrow"> + </div>
</td>
and put this javascript function
var rowNum = 1;
var InsertFormRow = function(row, ptable, form)
{
nextrow = $(row).clone(true).insertAfter(row).prev('#' + ptable + ' tbody>tr:last');
nextrow.attr("id", rowNum);
nextrow.find("input").each(function() {
this.name = $(this).data("origin") + "_" + rowNum;
this.id = $(this).data("origin") + "_" + rowNum;
});
rowNum++;
}