How to write exitClickHandler function better - javascript

There are 3 container classes
Two exit buttons are viewable inside each of their respective containers, where they each take you to a different container when clicked on.
<div class="container1"></div>
<div class="container2 hide"></div>
<div class="container3 hide"></div>
Code I am working on.
How would it be written differently to make it better?
How can this be improved?
https://jsfiddle.net/an23j14r/
function exitClickHandler(e) {
if (e.target.classList.contains("exit")) {
document.querySelector(".container2").classList.add("hide");
document.querySelector(".container3").classList.add("hide");
document.querySelector(".container1").classList.remove("hide");
console.log('Page1');
}
if (e.target.classList.contains("exitPage2")) {
document.querySelector(".container1").classList.add("hide");
document.querySelector(".container3").classList.add("hide");
document.querySelector(".container2").classList.remove("hide");
console.log('Page2');
}
if (e.target.classList.contains("exitPage3")) {
document.querySelector(".container2").classList.add("hide");
document.querySelector(".container1").classList.add("hide");
document.querySelector(".container3").classList.remove("hide");
console.log('Page3');
}
window.scrollTo(0, 0);
}
Here are the exit buttons that go to their corresponding CSS classes that they go to in the code.
You would click on a button and it should take you to a specific CSS class/page that it goes to.
There are 3 container classes, when 1 of 2 buttons is clicked on, 2 container classes should be hidden, where 1 of them becomes visible.
<div class="container1">
<button class="exit exitpPage2" type="button"></button>
<button class="exit exitpPage3" type="button"></button>
</div>
<div class="container2 hide">
<button class="exit" type="button"></button>
<button class="exit exitpPage3" type="button"></button>
</div>
<div class="container3 hide">
<button class="exit" type="button"></button>
<button class="exit exitpPage2" type="button"></button></div>
Each container/page would be unhidden when a button is clicked on, where the other containers/pages would stay hidden.
When exit button attached to .container1 is clicked on, .container2 and .container3 should be hidden.
When exit button attached to .container2 is clicked on, .container1 and .container3 should be hidden.
When exit button attached to .container3 is clicked on, .container2 and .container1 should be hidden.
Here is my code example:
const manageCover = (function makeManageCover() {
function showCover(playButton) {
const cover = playButton.parentElement;
cover.classList.add("active");
}
function openCurtain(curtain) {
curtain.classList.add("slide");
}
function coverClickHandler(evt) {
const cover = evt.currentTarget;
showCover(cover);
const curtain = evt.currentTarget.parentElement.parentElement.parentElement;
openCurtain(curtain);
}
function addCoverHandler(coverSelector, handler) {
const cover = document.querySelector(coverSelector);
cover.addEventListener("click", handler);
}
function addClickToButtons(playButtons) {
playButtons.forEach(function playButtonHandler(playButton) {
playButton.addEventListener("click", coverClickHandler);
});
}
function init( /*selectors*/ ) {
//config.containers = document.querySelector(selectors.container);
// const allContainers = document.querySelector(".container");
//const playButtons = document.querySelector(selectors.playButton);
const allPlaybuttons = document.querySelectorAll(".cover");
//const allPlaybuttons = document.querySelectorAll(".embed-youtube-play");
addClickToButtons(allPlaybuttons);
}
return {
addCoverHandler,
init
};
}());
const manageUI = (function makeManageUI() {
document.body.scrollTop = 0;
const players = [];
function findPlayers() {
const allCovers = document.querySelectorAll(".cover");
const allWrappers = document.querySelectorAll(".wrap");
allCovers.forEach(function addToPlayers(cover, index) {
players.push({
"cover": cover,
"wrapper": allWrappers[index]
});
});
}
function getWrapper(cover) {
const index = players.findIndex(
(player) => player.cover === cover
);
return players[index].wrapper;
}
function exitClickHandler(e) {
if (e.target.classList.contains("exit")) {
document.querySelector(".container2").classList.add("hide");
document.querySelector(".container3").classList.add("hide");
document.querySelector(".container1").classList.remove("hide");
console.log('Page1');
}
if (e.target.classList.contains("exitPage2")) {
document.querySelector(".container1").classList.add("hide");
document.querySelector(".container3").classList.add("hide");
document.querySelector(".container2").classList.remove("hide");
console.log('Page2');
}
if (e.target.classList.contains("exitPage3")) {
document.querySelector(".container2").classList.add("hide");
document.querySelector(".container1").classList.add("hide");
document.querySelector(".container3").classList.remove("hide");
console.log('Page3');
}
window.scrollTo(0, 0);
}
function addClickToExit(exitButtons) {
exitButtons.forEach(function addExitButtonHandler(exitButtons) {
exitButtons.addEventListener("click", exitClickHandler);
});
}
function addExitHandlers(callback) {
const resetVideo = document.querySelectorAll(".exit");
resetVideo.forEach(function resetVideoHandler(video) {
video.addEventListener("click", callback);
});
}
function init() {
findPlayers();
const exitButtons = document.querySelectorAll(".exit");
addClickToExit(exitButtons);
}
return {
addExitHandlers,
getWrapper,
init
};
}());
const videoPlayer = (function makeVideoPlayer() {
let player;
const tag = document.createElement("script");
tag.src = "https://www.youtube.com/player_api";
const firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
function onPlayerReady(event) {
player = event.target;
player.setVolume(100);
}
function onPlayerStateChange(event) {
const player = event.target;
return player;
}
function addPlayer(video, playerOptions) {
playerOptions.videoId = playerOptions.videoId || video.dataset.id;
playerOptions.events = playerOptions.events || {};
playerOptions.events.onReady = onPlayerReady;
playerOptions.events.onStateChange = onPlayerStateChange;
const player = new YT.Player(video, playerOptions);
return player;
}
return {
addPlayer
};
}());
const managePlayer = (function makeManagePlayer() {
const playerVars = {
autoplay: 1,
controls: 1,
disablekb: 1,
fs: 0,
iv_load_policy: 3
};
const defaults = {
height: 360,
host: "https://www.youtube-nocookie.com",
playerVars,
width: 640
};
function show(el) {
el.classList.remove("hide");
}
function combinePlayerOptions(opts1 = {}, opts2 = {}) {
const combined = Object.assign({}, opts1, opts2);
Object.keys(opts1).forEach(function checkObjects(prop) {
if (typeof opts1[prop] === "object") {
combined[prop] = Object.assign({}, opts1[prop], opts2[prop]);
}
});
return combined;
}
function createPlayer(videoWrapper, playerOptions = {}) {
const video = videoWrapper.querySelector(".video");
const options = combinePlayerOptions(defaults, playerOptions);
return videoPlayer.addPlayer(video, options);
}
function playerAdder(wrapper, playerOptions) {
return function addPlayerCallback() {
initPlayer(wrapper, playerOptions);
};
}
function removePlayer(wrapper) {
wrapper.player.destroy();
delete wrapper.player;
console.log("removePlayer");
}
function removePlayerHandler(evt) {
const el = evt.target;
let container = el.closest(".container");
let wrappers;
if (container) { //if multiple players
wrappers = container.querySelectorAll(".remove .wrap");
} else { //if single player
container = el.closest(".remove");
wrappers = container.querySelectorAll(".wrap");
}
wrappers.forEach(function(wrapper) {
if (wrapper.player) {
removePlayer(wrapper);
}
});
}
function initPlayer(wrapper, playerOptions) {
show(wrapper);
const player = createPlayer(wrapper, playerOptions);
wrapper.player = player;
}
return {
adder: playerAdder,
removePlayerHandler
};
}());
const players = (function coverUIPlayerFacade() {
function addPlayer(coverSelector, playerOptions) {
const cover = document.querySelector(coverSelector);
const wrapper = manageUI.getWrapper(cover);
const callback = managePlayer.adder(wrapper, playerOptions);
manageCover.addCoverHandler(coverSelector, callback);
}
function init() {
manageCover.init({
playButton: ".cover"
});
manageUI.init({});
manageUI.addExitHandlers(managePlayer.removePlayerHandler);
}
return {
add: addPlayer,
init
};
}());
players.init();
function onYouTubeIframeAPIReady() {
players.add(".playa", {
playerVars: {
loop: 1,
playlist: "djV11Xbc914"
}
});
players.add(".playb", {});
players.add(".playc", {});
players.add(".playd", {});
players.add(".playe", {
playerVars: {
playlist: ["mnfmQe8Mv1g", "M7lc1UVf-VE",
"-Xgi_way56U", "CHahce95B1g"
]
}
});
players.add(".playf", {});
players.add(".playg", {});
players.add(".playh", {});
players.add(".playi", {});
players.add(".playj", {
playerVars: {
playlist: ["mnfmQe8Mv1g", "M7lc1UVf-VE",
"-Xgi_way56U", "CHahce95B1g"
]
}
});
players.add(".playk", {});
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
body {
background: #302b63;
}
.container2 .container {
background: teal;
}
.container3 .container {
background: green;
}
.container1 {
position: absolute;
left: 0;
right: 0;
min-height: 100%;
min-width: 255px;
display: flex;
padding: 8px 8px;
}
.curtain1 {
flex: 1 0 0;
margin: auto;
max-width: 640px;
border: 21px solid;
border-radius: 12px;
border-color: #000 #101010 #000 #101010;
position: relative;
}
.ratio-keeper {
position: relative;
height: 0;
padding-top: 56.25%;
margin: auto;
overflow: hidden;
}
.container {
position: absolute;
left: 0;
right: 0;
min-height: 100%;
padding: 8px 8px;
}
.curtain {
margin: auto auto 40px;
max-width: 640px;
border: 21px solid;
border-radius: 12px;
border-color: #000 #101010 #000 #101010;
position: relative;
}
.embed-youtube iframe,
.embed-youtube .embed-youtube-play,
.embed-youtube .embed-youtube-play::before {
position: absolute;
}
.embed-youtube iframe {
height: 100%;
width: 100%;
top: 0;
left: 0;
}
.embed-youtube .embed-youtube-play {
-webkit-appearance: none;
appearance: none;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
margin: auto;
display: flex;
justify-content: center;
align-items: center;
width: 90px;
height: 90px;
border-radius: 50%;
cursor: pointer;
border: 9px solid blue;
background: transparent;
filter: drop-shadow(3px 3px 3px #000000b3);
z-index: 1;
}
.embed-youtube-play::before {
content: "";
width: 0;
height: 0;
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
border-left: 27px solid blue;
transform: translateX(4px);
}
.embed-youtube-play:hover {
box-shadow: 0 0 0 5px rgba(43, 179, 20, 0.5);
}
.embed-youtube-play:focus {
outline: 0;
box-shadow: 0 0 0 5px rgba(0, 255, 255, 0.5);
}
.embed-youtube.active .embed-youtube-play {
display: none;
}
#keyframes rotate {
0% {
transform: rotate(0deg);
}
99.9% {
border-color: red transparent red transparent;
pointer-events: none;
}
100% {
transform: rotate(360deg);
border-color: blue;
}
}
#keyframes triangle {
0% {
opacity: 0;
}
99.9% {
opacity: 0;
}
100% {
border-left-color: blue;
opacity: 1;
}
}
.exit {
position: absolute;
top: auto;
bottom: -47.63px;
margin: auto;
right: 0;
left: 0;
width: 47px;
height: 47px;
cursor: pointer;
border-radius: 100%;
background: transparent;
border: 5px solid red;
box-sizing: border-box;
clip-path: circle(50%);
}
.exit::before,
.exit::after {
content: "";
background-color: red;
width: 47px;
height: 5px;
position: absolute;
top: 0px;
left: -5px;
right: 0;
bottom: 0;
margin: auto;
}
.exit::before {
transform: rotate(45deg);
}
.exit::after {
transform: rotate(-45deg);
}
.exit.exitPage2 {
position: absolute;
top: auto;
bottom: -47.63px;
margin: auto;
right: 200px;
left: 0;
border: 5px solid blue;
}
.exit.exitPage2::before,
.exit.exitPage2::after {
background-color: blue;
}
.exit.exitPage3 {
position: absolute;
top: auto;
bottom: -47.63px;
margin: auto;
right: 0px;
left: 200px;
border: 5px solid purple;
}
.exit.exitPage3::before,
.exit.exitPage3::after {
background-color: purple;
}
.hide {
display: none;
}
<div class="container1">
<div class="curtain1 remove">
<div class="ratio-keeper">
<div class="video-one"></div>
<div class="wrap embed-youtube ">
<div class="video embed-youtube " data-id="djV11Xbc914">
</div>
<button class="playa cover embed-youtube-play" type="button"></button>
</div>
</div>
<button class="exit exitPage2" type="button"></button>
<button class="exit exitPage3" type="button"></button>
</div>
</div>
<div class="container2 hide">
<div class="container ">
<div class="curtain remove">
<div class="ratio-keeper">
<div class="video-two"></div>
<div class="wrap embed-youtube">
<div class="video embed-youtube" data-id="djV11Xbc914">
</div>
<button class="playb cover embed-youtube-play" type="button"></button>
</div>
</div>
</div>
<div class="curtain remove">
<div class="ratio-keeper">
<div class="video-three"></div>
<div class="wrap embed-youtube">
<div class="video embed-youtube" data-id="djV11Xbc914">
</div>
<button class="playc cover embed-youtube-play" type="button"></button>
</div>
</div>
</div>
<div class="curtain remove">
<div class="ratio-keeper">
<div class="video-four"></div>
<div class="wrap embed-youtube">
<div class="video embed-youtube" data-id="djV11Xbc914">
</div>
<button class="playd cover embed-youtube-play" type="button"></button>
</div>
</div>
</div>
<div class="curtain remove">
<div class="ratio-keeper">
<div class="video-five"></div>
<div class="wrap embed-youtube">
<div class="video embed-youtube" data-id="djV11Xbc914">
</div>
<button class="playe cover embed-youtube-play" type="button"></button>
</div>
</div>
</div>
<div class="curtain remove">
<div class="ratio-keeper">
<div class="video-six"></div>
<div class="wrap embed-youtube">
<div class="video embed-youtube" data-id="djV11Xbc914">
</div>
<button class="playf cover embed-youtube-play" type="button"></button>
</div>
</div>
<button class="exit" type="button"></button>
<button class="exit exitPage3" type="button"></button>
</div>
</div>
</div>
<div class="container3 hide">
<div class="container ">
<div class="curtain remove">
<div class="ratio-keeper">
<div class="video-seven"></div>
<div class="wrap embed-youtube">
<div class="video embed-youtube" data-id="djV11Xbc914">
</div>
<button class="playg cover embed-youtube-play" type="button"></button>
</div>
</div>
</div>
<div class="curtain remove">
<div class="ratio-keeper">
<div class="video-eight"></div>
<div class="wrap embed-youtube">
<div class="video embed-youtube" data-id="djV11Xbc914">
</div>
<button class="playh cover embed-youtube-play" type="button"></button>
</div>
</div>
</div>
<div class="curtain remove">
<div class="ratio-keeper">
<div class="video-nine"></div>
<div class="wrap embed-youtube">
<div class="video embed-youtube" data-id="djV11Xbc914">
</div>
<button class="playi cover embed-youtube-play" type="button"></button>
</div>
</div>
</div>
<div class="curtain remove">
<div class="ratio-keeper">
<div class="video-ten"></div>
<div class="wrap embed-youtube">
<div class="video embed-youtube" data-id="djV11Xbc914">
</div>
<button class="playj cover embed-youtube-play" type="button"></button>
</div>
</div>
</div>
<div class="curtain remove">
<div class="ratio-keeper">
<div class="video-eleven"></div>
<div class="wrap embed-youtube">
<div class="video embed-youtube" data-id="djV11Xbc914">
</div>
<button class="playk cover embed-youtube-play" type="button"></button>
</div>
</div>
<button class="exit" type="button"></button>
<button class="exit exitPage2" type="button"></button>
</div>
</div>
</div>

