I am creating dynamically multiple div elements using JavaScript. Below is the code I have used:
for(i=0;i<3;i++)
{
var d1 = document.createElement('div');
d1.id = "div" + i;
var l1 = document.createElement('label');
l1.innerHtml = "Hello";
d1.appendChild(l1);
var line1 = document.createElement('hr');
d1.appendChild(line1);
document.body.appendChild(d1);
}
Output:
Hello
Hello
Hello
Now I want to dynamically append event say onmouseover and onmouseout so that whenever I move cursor over a particular div element say div1, div2 or div3, that respective div section should change color (say blue) and when cursor moves out it should return to its original color.
I have tried working out but I am unable to retrieve the div id's which I have created dynamically.
You don't need to select by ID. You already have the element, so go ahead and add handlers to it.
for(i=0;i<3;i++) {
var d1 = document.createElement('div');
d1.id = "div" + i;
var l1 = document.createElement('label');
l1.innerHtml = "Hello";
d1.appendChild(l1);
var line1 = document.createElement('hr');
d1.appendChild(line1);
document.body.appendChild(d1);
d1.onmouseover = function() {
this.style.color = "#00F";
};
d1.onmouseout = function() {
this.style.color = "";
};
}
Just build your handlers and then assign them in the loop:
var mouseover = function() {
this.style.backgroundColor = '#AAF';
},
mouseout = function() {
this.style.backgroundColor = '';
};
for (i = 0; i < 3; i++) {
var d1 = document.createElement('div'),
l1 = document.createElement('label'),
line1 = document.createElement('hr');
d1.id = "div" + i;
l1.innerHtml = "Hello";
d1.appendChild(l1);
d1.appendChild(line1);
d1.onmouseover = mouseover;
d1.onmouseout = mouseout;
document.body.appendChild(d1);
}
Demo at: http://jsfiddle.net/vfVCm/
If your elements are created dynamically it may be better to use event delegation and attach the event listener to the parent element instead of every element that you're dynamically creating. This way your listener will work even for elements created after it's attached. DOM events bubble, and an actual target of an event is available as event.target. Here is an example:
<div id="parent">
<p id="event1">A</p>
<p id="event2">B</p>
<p id="event3">C</p>
</div>
// call on DOMContentLoaded
document.getElementById("parent").addEventListener("click", function(e) {
if(e.target && e.target.nodeName.toLowerCase() == "p") {
alert("Clicked element " + e.target.id);
}
});
See jsfiddle.
Related
This code is not creating a single div in the webpage which i linked the js below. how can i makes changes in the js or html for the code to be executed as expected
var div,
container = document.getElementById("container");
for (var i = 0; i < 5; i++) {
div = document.createElement("div");
div.onclick = function () {
alert("This is box #" + i);
};
container.appendChild(div);
}
1) To show a div you have to include some text inside divtag
2) You should use let instead of var to get the correct number when user click on div
var div,
container = document.getElementById("container");
for (let i = 0; i < 5; i++) { // change -> let instead of var
div = document.createElement("div");
div.textContent = `div${i}` // change -> add some text
div.onclick = function() {
alert("This is box #" + i);
};
container.appendChild(div);
}
<div id="container"></div>
I have a parent div to which I add children divs in a loop. For each child I try to add an onclick event - so that the child div would change its color when clicked on:
var div;
for (var i=1; i<=size*size; i++) {
div = document.createElement("div");
div.id = i;
div.style.width = 480/size + "px";
div.style.height = 480/size + "px";
div.onclick= function() {
div.style.backgroundColor="orange";
}
resultNode.appendChild(div);
}
However only the last div changes its color, no matter what child is clicked on. I suspect its because var div's last value is the last child, but shouldn't the onclick added to its previous objects remain with those objects once they are added inside resultNode?
I also tried adding this loop:
var children=resultNode.children;
for (var i=0; i<children.length; i++) {
children.item(i).onclick = function() {
children.item(i).style.backgroundColor="blue";
alert(i);
}
}
However, it only works for a single child which index varies, depending of the amount of children. If there are only 25 (its the value of size*size in the code) children, the child with index 6 would get colored. If there are 100 children, the 11th child would get colored, if there are 400 children, 21th child would get colored. That is always the second div of the second row (there are size*size divs which form a square with size rows and size columns, meaning the div that gets colored is in the size+1 position):
I don't understand this behavior. Why does this happen and how should I edit the code to achieve the desired result (any child div when clicked on changes its color)?
div does not reference what you are expecting within the click handler, see JavaScript closure inside loops – simple practical example. You can use event.target to reference the element where the event was dispatched
for (let i = 1; i <= 5; i++) {
let div = document.createElement("div");
div.id = i;
div.textContent = i;
div.onclick = e => e.target.style.backgroundColor = "orange";
resultNode.appendChild(div);
}
<div id="resultNode"></div>
Alternatively
for (let i = 1; i <= 5; i++) {
let div = document.createElement("div");
((div) => {
div.id = i;
div.textContent = i;
div.onclick = e => div.style.backgroundColor = "orange";
resultNode.appendChild(div);
})(div)
}
<div id="resultNode"></div>
Your code would also work if you just tweak it as below:
var div;
for (var i=1; i<=size*size; i++) {
div = document.createElement("div");
div.id = i;
div.style.width = 480/size + "px";
div.style.height = 480/size + "px";
div.onclick= function() {
this.style.backgroundColor="orange";
}
resultNode.appendChild(div);
}
Inside onclick function just change it to this.style.background = 'orange' instead of div.style.background = 'orange' object. Your code was not working because div object is pointing to your last div.
I am trying to retrieve the input value of a child element from automatically generated elements in my document in order to use its values but i am having trouble accessing the child, How can i go about doing this? (im very new to JS)
var createCard = function (num, x) {
var div = document.createElement('div');
var classN = "card" + num;
var classX = "card" + x;
div.className += classX;
div.className += " card ";
div.className += classN;
div.style.opacity ="1"
div.addEventListener("click", function (e) {
var div = $(e.target);
var n = div.firstElementChild.value; //here lies the suspected problem
if (div.css('opacity') == "0.3") {
div.css('opacity', "1");
aNum(n);
}
else {
div.css('opacity', "0.3");
mNum(n);
}
});
var worth = document.createElement('input')
worth.setAttribute('type', 'hidden');
worth.setAttribute('value', num);
div.appendChild(worth);
document.getElementById('gameArea').appendChild(div);
};
You can use Jquery to select an element's child.
There's multiple ways to go about this, but I'd suggest checking out Jquery Selectors.
I believe the selector for a child of an element is .children(":first")
So you'd do
var child = $("MyDivSelector").children(":first");
Set the id for the input
worth.setAttribute('id', 'hidworth');
Get the input
var hidWorth=document.getElementById('hidWorth');
What impact does eventlisteres have? Im talking about big numbers, here's an example:
There's only x amount of .marker at first
All children are added via JS when .marker is clicked - eventlistener
Each child does it's own thing which means each of them have their own eventlisteners
<!-- Final HTML of single .marker when it has been clicked -->
<div class="marker">
<div class="remove"></div>
<div class="change"></div>
<div class="add"></div>
<div class="drag"></div>
</div>
var count = 20 000;
for(i = 0; i < count; i++) {
var marker = document.createElement('div');
marker.className = 'marker';
someParentElement.appendChild(marker);
marker.click( function() {
//Create child elements
var remove = document.createElement('div');
remove.className = 'remove';
marker.appendChild(remove);
var change = document.createElement('div');
change.className = 'change';
marker.appendChild(change);
var add = document.createElement('div');
add.className = 'add';
marker.appendChild(add);
var drag = document.createElement('div');
drag.className = 'drag';
marker.appendChild(drag);
//Children eventlisteners
remove.click( function() {
//Do it's thing
});
change.click( function() {
//Do it's thing
});
add.click( function() {
//Do it's thing
});
drag.click( function() {
//Do it's thing
});
});
}
Please don't mind other things, e.g creating 20 000 elements programmatically. My question is this: what would be the impact of having all these eventlisteners with all this code in them? Does it even matter what or how much code is inside eventlistener as long as it hasn't been triggered?
Try using event delegation , single event handler. See switch , .is()
var count = 100;
for (i = 0; i < count; i++) {
var marker = document.createElement('div');
marker.className = 'marker';
marker.innerHTML = marker.className + " " + i;
document.body.appendChild(marker);
//Create child elements
var remove = document.createElement('div');
remove.className = 'remove';
remove.innerHTML = "remove" + i;
marker.appendChild(remove);
var change = document.createElement('div');
change.className = 'change';
change.innerHTML = "change" + i;
marker.appendChild(change);
var add = document.createElement('div');
add.className = 'add';
add.innerHTML = "add" + i;
marker.appendChild(add);
var drag = document.createElement('div');
drag.className = 'drag';
drag.innerHTML = "drag" + i;
marker.appendChild(drag);
//Create child elements
}
var check = function(args) {
alert(args.innerHTML.replace(/[^\d+]/g, ""))
}
var obj = {
remove: check,
change: check,
add: check,
drag: check
}
var message = function(name) {
console.log(name)
}
$("body").on("click", ".marker", function(event) {
var name = event.target.className;
switch (name) {
case "remove":
/* do stuff */
message(name);
break;
case "change":
/* do stuff */
message(name);
break;
case "add":
/* do stuff */
message(name);
break;
case "drag":
/* do stuff */
message(name);
break;
default:
/* do stuff */
alert(name);
break;
}
// utilizing `.is()`
if ($(event.target).is(".remove")) {
// do stuff
event.target.innerHTML += "clicked"
}
if ($(event.target).is(".change")) {
// do stuff
event.target.innerHTML += "clicked"
}
if ($(event.target).is(".add")) {
// do stuff
event.target.innerHTML += "clicked"
}
if ($(event.target).is(".drag")) {
// do stuff
event.target.innerHTML += "clicked"
}
if (!$(event.target).is(".marker")) {
// utilizing an object
obj[event.target.className](event.target)
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
Creating event handlers for so many things which are repeated feels like a waste of CPU cycles, plus memory to manage so many event listeners.
Instead, it would be preferrable to use event bubbling/delegation to listen to the click events from a parent node (as close an ancestor element as possible would be ideal) and see what element triggered the event and call the appropriate code accordingly.
This would be a one-time bind, and should also catch dynamically added elements if done right.
Examples with jQuery that are also explained quite well include the following
https://learn.jquery.com/events/event-delegation/
http://api.jquery.com/on/
Though you are not limited to just jQuery to implement this.
Hope that helps.
I'm confused on how to change text content of div with the DOM. When event is triggered, I see that the new text replace the old but it is in a new div. I want to keep it in "transcriptText" to keep all attributes.`How can I do that?
This is my old div with text inside:
var transcriptText = document.getElementById("transcriptText");
these are my new text SPAN elements
var newTranscript = document.createElement("div");
This is how I handle the event
function EventHandler() {
transcriptText.parentNode.replaceChild(newTranscript, transcriptText);
}
Here is the JSFiddle on how it currently works:
http://jsfiddle.net/b94DG/
What you're doing now is creating a new div, newTranscript, which you create by appending a bunch of spans based on the old text. Then in your event handler you replace the old one with the new one. Instead of that, you could still copy the text from the old one, but then clear it and append the children on the old div, replacing line 36 with:
transcriptText.appendChild(newSpan);
To clear the old element, it might work to just set innerHTML to "", or if necessary you could remove all the children with removeChild as described at https://developer.mozilla.org/en-US/docs/Web/API/Node.removeChild
EDIT:
I modified your fiddle to reflect this:
http://jsfiddle.net/b94DG/1/
You can change the innerHTML of transcriptText instead of creating a new div.
var transcriptText = document.getElementById("transcriptText");
var divideTranscript = document.getElementById("divideTranscript");
divideTranscript.onclick = function() {
var sArr = transcriptText.innerHTML.split(" ");
var newInnerHTML = "";
for (var i = 0; i < sArr.length; i++) {
var item = sArr[i];
var newText = "<span class='highlight' id='word" + i + "'>" + item + " </span>";
newInnerHTML += newText;
}
transcriptText.innerHTML = newInnerHTML;
var mouseOverFunction = function () {
this.style.backgroundColor = 'yellow';
};
var mouseOutFunction = function () {
this.style.backgroundColor = '';
};
var highlight = document.getElementsByClassName("highlight");
for (i = 0; i < highlight.length; i++) {
highlight[i].onmouseover = mouseOverFunction;
highlight[i].onmouseout = mouseOutFunction;
}
};
Here's the fiddle: http://jsfiddle.net/khnGN/