jQuery - Event delegation only targeting first newly-created element - javascript

I'm trying to create a simple reddit-like system where a user can add a post and then interact with the voting system (which pastes along with the form).
While I have utilized event delegation, it only seems to be affecting my first newly-created element. Thus, on the first newly-created element, the voting system works.
On the latter ones, however, what seems to happen is that the event does get attached, but it updates the first voting system (every post gets a little voting system attached to it).
Any help is appreciated! Thank you.
$("#subbtn").on("click", function(event){
event.preventDefault();
var postTitle = $("#title").val(),
postBody = $("#content").val();
$("#title").val("");
$("#content").val("");
var html = "<div class='wrapper'><div class='panel panel-default'><p class='button' id='plus'>+</p><p id='count'>0</p><p class='button' id='minus'>-</p><h3>'" + postTitle + "</h3><p>" + postBody + "</p></div></div>";
$("body").append(html);
});
var counter = 0;
$(document).on("click", "#plus", function() {
counter++;
$("#count").text(counter);
});
$(document).on("click","#minus", function() {
counter--;
$("#count").text(counter);
});
My HTML is:
<body>
<div class="panel panel-default" id="formStuff">
<div class="form-group">
<label for="title">Title </label> </label>
<input type="title" id="title" class="form-control">
</div>
<div class="form-group">
<label for="content">Content </label>
<textArea rows="5" type="content" id="content" class="form-control"></textArea>
</div>
<input type="submit" class="btn btn-success" id="subbtn">
</div>
</body>

