How can I append/prepend the same div created when the button is clicked to the divs in the HTML with the classes "quickAdds and "sideMenu, when the code completes it only prepends to sideMenu class div, I assume it overrides the quickAdds div because it's the last line of code. How can I fix this?
var addTaskBtn = document.querySelector("#enterBtn");
var titleInput = document.querySelector("#textField");
var taskDescription = document.querySelector("#taskDescriptionBox");
var quickAdds = document.querySelector(".quickAdds");
var sideMenu = document.querySelector(".sideMenu");
addTaskBtn.addEventListener("click", function() {
var div = document.createElement("div");
var h = document.createElement("h2");
var p = document.createElement("p");
h.textContent = titleInput.value;
p.textContent = taskDescription.value;
div.appendChild(h);
div.appendChild(p);
quickAdds.prepend(div);
sideMenu.prepend(div);
});
.sideMenuContainer {
/* display: none; */
display: block;
height: 100vw;
width: 550px;
position: absolute;
background: #343434a4;
}
.sideMenu {
display: grid;
grid-template-columns: 1fr;
width: 550px;
margin: 0;
}
.sideMenuTask {
height: auto;
width: 100%;
color: white;
margin: 0;
}
.quickAdds {
background: springgreen;
height: auto;
grid-gap: 5px;
display: grid;
grid-template-columns: repeat(4, 1fr);
border: 3px solid black;
border-radius: 3px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
-ms-border-radius: 3px;
-o-border-radius: 3px;
}
<div class="sideMenuContainer">
<div class="sideMenu">
<div class="sideMenuTask">
<h1>heading of tasks</h1>
<p>Body of tasks</p>
</div>
</div>
</div>
<div class="quickAdds">
</div>
tldr; you need to create two div elements.
When using prepend / appendChild The DOM will keep reference to the element, not value.
This means that it running the following code:
quickAdds.prepend(div);
sideMenu.prepend(div);
Will do the following:
Prepend div to quickAdds
Detach div from quickAdds
Prepend div to sideMenu
In order to prepend to both, you need to create two div elements. E.g.
const div = document.createElement('div');
const div2 = document.createElement('div');
quickAdds.prepend(div);
sideMenu.prepend(div2);
Elements are objects. When you create them they are unique, this is why when you move a node around like you are, it doesn't duplicate itself, the element node is actually moved.
We can use object.assign to duplicate an object, even an element, but the problem here is that you have several elements nested within each other. In order for them to be properly appended every single one of them has to be duplicated separately. When that's the case it's best to just create them individually or, more preferably, in a loop or function call.
When it comes to this type of situation I typically use functional programming to solve the problem, or at least mitigate the code.
This starts out with creating a simple create function that we can adjust for our needs.
function create(ele, params = {}) {
return Object.assign(document.createElement(ele), params);
}
let h2;
console.log( h2 = create("h2", { className: "blue", textContent: "hiya!" } ));
document.body.appendChild(h2);
.blue {
background: blue;
width: 100px;
height: 100px;
color: white;
}
You can extend this for use in your code. This is a simple example of how it could work, but you can also simplify this quite a great deal if you use the function properly. I won't go into that in depth because it's out of scope for this answer, but it's not difficult to imagine.
var addTaskBtn = document.querySelector("#enterBtn");
var titleInput = document.querySelector("#textField");
var taskDescription = document.querySelector("#taskDescriptionBox");
var quickAdds = document.querySelector(".quickAdds");
var sideMenu = document.querySelector(".sideMenu");
addTaskBtn.addEventListener("click", function() {
var div = create("div"), div2 = create("div");
var h = create("h2", { textContent: titleInput.value }),
h2 = create("h2", { textContent: titleInput.value });
var p = create("p", {textContent: taskDescription.value }),
p2 = create("p", {textContent: taskDescription.value });
div.appendChild(h); div2.appendChild(h2);
div.appendChild(p); div2.appendChild(p2);
quickAdds.prepend(div);
sideMenu.prepend(div2);
});
function create(ele, params = {}) {
return Object.assign(document.createElement(ele), params);
}
.sideMenuContainer {
/* display: none; */
display: block;
height: 100vw;
width: 550px;
position: absolute;
background: #343434a4;
}
.sideMenu {
display: grid;
grid-template-columns: 1fr;
width: 550px;
margin: 0;
}
.sideMenuTask {
height: auto;
width: 100%;
color: white;
margin: 0;
}
.quickAdds {
background: springgreen;
height: auto;
grid-gap: 5px;
display: grid;
grid-template-columns: repeat(4, 1fr);
border: 3px solid black;
border-radius: 3px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
-ms-border-radius: 3px;
-o-border-radius: 3px;
}
<div class="sideMenuContainer">
<div class="sideMenu">
<div class="sideMenuTask">
<h1>heading of tasks</h1>
<p>Body of tasks</p>
</div>
<button id="enterBtn">add task or whatever</button>
</div>
</div>
<div class="quickAdds">
</div>
<input type="text" id="textField">
<input type="text" id="titleInput" value="hihihhihi">
<input type="text" id="taskDescriptionBox" value="this is a description ">
Related
I have a div with a list of words from a file. I need help getting rid of the whitespace in the box using the CSS code below. Is it a margin error? I haven't text aligned to the centre either. I can't seem to figure out the CSS error. I'm hoping to keep the dimensions of the box the same just the words to fit in from the left but text-align: left doesn't solve it either. Please Help!
I reviewed your code and your list items were ul's so I changed them to li's and changed the parent ol to a ul and then styled list style none and removed the padding then fixed the width a bit.
The html won't be very responsive due to static widths so you might want to work more on that but I've fixed the issue you described.
#app {
display: table;
height: 80%;
font-size: 16px;
border: 1px solid black;
margin: 15px;
background: lightgray;
}
.search-header {
display: inline-flex;
}
#item-list {
height: 350px;
overflow: scroll;
border: 1px solid gray;
margin-left: 55px;
width: 240px;
background-color: white;
list-style: none;
padding: 0;
}
.search-text {
white-space: normal;
margin-left: 20px;
margin-right: 10px;
margin-top: 20px;
font-size: 15px;
height: 15px;
}
.search-box {
height: 15px;
width: 400px;
}
#search-box[placeholder] {
line-height: 20px;
font-size: 15px;
}
.allButtons{
height: 25px;
margin-left: 10px;
margin-top: 10px;
margin-right: 10px;
}
<!DOCTYPE html>
<html>
<head>
<title>JS search filter</title>
</head>
<body>
<div id="app">
<div class="search-header">
<div class="search-text"> Find:
<input id="search-box" />
<button type="button" class="allButtons" span onclick="var input = this.previousElementSibling; input.value = ''; input.focus();"> Clear </button></span>
</div>
</div>
<div>
<ul id="item-list"></ul>
</div>
</div>
</body>
<script type="text/javascript">
var itemList = [
"a",
"able",
"about",
"account",
"acid",
"across",
"act",
"addition",
"adjustment",
"advertisement",
"after",
"again",
"against",
"agreement",
];
const itemContainer = document.getElementById("item-list");
const searchInput = document.getElementById("search-box");
// Trigger function every time search text is changed
searchInput.onkeyup = (event) => {
filterBySearch(event.target.value);
};
// String to render HTML list item
const itemHTML = (item) => `<li>${item}</li>`;
// Function to render filtered list
const filterBySearch = (query = "") => {
var renderHTML = ``;
// Generate HTML for filtered List
itemList.forEach((item) => {
if (item.toLowerCase().indexOf(query.toLowerCase()) !== -1) {
renderHTML += itemHTML(item);
}
});
// Display updated HTML on screen
itemContainer.innerHTML = renderHTML;
};
// Load the list of items
filterBySearch();
</script>
</html>
I have 10 links and each of them is different from the others.I want when user hovers on them background image of the div changes and a tooltip text be shown on top of the links with a fade-in animation .
i have tried to make several functions using JS and it works but it's a lot of code and mostly repetitive.I want a good shortcut through all of that useless coding.
document.getElementById("d1").onmouseover = function() {
mouseOver1()
};
document.getElementById("d2").onmouseover = function() {
mouseOver2()
};
document.getElementById("d3").onmouseover = function() {
mouseOver3()
};
document.getElementById("d1").onmouseout = function() {
mouseOut1()
};
document.getElementById("d2").onmouseout = function() {
mouseOut2()
};
document.getElementById("d3").onmouseout = function() {
mouseOut3()
};
function mouseOver1() {
document.getElementById("dogs").style.background = "blue";
document.getElementById("tooltiptext1").style.visibility = "visible";
}
function mouseOut1() {
document.getElementById("dogs").style.background = "black";
document.getElementById("tooltiptext1").style.visibility = "hidden";
}
function mouseOver2() {
document.getElementById("dogs").style.background = "green";
document.getElementById("tooltiptext2").style.visibility = "visible";
}
function mouseOut2() {
document.getElementById("dogs").style.background = "black";
document.getElementById("tooltiptext2").style.visibility = "hidden";
}
function mouseOver3() {
document.getElementById("dogs").style.background = "red";
document.getElementById("tooltiptext3").style.visibility = "visible";
}
function mouseOut3() {
document.getElementById("dogs").style.background = "black";
document.getElementById("tooltiptext3").style.visibility = "hidden";
}
#dogs {
float: right;
margin-top: 5%;
background: black;
width: 150px;
height: 150px;
}
#d-list {
color: white;
direction: ltr;
float: right;
width: 60%;
height: 60%;
}
#tooltiptext1,
#tooltiptext2,
#tooltiptext3 {
color: black;
background-color: gray;
width: 120px;
height: 30px;
border-radius: 6px;
text-align: center;
padding-top: 5px;
visibility: hidden;
}
<div id="animals">
<div id="dogs"></div>
<div id="d-list">
<pre style="font-size:22px; color:darkorange">dogs</pre><br />
<pre>white Husky</pre>
<p id="tooltiptext1">Tooltip text1</p>
<pre>black Bull</pre>
<p id="tooltiptext2">Tooltip text2</p>
<pre>brown Rex</pre>
<p id="tooltiptext3">Tooltip text3</p>
</div>
</div>
Please have in mind that all of links will change same outer div object and the idea is to change the background image of that div and the tooltip shoud appear on the top of the links....so,
any ideas?
edit: added animation requested.
CSS is almost always better done in script by using classes when multiple elements are being manipulated with similar functions so I used that here. Rather than put some complex set of logic in place I simply added data attributes for the colors - now it works for any new elements you wish to add as well.
I did find your markup to be somewhat strangely chosen and would have done it differently but that was not part of the question as stated.
I took the liberty of removing the style attribute from your dogs element and put it in the CSS also as it seemed to belong there and mixing markup and css will probably make it harder to maintain over time and puts all the style in one place.
Since you DID tag this with jQuery here is an example of that.
$(function() {
$('#d-list').on('mouseenter', 'a', function(event) {
$('#dogs').css('backgroundColor', $(this).data('colorin'));
$(this).parent().next('.tooltip').animate({
opacity: 1
});
}).on('mouseleave', 'a', function(event) {
$('#dogs').css('backgroundColor', $(this).data('colorout'));
$(this).parent().next('.tooltip').animate({
opacity: 0
});
});
});
#dogs {
float: right;
margin-top: 5%;
background: black;
width: 150px;
height: 150px;
}
#d-list {
color: white;
direction: ltr;
float: right;
width: 60%;
height: 60%;
}
.dog-header {
font-size: 22px;
color: darkorange;
margin-bottom: 2em;
}
.tooltip {
color: black;
background-color: gray;
width: 120px;
height: 30px;
border-radius: 6px;
text-align: center;
padding-top: 5px;
opacity: 0;
position:relative;
top:-4.5em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div id="animals">
<div id="dogs"></div>
<div id="d-list">
<pre class="dog-header">dogs</pre>
<pre>white Husky</pre>
<p id="tooltiptext1" class="tooltip">Tooltip text1</p>
<pre>black Bull</pre>
<p id="tooltiptext2" class="tooltip">Tooltip text2</p>
<pre>brown Rex</pre>
<p id="tooltiptext3" class="tooltip">Tooltip text3</p>
</div>
</div>
Updated
This answer was written before the question was edited to show the intended markup/styling and before all the details were included. The code has been updated to work with that structure.
I think the simplest thing is just to create a configuration object to detail the varying bits, and then use common code for the rest. Here's one approach:
const configs = [
['d1', 'tooltiptext1', 'blue'],
['d2', 'tooltiptext2', 'green'],
['d3', 'tooltiptext3', 'red'],
];
configs.forEach(([id, tt, color]) => {
const dogs = document.getElementById('dogs');
const el = document.getElementById(id);
const tip = document.getElementById(tt);
el.onmouseover = (evt) => {
dogs.style.background = color
tip.style.visibility = "visible";
}
el.onmouseout = (evt) => {
dogs.style.background = "black";
tip.style.visibility = "hidden";
}
})
#dogs{float:right;margin-top:5%;background:#000;width:150px;height:150px}#d-list{color:#fff;direction:ltr;float:right;width:60%;height:60%}#tooltiptext1,#tooltiptext2,#tooltiptext3{color:#000;background-color:gray;width:120px;height:30px;border-radius:6px;text-align:center;padding-top:5px;visibility:hidden}
<div id="animals"> <div id="dogs"></div><div id="d-list"> <pre style="font-size:22px; color:darkorange">dogs</pre><br/> <pre>white Husky</pre> <p id="tooltiptext1">Tooltip text1</p><pre>black Bull</pre> <p id="tooltiptext2">Tooltip text2</p><pre>brown Rex</pre> <p id="tooltiptext3">Tooltip text3</p></div></div>
Obviously you can extend this with new rows really easily. And if you want to add more varying properties, you can simply make the rows longer. If you need to add too many properties to each list, an array might become hard to read, and it might become better to switch to {id: 'demo', tt: 'dem', color: 'blue'} with the corresponding change to the parameters in the forEach callback. (That is, replacing configs.forEach(([id, tt, color]) => { with configs.forEach(({id, tt, color}) => {.) But with only three parameters, a short array seems cleaner.
Older code snippet based on my made-up markup.
const configs = [
['demo', 'dem', 'blue'],
['dd', 'dem1', 'green']
];
configs.forEach(([id1, id2, color]) => {
const a = document.getElementById(id1)
const b = document.getElementById(id2)
a.onmouseover = (evt) => {
a.style.background = color
b.style.visibility = "visible";
}
a.onmouseout = (evt) => {
a.style.background = "black";
b.style.visibility = "hidden";
}
})
div {width: 50px; height: 50px; float: left; margin: 10px; background: black; border: 1px solid #666; color: red; padding: 10px; text-align: center}
#dem , #dem1{visibility:hidden;}
<div id="demo">demo</div>
<div id="dem">dem</div>
<div id="dd">dd</div>
<div id="dem1">dem1</div>
my way of seeing that => zero Javascript:
div[data-info] {
display: inline-block;
margin:80px 20px 0 0;
border:1px solid red;
padding: 10px 20px;
position: relative;
}
div[data-bg=blue]:hover {
background-color: blue;
color: red;
}
div[data-bg=green]:hover {
background-color: green;
color: red;
}
div[data-info]:hover:after {
background: #333;
background: rgba(0, 0, 0, .8);
border-radius: 5px;
bottom: 46px;
color: #fff;
content: attr(data-info);
left: 20%;
padding: 5px 15px;
position: absolute;
z-index: 98;
min-width: 120px;
max-width: 220px;
}
div[data-info]:hover:before {
border: solid;
border-color: #333 transparent;
border-width: 6px 6px 0px 6px;
bottom: 40px;
content: "";
left: 50%;
position: absolute;
z-index: 99;
}
<div data-info="Tooltip for A Tooltip for A" data-bg="blue">with Tooltip CSS3 A</div>
<div data-info="Tooltip for B" data-bg="green" >with Tooltip CSS3 B</div>
I'm working on a Q/A bare bones todolist app and notice that when a list item that is really long is added to the list, it pushes the button out.
Is there a way I can make the LI element larger when the textnode hits the button margin instead of pushing the button out of the LI element. Below is a screenshot. I'll post my source code below, but maybe this is a question that is a quick fix?
My source code can be found here - Issue with floating buttons right of my to do list
A) If I understood you well, you can easily fix it with CSS-Grid:
li {
display: grid;
grid-template-columns: 3fr 100px;
grid-template-areas: 'text button';
}
li > span {
grid-area: text;
}
li > button {
grid-area: button;
height: 30px;
}
https://jsfiddle.net/axqwhj29/
Play with the example linked above resizing the result area to check if that's what you are looking for.
B) Also, but I don't recommend you, if you really don't wanna change your li hight and you have a maximum text width (ex: 25 characters), you can clip parts of your message in a phone vertical view and if the user flips to horizontal show the whole text automatically.
https://jsfiddle.net/qfy3mz01/
Hope this help :)
Okay I have wrapped the text inside the li with span element and and added I add grid display to li and give every element inside the li a width and then I have added word-break: break-word; so the line will break when the text of the span reach the width limit and don't affect the delete button and I've deleted height from li so the li will grow with the lines on it
var addItemButton = document.getElementById('addItem')
var onEnter = document.getElementById('newNote')
//below event listener adds an item to the list on click
addItemButton.addEventListener('click', function() {
let item = document.getElementById('newNote').value
let node = document.createElement("li")
let span = document.createElement("span")
let textnode = document.createTextNode(item)
span.appendChild(textnode)
node.appendChild(span)
if (item) {
document.getElementById('list-body').appendChild(node)
}
let node2 = document.createElement('BUTTON')
let textnode2 = document.createTextNode('Delete')
node2.appendChild(textnode2)
node.appendChild(node2)
node2.addEventListener('click', function() {
node2.parentNode.parentNode.removeChild(node)
});
document.getElementById('newNote').value = ''
});
onEnter.addEventListener('keyup', function(event) {
if (event.keyCode === 13) {
// Cancel the default action, if needed
event.preventDefault();
// Trigger the button element with a click
addItemButton.click();
}
})
function applyButton() { //onload for dummy data or data from db
let getListObjects = document.querySelectorAll("li")
for (let i = 0; i < getListObjects.length; i++) {
let node2 = document.createElement('BUTTON')
let textnode2 = document.createTextNode('Delete')
node2.appendChild(textnode2)
getListObjects[i].appendChild(node2)
let y = getListObjects[i].querySelector('button')
y.addEventListener('click', function() {
y.parentNode.parentNode.removeChild(getListObjects[i])
});
}
}
.container {
height: 100%;
width: 40%;
margin: 0 auto;
}
.container2 {
display: grid;
grid-template-columns: repeat(2, 1fr);
background-color: grey;
border: 1px solid grey;
}
#main-grid {
width: 100%;
}
#newNote {
height: 25px;
}
#inputIdForGrid {
justify-content: left;
align-items: center;
display: flex;
padding-left: 0.3em;
padding-top: 0.5em;
padding-bottom: 0.5em;
}
button {
padding: 10px 18px;
background-color: green;
border: none;
color: white;
font-size: 14px;
align-self: center;
justify-self: end;
}
#addItem {
margin-left: 1em;
padding: 0.5em;
color: white;
font-size: 1.5em;
float: right;
}
ul {
list-style-type: none;
padding: 0px;
margin: 0px;
}
li {
padding: 5px 15px;
display: grid;
grid-template-columns: 2.5fr .5fr;
}
span {
word-break: break-word;
grid-column: 1 / 2;
display: flex;
align-items: center;
}
li:nth-child(2n) {
background-color: grey;
}
li>button {
background-color: red;
}
h1 {
text-align: center
}
<body onload="applyButton()">
<h1>Vanilla JS ToDo List - No Jquery, No Bootstrap</h1>
<div class='container'>
<div id='main-grid'>
<div class="container2">
<div id='inputIdForGrid'>
<input type='text' placeholder="Enter List Items Here" id='newNote'>
</div>
<div>
Hi
</div>
</div>
<ul id='list-body'>
<li><span>run all around town. walk all around town. drive all around town</span></li>
<li><span>Buy Apples</span></li>
<li><span>Hit Gym and Lift Bro</span></li>
<li><span>Stretch</span></li>
</ul>
</div>
</div>
</body>
P.S. I've edited your js code so it will generate span and add the text inside it
This question already has answers here:
Flex elements ignore percent padding in Firefox
(4 answers)
Closed 4 years ago.
In my example code, please click on the Generate Content button in order to understand the issue.
Once you click on the button, you can see all of the flex items(.each-result) generate. They are almost completely wrapped by the div/flexbox (.result-container), indicated by the blue dotted border. If I remove the margins from flex-items, it fits perfectly into the div. However, when I add the margins, the parent div (ie. the flexbox) doesn't expand to it's full width; it remains the same width as when there was no margin.
Is there anyway to change this so that the div expands when adding margin?
const leftArrow = document.querySelector('#left-arrow');
const rightArrow = document.querySelector('#right-arrow');
const rootDiv = document.querySelector('#root');
const generateButton = document.querySelector("#button-generate");
var navMargin = '';
let rootContainerWidth = window.getComputedStyle(rootDiv, null).getPropertyValue("width");
console.log(`Window size onload: ${rootContainerWidth}`);
window.addEventListener('resize', () => {
rootContainerWidth = window.getComputedStyle(rootDiv, null).getPropertyValue("width");
console.log(`The new window size is ${rootContainerWidth}`);
})
//This code basically generates the content within the div
generateButton.addEventListener("click", () => {
for (let i = 0; i < 10; i++) {
const newDiv = document.createElement("div");
newDiv.classList.add("each-result");
newDiv.appendChild(addImg("https://uk.usembassy.gov/wp-content/uploads/sites/16/please_read_icon_150x150.jpg"));
rootDiv.appendChild(newDiv);
}
rootDiv.firstElementChild.classList.add('nav-margin');
navMargin = document.querySelector('.nav-margin');
});
//These enable the arrow to scroll through the dynamically generated content
// function navArrow () {
// leftArrow.addEventListener('click', () => {
// });
// rightArrow.addEventListener('click', () => {
// if ()
// });
// }
//Simple function to create and image element with the src attribute set in one line
function addImg(url) {
const newImg = document.createElement("img");
newImg.setAttribute("src", url);
return newImg;
}
html, body {
height: 100%;
}
button {
position: relative;
z-index: 1
width: auto;
height: 50px;
}
.container {
display: flex;
justify-content: center;
position: relative;
top: 15%;
z-index: 0
}
.each-result {
height: 150px;
width: 150px;
border: 3px dotted red;
margin: 0 1%;
}
img {
height: 100%;
width: auto;
}
.nav-arrows {
display: flex;
justify-content: space-between;
width: 100%;
height: auto;
position: absolute;
background: clear;
pointer-events: none;
}
#left-arrow, #right-arrow {
pointer-events: auto;
}
#root-container {
display: flex;
align-items: center;
border: 1px solid black;
height: 200px;
position: relative;
flex-flow: row no-wrap;
/* overflow: hidden; */
width: 100%;
}
.result-container {
display: flex;
border: 2px blue dotted;
}
<script src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script>
<div class="container">
<div class="nav-arrows">
<button id="left-arrow"><i class="fas fa-arrow-alt-circle-left"></i>
</button>
<button id="right-arrow"> <i class="fas fa-arrow-alt-circle-right"></i>
</button>
</div>
<div id="root-container">
<div id="root" class="result-container">
</div>
</div>
</div>
<button id="button-generate">Generate Content</button>
If the margin can be a fixed value (instead of a percent), we can calc() the width of the element to account for the margin. For example, if we wanted a margin of 20px we'd do the following on the .each-result elements:
.each-result {
width: calc(10% + 20px);
margin: 0 20px;
}
Here's the working demo:
const leftArrow = document.querySelector('#left-arrow');
const rightArrow = document.querySelector('#right-arrow');
const rootDiv = document.querySelector('#root');
const generateButton = document.querySelector("#button-generate");
var navMargin = '';
let rootContainerWidth = window.getComputedStyle(rootDiv, null).getPropertyValue("width");
console.log(`Window size onload: ${rootContainerWidth}`);
window.addEventListener('resize', () => {
rootContainerWidth = window.getComputedStyle(rootDiv, null).getPropertyValue("width");
console.log(`The new window size is ${rootContainerWidth}`);
})
//This code basically generates the content within the div
generateButton.addEventListener("click", () => {
for (let i = 0; i < 10; i++) {
const newDiv = document.createElement("div");
newDiv.classList.add("each-result");
newDiv.appendChild(addImg("https://uk.usembassy.gov/wp-content/uploads/sites/16/please_read_icon_150x150.jpg"));
rootDiv.appendChild(newDiv);
}
rootDiv.firstElementChild.classList.add('nav-margin');
navMargin = document.querySelector('.nav-margin');
});
//These enable the arrow to scroll through the dynamically generated content
// function navArrow () {
// leftArrow.addEventListener('click', () => {
// });
// rightArrow.addEventListener('click', () => {
// if ()
// });
// }
//Simple function to create and image element with the src attribute set in one line
function addImg(url) {
const newImg = document.createElement("img");
newImg.setAttribute("src", url);
return newImg;
}
html, body {
height: 100%;
}
button {
position: relative;
z-index: 1
width: auto;
height: 50px;
}
.container {
display: flex;
justify-content: center;
position: relative;
top: 15%;
z-index: 0
}
.each-result {
height: 150px;
width: calc(10% + 20px);
margin: 0 20px;
border: 3px dotted red;
}
img {
height: 100%;
width: auto;
}
.nav-arrows {
display: flex;
justify-content: space-between;
width: 100%;
height: auto;
position: absolute;
background: clear;
pointer-events: none;
}
#left-arrow, #right-arrow {
pointer-events: auto;
}
#root-container {
display: flex;
align-items: center;
border: 1px solid black;
height: 200px;
position: relative;
flex-flow: row no-wrap;
/* overflow: hidden; */
width: 100%;
}
.result-container {
display: flex;
border: 2px blue dotted;
}
<script src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script>
<div class="container">
<div class="nav-arrows">
<button id="left-arrow"><i class="fas fa-arrow-alt-circle-left"></i>
</button>
<button id="right-arrow"> <i class="fas fa-arrow-alt-circle-right"></i>
</button>
</div>
<div id="root-container">
<div id="root" class="result-container">
</div>
</div>
</div>
<button id="button-generate">Generate Content</button>
I am trying to get the node.firstChild of the #root element, after generating content within the container. I expect it to be the first div, because when I look at the elements in the dev console, that's the first child that I see. I am not sure where this #text is coming from, or what it means even.
Please help me understand:
What #text is (obviously it's some type of text, but I don't see it)
Why it's showing up instead of the firstChild of my container which should actually be div.each-result
It should be noted that I am running this code in CodePen
I am also aware I can also use Node.firstElementChild, but I want to understand what's going wrong currently.
const leftArrow = document.querySelector('#left-arrow');
const rightArrow = document.querySelector('#right-arrow');
const rootDiv = document.querySelector('#root');
const generateButton = document.querySelector("#button-generate");
//This code basically generates the content within the div
generateButton.addEventListener("click", () => {
for (let i = 0; i < 10; i++) {
const newDiv = document.createElement("div");
newDiv.classList.add("each-result");
newDiv.appendChild(addImg("https://uk.usembassy.gov/wp-content/uploads/sites/16/please_read_icon_150x150.jpg"));
rootDiv.appendChild(newDiv);
}
console.log(rootDiv.firstChild);
});
//These enable the arrow to scroll through the dynamically generated content
leftArrow.addEventListener('click', () => {
//use
});
rightArrow.addEventListener('click', () => {
alert("right arrow works");
});
//Simple function to create and image element with the src attribute set in one line
function addImg(url) {
const newImg = document.createElement("img");
newImg.setAttribute("src", url);
return newImg;
}
html, body {
height: 100%;
}
button {
position: relative;
z-index: 1
width: auto;
height: 50px;
}
.container {
display: flex;
justify-content: center;
position: relative;
top: 15%;
z-index: 0
}
.result-container {
display: flex;
align-items: center;
border: 1px solid black;
width: 80%;
height: 200px;
position: relative;
flex-flow: row no-wrap;
overflow: hidden;
}
.each-result {
height: 150px;
width: 150px;
border: 3px dotted red;
margin: 1%;
}
img {
height: 100%;
width: auto;
}
.nav-arrows {
display: flex;
justify-content: space-between;
width: 100%;
height: auto;
position: absolute;
background: clear;
pointer-events: none;
}
#left-arrow, #right-arrow {
pointer-events: auto;
}
<script src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script>
<div class="container">
<div class="nav-arrows">
<button id="left-arrow"><i class="fas fa-arrow-alt-circle-left"></i>
</button>
<button id="right-arrow"> <i class="fas fa-arrow-alt-circle-right"></i>
</button>
</div>
<div id="root" class="result-container">
</div>
</div>
<button id="button-generate">Generate Content</button>
Look at the first example here: Node.firstChild
In the above, the console will show '#text' because a text node is
inserted to maintain the whitespace between the end of the opening <p>
and <span> tags. Any whitespace will create a #text node, from a
single space to multiple spaces, returns, tabs, and so on.
Another #text node is inserted between the closing </span> and
</p> tags.
If this whitespace is removed from the source, the #text nodes are not
inserted and the span element becomes the paragraph's first child.
As you suggested yourself, ParentNode.firstElementChild is the best way to go in this case.