add onclick event to dynamically create element - javascript

I would like to create list of divs,
one of the divs should like this:
<div onclick="myFunc(this, 'arrayValue')"></div>
I want to achieve it by iterating through my array and passing index value to my function. One of the solutions that worked was using setAttribute :
for(var i = 0; i < array.length; i++){
var div = document.createElement("div");
div.setAttribute("onclick", 'myFunc(this, \''+array[i]+'\')');
myDiv.appendChild(div);
}
The only problem is that this part looks really ugly: \''+array[i]+'\')'
Is there other way to achieve this? That would look like this or something similar:
div.setAttribute("onclick", myFunc(this, array[i]);
btw. other solutions: when I used div.onclick the onclick attr was not visible on div (result: <div></div>), possibly I did something wrong.

var array = ['bla1','bla2'];
var myFunc = function(value) {
alert('click : '+ value);
};
var myDiv = document.getElementById('myDiv');
for(var i = 0; i < array.length; i++){
var div = document.createElement("div");
div.className = 'bla';
myDiv.appendChild(div);
div.addEventListener('click', myFunc.bind(this, array[i]));
}
.bla {
border: 1px solid black;
width: 20px;
height: 20px;
margin: 10px;
}
<div id="myDiv"></div>
Is that you want ?

Related

Show class div and hide previous - pure javascript

I was actually using a script which allowed me to Show a div onclick and hide others but now I need to do the same with "class" instead of "id".
My current script:
function layout(divName){
var hiddenVal = document.getElementById("tempDivName");
if(hiddenVal.Value != undefined){
var oldDiv = document.getElementById(hiddenVal.Value);
oldDiv.style.display = 'none';
}
var tempDiv = document.getElementById(divName);
tempDiv.style.display = 'block';
hiddenVal.Value = document.getElementById(divName).getAttribute("class");}
What I tried using getElementsByClassName :
function layoutNEW(divName){
var hiddenVal = document.getElementById("tempDivName");
if(hiddenVal.Value != undefined){
var oldDiv = document.getElementById(hiddenVal.Value);
oldDiv.style.display = 'none';
}
var tempDiv = document.getElementsByClassName(divName);
for ( var i=0, len=tempDiv.length; i<len; ++i ){
tempDiv[i].style.display = 'block';
}
hiddenVal.Value = document.getElementById(divName).getAttribute("id");}
Any ideas ?
EDIT : A working example of my current script with "id" : JSFiddle
EDIT 2: It works great, but when the div (class) is cloned, only one of them is showing the div. Do you have an idea about this ? Where is a JSFiddle demonstrating the situation: JSFiddle
I think this is what you'd need. The idea is that you can use a data property on your <a> tags that will tell your click handler which classname to look for when showing an element. From there, you just hide the others. Here's a working demo:
var toggleControls = document.querySelectorAll("[data-trigger]");
var contentDivs = document.querySelectorAll(".toggle");
for (var i = 0; i < toggleControls.length; i++) {
toggleControls[i].addEventListener("click", function(event) {
var trigger = event.target;
var selector = "." + trigger.getAttribute("data-trigger");
var divToShow = document.querySelector(selector);
for (j = 0; j < contentDivs.length; j++) {
contentDivs[j].style.display = "none";
}
divToShow.style.display = "block";
});
}
.toggle {
height: 100px;
width: 100px;
display: none;
}
.div1 {
background-color: red;
}
.div2 {
background-color: blue;
}
.div3 {
background-color: purple;
}
.div4 {
background-color: green;
}
Show Div1
<br/>
Show Div2
<br/>
Show Div3
<br/>
Show Div4
<div class="toggle-container">
<div class="toggle div1"></div>
<div class="toggle div2"></div>
<div class="toggle div3"></div>
<div class="toggle div4"></div>
</div>
EDIT - As per updated question
In order to get this to work with dynamically created elements, you will have to put the var contentDivs = ... inside of the click handler, so you get a live version of that array. Also, you will need to change .querySelector to .querySelectorAll as the former only grabs the first matching element, not all as the latter does.
Here's what the code would look like: (note - I also moved the click handler into an outside function so it was not being recreated for every iteration of the loop, as is good practice)
function clickHandler(event) {
var contentDivs = document.getElementsByClassName("toggle"); // get live set of contentDivs in case any were added dynamically
var trigger = event.target;
var selector = "." + trigger.getAttribute("data-trigger");
var divsToShow = document.querySelectorAll(selector); // grab all matching divs
for (var i = 0; i < contentDivs.length; i++) {
contentDivs[i].style.display = "none";
}
for (var j = 0; j < divsToShow.length; j++) {
divsToShow[j].style.display = "block";
}
}
var toggleControls = document.querySelectorAll("[data-trigger]");
for (var i = 0; i < toggleControls.length; i++) {
toggleControls[i].addEventListener("click", clickHandler);
}
function cloneDiv() {
var elmnt = document.getElementsByClassName("container");
for ( var i=0; i<elmnt.length; i++ ) {
var cln = elmnt[i].cloneNode(true);
}
document.body.appendChild(cln);
document.getElementById("clone").appendChild(cln);
}
window.onload = cloneDiv();

(vanilla javascript calculator) How do I get the nodeValue from this nodeList?

What I'm trying to do is grab the node that was clicked and add it to the innerHTML of the screen I have set up. However, it seems as though my for loop is completing before I can get that value. In my case, keys[3] doesn't exist, so it is returning an error, but I would like to have the loop stop on the 'clicked' element and grab that value.
JS Bin snippit
What you need to do is use textContent instead of nodeValue to get 1, 2, or 3. Next, use this instead of keys[i].
var screen = document.getElementById("screen");
var keys = document.querySelectorAll('.keys');
for (var i = 0; i < keys.length; i++) {
keys[i].addEventListener('click', function() {
screen.innerHTML += this.textContent;
});
}
#calculator {
width: 500px;
height: 600px;
border: 1px solid black;
}
#screen {
width: 100%;
height: 100px;
border: 1px solid black;
}
.keys {
width: 24%;
display: inline-block;
border: 1px solid black;
height: 50px;
cursor: pointer;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div id="calculator">
<div id="screen">
</div>
<div class="keys">1</div>
<div class="keys">2</div>
<div class="keys">3</div>
</div>
</body>
</html>
Now this should be working properly as it gets the text content, and instead of keys[i], it uses this as i doesn't exist outside the loop. this references the current element. You could always define the anonymous function outside, and use a for-each loop.
The i variable exists only in the loop, it does not exist in the click event.
Try changing this:
screen.innerHTML += keys[i].firstChild.nodeValue;
To this:
screen.innerHTML += this.outerHTML;
for (var i = 0; i < keys.length; i++) {
keys[i].addEventListener('click', function(e) {
console.log(e, e.target)
screen.innerHTML += e.target.innerHTML;
});
i would use e.target to get anything out of div.
this feels more clean.
That is if you goal is to get any text that is in a container.
Although this would not be the most effective way to make a calculator.
http://jsbin.com/rifekejivi/1/edit?html,css,js,console,output
I would use let not var. This works:
for (let i = 0; i < keys.length; i++) {
keys[i].addEventListener('click', function() {
screen.innerHTML += keys[i].firstChild.nodeValue;
});
Ok: Edit:
var screen = document.getElementById("screen");
var keys = document.querySelectorAll('.keys');
var val = 0;
screen.innerHTML = 0;
for (let i = 0; i < keys.length; i++) {
keys[i].addEventListener('click', function() {
val += parseInt(keys[i].firstChild.nodeValue);
screen.innerHTML = val;
});
}
And to clarify: I would (allways) use let i = 0 in a loop because it also works with async operations in a loop because it is a block scope.
Not applying to this particular case but try this:
var x = [1,2,3,4];
for(var i = 0; i<x.length; i++){
window.setTimeout(function(){
console.log(i);
},Math.random())
}
//console.log returns: 4 4 4 4
for(let i = 0; i<x.length; i++){
window.setTimeout(function(){
console.log(i);
},Math.random())
}
//console.log returns 0 1 2 3
See the difference?
just add a click event to the body, and check if the targets class name equals key, then add the textContent of the target to screen
"use strict"
var screen = document.getElementById("screen");
var keys = document.querySelectorAll('.keys');
// for (var i = 0; i < keys.length; i++) {
// keys[i].addEventListener('click', function() {
// screen.innerHTML += this.textContent;
// });
// }
document.body.addEventListener('click', function(e) {
let target = e.target;
switch(target.className) {
case "keys":
screen.innerHTML += target.textContent;
break;
default:
}
})

How to append divs into another div inside a variable?

So, I am trying to create a HTML code generator just for fun. My actual problem is: How can I append divs from a loop inside another div that does not exist and is saved in a variable?
I hope I have been clear, thank you.
My little JavaScript until now:
colCont = $("<div class=\"stab-cont\"><div class=\"stab-row\"></div></div>");
function repeat(n) {
for (var i = 1; i < n + 1; i++) {
//Here I need to insert the n DIVs generated by this loop
}
}
repeat(3);
console.log(colCont);
JSFiddle: http://jsfiddle.net/qo3vdwhv/
Maybe I am under thinking it here, but this should work.
My code:
colCont = $("<div class=\"stab-cont\"></div>");
function repeat(n) {
for (var i = 1; i < n + 1; i++) {
$("<div class=\"stab-row\"></div>").appendTo(colCont); //build your div like you did with "colCont" and append the new div to colCont
}
}
repeat(3);
colCont.appendTo($("body"))
.stab-cont div {
border: 1px solid #c00;
margin: 10px;
float: left;
width: 200px;
height: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Here's something to consider; instead of making your repeat() function dependent on colCont, make it a jQuery function instead.
In this case I've created a function that will repeat the contents of a jQuery object N times (N >= 1).
colCont = $("<div class=\"stab-cont\"></div>");
jQuery.fn.times = function(n) {
var len = this.length;
for (var i = 1; i < n; ++i) {
for (var k = 0; k < len; ++k) {
this.push(this[0].cloneNode(true));
}
}
return this;
};
colCont
.append($('<div class="stab-row"></div>').times(3))
.appendTo('body');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Adding elements on loop jQuery

I am trying to generate a row of 16 boxes on load of webpage.
Here is my code:
var box = $("<div></div>").addClass("box");
$(document).ready(function(){
for(var i = 0; i < 16; i++) {
$("#container").append(box);
}
});
I also tried this within the for loop's code block:
if($("#container:contains(box)")) {
$(box).append(box);
}
I kind of understand why this does not work. That var box is only referencing an element and is not a copy of an element?
As you can likely tell, I'm new. I would really appreciate some pointers on how I can achieve this. Thanks.
Why not just use like this?
for(var i = 0; i < 16; i++) {
$("#container").append('<div class="box box-'+i+'" />');
}
You're appending the same div over and over. That will just move it (in this case, right back where it was). For a new div each time:
$(document).ready(function(){
var ctr = $('#container');
for(var i = 0; i < 16; i++) {
ctr.append("<div class='box'></div>");
}
});
$(document).ready(function() {
var ctr = $('#container');
for (var i = 0; i < 16; i++) {
ctr.append("<div class='box'></div>");
}
});
.box {
margin: 10px;
height: 25px;
width: 25px;
background-color: red;
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container"></div>
I recommend against using append in a loop, bad performance. I suggest this:
var buffer = [];
for(var i = 0; i < 16; i++) {
buffer.push("<div class='box'></div>");
}
var html=buffer.join('');
$('#container').append(html);

List all items from a for loop with javascript

I'm looking for a way to list each firstname from the below loop. Currently it loops through each firstname stoping at the last which is Jack and only displaying that. I want it to display all of them like: John, Jane, Joe
var person = [{firstName:"John"}, {firstName:"Jane"}, {firstName:"Jack"}];
for (var i = 0; i < person.length; i++) {
document.getElementById("demo").innerHTML = person[i].firstName;
}
Can anyone advise on how I would do this?
The problem is that your are overwriting the innerHTML value, instead that you need to append your values to innerHTML property using '+':
var person = [{firstName:"John"}, {firstName:"Jane"}, {firstName:"Jack"}];
var demo = document.getElementById("demo");
for (var i = 0, len = person.length; i < len; i++) {
demo.innerHTML += person[i].firstName + ' ';
}
Check out this codepen. I have add some modifications to make the code more performant.
Please take a look at this code:
var person = [{firstName:"John"}, {firstName:"Jane"}, {firstName:"Jack"}],
html = "";
for (var i = 0; i < person.length; i++) {
html += person[i].firstName;
}
document.getElementById("demo").innerHTML = html;
You are overwriting each time with the innerHTML because you are not using '+='. I like to create a string beforehand and set it to nothing. Then you can add everything to that and only need to call innerHTML once.
Hope this helps!
here's another way to do it using a more functional style
"use strict";
var people = [{firstName:"John"}, {firstName:"Jane"}, {firstName:"Jack"}];
var node = document.getElementById('demo');
node.innerHTML = people.map(function(person){
return person.firstName;
}).join(', ');
#demo {
padding: 1em;
background-color: #def;
border: 1px solid gray
}
<div id="demo"></div>

Categories

Resources