Appending more elements to one div horizontally - javascript

I want to create page, which will show bars/restaurants on page based on some filter. I have one div, which will contain all results (.resultsContainer). I have no problem appending more divs (.barContainer) to this one, but I am struggling to actually append information to these divs. I want .barContainer (.infoContainer) to hold more information such as picture, name, address etc. Problem is when I use append to it, divs are stacked vertically, because margins take full width, even when I set them to zero. I tried using createDocumentFragment() function, where I stack more childs, and then I append result to the .barContainer, which I pass then to HTML, but still it is not working how it should. Basically what I try to achieve is to stack information to infoContainer like tetris bricks. I appreciate any help, maybe there is way how to create html template and use it dynamically? I am pretty sure I am doing something wrong with appendChild, but I cant find a solution. I am new to webcoding.)
Here in my code I will try to put picture, adress and name into the infoContainer, each of those should take one third of the parent div's width and they should be next to each other without any margin. They will have different colours.
HTML:
<body>
<button type="button" id="myBtn" onclick="appendBars()">Append</button>
<div id="resultsContainer"></div>
</body>
JS:
function appendBars(){
var barContainer = document.createElement("div");
barContainer.className = "barContainer"
var infoContainer = document.createElement("div");
infoContainer.className = "infoContainer";
var barPicture = document.createElement("div");
barPicture.className = "barPicture";
var barName = document.createElement("div");
barName.className = "barName";
var barAddress = document.createElement("div");
barAddress.className = "barAddress";
var fragment = document.createDocumentFragment();
fragment.appendChild(barPicture);
fragment.appendChild(barName);
fragment.appendChild(barAddress);
infoContainer.appendChild(fragment);
barContainer.appendChild(infoContainer);
document.getElementById("resultsContainer").appendChild(barContainer);
}
CSS:
#resultsContainer{
float: right;
background: red;
width: 620px;
height: 100%;
overflow-x: auto;
}
.barContainer {
background-color: white;
width: 100%;
height: 200px;
border-top: 0px;
border-right: 0px;
border-bottom: 1px;
border-style: solid;
border-color: grey;
}
.infoContainer{
width: 620px;
height: 180px;
background-color: white;
padding: 10px;
}
.barPicture{
width: 200px;
height: 180px;
margin: 0;
background-color: yellow;
}
.barName{
background-color: blue;
margin: 0px;
width: 200px;
height: 180px;
}
.barAddress{
background-color: green;
margin: 0px;
width: 200px;
height: 180px;
}

Simply make your elements inline-block, as by default div is a block element and whatever the width you specify it will always occupy the whole row.
You can read more about block/inline elements
function appendBars(){
var barContainer = document.createElement("div");
barContainer.className = "barContainer"
var infoContainer = document.createElement("div");
infoContainer.className = "infoContainer";
var barPicture = document.createElement("div");
barPicture.className = "barPicture";
var barName = document.createElement("div");
barName.className = "barName";
var barAddress = document.createElement("div");
barAddress.className = "barAddress";
var fragment = document.createDocumentFragment();
fragment.appendChild(barPicture);
fragment.appendChild(barName);
fragment.appendChild(barAddress);
infoContainer.appendChild(fragment);
barContainer.appendChild(infoContainer);
document.getElementById("resultsContainer").appendChild(barContainer);
}
#resultsContainer{
float: right;
background: red;
width: 620px;
height: 100%;
overflow-x: auto;
}
.barContainer {
background-color: white;
width: 100%;
height: 200px;
border-top: 0px;
border-right: 0px;
border-bottom: 1px;
border-style: solid;
border-color: grey;
}
.infoContainer{
width: 620px;
height: 180px;
background-color: white;
padding: 10px;
}
.barPicture{
width: 200px;
height: 180px;
margin: 0;
background-color: yellow;
display:inline-block
}
.barName{
background-color: blue;
margin: 0px;
width: 200px;
height: 180px;
display:inline-block
}
.barAddress{
background-color: green;
margin: 0px;
width: 200px;
height: 180px;
display:inline-block
}
<button type="button" id="myBtn" onclick="appendBars()">Append</button>
<div id="resultsContainer"></div>

