I'm looking to clone addDriverContent (working fine) and increment the numbers for the name attribute on name="description" to name="description2", name="description3" on the clones
Also if anyone know how to also clone the add button so it works as it should on the clones would be extra points :) Some fiddles would be awesome :)
<div id="addDriverContent" style="display:none;">
<div class="content">
<div class="row">
<div class="col-md-12">
<label for="description" class="form-label font-weight-bold">Item Description:</label>
<input type="text" class="form-control" id="description" name="description" placeholder="Enter the items description"/>
</div>
</div>
</div>
</div>
<button type="button" class="add_field_button" id="clone_button">Add another item</button>
<div id="clone_wrapper"></div>
<script type="text/javascript">
$(function($) {
var max_fields = 4;
// origin selector would select all the first div ancestors.
var $content = $("#addDriverContent > .content");
var $clone_wrapper = $("#clone_wrapper") ;
var $add_button = $(".add_field_button"); //Add button ID
$add_button.click(function(e) {
e.preventDefault();
var counter = 0;
// jquery object is array liked object. Length mean how many elements is selected.
if ( $clone_wrapper.children(".content").length < max_fields )
$content.clone().appendTo($clone_wrapper);
});
$clone_wrapper.on("click",".remove_field", function(e){
e.preventDefault();
// this would be more specific.
$(this).parent(".content").remove();
})
});
</script>
As I have no idea what you intend to do with it, I will provide you with my dirty solution for it:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="addDriverContent" style="display:none;">
<div class="content">
<div class="row">
<div class="col-md-12">
<label for="description" class="form-label font-weight-bold">Item Description:</label>
<input type="text" class="description form-control" id="description" name="description" placeholder="Enter the items description"/>
<input type="text" class="fname form-control" id="fname" name="fname"/>
Remove<button type="button" class="add_field_button" id="clone_button">Add another item</button>
</div>
</div>
</div>
</div>
<button type="button" class="add_field_button" id="clone_button">Add another item</button>
<div id="clone_wrapper"></div>
<script type="text/javascript">
$(function($) {
var max_fields = 4;
// origin selector would select all the first div ancestors.
var $content = $("#addDriverContent > .content");
var $clone_wrapper = $("#clone_wrapper") ;
var $add_button = $(".add_field_button"); //Add button ID
$(".add_field_button").click(function() {
//e.preventDefault();
//var counter = 0;
// jquery object is array liked object. Length mean how many elements is selected.
if ( $clone_wrapper.children(".content").length < max_fields ) {
$content.clone().appendTo($clone_wrapper);
//$add_button.clone().appendTo($clone_wrapper);// mine
$(".description").each(function(index) {
$( this ).attr('name', 'description'+index)
});
$(".fname").each(function(index) {
$( this ).attr('name', 'fname'+index)
});
}
});
$(document).on('click', "#clone_wrapper .add_field_button", function () {
$('#addDriverContent + .add_field_button').trigger('click');
})
$(document).on('click', ".remove_field", function () {
//e.preventDefault();
// this would be more specific.
$(this).closest(".content").remove();
});
});
</script>
Related
I'm trying to create an interactive resume template using javascript and html and have managed to use cloneNode to duplicate work history blocks (see attached screenshot)
The problem(s) I am having is that clicking on the add list item button in the cloned/duplicated work history block at the bottom, creates a <li> item in the 1st/cloned element.
The objective is to be able to add or delete ````` list elements within a specific work history block and to also be able to add/remove entire work history sections. Currently it deletes from the top down, which is also an issue.
Thanks for any pointers in advance.
CODE
<!DOCTYPE html>
<html>
<body>
<div id="test">
<div id="node">
<div class="work_history">
<div class="row">
<strong>
<input type="text" name="company" value="ACME Company">
</strong>
</div>
<div class="row">
<input type="text" name="position" value="Cheese Taster">
</div>
<input type="text" name="start" value="1/2019">
<input type="text" name="end" value="2/2020">
<ul id="list">
<li>
<textarea id="task" name="task" rows="4" cols="50">Did some things. Tasted cheese.</textarea>
</li>
<button onclick="addTask()">Add List Item</button>
<button onclick="RemoveTask()">Delete List Item</button>
</ul>
<button onclick="addWork()">Add Work</button>
<button onclick="removeWork()">Remove Work</button>
</div>
</div>
</div>
<script>
function addWork() {
var div = document.getElementById("node");
var cln = div.cloneNode(true);
//cln.setAttribute( 'id', 'newId');
document.getElementById("test").appendChild(cln);
}
function removeWork(){
var last = document.getElementById("test");
// want to delete the last added work history not first
last.removeChild(last.childNodes[0]);
}
function addTask(){
var ul = document.getElementById("list");
var task = document.getElementById("task");
var li = document.createElement("li");
li.setAttribute('id',task.value);
li.appendChild(document.createTextNode(task.value));
ul.appendChild(li);
}
function removeTask(){
var ul = document.getElementById("list");
var task = document.getElementById("task");
var item = document.getElementById(task.value);
ul.removeChild(item);
}
</script>
</body>
</html>
You'd have to use e.currentTarget instead of document.getElementById, otherwise you're only referring to the first instance of it:
function addWork(e) {
const div = e.currentTarget.parentElement;
const cln = div.cloneNode(true);
document.getElementById("test").appendChild(cln);
}
function removeWork(e) {
const last = e.currentTarget.parentElement;
last.parentElement.removeChild(last);
}
function addTask(e) {
const ul = e.currentTarget.parentNode;
let task = ul.children[0].childNodes[1].value;
let li = document.createElement("li");
// Replace paragraph breaks
task = task.replace(/\r?\n|\r/g, " ");
li.innerText = task;
ul.appendChild(li);
}
function removeTask(e) {
const ul = e.currentTarget.parentNode;
ul.removeChild(ul.lastChild);
}
<!DOCTYPE html>
<html>
<body>
<div id="test">
<div id="node">
<div class="work_history">
<div class="row">
<strong>
<input type="text" name="company" value="ACME Company">
</strong>
</div>
<div class="row">
<input type="text" name="position" value="Cheese Taster">
</div>
<input type="text" name="start" value="1/2019">
<input type="text" name="end" value="2/2020">
<ul id="list">
<li>
<textarea name="task" rows="4" cols="50">Did some things. Tasted cheese.</textarea>
</li>
<button onclick="addTask(event)">Add List Item</button>
<button onclick="removeTask(event)">Delete List Item</button>
</ul>
<button onclick="addWork(event)">Add Work</button>
<button onclick="removeWork(event)">Remove Work</button>
</div>
</div>
</div>
</body>
</html>
This allows you to refer to the specific element where the click event occurred and add/remove any elements that are relative within the DOM.
As a side note, it's best practice to have unique id attributes, adding the same id to multiple elements goes against that.
var add_button = $(".add_form_field");
var wrapper = $(".container1");
var max_fields = 9;
var x = 1;
$(add_button).click(function (e) {
e.preventDefault();
if (x < max_fields) {
x++;
$(wrapper).append(
` <div class="email">
<label for="">Year</label>
<input type="text" name="eduYear${x}">
<label for="">Title Name</label>
<input type="text" name="eduTitle${x}">
<label for="">Institution/School Name</label>
<input type="text" name="eduPlace${x}">
<label for="">Details</label>
<input type="text" name="eduNotes${x}"> <br>Delete<hr></div>`
); //add input box
}
});
$(wrapper).on("click", ".delete", function (e) {
e.preventDefault();
$(this).parent("div").remove();
x--;
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container1">
<h2>Educations</h2>
<button type="button" class="add_form_field">Add Education
<span style="font-size:16px; font-weight:bold;">+ </span>
</button>
<div class="email">
<label for="">Year</label>
<input type="number" name="eduYear1">
<label for="">Title Name</label>
<input type="text" name="eduTitle1">
<label for="">Institution/School Name</label>
<input type="text" name="eduPlace1">
<label for="">Details</label>
<input type="text" name="eduNotes1">
</div>
you can try this to create dynamic form
I want to clone the template and show it to the <div id= "wrapper"> with different ID every time I make a clone. When I press the add-new-project button a new template is shown with different "ID" every time.
Javascript code:
$("document").ready(function () {
var cloneCntr = 1;
var i = 0;
$("#projectData").on('click', function () {
$('template').children().each(function () {
this.id = this.id+ this.i;
});
var temp = document.getElementsByTagName("template")[0];
var clon = temp.content.cloneNode(true);
i++;
$('#wrapper').append(clon);
});
});
Html code:
<form id="projectForm">
<div class="container">
////// ---------------------code-------//// <br>
<br>
<h4>Project Experience</h4>
<hr>
<template id="template">
<br>
<br>
<div class="form-row">
---------Template Code-------
</div>
</div>
<hr>
</template>
</div>
<div id="wrapper" class="container">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<div class="container">
<button type="button" id="projectData" class="btn btn-primary">Add New Project</button>
</div>
</body>
</html>
I want to replace every tag "id" in the template, every time when I make a clone of this.
Here's an example of how this could work for you.
See a demo here: https://jsfiddle.net/o76pqxyw/
Here's a screenshare, showing how the IDs change: https://www.loom.com/share/4a1556c4bb5c4422ad1d4b20a12a638a
HTML
<div id="template-form">
<p><label>First Name</label> <input type="text" id="first-name" /></p>
<p><label>Last Name</label> <input type="text" id="last-name" /></p>
</div>
<button id="btn">Add New User</button>
<div id="container"></div>
Javascript
const button = $('#btn');
const target = $('#container');
let counter = 0;
$(button).on('click', () => {
const template = $('#template-form');
const copy = $(template).clone();
counter++;
const elements = $(copy).find('input');
$(elements).each(function(index) {
const currentId = $(this).attr('id');
const newId = currentId + '-' + counter;
$(this).attr('id', newId);
});
$(target).append(copy);
})
I'm trying to create new fields like the first field in this form by clicking on an image, but the fields are spawning below the button to submit and I don't understand why. The behavior I'm looking for is for the new fields to spawn above the button.
Here's my code
<div id="title">
<h1>Monthly Run Operations Assessment</h1>
</div>
<div class="row">
<div class="col-20" id="row-one">
<label for="name">1. </label>
</div>
<div class="col-60">
<input type="text" id="op" name="op" placeholder="Insert operation here">
</div>
<div class="col-20" id="symbol">
<img src="file:///C:/Users/user/Downloads/plus-circle-solid.svg" id="add">
</div>
</div>
<div id="submit">
<input type="submit" value="Submit">
</div>
</div>
This is the function:
var element = document.getElementById("add");
element.onclick = function() {
console.log("woot");
var ele = document.getElementsByClassName("row")[0];
var clone = ele.cloneNode(true);
var newDiv = document.createElement("div");
document.body.appendChild(clone);
}
appendChild, as its name suggests, always appends the new element -- that is, it adds it to the end. What you want is insertBefore:
document.body.insertBefore(clone, ele);
One way to handle this is to wrap your form in a container and append to it :
var element = document.getElementById("add");
element.onclick = function() {
// console.log("woot");
var ele = document.getElementsByClassName("row")[0];
var clone = ele.cloneNode(true);
var newDiv = document.createElement("div");
document.querySelector('#container').appendChild(clone);
}
<div id="title">
<h1>Monthly Run Operations Assessment</h1>
</div>
<div id="container">
<div class="row">
<div class="col-20" id="row-one">
<label for="name">1. </label>
</div>
<div class="col-60">
<input type="text" id="op" name="op" placeholder="Insert operation here">
</div>
<div class="col-20" id="symbol">
<img src="file:///C:/Users/user/Downloads/plus-circle-solid.svg" id="add">
</div>
</div>
</div>
<div id="submit">
<input type="submit" value="Submit">
</div>
</div>
I combined the above answers to achieve the expected behavior.
var element = document.getElementById("add");
element.onclick = function() {
// console.log("woot");
var ele = document.getElementsByClassName("row")[0];
var clone = ele.cloneNode(true);
var newDiv = document.createElement("div");
document.querySelector('#container').insertBefore(clone, ele);
}
sorry i do not speak english well, i want to create a tool that allows to duplicate a div thanks to an "input number" and a button and then I also want to clone this tool by reinitializing it to be able to use the tool again , Here is a piece of code:
$(function() {
$('#btn_dupliquate').on('click', function() {
var numDuplication = $('#num-duplication').val();
if (numDuplication > -1) {
var div = $('.common_preview');
$('.result').html('');
for (var i = 0; i < numDuplication; i++) {
$('.result').append(div.clone());
}
}
});
});
$(function() {
$(".heading").keyup(function() {
var heading=$(this).val();
$(".common_preview").html("<div class='bloc'><p class='model'>"+heading+"</p></div>");
return false;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="toNumDuplicate">
<input type="text" class="heading" />
<br/>
<br/>
<input id="num-duplication" type="number" >
<br/>
<br/>
<button id="btn_dupliquate"> dupliquate </button>
</div>
<div id="toDuplicate">
<div class="common_preview" >
<div class="bloc">
<p class="model">test</p>
</div>
</div>
</div>
<div class="result"></div>
<button id="btn_clone">clone</button>
You could abstract your function to take dynamic selector strings for the duplicate button, duplicate number input, preview div and result div.
I would like to know how can I create textboxes and insert data at page load.
What I'm trying to do is open an array string from a database, create the textboxes and populate the textboxes at page load.
I have an array string from an ms sql database that looks something like this
test,test;bla;bla2;test44;test55;test66
I separated each individual array with ; and I would like to create textboxes and insert the values into a textbox, one-by-one, so the end result would look like this:
I don't know how to do it using the code below.
Whatever I try I mess up the add/remove functions or I end up cloning all textboxes when the plus button is clicked.
THANKS
SEE CODE BELOW OR GO TO https://jsfiddle.net/kj3cwww0
<script type='text/javascript'>//<![CDATA[
$(function() {
var clone = function(tmpl) {
return $((tmpl.clone()).html())
},
$template = $('#template_add_form'),
formArray = [ clone($template) ], // init array with first row
$formEntries = $('#entries');
$(document).on('click', '.btn-add', function() {
formArray.push(clone($template));
updateForm();
// set focus to adding row = last element in array
$(formArray).last()[0]
.find('input')
.first()
.focus();
});
// remove not working yet
$(document).on('click', '.btn-remove', function(evt) {
var id;
// iterate over formArray to find the currently clicked row
$.each(formArray, function(index, row) {
if ( row.has(evt.currentTarget).length == 1 ) {
id = index; // click target in current row
return false; // exit each loop
}
});
formArray.splice(id, 1);
updateForm();
});
var updateForm = function() {
// redraw form --> problem values are cleared!!
var lastIndex = formArray.length - 1,
name; // stores current name of input
$formEntries.empty(); // clear entries from DOM becaue we re-create them
$.each(formArray, function(index, $input) {
// update names of inputs and add index
$.each($input.find('input'), function(inputIndex, input) {
name = $(input).attr('name').replace(/\d+/g, ''); // remove ids
$(input).attr('name', name);
});
if (index < lastIndex) {
// not last element --> change button to minus
$input.find('.btn-add')
.removeClass('btn-add').addClass('btn-remove')
.removeClass('btn-success').addClass('btn-danger')
.html('<span class="glyphicon glyphicon-minus"></span>');
}
$formEntries.append($input);
});
};
updateForm(); // first init. of form
});
//]]>
</script>
<script id="template_add_form" type="text/template">
<div class = "entry input-group col-xs-9">
<div class = "col-xs-3">
<input class = "form-control" name="balance" type = "text"
placeholder = "Loan Balance" required = "required"/>
</div>
<div class="col-xs-3">
<input class="form-control" name="rate" type="text" placeholder="Interest Rate" required="required" />
</div>
<div class="col-xs-3">
<input class="form-control" name="payment" type="text" placeholder="Minimum Payment" required="required"/>
</div>
<span class="input-group-btn col-xs-1">
<button class="btn btn-success btn-add" type="button">
<span class="glyphicon glyphicon-plus"></span >
</button>
</span>
</div>
</script>
<div class="container">
<div class="row">
<div class="control-group" id="fields">
<label class="control-label" for="field1">
<h3>Enter your loans below</h3>
</label>
<div class="controls">
<div class="entry input-group col-xs-3">How much extra money can you pay per month?
<input class="form-control" name="extra" type="text" placeholder="Extra/month">
</div>
<br>
<div id="entries"></div>
</div>
<div class="input-group-btn">
<div class="col-xs-5">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
<br> <small>Press <span class="glyphicon glyphicon-plus gs"></span> to add another loan</small>
</div>
</div>
</div>
FORM SUBMIT CODE:
<body>
<form id="loanform" name="loanform" action="test5.asp" role="form" autocomplete="off" method="post">
<INPUT type="hidden" name="action" value="submit">
<div class="container">
......the rest of the existing code goes here...
</div>
</form>
</body>
CALLING IT VIA CLASSIC ASP:
if strComp(Request.Form("action"), "submit")= 0 then
Response.write("IT WORKS")
end if
Here is a solution that works :
$(function() {
var clone = function(tmpl) {
return $((tmpl.clone()).html())
},
$template = $('<div>').addClass("entry input-group col-xs-9").append(clone($('#template_add_form'))),
formArray = [ ], // init array enpty
$formEntries = $('#entries');
$(document).on('click', '.btn-add', function() {
formArray.push(clone($template));
updateForm();
// set focus to adding row = last element in array
$(formArray).last()[0]
.find('input')
.first()
.focus();
});
// remove not working yet
$(document).on('click', '.btn-remove', function(evt) {
var id;
// iterate over formArray to find the currently clicked row
$.each(formArray, function(index, row) {
if ( row.has(evt.currentTarget).length == 1 ) {
id = index; // click target in current row
return false; // exit each loop
}
});
formArray.splice(id, 1);
updateForm();
});
var addToForm = function (stringValue) {
values = stringValue.split(";");
for (var i = 0; i < values.length; i+=3) {
var newLine = clone($template);
var fields = newLine.find('.form-control');
var toAdd = Math.min(values.length-i, 3);
for (var j = 0; j < toAdd; j++) {
fields[j].value = values[i+j];
}
formArray.push(newLine);
}
}
var updateForm = function() {
// redraw form --> problem values are cleared!!
var lastIndex = formArray.length - 1,
name; // stores current name of input
$formEntries.empty(); // clear entries from DOM becaue we re-create them
$.each(formArray, function(index, $input) {
// update names of inputs and add index
$.each($input.find('input'), function(inputIndex, input) {
name = $(input).attr('name').replace(/\d+/g, ''); // remove ids
$(input).attr('name', name);
});
if (index < lastIndex) {
// not last element --> change button to minus
$input.find('.btn-add')
.removeClass('btn-add').addClass('btn-remove')
.removeClass('btn-success').addClass('btn-danger')
.html('<span class="glyphicon glyphicon-minus"></span>');
}
$formEntries.append($input);
});
};
addToForm("2;3;4;5;6;7");
formArray.push(clone($template));
updateForm();
$('#template_add_form').remove();
});
.entry:not(:first-of-type)
{
margin-top: 10px;
}
.glyphicon
{
font-size: 12px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<form id="loanform" name="loanform" action="test5.asp" role="form" autocomplete="off" method="post">
<INPUT type="hidden" name="action" value="submit">
<div class="container">
<div class="row">
<div class="control-group" id="fields">
<label class="control-label" for="field1">
<h3>Enter your loans below</h3>
</label>
<div class="controls">
<div class="entry input-group col-xs-3">How much extra money can you pay per month?
<input class="form-control" name="extra" type="text" placeholder="Extra/month">
</div>
<br>
<div id="entries"></div>
</div>
<div class="input-group-btn">
<div class="col-xs-5">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
<br> <small>Press <span class="glyphicon glyphicon-plus gs"></span> to add another loan</small>
</div>
</div>
</div>
<div id="template_add_form" type="text/template" style="display: none;">
<div class = "entry input-group col-xs-9">
<div class = "col-xs-3">
<input class = "form-control" name="balance" type = "text"
placeholder = "Loan Balance" required = "required"/>
</div>
<div class="col-xs-3">
<input class="form-control" name="rate" type="text" placeholder="Interest Rate" required="required" />
</div>
<div class="col-xs-3">
<input class="form-control" name="payment" type="text" placeholder="Minimum Payment" required="required"/>
</div>
<span class="input-group-btn col-xs-1">
<button class="btn btn-success btn-add" type="button">
<span class="glyphicon glyphicon-plus"></span >
</button>
</span>
</div>
</div>
</form>
</body>
Here's what I changed to your code :
Changed the template which was a <script> to a <div>, and hid it by default using style="display: none;" :
<div id="template_add_form" type="text/template" style="display: none;">
Initialized array empty, so that we can put our own first line : formArray = [ ],
Created a function to add a string in the form :
var addToForm = function (stringValue) {
values = stringValue.split(";");
for (var i = 0; i < values.length; i+=3) {
var newLine = clone($template);
var fields = newLine.find('.form-control');
var toAdd = Math.min(values.length-i, 3);
for (var j = 0; j < toAdd; j++) {
fields[j].value = values[i+j];
}
formArray.push(newLine);
}
}
At the end, I added some example data, then pushed an empty line and updated the form :
addToForm("2;3;4;5;6;7");
formArray.push(clone($template));
updateForm();
EDIT : I also deleted the template div at the end so that it isn't taken into the form when you submit :
$('#template_add_form').remove();
To be able to do that, I cloned it entirely at start :
$template = $('<div>').addClass("entry input-group col-xs-9").append(clone($('#template_add_form'))),