How to move child elements in carousel? - javascript

I'm making a simple JS slider and I want to change the order of the images when I click on the prev/next button:
<div id="slider-container">
<div class="btn" id="prevBtn">
<i class="arrow arrowLeft"></i>
</div>
<div class="multiple-items">
<div>
<img class="carousel-img" src="assets/carousel/img1.png">
</div>
<div>
<img class="carousel-img" src="assets/carousel/img2.png">
</div>
<div>
<img class="carousel-img" src="assets/carousel/img3.png">
</div>
<div>
<img class="carousel-img" src="assets/carousel/img4.png">
</div>
<div>
<img class="carousel-img" src="assets/carousel/img5.png">
</div>
</div>
<div class="btn" id="nextBtn">
<i class="arrow arrowRight"></i>
</div>
</div>
I want to switch img2 with img1 and img1 goes to the img5 place.
JS code, added listeners to buttons:
prevBtn.addEventListener('click', () => {
if (i > 1) {
i--
} else {
i = 5;
}
});
nextBtn.addEventListener('click', () => {
if (i < 5) {
i++
} else {
i = 1;
}
})

To do what you require you can select the :first-child/:last-child div elements and append()/prepend() them within their respective container:
const carousel = document.querySelector('.multiple-items');
document.querySelector('#prevBtn').addEventListener('click', () => {
const last = carousel.querySelector('div:last-child');
carousel.prepend(last);
});
document.querySelector('#nextBtn').addEventListener('click', () => {
const first = carousel.querySelector('div:first-child');
carousel.append(first);
});
.multiple-items > div {
display: inline-block;
width: 50px;
height: 50px;
border: 1px solid #CCC;
}
<div id="slider-container">
<div class="btn" id="prevBtn">
<i class="arrow arrowLeft">Prev</i>
</div>
<div class="multiple-items">
<div>
<img class="carousel-img" src="assets/carousel/img1.png" alt="img1" />
</div>
<div>
<img class="carousel-img" src="assets/carousel/img2.png" alt="img2" />
</div>
<div>
<img class="carousel-img" src="assets/carousel/img3.png" alt="img3" />
</div>
<div>
<img class="carousel-img" src="assets/carousel/img4.png" alt="img4" />
</div>
<div>
<img class="carousel-img" src="assets/carousel/img5.png" alt="img5" />
</div>
</div>
<div class="btn" id="nextBtn">
<i class="arrow arrowRight">Next</i>
</div>
</div>

Don't use IDs. You're limiting yourself to not being able to reuse your component inside a page. Use classes instead and have as many carousels as you desire
Use <button> instead of <div>
Use a live HTMLCollection by using Element.children
Use .append() and .prepend() Element methods
Use a more consistent CSS naming convention
document.querySelectorAll('.slider').forEach((elSlider) => {
const elItems = elSlider.querySelector(".slider-items");
const slides = elItems.children;
elSlider.querySelector(".slider-btn.prev").addEventListener("click", () => {
elItems.prepend(slides[slides.length - 1]);
});
elSlider.querySelector(".slider-btn.next").addEventListener("click", () => {
elItems.append(slides[0]);
});
});
.slider-items {
display: flex;
}
<div class="slider">
<div class="slider-items">
<div><img src="//via.placeholder.com/100x100/0bf?text=1" alt="img1"></div>
<div><img src="//via.placeholder.com/100x100/fb0?text=2" alt="img2"></div>
<div><img src="//via.placeholder.com/100x100/f0b?text=3" alt="img3"></div>
<div><img src="//via.placeholder.com/100x100/bf0?text=4" alt="img4"></div>
<div><img src="//via.placeholder.com/100x100/b0f?text=5" alt="img5"></div>
</div>
<button type="button" class="slider-btn prev" aria-label="previous">←</button>
<button type="button" class="slider-btn next" aria-label="next">→</button>
</div>
<div class="slider">
<div class="slider-items">
<div><img src="//via.placeholder.com/100x100/222?text=1" alt="img1"></div>
<div><img src="//via.placeholder.com/100x100/444?text=2" alt="img2"></div>
<div><img src="//via.placeholder.com/100x100/666?text=3" alt="img3"></div>
<div><img src="//via.placeholder.com/100x100/888?text=4" alt="img4"></div>
<div><img src="//via.placeholder.com/100x100/ccc?text=5" alt="img5"></div>
</div>
<button type="button" class="slider-btn prev" aria-label="previous">←</button>
<button type="button" class="slider-btn next" aria-label="next">→</button>
</div>
Thanks to the live HTMLCollection, with the example above you can also add or remove slides dynamically; the script will still work as expected.
What is still missing in the above is a better UI/UX. In the real world things do not teleport; users are used to cognitively perceive motion through animation. But that's another question.