Your best solution is to apply display: flex to .infoContainer. That will force the divs to be arranged in a row. You can also apply display: inline-block; for .barPicture and .barName, but it may look bad if you have an overflow.
Demo with .infoContainer {display: flex;}:
function appendBars(){
var barContainer = document.createElement("div");
barContainer.className = "barContainer"
var infoContainer = document.createElement("div");
infoContainer.className = "infoContainer";
var barPicture = document.createElement("div");
barPicture.className = "barPicture";
var barName = document.createElement("div");
barName.className = "barName";
var barAddress = document.createTextNode("div");
barAddress.className = "barAddress";
var fragment = document.createDocumentFragment();
fragment.appendChild(barPicture);
fragment.appendChild(barName);
fragment.appendChild(barAddress);
infoContainer.appendChild(fragment);
barContainer.appendChild(infoContainer);
document.getElementById("resultsContainer").appendChild(barContainer);
}
#resultsContainer{
float: right;
background: red;
width: 620px;
height: 100%;
overflow-x: auto;
}
.barContainer {
background-color: white;
width: 100%;
height: 200px;
border-top: 0px;
border-right: 0px;
border-bottom: 1px;
border-style: solid;
border-color: grey;
}
.infoContainer{
width: 620px;
height: 180px;
background-color: white;
padding: 10px;
display: flex;
}
.barPicture{
width: 200px;
height: 180px;
margin: 0;
background-color: yellow;
}
.barName{
background-color: blue;
margin: 0px;
width: 200px;
height: 180px;
}
.barAddress{
background-color: green;
margin: 0px;
width: 200px;
height: 180px;
}
<button type="button" id="myBtn" onclick="appendBars()">Append</button>
<div id="resultsContainer"></div>

If I understand your question correctly, you just need to add this to your CSS
/* CLASSES YOU WANT TO INCLUDE */
.barPicture,
.barName,
.barAddress{
display: inline-block;
}

Related

Cannot append localStorage data to an existing div class

Currently making a quick journal entry app in HTML, CSS, and JS. User inputs and submits text data along with the time and date. I'm trying to take that data from the localStorage to put inside an existing div class. Any advice?
This is the HTML code.
<div class="background-journal">
<button class="button-journal" onclick="openPopup()" id="entrybtn">New Entry</button>
<br><br><br><br><br><br><br>
<button class="show-journal" onclick="recallEntries()" id="showbtn">View Previous Entries</button>
<div class="journal-visual" id="data-viz">
</div>
<div id="popup" class="popup">
<form id="form" class="form">
<br>
<label for="journal-entry">何を勉強していますか?</label><br><br>
<textarea class="add-entry" id="journal-entry" rows="6" cols="150"></textarea><br>
<button type="submit" onclick="submitJournalEntry()">Submit</button>
<button type="button" onclick="closePopup()">Close</button>
</form>
</div>
This is the CSS code.
.background-journal{
position:absolute;
top: 35%;
left: 9.6%;
background-color:rgba(255,255,255,0);
z-index:1001;
width: 80%;
height: 600px;
overflow-y: auto;
overflow-x: hidden;
}
.button-journal {
background-color: #fff;
border: none;
color: #000;
text-align: center;
text-decoration: none;
font-size: 16px;
cursor: pointer;
width: 90%;
height: 100px;
left: 4.5%;
position: absolute;
box-shadow: 3px 5px #888888;
}
.show-journal{
background-color: #fff;
border: none;
color: #000;
text-align: center;
text-decoration: none;
font-size: 16px;
cursor: pointer;
width: 90%;
height: 100px;
left: 4.5%;
position: absolute;
box-shadow: 3px 5px #888888;
}
.journal-visual{
background-color: #fff;
z-index:1003;
width: 70%;
height: 450px;
overflow-y: auto;
overflow-x: hidden;
margin-left: auto;
margin-right: auto;
display: none;
position: relative;
color: #000;
text-align: center;
}
.button-popup-journal{
position: relative;
}
.popup {
display: none;
position: absolute;
z-index: 1;
width: 100%;
height: 200px;
overflow: auto;
background-color: rgba(0, 0, 0, 0.5);
text-align: center;
box-shadow: 3px 5px #000;
}
.popup form{
margin: auto;
}
.add-entry{
margin: auto;
overflow: auto;
position:inherit;
left: 5%;
}
.background-journal label{
color: white;
opacity: 70%;
}
and this is the JS code.
// Journal Function
function openPopup() {
document.getElementById("popup").style.display = "block";
document.getElementById("entrybtn").style.display = "none";
document.getElementById("showbtn").style.display = "none";
}
function closePopup() {
document.getElementById("popup").style.display = "none";
document.getElementById("entrybtn").style.display = "block";
document.getElementById("showbtn").style.display = "block";
}
function submitJournalEntry() {
var journalEntry = document.getElementById("journal-entry").value;
var date = new Date();
var timestamp = date.toString();
localStorage.setItem(timestamp, journalEntry);
closePopup();
}
function recallEntries() {
document.getElementById("entrybtn").style.display = "none";
document.getElementById("showbtn").style.display = "none";
document.getElementById("data-viz").style.display = "block";
var keys = Object.keys(localStorage);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var journalEntry = localStorage.getItem(key);
var viz = document.getElementById('data-viz');
div.innerHTML = '<p><strong>' + key + '</strong>: ' + journalEntry + '</p>';
document.body.appendChild(viz);
}
}
I was expecting the text to show up in the div class="journal-entry" id="data-viz" but nothing is there. Any ideas?

