Creating a dynamic width items for carousel slider - javascript

I'm currently in the middle making my carousel responsive. So far I've managed to make it responsive only if the user resizes and refreshes browser only then it will resize programmatically. How can I make it resize without having to refresh the browser.
Update:
I tried working with the answers below. Currently it stays on a fixed value even if I resize browser. Inside my css there is no fixed value placed
$(document).ready(function() {
var sliderWidth = 0;
var sliderContainer = $('.slider-container');
var slider = $('.slider-container .slider');
var sliderItems = $('.slider li');
var sliderContainerWidth = sliderContainer.width();
sliderItems.width(sliderContainerWidth / 2);
$('.slider-container ul.slider').children().each(function() {
sliderWidth += $(this).outerWidth();
slider.width(sliderWidth + 1000);
});
$('.btns .prev').on('click', function() {
prevSlide();
})
function prevSlide() {
var sliderItemsWidth = sliderItems.width();
var leftIndent = parseInt($(sliderItems).css('left')) - sliderItemsWidth;
function animate() {
$('.slider-container .slider:not(:animated)').animate({
'left': leftIndent
}, 100)
}
animate();
}
})
.wrapper {
max-width: 1280px;
margin: 0 auto;
background-color: #ccc;
}
.wrapper .slider-container {
float: left;
position: relative;
overflow: hidden;
width: 100%;
background-color: beige;
}
.wrapper .slider-container .slider {
display: flex;
flex-wrap: wrap;
position: relative;
}
.wrapper .slider-container .slider li {
height: 300px;
background-color: #ccc;
position: relative;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="slider-container">
<ul class="slider">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<ul class="btns">
<li class="prev">prev</li>
<li class="next">next</li>
</ul>
</div>
</div>

As per my comments, you can put the resizing bits into a function and call that on window resize:
$(document).ready(function() {
var sliderContainer = $('.slider-container');
var slider = $('.slider-container .slider');
var sliderItems = $('.slider li');
function resize() {
var sliderWidth = 0;
var sliderContainerWidth = sliderContainer.width();
sliderItems.width(sliderContainerWidth / 2);
$('.slider-container ul.slider').children().each(function() {
sliderWidth += $(this).outerWidth();
slider.width(sliderWidth + 1000);
});
}
$('.btns .prev').on('click', function() {
prevSlide();
})
function prevSlide() {
var sliderItemsWidth = sliderItems.width();
var leftIndent = parseInt($(sliderItems).css('left')) - sliderItemsWidth;
function animate() {
$('.slider-container .slider:not(:animated)').animate({
'left': leftIndent
}, 100)
}
animate();
}
resize(); // call onload
$(window).on('resize', function () {
resize(); // call when browser is resized
});
})

Related

setInterval issue in custom jquery image slider with both auto slide and buttons

I am creating a custom image slider with custom slide effect in jQuery which has both next & previous buttons and also slides automatically with 5 seconds timeout. Although it works nicely in a quick look but sometimes( I dont know exactly when, maybe when I press the buttons or if I leave it open for some time and minimize the window) the iterval bugs and the slides change after 1 second or less. Also when i press the button i tell it to 1) clear iterval 2) change slide 3) set interval again which means that after i change a slide with the button the timer is set to 5 seconds from the start but this is not happening all the times.Here is the code.
$(document).ready(function() {
'use strict';
var $carousel = $('.carousel');
var $nextBtn = $('#next');
var $prevBtn = $('#prev');
var animationSpeed = 1000;
var pause = 5000;
var interval;
function nextSlide() {
$('.carousel__list').animate({
left: '-200%'
}, 500, function() {
$('.carousel__list').css('left', '-100%');
$('.carousel__item').last().after($('.carousel__item').first());
});
}
function prevSlide() {
$('.carousel__list').animate({
left: '0%'
}, 400, function() {
$('.carousel__list').css('left', '-100%');
$('.carousel__item').first().before($('.carousel__item').last());
});
}
function startSlider() {
interval = setInterval(function() {
nextSlide();
}, pause);
}
function stopSlider() {
clearInterval(interval);
}
$carousel.on('mouseenter', stopSlider).on('mouseleave', startSlider);
startSlider();
$nextBtn.on('click', function() {
stopSlider();
nextSlide();
startSlider();
});
$prevBtn.on('click', function() {
stopSlider();
prevSlide();
startSlider();
});
});
*,
*::after,
*::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.carousel {
width: 100%;
height: 65vh;
overflow: hidden;
position: relative;
}
.carousel__list {
width: 400%;
height: 100%;
left: -100%;
position: relative;
list-style: none;
}
.carousel__item {
width: calc(100% / 4);
height: 100%;
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="carousel">
<ul class="carousel__list">
<li class="carousel__item" style="background-color: red"></li>
<li class="carousel__item" style="background-color: green"></li>
<li class="carousel__item" style="background-color: blue"></li>
<li class="carousel__item" style="background-color: yellow"></li>
</ul>
</section>
<button id="prev">PREVIOUS</button>
<button id="next">NEXT</button>
And here is a codepen: https://codepen.io/anon/pen/erpyJj
You are creating more intervals than you think and you don't actually clear each one because you overwrite the interval variable and then you don't a have a reference to the previous intervals, which may still be active.
What you could do is put every interval you create in an array, then when you need to stop all intervals, iterate through that array, clear each interval and empty the array.
// ...
var intervals = [];
// ...
function stopSlider() {
console.log("stopSlider() intervals (Before clear): ", intervals);
intervals.forEach(function(interval) {
clearInterval(interval); // stop one interval
});
intervals = []; // clear the array
console.log("stopSlider() intervals (After clear): ", intervals);
}
Here is your demo with many console logs. You can see that it doesn't matter how much you click on any button, the slider only automatically slides every 5 s.
$(document).ready(function() {
"use strict";
//cache dom elements
var $carousel = $(".carousel");
var $nextBtn = $("#next");
var $prevBtn = $("#prev");
var animationSpeed = 1000;
var pause = 5000;
var intervals = [];
function nextSlide() {
console.log("nextSlide() intervals: ", intervals);
$(".carousel__list").animate({
left: "-200%"
}, 500, function() {
$(".carousel__list").css("left", "-100%");
$(".carousel__item")
.last()
.after($(".carousel__item").first());
});
}
function prevSlide() {
console.log("prevSlide() intervals: ", intervals);
$(".carousel__list").animate({
left: "0%"
}, 400, function() {
$(".carousel__list").css("left", "-100%");
$(".carousel__item")
.first()
.before($(".carousel__item").last());
});
}
function startSlider() {
console.log("startSlider() interval (BEFORE): ", intervals);
var interval = setInterval(function() {
nextSlide();
}, pause);
intervals.push(interval);
console.log("startSlider() interval (AFTER): ", intervals);
}
function stopSlider() {
console.log("stopSlider() intervals (Before clear): ", intervals);
intervals.forEach(function(interval) {
clearInterval(interval); // stop one interval
});
intervals = []; // clear the array
console.log("stopSlider() intervals (After clear): ", intervals);
}
$carousel.on("mouseenter", stopSlider).on("mouseleave", startSlider);
startSlider();
$nextBtn.on("click", function() {
stopSlider();
nextSlide();
startSlider();
});
$prevBtn.on("click", function() {
stopSlider();
prevSlide();
startSlider();
});
});
*,
*::after,
*::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.carousel {
width: 100%;
height: 20vh;
overflow: hidden;
position: relative;
}
.carousel__list {
width: 400%;
height: 100%;
left: -100%;
position: relative;
list-style: none;
}
.carousel__item {
width: calc(100% / 4);
height: 100%;
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="carousel">
<ul class="carousel__list">
<li class="carousel__item" style="background-color: red"></li>
<li class="carousel__item" style="background-color: green"></li>
<li class="carousel__item" style="background-color: blue"></li>
<li class="carousel__item" style="background-color: yellow"></li>
</ul>
</section>
<button id="prev">PREVIOUS</button>
<button id="next">NEXT</button>

setting the browser's width as a variable in scss

How to get the browser's width to use it as a VARIABLE?
I know about the #media. what I need is getting the width and do some calculation to it
I tried using jQuery, it works great if the browser's width is FIXED, but when I resize the browse window it doesn't work
here is what I want to do:
html
<section id="slider">
<div class="slides">
<div class="slide">
<h1>silde 1</h1>
<p>Lorem ipsum dolor</p>
</div>
<div class="slide">
<h1>silde 2</h1>
<p>Lorem ipsum dolor</p>
</div>
</div> </section>
SCSS
$browser-width: (BROWSER WIDTH HERE) * .75 ;
#slider {
overflow: hidden;
position: relative;
margin: auto;
width: $browser-width;
.slides {
display: block;
margin: 0;
padding: 0;
width: 6000px;
}
.slide {
width: $browser-width;
display: inline-block;
float: left;
text-align: center;
}
}
What I did as a temporary solution is this:
using jQuery:
$(document).ready(function(){
var width = $(window).width() * .75;
var $slider = $('#slider');
var $slideContainer = $slider.find('.slides');
var $slides = $slideContainer.find('.slide');
$slider.css("width", width);
$slides.css("width", width);
/* function to make the slider here */
});
width = 75% doesn't work nor does width = 75vw
Never mind I found the problem
vw is the answer, it didn't work because I made this mistake in my sliding function
'margin-left' : '-=' + width
what I needed to do was this:
'margin-left' : '-=' + width + "vw"
never forget the units in your code .. lesson learned
here is my sliding function to those interested:
'use strict';
$(document).ready(function(){
var width = 75;
var animationSpeed = 1000;
var pause = 1000;
var currentSlide = 1;
var $slider = $('#slider');
var $slideContainer = $slider.find('.slides');
var $slides = $slideContainer.find('.slide');
var interval;
function startSlider(){
interval = setInterval(function() {
$slideContainer.animate({'margin-left' : '-='+width + "vw"}, animationSpeed, function(){
currentSlide++;
if (currentSlide === $slides.length){
currentSlide = 1;
$slideContainer.css('margin-left', 0);
}
});
}, pause);
}
function stopSlider(){
clearInterval(interval);
}
$slider.on('mouseenter', stopSlider).on('mouseleave', startSlider);
startSlider();
});

Programatically resize the H div and C div along with the resizer

When I click-drag (#cssNav) to the right, it is not moving proportionately along with the #html and #css div.
This might be something very obvious, but still am not able to figure it out, what am I missing here, please help?
Note: I don't want to use display:flex
codepen
$("#htmlNav").on("mousedown", dragStartH);
$("#cssNav").on("mousedown", dragStartH);
$("#jsNav").on("mousedown", dragStartH);
function dragStartH(e) {
e.preventDefault();
dragMeta = {};
dragMeta.pageX0 = e.pageX;
dragMeta.elem = this;
dragMeta.offset0 = $(this).offset();
dragMeta.codeWindow = "#" + $(e.target).attr("id").replace("Nav", "");
function handle_dragging(e) {
var change = e.pageX - dragMeta.pageX0;
var left = dragMeta.offset0.left + change;
$(dragMeta.elem).offset({ left: left });
$("#css").width($("#css").width() - change + "px");
$("#html").width($("#html").width() + change + "px");
}
function handle_mouseup(e) {
$("body")
.off("mousemove", handle_dragging)
.off("mouseup", handle_mouseup);
}
$("body").on("mouseup", handle_mouseup).on("mousemove", handle_dragging);
}
$(document).ready(function() {
var widthPercent = ($(window).width() - 30) / 3;
$("#html").width(widthPercent + "px");
$("#css").width(widthPercent + "px");
$("#js").width(widthPercent + "px");
});
html, body {
height: 100%;
margin: 0;
}
.container{
width:100%;
height: 100%;
background-color:#343;
display: flex;
flex-direction: column;
color: #fff;
margin: 0;
}
#preview, #code{
background-color:#433;
height: 50%;
width: 100%;
margin: 0;
}
#code{
border-bottom: #333 solid 2px;
width: 100%
}
#previewNav, #codeNav{
background-color:#bbb;
height: 10px;
width: 100%;
cursor: row-resize;
}
#html{
background-color: #BFB;
}
#css{
background-color: #FBB;
}
#js{
background-color: #BBF;
}
#html, #css, #js{
float: left;
width: 32%;
height: 100%;
}
#htmlNav, #cssNav, #jsNav{
background-color:#bbb;
float: left;
height:100%;
width: 10px;
cursor: col-resize;
z-index:10;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div id="codeNav"></div>
<div id="code">
<div id="htmlNav"></div>
<div id="html">H</div>
<div id="cssNav"></div>
<div id="css">C</div>
<div id="jsNav"></div>
<div id="js">J</div>
</div>
<div id="previewNav"></div>
<div id="preview">P</div>
</div>
This is how I would do it:
Keep track of which handle you press with navTypeand check if the user is holding its mouse down with dragging.
Then when the user moves the mouse in the document and it is holding its mouse down (dragging) it will move the #html, #css and #js accordingly
Change your javascript into this:
var mouseX, prevMouseX, navType, change;
var dragging = false;
$("#cssNav").mousedown(function () {
dragging = true;
navType = "css";
});
$("#jsNav").mousedown(function () {
dragging = true;
navType = "js";
});
$(document).mousemove(function (e) {
mouseX = e.pageX;
if(dragging){
e.preventDefault();
change = mouseX - prevMouseX;
if(navType == "css" && ($("#css").width() - (change)) > 0 && ($("#html").width() + (change)) > 0){
var hw = $("#html").width();
var cw = $("#css").width();
$("#html").width(hw + change);
$("#css").width(cw - change);
} else if(navType == "js" && ($("#css").width() + (change)) > 0 && ($("#js").width() - (change)) > 0){
var cw = $("#css").width();
var jw = $("#js").width();
$("#css").width(cw + change);
$("#js").width(jw - change);
}
}
prevMouseX = mouseX;
}).mouseup(function () {
dragging = false;
}).mouseleave(function () {
dragging = false;
});