Related

Hide parent container if children are set to display none

Not sure what I'm missing here, but trying to hide the entire container for links parent-container if the anchor links inside it are set to inline display: none
I've tried checking if the style is none with
[...document.querySelectorAll(".parent-container a")].map(item => item.style.display == "none" && document.querySelectorAll(".parent-container").style = "display: none")
But can't get it to check correctly.
const parentContainer = document.querySelector(".parent-container [data-filter]");
const toggleViews = function(filterName) {
parentContainer.forEach($el => {
if ($el.dataset.filter == filterName || filterName == 'show-all') {
$el.style.display = "initial";
} else {
$el.style.cssText = "display:none!important";
}
});
};
section {
border: 1px solid #000;
}
<section class="parent-container">
<div>
<div class="">
<header>
<h3>heading</h3>
</header>
<div class="col-w1">
<a href="#" class="" style="display: none;" data-filter="car">
<div class="col-item">
<img src="#" alt="">Test
</div>
</a>
<a href="#" class="" style="display: none;" data-filter="boat">
<div class="col-item">
<img src="#" alt="">Test
</div>
</a>
<a href="#" class="" style="display: none;" data-filter="house">
<div class="col-item">
<img src="#" alt="">Test
</div>
</a>
</div>
</div>
</div>
</section>
<section class="parent-container">
<div>
<div class="">
<header>
<h3>heading</h3>
</header>
<div class="col-w1">
<a href="#" class="" style="display: block;" data-filter="house">
<div class="col-item">
<img src="#" alt="">Test
</div>
</a>
<a href="#" class="" style="display: block;" data-filter="car">
<div class="col-item">
<img src="#" alt="">Test
</div>
</a>
<a href="#" class="" style="display: block;" data-filter="boat">
<div class="col-item">
<img src="#" alt="">Test
</div>
</a>
</div>
</div>
</div>
</section>
You need a nested loop, the outer iterating over each parent-container and the inner over each a element, here using NodeList.forEach for the outer loop and Array.every over the a elements queried from each container (with getElementsByTagName in this case).
document.querySelectorAll(".parent-container").forEach(container => {
const aElements = [...container.getElementsByTagName("a")];
if (aElements.every(element => element.style.display === "none")) {
container.style.display = 'none'
} else {
container.style.display = 'block'
}
});
section{
border: 1px solid #000;
}
<section class="parent-container"><div><div class=""><header><h3>heading</h3></header><div class="col-w1"><div class="col-item"><img src="#" alt="">Test</div><div class="col-item"><img src="#" alt="">Test</div><div class="col-item"><img src="#" alt="">Test</div></div></div></div></section><section class="parent-container"><div><div class=""><header><h3>heading</h3></header><div class="col-w1"><div class="col-item"><img src="#" alt="">Test</div><div class="col-item"><img src="#" alt="">Test</div><div class="col-item"><img src="#" alt="">Test</div></div></div></div></section>
Edit
In response to your more complete snippet here is an extended example. You are still not addressing the multiple levels necessary to achieve what you need (as noted by #danh in the comments as well). You need to address each parent-container and then the relevant children of each individually. The example below first uses your logic to filter the children of each container, and then checks if they have all been hidden or not. I've implemented it with a .hidden class instead of inline CSS but you can adapt as you see fit.
// query only the parent-containers
const parentContainers = document.querySelectorAll(".parent-container");
function toggleViews(filterName) {
for (const container of parentContainers) {
// query relevant children
const elements = [...container.querySelectorAll("[data-filter]")];
// hide filtered elements
for (const element of elements) {
if (element.dataset.filter === filterName || filterName === 'show-all') {
element.classList.remove('hidden');
} else {
element.classList.add('hidden');
}
}
// hide parent if all children are hidden
if (elements.every(element => element.classList.contains('hidden'))) {
container.classList.add('hidden');
} else {
container.classList.remove('hidden');
}
};
};
document.addEventListener('click', (e) => {
if (e.target.nodeName === 'BUTTON'){
toggleViews(e.target.textContent.toLowerCase().replace(' ', '-'));
}
});
section {
border: 1px solid #000;
}
.hidden {
display: none;
}
<button type="button" class="filter">Boat</button>
<button type="button" class="filter">House</button>
<button type="button" class="filter">Car</button>
<button type="button" class="filter">Show all</button>
<section class="parent-container">
<div>
<div class="">
<header>
<h3>Section 1</h3>
</header>
<div class="col-w1">
<a href="#" class="" data-filter="car">
<div class="col-item">
<img src="#" alt="">Car
</div>
</a>
<a href="#" class="" data-filter="bicycle">
<div class="col-item">
<img src="#" alt="">Bicycle
</div>
</a>
<a href="#" class="" data-filter="house">
<div class="col-item">
<img src="#" alt="">House
</div>
</a>
</div>
</div>
</div>
</section>
<section class="parent-container">
<div>
<div class="">
<header>
<h3>Section 2</h3>
</header>
<div class="col-w1">
<a href="#" class="" data-filter="shed">
<div class="col-item">
<img src="#" alt="">Shed
</div>
</a>
<a href="#" class="" data-filter="car">
<div class="col-item">
<img src="#" alt="">Car
</div>
</a>
<a href="#" class="" data-filter="boat">
<div class="col-item">
<img src="#" alt="">Boat
</div>
</a>
</div>
</div>
</div>
</section>

How do I get a 4by4 grid to display all my puzzle pieces?

I'm trying to make an image puzzle game where there is a 4by4 grid to try to solve a shuffled puzzle. I tried creating a 4by4 grid but had no luck let alone have each element in the array correspond to a puzzle piece on the board. I tried making divs for each image but couldn't figure out a way to display them properly on the board. How do I accomplish a 4by4 grid that can correspond to elements in my array?
Note: I know that my images don't display properly because the files haven't been converted to stack overflow's server, ignore it for now.
var pieces = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,];
function initialize()
{
for( var i = pieces.length; i<16; i++;){}
}
function shuffle()
{
}
* {
box-sizing: border-box;
}
body {
margin: 0;
background: radial-gradient(#9D5900, #3D2200);
}
.game-container {
display: grid;
grid-template-columns: repeat(4, auto);
grid-gap: 10px;
margin: 50px;
justify-content: center;
perspective: 500px;
}
.card {
height: 225px;
width: 175px;
}
<!DOCTYPE html>
<html>
<title></title>
<link rel="stylesheet" type="text/css" href="PicturePuzzle.css" />
<script src="PicturePuzzle.js" type="text/javascript"></script>
<head>
<body onload = "initialize()">
<div class="game-container">
<div class="card">
<img src="char1.jpg">
</div>
<div class="card">
<img src ="char2.jpg">
</div>
<div class="card">
<img src ="char3.jpg">
</div>
<div class="card">
<img src="char4.jpg">
</div>
<div class="card">
<img src="char5.jpg">
</div>
<div class="card">
</div>
<img src="char6.jpg">
</div>
<div class="card">
<img src="char7.jpg" >
<div class="card">
<img src="char8.jpg" >
</div>
<div class="card">
<img src="char9.jpg" >
</div>
<div class="card">
<img src="char10.jpg">
</div>
<div class="card">
<img src="char11.jpg">
</div>
<div class="card">
<img src="char12.jpg">
</div>
<div class="card">
<img src="char13.jpg">
</div>
<img src="char14.jpg">
</div>
<div class="card">
<img src="char15.jpg">
</div>
<img src="char16.jpg">
</div>
</div>
<button onclick = "shuffle()">Shuffle</button>
</body>
</head>
</html>
You have HTML errors messing up the grid - there are </div> tags in the wrong places - and missing <div> tags
Correct HTML:
<div class=game-container>
<div class=card>
<img src=char1.jpg>
</div>
<div class=card>
<img src=char2.jpg>
</div>
<div class=card>
<img src=char3.jpg>
</div>
<div class=card>
<img src=char4.jpg>
</div>
<div class=card>
<img src=char5.jpg>
</div>
<div class=card>
<img src=char6.jpg>
</div>
<div class=card>
<img src=char7.jpg>
</div>
<div class=card>
<img src=char8.jpg>
</div>
<div class=card>
<img src=char9.jpg>
</div>
<div class=card>
<img src=char10.jpg>
</div>
<div class=card>
<img src=char11.jpg>
</div>
<div class=card>
<img src=char12.jpg>
</div>
<div class=card>
<img src=char13.jpg>
</div>
<div class=card>
<img src=char14.jpg>
</div>
<div class=card>
<img src=char15.jpg>
</div>
<div class=card>
<img src=char16.jpg>
</div>
</div>
There is a Javascript error - it doesn't affect the grid
There should be no semicolon after the increment expression in loop control statement
Also prefer to use let instead of var
for(let i=pieces.length; i<16; i++) {}

jQuery not adding class to selected div id

I'm trying this code on website but it not working at all.
<script src="https://code.jquery.com/jquery-3.5.0.js"></script>
<script>
var link = jQuery(location).attr('pathname');
var fullurl = jQuery(location).attr('href');
if (link.split("/")[3] === "sardines") {
console.log("fullurl = " + fullurl);
console.log("pathname = " + link);
console.log("loop sardines");
jQuery('#sardines').addClass('capik');
console.log("end addClass");
}
else if (link.split("/")[3] === "saba"){
console.log("loop saba");
jQuery('#saba').addClass('capik');
console.log("end addClass");
}
else{
console.log("end of loop");
}
<div id="all-product-categories">
<div class="all-categories">
<h2>All Categories</h2>
</div>
<div class="col-12">
<div id="sardines" class="sardines col-3">
<a href="/index.php/products/sardines" alt="Sardines">
<div class="box">
<span>SARDINES</span>
<img src="images/AYAM-product-categories/sardines.png" alt="sardines" width="150" height="150" />
</div>
</a>
</div>
<div id="saba" class="saba col-3">
<a href="/index.php/products/saba" alt="Saba">
<div class="box">
<span>SABA</span>
<img src="images/AYAM-product-categories/saba.png" alt="saba" width="150" height="150" />
</div>
</a>
</div>
<div id="mackerel" class="col-3">
<a href="/index.php/products/mackerel" alt="Mackerel">
<div class="box">
<span>MACKEREL</span>
<img src="images/AYAM-product-categories/mackerel.png" alt="saba" width="150" height="150" />
</div>
</a>
</div>
<div id="tuna" class="col-3">
<a href="/index.php/products/tuna" alt="Tuna">
<div class="box">
<span>TUNA</span>
<img src="images/AYAM-product-categories/tuna.png" alt="saba" width="150" height="150" />
</div>
</a>
</div>
</div>
<div style="clear: both;"> </div>
<div class="col-12">
<div id="bakedbeans" class="col-3">
<a href="/index.php/products/baked-beans" alt="Baked Beans">
<div class="box">
<span>BAKED BEANS</span>
<img src="images/AYAM-product-categories/baked-beans.png" alt="saba" width="150" height="150" />
</div>
</a>
</div>
<div id="coconut" class="col-3">
<a href="/index.php/products/coconut" alt="Coconut">
<div class="box">
<span>COCONUT</span>
<img src="images/AYAM-product-categories/coconut.png" alt="saba" width="150" height="150" />
</div>
</a>
</div>
<div id="fruits" class="col-3">
<a href="/index.php/products/fruits" alt="Fruits">
<div class="box">
<span>FRUITS</span>
<img src="images/AYAM-product-categories/fruits.png" alt="saba" width="150" height="150" />
</div>
</a>
</div>
<div id="vegetables" class="col-3">
<a href="/index.php/products/vegetables" alt="Vegetables">
<div class="box">
<span>VEGETABLES</span>
<img src="images/AYAM-product-categories/vegetables.png" alt="saba" width="150" height="150" />
</div>
</a>
</div>
</div>
<div style="clear: both;"> </div>
Can someone help me with this issue. The script are running fine on the site but the jQuery not adding any class on the selected id. The loop also working fine. How to make the jQuery add the new class on the selected div id. Here i'm attaching the screenshot for the console that show the script are running fine and screenshot for the html. But the class are not added into the selected one.Look like it skipping the addClass script there.
This is when i'm on sardines page.
Wrap your code with jQuery(document).ready. Your code might have been executed before the html was fully loaded. Means that your selectors got executed when the element is not present yet..
// document.ready
jQuery(document).ready(function () {
var link = jQuery(location).attr('pathname');
console.log("url = " + link);
console.log(link.split("/")[3]);
console.log(link.split("/")[3] === "sardines");
if (link.split("/")[3] === "sardines") {
console.log("loop sardines");
jQuery('#sardines').addClass('class');
console.log("end addClass");
}
else if (link.split("/")[3] === "saba"){
console.log("loop saba");
jQuery('#saba').addClass('class');
console.log("end addClass");
}
else{
console.log("end of loop");
}
})
<!-- A not working example, inspect element you see there's no class -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$("#test").addClass("test");
</script>
<div id="test">
Test
</div>
<!-- A working example, inspect element you see there's a class -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).ready(function () {
$("#test").addClass("test");
});
</script>
<div id="test">
Test
</div>
Hope that helps

