Appending nested elements in Javascript function for HTML - javascript

I am trying to append another HTML element to a element in Javascript.
What my function below does is that on the click of the "add" button, whatever the user has typed into a textbox is put into a ul element in my menu and a element li is created to append that text inside the li element. My function works but I also want to append a a href = #> insert text here</a> nested inside the li element.
So what I have my function doing right now is
<ul class = "dropdown-menu">
<li> User Text </li>
</ul>
I want to reproduce this
<ul class = "dropdown-menu">
<li> User Text </li>
</ul>
This is what I have attempted so far:
(function() {
document.querySelector('#add').addEventListener('click', function() {
let input = document.querySelector('#addissuetext');
let list = document.querySelector('#menu');
let item = document.createElement('li'); // create li node
let hyper = document.createElement('a');
hyper.href = "#";
let itemText = document.createTextNode(input.value); // create text node
item.appendChild(itemText); // append text node to li node
hyper.appendChild(item);
list.appendChild(item); // append li node to list
input.value = ""; // clear input
});
})();
I have also tried innerHTML but I do not think that is what will work.

You need to append text into anchor first, then append that anchor into li, then li into ul.
ul > li > a > text
hyper.appendChild(itemText); // append text to anchor
item.appendChild(hyper); // append anchor node to li node
list.appendChild(item); // append li node to list
Since you have not provided snippet or full html, this may create some error.
(function() {
document.querySelector('#add').addEventListener('click', function() {
let input = document.querySelector('#addissuetext');
let list = document.querySelector('#menu');
let item = document.createElement('li'); // create li node
let hyper = document.createElement('a');
hyper.href = "#";
let itemText = document.createTextNode(input.value); // create text node
hyper.appendChild(itemText); // append text to anchor
item.appendChild(hyper); // append anchor node to li node
list.appendChild(item); // append li node to list
input.value = ""; // clear input
});
})();

You have things in the wrong order:
(function () {
document.querySelector('#add').addEventListener('click', function () {
let input = document.querySelector('#addissuetext');
let list = document.querySelector('#menu');
let item = document.createElement('li'); // create li node
let hyper = document.createElement('a');
hyper.href = "#";
let itemText = document.createTextNode(input.value); // create text node
hyper.appendChild(itemText); // append text node to hyperlink
item.appendChild(hyper); // append hyperlink to li
list.appendChild(item); // append li node to list
input.value = ""; // clear input
});
})();

Related

how to select or give a class name to createTextNode() tekst inside Li elements

I made a shopping list, now I want to strike through the items when I click on it.
When I click on it now, the whole li item gets striked through(the marker and the deletebutton gets striked through now).
I want to give the tekst in the list items I created in this script a class, but I can't get it working.
this is the script where the list items is made :
function createListElement() {
var li = document.createElement("li");
li.appendChild(document.createTextNode(input.value));
li.classList.add("tekstje");
ol.appendChild(li);
input.value = "";
var delBtn = document.createElement("BUTTON"); // Create a <button> element
delBtn.classList.add("deletebtn"); // Give a class name
delBtn.innerHTML = "X"; // Insert text
li.appendChild(delBtn); // Append <button> to <LI>
}
I tried the classlist.add method and giving it a P class, but that doesn't seem to work.
I also tried selecting it with :tekst
Override the CSS on the inner button. Or, just wrap the text within the li with a span and only add the strike through on the span.
var ol = document.getElementById("theOl");
var input = document.getElementById("theInput");
function createListElement() {
var li = document.createElement("li");
li.appendChild(document.createTextNode(input.value));
li.classList.add("tekstje");
ol.appendChild(li);
input.value = "";
var delBtn = document.createElement("BUTTON"); // Create a <button> element
delBtn.classList.add("deletebtn"); // Give a class name
delBtn.innerHTML = "X"; // Insert text
delBtn.onclick = function () {
delBtn.parentNode.classList.add("all-done");
}
li.appendChild(delBtn); // Append <button> to <LI>
}
.all-done {
text-decoration: line-through;
}
.all-done button {
text-decoration: none;
}
<ol id="theOl"></ol>
<input id="theInput" value="test">
<button onclick="createListElement()">Add</button>

How to create HTML tags (with content) on the fly with JavaScript?

