Html code
<div class="cont">
<div class="row">
<p>anything</p>
<input type="button" id="1" class="Done" name="Go" value="done">
</div>
<div class="row">
<p>anything</p>
<input type="button" id="2" class="Done" name="Go" value="done">
</div>
<div class="row">
<p>anything</p>
<input type="button" id="3" class="Done" name="Go" value="done">
</div>
</div>
I have 3 of them[buttons]
javascript
var remove=document.getElementsByClassName("Done")
for(var i=0;i<remove.length;i++){
var button=remove[i]
button.addEventListener('click',function(event){
var bclick = event.target
bclick.parentElement.remove()
});
}
I tried that, it's work for the first time but when I reload I miss changes.
I think you can use localstorage to track your removed parentElement. Simply check your localstorage whether your parentElement is removed or not, if it is removed already just hide your row class's elements. It will show nothing once button is clicked. Hope it will help.
var remove = document.getElementsByClassName("Done");
for (var i = 0; i < remove.length; i++) {
var button = remove[i];
if (button) {
if (window.localStorage.getItem(remove[i].id) == 'true') {
document.getElementById(remove[i].id).parentNode.style.display = 'none';
}
}
}
for (var i = 0; i < remove.length; i++) {
var button = remove[i];
if (button) {
button.addEventListener('click', (event) => {
var bclick = event.target;
window.localStorage.setItem(bclick.id, 'true');
bclick.parentElement.remove();
});
}
}
Related
I am trying to learn some javascript in web programming. Starting with a simple school registration webpage: the webpage allows to dynamically create any number of grades by clicking "Grade+" button; under each grade, any number of students can be created by clicking "Student+" button. "Grade+" button works as expected, however clicking "Student+" button does not present the student information, not sure what is happening. Any help will be highly appreciated. Thanks in advance.
The reference codes:
<!DOCTYPE html>
<html>
<body>
<div>
<label>Registration</label>
<div class="form-inline justify-content-center" id="school" style="display:none">
<label for="fname">Grade:</label>
<input type="text" id="grade" name="Grade"><br><br>
<div id="students">
<div id="student">
<label for="fname">First:</label>
<input type="text" id="first" name="First"><br><br>
<label for="lname">Last:</label>
<input type="text" id="last" name="Last"><br><br>
</div>
<div class="text-center" id="add_student">
<span id="idStudentRootCopy">----S----</span>
<button type="button" onclick="addItem('student', 'idGradeRootCopy', false)">Student+</button>
</div>
</div>
</div>
<div class="text-center" id="add_grade">
<span id="idGradeRootCopy">----G----</span>
<button type="button" onclick="addItem('school', 'idGradeRootCopy', true)">Grade+</button>
</div>
</div>
<script>
var count = 0;
function addItem(id, index, root) {
var original = document.getElementById(id);
var before = document.getElementById(index);
var clone = original.cloneNode(true);
clone.style.display='block';
clone.id = id + ++count;
var newFields = clone.childNodes;
for (var i = 0; i < newFields.length; i++) {
var fieldName = newFields[i].name;
if (fieldName)
newFields[i].name = fieldName + count;
}
if (root) {
original.parentNode.insertBefore(clone, before.parentNode);
} else {
original.insertBefore(clone, before);
}
}
</script>
</body>
</html>
If you open up the developer tools of your browsers and click the Student+ button you'll get an error message like:
Uncaught DOMException: Node.insertBefore: Child to insert before is
not a child of this node
So you're actually trying to put the cloned node into the wrong spot. Either way things are a bit confusing. Let's say you have clicked the Grade+ button three times and now you decide to click on Student+ of the first clone - how should it know where to put the student as there are three grades?
Well there's a fix of course. Each Student+ button is a child of an unique clone of the school <div> which you also gave an unique id yet (school1, school2,...). So if you pass the addItem() function a reference to the button you actually clicked, we can get it's parent div like:
clickedElement.parentNode.parentNode.parentNode
and add the cloned node using appendChild() instead of insertBefore().
Here's an example (just click on 'Run code snippet'):
var count = 0;
function addItem(id, index, root, clickedElement) {
var original = document.getElementById(id);
var before = document.getElementById(index);
var clone = original.cloneNode(true);
clone.style.display = 'block';
clone.id = id + ++count;
var newFields = clone.childNodes;
for (var i = 0; i < newFields.length; i++) {
var fieldName = newFields[i].name;
if (fieldName)
newFields[i].name = fieldName + count;
}
if (root) {
original.parentNode.insertBefore(clone, before.parentNode);
} else {
clickedElement.parentNode.parentNode.parentNode.appendChild(clone);
}
}
<div>
<label>Registration</label>
<div class="form-inline justify-content-center" id="school" style="display:none">
<label for="fname">Grade:</label>
<input type="text" id="grade" name="Grade"><br><br>
<div id="students">
<div id="student">
<label for="fname">First:</label>
<input type="text" id="first" name="First"><br><br>
<label for="lname">Last:</label>
<input type="text" id="last" name="Last"><br><br>
</div>
<div class="text-center" id="add_student">
<span id="idStudentRootCopy">----S----</span>
<button type="button" onclick="addItem('student', 'idGradeRootCopy', false,this)">Student+</button>
</div>
</div>
</div>
<div class="text-center" id="add_grade">
<span id="idGradeRootCopy">----G----</span>
<button type="button" onclick="addItem('school', 'idGradeRootCopy', true,this)">Grade+</button>
</div>
</div>
Update
If you click on the Grade+ button, it will automatically also 'create' a student input field as it's div is part of the school div. So move it out of the school div and change it's display mode to none.
If you want the new student input field to appear right before the Student+ button, we indeed need to use .insertBefore().
Here's the modified example:
var count = 0;
function addItem(id, index, root, clickedElement) {
var original = document.getElementById(id);
var before = document.getElementById(index);
var clone = original.cloneNode(true);
clone.style.display = 'block';
clone.id = id + ++count;
var newFields = clone.childNodes;
for (var i = 0; i < newFields.length; i++) {
var fieldName = newFields[i].name;
if (fieldName)
newFields[i].name = fieldName + count;
}
if (root) {
original.parentNode.insertBefore(clone, before.parentNode);
} else {
clickedElement.parentNode.insertBefore(clone, clickedElement);
}
}
<div>
<label>Registration</label>
<div id="student" style="display:none">
<label for="fname">First:</label>
<input type="text" id="first" name="First"><br><br>
<label for="lname">Last:</label>
<input type="text" id="last" name="Last"><br><br>
</div>
<div class="form-inline justify-content-center" id="school" style="display:none">
<label for="fname">Grade:</label>
<input type="text" id="grade" name="Grade"><br><br>
<div id="students">
<div class="text-center" id="add_student">
<span id="idStudentRootCopy">----S----</span>
<button type="button" onclick="addItem('student', 'idStudentRootCopy', false,this)">Student+</button>
</div>
</div>
</div>
<div class="text-center" id="add_grade">
<span id="idGradeRootCopy">----G----</span>
<button type="button" onclick="addItem('school', 'idGradeRootCopy', true,this)">Grade+</button>
</div>
</div>
i am developing a form where you should be able to generate dynamically textfields based on a button and delete if necessary, the wrong thing thing starts when i try to delete the whole DIV element i cloned but instead it only deletes the delete button and the textbox stays there and can't be deleted since the div containing the delete button is the one is deleted, the delete button is in the same div as the textbox, before i forget i am doing all of this using bootstrap 4 so i can't use classes for references as i have seen in some examples, i'll write the codeso you can see what i could be doing wrong
HTML CODE
<div class="form-group" name="CamposTexto" id="CamposTexto"> //whole div i desire to clone
<label class="col-sm-2 control-label" id="label_situacion_actual">Situación Actual:<a id="contador"></a></label>
<div class="col-sm-8">
<textarea id="situacion_permiso_precario" name="situacion_permiso_precario"
class="form-control input-sm" style="resize:none;height:60px;text-transform:uppercase;"
maxlength="500" onKeyPress="return SoloNumeros(event);"></textarea>
</div>
<div id="quitarCampoDeTexto" name="quitarCampoDeTexto"> //this is the div that disappears when i press the X to delete, only happens when i cloned the div
<button type="button" onClick="quitarCampoDeTexto(this);" class="btn btn-danger glyphicon glyphicon-remove"></button>
</div>
</div>
<div id="AgregarCampos" class="form-group" style="margin-bottom:10px;"></div> //reserved space for the cloned div to appear
<div id="Botones" style="margin-bottom:10px;">
<center>
<label>Agregar Más</label> //add more button
<button type="button" class="btn btn-success glyphicon glyphicon-plus"
onClick="agregarCampoDeTexto('CamposTexto', 'AgregarCampos');" id="botonAgregar" name="botonAgregar"></button>
</center>
</div>
JS
var contador = 1;
function agregarCampoDeTexto(divName, CamposTexto) {
if (contador == 25) {
document.getElementById("botonAgregar").remove();
} else {
var newdiv = document.createElement('div');
newdiv.innerHTML = document.getElementById(divName).innerHTML;
newdiv.className = 'form-group';
newdiv.id = 'situacion_permiso_precario';
newdiv.name = 'situacion_permiso_precario';
document.getElementById(CamposTexto).appendChild(newdiv);
contador++;
}
var selectElements = document.querySelectorAll('textarea');
for (var i = 1; i < selectElements.length; i++) {
selectElements[i].id = 'situacion_permiso_precario_' + i;
selectElements[i].name = 'situacion_permiso_precario_' + i;
document.getElementById("label_situacion_actual").innerHTML = "Situación Actual:" + i;
}
}
function quitarCampoDeTexto(obj) {
if (contador <= 1) {
return false;
}else{
obj.parentNode.Name == 'form-group'
obj.parentNode.parentNode.removeChild(obj.parentNode);
contador--;
}
}
I have been stuck with this for a couple of days, any kind of help would be great, thanks in advance
EDIT
Labels or div counters are not being displayed properly
Remove the parent of parent using double .parentNode
var contador = 1;
function agregarCampoDeTexto(divName, CamposTexto) {
if (contador == 25) {
document.getElementById("botonAgregar").remove();
} else {
var newdiv = document.createElement('div');
newdiv.innerHTML = document.getElementById(divName).innerHTML;
newdiv.className = 'form-group';
newdiv.id = 'situacion_permiso_precario';
newdiv.name = 'situacion_permiso_precario';
document.getElementById(CamposTexto).appendChild(newdiv);
contador++;
}
var selectElements = document.querySelectorAll('textarea');
for (var i = 1; i < selectElements.length; i++) {
selectElements[i].id = 'situacion_permiso_precario_' + i;
selectElements[i].name = 'situacion_permiso_precario_' + i;
document.getElementById("label_situacion_actual").innerHTML = "Situación Actual:" + i;
}
}
function quitarCampoDeTexto(obj) {
if (contador <= 1) {
return false;
}else{
obj.parentNode.Name == 'form-group';
obj.parentNode.parentNode.remove();
contador--;
}
}
<div class="form-group" name="CamposTexto" id="CamposTexto">
<label class="col-sm-2 control-label" id="label_situacion_actual">Situación Actual:<a id="contador"></a></label>
<div class="col-sm-8">
<textarea id="situacion_permiso_precario" name="situacion_permiso_precario"
class="form-control input-sm" style="resize:none;height:60px;text-transform:uppercase;"
maxlength="500" onKeyPress="return SoloNumeros(event);"></textarea>
</div>
<div id="quitarCampoDeTexto" name="quitarCampoDeTexto">
<button type="button" onClick="quitarCampoDeTexto(this);" class="btn btn-danger glyphicon glyphicon-remove"></button>
</div>
</div>
<div id="AgregarCampos" class="form-group" style="margin-bottom:10px;"></div>
<div id="Botones" style="margin-bottom:10px;">
<center>
<label>Agregar Más</label>
<button type="button" class="btn btn-success glyphicon glyphicon-plus"
onClick="agregarCampoDeTexto('CamposTexto', 'AgregarCampos');" id="botonAgregar" name="botonAgregar"></button>
</center>
</div>
I have written a script that allows a user to add user input into a sample analysis and to add additional samples with a button id="addsmplbtn". However it has come to my attention that in some cases a user would want to fill in one sample and then multiply it for various samples that require the same analyses an n amount of times.
The script below is a very simple version of the actual script. Adding various samples one-by-one is achieved, however I am struggling with adding multiple samples at the same time:
var variable = 1;
$("#addsmplbtn").click(function() {
var element = $(".samplesinfo.hidden").clone(true);
element.removeClass("hidden").appendTo(".paste:last");
$(".panel").hide();
});
$(document).ready(function() {
$("#samplebtn").click(function(){
$(this).next(".panel").slideToggle();
});
$("#addsmplbtn").trigger("click");
});
.hidden {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="addsmplbtn">Add Sample</button>
<div id="samplesinfo" class="samplesinfo hidden">
<button type="button" id="samplebtn" class="samplebtn"></i>Sample</button>
<div class="panel">
<input type="text" name="input1">Input1
<input type="text" name="input2">Input2
<select>
<option value=""></option>
<option>Option1</option>
<option>Option2</option>
</select>
<input type="checkbox" name="checkbox">Check1
<input type="checkbox" name="checkbox">Check2
<input type="text" name="batch_count" id="batch_count" placeholder="enter batch count">
<button type="button" id="add_batch" class="add_batch">Add batch samples</button>
</div>
</div>
<form>
<div>
<h3>No hidden content</h3>
</div>
<div id="paste" class="paste">
</div>
</form>
The following section is the jQuery I am struggling with, to select a single sample, fill in <input> and then to append that element an n amount of times:
$("#add_batch").on("click", function() {
var times = $(this).current("#batch_count").val();
for(var i=0; i < times; i++) {
$(this).current("#add_batch").click(function() {
var element = $(this).current(".samplesinfo").clone(true);
element.appendTo(".paste:last");
$(".panel").hide();
});
}
});
Can anybody please help me adjust the code so that it could achieve my goal?
function addSample(source, target, howMany) {
for(var i=0; i < howMany; i++) {
console.log("adding "+$(source).attr("id")+" to "+target);
var element = $(source).clone(true);
element.removeClass("hidden").appendTo(target);
$(".panel").hide();
}
}
function getInputValue(sender, inputName) {
return $(sender).parent().children('input[name="'+inputName+'"]').val();
}
$("#addsmplbtn").click(function() {
addSample($("#samplesinfo"), $(".paste:last"), 1);
});
$(document).ready(function() {
$("#samplebtn").click(function(){
$(this).next(".panel").slideToggle();
});
addSample($("#samplesinfo"), $(".paste:last"), 1);
});
$("#add_batch").on("click", function() {
var times = getInputValue(this, "batch_count");
addSample($(this).parent().parent().get(0), $(".paste:last"), times);
});
Please don't use the same id attribute on multiple elements. This causes many problems.
This fiddle can be a possible solution.
Never use multiple id-s on HTML elements, this is what classes for!
Use:
$(document).on('{event}', '{selector}', function(){})
on dynamically added elements.
// Add sample click event listener
$(document).on('click', '#add-sample', function() {
var element = $(".samples-info.hidden").clone(true);
element.removeClass("hidden").appendTo(".paste:last");
$(".panel").hide();
});
// Add batch click event listener
$(document).on('click', ".add_batch", function() {
var times = $(this).siblings('.batch_count').val();
var element = $(".samples-info.hidden").clone(true);
for(var i=0; i < times; i++) {
$(".paste:last").append("<div class='.samples-info'>" + element.html() + "</div>");
}
$(".panel").hide();
});
// Toggling the sample's panel
$(document).on('click', '.sample-btn', function() {
$(this).next(".panel").slideToggle();
});
$(document).ready(function() {
// Triggering the first sample on ready
$("#add-sample").trigger("click");
});
.hidden {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="add-sample">Add Sample</button>
<div class="samples-info hidden">
<button type="button" id="sample-btn" class="sample-btn">
Sample
</button>
<div class="panel">
<input type="text" name="input1">Input1
<input type="text" name="input2">Input2
<select>
<option value=""></option>
<option>Option1</option>
<option>Option2</option>
</select>
<input type="checkbox" name="checkbox">Check1
<input type="checkbox" name="checkbox">Check2
<input type="text" class="batch_count" placeholder="enter batch count">
<button type="button" class="add_batch" class="add_batch">
Add batch samples
</button>
</div>
</div>
<form>
<div>
<h3>No hidden content</h3>
</div>
<div id="paste" class="paste">
</div>
</form>
trying to create a dynamic button system to add/remove inputs on clicks. I have the addButton working but not the deleteButton. What am I missing?
$(document).ready(function() {
var maxFields = 20;
var addButton = $('#plusOne');
var deleteButton = $('#minusOne');
var wrapper = $('#userNumbers');
var fieldInput = '<div><input type="text" name="persons" id="persons"/></div>';
var x = 1;
$(addButton).click(function () {
if (x < maxFields) {
x++;
$(wrapper).append(fieldInput);
}
});
$(deleteButton).click(function(e) {
e.preventDefault();
$(this).parent('div').remove();
x--;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button" id="plusOne">+</button>
<button type="button" id="minusOne">-</button>
<div id="userNumbers">
<p>
<input type="text" id="person" name="person">
</p>
</div>
The problem is, that $(this) inside the delete button handler refers to the minus button. That minus button is not inside each of the items (It's at the top. and doesn't have a parent div), so you need to reference the element you want to delete another way. In my case below, I'm selecting the last <div> in $(wrapper):
$(document).ready(function() {
var maxFields = 20;
var addButton = $('#plusOne');
var deleteButton = $('#minusOne');
var wrapper = $('#userNumbers');
var fieldInput = '<div><input type="text" name="persons" id="persons"/></div>';
var x = 1;
$(addButton).click(function () {
if (x < maxFields) {
x++;
$(wrapper).append(fieldInput);
}
});
$(deleteButton).click(function(e) {
e.preventDefault();
$(wrapper).find('div:last').remove();
x--;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button" id="plusOne">+</button>
<button type="button" id="minusOne">-</button>
<div id="userNumbers">
<p>
<input type="text" id="person" name="person">
</p>
</div>
Also you can do it with pure JS using child Nodes. :D
Sometimes pure JS is beater than JQ
Explanation:
remove is a new function. It's a shortcut, making it simpler to remove an element without having to look for the parent node. It's unfortunately not available on old versions of Internet Explorer so, unless you don't want to support this browser, you'll have to use removeChild.
$(document).ready(function() {
var maxFields = 20;
var addButton = $('#plusOne');
var deleteButton = $('#minusOne');
var wrapper = $('#userNumbers');
var fieldInput = '<div><input type="text" name="persons" id="persons"/></div>';
var x = 1;
$(addButton).click(function () {
if (x < maxFields) {
x++;
$(wrapper).append(fieldInput);
}
});
$(deleteButton).click(function(e) {
e.preventDefault();
var myNode = document.getElementById("userNumbers");
i=myNode.childNodes.length - 1;
if(i>=0){
myNode.removeChild(myNode.childNodes[i]);
x--;
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button" id="plusOne">+</button>
<button type="button" id="minusOne">-</button>
<div id="userNumbers">
<p>
<input type="text" id="person" name="person">
</p>
</div>
Try below solution, I care about the back end also because you have to send the data to back end developer so you have to give the array name for input fields such as name="person[]". anyway you can try this solution also.
$(document).ready(function(){
var static_html = '<input type="text" name="person[]" class="input_fields" />';
$("#plus").click(function(){
if($(".input_fields").length < 20 )
$("#dynamic_field_container").append(static_html);
});
$("#minus").click(function(){
if($(".input_fields").length > 1 )
$(".input_fields:last").remove();
else
alert("This is default field so u can't delete");
});
});
.input_fields{
display:block;
}
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="fa fa-plus fa-4x" id="plus"> </span>
<span class="fa fa-minus fa-4x" id="minus"> </span>
<div id="dynamic_field_container">
<input type="text" name="person[]" class="input_fields" />
</div>
I have a form that user can select a/some year form select-options list than add these to next select-list.
To achieve it, I've create 2 select-option and four buttons to add or remove.
The part to insert and remove are achieved but the problem appear when user click add button but there is/arenn't options selected.
The error-message is successful appeared with add jquery animate-fadein/out.
But when error-message have appeared, the button isn't accessible/cann't clicked.
Below is the HTML, and js.
HTML
<div id="segitiga" class="sgtg1" style="background-image: url('picture/left_triangle.png'); display: none"></div>
<div id="err_msg_border" class="err_msg_border1" style="display: none"></div>
<div id="err_msg" class="err_msg1" style="display: none;">Pilih satu atau lebih tahun untuk dimasukkan ke daftar sebelah kanan</div>
<select id="list_tahun" style="width: 80px; margin-right: 5px" multiple="multiple" size="22"></select>
<input type="button" value="Add > >" class="btn_tahun" id="A" >
<input type="button" value="Add All > >" class="btn_tahun" id="AA">
<input type="button" value="< < Remove" class="btn_tahun" id="R" disabled="disabled" >
<input type="button" value=" < < Remove All" class="btn_tahun" id="RA" disabled="disabled">
<div id="segitiga" class="sgtg2" style="background-image: url('picture/right_triangle.png');display: none"></div>
<div id="err_msg_border" class="err_msg_border2" style="display:none"></div>
<div id="err_msg" class="err_msg2" style="display: none">Pilih satu atau lebih tahun yang akan dihapus</div>
Javascript
$(document).ready(function() {
a = document.getElementById('list_tahun');
b = document.getElementById('list_tahun_pilihan');
$("#A").click(function() {
count = 0;
count2 = 0;
for (var i = 0; i < a.options.length; i++) {
if (a.options[i].selected) {
option = document.createElement("option");
option.text = a.options[i].text;
option.value = a.options[i].value;
b.add(option);
a.options[i].selected = false;
a.options[i].disabled = true;
count++;
}
}
if (count < 1) {
$(".sgtg1").fadeIn();
$(".err_msg_border1").fadeIn();
$(".err_msg1").fadeIn();
} else if (count > 0) {
$(".sgtg1").fadeOut();
$(".err_msg_border1").fadeOut();
$(".err_msg1").fadeOut();
document.getElementById('R').disabled = false;
document.getElementById('RA').disabled = false;
}
for (var i = 0; i < a.options.length; i++) {
if (a.options[i].disabled) {
count2++;
}
}
if (count2 === a.options.length) {
document.getElementById('A').disabled = true;
document.getElementById('AA').disabled = true;
} else {
document.getElementById('A').disabled = false;
}
});
....
How I can set up the focus again to the buttons ?
-Thanks-
Your html is invalid.
First Change this:
<input type="button" value="Add>>" class="btn_tahun" id="A" >
To:
<input type="button" value="Add>>" class="btn_tahun" id="A" >
Text like < or > should be written in code like this:
< ==> <
> ==> >
After I inspect element with firefox, the height of area of error message -class="err_msg1" is too height and it's covered the buttons. So, when I want to click the button, the cursor will appear into class="err_msg1".
My advice, be crefully about specify each height-width of element so, when you want some of element runs well, don't let their layer are stacked.