I need the country tab to remain, when the sites expends. I think a forEach loop is causing issues and I am not sure how to adress this, any help is greatly appreciated. I have data to display for over 50 countries and once the function works, my "country" tab will be Copy/pasted, I thought of using hard coded ID but its gonna take forever :(
HTML
<li class="country"><div class="list_container">
<button class="country_name">Algeria</button>
<ul class="site_list">
<div class="site_container">
<li class="site">Bejaja</li>
<img src="imgs/Algeria.jpg" alt="">
</div>
<div class="site_container">
<li class="site">Constantine</li>
<img src="imgs/Algeria.jpg" alt="">
</div>
<div class="site_container">
<li class="site">Jijel</li>
<img src="imgs/Algeria.jpg" alt="">
</div>
<div class="site_container">
<li class="site">Setif</li>
<img src="imgs/Algeria.jpg" alt="">
</div>
</ul>
</div>
</li>
JS
const country = document.querySelectorAll('.list_container');
// country selection
country.forEach((item) => {
const btn = item.querySelector('.country_name');
btn.addEventListener('click', () => {
country.forEach((site) => {
if(site !== item) {
site.classList.remove('show_sites')
}
})
item.classList.toggle('show_sites')
})
})
// site selection
const siteGroup = document.querySelectorAll('.site_container');
siteGroup.forEach((item) => {
console.log(item);
siteBtn = item.querySelector('.site_link');
console.log(siteBtn)
siteBtn.addEventListener('click', () => {
siteGroup.forEach(site => {
console.log(site)
if(site !== item) {
site.classList.remove('display_site')
}
})
item.classList.toggle('display_site')
})
})```
CSS
.country_list {
height: 100%;
width: 100%;
margin: 0;
padding: 1em;
}
.country {
list-style-type: none;
padding: 0em;
margin: 0.5em;
}
.country_name {
text-decoration:none;
background-color: rgba(114, 114,114, 0.5);
padding: 0.3em 1em;
color: white;
border-radius: 15px;
z-index: 3;
position: relative;
}
.list_container {
height: 2em;
width: 80%;;
overflow: hidden;
}
.site_list {
list-style-type: none;
background-color: rgba(255,255,255, 0.5);
border-radius: 5px;
width: 50em;
z-index: 4;
padding: 0.3em;
overflow: hidden;
}
.site_container {
height: 1.3em;
overflow: hidden;
}
.display_site {
height: 3.5em;
}
.site {
padding: 0.2em;
}
.show_sites {
height: 30em;
}
Related
I have an automatic sliding carousel which is working fine except that when it reach the last image then it just freeze on the last image instead of auto slide to the first image. I just can't remake my javascript code alone. Strange but autosliding to the first image was working a few months ago. I had nothing change to the code but seems after last updates of chrome its just not working correctly neither on pc neither on mobile devices. Here is my javascript code:
const carousels = document.querySelectorAll('.img-carousel');
const prevBtn = document.querySelectorAll('.prev');
const nextBtn = document.querySelectorAll('.next');
let carsouselImages = document.querySelectorAll('.img-carousel div');
//Next Carousel
carousels.forEach((carousel, index)=>{
const nextCarousel = () => {
if(carsouselImages[carsouselImages.length - 1]) {
carousel.scrollTo(0, 0);
}
carousel.scrollBy(300, 0);
};
nextBtn[index].addEventListener('click', e => {
nextCarousel();
});
//Prev Carousel
const prevCarousel = () => {
if(carsouselImages[0]) {
carousel.scrollTo(4800,0);
}
carousel.scrollBy(-300, 0);
};
prevBtn[index].addEventListener('click', e => {
prevCarousel();
});
// Auto carousel
const auto = true; // Auto scroll
const intervalTime = 5000;
let sliderInterval;
if (auto) {
sliderInterval = setInterval(nextCarousel, intervalTime);
};
carousel.addEventListener('mouseover', (stopInterval) => {
clearInterval(sliderInterval);
});
carousel.addEventListener('mouseleave', (startInterval) => {
if (auto) {
sliderInterval = setInterval(nextCarousel, intervalTime);
}
});
//for mobile events
carousel.addEventListener('touchstart', (stopIntervalT) => {
clearInterval(sliderInterval);
});
carousel.addEventListener('touchend', (startIntervalT) => {
if (auto) {
sliderInterval = setInterval(nextCarousel, intervalTime);
}
});
//Debounce
var previousCall;
window.addEventListener('resize', () => {
if (previousCall >= 0) {
clearTimeout(previousCall);
}
});
});
Here are css and html codes if needed:
/** img-carousel **/
#imgages-carousel {
display: grid;
align-items: center;
justify-items: center;
padding: 40px 0px;
}
#imgages-carousel1 {
display: grid;
align-items: center;
justify-items: center;
padding: 40px 0px;
}
.img-carousel-container {
width: 800px;
position: relative;
}
.img-carousel {
display: flex;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
padding-bottom: 5px;
}
.img-carousel div {
flex: none;
scroll-snap-align: start;
width: 800px;
position: relative;
}
.img-carousel div img {
display: block;
width: 100%;
object-fit: cover;
}
.img-carousel div p {
position: absolute;
top: 0;
right: 10px;
background: rgba(0,0,0,0.5);
color: #fff;
padding: 5px;
border-radius: 10px;
}
.img-carousel-container button {
position: absolute;
top: calc(50% - 15px);
transform: translateY(-50%);
border: none;
background-color: rgba(255, 193, 7, 0.7);
color: #000;
cursor: pointer;
padding: 10px 15px;
border-radius: 50%;
outline: none;
opacity: 0;
transition: all ease-in-out 0.5s;
}
.prev {
left: 10px;
}
.next {
right: 10px;
}
.img-carousel-container:hover button {
opacity: 1;
}
.img-carousel-container button:hover {
background-color: #ffc107;
}
/** custom scrollbar **/
.img-carousel::-webkit-scrollbar {
width: 10px;
height: 10px;
}
.img-carousel::-webkit-scrollbar-thumb {
background: #ffc107;
border-radius: 10px;
}
.img-carousel::-webkit-scrollbar-track {
background: transparent;
}
.img-carousel-container:hover .img-carousel::-webkit-scrollbar-thumb {
visibility: visible;
}
#media screen and (max-width: 800px) {
.img-carousel-container {
width: 100%;
}
.img-carousel div {
width: 100%;
}
}
html:
<!-- section images carousel -->
<section id="imgages-carousel">
<div class="img-carousel-container">
<div class="img-carousel">
<div>
<img src="https://source.unsplash.com/9Nok_iZEgLk/800x450">
<p>1/6</p>
</div>
<div>
<img src="https://source.unsplash.com/4v7ubW7jz1Q/800x450">
<p>2/6</p>
</div>
<div>
<img src="https://source.unsplash.com/rtCujH697DU/800x450">
<p>3/6</p>
</div>
<div>
<img src="https://source.unsplash.com/ELv8fvulR0g/800x450">
<p>4/6</p>
</div>
<div>
<img src="https://source.unsplash.com/LoPGu6By90k/800x450">
<p>5/6</p>
</div>
<div>
<img src="https://source.unsplash.com/Ndz3w6MCeWc/800x450">
<p>6/6</p>
</div>
</div>
<button class="prev"><i class="fas fa-chevron-left fa-2x"></i></button>
<button class="next"><i class="fas fa-chevron-right fa-2x"></i></button>
</div>
</section>
<section id="imgages-carousel1">
<div class="img-carousel-container">
<div class="img-carousel">
<div>
<img src="https://source.unsplash.com/9Nok_iZEgLk/800x450">
<p>1/6</p>
</div>
<div>
<img src="https://source.unsplash.com/4v7ubW7jz1Q/800x450">
<p>2/6</p>
</div>
<div>
<img src="https://source.unsplash.com/rtCujH697DU/800x450">
<p>3/6</p>
</div>
<div>
<img src="https://source.unsplash.com/ELv8fvulR0g/800x450">
<p>4/6</p>
</div>
<div>
<img src="https://source.unsplash.com/LoPGu6By90k/800x450">
<p>5/6</p>
</div>
<div>
<img src="https://source.unsplash.com/Ndz3w6MCeWc/800x450">
<p>6/6</p>
</div>
</div>
<button class="prev"><i class="fas fa-chevron-left fa-2x "></i></button>
<button class="next"><i class="fas fa-chevron-right fa-2x "></i></button>
</div>
</section>
I have 2 collapsible nested inside each other
When clicking on Test 7, it closes both the BRAND and test 7 accordions
I have this JavaScript code where "mobile-nav_accordion-contentbox" is the className of the parent element (BRAND)
const mobile_navbar_accordion = document.getElementsByClassName("mobile-nav_accordion-contentbox");
for (let i = 0; i < mobile_navbar_accordion.length; i++) {
let checkbox = mobile_navbar_accordion[i];
checkbox.addEventListener("click", (e) => {
e.currentTarget.classList.toggle("active");
})
}
Solutions I tried:
Adding e.stopPropagation(); inside the click event
Replacing e.currentTarget with e.target but the click event is never working on the parent element, I tested this with the following code
if (e.target == e.currentTarget) console.log("clicked on parent");
else console.log("clicked on children")
I also tried
if(e.target == this) console.log("clicked on parent")
else console.log("clicked on children")
In both cases it returned "clicked on children"
I replaced e.currentTarget with this
this.classList.toggle('..')
And in the console I received this error
pointer-events: none;
In css for the children box, also for children title + content separately but it caused 2 issues, first stopping (Test 5, Test 6) from firing the link event. However it still didn't stop closing the parent when clicking on children box or children elements
const mobile_navbar_accordion = document.getElementsByClassName("mobile-nav_accordion-contentbox");
const mobile_navbar_accordion_grandchildren = document.getElementsByClassName("mobile-nav_accordion-contentbox__grandchildren");
for (let i = 0; i < mobile_navbar_accordion.length; i++) {
let checkbox = mobile_navbar_accordion[i];
checkbox.addEventListener("click", (e) =>
e.currentTarget.classList.toggle("active")
)
}
for (let i = 0; i < mobile_navbar_accordion_grandchildren.length; i++) {
let checkbox = mobile_navbar_accordion_grandchildren[i];
checkbox.addEventListener("click", (e) =>
e.currentTarget.classList.toggle("active")
)
}
ul{
list-style: none;
}
a{
color: black;
text-decoration: none;
padding: 10px 0;
}
.mobile-nav_accordion,
.mobile-nav_accordion__grandchildren{
width: 600px;
}
.mobile-nav_accordion .mobile-nav_accordion-contentbox,
.mobile-nav_box {
position: relative;
margin-bottom: 1.5rem;
width: 100%;
}
.mobile-nav_accordion-contentbox__grandchildren {
position: relative;
width: 100%;
}
.mobile-nav_accordion .mobile-nav_accordion-contentbox .mobile-nav_accordion-contentbox-label,
.mobile-nav_accordion__grandchildren .mobile-nav_accordion-contentbox__grandchildren .mobile-nav_accordion-contentbox-label__grandchildren{
position: relative;
width: 100%;
padding: 20px 0;
}
/* For + sign after each collapsible title */
.mobile-nav_accordion .mobile-nav_accordion-contentbox .mobile-nav_accordion-contentbox-label::before,
.mobile-nav_accordion__grandchildren .mobile-nav_accordion-contentbox__grandchildren .mobile-nav_accordion-contentbox-label__grandchildren::before
{
content: "+";
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
font-size: 18px;
}
.mobile-nav_accordion .mobile-nav_accordion-contentbox.active .mobile-nav_accordion-contentbox-label::before,
.mobile-nav_accordion__grandchildren .mobile-nav_accordion-contentbox__grandchildren.active .mobile-nav_accordion-contentbox-label__grandchildren::before
{
content: "-";
}
.mobile-nav_accordion .mobile-nav_accordion-contentbox .mobile-nav_accordion-contentbox-content,
.mobile-nav_accordion__grandchildren .mobile-nav_accordion-contentbox__grandchildren .mobile-nav_accordion-contentbox-content__grandchildren
{
position: relative;
height: 0;
overflow: hidden;
padding: 0 0.5rem;
transition-property: all;
transition-duration: 0.1s !important;
transition-timing-function: linear;
}
.mobile-nav_accordion-contentbox-content__grandchildren{
padding-left: 1rem;
}
.mobile-nav_accordion .mobile-nav_accordion-contentbox.active .mobile-nav_accordion-contentbox-content,
.mobile-nav_accordion__grandchildren .mobile-nav_accordion-contentbox__grandchildren.active .mobile-nav_accordion-contentbox-content__grandchildren{
height: max-content;
padding: 0.5rem;
}
.mobile-nav__links,
.mobile-nav_accordion-contentbox-label__grandchildren h5{
font-size: 13px;
margin-top: 1rem;
color: #3c3c3c;
}
<div class="mobile-nav_accordion">
<div class="mobile-nav_accordion-contentbox">
<label class="mobile-nav_accordion-contentbox-label">
BRAND
</label>
<div class="mobile-nav_accordion-contentbox-content">
<ul class="navigation-item-children--top-level">
<li>
<a class="mobile-nav__links" href="#">
<span>
Hello World 1
</span>
</a>
<!-- HERE GOES THE GRANDCHILDS -->
<div class="mobile-nav_accordion__grandchildren">
<div class="mobile-nav_accordion-contentbox__grandchildren">
<label class="mobile-nav_accordion-contentbox-label__grandchildren">
Test 1
</label>
<div class="mobile-nav_accordion-contentbox-content__grandchildren">
<ul>
<li>
<a class="mobile-nav__links" href="#">
Hello world
</a>
</li>
</ul>
</div>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
I think you can basically change your script to the provided version below.
const mobile_navbar_accordion = document.getElementsByClassName("mobile-nav_accordion-contentbox-label");
const mobile_navbar_accordion_grandchildren = document.getElementsByClassName("mobile-nav_accordion-contentbox-label__grandchildren");
for (let i = 0; i < mobile_navbar_accordion.length; i++) {
let checkbox = mobile_navbar_accordion[i];
checkbox.addEventListener("click", function(e){
// getting the parent element to add active
e.currentTarget.closest('.mobile-nav_accordion-contentbox').classList.toggle("active")
})
}
for (let i = 0; i < mobile_navbar_accordion_grandchildren.length; i++) {
let checkbox = mobile_navbar_accordion_grandchildren[i];
checkbox.addEventListener("click", function(e){
e.stopPropagation();
// getting the parent element to add active
e.currentTarget.closest('.mobile-nav_accordion-contentbox__grandchildren').classList.toggle("active")
} )
}
ul{
list-style: none;
}
a{
color: black;
text-decoration: none;
padding: 10px 0;
}
.mobile-nav_accordion,
.mobile-nav_accordion__grandchildren{
width: 600px;
}
.mobile-nav_accordion .mobile-nav_accordion-contentbox,
.mobile-nav_box {
position: relative;
margin-bottom: 1.5rem;
width: 100%;
}
.mobile-nav_accordion-contentbox__grandchildren {
position: relative;
width: 100%;
}
.mobile-nav_accordion .mobile-nav_accordion-contentbox .mobile-nav_accordion-contentbox-label,
.mobile-nav_accordion__grandchildren .mobile-nav_accordion-contentbox__grandchildren .mobile-nav_accordion-contentbox-label__grandchildren{
position: relative;
width: 100%;
padding: 20px 0;
}
/* For + sign after each collapsible title */
.mobile-nav_accordion .mobile-nav_accordion-contentbox .mobile-nav_accordion-contentbox-label::before,
.mobile-nav_accordion__grandchildren .mobile-nav_accordion-contentbox__grandchildren .mobile-nav_accordion-contentbox-label__grandchildren::before
{
content: "+";
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
font-size: 18px;
}
.mobile-nav_accordion .mobile-nav_accordion-contentbox.active .mobile-nav_accordion-contentbox-label::before,
.mobile-nav_accordion__grandchildren .mobile-nav_accordion-contentbox__grandchildren.active .mobile-nav_accordion-contentbox-label__grandchildren::before
{
content: "-";
}
.mobile-nav_accordion .mobile-nav_accordion-contentbox .mobile-nav_accordion-contentbox-content,
.mobile-nav_accordion__grandchildren .mobile-nav_accordion-contentbox__grandchildren .mobile-nav_accordion-contentbox-content__grandchildren
{
position: relative;
height: 0;
overflow: hidden;
padding: 0 0.5rem;
transition-property: all;
transition-duration: 0.1s !important;
transition-timing-function: linear;
}
.mobile-nav_accordion-contentbox-content__grandchildren{
padding-left: 1rem;
}
.mobile-nav_accordion .mobile-nav_accordion-contentbox.active .mobile-nav_accordion-contentbox-content,
.mobile-nav_accordion__grandchildren .mobile-nav_accordion-contentbox__grandchildren.active .mobile-nav_accordion-contentbox-content__grandchildren{
height: max-content;
padding: 0.5rem;
}
.mobile-nav__links,
.mobile-nav_accordion-contentbox-label__grandchildren h5{
font-size: 13px;
margin-top: 1rem;
color: #3c3c3c;
}
<div class="mobile-nav_accordion">
<div class="mobile-nav_accordion-contentbox">
<label class="mobile-nav_accordion-contentbox-label">
BRAND
</label>
<div class="mobile-nav_accordion-contentbox-content">
<ul class="navigation-item-children--top-level">
<li>
<a class="mobile-nav__links" href="#">
<span>
Hello World 1
</span>
</a>
<!-- HERE GOES THE GRANDCHILDS -->
<div class="mobile-nav_accordion__grandchildren">
<div class="mobile-nav_accordion-contentbox__grandchildren">
<label class="mobile-nav_accordion-contentbox-label__grandchildren">
Test 1
</label>
<div class="mobile-nav_accordion-contentbox-content__grandchildren">
<ul>
<li>
<a class="mobile-nav__links" href="#">
Hello world
</a>
</li>
</ul>
</div>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
I am confused. I want two products to be selected. These products will be open by clicking the button. The selection will be made on the screen that opens. And the selected product will replace the button clicked.
I can show the products by clicking the button. I even got the result I wanted as text with jquery. But I used <select> <option> for this. There will be no drop-down list and only one will be selected. The selected image will replace the clicked area. I couldn't :(
$(document).ready(function() {
$(".showbutton, .showbutton img").click(function(event) {
var buttonName = $(this).closest('div').attr('id');
var buttonNo = buttonName.slice(4);
var boxName = "#box" + buttonNo;
$(boxName).fadeIn(300);
});
$(".closebtn").click(function() {
$(".box").fadeOut(200);
});
$(".box").click(function() {
$(".box").fadeOut(200);
});
$(".innerbox").click(function() {
event.preventDefault();
event.stopPropagation();
});
});
div.showbutton {}
div.showbutton:hover {}
.box {
position: fixed;
display: none;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
.innerbox {
overflow: scroll;
width: 80%;
height: 80%;
margin: 5% auto;
background-color: white;
border: 3px solid gray;
padding: 10px;
box-shadow: -10px -10px 25px #ccc;
}
#box1 {
position: fixed;
display: none;
width: 400px;
height: 400px;
top: 0;
left: 0;
}
#box2 {
position: fixed;
display: none;
width: 400px;
height: 400px;
top: 0;
left: 0;
}
.closebutton {
width: 20%;
float: right;
cursor: pointer;
}
.closebtn {
text-align: right;
font-size: 20px;
font-weight: bold;
}
.clear {
clear: both;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form name="builder" action="" method="POST">
<div class="showbutton" id="link1">
click for first items
</div>
<div id="box1" class="box">
<div class="innerbox">
<div class="closebutton">
<div class="closebtn">X</div>
</div>
- item1.png - item2.png - item3.png
</div>
</div>
<div class="showbutton" id="link1">
click for second items
</div>
<div id="box1" class="box">
<div class="innerbox">
<div class="closebutton">
<div class="closebtn">X</div>
</div>
- item1.png - item2.png - item3.png
</div>
</div>
JSFIDDLE example of my codes: https://jsfiddle.net/j5fqhat6/
You can add data attribute to your kutu div this will help us to identify from where click event has been occurred .So, whenever your gosterButonu is been clicked you can use this data-id to add selected images text to your gosterButonu div.
Demo Code :
$(document).ready(function() {
$(".gosterButonu, .gosterButonu img").click(function(event) {
var butonAdi = $(this).attr('id');
console.log(butonAdi)
//if on click of button you want to remove active class
// $("div[data-id="+butonAdi+"]").find("li").removeClass("active")
$("div[data-id=" + butonAdi + "]").fadeIn(300);
});
$(".kapatButonu").click(function() {
var data_id = $(this).closest(".kutu").data("id");
$("#" + data_id).text($(this).closest(".icKutu").find("li.active").text())
$(".kutu").fadeOut(200);
});
$(".kutu").click(function() {
$(".kutu").fadeOut(200);
});
$(".icKutu").click(function() {
event.preventDefault();
event.stopPropagation();
});
//on click of li
$(".images li").click(function() {
//remove active class from other lis
$(this).closest(".images").find("li").not(this).removeClass("active")
//add active class to li which is clicked
$(this).addClass("active");
})
});
div.gosterButonu {}
div.gosterButonu:hover {}
.kutu {
position: fixed;
display: none;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
.icKutu {
overflow: scroll;
width: 80%;
height: 80%;
margin: 5% auto;
background-color: white;
border: 3px solid gray;
padding: 10px;
box-shadow: -10px -10px 25px #ccc;
}
#kutu1 {
position: fixed;
display: none;
width: 400px;
height: 400px;
top: 0;
left: 0;
}
#kutu2 {
position: fixed;
display: none;
width: 400px;
height: 400px;
top: 0;
left: 0;
}
.kapatButonuCerceve {
width: 20%;
float: right;
cursor: pointer;
}
.kapatButonu {
text-align: right;
font-size: 20px;
font-weight: bold;
}
.clear {
clear: both;
}
ul li {
list-style-type: none
}
.active {
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form name="builder" action="" method="POST">
<div class="gosterButonu" id="link1">
clickfor first items
</div>
<!--added data-id which matched with the div above-->
<div id="kutu1" data-id="link1" class="kutu">
<div class="icKutu">
<div class="kapatButonuCerceve">
<div class="kapatButonu">X</div>
</div>
<div class="clear"></div>
<!--added ul li-->
<ul class="images">
<li>- item1.png</li>
<li> - item2.png </li>
<li>- item3.png</li>
</ul>
</div>
</div>
<div class="gosterButonu" id="link2">
click for second items
</div>
<!--added data-id which matched with the div above-->
<div id="kutu2" data-id="link2" class="kutu">
<div class="icKutu">
<div class="kapatButonuCerceve">
<div class="kapatButonu">X</div>
</div>
<div class="clear"></div>
<ul class="images">
<li>- item1.png</li>
<li> - item2.png </li>
<li>- item3.png</li>
</ul>
</div>
</div>
I am stuck in a logical problem.
I have an array where i am stacking items with array.push() where came up from a user's Input.
Problem is now:
How can i print these items to the DOM? ATM i am doing this,
function getInput(operator, description, value) {
// SAVE IN INCOME IF "+" IS CHOOSEN (DEFAULT)
if (addType.value == 'inc') {
let op = incomeArr['operator'] = operator;
let des = incomeArr['description'] = description;
let val = incomeArr['value'] = value;
incomeArr.push([op, des, val]);
return incomeArr;
}
}
Creating a associative array in the getInput();
First attempt to print this data into the DOM looked like this:
function printToDOM(item) {
// every function call should run this once to update the UI
const incomeList = document.querySelector('.income__list');
const expenseList = document.querySelector('.expenses__list');
let incomeItemSpan = `<span> ${item.description}: ${item.value} </span></br>`;
let expenseItemSpan = `<span> ${item.description}: ${item.value} </span> </br>`;
for (var i = 0; i < expenseArr.length; i++) {
incomeItemSpan;
incomeList.append(incomeItemSpan);
}
}
My problem here is that my forLoop index condition is messing up because of the "everytime function call" the value which is printed out will be printed twice in the next function call of this. the index start again at 0 and even with a out of function loop counter this will not work.
[![gave-input][1]][1]
So the next attempt was:
function printToDOM(item) {
// every function call should run this once to update the UI
const incomeList = document.querySelector('.income__list');
const expenseList = document.querySelector('.expenses__list');
let incomeItemSpan = `<span> ${item.description}: ${item.value} </span></br>`;
let expenseItemSpan = `<span> ${item.description}: ${item.value} </span> </br>`;
incomeArr.forEach(() => {
incomeList.innerHTML = incomeItemSpan;
});
}
i tried it with a forEach and the problem here is, i have absolutely no idea how to print out the incomeItemSpan without a innerHTML. I want a list of items in the DOM which are stacked from top down, every line is a new item from the array like i would use item.append(), but HTML wont work in a append().
How can i do this?
/* TODO:
- Add Eventlistener for Submit a +/- Value
- if + {add 1. into INCOME section} + Set INCOME in header to the amount
of all incomes added
if - {same like if+ just for -}
- create a update DOM function to update the visualisation of the calculations
- INCOME AND EXPENSES should be a Array
- add a prototype function to remove entrys from INCOME and EXPENSES, use
indexOf to get the index item and remove with array.splice().
- calc every expense with INCOME to get a % value of how much this entry is
% related to the max INCOME
*/
// VARS:
let addType = document.querySelector('.add__type');
let description = document.querySelector('.add__description');
let addValue = document.querySelector('.add__value');
let incomeArr = [];
let expenseArr = [];
// EVENTLISTENER Constructor:
function EventListner(selector, listner, fnt) {
this.selector = selector;
this.listner = listner;
this.fnt = fnt;
document.querySelector(selector).addEventListener(listner, fnt);
};
// getInput VALUES FROM USER Constructor:
function getInput(operator, description, value) {
// SAVE IN INCOME IF "+" IS CHOOSEN (DEFAULT)
if (addType.value == 'inc') {
let op = incomeArr['operator'] = operator;
let des = incomeArr['description'] = description;
let val = incomeArr['value'] = value;
incomeArr.push([op, des, val]);
// TODO: WHAT AFTER SAVING?
return incomeArr;
}
// SAVE IN EXPENSE IF "-" IS CHOOSEN
if (addType.value == 'exp') {
let op = expenseArr['operator'] = operator;
let des = expenseArr['description'] = description;
let val = expenseArr['value'] = value;
expenseArr.push([op, des, val]);
// TODO: WHAT AFTER SAVING?
return expenseArr;
}
};
// STUCK AS FUCK!
function printToDOM(item) {
// every function call should run this once to update the UI
const incomeList = document.querySelector('.income__list');
const expenseList = document.querySelector('.expenses__list');
let incomeItemSpan = `<span> ${item.description}: ${item.value} </span></br>`;
let expenseItemSpan = `<span> ${item.description}: ${item.value} </span> </br>`;
incomeArr.forEach(() => {
incomeList.innerHTML = incomeItemSpan;
});
// for (var i = 0; i < incomeArr.length; i++) {
// console.log([i]);
// incomeItemSpan;
// incomeList.append(incomeItemSpan);
// }
// console.log(incomeItemSpan);
//
// incomeList.append(expenseArr);
// incomeArr.toString();
// expenseArr.toString();
// incomeList.innerHTML = incomeItemSpan;
};
const main = (function() {
// EVENTLISTENERS
const clickListener = new EventListner('.add__btn', 'click', () => {
if (description.value == '' || addValue.value == '') {
// MAKE SURE DESCRIPTION AND VALUE IS NOT EMPTY
alert('description and value can\'t be empty');
return;
}
getInput(addType.value, description.value, addValue.value);
});
const enterKeyListener = new EventListner('.add__value', 'keypress', (e) => {
let testArray = [];
for (var i = 0; i < testArray.length; i++) {
testArray[i] = [i];
console.log(testArray[i]);
}
testArray.push('item');
if (e.keyCode == 13) {
if (description.value == '' || addValue.value == '') {
// MAKE SURE DESCRIPTION AND VALUE IS NOT EMPTY
alert('description and value can\'t be empty');
return;
}
// ON ENTER SAVE VALUES IN AN ARRAY
// IF PLUS INTO incomeArr, ON MINUS INTO expenseArr
// getInput(addType.value, description.value, addValue.value);
printToDOM(getInput(addType.value, description.value, addValue.value));
}
});
}());
//
/**********************************************
*** GENERAL
**********************************************/
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.clearfix::after {
content: "";
display: table;
clear: both;
}
body {
color: #555;
font-family: Open Sans;
font-size: 16px;
position: relative;
height: 100vh;
font-weight: 400;
}
.right { float: right; }
.red { color: #FF5049 !important; }
.red-focus:focus { border: 1px solid #FF5049 !important; }
/**********************************************
*** TOP PART
**********************************************/
.top {
height: 40vh;
background-image: linear-gradient(rgba(0, 0, 0, 0.35), rgba(0, 0, 0, 0.35)), url(back.png);
background-size: cover;
background-position: center;
position: relative;
}
.budget {
position: absolute;
width: 350px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #fff;
}
.budget__title {
font-size: 18px;
text-align: center;
margin-bottom: 10px;
font-weight: 300;
}
.budget__value {
font-weight: 300;
font-size: 46px;
text-align: center;
margin-bottom: 25px;
letter-spacing: 2px;
}
.budget__income,
.budget__expenses {
padding: 12px;
text-transform: uppercase;
}
.budget__income {
margin-bottom: 10px;
background-color: #28B9B5;
}
.budget__expenses {
background-color: #FF5049;
}
.budget__income--text,
.budget__expenses--text {
float: left;
font-size: 13px;
color: #444;
margin-top: 2px;
}
.budget__income--value,
.budget__expenses--value {
letter-spacing: 1px;
float: left;
}
.budget__income--percentage,
.budget__expenses--percentage {
float: left;
width: 34px;
font-size: 11px;
padding: 3px 0;
margin-left: 10px;
}
.budget__expenses--percentage {
background-color: rgba(255, 255, 255, 0.2);
text-align: center;
border-radius: 3px;
}
/**********************************************
*** BOTTOM PART
**********************************************/
/***** FORM *****/
.add {
padding: 14px;
border-bottom: 1px solid #e7e7e7;
background-color: #f7f7f7;
}
.add__container {
margin: 0 auto;
text-align: center;
}
.add__type {
width: 55px;
border: 1px solid #e7e7e7;
height: 44px;
font-size: 18px;
color: inherit;
background-color: #fff;
margin-right: 10px;
font-weight: 300;
transition: border 0.3s;
}
.add__description,
.add__value {
border: 1px solid #e7e7e7;
background-color: #fff;
color: inherit;
font-family: inherit;
font-size: 14px;
padding: 12px 15px;
margin-right: 10px;
border-radius: 5px;
transition: border 0.3s;
}
.add__description { width: 400px;}
.add__value { width: 100px;}
.add__btn {
font-size: 35px;
background: none;
border: none;
color: #28B9B5;
cursor: pointer;
display: inline-block;
vertical-align: middle;
line-height: 1.1;
margin-left: 10px;
}
.add__btn:active { transform: translateY(2px); }
.add__type:focus,
.add__description:focus,
.add__value:focus {
outline: none;
border: 1px solid #28B9B5;
}
.add__btn:focus { outline: none; }
/***** LISTS *****/
.container {
width: 1000px;
margin: 60px auto;
}
.income {
float: left;
width: 475px;
margin-right: 50px;
}
.expenses {
float: left;
width: 475px;
}
h2 {
text-transform: uppercase;
font-size: 18px;
font-weight: 400;
margin-bottom: 15px;
}
.icome__title { color: #28B9B5; }
.expenses__title { color: #FF5049; }
.item {
padding: 13px;
border-bottom: 1px solid #e7e7e7;
}
.item:first-child { border-top: 1px solid #e7e7e7; }
.item:nth-child(even) { background-color: #f7f7f7; }
.item__description {
float: left;
}
.item__value {
float: left;
transition: transform 0.3s;
}
.item__percentage {
float: left;
margin-left: 20px;
transition: transform 0.3s;
font-size: 11px;
background-color: #FFDAD9;
padding: 3px;
border-radius: 3px;
width: 32px;
text-align: center;
}
.income .item__value,
.income .item__delete--btn {
color: #28B9B5;
}
.expenses .item__value,
.expenses .item__percentage,
.expenses .item__delete--btn {
color: #FF5049;
}
.item__delete {
float: left;
}
.item__delete--btn {
font-size: 22px;
background: none;
border: none;
cursor: pointer;
display: inline-block;
vertical-align: middle;
line-height: 1;
display: none;
}
.item__delete--btn:focus { outline: none; }
.item__delete--btn:active { transform: translateY(2px); }
.item:hover .item__delete--btn { display: block; }
.item:hover .item__value { transform: translateX(-20px); }
.item:hover .item__percentage { transform: translateX(-20px); }
.unpaid {
background-color: #FFDAD9 !important;
cursor: pointer;
color: #FF5049;
}
.unpaid .item__percentage { box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.1); }
.unpaid:hover .item__description { font-weight: 900; }
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:100,300,400,600" rel="stylesheet" type="text/css">
<link href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet" type="text/css">
<link type="text/css" rel="stylesheet" href="style.css">
<title>Budgety</title>
</head>
<body>
<div class="top">
<div class="budget">
<div class="budget__title">
Available Budget in <span class="budget__title--month">%Month%</span>:
</div>
<div class="budget__value">+ 0</div>
<div class="budget__income clearfix">
<div class="budget__income--text">Income</div>
<div class="right">
<div class="budget__income--value">+ 0</div>
<div class="budget__income--percentage"> </div>
</div>
</div>
<div class="budget__expenses clearfix">
<div class="budget__expenses--text">Expenses</div>
<div class="right clearfix">
<div class="budget__expenses--value">- 0</div>
<div class="budget__expenses--percentage">0%</div>
</div>
</div>
</div>
</div>
<div class="bottom">
<div class="add">
<div class="add__container">
<select class="add__type">
<option value="inc" selected>+</option>
<option value="exp">-</option>
</select>
<input type="text" class="add__description" placeholder="Add description">
<input type="number" class="add__value" placeholder="Value">
<button class="add__btn"><i class="ion-ios-checkmark-outline"></i></button>
</div>
</div>
<div class="container clearfix">
<div class="income">
<h2 class="icome__title">Income</h2>
<div class="income__list">
<!-- <div class="item clearfix" id="income-0">
<div class="item__description"></div>
<div class="right clearfix">
<div class="item__value"></div>
<div class="item__delete">
<button class="item__delete--btn"><i class="ion-ios-close-outline"></i></button>
</div>
</div>
</div>
<div class="item clearfix" id="income-1">
<div class="item__description">Sold car</div>
<div class="right clearfix">
<div class="item__value">+ 1,500.00</div>
<div class="item__delete">
<button class="item__delete--btn"><i class="ion-ios-close-outline"></i></button>
</div>
</div>
</div> -->
</div>
</div>
<div class="expenses">
<h2 class="expenses__title">Expenses</h2>
<div class="expenses__list">
<!--
<div class="item clearfix" id="expense-0">
<div class="item__description">Apartment rent</div>
<div class="right clearfix">
<div class="item__value">- 900.00</div>
<div class="item__percentage">21%</div>
<div class="item__delete">
<button class="item__delete--btn"><i class="ion-ios-close-outline"></i></button>
</div>
</div>
</div>
<div class="item clearfix" id="expense-1">
<div class="item__description">Grocery shopping</div>
<div class="right clearfix">
<div class="item__value">- 435.28</div>
<div class="item__percentage">10%</div>
<div class="item__delete">
<button class="item__delete--btn"><i class="ion-ios-close-outline"></i></button>
</div>
</div>
</div>
-->
</div>
</div>
</div>
</div>
<script src="app.js"></script>
</body>
</html>
Is that exactly what you're looking for?
const arr = new Array();
function addList() {
const el = document.querySelector("input[name=user]")
const val = el.value
arr.push(val);
el.value = null;
return false;
}
function showList() {
for (let i = 0; i < arr.length; i++) {
const listElement = document.createElement("li");
listElement.textContent = arr[i]
document.body.appendChild(listElement);
}
}
<form onsubmit="return addList()">
<input type="text" name="user">
<button>Add list item</button>
</form><br>
<button class="showList" onclick="showList()">Show list</button>
<ul class="list"></ul>
For creating a list of items, create a ordered/unordered list then append each item to this list in forEach and finally set the html to ordered//unordered list.
Example:
var ol=$('<ol></ol>');
incomeArr.forEach(() => {
ol.append($('<li></li>').text(`${item.description}: ${item.value}`));
});
$('#display').html(ol);
I am trying to build a slide show from scratch. I want to use only javascript, no jquery.
As of now, when I click on the 'prev' button, it only moves 50px to left just once. How do I make it move 50px every time on click of 'prev' button.
Javascript Code :-
function prev() {
document.getElementById('slide').style.left = document.getElementById('slide').style.left - 50;
}
function nxt() {
document.getElementById('slide').style.left = document.getElementById('slide').style.left + 50;
}
HTML :-
<div class="slideshow-wrapper">
<h1>Slide Show</h1>
<div class="slideshow-outside-container">
<div class="slideshow-inner-container" id="slide">
<ul>
<li class="slide slide1"></li>
<li class="slide slide2"></li>
<li class="slide slide3"></li>
<li class="slide slide4"></li>
<li class="slide slide5"></li>
<li class="slide slide1"></li>
<li class="slide slide2"></li>
<li class="slide slide3"></li>
<li class="slide slide4"></li>
<li class="slide slide5"></li>
</ul>
</div>
</div>
<div class="slideshow-controls-wrapper">
<button onclick="prev()" class="prev">Prev</button>
<button onclick="nxt()" class="nxt">Next</button>
</div>
</div>
CSS:-
body{
font-family: 'tahoma', sans-serif;
font-size: 14px;
color: #999999;
background-color: #cccccc;
}
ul{
margin: 0;
padding: 0;
list-style-type: none;
}
ul li{
padding: 0;
display: block;
}
.slideshow-wrapper{
position: relative;
width: 100%;
text-align: center;
}
.slideshow-outside-container h1{
margin-bottom: 30px;
}
.slideshow-outside-container{
position: relative;
display: block;
margin: 0 auto;
padding: 10px;
width: 80%;
height: 150px;
background-color: #ffffff;
overflow: hidden;
}
.slideshow-inner-container{
position: absolute;
top: 12px;
left: 0;
width: 1920px;
height: 140px;
border: 1px solid #000000;
}
.slide{
float: left;
width: 150px;
height: 140px;
margin-right: 20px;
background-color: #eeeeee;
}
.slide1{
background-color: green;
}
.slide2{
background-color: yellow;
}
.slide3{
background-color: red;
}
.slide4{
background-color: blue;
}
.slide5{
background-color: orange;
}
.slideshow-controls-wrapper button{
display: inline-block;
cursor: pointer;
padding: 20px;
}
Your first problem is that the slide element does not have a current value for left, so even parsing it will return NaN and not work. You can parseInt the current value (50px parses to 50), but default it to 0 using ||, then +/- 50.
When you set the value you also need to say which units it is in, in your case 'px'.
You could cache the value in a variable as some people have suggested, but I don't really see the need. Parsing it each time is quick enough, ensures the function does what it is meant to each time and you don't run the risk of the stored value getting out of sync.
function prev() {
var val = (parseInt(document.getElementById('slide').style.left, 10) || 0) - 50;
document.getElementById('slide').style.left = val + 'px';
}
function nxt() {
var val = (parseInt(document.getElementById('slide').style.left, 10) || 0) + 50;
document.getElementById('slide').style.left = val + 'px';
}
Fiddle here
try this
function prev(){
var val=parseint(document.getElementById('slide').style.left) - 50;
document.getElementById('slide').style.left = val+"px";
}
EDIT
This answer have some limitation..