I am trying to convert this HTML code to be generated by Javascript on the fly for live data.
<div class="dropdown">
<button class="dropbtn">Dropdown</button>
<div class="dropdown-content">
Link 1
Link 2
Link 3
</div>
</div>
Ive found a few methods like: appendChild, getElementById, innerHTML and so on. Here is what I've tried so far. I can't seem to get the data to show up.
stringy = data2.Items[0].groupName.values[i];
var para = document.createElement("div");
var node = document.createTextNode(stringy);
para.appendChild(node);
var element = document.getElementById("parental");
element.appendChild(para);
//create div and give it a class
para.setAttribute('class', 'dropbtn');
var div = document.createElement("div");
div.setAttribute('class', 'dropdown-content');
para.parentNode.insertBefore(div, para.nextSibling);
//create link tags and give them text
var alinky = document.createElement("a");
alinky.setAttribute('id', 'linky');
document.getElementById('linky').innerHTML = "linky poo"
div.appendChild(alinky);
Hopefully someone could fill in the blanks on getting this HTML code to be reproduced with javascript. Thanks in advance!
EDIT:
I am trying to create a dropdown menu like this:
https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_js_dropdown_hover
However, I am trying to create multiple dropdown menus, that dynamically change in quantity based on a query to DynamoDB (AWS). therefore I am using javascript to create the html tags.
The problem is that the scope of the query function does not allow me to see the data outside of the query function, or even inject data into it.
For example, if I try to get a button description from the query, and write to it descriptionArray[0] = data2.Items[0].description; so that I can append the button to the dropdown div, it doesn't know which iteration I'm on in the for loop due to scope. In this example, descriptionArray[0] will work, but descriptionArray[i] will not work because the for loop is outside the query.
Here is the entire logic:
//group data
var length = data2.Items[0].groupName.values.length;
// create elements
const dpdown1 = document.createElement('div');
// set dpdown1 class
dpdown1.setAttribute('class', 'dropdown');
console.log(dpdown1);
var button = new Array();
var dpdown2 = new Array();
var membersArray = new Array();
var descriptionArray = new Array();
var linksArray = new Array();
var stringy = new Array;
//list groups
for(i = 0; i<length; i++){
// create button, set button attribs
button[i] = document.createElement('button');
button[i].setAttribute('class','dropbtn');
//create dropdown div, set attributes
dpdown2[i] = document.createElement('div');
dpdown2[i].setAttribute('class', 'dropdown-content');
//list of group names
stringy[i] = data2.Items[0].groupName.values[i];
var stringyy = stringy[i];
var desc;
//query group members and description
var docClient1 = new AWS.DynamoDB.DocumentClient({ region: AWS.config.region });
var identityId = AWS.config.credentials.identityId;
var paramsyy = {
ExpressionAttributeValues: {
":v1": stringyy
},
KeyConditionExpression: "groupName = :v1",
TableName: "group"
};
docClient1.query(paramsyy, function(err, data2) {
if (err) {
console.error(err);
}else{
descriptionArray[0] = data2.Items[0].description;
//traverse members
for(k = 0; k<data2.Items[0].members.values.length; k++){
// create dropdown links of members
membersArray[k] = data2.Items[0].members.values[k];
linksArray[k] = document.createElement('a');
linksArray[k].setAttribute('href', '#')
linksArray[k].innerText = membersArray[k];
// nest into dpdown2 div, set dpdown2 attribs
dpdown2[0].appendChild(linksArray[k]);
}
}
});
button[i].innerText = stringyy + ": " + descriptionArray[0];
// nest into dpdown1
dpdown1.appendChild(button[i]);
dpdown1.appendChild(dpdown2[i]);
}
// append to DOM
const target = document.getElementById('target');
target.appendChild(dpdown1);
if I use the I from the first for loop inside the query function, it will give me undefined results.
here's how you can do it with vanilla JavaScipt, there are multiple ways to do it, but this way only uses 4 methods: createElement, setAttribute, appendChild, and getElementById, and directly sets 1 property: innerText.
// create elements
const dpdown1 = document.createElement('div');
const button = document.createElement('button');
const dpdown2 = document.createElement('div');
const link1 = document.createElement('a');
const link2 = document.createElement('a');
const link3 = document.createElement('a');
// set link attribs
link1.setAttribute('href', '#')
link1.innerText = 'Link 1';
link2.setAttribute('href', '#')
link2.innerText = 'Link 2';
link3.setAttribute('href', '#')
link3.innerText = 'Link 3';
// nest into dpdown2, set dpdown2 attribs
dpdown2.appendChild(link1);
dpdown2.appendChild(link2);
dpdown2.appendChild(link3);
dpdown2.setAttribute('class', 'dropdown-content');
// set button attribs
button.setAttribute('class','dropbtn');
button.innerText = "Dropdown"
// nest into dpdown1
dpdown1.appendChild(button);
dpdown1.appendChild(dpdown2);
// set dpdown1 class
dpdown1.setAttribute('class', 'dropdown');
// append to DOM
const target = document.getElementById('target');
target.appendChild(dpdown1);
<div id="target"></div>
You will to append it to something, in this example it's <div id="target"></div> but it could be something else.
Happy coding!
Mainly you are just doing things out of order.
Create the .dropdown <div> with its class.
Complete the .dropbtn <button> with its class and text.
Add the button to the div.
Create the .dropdown-content <div>.
Complete each link with its href attribute and text.
Add each link to the .dropdown-content <div>.
Add the .dropdown-content div to the .dropdown <div>.
Find the parent element in the document.
Append the whole complete .dropdown <div> to the document.
var para = document.createElement("div"); //make .dropdown div
para.setAttribute('class', 'dropdown'); //add .dropdown class to div
var button = document.createElement("button"); //create button
button.setAttribute('class', 'dropbtn'); //add .dropbtn class to button
var node = document.createTextNode('Dropdown'); //create button text
button.appendChild(node); //add text to button
para.appendChild(button); //add button to .dropdown div
var div = document.createElement("div"); //create .dropdown-content div
div.setAttribute('class', 'dropdown-content'); //add .dropdown-content class to div
//repeat for all necessary links
var alinky = document.createElement("a"); //creat link
alinky.setAttribute('href', '#'); //set link href attribute
var alinkyText = document.createTextNode("Link 1"); //create text for link
alinky.appendChild(alinkyText); //add text to link
div.appendChild(alinky); //add link to dropdown div
para.appendChild(div); //add .dropdown-content div to .dropdown div
var element = document.getElementById("parental"); //find parent element
element.parentNode.insertBefore(para, element.nextSibling); //add .dropdown div to the bottom of the parent element
<div id="parental">
</div>