You are adding multiple voting systems with same IDs plus,count and minus. But Ids should be unique. Instead use classes with same classes and make the selector work on the classes. Please check below snippet for more understanding.
$("#subbtn").on("click", function(event){
event.preventDefault();
var postTitle = $("#title").val(),
postBody = $("#content").val();
$("#title").val("");
$("#content").val("");
var html = "<div class='wrapper'><div class='panel panel-default'><p class='button plus'>+</p><p class='count'>0</p><p class='button minus'>-</p><h3>'" + postTitle + "</h3><p>" + postBody + "</p></div></div>";
$("body").append(html);
});
$(document).on("click", ".plus", function() {
var counter = $(this).siblings(".count").text();
counter++;
$(this).siblings(".count").text(counter);
});
$(document).on("click",".minus", function() {
counter--;
var counter = $(this).siblings(".count").text();
counter--;
$(this).siblings(".count").text(counter);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="panel panel-default" id="formStuff">
<div class="form-group">
<label for="title">Title </label> </label>
<input type="title" id="title" class="form-control">
</div>
<div class="form-group">
<label for="content">Content </label>
<textArea rows="5" type="content" id="content" class="form-control"></textArea>
</div>
<input type="submit" class="btn btn-success" id="subbtn" />
</div>

This is happening because of the following line:
$(document).on("click", "#plus", function() {...});
// here you are using id selector which are unique.

Related

Jquery : Find only one nearest matching element

i am adding form fields dynamically using Below code
$(document).ready(function () {
var add_fields = "" +
"<div class='col-md-3 form-group pull-right'>" +
"<label>Please select a field type</label>" +
"<select name='add_fields' class='form-control' id='add_fields'>" +
"<option value=''>Please Select a value</option>" +
"<option value='text'>Text Field</option>" +
"<option value='select'>Select List</option>" +
"<option value='radio'>Radio Buttons</option>" +
"<option value='checkboxes'> Checkboxes</option>" +
"<option value='file'> File Upload</option>" +
"</select></div>";
var text_field_append= "" +
"<div class='row'>" +
"<div class='col-md-3 '>" +
"<div class='form-group'>" +
"<label>Add Field Label</label>" +
"<input type='text' name='textfield_label' class='form-control'>" +
"</div>" +
"</div>" +
"<div class='col-md-3'> " +
"<label></label><input type='text' placeholder='' name='' class='form-control field' disabled >" +
"</div>" +
"</div>";
$('#add_form').on('click',function (e) {
$('#form_holder').append(add_fields);
$('#add_fields').on('change',function () {
if($(this).val()=='text'){
$('#form_holder').append(text_field_append);
var nearest_field= $("[name='textfield_label']").closest('.row').find('.field');
$("[name='textfield_label']").on('input',function(e){
$(nearest_field).attr("placeholder", $(this).val());
var field_name =$(this).val().replace(/ /g,"_");
$(nearest_field).attr("name", field_name);
});
}
})
})
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="col-md-12">
<h1>Please use Following wizard to generate your form </h1>
<p>Click on Add Fields to get started </p>
<a id="add_form" class="btn btn-primary pull-right">Add Fields</a>
</div>
<form id="myform">
<div id="form_holder">
</div>
</form>
now upon adding a text field i am selecting nearest added element as below:
var nearest_field= $("[name='textfield_label']").closest('.row').find('.field');
Problem with this is i want only latest added(nearest) element to be selected while it selects all the elements, Can someone please advise how can i fix it
The issue is partly due to the repeated id attributes in the dynamic content, which need to be replaced with common class attributes, and also with the nested event handlers.
To both fix the issue and improve the logic, remove all the HTML from the JS and place it within 'templates' in the HTML. Your JS should ideally contain no HTML at all as it's a violation of the Separation of Concerns principle
From there you can use delegated event handlers, bound at runtime, to handle the events on all dynamic elements. These event handlers can use DOM traversal to relate the 'label' to the relevant 'placeholder'.
Finally, note that the template for the field types uses a pattern whereby the first part of its id matches the value of the option used to append it. This way the code is extensible, and your logic can be simplified.
Try this:
jQuery($ => {
let $add_form = $('#add_form');
let $form_holder = $('#form_holder');
let add_fields = $('#fields').html();
$add_form.on('click', function(e) {
$form_holder.append(add_fields);
});
$form_holder.on('change', '.add_fields', e => {
let fieldHtml = $(`#${e.target.value}_field`).html();
$form_holder.append(fieldHtml);
});
$form_holder.on('input', '.text-field-label', e => {
let $label = $(e.target);
let labelValue = $label.val();
let $placeholder = $label.closest('.row').find('.text-field');
$placeholder.prop({
placeholder: labelValue,
name: labelValue,
value: labelValue.replace(/ /g, '_')
});
});
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="col-md-12">
<h1>Please use Following wizard to generate your form </h1>
<p>Click on Add form to get started </p>
<a id="add_form" class="btn btn-primary pull-right">Add Form</a>
</div>
<form id="myform">
<div id="form_holder"></div>
</form>
<script type="text/html" id="fields">
<div class="col-md-3 form-group pull-right"><label>Please select a field type</label>
<select name="add_fields" class="form-control add_fields">
<option value="">Please Select a value</option>
<option value="text">Text Field</option>
<option value="select">Select List</option>
<option value="radio">Radio Buttons</option>
<option value="checkboxes">Checkboxes</option>
<option value="file">File Upload</option>
</select>
</div>
</script>
<script type="text/html" id="text_field">
<div class="row">
<div class="col-md-3">
<div class="form-group">
<label>Add Field Label</label>
<input type="text" name="textfield_label" class="form-control text-field-label" />
</div>
</div>
<div class="col-md-3">
<label></label>
<input type="text" placeholder="" name="" class="form-control text-field" disabled />
</div>
</div>
</script>

Button click function not working in jQuery

So I'm developing a website for a medical clinic and they asked me to add a button beneath every doctor to make an appointment.
this is what i have for the doctors section
for (var i = 0; i < 3; i++) {
$('#get_medicos').append(
'<div class="col-md-3 dummy">' +
'<div class="text-box">' +
'<img src="assets/images/corpo-clinico/' + medico[i].ficheiro + '" alt="" class="img-responsive"/>' +
'<div class="clearfix"></div>' +
'<div class="text-box white padding-3">' +
'<h5 class="less-mar1 text-blue">' + medico[i].nome +'</h5>' +
'<p>' + medico[i].especialidade + '</p>' +
'<a id="marcar" type="button" class="btn btn-primary">Marcar consulta</a>' +
'</div>' +
'</div>' +
'</div>'
);
}
The then code for the click function (that doesn't work):
$('#marcar').click(function() {
var offset = $('#marcacao').offset();
$('html, body').animate({
scrollTop: offset.top-100,
scrollLeft: offset.left
}, 1000);
$('#marcacao-consulta').find('#especialidade-marcacao option[id="default"]').text(medico[i].especialidade);
$('#marcacao-consulta').find('#corpo-clinico option[id="default"]').text(medico[i].nome);
console.log('test');
});
This is all inside a $(document).ready(function() {}); and what should do is when i click that button beneath the doctor, should go up to the form and fill the doctor's name and specialty... but it seems it's not working for some reason... this is a copy of other click functions in the code, but they seem to work fine.
HTML form:
<div id="marcacao-consulta" data-target="#marcacao-consulta">
<div class="row">
<div class="col-md-6 col-lg-6 col-sm-12">
<div class="section">
<label class="field select prepend-icon">
<select id="especialidade-marcacao" class="gui-input">
<option id="especialiade-default" value="default">Escolha a especialidade</option>
<?
$query = $dbHandle->prepare("
SELECT `especialidade`
FROM `especialidade`
ORDER BY `especialidade` ASC
");
$query->execute();
if ($query->rowCount() > 0) {
while ($row = $query->fetch(PDO::FETCH_ASSOC)) { ?>
<option value="<?=$row["especialidade"]; ?>"><?=$row["especialidade"]; ?></option>
<? }
} else { ?>
<option value="">Nenhum resultado</option>
<? }
?>
</select>
<span class="field-icon"><i class="fas fa-heartbeat"></i></span>
</label>
</div>
</div>
<div class="col-md-6 col-lg-6 col-sm-12">
<div class="section">
<label class="field select prepend-icon">
<select id="corpo-clinico-marcacao" class="gui-input">
<option id="corpo-clinico-default" value="default">Escolha o médico</option>
<?
$query = $dbHandle->prepare("
SELECT `nome`
FROM `medico`
ORDER BY `nome` ASC
");
$query->execute();
if ($query->rowCount() > 0) {
while ($row = $query->fetch(PDO::FETCH_ASSOC)) { ?>
<option value="<?=$row["nome"]; ?>"><?=$row["nome"]; ?></option>
<? }
} else { ?>
<option value="">Nenhum resultado</option>
<? }
?>
</select>
<span class="field-icon"><i class="fas fa-user-md"></i></span>
</label>
</div>
</div>
<div class="col-md-12 col-lg-12 col-sm-12">
<div class="section">
<label class="field prepend-icon">
<input id="nome" class="gui-input" type="text" placeholder="Nome Completo">
<span class="field-icon"><i class="fas fa-user"></i></span>
</label>
</div>
<div class="section">
<label class="field prepend-icon">
<input id="email" class="gui-input" type="text" placeholder="Endereço de correio eletrónico">
<span class="field-icon"><i class="fas fa-envelope"></i></span>
</label>
</div>
<div class="section">
<label class="field prepend-icon">
<input id="telefone" class="gui-input" type="text" placeholder="Telefone/Télemovel">
<span class="field-icon"><i class="fas fa-phone-square"></i></span>
</label>
</div>
<div class="section">
<label class="field prepend-icon">
<input id="tipo" class="gui-input" type="text" value="consulta" disabled>
</label>
</div>
</div>
</div>
</div>
You have to add the element and register the event for the element. Here is the fiddle which works for you
https://jsfiddle.net/0q3kpyfv/
Your sample HTML
<div id="get_medicos">
</div>
Sample jquery code
Notice I have added the data-val attribute to the added anchor tag which will help you to get the information and perform the logic based on which button is clicked. you can pass dynamic data to data-val attribute and use it in click event.
$(document).ready(function() {
var sampleString = "";
var medico = [{'especialidade':'speciality 0','nome':'Doctor 0'},{'especialidade':'speciality 1','nome':'Doctor 1'},{'especialidade':'speciality 2','nome':'Doctor 2'}]
for (var i = 0; i < 3; i++) {
var doctorData = medico[i];
$('#get_medicos').append(
'<div class="col-md-3 dummy">' +
'<div class="text-box">' +
'<img src="assets/images/corpo-clinico/' + medico[i].especialidade + '" alt="" class="img-responsive"/>' +
'<div class="clearfix"></div>' +
'<div class="text-box white padding-3">' +
'<h5 class="less-mar1 text-blue">' + medico[i].nome +'</h5>' +
'<p>' + medico[i].especialidade + '</p>' +
'<a id="marcar" data-doctor-especialiadade="'+medico[i].especialidade+'" data-doctor-nome="'+medico[i].nome+'" type="button" class="btn btn-primary">Marcar consulta'+i+'</a>' +
'</div>' +
'</div>' +
'</div>'
);
};
$('#get_medicos').on('click','a',function(event){
var elementClicked = event.target;
var doctorEspecialiadade = $(elementClicked).data('doctor-especialiadade');
var doctorName = $(elementClicked).data('doctor-nome');
$('#marcacao-consulta').find('#especialidade-marcacao option[id="default"]').text(doctorEspecialiadade);
$('#marcacao-consulta').find('#corpo-clinico option[id="default"]').text(doctorName);
})
});
if you create the button after your event, you could have problem so, use the delegate version of click:
$('div').on('click', 'a', (function()....
and better put an id on the ancestor div:
'<div class="text-box white padding-3" id="mydiv"'
:
$('#mydiv').on('click', 'a', (function()....
another thing, with the loop you will have same id more time in your html??its no good.
so you'll have to rebuild your program logic...and bind the event with the right button (use a common class) it will be better than an id
If you bind the event to the parent element, and filter by the children, you can listen to any new elements that are added, doesn't matter how many.
<div class="container"></div>
<button class="js-add-new">Add new</button>
const $addNew = $('.js-add-new')
const $container = $('.container')
let count = 0
$addNew.on("click", () => {
count += 1
$container.append(`
<div>
<button>log me ${count}</button>
</div>
`)
})
$container.on("click", "button", (event) => {
console.log(event.currentTarget)
})
A working example: https://codepen.io/alexmccabe/pen/jOrXZxj?editors=1111
The button click is working. Here is a fiddle showing it does:
https://jsfiddle.net/bradberkobien/qL4m10y6/3/
There must be an issue with the code that comes before the console.log("test") line within the click. I would use the debugger to help you with that.

passing corresponding text-field values into the function which has the same id's

I have a button called "Add text field". When it is clicked, the group of HTML elements like two text-fields-"Text input", "file name" and one button -"Download audio file", would be created. When a "Download audio file" button is clicked, it should take the input from the corresponding text fields like "Text input" and "file name" to be passed into the function start().
Important thing is these text fields are added into the DOM with innerHTML so all the iteration would have the same id for the text-fields and even for button.
My HTML:
<form class="col-sm-12">
<div id="textfields">
<div class="form-row">
<div class="col-sm-8">
<div class="form-group">
<label for="Textarea1">Text Input</label>
<!--
<textarea class="form-control" id="textarea1" rows="10"></textarea>-->
<textarea class='form-control' id='textarea'"+textareaid=1+" rows='10'></textarea>
</div>
</div>
<div class="col-sm-3 ml-auto">
<div class="form-row">
<label for="Textarea2">File Name</label>
<!--
<input type="text" class="form-control" id="filename">-->
<input type='text' class='form-control' id='filename'"+filenameid=1+">
</div></br>
<div class="form-row text-center">
<div class="col-12">
<button type="button" class="btn btn-primary" onclick="start();">Download audio file</button>
</div>
</div>
</div>
</div>
</div>
<button type="button" class="btn btn-primary" onclick="addTextFields();">Add Text field</button>
</form>
JavaScript to add text-fields:
var textareaid=2; var filenameid=2;
function addTextFields(){
var objTo = document.getElementById('textfields');
var divtest = document.createElement("div");
divtest.innerHTML = "<div class='form-row'><div class='col-sm-8'><div class='form-group'><label for='Textarea1'>Text Input</label><textarea class='form-control' id='textarea'"+textareaid+" rows='10'></textarea></div></div><div class='col-sm-3 ml-auto'><div class='form-group'><label for='Textarea2'>File Name</label><input type='text' class='form-control' id='filename'"+filenameid+"></br><div class='form-row text-center'><div class='col-12'><button type='button' class='btn btn-primary' onclick='start();'>Download audio file</button></div></div></div></div></div>";
objTo.appendChild(divtest);
textareaid++;
filenameid++;
}
API request for start():
'body': {
"input": {
"text":document.getElementById("textarea"+textareaid).value,
"filename":document.getElementById("filename"+filenameid).value
},
"voice": {
"languageCode": document.getElementById("languages").value,
"ssmlGender": document.getElementById("gender").value,
"name": document.getElementById("entries").value
}
}
Problem is, when the button is clicked from the second group of elements, it is still taking the parameters from first iteration instead of the second one.
This is how the elements look like in HTML.
Any ideas would be useful.
Since Id's should not be same use class if you want to control multiple controls with same name. You can assign different ids to each textarea by replacing script with this so that every time new id will generate for every textarea hence it will unique.
<script>
var textareaid=2;
function addTextFields(){
var objTo = document.getElementById('textfields');
var divtest = document.createElement("div");
divtest.innerHTML = "<div class='form-row'><div class='col-sm-8'><div class='form-group'><label for='Textarea1'>Text Input</label><textarea class='form-control' id='textarea"+textareaid+"'"+
"rows='10'></textarea></div></div><div class='col-sm-3 ml-auto'><div class='form-group'><label for='Textarea2'>File Name</label><input type='text' class='form-control' id='textarea"+textareaid+"></br><div class='form-row text-center'><div class='col-12'><button type='button' class='btn btn-primary' onclick='start();'>Download audio file</button></div></div></div></div></div>";
objTo.appendChild(divtest);
textareaid++;
}
</script>

Replicating and differentiating portions of a form

UPDATE:
Using the code that colecmc provide(Thank you!!) I updated the codepen. I like how the date.now is added, but I would like to just do a an incremental increase. Im not sure how to apply that to this function I tried zer00ne's index incremental but am doing something wrong.
let cloneList = [],
index = 0; // index must be declared apart from function or else you will set it to the initial value every time the function is called.
document.getElementById('launch').onclick = function(event) {
event.preventDefault();
var addOnDiv = document.getElementById('addon');
var container = document.getElementById('add-components')
var clonedNode = addOnDiv.cloneNode(true);
var component = clonedNode.querySelector('input');
index++;
clonedNode.id = index+1;
cloneList.push(clonedNode.id);
component.id = `componentID_${clonedNode.id}`;
component.name = `componentName_${clonedNode.id}`;
container.appendChild(clonedNode);
}
Im having an issue with my form. Initially I had two forms on the page. However on submit only the info from the first form was written. I tried combining the forms. Now if i fill out the campaign and component inputs and submit it writes to the correct tables(good!). However the component section is supposed to be replicated. A campaign can have as many components as the user wants. I am using cloneNode and before I combined the table it added more component sections. Now that they are combined the function no longer works. Im confused if this is even the right approach for what Im doing. I included a copdpen that shows a stripped down version of what Im trying to do.
Basically I want to be able to press add component, add as many new components as I'd like fill them out and have then all written as records to the db. I need a way to differentiate all the clones (new ids or names?)
codepen: https://codepen.io/anon_guy/pen/VMZWWW?editors=1010
HTML:
<div class="panel panel-default">
<div class="panel-heading">
</div>
<div class="panel-body">
<form action="<?php echo $action; ?>" method="post" enctype="multipart/form-data" id="form-event" class="form-horizontal">
<div class="col-sm-4">
<label>name</label>
<input type="text" name="name" value="name" placeholder="name" id="name" class="form-control" />
</div>
<div class="col-sm-4">
<label>address</label>
<input type="text" name="address" value="address" placeholder="address" id="address" class="form-control" />
</div>
<div class="col-sm-4">
<label>phone</label>
<input type="text" name="phone" value="phone" placeholder="phone" id="phone" class="form-control" />
<div class="text-danger"></div>
</div>
</div>
<div class="row">
<div class="add_component">
<button id='launch'>Add Component</button>
</div>
</div>
</div>
<div class="wrapper" id="add-components">
<div class="panel panel-default " id="addon">
<div class="panel-heading">
</div>
<div class="panel-body">
<div class="col-sm-6">
<label>component</label>
<input type="text" name="component" value="component" placeholder="component" id="component" class="form-control" />
</div>
</form>
</div>
</div>
</div>
JS:
document.getElementById('launch').onclick = function() {
var addOnDiv = document.getElementById('addon');
var container = document.getElementById('add-components')
var clonedNode = addOnDiv.cloneNode(true);
container.appendChild(clonedNode );
}
You will want to try something like this before appending to the container clonedNode.id = Date.now();
That will provide a way to differentiate all the clones by giving a unique id. You can take it a step further like this:
let cloneList = [];
document.getElementById('launch').onclick = function(event) {
event.preventDefault();
var addOnDiv = document.getElementById('addon');
var container = document.getElementById('add-components')
var clonedNode = addOnDiv.cloneNode(true);
var component = clonedNode.querySelector('input');
clonedNode.id = Date.now();
cloneList.push(clonedNode.id);
component.id = `componentID_${clonedNode.id}`;
component.name = `componentName_${clonedNode.id}`;
container.appendChild(clonedNode);
}
<div class="panel panel-default">
<div class="panel-heading">
</div>
<div class="panel-body">
<form action="<?php echo $action; ?>" method="post" enctype="multipart/form-data" id="form-event" class="form-horizontal">
<div class="col-sm-4">
<label>name</label>
<input type="text" name="name" value="name" placeholder="name" id="name" class="form-control" />
</div>
<div class="col-sm-4">
<label>address</label>
<input type="text" name="address" value="address" placeholder="address" id="address" class="form-control" />
</div>
<div class="col-sm-4">
<label>phone</label>
<input type="text" name="phone" value="phone" placeholder="phone" id="phone" class="form-control" />
<div class="text-danger"></div>
</div>
</div>
<div class="row">
<div class="add_component">
<button id='launch'>Add Component</button>
</div>
</div>
</div>
<div class="wrapper" id="add-components">
<div class="panel panel-default " id="addon">
<div class="panel-heading">
</div>
<div class="panel-body">
<div class="col-sm-6">
<label>component</label>
<input type="text" name="component" value="component" placeholder="component" id="component" class="form-control" />
</div>
</form>
</div>
</div>
</div>
This is the closest I came to what I believe is your way of thinking by looking at your code. (I also removed some unnecessary steps in your code to make it a little bit cleaner). This is for if you must have different names and ID:s on your inputs. However, if you can manage to have the same for both (i.e. component_0, other_0 etc.), you can remove the "names" array and the "names" forEach.
When you want to add an input to your addon-div, just add the ID (and name if you decide to keep it), without the "_0", to the array/s as in the example.
Change the name to "otherName_0" and ID to "otherID_0" in your html and this should work.
var i = 1;
document.getElementById('launch').onclick = function(event) {
event.preventDefault();
var addOnDiv = document.getElementById('addon');
var container = document.getElementById('add-components')
var clonedNode = addOnDiv.cloneNode(true);
var ids = ['componentID', 'otherID'];
var names = ['componentName', 'otherName'];
ids.forEach(function(id) {
var currentInput = clonedNode.querySelector(`#${id}_0`);
currentInput.id = `${id}_${i}`;
});
names.forEach(function(name) {
var currentInput = clonedNode.querySelector(`input[name=${name}_0]`);
currentInput.name = `${name}_${i}`;
});
container.appendChild(clonedNode);
i++;
}

Cloning a div and changing the id's of all the elements of the cloned divs

I am working with a django project, and part of the requirement is to have a button on the html page which when clicked clones a particular div and appends it to the bottom of the page as shown in the screenshot:
Screenshot of the Page
I was successful in doing this applying the following code:
var vl_cnt =1; //Initial Count
var original_external_int_div = document.getElementById('ext_int_div_1'); //Div to Clone
function addVL(){
var clone = original_external_int_div.cloneNode(true); // "deep" clone
clone.id = "ext_int_div_" + ++vl_cnt; // there can only be one element with an ID
original_external_int_div.parentNode.append(clone);
var cloneNode = document.getElementById(clone.id).children[0].firstElementChild.firstElementChild;
cloneNode.innerText = "External Interface "+vl_cnt; //Change the Header of the Cloned DIV
$(clone).find('input:text').val('') //Clear the Input fields of the cloned DIV
document.getElementById("vl_count").value = vl_cnt; //Keep track of the number of div being cloned
window.scrollTo(0,document.body.scrollHeight);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="height:0px;clear:both"></div>
<div style="float:right">
<span class="label label-primary" id="add_cp_button" style="cursor: pointer;" onclick="addVL()">+ Add VL </span>
</div>
<div style="height:0px;clear:both"></div>
<div>
<div id="ext_int_div_1">
<div class="section">
<fieldset class="scheduler-border">
<legend class="scheduler-border">External Interface 1</legend>
<div class="sectionContent" style="border:0px solid grey;width:75%">
<div style="height:15px;clear:both"></div>
<div class="form-group">
<div class="col-sm-4">
<label>Name</label>
</div>
<div class="col-sm-8">
<input type="text" class="form-control" name="vl_name_1" id="vl_name_1" placeholder="Name"/>
</div>
</div>
<div style="height:15px;clear:both"></div>
<div class="form-group">
<div class="col-sm-4">
<label>Connectivity Type</label>
</div>
<div class="col-sm-8">
<select class="form-control" name="vl_connectivity_type_1" id="vl_connectivity_type_1">
<option value="VIRTIO">VIRTIO</option>
<option value="">None</option>
</select>
</div>
</div>
<div style="height:15px;clear:both"></div>
<div class="form-group">
<div class="col-sm-4">
<label>Connection point Ref</label>
</div>
<div class="col-sm-8">
<select class="form-control" name="vl_con_ref_1" id="vl_con_ref_1" />
</select>
</div>
</div>
<div style="height:15px;clear:both"></div>
</div>
</fieldset>
<div style="height:2px;clear:both;"></div>
</div>
</div>
</div>
<input type="hidden" name="vl_count" id="vl_count" value="1" />
Now i have a new issue, i need to make sure that the ID's of the elements withing the DIV are unique too, for example the the ID = "vl_name_1" for the first input box must be changed to "vl_name_2" when creating the creating the clone.
I tried the following example and added the snipped within my addVL() function just to see if any changes happen to my div's:
$("#ext_int_div_1").clone(false).find("*[id]").andSelf().each(function() { $(this).attr("id", $(this).attr("id") + clone.id); });
However, the above code got me nothing ( i am pretty sure the above piece of code is rubbish since i have no clue what it is doing).
Help appreciated here.
Thank you
I hope the snippet below helps.
$(document).ready(function () {
$sharerCount = 1;
$('#addSharer').click(function() {
if($sharerCount < 5) {
$('#sharer_0').clone().attr('id', 'sharer_' + $sharerCount).insertAfter('.sharers:last').find("*[id]").attr('id', 'input_' + $sharerCount).val("").clone().end();
$sharerCount += 1;
}
else {
$('#addSharer').prop('disabled', 'true');
}
});
});
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<div class="form">
<div class="form-group">
<label class="control-label col-sm-3 col-xs-12">Share With<span class="red-text">*</span></label>
<div class="col-sm-9 col-xs-12">
<div id="sharer_0" class="field-group sharers">
<input id="input_0" type="text" class="form-control field-sm">
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-9 col-xs-12">
<button id="addSharer" type="button" class="btn btn-success">Add Another</button>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
I did the following and solved my problem:
var vl_cnt =1; //Initial Count
var original_external_int_div = document.getElementById('ext_int_div_1'); //Div to Clone
function addVL(){
var clone = original_external_int_div.cloneNode(true); // "deep" clone
clone.id = "ext_int_div_" + ++vl_cnt; // there can only be one element with an ID
original_external_int_div.parentNode.append(clone);
var cloneNode = document.getElementById(clone.id).children[0].firstElementChild.firstElementChild;
cloneNode.innerText = "External Interface "+vl_cnt; //Change the Header of the Cloned DIV
$(clone).find("*[id]").each(function(){
$(this).val('');
var tID = $(this).attr("id");
var idArray = tID.split("_");
var idArrayLength = idArray.length;
var newId = tID.replace(idArray[idArrayLength-1], vl_cnt);
$(this).attr('id', newId);
});
document.getElementById("vl_count").value = vl_cnt; //Keep track of the number of div being cloned
window.scrollTo(0,document.body.scrollHeight);
Thank you #ProblemChild for giving me the pointer in the right direction, I cannot upvote #ProblemChild for providing partial solution.

Categories

Resources