Buttons with JavaScript - javascript

I'm new in JavaScript, html and CSS and I'm trying to make a simple web page about Formula 1. In this page I was trying to make a small menu with 10 buttons, each one of them would lead you to a formula one team web page. I was doing using only html the first time but then realize I probably could do it using a loop in JavaScript and save a lot of lines and time, I have some thoughts about how to do it but I don't know how to execute the idea properly.
First I would create a list of 10 objects, each object with an image link and the web page of one of the 10 teams to use in the buttons:
var teams = [
{name: mercedes, logo: teammercedes.icon, web: mercedes.com
{name: ferrari, logo: ferrari.icon, web: ferrari.com}
Then would create a "for" (I'm guessing here)
for(i = 0; i < 11; i++){
Now, I have no idea how to put this in JS but I here is what I want:
mercedes is i = 0, so the JS create all the button tag structure using
the Mercedes logo I saved in the list above to decorate de button.
then it goes to i = 1, which would be Ferrari, and the JS create again
all the button tag structure using the Ferrari logo saved in the list
}
I think by this method I would need to write the button structure once in the JS and, somehow, push the information inside of it 10 times, using 10 different index defined on a list

You're on the right lines. Create an array of companies, and then iterate over the names to build some HTML, and then attach it to a menu. Use some CSS to style the buttons.
This example uses some modern JS techniques that aren't meant to scare you off, I promise. There's full documentation at the end of the answer, but I'll try and explain things along the way.
// The array of companies that you wanted
const companies = ['Mercedes', 'Renault', 'Saab', 'Fiat'];
// We cache the menu element using `querySelector`
const menu = document.querySelector('#menu');
// We assign a listener to the menu so when it is clicked
// we can redirect to a new page based on the the button id
menu.addEventListener('click', handleClick, false);
// For the buttons we can `map` over the array and create
// a new array of HTML that we `join` into a string at the end.
// I've used a dummy image here, but you can substitute in your
// own images for the img source
const buttons = companies.map(company => {
const src = `https://dummyimage.com/100x30/b5d19d/000&text=${company}`;
// Return some HTML that uses a class, a data attribute for
// the company name, and the src image for the "button", and
return `<img class="company" data-id="${company.toLowerCase()}" src="${src}" />`;
// then `join` the new array up into one string
}).join('');
// Add the button HTML to the menu element
menu.innerHTML = buttons;
// When the listener is called
function handleClick(e) {
// Grab the id value from the data attribute, and
// the className from the element that was clicked
// using destructuring assignment
const { dataset: { id }, className } = e.target;
// Check to see if the element that was click was a button
if (className === 'company') {
// And then navigate to your new page
console.log(`http://example.com/${id}.html`);
// window.location.href = `http://example.com/${id}.html`;
}
}
.company { border: 1px solid white; border-radius: 10px; display: block; margin: 1em; cursor: pointer; }
.company:hover { border: 1px solid black; }
<div id="menu"></div>
Additional documentation
querySelector
map
addEventListener
Template/string literals
Destructuring assignment
join
Data attributes

You did not specify where to insert elements(DOM string) generated by JavaScript. So, the code below inserts elements into body tag as an example.
var teams = [
{name: "mercedes", logo: "teammercedes.icon", web: "mercedes.com"},
{name: "ferrari", logo: "ferrari.icon", web: "ferrari.com"}
];
let body = document.querySelector('body');
for (let i = 0; i < teams.length; i++) {
let link = teams[i].web;
let logo = teams[i].logo;
let name = teams[i].name;
body.insertAdjacentHTML('afterbegin', `<img src="${logo}" alt="${name}" />${name}`);
}
Although you think using JavaScript is an good way to list elements, I disagree. The JavaScript code runs in the browser. That means, the list of buttons will not be recognized until JavaScript runs.
Therefore, I believe it is better to return the list of buttons included in a HTML document.

Related

How do I create a new HTML element from JavaScript? [duplicate]

I want to dynamically create some HTML elements (3 html element) and then return this html code as a string in a variable. I don't want to write the HTML code in the following function to some div, but, I want to return it in a var.
function createMyElements(id1,id2,id3){
//create anchor with id1
//create div with id 2
//create xyz with id3
//now return the html code of above created just now
}
How can I do this?
[Edit 2021/10] This answer is now > 10 years old. Here is a snippet containing several ways to create and/or inject elements. The answer for the question asked (create some element(s) and retrieve their html code) can be found # the bottom of the snippet.
// The classic createElement
// -------------------------
// create a paragraph element using document.createElement
const elem = document.createElement(`p`);
elem.id = `myBrandnewDiv1`;
// put in some text
elem.appendChild(document.createTextNode(`My brand new div #1`));
// append some html (for demo, preferrably don't use innerHTML)
elem.innerHTML += ` => created using
<code>document.createElement</code>`;
// append a new paragraph within #myBrandNewDiv1
const nested = elem.appendChild(document.createElement(`p`));
nested.classList.add(`nested`);
// add some text to that
nested.textContent = `I am nested!`;
// the elements are still in memory, now add the
// whole enchillada to the document
document.body.appendChild(elem);
// insertAdjacentHTML
// ------------------
// nest an element within the nested div
nested.insertAdjacentHTML(`afterbegin`,
`<div id="nestedWithin#nested">
This text will appear <i>above</i> the text of
my parent, that being div#nested.
Someone had the nerve to insert me using
<code>insertAdjacentHTML</code>
</div>`);
// Object.assign
// -------------
// Use Object.assign to create an element and
// assign properties/html to it in one go
const newElem = Object.assign(
document.createElement(`div`),
{ id: `myBrandnewDiv2`,
innerHTML: `div#myBrandnewDiv2 signing in.
I was <i>assigned</i> using <code>Object.assign</code>…`});
document.body.appendChild(newElem);
// insertAdjacentElement combined with Object.assign
// -------------------------------------------------
// use the above technique combined with insertAdjacentElement
newElem.insertAdjacentElement(
`beforeend`,
Object.assign(document.createElement(`span`),
{ id: `myBrandnewnested2_nested`,
innerHTML: `<br>Me too! And appended I was
with <code>insertAdjacentElement</code>` })
);
// createDocumentFragment
// ----------------------
// Use a document fragment to create/inject html
const fragment = document.createDocumentFragment();
const mdnLnk = `https://developer.mozilla.org/en-US/` +
`docs/Web/API/Document/createDocumentFragment`;
fragment.appendChild(
Object.assign(
document.createElement(`p`),
{innerHTML: `Regards from <code>createDocumentFragment</code>
(see MDN)`})
);
document.querySelector(`#myBrandnewDiv2`).appendChild(fragment);
// Create, but don't inject
// ------------------------
const virtual = Object.assign(
document.createElement(`p`),
{ innerHTML: `
id1
<div id="id2">Hi!</div>
<p id="id3">Hi 2!</p>`,
classList: [`xyz`], } );
const prepareHtml4Reporting = html =>
html.replace(/</g, `<`)
.replace(/\n\s+/g, `\n`)
.replace(/\n\n/g, `\n`);
document.body.insertAdjacentHTML(
`beforeend`,
`<h3>html only</h3><pre>${
prepareHtml4Reporting(virtual.innerHTML)}</pre>`);
body {
font: normal 12px/15px verdana, arial, sans-serif;
margin: 2rem;
}
code {
background-color: #eee;
}
.nested {
margin-left: 0.7rem;
max-width: 450px;
padding: 5px;
border: 1px solid #ccc;
}
I have used some of these methods in this library (see /src/DOM.js), with a mechanism for sanitizing html before it is injecting.
Html:
<div id="main"></div>
JavaScript:
var tree = document.createDocumentFragment();
var link = document.createElement("a");
link.setAttribute("id", "id1");
link.setAttribute("href", "http://site.com");
link.appendChild(document.createTextNode("linkText"));
var div = document.createElement("div");
div.setAttribute("id", "id2");
div.appendChild(document.createTextNode("divText"));
tree.appendChild(link);
tree.appendChild(div);
document.getElementById("main").appendChild(tree);
The main reason to use a documentFragment in stead of just adding the elements directly is speed of execution.
At this size it doesn't matter, but when you start adding hundreds of elements, you will appreciate doing it in-memory first :-)
With documentFragment you can construct a whole tree of DOM-elements in-memory and will not afffect the browser DOM untill the last moment.
Otherwise it forces the browser to update for every element, which sometimes can be a real pain to watch.
If you're doing this repeatedly (dynamically creating HTML), you might want to use a more general approach.
If you want to create three unrelated elements, you can do:
var anchor = elem("a", {"id":"id1"});
var div = elem("div", {"id":"id2"});
var xyz = elem("div", {"id":"id3"});
Now, you have three elements. If you want to get the HTML of these (as string), simply do:
var html = anchor.outerHTML + div.outerHTML + xyz.outerHTML;
If you want to have these three in an element (say, div), do:
var div = elem("div", null, [
elem("a", {"id":"id1"}),
elem("div", {"id":"id2"}),
elem("div", {"id":"id3"}),
]);
You can get the HTML with div.outerHTML, or you can just append it anywhere you want.
To know more about elem(), visit element.js (GitHub).
I'm adding this answer not for the 8 year old question, but for the future visitors. Hope, it helps.
You can construct the html as a string in one variable like
var html = "";
html += "<a id='" + id1 +"'>link</a>";
html += "<div id='" + id1 +"'>div</div>";
// ... and so on
then you return the variable html
return html;
The better way would be to Import ElementsJS and just reference each element in it.
var root = document.getElementById("root");
var elementdiv = create_element('div',{'class':'divcss'}, root, null);
create_element('h1',{'class':'hellocss'}, elementdiv, "Hello World");
.hellocss {
color : red;
}
.divcss {
background-color : blue;
height: 100px;
position: absolute;
}
<script src="https://elementsjs.blob.core.windows.net/public/create-elements.js"></script>
<body id="root"></body>
For More Details Refer to https://github.com/divyamshu/Elements-JS
Well Documented with Example.
Here's simple illustration for converting the html-page (static), to javascript based html-page (dynamic).
Let us say, you have html-page as "index.html" (calling index_static.html here).
index_static.html
<!DOCTYPE HTML>
<html>
<head>
<title>Test</title>
</head>
<body>
<h1> Hello !!! </h1>
</body>
</html>
You can open this file in the browser, to see the desired output.
Now, lets create a javascript equivalent to this.
Use online-tool, to generate the javascript source (by pasting the above html file source to it). Therefore, it follows as:
dynamic.js
document.write("<!DOCTYPE HTML>");
document.write("<html>");
document.write(" <head>");
document.write(" <title>Test<\/title>");
document.write(" <\/head>");
document.write(" <body>");
document.write(" <h1> Hello !!! <\/h1>");
document.write(" <\/body>");
document.write("<\/html>");
And now, your dynamic version of the static_index.html will be as below:
index_dynamic.html
<script language="JavaScript" src="dynamic.js"></script>
Open the index_dynamic.html on the browser to validate the web-page (dynamic though, down-the-line).
more info

How would I add the information entered in a form onto the page? [duplicate]

I want to dynamically create some HTML elements (3 html element) and then return this html code as a string in a variable. I don't want to write the HTML code in the following function to some div, but, I want to return it in a var.
function createMyElements(id1,id2,id3){
//create anchor with id1
//create div with id 2
//create xyz with id3
//now return the html code of above created just now
}
How can I do this?
[Edit 2021/10] This answer is now > 10 years old. Here is a snippet containing several ways to create and/or inject elements. The answer for the question asked (create some element(s) and retrieve their html code) can be found # the bottom of the snippet.
// The classic createElement
// -------------------------
// create a paragraph element using document.createElement
const elem = document.createElement(`p`);
elem.id = `myBrandnewDiv1`;
// put in some text
elem.appendChild(document.createTextNode(`My brand new div #1`));
// append some html (for demo, preferrably don't use innerHTML)
elem.innerHTML += ` => created using
<code>document.createElement</code>`;
// append a new paragraph within #myBrandNewDiv1
const nested = elem.appendChild(document.createElement(`p`));
nested.classList.add(`nested`);
// add some text to that
nested.textContent = `I am nested!`;
// the elements are still in memory, now add the
// whole enchillada to the document
document.body.appendChild(elem);
// insertAdjacentHTML
// ------------------
// nest an element within the nested div
nested.insertAdjacentHTML(`afterbegin`,
`<div id="nestedWithin#nested">
This text will appear <i>above</i> the text of
my parent, that being div#nested.
Someone had the nerve to insert me using
<code>insertAdjacentHTML</code>
</div>`);
// Object.assign
// -------------
// Use Object.assign to create an element and
// assign properties/html to it in one go
const newElem = Object.assign(
document.createElement(`div`),
{ id: `myBrandnewDiv2`,
innerHTML: `div#myBrandnewDiv2 signing in.
I was <i>assigned</i> using <code>Object.assign</code>…`});
document.body.appendChild(newElem);
// insertAdjacentElement combined with Object.assign
// -------------------------------------------------
// use the above technique combined with insertAdjacentElement
newElem.insertAdjacentElement(
`beforeend`,
Object.assign(document.createElement(`span`),
{ id: `myBrandnewnested2_nested`,
innerHTML: `<br>Me too! And appended I was
with <code>insertAdjacentElement</code>` })
);
// createDocumentFragment
// ----------------------
// Use a document fragment to create/inject html
const fragment = document.createDocumentFragment();
const mdnLnk = `https://developer.mozilla.org/en-US/` +
`docs/Web/API/Document/createDocumentFragment`;
fragment.appendChild(
Object.assign(
document.createElement(`p`),
{innerHTML: `Regards from <code>createDocumentFragment</code>
(see MDN)`})
);
document.querySelector(`#myBrandnewDiv2`).appendChild(fragment);
// Create, but don't inject
// ------------------------
const virtual = Object.assign(
document.createElement(`p`),
{ innerHTML: `
id1
<div id="id2">Hi!</div>
<p id="id3">Hi 2!</p>`,
classList: [`xyz`], } );
const prepareHtml4Reporting = html =>
html.replace(/</g, `<`)
.replace(/\n\s+/g, `\n`)
.replace(/\n\n/g, `\n`);
document.body.insertAdjacentHTML(
`beforeend`,
`<h3>html only</h3><pre>${
prepareHtml4Reporting(virtual.innerHTML)}</pre>`);
body {
font: normal 12px/15px verdana, arial, sans-serif;
margin: 2rem;
}
code {
background-color: #eee;
}
.nested {
margin-left: 0.7rem;
max-width: 450px;
padding: 5px;
border: 1px solid #ccc;
}
I have used some of these methods in this library (see /src/DOM.js), with a mechanism for sanitizing html before it is injecting.
Html:
<div id="main"></div>
JavaScript:
var tree = document.createDocumentFragment();
var link = document.createElement("a");
link.setAttribute("id", "id1");
link.setAttribute("href", "http://site.com");
link.appendChild(document.createTextNode("linkText"));
var div = document.createElement("div");
div.setAttribute("id", "id2");
div.appendChild(document.createTextNode("divText"));
tree.appendChild(link);
tree.appendChild(div);
document.getElementById("main").appendChild(tree);
The main reason to use a documentFragment in stead of just adding the elements directly is speed of execution.
At this size it doesn't matter, but when you start adding hundreds of elements, you will appreciate doing it in-memory first :-)
With documentFragment you can construct a whole tree of DOM-elements in-memory and will not afffect the browser DOM untill the last moment.
Otherwise it forces the browser to update for every element, which sometimes can be a real pain to watch.
If you're doing this repeatedly (dynamically creating HTML), you might want to use a more general approach.
If you want to create three unrelated elements, you can do:
var anchor = elem("a", {"id":"id1"});
var div = elem("div", {"id":"id2"});
var xyz = elem("div", {"id":"id3"});
Now, you have three elements. If you want to get the HTML of these (as string), simply do:
var html = anchor.outerHTML + div.outerHTML + xyz.outerHTML;
If you want to have these three in an element (say, div), do:
var div = elem("div", null, [
elem("a", {"id":"id1"}),
elem("div", {"id":"id2"}),
elem("div", {"id":"id3"}),
]);
You can get the HTML with div.outerHTML, or you can just append it anywhere you want.
To know more about elem(), visit element.js (GitHub).
I'm adding this answer not for the 8 year old question, but for the future visitors. Hope, it helps.
You can construct the html as a string in one variable like
var html = "";
html += "<a id='" + id1 +"'>link</a>";
html += "<div id='" + id1 +"'>div</div>";
// ... and so on
then you return the variable html
return html;
The better way would be to Import ElementsJS and just reference each element in it.
var root = document.getElementById("root");
var elementdiv = create_element('div',{'class':'divcss'}, root, null);
create_element('h1',{'class':'hellocss'}, elementdiv, "Hello World");
.hellocss {
color : red;
}
.divcss {
background-color : blue;
height: 100px;
position: absolute;
}
<script src="https://elementsjs.blob.core.windows.net/public/create-elements.js"></script>
<body id="root"></body>
For More Details Refer to https://github.com/divyamshu/Elements-JS
Well Documented with Example.
Here's simple illustration for converting the html-page (static), to javascript based html-page (dynamic).
Let us say, you have html-page as "index.html" (calling index_static.html here).
index_static.html
<!DOCTYPE HTML>
<html>
<head>
<title>Test</title>
</head>
<body>
<h1> Hello !!! </h1>
</body>
</html>
You can open this file in the browser, to see the desired output.
Now, lets create a javascript equivalent to this.
Use online-tool, to generate the javascript source (by pasting the above html file source to it). Therefore, it follows as:
dynamic.js
document.write("<!DOCTYPE HTML>");
document.write("<html>");
document.write(" <head>");
document.write(" <title>Test<\/title>");
document.write(" <\/head>");
document.write(" <body>");
document.write(" <h1> Hello !!! <\/h1>");
document.write(" <\/body>");
document.write("<\/html>");
And now, your dynamic version of the static_index.html will be as below:
index_dynamic.html
<script language="JavaScript" src="dynamic.js"></script>
Open the index_dynamic.html on the browser to validate the web-page (dynamic though, down-the-line).
more info

how to prevent newly created elements by javascript to disappear when is refreshed?

Actually i am making list ... first i get the user info and store it into mysql database . when user clicks 'add' button a new element of list appears in the bottom of list as the part of list which is already coded in html. Now the problem is when i refresh the page the the new created element of list disappears ? Any suggestions?
<html>
<ul id="list" class="list-group" style="margin-top:20vh ;opacity:0.3;">
<span class="badge badge-primary badge-pill">+</span>Add shop
<a href="#" onclick="location.href='action.php';" class="list-group-item list-group-item-action" id="bg" >Emporium</a>
</ul>
</html>
<script>
function newuser() {
var ul = document.getElementById("list");
var li = document.createElement("a");
li.appendChild(document.createTextNode("<?php echo $row3['shopname'] ?>"));
li.setAttribute("id", "bg"); // added line
li.setAttribute("class", "list-group-item list-group-item-action");
li.setAttribute("href", "#");
// li.insertBefore(li, ul.children[0]);
ul.appendChild(li);
}
</script>
When you will reload the page, JS files will reload and execute again, so if you want some action based on some event and store that action event after reload, use cookie, local storage, or session storage and store some flag, based on that trigger your function on page load.
The page is rendered again every time you refresh the page. The JavaScript block will be executed again too. So nothing you create will 'inject' into your file with the code or stay there forever.
However, there are solutions that can help you achieve that (or simulate it). For example, localStorage or sessionStorage. Personally, I'd use localStorage for that purpose (unless there's some sensitive data included, e.g. bank account info and similar stuff). On page load where you'd have your form shown, you immediately invoke a method for getting an existing data object inside localStorage, e.g. localStorage.getItem(data). The localStorage and sessionStorage properties allow to save key/value pairs in a web browser. The localStorage object stores data with no expiration date. The data will not be deleted when the browser is closed, and will be available the next day, week, or year.
For example, if you want to keep the elements in a todo list, you might want to do something like this:
const addButton = document.querySelector("#addToDo");
const delBtn = document.querySelector("#delToDo");
addButton.addEventListener("click", addTask, false);
var tasksID = 0;
function saveTask(taskID, taskInfo) {
// Get tasks from local storage
let tasks = localStorage.getItem("todo-tasks");
if (!tasks) {
tasks = {};
} else {
tasks = JSON.parse(tasks);
tasks[taskID] = taskInfo;
}
// Save the result back
let infobj = JSON.stringify(tasks);
localStorage.setItem("todo-tasks", infobj);
}
function drawSavedTasks() {
let tasks = localStorage.getItem("todo-tasks");
if (tasks) {
tasks = JSON.parse(tasks);
Object.keys(tasks).forEach(k => {
addTask(null, tasks[k]);
});
}
}
drawSavedTasks();
function addTask(e, textToDo = undefined) {
if (!textToDo) {
textToDo = document.querySelector("#toDo").value;
}
var list = document.querySelector(".list");
var divToDo = document.createElement("div");
var p = document.createElement("p");
var delButton = document.createElement("button");
divToDo.setAttribute("id", "todo" + tasksID);
divToDo.setAttribute("class", "toDo");
delButton.classList.add("delToDo");
delButton.textContent = "Delete";
p.textContent = textToDo;
delButton.onclick = function() {
divToDo.parentNode.removeChild(divToDo);
}
divToDo.appendChild(p);
divToDo.appendChild(delButton);
list.appendChild(divToDo);
saveTask(tasksID, textToDo);
++tasksID;
}
.toDo {
width: 200px;
height: 80px;
border: 1px solid black;
margin: 5px;
padding: 5px;
text-align: center;
background-color: yellow;
}
<div class="form">
<input type="text" id="toDo" placeholder="To do...">
<button id="addToDo">Add</button>
</div>
<div class="list">
</div>
Note: The jsfiddle is not broken! Since JSFiddle loads the code under an iframe, you must select it on your developer console before running the code for the localStorage to work, or you might test it locally. If the HTML can not be seen, press the Full-page button. (Info here).
Note the functions saveTask and drawSavedTasks. drawSavedTasks is called first so anything you saved do be redrawn. Also, I don't save the entire previously created object, but only some relevant info about it, so I can re-create it.
Another solution would be if you'd use a database and/or a framework. Here, in the same way as with localStorage, you can save some metadata about the objects and redraw them on reload easily. For example, angularjs has a directive called ng-repeat where for every item in an array, a new element will be created when the page will be rendered. This can also be done with react or even laravel if you use php.
#foreach($itemas $itemsList)
<div>
Some data
</div>
#endforeach
Hope this helped you.
Cheers!

Is this event listener reaching the top most element?

I am developing a page that will create many <div>s and appending them to a container <div>. I need to know which one of them is being clicked on. At first, I figured putting an eventListener on each one of them would be fine. However, I just read an article about using Smart Event Handlers here: Best Practices for Speeding Up Your Web Site. And it talks about using only 1 eventListener and figuring out which one of the elements the event originates from.
EDIT
I removed the previous example, here is a small example that is much closer to my target functionality and illustrates why it would be preferable to have one listener that dispatches what was clicked on. The main thing is that the <div> is what knows which index in an array needs to be grabbed for data. However, the data gets presented in <div>s that are inside the <div> that knows the array index and the event doesn't hook with him for some reason.
When you run it, you see that the log only lists the contact whenever the green "middle" <div> gets clicked but not the red "information" <div>s. How can I get the red information <div>s to trigger the listener as well without adding a zillion listeners?
JSFiddle
<!DOCTYPE html>
<html>
<head>
<title>Bubbling</title>
<meta charset="UTF-8">
<style>
div{
margin: 10px;
padding: 10px;
width: 200px;
}
#big{
background: #ccffcc;
}
.contactDiv{
background: #99ff99;
}
.nameDiv, .phoneDiv{
background: #ff9999;
}
#log{
background: #ccccff;
}
</style>
</head>
<body>
<div id="log">I log stuff</div>
<button id="adder">Add Some Div</button>
<!--Highest div that encloses multiple other div-->
<div id="big"></div>
<script>
var log = document.getElementById("log"),
adderButton = document.getElementById("adder"),
bigDiv = document.getElementById("big"),
numDivsToMake = 100,
i, contactDiv, nameDiv, phoneDiv,
contacts = [];
for (i = 0; i < numDivsToMake; i++) {
contacts.push({
name: "Bob-" + i,
phone: "555-1234"
});
}
// Make more divs whenever we click the super button
adderButton.addEventListener("click", function() {
// Don't make more
adderButton.setAttribute("disabled");
// Make the divs with data
for (i = 0; i < numDivsToMake; i++) {
// Make name and number divs
contactDiv = document.createElement("div");
nameDiv = document.createElement("div");
phoneDiv = document.createElement("div");
// Add classes
contactDiv.className = "contactDiv";
nameDiv.className = "nameDiv";
phoneDiv.className = "phoneDiv";
// Set their values
nameDiv.innerHTML = contacts[i].name;
phoneDiv.innerHTML = contacts[i].phone;
// Set the container to know how to get back to the data in the array
contactDiv.setAttribute("data-contactId", i);
// Add them to the dom
bigDiv.appendChild(contactDiv);
contactDiv.appendChild(nameDiv);
contactDiv.appendChild(phoneDiv);
}
});
// Make smart handler
bigDiv.addEventListener("click", function(e) {
// Get whether the element has the attribute we want
var att = e.target.getAttribute("data-contactId");
// Say if it does or not
if (att) {
log.innerHTML = "You clicked: " +
contacts[att].name + " " +
contacts[att].phone;
}
else {
console.log("No attribute");
}
});
</script>
</body>
</html>
I think I understand what you're doing. The event delegation you've set up in the fiddle seems to work well. The data attribute you want to select could easily be selected inside your click handler by querying the DOM. Instead of looking at the source of the click if you know you always want the data, just do another document.getElementById to retrieve your data. I think you're trying to collapse two steps into one in a way that won't work with your design.