How to find the next closest input outside of parent and parents in Javascript?

Basically, I'm trying to update the value of the closest input to an element based on some conditions.
This doesn't seem to work at all.
To explain this better, here's a working example:
$('.t').append('<div class="row" style="margin-bottom:10px;"></div><div class="block block-strong myBlock"><div class="imgHolder"><div data-id="ASAS-HHH-UUU-TEY.jpg?42344444444" class="addedImg"><div class="deletImg" data-id="ASAS-HHH-UUU-TEY.jpg?42344444444">X</div><img class="tappableImg" src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Test-Logo.svg/783px-Test-Logo.svg.png" ></div></div></div><div><input type="text" class="input" value="22,44,66,99,ASAS-HHH-UUU-TEY.jpg?42344444444"/><div><div class="row" style="margin-bottom:10px;"></div><div class="block block-strong myBlock"><div class="imgHolder"><div data-id="ASAS-HHH-UUU-TEY.jpg?423423" class="addedImg"><div class="deletImg" data-id="ASAS-HHH-UUU-TEY.jpg?423423">X</div><img class="tappableImg" src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Test-Logo.svg/783px-Test-Logo.svg.png" ></div></div></div><div><input type="text" class="input" value="22,44,66,99,ASAS-HHH-UUU-TEY.jpg?423423"/>');
$(document).on('click', '.deletImg', function() {
var $this = (this);
var id = $(this).attr('data-id');
var inp = $($this).parents().parent().eq(1).find(".input").val();
inp = inp.replace(id + ',', '');
inp = inp.replace(id, ''); //$($this).parents().parents().parent().eq(1).find(".input").val(inp);
});
.addedImg {
width: 100px;
height: 100px;
position: relative;
display: inline-block;
margin-right: 12px;
}
.imgHolder {
height: auto;
overflow-y: hidden;
overflow-x: scroll;
min-width: 1000px;
width: auto;
}
.myBlock {
overflow-y: hidden;
overflow-x: scroll;
margin-bottom: 10px;
}
.addedImg img {
width: 100%;
border-radius: 4px;
}
.deletImg {
position: absolute;
width: 25px;
height: 25px;
text-align: center;
line-height: 25px;
background: black;
color: white;
top: 10px;
right: 10px;
border-radius: 4px;
}
<div class="t">
</div>
If you run the jsfiddle above, and click on the FIRST delete button (black X), it finds the data-id of that element and then it should look into the CLOSEST input for that value/data-id and update that input value only.
But at the moment, when I click on the delete button, it updates all the inputs!
Can someone please advice oaths issue?
First, you have a typo in the HTML that you're appending to .t. The <div> after the <input> should be </div>.
The input is not contained in any parent unique to just the delete button. If you go up to the .myBlock DIV, you need to go to the next DIV after that and find the .input within it.
$('.t').append('<div class="row" style="margin-bottom:10px;"></div><div class="block block-strong myBlock"><div class="imgHolder"><div data-id="ASAS-HHH-UUU-TEY.jpg?42344444444" class="addedImg"><div class="deletImg" data-id="ASAS-HHH-UUU-TEY.jpg?42344444444">X</div><img class="tappableImg" src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Test-Logo.svg/783px-Test-Logo.svg.png" ></div></div></div><div><input type="text" class="input" value="22,44,66,99,ASAS-HHH-UUU-TEY.jpg?42344444444"/></div><div class="row" style="margin-bottom:10px;"></div><div class="block block-strong myBlock"><div class="imgHolder"><div data-id="ASAS-HHH-UUU-TEY.jpg?423423" class="addedImg"><div class="deletImg" data-id="ASAS-HHH-UUU-TEY.jpg?423423">X</div><img class="tappableImg" src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Test-Logo.svg/783px-Test-Logo.svg.png" ></div></div></div><div><input type="text" class="input" value="22,44,66,99,ASAS-HHH-UUU-TEY.jpg?423423"/></div>');
$(document).on('click', '.deletImg', function() {
var $this = (this);
var id = $(this).attr('data-id');
var inp = $($this).closest(".myBlock").next().find(".input").val();
inp = inp.replace(id + ',', '');
inp = inp.replace(id, '');
$($this).closest(".myBlock").next().find(".input").val(inp);
});
.addedImg {
width: 100px;
height: 100px;
position: relative;
display: inline-block;
margin-right: 12px;
}
.imgHolder {
height: auto;
overflow-y: hidden;
overflow-x: scroll;
min-width: 1000px;
width: auto;
}
.myBlock {
overflow-y: hidden;
overflow-x: scroll;
margin-bottom: 10px;
}
.addedImg img {
width: 100%;
border-radius: 4px;
}
.deletImg {
position: absolute;
width: 25px;
height: 25px;
text-align: center;
line-height: 25px;
background: black;
color: white;
top: 10px;
right: 10px;
border-radius: 4px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="t">
</div>

Filling in space between two objects dynamically

What is the best way to fill in the space between these two objects, essentially making one object that fills the space from the most left the a to the most right of b. I need a dynamic solution, since the the position of A and B will vary, sometimes B will be further left than A. I would like them to begin as two separate objects though. Also note only the space between the two do I wish to be filled, nothing outside.
function myFunction() {
var x = document.getElementById('a');
var y = document.getElementById('b');
x.style.right = "70%";
y.style.right = "50%";
var greenRect = x.getBoundingClientRect();
var blueRect = y.getBoundingClientRect();
}
h1 {
position: relative;
width: auto;
height: 50px;
background-color: beige;
}
h2 {
position: relative;
}
#a {
position: relative;
width: 50px;
height: 50px;
background-color: green;
float: right;
margin-left: -50px;
transform-origin: left;
border-radius: 50%;
}
#b {
position: relative;
width: 50px;
height: 50px;
background-color: green;
float: right;
border-radius: 50%;
}
<h1>
<div id='a'></div>
<div id='b'></div>
</h1>
<h2>
<button onclick='myFunction()'>PRESS</button>
</h2>
function myFunction() {
var x = document.getElementById('a');
var y = document.getElementById('b');
x.style.right = "70%";
y.style.right = "50%";
var greenRect = x.getBoundingClientRect();
var blueRect = y.getBoundingClientRect();
y.style.width = (blueRect.left - greenRect.left) + "px";
}
h1 {
position: relative;
width: auto;
height: 50px;
background-color: beige;
}
h2 {
position: relative;
}
#a {
position:relative;
width: 50px;
height: 50px;
background-color: green;
float: right;
margin-left: -50px;
transform-origin: left;
}
#b {
position:relative;
min-width: 50px;
height: 50px;
background-color: green;
float: right;
}
<h1>
<div id = 'a'></div>
<div id = 'b'></div>
</h1>
<h2>
<button onclick = 'myFunction()'>PRESS</button>
</h2>
You can use some background and box-shadow trick to visually fill the space between:
var x = document.getElementById('a');
var y = document.getElementById('b');
function myFunction() {
var r = Math.random()*100;
y.style.right=r+"%";
x.style.right=(Math.random()*(100 - r) + r)+"%";
}
h1 {
overflow:auto;
background-color: blue;
color:#fff;
text-align:center;
}
#a {
position: relative;
width: 50px;
height: 50px;
background-color: green;
float: right;
margin-left: -50px;
transform-origin: left;
border-radius: 50%;
box-shadow:-50vw 0 0 50vw beige;
}
#b {
position: relative;
width: 50px;
height: 50px;
background-color: green;
float: right;
border-radius: 50%;
box-shadow:50vw 0 0 50vw beige;
}
<h1>
<div id='a'>1</div>
<div id='b'>2</div>
</h1>
<h2>
<button onclick='myFunction()'>PRESS</button>
</h2>