If you want something that is similar to a carousel, you only need two buttons outside each container to control the index of the container that should be visible. The index start at 0 and is then changed ±1 steps depending on which button that is clicked.
toggleContainer() checks that the index of the container isn't out of bounce (less than 0 or bigger than the number of containers).
hideAllContainersBut() loops through the container "array" and hides every container except the current index.
document.getElementById('prev-button').addEventListener('click', toggleContainers);
document.getElementById('next-button').addEventListener('click', toggleContainers);
let containers = document.querySelectorAll('.container')
var index = 0;
function toggleContainers(event) {
let indexChange = event.target.dataset.indexChange;
index = index + Number(indexChange);
if (index < 0) { index = containers.length - 1; };
if (index >= containers.length) { index = 0; };
hideAllContainersBut(index);
}
function hideAllContainersBut(index) {
for (let i = 0; i < containers.length; i++) {
containers[i].hidden = index !== i;
}
}
.container {
height: 15vw;
padding: 1rem;
margin-bottom: 1rem;
}
button {
cursor: pointer;
}
.container.one {
background-color: red;
}
.container.two {
background-color: lightgreen;
}
.container.three {
background-color: yellow;
}
<section>
<div class="container one">
Container 1
</div>
<div class="container two" hidden>
Container 2
</div>
<div class="container three" hidden>
Container 3
</div>
<button id="prev-button" data-index-change="-1" type="button">Previous</button>
<button id="next-button" data-index-change="1" type="button">Next</button>
</section>