How can I adjust this carousel to only pause when user mouses over one of the boxes?

I'm trying to alter this premade code so that it works for my website idea. I'm wondering how the 'pause' function can only be triggered upon the user mousing over one of the li items; otherwise, the carousel would loop forever.
How might this be achieved? I googled and was trying things like:
if ($('#element:hover').length != 0) {
pause();
}
but this is not compliant with the code. Can I receive some assistance? Thank you.
https://jsfiddle.net/lovromar/Z4VpZ/
HTML
<div id="carousel-container">
<div id="carousel-inner">
<ul id="carousel-ul">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ul>
</div>
</div>
CSS
#carousel-container {
width: 680px;
margin: 2em auto;
position: relative;
border: 1px solid #ccc;
overflow: hidden;
height: 250px;
}
#carousel-inner {
width: 680px;
float: left;
position: relative;
overflow: hidden;
}
#carousel-ul {
position:relative;
left:-160px;
list-style-type: none;
margin: 0px;
padding: 0px;
width:9999px;
padding-bottom:50px;
}
#carousel-ul li{
float: left;
width: 150px;
padding:0px;
height:186px;
margin: 50px 15px 0 15px;
position: relative;
background: #c0c0c0;
line-height: 186px;
font-size: 2em;
text-align: center;
}
JS
var Carousel = new
function() {
var wrapper = document.getElementById('carousel-container'),
timer = null;
var start = function() {
doCarousel();
};
var sliding = function() {
var item_width = $('#carousel-ul li').outerWidth() + 10;
var left_indent = parseInt($('#carousel-ul').css('left')) - item_width;
$('#carousel-ul:not(:animated)').animate({
'left': left_indent
}, 2000, 'linear', function() {
$('#carousel-ul li:last').after($('#carousel-ul li:first'));
$('#carousel-ul').css({
'left': '-160px'
});
});
};
var doCarousel = function() {
timer = setInterval(sliding, 2000);
};
var pause = function() {
clearInterval(timer);
timer = null;
};
var resume = function() {
doCarousel();
};
this.init = function() {
start();
};
}();
$(function() {
Carousel.init();
});
I made it work.
I changed the way you declare your object and it works like that:
var Carousel = {
timer :null,
wrapper: null,
init : function()
{
var self = this;
this.timer = setInterval(function(){self.sliding();}, 2000);
},
sliding : function() {
var item_width = $('#carousel-ul li').outerWidth() + 10;
var left_indent = parseInt($('#carousel-ul').css('left')) - item_width;
$('#carousel-ul:not(:animated)').animate({
'left': left_indent
}, 2000, 'linear', function() {
$('#carousel-ul li:last').after($('#carousel-ul li:first'));
$('#carousel-ul').css({
'left': '-160px'
});
})},
pause : function() {
clearInterval(this.timer);
this.timer = null;
},
resume : function() {
this.init();
},
};
$(function() {
alert("init");
Carousel.init();
$('#carousel-ul li').mouseover(function(){
//clearInterval(timer);
//timer = null;
//pause();
Carousel.pause();
});
$('#carousel-ul li').mouseout(function(){
//clearInterval(timer);
//timer = null;
//pause();
Carousel.resume();
});
});
Here is your Jsfiddle: https://jsfiddle.net/Z4VpZ/4/
Usually, I avoid using Javascript function to declare classes, I make use of js object {}, or I use the ECMASCRIPT 6 class statement.
Did you try something like that ?
$("#carousel-ul li").mouseover(function(){ Carousel.pause();});