JS: Function call over-rides my other 2 function calls?

I am trying to design a menu system for upgrading attack skills. For example, when you click upgrade "strike skill", you get a circle with 3 subset skills to upgrade to.
The Problem I am running into is my function calls. The last function of similar type, seems to over-ride the first 2 functions, so instead of filling all 3 circles in with their numbers, it instead just overwrites the last 2 instead. Why does it do this and how can I fix it?
The problem:
skills("skills", "attack1", "I");
skills("skills", "attack2", "II");
skills("skills", "attack3", "III");
Javascript Code:
function upgradeBar() {
menu("upgradeMenu", "systemMenu");
}
function menu(classID, id) {
var button = dom.el("skill"); // Apply DIV to THIS location
var x = document.createElement("div");
x.setAttribute("class", classID);
x.setAttribute("id", id);
button.appendChild(x);
function skills(classID, id, text){
var circle = dom.el("systemMenu"); // Apply DIV to THIS location
var x = document.createElement("div");
x.setAttribute("class", classID);
x.setAttribute("id", id);
circle.appendChild(x);
dom.setText("attack1", text);
}
skills("skills", "attack1", "I");
skills("skills", "attack2", "II");
skills("skills", "attack3", "III");
}
CSS Code:
.upgradeMenu {
width: 100px;
height: 100px;
background-color: white;
border: 1px solid black;
border-radius: 50px;
position: relative;
}
#attack1 {
width: 50px;
height: 50px;
background-color: white;
border: 1px solid black;
border-radius: 50px;
position: absolute;
top: 0;
left: 0;
margin-left: -10px;
}
#attack2 {
width: 50px;
height: 50px;
background-color: white;
border: 1px solid black;
border-radius: 50px;
position: absolute;
top: 0;
right: 0;
margin-right: -10px;
}
#attack3 {
width: 50px;
height: 50px;
background-color: white;
border: 1px solid black;
border-radius: 50px;
position: absolute;
bottom: 0;
margin-left: 23px;
margin-bottom: -10px;
}