Related

Show multiple file thumbnail on custom dropzone

I created custom dropzone in order to upload my files as the following example
function readFile(input) {
debugger;
if (input.files && input.files[0]) {
var reader = new FileReader();
for (let i = 0; i < input.files.length; i++) {
reader.onload = function(e) {
var htmlPreview =
'<img width="100" src="' +
e.target.result +
'" />' +
"<p>" +
input.files[i].name +
"</p>";
var wrapperZone = $(input).parent();
var previewZone = $(input)
.parent()
.parent()
.find(".preview-zone");
var boxZone = $(input)
.parent()
.parent()
.find(".preview-zone")
.find(".box")
.find(".box-body");
wrapperZone.removeClass("dragover");
previewZone.removeClass("hidden");
// boxZone.empty();
boxZone.append(htmlPreview);
};
}
reader.readAsDataURL(input.files[0]);
}
}
function reset(e) {
e.wrap("<form>")
.closest("form")
.get(0)
.reset();
e.unwrap();
}
$(".dropzone").change(function() {
readFile(this);
});
$(".dropzone-wrapper").on("dragover", function(e) {
e.preventDefault();
e.stopPropagation();
$(this).addClass("dragover");
});
$(".dropzone-wrapper").on("dragleave", function(e) {
e.preventDefault();
e.stopPropagation();
$(this).removeClass("dragover");
});
$(".remove-preview").on("click", function() {
var boxZone = $(this)
.parents(".preview-zone")
.find(".box-body");
var previewZone = $(this).parents(".preview-zone");
var dropzone = $(this)
.parents(".form-group")
.find(".dropzone");
boxZone.empty();
previewZone.addClass("hidden");
reset(dropzone);
});
.container {
padding: 50px 100px;
}
.box {
position: relative;
background: #ffffff;
width: 100%;
}
.box-header {
color: #444;
display: block;
padding: 10px;
position: relative;
margin-bottom: 10px;
}
.box-tools {
position: absolute;
right: 10px;
top: 5px;
}
.dropzone-wrapper {
border: 2px dashed #91b0b3;
color: #92b0b3;
position: relative;
height: 150px;
}
.dropzone-desc {
position: absolute;
margin: 0 auto;
left: 0;
right: 0;
text-align: center;
width: 40%;
top: 60px;
font-size: 16px;
}
.dropzone,
.dropzone:focus {
outline: none !important;
width: 100%;
cursor: pointer;
}
.input-file {
position: absolute;
width: 100%;
height: 150px;
opacity: 0;
}
.dropzone-wrapper:hover,
.dropzone-wrapper.dragover {
background: #ecf0f5;
}
.preview-zone {
text-align: center;
}
.preview-zone .box {
box-shadow: none;
border-radius: 0;
margin-bottom: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet" />
<div class="row" id="10secs">
<div class="col-lg-12">
<div class="card">
<div class="card-header">
<h4 class="card-title">10sec</h4>
</div>
<div class="card-body">
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="form-group">
<div class="preview-zone hidden">
<div class="box box-solid">
<div class="box-header with-border">
<div><b>Preview</b></div>
<div class="box-tools pull-right">
<button type="button" class="btn btn-danger btn-xs remove-preview">
<i class="fa fa-times"></i> Reset
</button>
</div>
</div>
<div class="box-body"></div>
</div>
</div>
<div class="dropzone-wrapper">
<div class="dropzone-desc">
<i class="glyphicon glyphicon-download-alt"></i>
<div>Choose an image file or drag it here.</div>
</div>
<input type="file" class="dropzone input-file" multiple asp-for="#Model.Files10" />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
As you can see it is a multiple-input file, so you can upload multiple files in the same dropzone.
as you can see in the readFile javascript function, I create the thumbnail, the problem is when selecting more than one file, it only shows one thumbnail, how can I display each of them each next to the other as:
Regards

how to auto slide carousel to the first item after it reach the last item?

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>

Slider goes out of first and last element

Im new to web development.
What i want to make is a slider for buttons.
How can i prevent it going out of first and last element? Right now i can slide it to the right on click, move it and when i click again it moves back to its initial position.
How can i make it draggable only between the first and last element and not go out of it.
Sorry if anything is unclear.
Any help is appreciated!
Here is my code below.
const track = document.querySelector('.track');
let initialPosition = null;
let moving = false;
let transform = 0;
let firstPosition = window.scrollX + document.querySelector('.track').getBoundingClientRect().left // X
const scrollStart = (e) => {
initialPosition = e.pageX;
moving = true;
const transformMatrix = window.getComputedStyle(track).getPropertyValue('transform');
if(transformMatrix !== 'none'){
if((parseInt(transformMatrix.split(',')[4].trim())) >= firstPosition){
transform = firstPosition;
} else {
transform = parseInt(transformMatrix.split(',')[4].trim());
}
}
};
const scrollMove = (e) => {
if(moving) {
const currentPosition = e.pageX;
const diff = currentPosition - initialPosition;
if(diff){
track.style.transform = `translateX(${transform + diff}px)`;
}
}
};
const scrollEnd = (e) => {
moving = false;
if(transform >= firstPosition){
track.style.transform = `translateX(${firstPosition})`;
}
};
if(window.PointerEvent) {
window.addEventListener('pointerdown', scrollStart);
window.addEventListener('pointermove', scrollMove);
window.addEventListener('pointerup', scrollEnd);
} else {
window.addEventListener('mousedown', scrollStart);
window.addEventListener('mousemove', scrollMove);
window.addEventListener('mouseup', scrollEnd);
window.addEventListener('touchdown', scrollStart);
window.addEventListener('touchmove', scrollMove);
window.addEventListener('touchup', scrollEnd);
}
body {
margin: 0;
}
.carousel {
width: 100%;
height: 140px;
background: #203290;
position: relative;
overflow: hidden;
}
.carousel .track {
position: absolute;
top: 10px;
left: 10px;
display: inline-flex;
touch-action: none;
}
.carousel .track .card {
width: 300px;
height: 120px;
background: #081050;
border-radius: 15px;
margin-right: 10px;
}
.card-button {
width: 100%;
height: 100%;
border-radius: 15px;
}
.card-button-text {
font-size: 4vh;
}
<div class="container">
<div class="carousel">
<div class="track">
<div class="card">
<button class="card-button"><span class="card-button-text">Link1</span></button>
</div>
<div class="card">
<button class="card-button"><span class="card-button-text">Link2</span></button>
</div>
<div class="card">
<button class="card-button"><span class="card-button-text">Link3</span></button>
</div>
<div class="card">
<button class="card-button"><span class="card-button-text">Link4</span></button>
</div>
<div class="card">
<button class="card-button"><span class="card-button-text">Link5</span></button>
</div>
<div class="card">
<button class="card-button"><span class="card-button-text">Link6</span></button>
</div>
<div class="card">
<button class="card-button"><span class="card-button-text">Link7</span></button>
</div>
<div class="card">
<button class="card-button"><span class="card-button-text">Link8</span></button>
</div>
<div class="card">
<button class="card-button"><span class="card-button-text">Link9</span></button>
</div>
<div class="card">
<button class="card-button"><span class="card-button-text">Link10</span></button>
</div>
</div>
</div>
</div>

Intersection Observer fine tuning for different window sizes

This is my code so far:
const mediaInViewport = document.querySelectorAll('.media');
const links = Array.from(document.querySelectorAll('.link'));
let actLink = links[0];
document.body.addEventListener('click', (event) => {
if (event.target.tagName === 'a') {
actLink.classList.remove('active');
actLink = links.find(link => event.target.href === link.href)
actLink.classList.add('active');
}
}, false)
observer = new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
if (entry.target && entry.isIntersecting) {
const closestParent = entry.target.closest('section');
if (closestParent) {
actLink.classList.remove('active');
actLink = links.find(link =>
link.href.slice(link.href.lastIndexOf('#')) === `#${closestParent.id}`
)
actLink.classList.add('active');
}
}
});
}, {
threshold: 0
});
window.addEventListener('DOMContentLoaded', () => {
setTimeout( // Wait for images to fully load
() => {
mediaInViewport.forEach((item) => {
observer.observe(item);
});
}, 1000);
});
* {
margin: 0;
padding: 0;
font-family: sans-serif;
font-size: 30px;
text-decoration: none;
color: inherit;
}
body {
display: flex;
cursor: default;
}
#left,
#right {
width: 50%;
height: 100vh;
overflow-y: scroll;
scroll-behavior: smooth;
}
#left {
background-color: rgb(220, 220, 220);
}
#right {
background-color: rgb(200, 200, 200);
}
.media {
padding: 10px;
padding-bottom: 0;
}
.media:nth-last-child(1) {
margin-bottom: 10px;
}
img {
display: block;
width: 100%;
}
.link {
cursor: pointer;
}
.active {
background-color: black;
color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="left">
<a class="link active" href="#landscape">Landscapes</a>
<a class="link" href="#cats">Cats</a>
<a class="link" href="#beer">Beer</a>
<a class="link" href="#food">Food</a>
</div>
<div id="right">
<section id="landscape">
<div class="media">
<img src="https://upload.wikimedia.org/wikipedia/commons/8/8d/Freudenberg_sg_Switzerland.jpg">
</div>
<div class="media">
<img src="https://upload.wikimedia.org/wikipedia/commons/8/8d/Freudenberg_sg_Switzerland.jpg">
</div>
</section>
<section id="cats">
<article class="media">
<img src="https://upload.wikimedia.org/wikipedia/commons/b/b8/Cute_cat_%281698598876%29.jpg">
</article>
<article class="media">
<img src="https://upload.wikimedia.org/wikipedia/commons/b/b8/Cute_cat_%281698598876%29.jpg">
</article>
</section>
<section id="beer">
<article class="media beer">
<img src="https://upload.wikimedia.org/wikipedia/commons/8/89/Craft_Beer_at_the_Taedonggang_Microbrewery_No._3_%2812329931855%29.jpg">
</article>
</section>
<section id="food">
<article class="media food">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/6/6d/Good_Food_Display_-_NCI_Visuals_Online.jpg/1200px-Good_Food_Display_-_NCI_Visuals_Online.jpg">
</article>
</section>
</div>
The observation function should work with all window sizes. Currently, if the window size is a bit higher, for example the "Beer" link doesn't receive the .active class if you click on it or scroll too insensitive.
Is there a way to fix that?
Rules like the following would be needed:
Always only the last observed object should trigger an .active
class.
But: If there are at one point different observable objects visible
(for example after a click on the link "Beer"), then the "most
dominant" one (the one that is not cut off and most present) should
trigger the .active class.
I would be sooooo thankful for help! <3
const mediaInViewport = Array.from(document.querySelectorAll('.media'));
const sections = Array.from(document.querySelector('#right').children);
const links = Array.from(document.querySelectorAll('.link'));
let actLink = links[0];
let actSection = null;
let targetLink = null;
let targetSection = null;
document.body.addEventListener('click', (event) => {
if (event.target.tagName === 'A') {
event.preventDefault();
targetLink = event.target;
targetSection = sections.find(section => section.id === targetLink.href.slice(targetLink.href.lastIndexOf('#')+1))
location.hash = targetLink.href.slice(targetLink.href.lastIndexOf('#'));
actLink.classList.remove('active');
actLink = links.find(l => event.target.href === l.href)
actLink.classList.add('active');
}
}, false)
observer = new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
if (entry.target && entry.isIntersecting) {
const closestParent = entry.target.closest('section');
if (closestParent) {
actLink.classList.remove('active');
if (!targetLink) {
actLink = links.find(link =>
link.href.slice(link.href.lastIndexOf('#')) === `#${closestParent.id}`
)
} else {
if (closestParent === targetSection){
targetLink = null
}
}
actSection = sections.find(section => section.id === actLink.href.slice(actLink.href.lastIndexOf('#')))
actLink.classList.add('active');
}
}
});
}, {
threshold: 0.3
});
window.addEventListener('DOMContentLoaded', () => {
setTimeout( // Wait for images to fully load
() => {
mediaInViewport.forEach((item) => {
observer.observe(item);
});
}, 1000);
});
* {
margin: 0;
padding: 0;
font-family: sans-serif;
font-size: 30px;
}
body {
display: flex;
cursor: default;
}
#left,
#right {
width: 50%;
height: 100vh;
overflow-y: scroll;
scroll-behavior: smooth;
}
#left {
background-color: rgb(220, 220, 220);
}
#right {
background-color: rgb(200, 200, 200);
}
.media {
padding: 10px;
padding-bottom: 0;
}
.media:nth-last-child(1) {
margin-bottom: 10px;
}
img {
display: block;
width: 100%;
}
.link:active {
cursor: pointer;
}
a:target {
background-color: black;
color: white;
}
a {
text-decoration: none;
color: inherit;
}
section:target {
background-color: black;
color: white;
}
.active {
background-color: black;
color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="left">
<a class="link active" href="#landscape">Landscapes</a>
<a class="link" href="#cats">Cats</a>
<a class="link" href="#beer">Beer</a>
<a class="link" href="#food">Food</a>
</div>
<div id="right">
<section id="landscape">
<div class="media">
<img src="https://upload.wikimedia.org/wikipedia/commons/8/8d/Freudenberg_sg_Switzerland.jpg">
</div>
<div class="media">
<img src="https://upload.wikimedia.org/wikipedia/commons/8/8d/Freudenberg_sg_Switzerland.jpg">
</div>
</section>
<section id="cats">
<article class="media">
<img src="https://upload.wikimedia.org/wikipedia/commons/b/b8/Cute_cat_%281698598876%29.jpg">
</article>
<article class="media">
<img src="https://upload.wikimedia.org/wikipedia/commons/b/b8/Cute_cat_%281698598876%29.jpg">
</article>
</section>
<section id="beer">
<article class="media beer">
<img src="https://upload.wikimedia.org/wikipedia/commons/8/89/Craft_Beer_at_the_Taedonggang_Microbrewery_No._3_%2812329931855%29.jpg">
</article>
</section>
<section id="food">
<article class="media food">
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/6/6d/Good_Food_Display_-_NCI_Visuals_Online.jpg/1200px-Good_Food_Display_-_NCI_Visuals_Online.jpg">
</article>
</section>
</div>

Slider with async function?

Hello this is my code and jsfiddle
<div id="section-2" class="section">
<div class="fullContentWrap">
<!-- client_logos_row -->
<div class="flexRow toLeft" style="left: 0%;">
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
</div>
<div class="flexRow toLeft" style="left: 0%;">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<!-- flexRow toLeft -->
</div>
<!-- fullContentWrap -->
</div>
$(document).ready(function() {
console.log("interval doc ready");
var currToLeft = $('.toLeft').first();
currToLeft.addClass("toLeftActive");
var myInt = setInterval(intFunc,3000);
console.log('myInt set');
function intFunc() {
console.log('intFunc !');
currToLeft.animate({left: '-101%'}, "slow",function () {
$(this).removeClass("toLeftActive");
$(this).css("left",'0%');
currToLeft = $(this).next();
if (currToLeft.length === 0) {
currToLeft = $('.toLeft').first();
}
currToLeft.addClass('toLeftActive');
});
}
// intFunc
});
// document ready
.box {
width: 100px;
height: 100px;
}
.flexRow {
display: flex;
}
.toLeft{
display: none;
left: 100%;
}
.toLeftActive {
display: flex !important;
}
.flexRow:nth-child(1) .box:nth-child(1) {
background: blue;
}
.flexRow:nth-child(1) .box:nth-child(2) {
background: red;
}
.flexRow:nth-child(1) .box:nth-child(3) {
background: orange;
}
.flexRow:nth-child(2) .box:nth-child(1) {
background: aqua;
}
.flexRow:nth-child(2) .box:nth-child(2) {
background: green;
}
.flexRow:nth-child(2) .box:nth-child(3) {
background: brown;
}
div#section-2 {
position: relative;
}
div#section-2>.fullContentWrap {
position: inherit;
}
div#section-2>.fullContentWrap>.flexRow {
position: inherit;
justify-content: center;
}
div#section-2>.fullContentWrap>.flexRow>div {
position: inherit;
}
https://jsfiddle.net/2918ztze/
As you can guess I am making a slider. The first block should go out of the screen to the left and the other one should come from right to left:0 meanwhile.
I am not sure how this meanwhile part should be done, probably with some async coding, but how do I do it?

Categories

Resources