I'm attempting to create a page where the user is able to customize the form to their needs by adding in extra divs or nested divs (as many layers deep as they'd like). Within each div I'd like to have text input and a button which adds another div on the same level and a button that nests a div within it. Both divs should again have a text input and a button which does the same thing.
However I've gotten a bit stuck. When I attempt to create a nested div I always end up adding it at the very bottom instead of inside its parent.
<html>
<script type="text/javascript">
var counter = 1;
function addNode() {
var newDiv = document.createElement('div');
counter++;
newDiv.innerHTML = "Entry " + counter + " <br><input type='text' name='myInputs'>";
document.getElementById("dynamicInput").appendChild(newDiv);
var newButton = document.createElement('button');
newButton.type = "button";
newButton.onclick = addSub;
document.getElementById("dynamicInput").appendChild(newButton);
}
function addSub() {
var newDiv = document.createElement('div');
counter++;
newDiv.innerHTML = "Entry " + counter + " <br><input type='text' name='myInputs' style='margin:10px'>";
document.getElementById("subInput").appendChild(newDiv);
}
</script>
<form class="form" method="POST">
<div id="dynamicInput" name="dynamicInput" multiple="multiple">
Entry 1<br><input type="text" name="myInputs">
<div id="subInput" name="subInput" multiple="multiple">
<input type="button" value="add nested" onClick="addSub();">
</div>
</div>
<input type="button" value="Add another text input" onClick="addNode();" >
<input type="submit" value = "answer" multiple="multiple"/>
</form>
</html>
Here is a complete solution for you keep in mind that if you need to bind extra events on your produced inputs and buttons you ll have to do it inside the functions addNode or addSub as i did for the click event on the buttons.
Working example : https://jsfiddle.net/r70wqav7/
var counter = 1;
function addNode(element) {
counter++;
var new_entry="Entry "+counter+"<br><input type='text' name='myInputs'><br>";
element.insertAdjacentHTML("beforebegin",new_entry);
}
function addSub(element) {
counter++;
var new_sub_entry="<div class='block'>"
+"Entry "+counter+"<br><input type='text' name='myInputs'><br>"
+"<div class='buttons'>"
+"<input class='add_sub_button' type='button' value='add nested'>"
+"<input class='add_button' type='button' value='Add another text input' >"
+"</div>"
+"</div><br />"
+"</div>";
element.insertAdjacentHTML("beforebegin",new_sub_entry);
var blocks=element.parentNode.getElementsByClassName("block");
blocks[blocks.length-1].getElementsByClassName("add_sub_button")[0].addEventListener("click",function(){
addSub(this.parentNode);
});
blocks[blocks.length-1].getElementsByClassName("add_button")[0].addEventListener("click",function(){
addNode(this.parentNode);
});
}
var buttons=document.getElementsByClassName("add_button");
for(i=0;i<buttons.length;i++){
buttons[i].addEventListener("click",function(){
addNode(this.parentNode);
});
}
var nested_buttons=document.getElementsByClassName("add_sub_button");
for(i=0;i<buttons.length;i++){
nested_buttons[i].addEventListener("click",function(){
addSub(this.parentNode);
});
}
div.block{
padding:5px;
border:2px solid #000;
}
<form class="form" method="POST">
<div class="block">
Entry 1<br><input type="text" name="myInputs"><br>
<div class="buttons">
<input class="add_sub_button" type="button" value="add nested">
<input class="add_button" type="button" value="Add another text input" >
</div>
</div><br />
<input type="submit" value = "answer" multiple="multiple"/>
</form>
EDITED : There was an error binding the click event on nested items updated to work properly
Here's another worked example which makes use of the concepts I mentioned in an earlier comment. I've moved the Add-Item button outside the form and altered the method used to determine the text for each new item added. Rather than keep a counter, I count the number of existing items in the document and increment it, using this as as the n in the string "Entry n"
I should have added(appended) the sub-item before the button that creates new ones, but was lazy and just called appendChild on the button after the other new element was added - the end result is the same, but it's less efficient and will cause slower performance/shorter battery life.
I was going to use the .cloneNode method of the .dynamicInput div, when clicking "Add new item", however this will copy all subitems of the chosen target and we still need to call addEventListener for the button anyway, so I've opted to simply create each input-item added with the "Add new item" button instead.
<!doctype html>
<html>
<head>
<script>
"use strict";
function byId(id,parent){return (parent == undefined ? document : parent).getElementById(id);}
function allByClass(className,parent){return (parent == undefined ? document : parent).getElementsByClassName(className);}
function allByTag(tagName,parent){return (parent == undefined ? document : parent).getElementsByTagName(tagName);}
function newEl(tag){return document.createElement(tag);}
function newTxt(txt){return document.createTextNode(txt);}
window.addEventListener('load', onDocLoaded, false);
function onDocLoaded(evt)
{
byId('addNewInputBtn').addEventListener('click', myAddNewItem, false);
var subItemBtn = document.querySelectorAll('.dynamicInput button')[0];
subItemBtn.addEventListener('click', myAddSubItem, false);
}
function makeNewItem(titleStr)
{
var div = newEl('div');
div.className = 'dynamicInput';
var heading = newEl('h3');
heading.innerText = titleStr;
div.appendChild(heading);
var input = newEl('input');
div.appendChild(input);
var btn = newEl('button');
btn.innerText = 'Add sub-items';
btn.addEventListener('click', myAddSubItem, false);
div.appendChild(btn);
return div;
}
function myAddNewItem(evt)
{
var numAlreadyExisting = allByClass('dynamicInput').length; // count number of divs with className = dynamicInput
var newNum = numAlreadyExisting + 1;
var newInputPanel = makeNewItem('Entry ' + newNum);
byId('myForm').appendChild(newInputPanel);
return false;
}
function myAddSubItem(evt)
{
evt.preventDefault(); // stops this button causing the form to be submitted
var clickedBtn = this;
var inputDiv = clickedBtn.parentNode;
var newInput = newEl('input');
inputDiv.appendChild(newInput);
inputDiv.appendChild(clickedBtn);
}
</script>
</head>
<body>
<form id='myForm'>
<div class='dynamicInput'>
<h3>Entry 1</h3>
<input type='text'/><button>Add sub-item</button>
</div>
</form>
<button id='addNewInputBtn'>Add new item</button>
</body>
</html>
Related
Here is the section which is confusing me:
<script type="text/javascript">
//declaring veriables
var inputField = document.getElementById("input");
var addBtn = document.getElementById("addBtn");
var html = "";
var x = 0;
addBtn.addEventListener('click', function(){
var text = inputField.value;
addToList(text);
})
//adds items to list
function addToList(text){
html += "<li id=(x+=1)><h4><input type='checkbox' id=(x+=1) onclick= 'clearspecifieditems()'>"+text+"</h4></li>";
document.getElementById("myList").innerHTML = html;
inputField.value = "";
}
//clears items
function clearspecifieditems(itemid)
{
//delete selected item
};
So the goal here is to create a to-do list (I'm new to coding). The addToList(text) function is supposed to create a new list item and assign a sequential ID to it. However, I cannot seem to figure out how to have it generate the ID. In addition, clearspecifieditems(itemid) is supposed to get the IDs of all the list items that are checked, and clear all of them.
For the first part of your question either use string concatenation similar to how you added the text variable...
function addToList(text) {
const id = x + 1;
html += '<li id="' + id + '"><h4><input type="checkbox" id="' + id + '">' + text + '</h4></li>';
// ..
}
...or use a template literal:
function addToList(text) {
const id = x + 1;
html += `<li id="${id}"><h4><input type="checkbox" id="${id}" />${text}</h4></li>`;
// ..
}
HOWEVER, for the second part, how to clear checked boxes:
I purposely left the onclick out of the above code because it sounds as if you need a separate button to clear the checkboxes:
// Grab the button and add an click listener to it
// to call `clearSpecifiedItems`
const button = document.querySelector('.clear');
button.addEventListener('click', clearSpecifiedItems, false);
function clearSpecifiedItems() {
// Select all the checked checkboxes using their class
const selected = document.querySelectorAll('.test:checked');
// Set their checked property to false (or null)
selected.forEach(input => input.checked = false);
}
<input class="test" type="checkbox" />
<input class="test" type="checkbox" />
<input class="test" type="checkbox" />
<input class="test" type="checkbox" />
<button class="clear">Clear</button>
Notice that none of these inputs have IDs. I've used a class to pick up the elements instead. So unless you're using the ids for anything else it makes the first part of your code redundant. Just use a CSS selector to grab the elements you need and then process them. No IDs required!
I can see what you're going for. You are almost there. Just a little bit of syntactical error, and a bit of a logical one.
You see, when you increment x two times, You will have a different id for the <li> and the <input>. What I suggest is you increment the x beforehand and then use it.
You can do it like this:
function addToList(text){
x++;
html += "<li id="+ x +"><h4><input type='checkbox' id="+ x +" onclick= 'clearspecifieditems()'>"+text+"</h4></li>";
document.getElementById("myList").innerHTML = html;
inputField.value = "";
}
or this (ES6)
function addToList(text){
x++;
html += `<li id=${x}><h4><input type='checkbox' id=${x} onclick= 'clearspecifieditems()'>${text}</h4></li>`;
document.getElementById("myList").innerHTML = html;
inputField.value = "";
}
Is it absolutely necessary that you must only increment? Can the ID's be truly unique? I suggest you use UUID in that case
Your second question is how to make clearspecifieditems work. Here's what you can do. You can pass the context, or simply the checkbox that was clicked and then get it's ID easily..
So you would define your function something like this:
function clearspecifieditems(element){
//delete selected item
console.log(element.id); // this would give you the ID of the selected checkbox and then you can do whatever with it
};
and slightly modify your function call on the click event
html += "<li id="+ x +"><h4><input type='checkbox' id="+ x +" onclick= 'clearspecifieditems(this)'>"+text+"</h4></li>";
Note this this part.
More more information, See this
Just use string interpolation to reference the x variable and increment it by one every time you add a new item as follows:
/* JavaScript */
var inputField = document.getElementById("input");
var addBtn = document.getElementById("addBtn");
var output = document.getElementById("output");
var html = "";
var x = 0;
function addToList(text) {
output.innerHTML += `<li id=id${x}><h4><input type='checkbox' id=${x}>This list item has an id: id${x}"</h4></li>`;
inputField.value = "";
x++;
}
addBtn.addEventListener('click', function(){
var text = inputField.value;
addToList(text);
})
<!-- HTML -->
<input type="text" id="input" />
<button id="addBtn">Add Items</button>
<div id="output"></div>
And for removing checked elements, simply add another button, say removeBtn and then add a click listener to the button that invokes the clearspecifieditems().
Inside the function, assign a variable to a list of all the checkboxes, loop through the variable using forEach and remove any checkbox that is not checked like this:
function clearspecifieditems() {
var check = document.querySelectorAll('[id^="id"]');
check.forEach(checkBox => {
if(checkBox.children[0].children[0].checked){
checkBox.remove();
}
});
}
removeBtn.addEventListener('click', clearspecifieditems);
#output {list-style: none;}
/* <input type="text" id="input" />
<button id="addBtn">Add Items</button> */
<ul id="output">
<li id="id0"><h4><input type="checkbox" id="input0">This list item has an id: id0"</h4></li>
<li id="id1"><h4><input type="checkbox" id="input1">This list item has an id: id1"</h4></li>
<li id="id2"><h4><input type="checkbox" id="input2">This list item has an id: id2"</h4></li>
<li id="id3"><h4><input type="checkbox" id="input3">This list item has an id: id3"</h4></li>
</ul>
<hr>
<button id="removeBtn">Remove</button>
You're sending X as 1. You should do like this :
var input = document.getElementById("input");
var div = document.getElementById("div");
var button = document.getElementById("addbutton");
var id = 0;
button.onclick = function() {
text = input.value;
addtask(text)
}
function addtask(text) {
var element = document.createElement("li");
element.setAttribute("id", id)
var deleteE = document.createElement("input");
deleteE.setAttribute("type", "checkbox");
deleteE.setAttribute("onclick", "deleteX(" + id + ")");
var node = document.createTextNode(text);
element.appendChild(deleteE);
element.appendChild(node);
div.appendChild(element);
id += 1;
}
function deleteX(id) {
document.getElementById(id).style.visibility = "hidden";
}
<input id="input"> <button id="addbutton"> add </button>
<div id="div"></br> </div>
I'm trying to make a 'CRUD' in pure Javascript, it's almost done, the only thing that I need is preparing the inputs with the value of <li>, to do it, I'd like to add an onclick event in a checkbox that is created dynamically in the function insert(), but everytime I click the checkbox nothing happens.
<!DOCTYPE html>
<html>
<head>
<script>
window.onload = function(){
btnInsert = document.getElementById("btnInsert");
btnEdit = document.getElementById("btnEdit");
btnDelete = document.getElementById("btnDelete");
vname = document.getElementById("tbName");
ul = document.getElementsByTagName("ul")[0];
btnInsert.onclick = insert;
btnDelete.onclick = remove;
}
function insert(){
li = document.createElement("li");
li.innerHTML = vname.value;
li.innerHTML += " <input type='checkbox' onclick='select()' value='Select' /> Update";
ul.appendChild(li);
vname.value = "";
}
function select(){
alert("Checked");
}
function remove(){
var lis = document.getElementsByTagName("li");
for(i = 0; i<lis.length; i++){
lis[i].onclick = function(){
this.remove();
}
}
}
</script>
</head>
<body>
<label for="tbName">Name: </label>
<input name="tbName" id="tbName"/><br /><br />
<button id="btnInsert">Insert</button>
<button id="btnEdit">Edit</button>
<button id="btnDelete">Delete</button>
<br /><br />
<ul>
</ul>
</body>
</html>
It seems the name select is causing conflict since I could get your code working with the following changes:
HTML
li.innerHTML += " <input type='checkbox' onclick='sel()' value='Select' />Update";
Javascript
function sel(){
alert("Checked");
}
Further tests show that if we log the contents of the function with:
li.innerHTML += " <input type='checkbox' onclick='console.log(select.toString)' value='Select' />Update";
the console shows the following
function select() { [native code] }
So my guess is that select is the name of a function already defined by the browser, hence why you can't use it as a name for your functions.
In short, your code triggers another select function, not the one you defined in your source code.
The OP doesn't want it to fire on the LI, he wants it to fire on the checkbox!
Give your dynamic checkbox an ID value like chkBox1.
Now after you have appended it to the document, you can call it with:
var thechkBox=document.getElementById("chkBox1");
Now you can hit thechkBox with:
thechkBox.addEventListener("click", itfired); //itfired is the script that captures the click event.
That is one of many Events you would then have access to (https://www.w3schools.com/js/js_htmldom_events.asp)!
If you needed the dynamic checkbox to perform a function "on"click!
I'm making an app that submits posts, but I originally designed it with a textarea in mind, I've since put in an iframe to create a rich text field, set the display style to hidden for the textarea and wanted to know how I could modify it to use the iframe value.
HTML
<div id="textWrap">
<div class="border">
<h1>Start Writing</h1><br />
<input id="title" placeholder="Title (Optional)">
<div id="editBtns">
<button onClick="iBold()">B</button>
<button onClick="iUnderline()">U</button>
<button onClick="iItalic()">I</button>
<button onClick="iHorizontalRule()">HR</button>
<button onClick="iLink()">Link</button>
<button onClick="iUnLink()">Unlink</button>
<button onClick="iImage()">Image</button>
</div>
<textarea id="entry" name="entry" rows="4" cols="50" type="text" maxlength="500" placeholder="Add stuff..."></textarea>
<iframe name="richTextField" id="richTextField"></iframe><br />
<button id="add">Submit</button>
<button id="removeAll" onclick="checkRemoval()">Delete All Entries</button>
<ul id="list"></ul>
<ul id="titleHead"></ul>
</div><!--end of border div-->
</div><!--end of textWrap-->
Here is the JS to submit the posts.
//target all necessary HTML elements
var ul = document.getElementById('list'),
removeAll = document.getElementById('removeAll'),
add = document.getElementById('add');
//richText = document.getElementById('richTextField').value;
//make something happen when clicking on 'submit'
add.onclick = function(){
addLi(ul)
};
//function for adding items
function addLi(targetUl){
var inputText = document.getElementById('entry').value, //grab input text (the new entry)
header = document.getElementById('title').value, //grab title text
li = document.createElement('li'), //create new entry/li inside ul
content = document.createElement('div'),
title = document.createElement('div'),
//textNode = document.createTextNode(inputText + ''), //create new text node and give it the 'entry' text
removeButton = document.createElement('button'); //create button to remove entries
content.setAttribute('class','content')
title.setAttribute('class','title')
content.innerHTML = inputText;
title.innerHTML = header;
if (inputText.split(' ').join(' ').length === 0) {
//check for empty inputs
alert ('No input');
return false;
}
removeButton.className = 'removeMe'; //add class to button for CSS
removeButton.innerHTML = 'Delete'; //add text to the remove button
removeButton.setAttribute('onclick', 'removeMe(this);'); //creates onclick event that triggers when entry is clicked
li.appendChild(title); //add title textnode to created li
li.appendChild(content); //add content textnode to created li
li.appendChild(removeButton); //add Remove button to created li
targetUl.appendChild(li); //add constructed li to the ul
}
//function to remove entries
function removeMe(item){
var deleteConfirm = confirm('Are you sure you want to delete this entry?');
if (deleteConfirm){var parent = item.parentElement;
parent.parentElement.removeChild(parent)}
};
function checkRemoval(){
var entryConfirm = confirm('Are you sure you want to delete all entries?');
if (entryConfirm){
ul.innerHTML = '';
}
};
demo I'm working on for reference.. http://codepen.io/Zancrash/pen/VemMxz
you can use either local storage for passing iframe values to the parent DOM.
or ( use this to pass value from iframe to parent container )
var iFrameValue = $('#iframe').get(0).contentWindow.myLocalFunction();
var iFrameValue = $('#iframe').get(0).contentWindow.myLocalVariable;
From IFrame html
<script type="text/javascript">
var myLocalVariable = "text";
function myLocalFunction () {
return "text";
}
</script>
Here is the link
I managed to get my buttons work like I want them to, to increase the number of 'Points' by 50 on each click, and every time the 'Points' reach another 500, the 'Level' increases by one.
If I were to use this as a To-Do List, how could I keep adding buttons, like the ones already coded in, but dynamically. Instead of coding the buttons in to the HTML, I'd much prefer being able to add more buttons, with the title of my choice (text input?). I'd hope they were all similar in style. (I'm using bootstrap CSS).
If possible for me to choose how many points each button gives.
I have absolutely no clue on how to do this, can someone please help me out? Thank you in advance.
Also, how can I send the 'Points' and 'Levels', as well as all the created buttons to a text file, so that when I refresh the page, nothing's changed? Thank you again.
Here is the same code used in the JSbin link above.
HTML
<center>
<h2>Reward System</h2>
</br>
<div class='well' style="width:400px;">
<input type='button' value='Task 1' onClick='add()' class='btn btn-danger'>
<span class="label label-default">+50</span>
</div>
<div class='well' style="width:400px;">
<input type='button' value='Task 2' onClick='add()' class='btn btn-danger'>
<span class="label label-default">+50</span>
</div>
<div class='well' style="width:400px;">
<input type='button' value='Task 3' onClick='add()' class='btn btn-danger'>
<span class="label label-default">+50</span>
</div>
<div class='well' style="width:400px;">
<input type='button' value='Task 4' onClick='add()' class='btn btn-danger'>
<span class="label label-default">+50</span>
</div>
</br></br>
<hr style="width:400px;">
<div>
<h3>Points </h3>
<p id='p'>0</p>
</div>
<hr style="width:400px;">
<div style="width:400px;">
<h3>Level
<p id='lvl'>0</p>
</div>
<hr style="width:400px;">
</center>
Javascript
var i = 0;
var lvl = 0;
var a = 100;
function add() {
i+=50;
document.getElementById('p').innerHTML = i;
var perc = ' "' + ' "px';
var para = document.getElementById("p");
para.style.fontSize = perc;
while (i > 5*a) {
lvl+=1;
a+=100;
}
document.getElementById('lvl').innerHTML = lvl;
var perc1= ' "' + ' "px';
var para1= document.getElementById("lvl");
para1style.fontSize = perc1;
}
Regarding the file part, you can save the data in browser localStorage instead of writing it into a file
to save something:
localStorage.setItem("param1",param1Value);
to get it (after loading the page again, on load):
var param1Value = localStorage.getItem("param1");
regard the add task, I've added fiddle example but it uses jQuery (which is very recommended for your tasks..) hope that's help
<div><button id="addTaskButton" class="btn">Add Task</button></div>
$("#addTaskButton").click(function (event) {
var nextNumber = $(".well").length + 1;
$($("hr")[0]).before("<div class='well' style='width:400px;'><input type='button' value='Task " + nextNumber + "' onClick='add()' class='btn btn-danger'> <span class='label label-default'>+50</span></div>");
});
Press 'Add Task' button will add you a new task button..
You can give the new buttons the same class as the other ones.
var newBtn = document.createElement('button');
newBtn.className = 'btn';
To add click Listener you can attach to them before appending them:
newBtn.addEventListener('click', function() {
addToResult(this.getAttribute('data-points'));
});
I've added an attribute to the buttons called data-points which stores the points clicking that button will give. It'd be more appropriate this way than getting it from a sibling span, but the span is rather to show user.
Edited code:
var addBtn = document.getElementById('addBtn');
addBtn.addEventListener('click', function() {
var container = document.getElementById('container');
var btnName = document.getElementById('btnName').value;
var btnPoints = parseInt(document.getElementById('btnPoints').value);
if(!btnName)
btnName = "Button ?";
if(!btnPoints)
btnPoints = 50;
var newBtn = document.createElement('button');
var newPnt = document.createElement('span');
newBtn.className = 'btn';
newBtn.innerText = btnName;
newBtn.setAttribute('data-points', btnPoints);
newBtn.addEventListener('click', function() {
addToResult(this.getAttribute('data-points'));
});
newPnt.className = 'label';
newPnt.innerText = "+" + btnPoints;
container.appendChild(newBtn);
container.appendChild(newPnt);
});
Updated jsfiddle DEMO
EDIT 2:
To remove and element you use: element.parentNode.removeChild(element). So to put it into context, you'll need to remove the associated span as well:
newBtn.addEventListener('click', function() {
addToResult(this.getAttribute('data-points'));
this.parentNode.removeChild(this.nextElementSibling);
this.parentNode.removeChild(this);
});
EDIT#N:
It's fairly simple to use localStorage. To save the result:
var result = document.getElementById('result').innerText;
localStorage.setItem("whateverName", result);
And whenever you want to get it back:
localStorage.getItem("whateverName");
// Creating an element:
var newDiv = document.createElement('div');
// Changing attributes of an element:
newDiv.setAttribute('class','desiredClass');
// Changing the innerHTML of the element:
newDiv.innerHTML = 'Desired inner HTML';
// Finally - Append the new element somewhere in the DOM (HTML Tree):
document.getElementsById('SomeID').appendChild(newDiv);
I have a code like this...
<html>
<head>
<title>test</title>
<script type="text/javascript">
var counter = 2;
var idCounter= 3;
function addNew() {
if(counter<=5){
// Get the main Div in which all the other divs will be added
var mainContainer = document.getElementById('mainContainer');
// Create a new div for holding text and button input elements
var newDiv = document.createElement('div');
newDiv.id='divs'+counter;
// Create a new text input
var newText = document.createElement('input');
var newText1 = document.createElement('input');
newText.type = "input";
newText.id="ans"+(idCounter);
idCounter++;
newText1.type = "input";
newText1.id="ans"+(idCounter);
idCounter++;
// newText.value = counter;
// Create a new button input
var newDelButton = document.createElement('input');
newDelButton.type = "button";
newDelButton.value = "Remove";
// Append new text input to the newDiv
newDiv.appendChild(newText);
newDiv.appendChild(newText1);
// Append new button input to the newDiv
newDiv.appendChild(newDelButton);
// Append newDiv input to the mainContainer div
mainContainer.appendChild(newDiv);
counter++;
// Add a handler to button for deleting the newDiv from the mainContainer
newDelButton.onclick = function() {
mainContainer.removeChild(newDiv);
counter--;
}
}
else{
alert('Only 5 rows are allowed');
}}sss
function removeRow(divId){
mainContainer.removeChild(divId);
counter--;
}
</script>
</head>
<body >
<div id="mainContainer">
<div><input type="button" value="Add New Row" onClick="addNew()"></div>
<div id="div1"><input type="text" id="ans1"><input type="text" id="ans2"><input type="button" value="Remove" onClick ="javascript:removeRow(div1);"></div>
</div>
</body>
</html>
I want to achieve the same using jQuery.I also need the values entered in each of these textboxes.Please help.
Okay, because I had nothing better to do, and, to be honest, I was curious, I put this together. As implied in my comment, above, I didn't particularly like the way you had it laid out, so I used the following (x)html:
<form action="#" method="post">
<fieldset id="rows">
<ul>
<li>
<input type="text" id="ans1" name="ans1" />
<input type="text" id="ans2" name="ans2" />
</li>
</ul>
</fieldset>
<fieldset id="controls">
<button id="addRow">add</button>
<button id="removeRow" disabled>remove</button>
</fieldset>
</form>
With the following jQuery (although I've clearly not optimised, or refined it, but it should meet your requirements):
$(document).ready(
function(){
$('#addRow').click(
function() {
var curMaxInput = $('input:text').length;
$('#rows li:first')
.clone()
.insertAfter($('#rows li:last'))
.find('input:text:eq(0)')
.attr({'id': 'ans' + (curMaxInput + 1),
'name': 'ans' + (curMaxInput + 1)
})
.parent()
.find('input:text:eq(1)')
.attr({
'id': 'ans' + (curMaxInput + 2),
'name': 'ans' + (curMaxInput + 2)
});
$('#removeRow')
.removeAttr('disabled');
if ($('#rows li').length >= 5) {
$('#addRow')
.attr('disabled',true);
}
return false;
});
$('#removeRow').click(
function() {
if ($('#rows li').length > 1) {
$('#rows li:last')
.remove();
}
if ($('#rows li').length <= 1) {
$('#removeRow')
.attr('disabled', true);
}
else if ($('#rows li').length < 5) {
$('#addRow')
.removeAttr('disabled');
}
return false;
});
});
JS Fiddle demo of the above
I'm not, however, sure what you mean by:
I also need the values entered in each of these textboxes.
If you can explain what that means, or how you want them to be available (and, ideally, why they're not already available to you) I'll do my best to help.
I have a solution which will help you use here is the code
<script type="text/javascript" src="js/jquery.js"></script>
<script type = 'text/javascript'>
var newRowNum = 1;
var project_id ;
$(function() {
$('#addnew').click(function()
{
newRowNum++; // This is counter
//var i = 0;
///////// <a> <td> <tr>
var addRow = $(this).parent().parent();
///////// In the line below <tr> is created
var newRow = addRow.clone();
$('input', addRow).val('');
$('td:first-child', newRow).html();
$('td:last-child', newRow).html('<a href="" class="remove span">Remove<\/a>');
var newID = 'project'+newRowNum;
var add = 'description'+newRowNum;
newRow.children().children().first('input').attr('id', newID).attr('name', newID);
newRow.children().children().eq(1).attr('id', add).attr('name', add);
$('#table').find('tr:last').after(newRow);
$('a.remove', newRow).click(function()
{
newRowNum--;
$('#table').find('tr:last').remove();
return false;
});
return false;
});
});
</script>
<table width="75%" border="0" align = "center" id = 'table'>
<tr>
<td align = "center">Project </td>
<td align = "center">Description</td>
<td align = "center">Add Row</td>
</tr>
<tr>
<td align = "center"><input type = 'text' size = '35'name = 'project[]' id="project" ></td>
<td align = "center"><input type = 'text'size = '55' name = "description[]" id = 'description'></td>
<td width = '10%'><a id="addnew" href= "" class = 'span'>Add</a></td>
</tr>
</table>
You can also give each text box unique name if you change code like this and changing these two variables
var newID = 'project'+newRowNum;
var add = 'description'+newRowNum;
if you use the first method i shown here it will be easy to post data using array. That's all.