Repeat a div number of times

how to repeat a div X times over html page,
lets say I want to set variance to declare times of repeat.
repeat this section 5 times, I assume it's with JS.
<div class="blackstrip">black</div>
<div class="bluestrip">
BLUE
<div class="whitestrip">WHITE strip</div>
</div>
I'm adding the css as it comes out strange look -
.blackstrip{
opacity: 0.8;
width: 600px;
height: 100px;
background-color: black;
background-position: center;
padding-top: 10px;
padding-bottom: 10px;
text-align: center;
margin: 0 auto;
}
.bluestrip{
opacity: 0.5;
width: 600px;
height: 300px;
background-color: blue;
background-repeat: none;
padding-bottom: 10px;
position: relative;
margin-top:50px;
margin: 20px auto;
}
.whitestrip{
opacity: 0.8;
width: 100px;
height:300px;
background-color: gray;
position: relative;
float: right;
padding-top: 10px;
padding-bottom: 10px;
}
Just use a for loop eg:
var amount = 5;
for (var i = 0; i < amount; i++){
var new_div = document.createElement("div");
new_div.className = "bluestrip";
document.body.appendChild(new_div);
console.log("This is repeat " + i);
}
Simple technic, huh?
https://jsfiddle.net/d15e9r6z/
Like Andreas said, it is more effective if you use
DocumentFragment to change multiple DOM's.

Categories

Resources