How to change data-attr when clone div - javascript

I have issue with cloning a div.
I have a div with id=director-uploads1. I want to append a div with class=director-uploads-hidden to it. I want to set newly cloned div with class director-uploads-hidden data-number to be with value #director-uploads1 data-number + 1.
$(document).ready(function() {
function clone(){
var number = $('#director-uploads1').attr('data-number');
var director = $('.director-uploads-hidden').html();
var clone = $('#director-uploads1').append(director)
.find("*")
.each(function() {
var name = $(this).attr('name');
})
.on('click', 'button.clone', clone);
//I want to get $("#director-uploads1") attr data-number and to set data-number to the newly cloned div to be current value + 1
//First I did it in this way $("#director-uploads1").attr('data-number', parseInt(number)+1); but I don't want to change initial value of div, only value of the cloned div
}
$("button#add-director").on("click", clone);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="director-uploads number" id="director-uploads1" data-number="0" data-changed="0">
//some data
</div>
<div class="director-uploads-hidden number" style="display:none;" data-number="1" data-changed="0">
//cloned data
</div>
<button type="button" class="btn btn-success" id="add-director">Add Additional Director</button>
So, that after that I pass data to controller via ajax, I can get data-number of each separate div to be different, so that I can differ them.
How could I do that? Thanks.
Updated:
$(document).ready(function() {
function clone(){
var number = $('.director-uploads-hidden').attr('data-number');
var director = $('.director-uploads-hidden').clone(true);
director.data("number", parseInt(number)+1);
$('#director-uploads1').append(director);
director.css("display", "block");
}
$("button#add-director").on("click", clone);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="director-uploads number" id="director-uploads1" data-number="0" data-changed="0">
//some data
</div>
<div class="director-uploads-hidden number" style="display:none;" data-number="1" data-changed="0">
//cloned data
</div>
<button type="button" class="btn btn-success" id="add-director">Add Additional Director</button>
Thank you all for help, maybe it's not the best solution, but I tried with this and it's working:
$(document).ready(function() {
function clone(){
var number = $('#director-uploads1').attr('data-number');
$("#director-uploads1").attr('data-number', parseInt(number)+1);
$('.director-uploads-hidden').find('.app-file').attr('data-item', parseInt(number)+1);
var director = $('.director-uploads-hidden').html();
$('#director-uploads1').append(director)
.find("*")
.each(function() {
var name = $(this).attr('name');
})
.on('click', 'button.clone', clone);
}
$("button#add-director").on("click", clone);
$("html").on('change', '.app-file', function(){
var number = $(this).attr('data-item');
console.log(number);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="director-uploads number" id="director-uploads1" data-number="0" data-changed="0">
<input type="file" class="app-file director_documents" data-item="0" name="director_front_passport[]"/>
</div>
<div class="director-uploads-hidden number" style="display:none;" data-number="1" data-changed="0">
<input type="file" class="app-file director_documents" data-item="0" name="director_front_passport[]"/>
</div>
<button type="button" class="btn btn-success" id="add-director">Add Additional Director</button>

Your clone variable won't be holding a clone of #director-uploads1 it's going to be the collection that find('*') creates.
And $('.director-uploads-hidden').html() will only get the inner html, not the outer div tag that holds the data attribute.
To make a clone you would simply use the clone() jQuery method
var $clone = $('.director-uploads-hidden').clone();
After that to change the data attribute you just set it from $clone not $("#director-uploads1")
$clone.data('number', parseInt(number,10)+1);
//or
$clone.attr('data-number', parseInt(number,10)+1);
Also
.on('click', 'button.clone', clone);
Is trying to set the click handler as your element not your function, because the local variable clone is named the same as your function. Rename your clone variable, for instance like $clone as in the example above.

Try with this snippet.
You can change the attributes and append position as per your need.
//Get old number from the first div
var newNumber = parseInt($('#director-uploads1').attr('data-number'));
$('#add-director').click(function(){
//Get the new length that you would like to set for id
var newLength = parseInt($('.number').length)+1;
//Increment the old number value with +1 to set the new number for every div.
newNumber += 1;
$('div#director-uploads1')
.clone()
.attr('id', 'director-uploads'+newLength)
.attr('data-number', newNumber)
.removeClass()
.addClass('director-uploads-hidden number')
.html('clone data: number'+newNumber +': id '+' director-uploads'+newLength)
.insertBefore('#add-director');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="director-uploads number" id="director-uploads1" data-number="0" data-changed="0">
//some data
</div>
<button type="button" class="btn btn-success" id="add-director">Add Additional Director</button>

jQuery's clone() method should help you:
$(document).ready(function() {
var number = parseInt($('#director-uploads1').data('number'));
function clone(){
var director = $('.director-uploads-hidden').clone(true); //true will cause it to clone all associated data and events as well
director.data("number", number+1);
director.removeClass("director-uploads-hidden");
director.css("display", "block");
//if you want to add any other extra data or events, do it here before appending the object
$('#director-uploads1').append(director);
number++;
}
$("button#add-director").on("click", clone);
});
See https://api.jquery.com/clone/ for more info on the quirks of this method. You may need to do some more tweaking depending on your precise situation and requirements.

Related

How to store the values of different buttons separately in textbox on click event using Javascript?

I am working on a attendance module and this is the prototype of the code, but I have some errors.
As you can see there are dynamically generated buttons and they change colour on click event. I am also storing the value of the buttons in textboxes on click as I have to handle this data on backend with PhP, the error is that when I turn a button to green it's value goes into a textbox and when again i turn it red same value goes into another textbox also, which I don't want. So please help me in solving this problem by reducing the duplicacy of data or by providing a code of a different submit button which when clicked checks the color of all the buttons and stores the values in different textboxes respectively, one for red and one for green. Thanks in advance.
<html>
<head>
<title>Button click event</title>
</head>
<body>
<?php
for($i=0;$i<=10;$i++) {
?>
<button class="btnColorChange" id="<?php echo $i; ?>" style="background-color:#FF0000"><?php echo $i; ?></button>
<?php
}
?>
<div>
<input type="text" name="text1" id="textbox1" value=""/><br><br>
<input type="text" name="text2" id="textbox2" value=""/><br><br>
</div>
<script>
$(".btnColorChange").click(function(){
xyz = this.id
if(this.clicked){
$(this).css('background-color', '#FF0000');
const tb=document.querySelector("#textbox1");
tb.value=tb.value+","+xyz;
console.log(xyz)
this.clicked = false;
} else {
$(this).css('background-color', '#008000');
const tb2=document.querySelector("#textbox2");
tb2.value=tb2.value+","+xyz;
console.log(xyz)
this.clicked = true;
}
});
</script>
</body>
</html>
First, the below statement is wrong:
there are dynamically generated buttons...
When talking about "dynamic" elements, we talk about element that were not existing on page load. It's not the case here, since they were created before page load, on the server-side. Using a loop does not make them "dynamic".
To store clicked/unclicked ids, I suggest you to use some arrays for this.
As I understand it, you want all the "clicked" and "unclicked" ids separately.
The "never clicked" are ignored.
Using two arrays, you can store ids in the relevant group... And even sort them (optionnally).
And you can send those arrays straight to your backend... So the input elements would now be just for testing purposes.
See comments in code:
// Arrays to store ids
var clicked = [],
unclicked = [];
$(".btnColorChange").on("click",function(){
// useful for this demo
console.clear();
// Get the clicked element id
var this_id = this.id;
console.log("Clicked id: "+this_id);
// Toggle the classes (button colors)
$(this).toggleClass("clicked unclicked");
// Check if in array
var in_clicked = $.inArray(this_id,clicked);
var in_unclicked = $.inArray(this_id,unclicked);
//console.log(in_clicked+" "+in_unclicked)
// If clicked
if($(this).hasClass("clicked")){
if(in_clicked==-1){
clicked.push(this_id);
clicked.sort();
}
if(in_unclicked>-1){
unclicked.splice(in_unclicked,1);
}
}
// If unclicked
if($(this).hasClass("unclicked")){
if(in_unclicked==-1){
unclicked.push(this_id);
unclicked.sort();
}
if(in_clicked>-1){
clicked.splice(in_clicked,1);
}
}
// Show arrays content in console
console.log(clicked);
console.log(unclicked);
// Show the ids in inputs as a coma separated string
$("#textbox1").val(clicked.join(","));
$("#textbox2").val(unclicked.join(","));
});
.unclicked{
background-color: #FF0000;
}
.clicked{
background-color: #008000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="btnColorChange unclicked" id="1">1</button>
<button class="btnColorChange unclicked" id="2">2</button>
<button class="btnColorChange unclicked" id="3">3</button>
<button class="btnColorChange unclicked" id="4">4</button>
<button class="btnColorChange unclicked" id="5">5</button>
<br>
<br>
<div>
<input type="text" name="text1" id="textbox1" value=""/><br><br>
<input type="text" name="text2" id="textbox2" value=""/><br><br>
</div>
Please run the snippet in full page mode, because of the console logs.
For more reading, the below demo uses the following methods:
.on()
.toggleClass()
$.inArray()
.hasClass()
.push()
.sort()
.splice
.val()
.join()
You certainly noticed that I used two CSS rules for the button colors, instead of inline style attributes.
CodePen
If i understood you well, you want for example the Button to handle updates of textbox1 on first click and update textbox2 on second click. You could do this.
$(".btnColorChange").on("click", function(){
var btn = $(this);
var id = btn.attr("id");
if(btn.hasClass('clicked')){
var textboxselected = $("#textbox1");
var backgroundColor = "#FF0000";
btn.removeClass('clicked');
}else{
var textboxselected = $("#textbox2");
var backgroundColor = "#008000";
btn.addClass('clicked');
}
btn.css("background-color", backgroundColor);
textboxselected.val(textboxselected.val()+id);
});
Suppose you want to update same textbox
$(".btnColorChange").on("click", function(){
var btn = $(this);
var id = btn.attr("id");
var textvalue = $("#textbox1").val();
if(btn.hasClass('clicked')){
var backgroundColor = "#FF0000";
btn.removeClass('clicked');
}else{
var backgroundColor = "#008000";
btn.addClass('clicked');
}
btn.css("background-color", backgroundColor);
$("#textbox1").val(textvalue);
});
Its untested but hopes it works for you.

Why does my delete all button need to be double clicked to work?

So, I was adding a delete all button and it works, the only problem is that it needs to be double clicked just to make it work.
may I ask what's wrong? thank you :)
I added the codes that were used to create the button here:
<body>
<!--for everything in the navigation part including the add favorite bar-->
<div class="topnav">
<div class="addFave">
<!--the text bar-->
<input type="text" name="enter" class="enter" value="" id="added" placeholder= "Add Favorites"/>
<!--the enter button-->
<input type="button" value="Enter" id = "addIt" OnClick="adding()" />
<!--for the script of the add favorite bar to add its functions-->
<script type="text/javascript">
var faves = [];
var y = document.getElementById("added");
function adding() {
faves.push(y.value);
document.getElementById("faveLists").innerHTML = faves;
}
var input = document.getElementById("added");
input.addEventListener("keyup", function(event) {
event.preventDefault();
if (event.keyCode === 13) {
document.getElementById("addIt").click();
}
});
</script>
</div>
</div>
<br />
<div class="buttons">
<button onclick="eradicateFaves()">Remove All Favorite</button>
<script>
-coding to remove all the favorites on the list-->
function eradicateFaves(){
document.getElementById("faveLists").innerHTML = faves;
while(faves.length > 0){
faves.shift();
}
}
</script>
</div>
<p id = "faveLists"></p>
while(faves.length > 0){
faves.shift();
}
Why not just faves = [] to empty it? And shouldn't you empty the list before assigning it? That's why you need two clicks; first time re-assigns current list then empties it, and second time assigns the empty list then does nothing more as it is already empty. So, try this:
function eradicateFaves(){
faves = [];
document.getElementById("faveLists").innerHTML = faves;
}
When you say "delete all" I assume you mean reset the faves array back to []. Well why not just do this:
function eradicateFaves() {
faces = [];
document.getElementById("faveLists").innerHTML = faves;
}
The reason it wasn't working earlier was because Array.prototype.shift() only removes the first element of the array. According to the MDN docs:
The shift() method removes the first element from an array and returns that removed element. This method changes the length of the array.

JavaScript- dynamically adding input to a page

i am using JavaScript to add a div on the fly. The div should contain a form input whose 'name' attribute WILL changes in value incrementally.
I have managed to do this- I however have two problems.
First Problem:
The first div that i created is cancelled out by the next dynamically created div.
thus, when i submit the form, the first dynamically created imput form is blank-
but subsequent ones have values on them.
MY CODE :
html
<div id="dynamicDivSection"></div>
<button id="addbutton">add box</button>
<div id="boxes">
<div class="box">
<input type="text" id='dynamic-imput' name="">
</div>
</div>
javascript
var addbutton = document.getElementById("addbutton");
var key = 1;
addbutton.addEventListener("click", function() {
key++;
document.getElementById('dynamic-imput').name = 'ser['+key+'][\'name\']';
var boxes = document.getElementById("boxes");
var head = document.getElementById("dynamicDivSection");
var clone = boxes.firstElementChild.cloneNode(true);
head.appendChild(clone);
});
i suspect that the problem is causing by this:
document.getElementById('dynamic-imput').name =
'ser['+key+'][\'name\']';
i.e when i create the dynamic div it creates several inputs on the page that contain the same Id. if i am correct, then perhaps teh solution is to change the Id of the newly created imput - however, i am not sure how to change the Id of a dynamically created Imput.
Second problem.
i want each dynamically created div to go to the top of the page; i.e to be placed before the earlier created dynamic div- however, at the moment each dynamically created div go directly under the first dynamically created div.
You can insert as the first child with:
parent.insertAdjacentElement('afterbegin', nodeToInsert);
You can get and set attributes such as id with setAttribute and getAttribute. Though I'm not sure why you even need an ID here, it would be simpler not to have one and select the element with a class.
var addbutton = document.getElementById("addbutton");
var key = 1;
addbutton.addEventListener("click", function() {
key++;
document.getElementById('dynamic-imput').name = 'ser['+key+'][\'name\']';
var boxes = document.getElementById("boxes");
var head = document.getElementById("dynamicDivSection");
var clone = boxes.firstElementChild.cloneNode(true);
var clonedInput = clone.firstElementChild;
clonedInput.setAttribute('id', clonedInput.getAttribute('id') + '-' + head.children.length);
head.insertAdjacentElement('afterbegin', clone);
});
<div id="dynamicDivSection"></div>
<button id="addbutton">add box</button>
<div id="boxes">
<div class="box">
<input type="text" id='dynamic-imput' name="">
</div>
</div>

Select dynamically created element

I created a div dynamically and attached to div. I'm trying to add data from query and load it to that text field. But, I'm unable to select the dynamically created elements because its not visible in the DOM, since its already loaded.
This is what I have fiddle
<div id="parent">
<input id='childButton' type="button" value="Add"/>
<div id="child" data-row="0">
<input type="text" value="" />
</div>
</div>
var rowNum = 0;
$('#parent').on('click', '#childButton', function() {
var clone = $('#child').clone().attr('data-row', ++rowNum);
$('#parent').append(clone);
console.log($('#child[data-row=1]').length);
});
The problem is the id selector, will return only the first element with the given id. In your case you are creating multiple elements with the id child. So #child will return the first child element, but then applying the data-row rule will filter out the selected element so you are getting 0 are the result.
The solution is to use a class instead of id to select the element
var rowNum = 0;
$('#parent').on('click', '#childButton', function() {
var clone = $('#child').clone().attr('data-row', ++rowNum).removeAttr('id');
$('#parent').append(clone);
//here clone refers to the dynamically create element
//but if you want to fetch the element using a selector then
snippet.log($('.child[data-row=1]').length);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
<div id="parent">
<input id='childButton' type="button" value="Add" />
<div id="child" class="child" data-row="0">
<input type="text" value="" />
</div>
</div>
You're cloned element with same id, if you want to check just use
console.log($('div[data-row=1]').length);
Like others said, an ids should be unique. Use class definition instead for child id name.
When you're cloning an element with id, change the id (fiddle):
var rowNum = 0;
$('#parent').on('click', '#childButton', function() {
var origin = $('#child');
var originId = $('#child').attr('id');
var cloneId = originId + rowNum;
var clone = $('#child').clone().attr('data-row', ++rowNum).attr('id', cloneId);
$('#parent').append(clone);
console.log($('#' + cloneId).length);
});
DEMO
var rowNum = 0;
$('#parent').on('click', '#childButton', function() {
var clone = $('#child').clone().attr('data-row', ++rowNum);
$('#parent').append(clone);
console.log($('#parent input:text').length);
});
You can also select the input by using the selector input:text
UPDATE
DEMO
IF you want to select the specific input to set value into you can use the index and set the value by finding that index
I think your selector is wrong it must be:
console.log($('#child[data-row="1"]').length);
and consider to remove the id attr in order to avoid multiple ids.
Demo: http://jsfiddle.net/o1j7z1gL/

Delete button next to each array's value

I have a HTML-JavaScript script in which the user can insert data to a new array [] by using a form's text field and an insert button.
By pressing insert button, the user inserts the data typed into the array.
I have a function which prints all the values of the array into <p id="demo"></p> and runs itself every 100 milliseconds in order to be updated with the arrays values.
I also have a reset button to delete every array's value when clicked.
What I want to do is add a delete button next to each array's value in order to be easier for the user to delete the wrong value he inserted.
I am using this code to insert values and print them:
HTML:
<div align="center">
<form id="form1">
<input type="text" name="fname" id="fname" placeholder="Type here!">
</form>
<br>
<input type="button" id="Button Insert" onclick="myFunction()" value="Insert">
<input type="button" onclick="myFunction3()" value="Reset">
</div>
<p id="demo" align="center"></p>
JavaScript/JQuery:
var all_values =[];
function myFunction() {
var temp_val = $("#fname").val();
all_values.push(temp_val);
document.getElementById("form1").reset();
}
setInterval(function () {
$("#demo").html(all_values.join("<br>"));
}, 100);
function myFunction3() {
all_values.length = 0;
}
To be more specific I want something like these things: iOS example JSFiddle Example 1 JSFiddle Example 2.
Could you please help me? Thanks in advance.
I'd do it the other way around.
Remove setInterval as it's really bad way to do such things.
Remove white spaces from the id attribute (id="Button-Insert", not id="Button Insert")
Don't use onclick attributes. Instead, register click event handlers with jQuery
// caching is a good practice when you reffer to the same elements multiple times:
var all_values =[], demo = $("#demo"), form = $("#form1")[0], fname = $("#fname");
$('#Button-insert').click(function(){
var temp_val = fname.val();
all_values.push(temp_val);
// create delete button along with the value
demo.append('<p>'+temp_val+' <button value="'+temp_val+'" type="button" class="del-btn">Delete</button></p>');
form.reset();
});
$('#Button-reset').click(function(){
all_values = [];
demo.html('');
});
// event delegation for dynamic elements:
demo.on('click', '.del-btn', function(){
all_values.splice(all_values.indexOf($(this).val()), 1);
$(this).parent().remove();
});
JSFiddle
Simply create the delete buttons at the same time you create the table.
function loadvalues(){
var i, button;
$('#demo').empty();
for(i in all_values){
$('#demo').append(all_values[i]);
button = $('<button>',{'text':'Delete'}).click(function(){
all_values.splice(this,1);
loadvalues();
}.bind(i)).appendTo('#demo');
$('#demo').append('<br>');
}
}
Also you don't need to poll, you could simply add each one on demand with a function like this:
function addVal(){
var val = $("#fname").val(), i = all_values.length;
all_values.push(val);
$('#demo').append(val);
button = $('<button>',{'text':'Delete'}).click(function(){
all_values.splice(this,1);
loadvalues();
}.bind(i)).appendTo('#demo');
$('#demo').append('<br>');
}
I had some typos, the code works,
Check here:
http://codepen.io/anon/pen/QbvgpW

Categories