Dynamically creating HTML elements using Javascript?

I want to dynamically create some HTML elements (3 html element) and then return this html code as a string in a variable. I don't want to write the HTML code in the following function to some div, but, I want to return it in a var.
function createMyElements(id1,id2,id3){
//create anchor with id1
//create div with id 2
//create xyz with id3
//now return the html code of above created just now
}
How can I do this?
[Edit 2021/10] This answer is now > 10 years old. Here is a snippet containing several ways to create and/or inject elements. The answer for the question asked (create some element(s) and retrieve their html code) can be found # the bottom of the snippet.
// The classic createElement
// -------------------------
// create a paragraph element using document.createElement
const elem = document.createElement(`p`);
elem.id = `myBrandnewDiv1`;
// put in some text
elem.appendChild(document.createTextNode(`My brand new div #1`));
// append some html (for demo, preferrably don't use innerHTML)
elem.innerHTML += ` => created using
<code>document.createElement</code>`;
// append a new paragraph within #myBrandNewDiv1
const nested = elem.appendChild(document.createElement(`p`));
nested.classList.add(`nested`);
// add some text to that
nested.textContent = `I am nested!`;
// the elements are still in memory, now add the
// whole enchillada to the document
document.body.appendChild(elem);
// insertAdjacentHTML
// ------------------
// nest an element within the nested div
nested.insertAdjacentHTML(`afterbegin`,
`<div id="nestedWithin#nested">
This text will appear <i>above</i> the text of
my parent, that being div#nested.
Someone had the nerve to insert me using
<code>insertAdjacentHTML</code>
</div>`);
// Object.assign
// -------------
// Use Object.assign to create an element and
// assign properties/html to it in one go
const newElem = Object.assign(
document.createElement(`div`),
{ id: `myBrandnewDiv2`,
innerHTML: `div#myBrandnewDiv2 signing in.
I was <i>assigned</i> using <code>Object.assign</code>…`});
document.body.appendChild(newElem);
// insertAdjacentElement combined with Object.assign
// -------------------------------------------------
// use the above technique combined with insertAdjacentElement
newElem.insertAdjacentElement(
`beforeend`,
Object.assign(document.createElement(`span`),
{ id: `myBrandnewnested2_nested`,
innerHTML: `<br>Me too! And appended I was
with <code>insertAdjacentElement</code>` })
);
// createDocumentFragment
// ----------------------
// Use a document fragment to create/inject html
const fragment = document.createDocumentFragment();
const mdnLnk = `https://developer.mozilla.org/en-US/` +
`docs/Web/API/Document/createDocumentFragment`;
fragment.appendChild(
Object.assign(
document.createElement(`p`),
{innerHTML: `Regards from <code>createDocumentFragment</code>
(see MDN)`})
);
document.querySelector(`#myBrandnewDiv2`).appendChild(fragment);
// Create, but don't inject
// ------------------------
const virtual = Object.assign(
document.createElement(`p`),
{ innerHTML: `
id1
<div id="id2">Hi!</div>
<p id="id3">Hi 2!</p>`,
classList: [`xyz`], } );
const prepareHtml4Reporting = html =>
html.replace(/</g, `<`)
.replace(/\n\s+/g, `\n`)
.replace(/\n\n/g, `\n`);
document.body.insertAdjacentHTML(
`beforeend`,
`<h3>html only</h3><pre>${
prepareHtml4Reporting(virtual.innerHTML)}</pre>`);
body {
font: normal 12px/15px verdana, arial, sans-serif;
margin: 2rem;
}
code {
background-color: #eee;
}
.nested {
margin-left: 0.7rem;
max-width: 450px;
padding: 5px;
border: 1px solid #ccc;
}
I have used some of these methods in this library (see /src/DOM.js), with a mechanism for sanitizing html before it is injecting.
Html:
<div id="main"></div>
JavaScript:
var tree = document.createDocumentFragment();
var link = document.createElement("a");
link.setAttribute("id", "id1");
link.setAttribute("href", "http://site.com");
link.appendChild(document.createTextNode("linkText"));
var div = document.createElement("div");
div.setAttribute("id", "id2");
div.appendChild(document.createTextNode("divText"));
tree.appendChild(link);
tree.appendChild(div);
document.getElementById("main").appendChild(tree);
The main reason to use a documentFragment in stead of just adding the elements directly is speed of execution.
At this size it doesn't matter, but when you start adding hundreds of elements, you will appreciate doing it in-memory first :-)
With documentFragment you can construct a whole tree of DOM-elements in-memory and will not afffect the browser DOM untill the last moment.
Otherwise it forces the browser to update for every element, which sometimes can be a real pain to watch.
If you're doing this repeatedly (dynamically creating HTML), you might want to use a more general approach.
If you want to create three unrelated elements, you can do:
var anchor = elem("a", {"id":"id1"});
var div = elem("div", {"id":"id2"});
var xyz = elem("div", {"id":"id3"});
Now, you have three elements. If you want to get the HTML of these (as string), simply do:
var html = anchor.outerHTML + div.outerHTML + xyz.outerHTML;
If you want to have these three in an element (say, div), do:
var div = elem("div", null, [
elem("a", {"id":"id1"}),
elem("div", {"id":"id2"}),
elem("div", {"id":"id3"}),
]);
You can get the HTML with div.outerHTML, or you can just append it anywhere you want.
To know more about elem(), visit element.js (GitHub).
I'm adding this answer not for the 8 year old question, but for the future visitors. Hope, it helps.
You can construct the html as a string in one variable like
var html = "";
html += "<a id='" + id1 +"'>link</a>";
html += "<div id='" + id1 +"'>div</div>";
// ... and so on
then you return the variable html
return html;
The better way would be to Import ElementsJS and just reference each element in it.
var root = document.getElementById("root");
var elementdiv = create_element('div',{'class':'divcss'}, root, null);
create_element('h1',{'class':'hellocss'}, elementdiv, "Hello World");
.hellocss {
color : red;
}
.divcss {
background-color : blue;
height: 100px;
position: absolute;
}
<script src="https://elementsjs.blob.core.windows.net/public/create-elements.js"></script>
<body id="root"></body>
For More Details Refer to https://github.com/divyamshu/Elements-JS
Well Documented with Example.
Here's simple illustration for converting the html-page (static), to javascript based html-page (dynamic).
Let us say, you have html-page as "index.html" (calling index_static.html here).
index_static.html
<!DOCTYPE HTML>
<html>
<head>
<title>Test</title>
</head>
<body>
<h1> Hello !!! </h1>
</body>
</html>
You can open this file in the browser, to see the desired output.
Now, lets create a javascript equivalent to this.
Use online-tool, to generate the javascript source (by pasting the above html file source to it). Therefore, it follows as:
dynamic.js
document.write("<!DOCTYPE HTML>");
document.write("<html>");
document.write(" <head>");
document.write(" <title>Test<\/title>");
document.write(" <\/head>");
document.write(" <body>");
document.write(" <h1> Hello !!! <\/h1>");
document.write(" <\/body>");
document.write("<\/html>");
And now, your dynamic version of the static_index.html will be as below:
index_dynamic.html
<script language="JavaScript" src="dynamic.js"></script>
Open the index_dynamic.html on the browser to validate the web-page (dynamic though, down-the-line).
more info

Categories