I created different elements-paragraphs with createElement()/createTextNode() and added them to the body.
My problem is that i want to make those divs links or be able to add events such as onclick and obviously there is no HTML code to do that..just javascript generated objects.
my code atm:
for (i=0; i<10; i++){
var newDiv = document.createElement("div");
newDiv.className = "block";
var heading = document.createElement("h2");
var newContent = document.createTextNode(data[1][i]);
heading.className="title";
heading.appendChild(newContent);
newDiv.appendChild(heading);
var paragraph = document.createElement("p");
var newContent2 = document.createTextNode(data[2][i]);
paragraph.className="light";
paragraph.appendChild(newContent2);
newDiv.appendChild(paragraph);
var currentDiv = document.getElementById("div1");
document.body.insertBefore(newDiv, currentDiv);
}
You can add the event listener to the object you just created. The object does not have to be HTML. Read more about adding event listeners and see simple example:
var someDiv = document.createElement('div');
var txt = document.createTextNode('click me');
someDiv.append(txt);
document.body.append(someDiv);
var myFancyFunction = function() {
alert('you clicked me');
};
someDiv.addEventListener('click', myFancyFunction);
Update after your code you can add an event listener to those objects you create on the fly. You can also add different functions on the same event. In this case it's the same function for both elements/objects .. play with this: (I changed the data to "dummy data" as there was no data)
var myClick = function(event) {
alert(event.target.innerHTML);
};
for (i=0; i<10; i++){
var newDiv = document.createElement("div");
newDiv.className = "block";
var heading = document.createElement("h2");
var newContent = document.createTextNode('dummy data1 index: ' + i);
heading.className="title";
heading.appendChild(newContent);
newDiv.appendChild(heading);
var paragraph = document.createElement("p");
var newContent2 = document.createTextNode('dummy data2 index: ' + i);
paragraph.className="light";
paragraph.appendChild(newContent2);
newDiv.appendChild(paragraph);
var currentDiv = document.getElementById("div1");
document.body.insertBefore(newDiv, currentDiv);
heading.addEventListener('click', myClick);
paragraph.addEventListener('click', myClick);
}
You can simply call addEventListener on the JS-generated objects, even before they are inserted into the DOM, or are never inserted at all:
let div = document.createElement('div');
div.addEventListener('click', function(event) {
// do something
});
// This will trigger a call of the registered click callback,
// regardless of whether the div is in the DOM:
div.dispatchEvent(new Event('click', {
"bubbles": true,
"cancelable": false,
}));
// To add it to the DOM, simply add it the way you wish:
document.body.appendChild(div);
EventTarget.dispatchEvent allows you to trigger an event in a computational way (has equivalent effect to actually clicking the div)
Do take note of the browser compatibility of the event constructor in the example above.
Once an element is added to the dom, you can select it just like any other element.
// Create the element
var paragraph = document.createElement('p');
// Give it an `id`
paragraph.id = 'foo';
// Add the element to the `dom`
document.body.appendChild(paragraph);
// Add the listener
paragraph.addEventListener('click', function() {
this.innerHTML = 'It was clicked';
});
p {
height:20px;
padding:10px;
outline:1px solid #bada55;
}
In the example above, I added an id. If for some reason you need to re-select the element it may make it easier.
Related
This question already has answers here:
one document.createElement, append it twice, only shows once
(2 answers)
Closed 4 years ago.
I'm writing a function to create two cards -one is square and another round in shape to display on a button's click. When another button is pressed, few more styles gets added.
But the problem I'm running into is that the div squareMainID and roundMainID both of them have same number of divs within divs. When the div gets displayed on the DOM, only roundMainId's div tags and children shows up(see image). If you can see the dev tool, the black arrows next to the roundMainID is collapsable. Not the same for SqaureMainID. Even the styles that I'm trying to apply gets applied only to the roundMainID and not to the square. Why is this happening and how to fix?
code:
var pick= document.getElementById("pick");
var attachCardsDiv = document.createElement("div");
attachCardsDiv.className += "attach-cards-div"
var squareMainDiv = document.createElement("div");
squareMainDiv.className = "cardsPanel";
squareMainDiv.setAttribute("id", "squareMainID");
var roundMainDiv = document.createElement("div");
roundMainDiv.className = "cardsPanel";
roundMainDiv.setAttribute("id", "roundMainID");
var classADiv = document.createElement("div");
var classBDiv = document.createElement("div");
var apple = document.createElement("div");
var banana = document.createElement("div");
function attachTwoCardsOnDom(){
classBDiv.appendChild(banana);
classBDiv.appendChild(apple);
classADiv.appendChild(classBDiv)
squareMainDiv.appendChild(classADiv).addEventListener('click',
function(event){
console.log("clicked");
});
attachCardsDiv.appendChild(squareMainDiv);
document.body.appendChild(attachCardsDiv);
// ************************************************************
classBDiv.appendChild(banana);
classBDiv.appendChild(apple);
classADiv.appendChild(classBDiv)
roundMainDiv.appendChild(classADiv).addEventListener('click',
function(event){
console.log("clicked");
});
attachCardsDiv.appendChild(roundMainDiv);
document.body.appendChild(attachCardsDiv);
}
pick.addEventListener('click', function(event){
attachTwoCardsOnDom();
})
html:
<button id="pick">Press</button>
In:
var classADiv = document.createElement("div");
var classBDiv = document.createElement("div");
var apple = document.createElement("div");
var banana = document.createElement("div");
You create the divs just once and then in:
function attachTwoCardsOnDom(){
classBDiv.appendChild(banana);
classBDiv.appendChild(apple);
classADiv.appendChild(classBDiv)
you just move them around.
That is, you actually are adding to squareMainDiv, but later you are removing them from it when adding the divs to roundMainDiv.
Fix: You have to recreate the divs every time:
function attachTwoCardsOnDom(){
var classADiv = document.createElement("div"); // creating here
var classBDiv = document.createElement("div"); // creating here
var apple = document.createElement("div"); // creating here
var banana = document.createElement("div"); // creating here
classBDiv.appendChild(banana);
classBDiv.appendChild(apple);
classADiv.appendChild(classBDiv)
squareMainDiv.appendChild(classADiv).addEventListener('click',
function(event){
console.log("clicked");
});
attachCardsDiv.appendChild(squareMainDiv);
document.body.appendChild(attachCardsDiv);
// ************************************************************
var classADiv2 = document.createElement("div"); // creating here, different name
var classBDiv2 = document.createElement("div"); // creating here, different name
var apple2 = document.createElement("div"); // creating here, different name
var banana2 = document.createElement("div"); // creating here, different name
classBDiv2.appendChild(banana2); // notice classBDiv2 (2!)
classBDiv2.appendChild(apple2); // and on...
classADiv2.appendChild(classBDiv2)
roundMainDiv.appendChild(classADiv2).addEventListener('click',
function(event){
console.log("clicked");
});
attachCardsDiv.appendChild(roundMainDiv);
document.body.appendChild(attachCardsDiv);
}
Demo JSFiddle: https://jsfiddle.net/acdcjunior/s41ax3rb/3/
I want to add a link dynamically and attach "onclick" event on it. Here's a simplified version of what I have:
for (var i = 0; ....) {
var a1 = document.createElement("a");
a1.innerHTML = "My link123";
a1.addEventListener("click", function(event) {
myFunc(someArray[i].property1, event);
// alert("test123");
});
var p1 = document.createElement("p");
var sp1 = document.createElement("span");
//..........
divContainer.innerHTML += a1.outerHTML + p1.outerHTML + sp1.outerHTML;
}
But it doesn't trigger the "click" event when I click on it.
update:
after it's created and I click on it, I get:
myFunc(someArray[i].property1, event); -- Cannot read property 'property1' of undefined
I guess it's something related to how clojures are evaluated.
update2
I've tried this:
a1.addEventListener("click", function(event) {
(function(i2){
myFunc(i2, event);
})(myArray[i].property1);
});
But it said at runtime when I clicked on it "property1 isn't defined"; How can I fix that?
divContainer.innerHTML += a1.outerHTML + p1.outerHTML + sp1.outerHTML;
You are serialising the DOM nodes (both the new ones and the ones already in divContainer) to HTML, which doesn't include the event listeners, and then creating new DOM nodes from the HTML.
Use appendChild and friends instead.
divContainer.appendChild(a1);
divContainer.appendChild(p1);
divContainer.appendChild(sp1);
I'm a little new to Web Development so I was hoping someone could answer this for me.
I'm building a prototype for a "Web Messenger" similar to Facebook messenger. I have a sidebar that I populate with a UL of anchor tags when the window loads and it looks like this. Here is the code for it
var toAdd = document.createDocumentFragment();
var newUL = document.createElement('ul');
newUL.id = 'menu-content';
newUL.className = 'menu-content collapse out';
for(var i = 0; i < 5; i++){
var newLI = document.createElement('li');
var newA = document.createElement('a');
newA.id = 'chat' + i;
newA.setAttribute('href', "#");
newA.innerHTML = "Chat" + (i + 1);
newLI.appendChild(newA);
newUL.appendChild(newLI);
}
toAdd.appendChild(newUL)
document.getElementById("menu-list").appendChild(toAdd);
I also have a Div at the top of the page which will display some details about the current chat, but for the time being will simply display the name of the chat, same as on the anchor tags.
Now based on another StackOverflow post the correct way to call a JS function from an anchor tag is
var c0 = document.getElementById("chat0");
//Set code to run when the link is clicked
// by assigning a function to "onclick"
c0.onclick = function(id) {
//Change Title Name here
//Do other stuff in the future
return false;
}
However I could have 20+ chats on the sidebar at any one time, so this seems like a lot of repetitive code to write.
Is there a better way to do this?
Give your chats a general class instead example chat then attach the click event to all the chat's in the same time using .getElementsByClassName().
So you could add className just after newA.id :
newA.id = 'chat' + i;
newA.className = 'chat';
Then attach the click event :
var chats = document.getElementsByClassName('chat');
for (var i=0; i < chats.length; i++) {
chats[i].addEventListener('click', chatClick, false);
}
function chatClick(){
//chat is clicked
//The 'this' object here refer to clicked element
}
You could use .addEventListener() instead of onclick.
NOTE : You can attach the click event directly after node creation :
for(var i = 0; i < 5; i++){
var newLI = document.createElement('li');
var newA = document.createElement('a');
newA.id = 'chat' + i;
newA.setAttribute('href', "#");
newA.innerHTML = "Chat" + (i + 1);
newA.addEventListener('click', chatClick, false); //Attach click event HERE
newLI.appendChild(newA);
newUL.appendChild(newLI);
}
Hope this help.
Yap sure. You can give them all a class and after load just use a simple jQuery code to bind onclick for all of them:
$('a.className').click(function() {
// Your code here
});
Now if the a tags are added after execution of the code you just simply need to call this again or bind to those elements manually.
The code below makes a Div for every object it finds in an array. It then adds a header, a paragraph, an image, and an anchor.
The div's actually look like rectangles on top of one another. What I would like to do is add an onclick attribute to the divs based on the keys within my objects ( coffeShops[i].menu). When I do so though, clicking just doesn't do anything and i get this error message in console
"Uncaught TypeError: Cannot read property 'menu' of undefined"
This only happens when I try window.open with the object key coffeShops[i].menu. If I swap that out with "http://www.google.com" it works just fine. Also, the links from that variable show up in the console just fine. So I know it's getting the data from the object just fine. But for some reason it doesn't want to open from the div.
FYI I'm extremely new to this so apologies if the explanation doesn't make sense.
var containerDiv = document.getElementById("container");
console.log(containerDiv);
for (var i = 0; i < coffeeShops.length; i++){
var launchMenu = function(){
window.open(coffeeShops[i].menu);
}
console.log(coffeeShops[i].menu);
var coffeeShopDiv = document.createElement("div");
coffeeShopDiv.className = "coffeeShop";
coffeeShopDiv.onclick = launchMenu;
containerDiv.appendChild(coffeeShopDiv);
var coffeeShopImage = document.createElement("img");
coffeeShopImage.src = coffeeShops[i].image;
coffeeShopImage.className = "coffeeImage";
coffeeShopDiv.appendChild(coffeeShopImage);
var coffeeShopHeader = document.createElement("h1");
coffeeShopHeader.className = "coffeeHeader"
coffeeShopHeader.innerHTML = coffeeShops[i].name;
coffeeShopDiv.appendChild(coffeeShopHeader);
var coffeeShopPar = document.createElement("p");
coffeeShopPar.className = "coffeeDescription"
coffeeShopPar.innerHTML = coffeeShops[i].description;
coffeeShopDiv.appendChild(coffeeShopPar);
var coffeeMenu = document.createElement("a");
coffeeMenu.href = coffeeShops[i].menu;
coffeeMenu.innerHTML = "MENU"
coffeeShopDiv.appendChild(coffeeMenu);
};
EDITED: in light of comment
It looks like you need to separate the function which opens the new window from the code which generates page items. By slightly restructuring your code this can be achieved by using the element.addEventListener() method.
/* place the 'launchMenu' outside of
the for-loop so it can be accessed
by each of the target elements */
function launchMenu(event){
/* get the class attribte of
the clicked element */
var clickedClass = event.target.className;
var targetElement,
link;
/* is the clicked element the containing div? */
if (clickClass !== 'coffeeShop') {
/* nope */
targetElement = event.target.parentNode;
} else {
/* yep */
targetElement = event.target;
}
/* get 'data-url' of target */
link = targetElement.getAttribute('data-url');
/* open the new window */
window.open(link);
}
/* elsewhere: create elements as before */
for (var i = 0; i < coffeeShops.length; i++){
var coffeeShopDiv = document.createElement("div");
coffeeShopDiv.className = "coffeeShop";
/* add 'data-' attribute to target div */
coffeeShopDiv.setAttribute('data-url', coffeeShops[i].menu);
containerDiv.appendChild(coffeeShopDiv);
var coffeeShopImage = document.createElement("img");
coffeeShopImage.src = coffeeShops[i].image;
coffeeShopImage.className = "coffeeImage";
coffeeShopDiv.appendChild(coffeeShopImage);
var coffeeShopHeader = document.createElement("h1");
coffeeShopHeader.className = "coffeeHeader"
coffeeShopHeader.innerHTML = coffeeShops[i].name;
coffeeShopDiv.appendChild(coffeeShopHeader);
var coffeeShopPar = document.createElement("p");
coffeeShopPar.className = "coffeeDescription"
coffeeShopPar.innerHTML = coffeeShops[i].description;
coffeeShopDiv.appendChild(coffeeShopPar);
var coffeeMenu = document.createElement("a");
coffeeMenu.className = 'coffeeMenu';
coffeeMenu.innerHTML = "MENU"
coffeeShopDiv.appendChild(coffeeMenu);
/* attach an eventListener to each
created '.coffeeShopDiv' element */
coffeeMenu.addEventListener(
'click', launchMenu, false
);
};
The target element (coffeeShopDiv) now contains a url-reference in its 'data-url' attriubte and has an event listener assigned.
When the target element, or any of her child elements, are clicked the launchMenu() function will be invoked. This function checks which element was clicked by comparing the className attribute to the class name of 'coffeeShopDiv' - such that if the class name of the clicked element is not 'coffeeShop' the targetElement variable is assigned to the clicked elements parent Node (that is, 'coffeShopDiv').
The 'data-url' reference is obtained and used in window.open().
Also see:
Using data-* attributes
Event.target
Quriksmode: Introduction to Events
This StackOverflow answer about using
window.open()
I'm trying to add a div dynamically using an link and some javascript. I've set up a jsfiddle http://jsfiddle.net/W4Sup/1654/.
Here's the html
Add Div
Here's the css
div {
border: 1px dotted red;
padding: 10px;
}
And here is the javascript:
var iDiv = document.createElement('div');
iDiv.id = 'block';
iDiv.className = 'block';
document.getElementsByTagName('body')[0].appendChild(iDiv);
iDiv.innerHTML = "I'm the first div";
// Now create and append to iDiv
var innerDiv = document.createElement('div');
innerDiv.className = 'block-2';
// The variable iDiv is still good... Just append to it.
iDiv.appendChild(innerDiv);
innerDiv.innerHTML = "I'm the inner div";
function addDiv() {
var newDiv = document.createElement('div');
newDiv.className = 'block-3';
iDiv.appendChild(newDiv);
newDiv.innerHTML = "Another inner div";
}
Can someone explain what I've got wrong please
check this updated fiddle, basically addDiv was not visible to the click event handler since it was not in a global scope (since it is inside domready event handler)
<script>
var addDiv;
</script>
addDiv = function addDiv() {
var newDiv = document.createElement('div');
newDiv.className = 'block-3';
iDiv.appendChild(newDiv);
newDiv.innerHTML = "Another inner div";
return false;
}
Well first of all you dont need the href, only the onclick will matter, thus making it usable on any html tag, not only <a>'s
Add Div
the onclick doesnt take a ; at the end of your function, it's an assignation, you'not calling it
I prefer the assign-in-the-JS approach. Set your event listener in your JS by grabbing that link and putting addDiv in its click event handler.
Demo using your code
Basic changes -
JS:
document.getElementById("joe").addEventListener("click", addDiv, false);
...
function addDiv( event ) {
event.preventDefault();
...
}
HTML:
Add Div
You don't have to use an ID, it was just the most convenient way in this example. I recommend it though if that's an option for you.