JavaScript Fade In Not Working Correctly - 2 of 4 divs fade in correctly

I just need each div to fade in once, doesn't need to fade out. Only .landing and .about fade in. .images and .contact don't fade in at all, but I can still click the invisible button on the .images div. If you need my CSS for the ids, please let me know. I'm still a JavaScript beginner, so this could be an easy fix.
<div class="landing">
<div class="content" id="fadein"> <!-- "fadein" is for my onload function -->
<div class="header">
<h1 style="margin: 0;">Placeholder</h1>
<h4 style="margin: 0;">Placeholder</h4>
</div>
<div class="down">
<a href="#about">
<img src="down.png">
</a>
</div>
</div>
</div>
<a id="about"></a>
<div class="wrapper">
<div class="content" id="fadeinclick">
<h3 style="margin: 0;">Placeholder</h3>
<h3 style="margin: 0;">Placeholder</h3>
<h3 style="margin: 0;">Placeholder</h3>
<h3 style="margin: 0;">Placeholder</h3>
<div class="down">
<a href="#images">
<img src="down.png">
</a>
</div>
</div>
</div>
<a id="images"></a>
<div class="wrapper">
<div class="content" id="fadeinclick"> <!-- first div that won't fade in -->
<h3>Images</h3>
<div class="activity">
<img src="placeholder.png"></img>
<img src="placeholder.png"></img>
<img src="placeholder.png"></img>
</div>
<div class="down">
<a href="#contact">
<img src="down.png">
</a>
</div>
</div>
</div>
<a id="contact"></a>
<div class="wrapper">
<div class="content" id="fadeinclick"> <!-- second div that won't fade in -->
<h3>Contact</h3>
<div class="activity">
<img src="placeholder.png"></img>
<img src="placeholder.png"></img>
<img src="placeholder.png"></img>
</div>
</div>
</div>
<!-- Fade scripts -->
<script>
window.onload = function() {
document.getElementById("fadein").style.opacity = 1;
}
</script>
<script>
window.onclick = function() {
document.getElementById("fadeinclick").style.opacity = 1;
}
</script>
opacity isn't a child of style, but rather a property. Just do
elem.style = "opacity:100%"
But keep in mind it won't fade. My advice?
var fade = 0
var elem = document.getElementById('imageId')
rate = 1
function step() {
fade = fade + 1
}
function start() {
if (fade < 100) {
step()
setInterval(function() {start}, rate)
};
};