changing text-node value in javascript

// Create element
const loi = document.createElement('li');
// Add class
loi.className = 'collection-item';
// Add id
loi.id = 'new-item';
// Add attribute
loi.setAttribute('title', 'New Item');
// Create text node and append
loi.appendChild(document.createTextNode('Hello World'));
// Create new link element
const link = document.createElement('a');
// Add classes
link.className = 'delete-item secondary-content';
// Add icon HTML
link.innerHTML = '<i class="fa fa-remove"></i>';
// Append link into li
loi.appendChild(link);
// Append li as child to ul
document.querySelector('ul.collection').appendChild(loi);
console.log(loi);
Here when I want to update the text-node which is hello-world, by writing loi.textContent="ghg"; then that hello world is changed to ghg, but I missed those anchor tag, and I tag which I have created apart from this everything is there, I have attached the output screenshot also.
When you are inserting a text node into li, it is the first child of li like you mentioned. You can access it with loi.childNodes[0] or use the read-only attribute loi.firstChild to verify.
const loi = document.createElement('li');
// Add class
loi.className = 'collection-item';
// Add id
loi.id = 'new-item';
// Add attribute
loi.setAttribute('title', 'New Item');
// Create text node and append
//const span = document.createElement("span");
//const text = document.createTextNode("Hello World");
//span.appendChild(text);
loi.appendChild(document.createTextNode("Hello World"));
// Create new link element
const link = document.createElement('a');
// Add classes
link.className = 'delete-item secondary-content';
// Add icon HTML
link.innerHTML = '<i class="fa fa-remove"></i>';
// Append link into li
loi.appendChild(link);
// Append li as child to ul
document.querySelector('ul.collection').appendChild(loi);
const newText = document.createTextNode("New World");
console.log(loi.childNodes[0]);
loi.childNodes[0].replaceWith(newText);
//OR loi.replaceChild(newText, loi.childNodes[0]);
<ul class="collection"></ul>

href in a specific word of the String using JavaScript and HTML5

