Simple jquery slider - javascript

I'm using mousewheel jQuery plugin and trying to create a simple slider. Here is a example but slider next and prev button not working properly.
$('.container').mousewheel(function(event, delta) {
this.scrollLeft -= (delta * 40);
event.preventDefault();
});
// next & prev option
//prev
$('.prev').click(function(){
$('.storepos').val($('.storepos').val() / 1 - 110);
$('.container').animate({scrollLeft:$('.storepos').val()}, 200);
});
//next
$('.next').click(function(){
$('.storepos').val($('.storepos').val() / 1 + 110);
$('.container').animate({scrollLeft:$('.storepos').val()}, 200);
});
.container{overflow-x:scroll}
.content {width:1600px}
.items { background:black;
color:white;
margin-left:10px;
width:100px;
height:100px;
float:left;
text-align:center
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js"></script>
<div class="container">
<div class="content">
<div class="items">1</div>
<div class="items">2</div>
<div class="items">3</div>
<div class="items">4</div>
<div class="items">5</div>
<div class="items">6</div>
<div class="items">7</div>
<div class="items">8</div>
<div class="items">9</div>
<div class="items">10</div>
</div>
</div>
Prev / Next
<input class="storepos" value="" />
Need to stop position update when next / prev items ended.

check in your onclick function the value through if statement of your storepos element
Previous button
$('.prev').click(function(){
var storepos = $(".storepos").val();
if(storepos == 0){
//Do nothing
}else{
$('.storepos').val($('.storepos').val() / 1 - 110);
$('.container').animate({scrollLeft:$('.storepos').val()}, 200);
}
});
Next button
Updated
$('.next').click(function(){
var storepos = $(".storepos").val();
var maxLength = (($(".items").length * 110) / 2);
if(storepos == maxLength){
//Do nothing
}else{
$('.storepos').val($('.storepos').val() / 1 + 110);
$('.container').animate({scrollLeft:$('.storepos').val()}, 200);
}
});

Related

Change CSS of inner div when scroll reaches that div

I am attempting to implement a scroll function where the CSS of the inner div's change when it reaches a certain height from the top.
var $container = $(".inner-div");
var containerTop = $container.offset().top;
var documentTop = $(document).scrollTop();
var wHeight = $(window).height();
var minMaskHeight = 0;
var descriptionMax = 200;
var logoMin = -200;
var maskDelta = descriptionMax - minMaskHeight;
var $jobOverview = $container.find(".right");
var $jobLogo = $container.find(".left");
var curPlacementPer = ((containerTop - documentTop) / wHeight) * 100;
var topMax = 85;
var center = 20;
var bottomMax = -15;
//console.log("Placement: " + curPlacementPer);
function applyChanges(perOpen) {
var maskHeightChange = maskDelta * (perOpen / 100);
var opacityPer = perOpen / 100;
var newDescriptionLeft = descriptionMax - maskHeightChange;
var newLogoLeft = logoMin + maskHeightChange;
if (newDescriptionLeft <= 0) newDescriptionLeft = 0;
if (newLogoLeft >= 0) newLogoLeft = 0;
if (opacityPer >= 1) opacityPer = 1;
$jobOverview.css({
transform: "translate(" + newDescriptionLeft + "%,-50%)",
opacity: opacityPer
});
$jobLogo.css({
transform: "translate(" + newLogoLeft + "%,-50%)",
opacity: opacityPer
});
}
if (window.innerWidth > 640) {
$container.removeClass("mobile");
// console.log("Placement: " + curPlacementPer);
if (curPlacementPer <= topMax /*&& curPlacementPer >= center*/ ) {
var perOpen = ((topMax - curPlacementPer) / 25) * 100;
applyChanges(perOpen);
} else if (curPlacementPer < center /*&& curPlacementPer >= bottomMax*/ ) {
var perOpen = (((bottomMax - curPlacementPer) * -1) / 25) * 100;
applyChanges(perOpen);
} else {
$jobOverview.css({
transform: "translate(200%,-50%)",
opacity: "0"
});
$jobLogo.css({
transform: "translate(-300%,-50%)",
opacity: "0"
});
}
<div class="outer-div">
<div class="inner-div first">
<div class="left"></div>
<div class="right"></div>
</div>
<div class="inner-div second">
<div class="left"></div>
<div class="right"></div>
</div>
<div class="inner-div third">
<div class="left"></div>
<div class="right"></div>
</div>
<div class="inner-div fourth">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
Currently, all of the inner div's gets changed at the same time.
I noticed that when I change the $container class to equal '.first' and specify it more, it works.
Is there any way to make the inner div's change separately, relative to its height from the top? Any way I can iterate the scroll function so I can add more inner div's in the future and not have to worry about changing my scroll function?
In raw JavaScript, this is my answer:
// Define the element -- The '#fooBar' can be changed to anything else.
var element = document.querySelector("#fooBar");
// Define how much of the element is shown before something happens.
var scrollClipHeight = 0 /* Whatever number value you want... */;
// Function to change an element's CSS when it is scrolled in.
const doSomething = function doSomething() {
/** When the window vertical scroll position plus the
* window's inner height has reached the
* top position of your element.
*/
if (
(window.innerHeight + window.scrollY) - (scrollClipHeight || 0) >=
element.getBoundingClientRect().top
)
// Generally, something is meant to happen here.
element.style = "/* Yay, some CSS! */"
};
// Call the function without an event occurring.
doSomething();
// Call the function when the 'window' scrolls.
addEventListener("scroll", doSomething, false)
This is the method I use. If there are other methods, I'd love to see them as well but this is my answer for now.
consider using 3rd party jQuery plugin for easier job, like one of these:
https://github.com/xobotyi/jquery.viewport
or
https://github.com/zeusdeux/isInViewport
then you can have additional element selector e.g.: ":in-viewport"
so you can:
$(window).on('scroll',function() {
$('div').not(':in-viewport').html('');
$('div:in-viewport').html('hello');
});
Check if current scroll offset from top is bigger than the element offset from the top:
$(window).scroll(function() {
var height = $(window).scrollTop();
var element = $('#changethis'); //change this to your element you want to add the css to
if(height > element.offset().top) {
element.addClass('black'); //add css class black (change according to own css)
}
});
Html:
<div id="changethis">Test</div>
Css:
body
{
height:2000px;
}
.black
{
background-color:black;
color:white;
padding:20px;
}
Demo:
https://codepen.io/anon/pen/WZdEap
You could easily implement this in your existing code.
Below is the sample snippet code, Hope it'll work for you:
$(document).ready(function(){
topMax = 100;
topMin = 25;
$(document).scroll(function(){
$('.inner-div').each(function(){
if($(this).offset().top-$(window).scrollTop()<=topMax && $(this).offset().top-$(window).scrollTop()>=topMin){
$(this).css({'background':'#c7c7c7'});
}else{
$(this).css({'background':'inherit'});
}
});
});
});
div{
width:100%;
border:1px solid red;
padding:5px;
}
div.inner-div{
border: 1px dashed green;
height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="outer-div">
<div class="inner-div first">
<div class="left"></div>
<div class="right"></div>
</div>
<div class="inner-div second">
<div class="left"></div>
<div class="right"></div>
</div>
<div class="inner-div third">
<div class="left"></div>
<div class="right"></div>
</div>
<div class="inner-div fourth">
<div class="left"></div>
<div class="right"></div>
</div>
</div>
Happy to help you! :)

jQuery bind / unbind not working

I'm trying to create a simple slider. Here is a example but slider next and prev button not working properly.
// next
var next = $('.next').click(function() {
var storepos = $(".storepos").val();
$('.prev').bind('click');
$('.storepos').val($('.storepos').val() / 1 + 110);
$('.container').animate({
scrollLeft: $('.storepos').val()
}, 200);
});
//prev
$('.prev').click(function() {
var storepos = $(".storepos").val();
$('.next').bind('click');
$('.storepos').val($('.storepos').val() / 1 - 110);
$('.container').animate({
scrollLeft: $('.storepos').val()
}, 200);
});
//after scrollend right event
$('.container').bind('scroll', function() {
if ($('.container').scrollLeft() + $(this).innerWidth() >= $(this)[0].scrollWidth) {
$('.next').unbind('click');
}
});
//after scrollend left event
$('.container').bind('scroll', function() {
if ($('.container').scrollLeft() < 1) {
$('.prev').unbind('click');
}
});
.container {
overflow: hidden !important
}
.container::-webkit-scrollbar {
width: 0;
height: 0
}
.content {
width: 1600px
}
.items {
background: black;
color: white;
margin-left: 10px;
width: 100px;
height: 100px;
float: left;
text-align: center
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="content">
<div class="items">1</div>
<div class="items">2</div>
<div class="items">3</div>
<div class="items">4</div>
<div class="items">5</div>
<div class="items">6</div>
<div class="items">7</div>
<div class="items">8</div>
<div class="items">9</div>
<div class="items">10</div>
</div>
</div>
Prev / Next
<input class="storeposx" value="" />
<input class="storepos" value="" />
fiddle
I see two errors. First, the previous button is active from the begging, enabling scrolling to negative values. Second, you do unbind the events when reaching the end both sides, but you're not bind them back after that.
I used two variables where I keep the buttons status. When I reach the start or end position I don't unbind them, instead I just return false on click.
// next
var next = $('.next').click(function() {
if (!nextIsActive || $('.container').is(':animated')) return false;
var storepos = $(".storepos").val();
$('.prev').bind('click');
$('.storepos').val($('.storepos').val() / 1 + 110);
$('.container').animate({
scrollLeft: $('.storepos').val()
}, 200);
});
//prev
$('.prev').click(function() {
if (!prevIsActive || $('.container').is(':animated')) return false;
var storepos = $(".storepos").val();
$('.next').bind('click');
$('.storepos').val($('.storepos').val() / 1 - 110);
$('.container').animate({
scrollLeft: $('.storepos').val()
}, 200);
});
var nextIsActive=true;
var prevIsActive=false;
//after scrollend right event
$('.container').bind('scroll', function() {
if ($('.container').scrollLeft() + $(this).innerWidth() >= $(this)[0].scrollWidth) {
nextIsActive=false;
}else{
nextIsActive=true;
}
});
//after scrollend left event
$('.container').bind('scroll', function() {
if ($('.container').scrollLeft() < 1) {
prevIsActive=false;
}else{
prevIsActive=true;
}
});
.container{overflow:hidden !important}
.container::-webkit-scrollbar {
width:0;
height:0
}
.content {width:1600px}
.items { background:black;
color:white;
margin-left:10px;
width:100px;
height:100px;
float:left;
text-align:center
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="content">
<div class="items">1</div>
<div class="items">2</div>
<div class="items">3</div>
<div class="items">4</div>
<div class="items">5</div>
<div class="items">6</div>
<div class="items">7</div>
<div class="items">8</div>
<div class="items">9</div>
<div class="items">10</div>
</div>
</div>
Prev / Next
<input class="storeposx" value="" />
<input class="storepos" value="" />

Crossbrowser solution for disable/enable scroll

Long time ago I found somewhere (on stackoverflow I think) code to scroll one window height per scroll. I tried many libraries but that script works just like I want. But it's jumpy when scrolling during animation. So I disable scroll during animation but it works only in Firefox.
I made a fiddle: https://jsfiddle.net/msoys5gc/1/
if( $(window).scrollTop() < $(window).height() * 6 ) {
window.onwheel = function(){ return false; };
}
$('html,body').stop().animate({
scrollTop: divs.eq(div).offset().top
}, 600, function() {
window.onwheel = function(){ return true; };
});
I don`t understand this:
if( $(window).scrollTop() < $(window).height() * 6 )
this will be true until you pass the six slide...
UPDATED: If you want to stop triggering the animation while it is running you can just delete the stop(). Then if you don't want to enqueue animations(and then get strange behaviors), you can just call clearQueue() when the animation has finished.
var divs = $('.section');
var dir = 'up'; // wheel scroll direction
var div = 0; // current div
$(document.body).on('DOMMouseScroll mousewheel', function (e) {
if (e.originalEvent.detail > 0 || e.originalEvent.wheelDelta < 0) {
dir = 'down';
}
else {
dir = 'up';
}
// find currently visible div :
div = -1;
divs.each(function(i){
if (div<0 && ($(this).offset().top >= $(window).scrollTop())) {
div = i;
}
});
if (dir == 'up' && div > 0) {
div--;
}
if (dir == 'down' && div < divs.length) {
div++;
}
$('html,body').animate({
scrollTop: divs.eq(div).offset().top
}, 1600, function() {
$('html,body').clearQueue();
});
return false;
});
$(window).resize(function () {
$('html,body').scrollTop(divs.eq(div).offset().top);
});
.section {
height: 100vh;
}
body{
margin: 0px !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="section" style="background: yellow;"></div>
<div class="section" style="background: green;"></div>
<div class="section" style="background: blue;"></div>
<div class="section" style="background: red;"></div>
<div class="section" style="background: violet;"></div>
<div class="section" style="background: orange;"></div>
<div class="section" style="background: black;"></div>

How do I stop clicking next too many times from breaking my image rotator?

Im new to jquery and have been trying to code a simple image rotator, it works well at the moment except for the fact that if you click the "next" of "prev" buttons too many times very quickly it will break the image rotator.
Here is the html:
<div id="viewport">
<div id="imageContainer">
<div class="image" style="background-color:red;">
<div class="title"><p>This is the title of the post</p></div>
</div>
<div class="image" style="background-color:green;">
<div class="title"><p>This is the title of the post</p></div>
</div>
<div class="image" style="background-color:yellow;">
<div class="title"><p>This is the title of the post</p></div>
</div>
<div class="image" style="background-color:brown;">
<div class="title"><p>This is the title of the post</p></div>
</div>
<div class="image" style="background-color:purple;">
<div class="title"><p>This is the title of the post</p></div>
</div>
</div>
</div>
<input type="button" name="prev" id="prev" value="prev" />
<input type="button" name="next" id="next" value="next" />
and jquery:
var ic = $('#imageContainer');
var numItems = $('.image').size();
var position = 0;
ic.css('left', '0px');
var inter;
var rotateTimeout;
function rotate(){
inter = setInterval(function(){
if (position == (numItems - 1)) {
console.log(position);
$('.image').first().insertAfter($('.image').last());
ic.css('left', '+=400px');
position--;
}
ic.animate({opacity: 0.2, left: "-=400px"}, 1500, function(){
ic.animate({opacity: 1.0}, 1000);
});
position += 1;
}, 6000);
}
rotate();
$('#prev').click(function () {
console.log(position);
if (position == 0) {
$('.image').last().insertBefore($('.image').first());
ic.css('left', '-=400px');
position++;
}
ic.animate({
left: "+=400px"
});
position -= 1;
clearInterval(inter);
clearTimeout(rotateTimeout);
rotateTimeout = setTimeout(rotate, 10000);
});
$('#next').click(function () {
if (position == (numItems - 1)) {
console.log(position);
$('.image').first().insertAfter($('.image').last());
ic.css('left', '-400px');
position--;
}
ic.animate({
left: "-=400px"
});
position += 1;
clearInterval(inter);
clearTimeout(rotateTimeout);
rotateTimeout = setTimeout(rotate, 10000);
});
Here is a demo of the rotator.
So how can I either stop the user from clicking the button too quickly, or perhaps only account for a click per two seconds to allow the rotator to do what it needs?
To limit function call frequency you can use some "Throttle" function. For example _.throttle from Underscore.js or any other implementation. It is not necessary to use whole library, only required function could be copied from there.
The event handler attachment will look like this:
$('#prev').click( _.throttle(function () { yours code... }, 2000) );

Animation gets fail

i have a script here that animate 3 divs containing product came from the database. It animate well when the page load in the first time but my problem is its not animate well after a min and everytime i refresh the page.
<html>
<script src='jquery.js'></script>
<script>
$(document).ready(function(){
$("#Slide2").hide();
$("#Slide3").hide();
});
var h = 1;
var x = setTimeout(show2, 3000);
function show1()
{
h = 1;
$("#Slide1").show();
$("#Slide2").hide();
$("#Slide3").hide();
$("#Slide1").css("left", "-400px");
$("#Slide1").animate({left:'-1px'});
clearTimeout(x);
x = setTimeout(show2, 3000);
}
function show2()
{
if(h <= 2)
{
h = 2;
$("#Slide2").show();
$("#Slide1").hide();
$("#Slide3").hide();
$("#Slide2").css("right", "-400px");
$("#Slide2").animate({right:'-1px'});
clearTimeout(x);
x = setTimeout(show3, 3000);
}
else
{
h = 2;
$("#Slide2").show();
$("#Slide1").hide();
$("#Slide3").hide();
$("#Slide2").css("left", "-400px");
$("#Slide2").animate({left:'-1px'});
clearTimeout(x);
x = setTimeout(show3, 3000);
}
}
function show3()
{
h = 3;
$("#Slide3").show();
$("#Slide2").hide();
$("#Slide1").hide();
$("#Slide3").css("right", "-400px");
$("#Slide3").animate({right:'-1px'});
clearTimeout(x);
x = setTimeout(show1, 3000);
}
</script>
<style>
#Slide1 , #Slide2, #Slide3
{
width:530px;
height:100px;
position:relative;
background:blue;
}
#container
{
width:500px;
margin:auto;
border:1pt solid black;
overflow:hidden;
height:auto;
}
</style>
<body>
<div id='container'>
<button onclick="check1()">1</button>
<button onclick="check2()">2</button>
<button onclick="check3()">3</button>
<br></br>
<div style='width:530px;margin:auto'>
<div id='Slide1'>
<div style='width:120px;height:100px;float:left;margin-left:10px;background:#ff0'></div>
<div style='width:120px;height:100px;float:left;margin-left:10px;background:#ff0'></div>
<div style='width:120px;height:100px;float:left;margin-left:10px;background:#ff0'></div>
<div style='width:120px;height:100px;float:left;margin-left:10px;margin-right:10px;background:#ff0'></div>
</div>
<div id='Slide2' >
<div style='width:120px;height:100px;float:left;margin-left:10px;background:green'></div>
<div style='width:120px;height:100px;float:left;margin-left:10px;background:green'></div>
<div style='width:120px;height:100px;float:left;margin-left:10px;background:green'></div>
<div style='width:120px;height:100px;float:left;margin-left:10px;margin-right:10px;background:green'></div>
</div>
<div id='Slide3' >
<div style='width:120px;height:100px;float:left;margin-left:10px;background:red'></div>
<div style='width:120px;height:100px;float:left;margin-left:10px;background:red'></div>
<div style='width:120px;height:100px;float:left;margin-left:10px;background:red'></div>
<div style='width:120px;height:100px;float:left;margin-left:10px;margin-right:10px;background:red'></div>
</div>
</div>
</div>
</body>
</html>
You are not clearing your previous setInterval before starting new setInterval. Use clearInterval(x) before every setInterval in your show1(), show2() and show3() . hope it ll help.
You have redundant if else loop in your show2() . check it here (http://jsfiddle.net/cJ9FK/)
Hope it'll help, Thank you

Categories