jQuery: animated slider pager

I've set up an animated slider using jQuery:
jsFiddle demo: http://jsfiddle.net/neal_fletcher/9zRDV/
The reason being I wanted to achieve a slight overhang on the slides, i.e. while viewing slide 1 you can see some of slide 2 etc. The slider works great, perfect in fact for what I'm after, now though I'm trying to figure out if it's possible to set up a pager for this slider, the aim of which being to click on a .slide-menu-item and the slider will slide to the relevant slide, if at all possible?
One other slight problem too, is it possible to animate the slider on load? Thus, the pager will slide every 5 seconds, but you can still navigate the slider using the pager / next and previous buttons?
Any suggestions would be greatly appreciated!
HTML:
<div class="outerwrapper">
<div class="innerwrapper">
<div class="inner-slide">SLIDE 01</div>
<div class="inner-slide">SLIDE 02</div>
<div class="inner-slide">SLIDE 03</div>
<div class="inner-slide">SLIDE 04</div>
<div class="inner-slide">SLIDE 05</div>
<div class="inner-slide">SLIDE 06</div>
<div class="inner-slide">SLIDE 07</div>
</div>
</div>
<ul id="slide-menu">
<li id="one" class="slide-menu-item">01</li>
<li id="two" class="slide-menu-item">02</li>
<li id="three" class="slide-menu-item">03</li>
<li id="four" class="slide-menu-item">04</li>
<li id="five" class="slide-menu-item">05</li>
<li id="six" class="slide-menu-item">06</li>
<li id="seven" class="slide-menu-item">07</li>
</ul>
<div id="left">LEFT</div>
<div id="right">RIGHT</div>
CSS:
.outerwrapper {
position: absolute;
left: 50%;
height: 250px;
width: 400px; margin-left: -225px;
border: 1px solid black;
overflow: hidden;
padding-left: 50px;
}
.innerwrapper {
height: 250px;
width: 4000px;
}
.inner-slide {
height: 250px;
width: 350px;
float: left;
background: silver;
}
.innerwrapper div:nth-child(odd) {
background: silver;
}
.innerwrapper div:nth-child(even) {
background: red;
}
#left, #right {
position: absolute;
cursor: pointer;
}
#left {
left: 10px; bottom: 10px;
}
#right {
right: 10px; bottom: 10px;
}
#slide-menu {
position: absolute;
top: 250px;
list-style: none;
}
.slide-menu-item {
display: inline-block;
width: 50px;
cursor: pointer;
}
jQuery:
var animating = false,
slideWidth = $('.inner-slide').width(),
$wrapper = $('.outerwrapper'),
slideIndex = 2,
slideLen = $('.inner-slide').length,
build = function() {
$firstClone = $('.inner-slide').eq(0).clone();
$secondClone = $('.inner-slide').eq(1).clone();
$preLastClone = $('.inner-slide').eq(slideLen - 2).clone();
$lastClone = $('.inner-slide').eq(slideLen - 1).clone();
$wrapper.find('.innerwrapper').append($firstClone, $secondClone).prepend($preLastClone, $lastClone);
$wrapper.animate({
scrollLeft: '+=' + slideWidth * slideIndex + 'px'
}, 0);
},
slide = function(dir, speed) {
if(!animating) {
animating = true;
dir == 'right' ? slideIndex++ : slideIndex--;
slideIndex == slideLen - 1 ? slideIndex == 0 : '';
if(slideIndex == 0 && dir == 'left') {
//if the slide is at the beginning and going left
slideIndex = slideLen + 1;
$wrapper.animate({
scrollLeft: slideIndex * slideWidth + 'px'
}, 0, function() {
animating = false;
});
slideIndex--;
} else if(slideIndex == slideLen + 2 && dir == 'right') {
//if the slide is at the end and going right
slideIndex = 1;
$wrapper.animate({
scrollLeft: slideIndex * slideWidth + 'px'
}, 0, function() {
animating = false;
});
slideIndex++;
}
$wrapper.animate({
scrollLeft: slideIndex * slideWidth + 'px'
}, speed, function() {
animating = false;
});
}
};
$(function() {
build();
$('#right, #left').on('click', function() {
slide($(this).attr('id'), 600)
});
});
Add the slideTo function:
slideTo = function (index, speed) {
slideIndex = index+1;
$wrapper.animate(
{scrollLeft: slideIndex * slideWidth + 'px'},
speed, function () {animating = false;}
);
}
Then call it when you click one of the page buttons:
$('.slide-menu-item').click(function() {
var toSlideIndex = Math.round($(this).text());
slideTo(toSlideIndex, 600);
});
And then, to make it slide automatically every 5 seconds, add this:
setInterval(function() {slide("right", 600);}, 5000);
JSFiddle demo: http://jsfiddle.net/9zRDV/3/
for example ?
$('#yourFavouriteIdForButtonThree').click(function(){
slide('three', 600)
});

Categories