I'm trying to show the content of var fruits (array) in a HTML page using li, ul, a and href for a specific word (not all the text).
For example, for the sentence I want a link here I want the link only for the word here but I don't know how to do it...
Here is the code so far:
<script>
// selects the div with an id of placeholder
var div = document.getElementById('placeholder');
// say that fruits contains all your data
var fruits = ['I want a link here','I want a link here','I want a link here','I want a link here','I want a link here'],
ul = document.createElement('ul'); // create an arbitrary ul element
// loop through the fruits array
for(var i in fruits) {
// create an arbitrary li element
var li = document.createElement('li'),
content = document.createTextNode(fruits[i]); // create a textnode to the document
var link = "http://google.com";
var element = document.createElement("a");
element.setAttribute("href", link);
element.innerHTML = fruits[i];
li.appendChild(element); // append the created textnode above to the li element
ul.appendChild(li); // append the created li element above to the ul element
}
div.appendChild(ul); // finally the ul element to the div with an id of placeholder
</script>
FIDDLE
One possible solution
var div = document.getElementById('placeholder');
// say that fruits contains all your data
var fruits = ['I want a link here','I want a link here','I want a link here','I want a link here','I want a link here'],
ul = document.createElement('ul'); // create an arbitrary ul element
// loop through the fruits array
for(var i in fruits) {
// create an arbitrary li element
var li = document.createElement('li'),
content = document.createTextNode(fruits[i]); // create a textnode to the document
var link = "http://google.com";
var element = document.createElement("span");
element.innerHTML = fruits[i];
li.appendChild(element); // append the created textnode above to the li element
ul.appendChild(li); // append the created li element above to the ul element
}
div.appendChild(ul); // finally the ul element to the div with an id of placeholder
Fiddle
If you don't want to change your original data array you could use.
for(var i in fruits) {
// create an arbitrary li element
var li = document.createElement('li');
var link = "http://google.com";
var content = fruits[i].replace('here', 'here');
var element = document.createElement("span");
element.innerHTML = content;
li.appendChild(element); // append the created textnode above to the li element
ul.appendChild(li); // append the created li element above to the ul element
}
Fiddle
This works in the fiddle you provided.
// selects the div with an id of placeholder
var div = document.getElementById('placeholder');
// say that fruits contains all your data
var fruits = ['I want a link here', 'I want a link here', 'I want a link here', 'I want a link here', 'I want a link here'],
ul = document.createElement('ul'); // create an arbitrary ul element
// loop through the fruits array
for (var i in fruits) {
// split words from sentence
var fruitWords = fruits[i].split(' ');
// select the word you want linked ( I selected 'here')
var linkWord = fruitWords[fruitWords.length-1];
// reconstruct sentence removing the linked word
fruitWords.pop();
fruits[i] = fruitWords.join(' ');
// create an arbitrary li element
var li = document.createElement('li'),
content = document.createTextNode(fruits[i]); // create a textnode to the document
var link = "http://google.com";
var element = document.createElement("a");
element.setAttribute("href", link);
element.innerHTML = linkWord;
li.innerHTML = fruits[i] + ' ';
li.appendChild(element); // append the created textnode above to the li element
ul.appendChild(li); // append the created li element above to the ul element
}
div.appendChild(ul); // finally the ul element to the div with an id of placeholder

Create List Item From Rich Text Field Content

I want to take the user input text from this div and input tag I've got:
<input id="title" placeholder="Title (Optional)">
<div class="editor" contenteditable></div>
The div is a rich text field that I've put in place of a regular textarea tag
and create a list item inside a <ul> tag.
Here is the javascript I've got, but is not working...
(works just fine with regular text area, but I get nothing with the rich text form)
/*------POST SUBMIT JS------*/
//target all necessary HTML elements
var ul = document.getElementById('list'),
removeAll = document.getElementById('removeAll'),
add = document.getElementById('add');
//make something happen when clicking on 'submit'
add.onclick = function(){
addLi(ul)
};
//function for adding items
function addLi(targetUl){
var inputText = document.getElementsByClassName('editor').value, //grab input text (the new entry)
header = document.getElementById('title').value, //grab title text
li = document.createElement('li'), //create new entry/li inside ul
content = document.createElement('div'),
title = document.createElement('div'),
removeButton = document.createElement('button'); //create button to remove entries
content.setAttribute('class','content')
title.setAttribute('class','title')
content.innerHTML = inputText;
title.innerHTML = header;
if (inputText.split(' ').join(' ').length === 0) {
//check for empty inputs
alert ('No input');
return false;
}
removeButton.className = 'removeMe'; //add class to button for CSS
removeButton.innerHTML = 'Delete'; //add text to the remove button
removeButton.setAttribute('onclick', 'removeMe(this);'); //creates onclick event that triggers when entry is clicked
li.appendChild(title); //add title textnode to created li
li.appendChild(content); //add content textnode to created li
li.appendChild(removeButton); //add Remove button to created li
targetUl.appendChild(li); //add constructed li to the ul
}
//function to remove entries
function removeMe(item){
var deleteConfirm = confirm('Are you sure you want to delete this entry?');
if (deleteConfirm){var parent = item.parentElement;
parent.parentElement.removeChild(parent)}
};
function checkRemoval(){
var entryConfirm = confirm('Are you sure you want to delete all entries?');
if (entryConfirm){
ul.innerHTML = '';
}
};
Here is the demo I'm working on
Here is the demo using a textarea tag
getElementsByClassName('editor') is going to return an array of elements with the class editor, so you can't just do .value, you need to get the first element in the array.
Also, since it's a div, I think you want to use textContent, so it'll look like this
var inputText = document.getElementsByClassName('editor')[0].textContent
for the input type you have to write following into your javascript:
var input_val = getElementsByClassName('title').value;
for the div you have to write following into your javascript:
var div_val = getElementsByClass('editor').value;
I hope this will work

Categories