I'm using bootstrap carousel for the slider , on each slide there is some text over it.
I would like that text over the slides to aappear letter by letter.
I have almost solved it..
But there are 2 issues
On first slide the text doesn't come up at all
If the user goes to some other tab on the browser means if the current window is not in focus ,then everything gets messed up.
Here is my fiddle
HTML
<main>
<div class="container">
<div class="block-wrap">
<div id="js-carousel" class="carousel slide" data-ride="carousel">
<!-- Wrapper for slides -->
<div class="carousel-inner" role="listbox">
<div class="item active">
<img src="http://cdn.theatlantic.com/assets/media/img/photo/2015/11/images-from-the-2016-sony-world-pho/s01_130921474920553591/main_900.jpg?1448476701" alt="Chania">
<div class="caption">
<div class="mystring hide">companies with Inbound Marketing</div>
<h4>We help <div class="demo-txt"></div> </h4>
</div>
</div>
<div class="item">
<img src="http://cdn.theatlantic.com/assets/media/img/photo/2015/11/images-from-the-2016-sony-world-pho/s01_130921474920553591/main_900.jpg?1448476701" alt="Chania">
<div class="caption">
<div class="mystring hide">companies with Inbound Marketing</div>
<h4>We help <div class="demo-txt "></div> </h4>
</div>
</div>
<div class="item">
<img src="http://cdn.theatlantic.com/assets/media/img/photo/2015/11/images-from-the-2016-sony-world-pho/s01_130921474920553591/main_900.jpg?1448476701" alt="Flower">
<div class="caption">
<div class="mystring hide">2companies with Inbound Marketing</div>
<h4>We help <div class="demo-txt"></div> </h4>
</div>
</div>
<div class="item">
<img src="http://cdn.theatlantic.com/assets/media/img/photo/2015/11/images-from-the-2016-sony-world-pho/s01_130921474920553591/main_900.jpg?1448476701" alt="Flower">
<div class="caption">
<div class="mystring hide">3companies with Inbound Marketing</div>
<h4>We help <div class="demo-txt"></div> </h4>
</div>
</div>
<div class="overlay-effect"></div>
</div>
</div>
</div>
</div>
</main>
JS:
$(document).ready(function() {
$('#js-carousel').carousel({
interval: 5000
});
$('#js-carousel').on('slid.bs.carousel', function () {
var showText = function (target, message, index, interval) {
if (index < message.length) {
$(target).append(message[index++]);
setTimeout(function () { showText(target, message, index, interval); }, interval);
}
}
var str = $(this).find(".active .mystring").html();
$('.active .demo-txt').html("");
showText(".active .demo-txt", str, 0, 100);
});
});
Instead of settimeout use setInterval function. Also use clearInterval to clear schedular when a new slide begin. (I think this is your second problem.)
Here is your target js file:
$(document).ready(function() {
$('#js-carousel').carousel({
interval: 5000
});
var handler;
var interval = 5000;
var index = 0;
function showText(target, message, index, interval) {
if (index < message.length) {
$(target).append(message[index]);
}
}
function iteration() {
if(handler){
clearInterval(handler);
}
index = 0;
var str = $(this).find(".active .mystring").html();
$('.active .demo-txt').html("");
showText(".active .demo-txt", str, index++, 100);
handler = setInterval(function(){
showText(".active .demo-txt", str, index++, 100);
}, 100);
}
//on each carousel slide change:
$('#js-carousel').on('slid.bs.carousel', iteration);
//start immediately for your first problem:
iteration.bind($('#js-carousel'))();
});
It's because your function is inside the slide event. At starting, the carousel doesn't slide...
Fiddle: https://jsfiddle.net/Lbasa2jh/5/
JS:
$(document).ready(function() {
var showText = function (target, message, index, interval) {
if (index < message.length) {
$(target).append(message[index++]);
setTimeout(function () { showText(target, message, index, interval); }, interval);
}
};
$('#js-carousel').carousel({
interval: 5000
});
var str0 = $(this).find(".active .mystring").html();
$('.active .demo-txt').html("");
showText(".active .demo-txt", str0, 0, 100);
$('#js-carousel').on('slid.bs.carousel', function () {
var str = $(this).find(".active .mystring").html();
$('.active .demo-txt').html("");
showText(".active .demo-txt", str, 0, 100);
});
});
The timer can be tricky when the tab goes inactive. I moved code around and cleared the timeout to make sure the timeout is clean when starting a new slide.
I noticed an issue (not always) when switching back from a different tab is that the carousel actually moves to next slide quicker than 5 second causing the text to be incomplete.
https://jsfiddle.net/vLwm58Ln/
$(document).ready(function() {
$('#js-carousel').carousel({
interval: 5000
});
var showText = function(target, message, index, interval) {
if (index < message.length) {
$(target).append(message[index++]);
timer = setTimeout(function() {
showText(target, message, index, interval);
}, interval);
}
}, timer;
//First time, this triggers right away instead of waiting for the slide to move
showText(".active .demo-txt", $('#js-carousel').find(".active .mystring").html(), 0, 100);
$('#js-carousel').on('slid.bs.carousel', function() {
//clear any messed up timeout from prev slide
clearTimeout(timer);
//clear message that may be incomplete from the previous text animation
$('.prevActive').removeClass('prevActive').html('');
var str = $(this).find(".active .mystring").html();
$('.active .demo-txt').addClass('prevActive').html("");
showText(".active .demo-txt", str, 0, 100);
});
});
.carousel-inner {
position: relative;
}
.carousel-inner .overlay-effect {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
}
.carousel-inner .caption {
color: #ffffff;
font-weight: bold;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
height: 100px;
z-index: 9999;
left: 5%;
}
.carousel-inner .caption h1,
.carousel-inner .caption h2 {
font-weight: bold;
line-height: 1.6;
}
.carousel-inner .caption h1 {
font-size: 64px;
}
.carousel-inner .caption h2 {
font-size: 44px;
}
.carousel-inner .demo-txt {
border-bottom: 4px solid #ec8422;
padding-bottom: 5px;
}
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.2.js"></script>
<script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<main>
<div class="container">
<div class="block-wrap">
<div id="js-carousel" class="carousel slide" data-ride="carousel">
<!-- Wrapper for slides -->
<div class="carousel-inner" role="listbox">
<div class="item active">
<img src="http://cdn.theatlantic.com/assets/media/img/photo/2015/11/images-from-the-2016-sony-world-pho/s01_130921474920553591/main_900.jpg?1448476701" alt="Chania">
<div class="caption">
<div class="mystring hide">companies with Inbound Marketing</div>
<h4>We help <div class="demo-txt"></div> </h4>
</div>
</div>
<div class="item">
<img src="http://cdn.theatlantic.com/assets/media/img/photo/2015/11/images-from-the-2016-sony-world-pho/s01_130921474920553591/main_900.jpg?1448476701" alt="Chania">
<div class="caption">
<div class="mystring hide">companies with Inbound Marketing</div>
<h4>We help <div class="demo-txt "></div> </h4>
</div>
</div>
<div class="item">
<img src="http://cdn.theatlantic.com/assets/media/img/photo/2015/11/images-from-the-2016-sony-world-pho/s01_130921474920553591/main_900.jpg?1448476701" alt="Flower">
<div class="caption">
<div class="mystring hide">2companies with Inbound Marketing</div>
<h4>We help <div class="demo-txt"></div> </h4>
</div>
</div>
<div class="item">
<img src="http://cdn.theatlantic.com/assets/media/img/photo/2015/11/images-from-the-2016-sony-world-pho/s01_130921474920553591/main_900.jpg?1448476701" alt="Flower">
<div class="caption">
<div class="mystring hide">3companies with Inbound Marketing</div>
<h4>We help <div class="demo-txt"></div> </h4>
</div>
</div>
<div class="overlay-effect"></div>
</div>
</div>
</div>
</div>
</main>
Related
I have a few elements I want to toggle wth a function, but by some reason I can't make it work. When the toggle function is executed, the console logs "cannot read the property classList of Undefined". But if I log them before the function starts I can see the elements.
Javascript
const toggle = element => {
element.classList.toggle('toggle');
};
let numberOfProyects = document.getElementsByClassName('portfolio__item'),
proyects = [],
for (var i = 0; i < numberOfProyects.length; i++) {
proyects[i] = document.getElementById(`proyect${i+1}`);
console.log(proyects[i]);
new IntersectionObserver(()=>{
toggle(proyects[i])
},{threshold: .6}).observe(proyects[i]);
};
HTML
<div class="portfolio__item toggle" id="proyect1">
<h3 class="portfolio__item-title">Podomoro Timer</h3>
<img class="portfolio__item-img" src="assets/images/Captura de pantalla (316).png">
<div class="portfolio__item-links">
<div class="overlay portfolio__item-links-overlay">
<a target="_blank" href="https://js-codetalker.github.io/Timer/" class="portfolio__item-links-overlay-link">
<img src="assets/images/world.svg" class="portfolio__item-links-overlay-link-img">
<p class="portfolio__item-links-overlay-link-txt">Go proyect</p>
</a>
</div>
<div class="overlay portfolio__item-links-overlay">
<a target="_blank" href="https://github.com/Js-codetalker/Timer" class="portfolio__item-links-overlay-link">
<img src="assets/images/github.svg" class="portfolio__item-links-overlay-link-img">
<p class="portfolio__item-links-overlay-link-txt">Go github</p>
</a>
</div>
</div>
</div>
<div class="portfolio__item toggle" id="proyect2">
<h3 class="portfolio__item-title">Sample Restaurant</h3>
<img class="portfolio__item-img" src="assets/images/Captura de pantalla (317).png">
<div class="portfolio__item-links">
<div class="overlay portfolio__item-links-overlay">
<a target="_blank" href="https://js-codetalker.github.io/restaurant-example/" class="portfolio__item-links-overlay-link">
<img src="assets/images/world.svg" class="portfolio__item-links-overlay-link-img">
<p class="portfolio__item-links-overlay-link-txt">Go proyect</p>
</a>
</div>
<div class="overlay portfolio__item-links-overlay">
<a target="_blank" href="https://github.com/Js-codetalker/restaurant-example" class="portfolio__item-links-overlay-link">
<img src="assets/images/github.svg" class="portfolio__item-links-overlay-link-img">
<p class="portfolio__item-links-overlay-link-txt">Go github</p>
</a>
</div>
</div>
</div>
What I want is to create a different observer for each element in order to remove the class "toggle" when it reach the expected space in the viewport
(almost) Always use let instead of var when defining variables inside for loops
Also, you don't need store your elements in second array.
const toggle = element => {
element.classList.toggle('toggle');
console.log(element);
};
const proyects = document.getElementsByClassName('portfolio__item');
for (let i = 0; i < proyects.length; i++) {
new IntersectionObserver(() => {
toggle(proyects[i])
}, {
threshold: .6
}).observe(proyects[i]);
};
.container
{
border: 1px solid black;
resize: both;
overflow: auto;
width: 20em;
height: 10em;
}
.container > :after
{
content: attr(id) " class is " attr(class);
}
.container > :not(.toggle) {
background-color: pink;
}
.container >.toggle {
background-color: lightgreen;
}
<div class="container">
<div class="portfolio__item toggle" id="proyect1">
<h3 class="portfolio__item-title">Podomoro Timer</h3>
</div>
<div class="portfolio__item" id="proyect2">
<h3 class="portfolio__item-title">Sample Restaurant (has not toggle by default)</h3>
</div>
<div class="portfolio__item toggle" id="proyect3">
<h3 class="portfolio__item-title">test</h3>
</div>
<div class="portfolio__item toggle" id="proyect4">
<h3 class="portfolio__item-title">test</h3>
</div>
</div>
I have three panels that have just text or text and images that I want to loop indefinitely, and be scalable from 1-1000 slides.
I have the following markup:
<div class="mb-panel-container cf">
<div class="mb-panel-section mb-slider">
<div class="mb-panel active">
<h1>1.1</h1>
<p>slide 1.1</p>
<p class="datetime"></p>
</div>
<div class="mb-panel">
<h1>1.2</h1>
<p>slide 1.2</p>
<p class="datetime"></p>
</div>
<div class="mb-panel">
<h1>1.3</h1>
<p>slide 1.3</p>
<p class="datetime"></p>
</div>
</div>
<div class="mb-panel-section mb-slider">
<div class="mb-panel active">
<h1>2.1</h1>
<p>slide 2.1</p>
<p class="datetime"></p>
</div>
<div class="mb-panel">
<h1>2.2</h1>
<p>slide 2.2</p>
<p class="datetime"></p>
</div>
<div class="mb-panel">
<h1>2.3</h1>
<p>slide 2.3</p>
<p class="datetime"></p>
</div>
</div>
<div class="mb-panel-section mb-slider">
<div class="mb-panel active">
<h1>3.1</h1>
<p>slide 3.1</p>
<p class="datetime"></p>
</div>
<div class="mb-panel">
<h1>3.2</h1>
<p>slide 3.2</p>
<p class="datetime"></p>
</div>
<div class="mb-panel">
<h1>3.3</h1>
<p>slide 3.3</p>
<p class="datetime"></p>
</div>
</div>
</div>
And the following script:
<script>
$(document).ready(function() {
var items = $(".mb-panel"),
currentItem = items.filter(".active");
window.setInterval( function() {
var nextItem = currentItem.next();
currentItem.removeClass("active");
if( nextItem.length ) {
currentItem = nextItem.addClass("active");
} else {
currentItem = items.first().addClass("active");
}
}, 5000);
});
</script>
Unfortunately I am ending up with something like this:
Essentially, the first run of the panels work, but when it gets to the loops it stops for the other panels apart from column 1. I will be opening this up to allow the users to add as many notices per panel as they need, but require it to loop back to the beginning for each column once it reaches the last slide.
You have to pick the exact element with .eq(index) and change the index, depending - if it reached the max allowed length.
$('.mb-slider').each(function(){ // looping for each slider block
let panels = $(this).find('.mb-panel'); // collecting current slides
let len = panels.length;
let index = 0;
setTimeout(function loop(){
panels.eq(index).removeClass('active');
index = (index == len - 1) ? 0 : index + 1; // Google → Ternary operator
panels.eq(index).addClass('active');
setTimeout(loop, 1000);
}, 1000);
});
.mb-panel {
display: none;
border: 2px solid orange;
margin: 5px;
padding: 5px;
}
.mb-panel.active { display: block; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="mb-panel-container cf">
<div class="mb-panel-section mb-slider">
<div class="mb-panel active">1-1</div>
<div class="mb-panel">1-2</div>
<div class="mb-panel">1-3</div>
</div>
<div class="mb-panel-section mb-slider">
<div class="mb-panel active">2-1</div>
<div class="mb-panel">2-2</div>
<div class="mb-panel">2-3</div>
<div class="mb-panel">2-4</div>
</div>
<div class="mb-panel-section mb-slider">
<div class="mb-panel active">3-1</div>
<div class="mb-panel">3-2</div>
<div class="mb-panel">3-3</div>
<div class="mb-panel">3-4</div>
<div class="mb-panel">3-5</div>
</div>
</div>
I've used self-calling setTimeout chain just because like that trick. Here you can use setInterval as well. But in some cases, it make sense - not to call function repetitively, while the previous step haven't completed yet.
Translated into native JS ( find 10 differences :D ):
let slider = document.querySelectorAll('.mb-slider');
for( let i = 0; i < slider.length; i++ ){
let panels = slider[i].querySelectorAll('.mb-panel');
let len = panels.length;
let index = 0;
setTimeout(function loop(){
panels[index].classList.remove('active');
index = (index == len - 1) ? 0 : index + 1;
panels[index].classList.add('active');
setTimeout(loop, 1000);
}, 1000);
}
.mb-panel {
display: none;
border: 2px solid orange;
margin: 5px;
padding: 5px;
}
.mb-panel.active { display: block; }
<div class="mb-panel-container cf">
<div class="mb-panel-section mb-slider">
<div class="mb-panel active">1-1</div>
<div class="mb-panel">1-2</div>
<div class="mb-panel">1-3</div>
</div>
<div class="mb-panel-section mb-slider">
<div class="mb-panel active">2-1</div>
<div class="mb-panel">2-2</div>
<div class="mb-panel">2-3</div>
<div class="mb-panel">2-4</div>
</div>
<div class="mb-panel-section mb-slider">
<div class="mb-panel active">3-1</div>
<div class="mb-panel">3-2</div>
<div class="mb-panel">3-3</div>
<div class="mb-panel">3-4</div>
<div class="mb-panel">3-5</div>
</div>
</div>
I'm trying to have it where pressing "btn1" alone populates the sidebar. I tried $("#container").on("click", ".btn1", function() but it doesn't work.
$("#container").on("click", ".item", function() {
$("#title").text($(this).find(".title").text());
var itemImgSrc = $(this).find(".image").attr("src");
$("#image")
.css("background-image", 'url("' + itemImgSrc + '")')
.css("background-repeat", "no-repeat");
});
#container {
display: flex;
height: 100px;
}
.image {
height: 100px;
}
#image {
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<!-- Item 1 -->
<div class="item">
<button class="btn1"></button>
<div class="title">Dog</div>
<img class="image" src="http://cdn2-www.dogtime.com/assets/uploads/2011/01/file_23244_what-is-the-appenzeller-sennenhunde-dog-300x189.jpg">
</div>
<!-- Item 2 -->
<div class="item">
<button class="btn1"></button>
<div class="title">Cat</div>
<img class="image" src="https://www.royalcanin.com/~/media/Royal-Canin/Product-Categories/cat-adult-landing-hero.ashx">
</div>
<!-- Sidebar Div -->
</div>
<div class="modal">
<h2 id="title"></h2>
<div id="image"></div>
</div>
.title and .image are not contained in .btn1. You need to go up to the containing .item and then find them.
$("#container").on("click", ".btn1", function() {
var item = $(this).closest(".item");
$("#title").text(item.find(".title").text());
var itemImgSrc = item.find(".image").attr("src");
$("#image")
.css("background-image", 'url("' + itemImgSrc + '")')
.css("background-repeat", "no-repeat");
});
#container {
display: flex;
height: 100px;
}
.image {
height: 100px;
}
#image {
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<!-- Item 1 -->
<div class="item">
<button class="btn1"></button>
<div class="title">Dog</div>
<img class="image" src="http://cdn2-www.dogtime.com/assets/uploads/2011/01/file_23244_what-is-the-appenzeller-sennenhunde-dog-300x189.jpg">
</div>
<!-- Item 2 -->
<div class="item">
<button class="btn1"></button>
<div class="title">Cat</div>
<img class="image" src="https://www.royalcanin.com/~/media/Royal-Canin/Product-Categories/cat-adult-landing-hero.ashx">
</div>
<!-- Sidebar Div -->
</div>
<div class="modal">
<h2 id="title"></h2>
<div id="image"></div>
</div>
You could also use $(this).siblings(".title') and $(this).siblings(".image").
You need to change $(this) to $(.btn1).
$(this) being the button clicked works for .btn1 and not for .btn2, changing it from dynamic $(this) to always looking for .link in .btn1 should solve it.
Have you tried using $(this).parent().find(".title"). You could move up the heirarchy and get the element from there and then
$("#container").on("click", ".item", function() {
$("#title").text($(this).parent().find(".title").text());
var itemImgSrc = $(this).parent().find(".image").attr("src");
$("#image")
.css("background-image", 'url("' + itemImgSrc + '")')
.css("background-repeat", "no-repeat");
});
#container {
display: flex;
height: 100px;
}
.image {
height: 100px;
}
#image {
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<!-- Item 1 -->
<div class="item">
<button class="btn1"></button>
<div class="title">Dog</div>
<img class="image" src="http://cdn2-www.dogtime.com/assets/uploads/2011/01/file_23244_what-is-the-appenzeller-sennenhunde-dog-300x189.jpg">
</div>
<!-- Item 2 -->
<div class="item">
<button class="btn1"></button>
<div class="title">Cat</div>
<img class="image" src="https://www.royalcanin.com/~/media/Royal-Canin/Product-Categories/cat-adult-landing-hero.ashx">
</div>
<!-- Sidebar Div -->
</div>
<div class="modal">
<h2 id="title"></h2>
<div id="image"></div>
</div>
Also try using an index with the find method. it returns an array but i dont think that giving index is necessary when there is only one element.
something like this
$(this).parent().find(".item")[0].text();
So, I'm trying to obtain multiple slideshows on my website.
I have done almost everything, excepting the fact that when I press a picture, the modal of previews is showing, but the clicked image is not showing up. I have to use the buttons of the slideshow to go through them and make the first one to appear.
**
If you don't want to go along this whole code, here you can see what's happening: http://beta.eduardstefan.com
**
I am not trying to promote myself, I just think that I am not quite easy to understand without the example
So, my question, how can I make the first picture to show up when I press one, or why it's not happening, what is bad with my code?
My html:
<div class="portfolio-slideshow">
<a class="prev" onclick="slide(0,-1)">❮</a>
<div class="slide"> <img src="img/dailyui/008.png" class="slideimg_0" id="0" data-no="0"> </div>
<div class="slide"> <img src="img/dailyui/007.jpg" class="slideimg_0" id="1" data-no="0"> </div>
<div class="slide"> <img src="img/dailyui/006.jpg" class="slideimg_0" id="2" data-no="0"> </div>
<div class="slide"> <img src="img/dailyui/003.jpg" class="slideimg_0" id="3" data-no="0"> </div>
<a class="next" onclick="slide(0,1)">❯</a>
</div>
<div class="portfolio-slideshow">
<a class="prev" onclick="slide(2,-1)">❮</a>
<div class="slide"> <img src="img/dailyui/008.png" class="slideimg_2" id="0" data-no="2"> </div>
<div class="slide"> <img src="img/dailyui/007.jpg" class="slideimg_2" id="1" data-no="2"> </div>
<div class="slide"> <img src="img/dailyui/006.jpg" class="slideimg_2" id="2" data-no="2"> </div>
<div class="slide"> <img src="img/dailyui/003.jpg" class="slideimg_2" id="3" data-no="2"> </div>
<a class="next" onclick="slide(2,1)">❯</a>
</div>
<div class="imgpreview">
<i class="fa fa-close" onclick="closepreview()"></i>
<div class="slidepreview no_0">
<a class="prev" onclick="slide(1,-1)">❮</a>
<div class="slidep"> <img src="img/dailyui/008.png" class="slideimg_1" id="0"> </div>
<div class="slidep"> <img src="img/dailyui/007.jpg" class="slideimg_1" id="1"> </div>
<div class="slidep"> <img src="img/dailyui/006.jpg" class="slideimg_1" id="2"> </div>
<div class="slidep"> <img src="img/dailyui/003.jpg" class="slideimg_1" id="3"> </div>
<a class="next" onclick="slide(1,1)">❯</a>
</div>
<div class="slidepreview no_2">
<a class="prev" onclick="slide(3,-1)">❮</a>
<div class="slidep"> <img src="img/dailyui/008.png" class="slideimg_3" id="0"> </div>
<div class="slidep"> <img src="img/dailyui/007.jpg" class="slideimg_3" id="1"> </div>
<div class="slidep"> <img src="img/dailyui/006.jpg" class="slideimg_3" id="2"> </div>
<div class="slidep"> <img src="img/dailyui/003.jpg" class="slideimg_3" id="3"> </div>
<a class="next" onclick="slide(3,1)">❯</a>
</div>
</div>
SCSS:
.portfolio-slideshow{
width: 30%;
display: flex;
justify-content: space-between;
align-items: center;
}
.slide{
padding:0 35px;
display: block;
img{
display: none;
max-height:40vh;
max-width:100%;
}
}
.prev,.next{
display: flex;
align-items: center;
justify-content: center;
}
.imgpreview{
display: none;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0,0,0,0.9);
justify-content: center;
align-items: center;
padding: 50px;
}
.slidepreview{
display: none;
align-items: center;
justify-content: center;
.slidep{
display: block;
img{
display: none;
max-height: 85vh;
max-width: 85vw;
}
}
And Javascript:
var slideIndex = [0,0,0,0,0,0,0,0]
function showSlides(){
var aux = slideIndex.length;
var i;
for(i=0; i<aux; i+=2) { slide(i,0); }
}
function slide(n,m){
var i;
var aux = document.getElementsByClassName("slideimg_" + n);
var aux2 = aux.length - 1;
if (slideIndex[n] == 3 && m == 1) slideIndex[n] = -1;
if (slideIndex[n] == 0 && m == -1) slideIndex[n] = 4;
slideIndex[n] += m;
if (slideIndex[n] < 0) slideIndex = aux2;
else if (slideIndex[n] > aux2) slideIndex = 0;
for(i=0; i<aux.length; i++){
aux[i].style.display = "none";
aux[i].parentElement.style.display = 'none';
}
aux[slideIndex[n]].style.display = "block";
aux[slideIndex[n]].parentElement.style.display = 'block';
}
function closepreview(){
$('.imgpreview').css("display" , "none");
$('.slidepreview').css("display" , "none")
}
$(document).ready(function() {
$(".slide img").click(function(){
var id = $(this).attr('id');
var no = $(this).attr('data-no');
var no2 = no + 1;
$(".imgpreview").css("display" , "flex");
$(".no_" + no).css("display" , "flex");
$("img#" + id + ".slideimg_" + no2).css("display" , "block");
slideIndex[no2] = id;
});
}).resize();
The IDs must be unique.
Instead of inline event handlers I would suggest to attach them to the js code (separate html from js code).
I removed all IDs and I changed everything in jQuery using:
.index()
.toggle( display )
.nextAll(), .next(), .prev() and .prevAll()
I used a class: active. This class is used to mark the current active element. Moreover, every time I need to move next or prev I move this class to the corresponding element. This class takes track of which img must be shown.
The snippet:
$(document).ready(function() {
//
// Toggle visibility
//
$('.slide:not(.active), .slide:not(.active) img').toggle(false);
$('.slide.active, .slide.active img').toggle(true);
//
// closing preview....
//
$('.imgpreview .fa.fa-close').on('click', function(e) {
$('.imgpreview, .slidepreview').css("display" , "none");
//
// ...remove active class and toggle visibility
//
$('.imgpreview, .slidepreview').find('.active, .active img').toggleClass(false).removeClass('active');
});
//
// on prev....
//
$(".prev").on('click', function(e) {
//
// get the active element and so the previous one
//
var active = $(this).nextAll('.slide.active');
var prev = active.prev('.slide');
if (prev.length == 0) {
//
// if at the beginning take the last one
//
prev = $(this).nextAll('.slide').last();
}
//
// move active class and toggle visibility
//
active.removeClass('active');
prev.addClass('active').find('img').andSelf().toggle(true);
$('.slide:not(.active), .slide:not(.active) img').toggle(false);
});
$(".next").on('click', function(e) {
//
// get the active element and so the next one
//
var active = $(this).prevAll('.slide.active');
var next = active.next('.slide');
if (next.length == 0) {
//
// if at the end take the first one
//
next = $(this).prevAll('.slide').last();
}
//
// move active class and toggle visibility
//
active.removeClass('active');
next.addClass('active').find('img').andSelf().toggle(true);
$('.slide:not(.active), .slide:not(.active) img').toggle(false);
});
$(".slide img").on('click', function(e) {
//
// take the index of curr element in the parent element
//
var idx = $(this).closest('div.slide').index();
var no = $(this).data('no');
$('.imgpreview, .no_' + no).css('display' , 'flex');
$('.no_' + no).children().eq(idx).addClass('active');
$('.no_' + no).find('.slide:not(.active), .slide:not(.active) img').toggle(false);
$('.no_' + no).find('.slide.active, .slide.active img').toggle(true);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="http://beta.eduardstefan.com/css/style.css">
<link rel="stylesheet" href="http://beta.eduardstefan.com/css/font-awesome.css">
<div class="portfolio-slideshow">
<a class="prev">❮</a>
<div class="slide active"> <img src="http://beta.eduardstefan.com/img/dailyui/008.png" class="slideimg_0" data-no="0"></div>
<div class="slide"> <img src="http://beta.eduardstefan.com/img/dailyui/007.jpg" class="slideimg_0" data-no="0"></div>
<div class="slide"> <img src="http://beta.eduardstefan.com/img/dailyui/006.jpg" class="slideimg_0" data-no="0"></div>
<div class="slide"> <img src="http://beta.eduardstefan.com/img/dailyui/003.jpg" class="slideimg_0" data-no="0"></div>
<a class="next">❯</a>
</div>
<div class="portfolio-slideshow">
<a class="prev">❮</a>
<div class="slide active"> <img src="http://beta.eduardstefan.com/img/dailyui/008.png" class="slideimg_2" data-no="2"></div>
<div class="slide"> <img src="http://beta.eduardstefan.com/img/dailyui/007.jpg" class="slideimg_2" data-no="2"></div>
<div class="slide"> <img src="http://beta.eduardstefan.com/img/dailyui/006.jpg" class="slideimg_2" data-no="2"> </div>
<div class="slide"> <img src="http://beta.eduardstefan.com/img/dailyui/003.jpg" class="slideimg_2" data-no="2"></div>
<a class="next">❯</a>
</div>
<div class="imgpreview">
<i class="fa fa-close"></i>
<div class="slidepreview no_0">
<a class="prev" onclick="slide(1,-1)">❮</a>
<div class="slide"> <img src="http://beta.eduardstefan.com/img/dailyui/008.png" class="slideimg_1"></div>
<div class="slide"> <img src="http://beta.eduardstefan.com/img/dailyui/007.jpg" class="slideimg_1"></div>
<div class="slide"> <img src="http://beta.eduardstefan.com/img/dailyui/006.jpg" class="slideimg_1"></div>
<div class="slide"> <img src="http://beta.eduardstefan.com/img/dailyui/003.jpg" class="slideimg_1"></div>
<a class="next">❯</a>
</div>
<div class="slidepreview no_2">
<a class="prev">❮</a>
<div class="slide"> <img src="http://beta.eduardstefan.com/img/dailyui/008.png" class="slideimg_3"></div>
<div class="slide"> <img src="http://beta.eduardstefan.com/img/dailyui/007.jpg" class="slideimg_3"></div>
<div class="slide"> <img src="http://beta.eduardstefan.com/img/dailyui/006.jpg" class="slideimg_3"></div>
<div class="slide"> <img src="http://beta.eduardstefan.com/img/dailyui/003.jpg" class="slideimg_3"></div>
<a class="next">❯</a>
</div>
</div>
At least one problem is here:
var no = $(this).attr('data-no');
var no2 = no + 1;
no is a string so if no is "0", then no + 1 is "01", so instead you can do this:
var no = $(this).attr('data-no');
var no2 = Number(no) + 1;
https://codepen.io/anon/pen/MmwdZb?editors=1111
Beyond that, why re-invent the wheel? There are plenty of good slideshow plugins available.
I have multiple div elements with same class dot under parent div like this
<div id="dots">
<div class="dot"> . </div>
<div class="dot"> . </div>
<div class="dot"> . </div>
...
<div class="dot"> . </div>
</div>
How can I using JavaScript select all elements with class="dot" and on every 5 seconds apply certain class on random element.
randomElement.addClass('someClass');
What you need to do is basically first select all dots, then on each periodic activation run remove previously set class and set it again to random element with index within range from 0 to dots count - 1.
Here is an example.
var $dots = $('#dots .dot');
function activate() {
$dots.removeClass('active')
.eq([Math.floor(Math.random()*$dots.length)])
.addClass('active');
setTimeout(activate, 1000);
}
activate();
#dots .dot {
display: inline-block;
height: 50px;
width: 50px;
background: coral;
border-radius: 50%;
opacity: 0.2;
transition: opacity .3s ease;
}
#dots .dot.active {opacity: 1;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="dots">
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
</div>
How about this?
function addClassToRandomDotElement(){
var dotElements = document.getElementsByClassName('dot');
var totalDotElements = dotElements.length;
var randomNumber = Math.floor(Math.random() * totalDotElements ) + 1;
var randomDotElement = dotElements[randomNumber];
randomDotElement.addClass('someClass');
}
setInterval(function(){
addClassToRandomDotElement();
},5000);
Still one more different way, easy to understand.
DEMO
var noofdot = $(".dot").length;
setInterval(function () {
$(".dot").removeClass("someClass");
var x = Math.floor((Math.random() * noofdot) + 1);
$(".dot:nth-child(" + x + ")").addClass("someClass");
}, 5000);
.someClass
{
background:green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="dots">
<div class="dot">.</div>
<div class="dot">.</div>
<div class="dot">.</div>...
<div class="dot">.</div>
</div>
Here is an iteration over all elements:
iteration over all elements
Add class to random elements
Remove that elements from the iteration list.
var elements = document.getElementsByClassName("dot");
setInterval(function() {
var random = Math.floor(Math.random() * elements.length);
elements[random].className += " extra";
delete elements[random];
}, 1000);
//change 1000 to 5000. This is the interval speed in milisec.
.extra {
font-size: 200%;
background-color: cornflowerblue;
width: 50px;
}
<div class="container">
<div class="dot">Test</div>
<div class="dot">Test</div>
<div class="dot">Test</div>
<div class="dot">Test</div>
</div>
I think the below should work for you.
window.radomNo = 0;
setInterval(function(){
if(radomNo) $(".dot:eq("+ radomNo +")").toggleClass("randomcss");
window.radomNo = Math.floor((Math.random() * $(".dot").length) + 1);
$(".dot:eq("+ radomNo +")").toggleClass("randomcss");
},1000);
.randomcss {
background : yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="dots">
<div class="dot"> . </div>
<div class="dot"> . </div>
<div class="dot"> . </div>
<div class="dot"> . </div>
<div class="dot"> . </div>
<div class="dot"> . </div>
<div class="dot"> . </div>
<div class="dot"> . </div>
<div class="dot"> . </div>
<div class="dot"> . </div>
<div class="dot"> . </div>
<div class="dot"> . </div>
<div class="dot"> . </div>
</div>
http://jsfiddle.net/kishoresahas/7qgvru5p/
Here is another simple way:
function changeColor(){
var randInt = getRandomInt(0, $(".dot:not(.newStyle)").length -1);
$($(".dot:not(.newStyle)")[randInt]).addClass('newStyle');
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
setInterval(function(){
changeColor();
},3000);
.newStyle{background-color:green;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="dot">testing</div>
<div class="dot">test</div>
<div class="dot">cool</div>
<div class="dot">more</div>
<div class="dot">cat</div>
<div class="dot">lol</div>
if you use jquery you can try the following:
randomElements = jQuery("div").get().sort(function(){
return Math.round(Math.random())-0.5
}).slice(0,5)