mouseout image hide div containing text

I have the following script that shows/hides some text when an image is clicked. This text then is replaced when another image is clicked and so on. At the moment there is always some text visible.
I want this text to disappear (or perhaps display and empty div?) on mouseOut of the image.
Here is what I currently have:
JS:
<script type="text/javascript" language="JavaScript">
<!--
function showonlyonev2(thechosenone) {
var newboxes = document.getElementsByTagName("div");
for(var x=0; x<newboxes.length; x++) {
name = newboxes[x].getAttribute("name");
if (name == 'textboxes') {
if (newboxes[x].id == thechosenone) {
if (newboxes[x].style.display == 'block') {
} else {
newboxes[x].style.display = 'block';
}
} else {
newboxes[x].style.display = 'none';
}
}
}
}
</script>
HTML:
<div id="text-container">
<div id="text1" name="textboxes">
<p>Some text here about person 1</p>
<div id="text2" name="textboxes">
<p>Some text here about person 2</p>
<div id="text3" name="textboxes">
<p>Some text here about person 3</p>
<div id="text4" name="textboxes">
<p>Some text here about person 4</p>
</div>
<div class="people-images">
<a href="javascript:showonlyonev2('text1');" class="rollovers">
<div id="person1-rollover"><img src="images/people/person1.jpg" alt="" /> </div>
</a>
</div>
<div class="people-images">
<a href="javascript:showonlyonev2('text2');" class="rollovers">
<div id="person2-rollover"><img src="images/people/person2.jpg" alt="" /> </div>
</a>
</div>
<div class="people-images">
<a href="javascript:showonlyonev2('text3');" class="rollovers">
<div id="person3-rollover"><img src="images/people/person3.jpg" alt="" /> </div>
</a>
</div>
<div class="people-images">
<a href="javascript:showonlyonev2('text4');" class="rollovers">
<div id="person4-rollover"><img src="images/people/person4.jpg" alt="" /> </div>
</a>
</div>
CSS:
#text1 {
width: 300px;
height: 300px;
background: #c2bfba;
}
#text2, #text3, #text4 {
width: 300px;
height: 300px;
background: #c2bfba;
display:none;
}
Thanks for any help.
You could use this in the image tag:
<img src='...' onmouseover='javascript:showonlyonev2('text1')' onmouseout='javascript:showonlyonev2('blank')' />
This way your function gets called whenever the image is hovered over. you can create an empty div called 'blank' so that your function uses it when mouse out, so it appears blank.
Keep your Javascript the same.
Change your HTML to:
<div id="text-container">
<!-- All of these DIV's should have closing tags -->
<div id="text1" name="textboxes"><p>Some text here about person 1</p></div>
<div id="text2" name="textboxes"><p>Some text here about person 2</p></div>
<div id="text3" name="textboxes"><p>Some text here about person 3</p></div>
<div id="text4" name="textboxes"><p>Some text here about person 4</p></div>
<div id="blank" name="textboxes"><p> </p></div>
</div>
<div class="people-images">
<a href="javascript:showonlyonev2('text1');" class="rollovers">
<div id="person1-rollover"><img src="images/people/person1.jpg" onmouseout="javascript:showonlyonev2('blank');" alt="" /> </div></a>
</div>
<div class="people-images">
<a href="javascript:showonlyonev2('text2');" class="rollovers">
<div id="person2-rollover"><img src="images/people/person2.jpg" onmouseout="javascript:showonlyonev2('blank');" alt="" /> </div></a>
</div>
<div class="people-images">
<a href="javascript:showonlyonev2('text3');" class="rollovers">
<div id="person3-rollover"><img src="images/people/person3.jpg" onmouseout="javascript:showonlyonev2('blank');" alt="" /> </div></a>
</div>
<div class="people-images">
<a href="javascript:showonlyonev2('text4');" class="rollovers">
<div id="person4-rollover"><img src="images/people/person4.jpg" onmouseout="javascript:showonlyonev2('blank');" alt="" /> </div></a>
</div>
Change your CSS to:
#blank {
width: 300px;
height: 300px;
background: #c2bfba;
}
#text1, #text2, #text3, #text4 {
width: 300px;
height: 300px;
background: #c2bfba;
display:none;
}
Let me know if that works for you.

Categories

Resources