I am making a page, where on scroll down, the left side of the page will slide up, and the right side of the page will slide down.
and on scroll up, the left side of the page will slide down, and the right side of the page will slide up.
I have this working if the user ONLY scrolls once (using a mouse wheel), when you scroll multiple times (before the function has completed, the left and right side will continue to scroll and mess up. Is there a way to disable more than one scroll?
I have added my code and the fiddle below.
<div class="left">
<div id="left1" class="onLeft Side">
</div>
<div id="left2" class="onLeft Side">
</div>
<div id="left3" class="onLeft Side">
</div>
</div>
<div class="right">
<div id="right3" class="onRight Side">
</div>
<div id="right2" class="onRight Side">
</div>
<div id="right1" class="onRight Side">
</div>
</div>
$(document).ready(function(){
var wholeHeight = jQuery('.right').height();
var rightLength = jQuery('.onRight').length;
jQuery('.right').css({top:-((wholeHeight*rightLength)-wholeHeight)});
var leftHeight = jQuery('.left').height();
var leftLength = jQuery('.onLeft').length;
var tot = (leftHeight * leftLength) - leftHeight;
console.log('tot', tot)
$('body').bind('mousewheel', function(e){
var height = jQuery('.left').height();
var leftTop = jQuery('.left').position().top;
var rightTop = jQuery('.right').position().top;
if(e.originalEvent.wheelDelta /120 > 0) {
if (leftTop != 0) {
console.log('scrolling up !');
jQuery('.left').animate({top:leftTop + height});
jQuery('.right').animate({top:rightTop - height});
} else {
console.log('The up end');
}
} else {
if (leftTop != -tot) {
console.log('scrolling down !');
jQuery('.left').animate({top:leftTop - height});
jQuery('.right').animate({top:rightTop + height});
} else {
console.log('the down end')
}
}
});
});
https://jsfiddle.net/11pftj26/
Thanks
try this:
$(document).ready(function(){
var wholeHeight = jQuery('.right').height();
var rightLength = jQuery('.onRight').length;
jQuery('.right').css({top:-((wholeHeight*rightLength)-wholeHeight)});scrolling=false;
var leftHeight = jQuery('.left').height();
var leftLength = jQuery('.onLeft').length;
var tot = (leftHeight * leftLength) - leftHeight;
console.log('tot', tot)
$('body').bind('mousewheel', function(e){
if(scrolling)
return;
scrolling=true;
var height = jQuery('.left').height();
var leftTop = jQuery('.left').position().top;
var rightTop = jQuery('.right').position().top;
if(e.originalEvent.wheelDelta /120 > 0) {
if (leftTop != 0) {
console.log('scrolling up !');
jQuery('.left').animate({top:leftTop + height},{done:function(){scrolling=false}});
jQuery('.right').animate({top:rightTop - height},{done:function(){scrolling=false}});
} else {
console.log('The up end');
scrolling=false;
}
} else {
if (leftTop != -tot) {
console.log('scrolling down !');
jQuery('.left').animate({top:leftTop - height},{done:function(){scrolling=false}});
jQuery('.right').animate({top:rightTop + height},{done:function(){scrolling=false}});
} else {
console.log('the down end');
scrolling=false;
}
}
});
});
Fiddle in Action
You can use .one() function of Jquery, read the official guide.
http://api.jquery.com/one/
When you scroll twice quickly your calculations for leftTop and leftRight will be off. What you can do is seperate the top calculation from the DOM state:
https://jsfiddle.net/11pftj26/2/
$(document).ready(function(){
var wholeHeight = jQuery('.right').height();
var rightLength = jQuery('.onRight').length;
jQuery('.right').css({top:-((wholeHeight*rightLength)-wholeHeight)});
var leftHeight = jQuery('.left').height();
var leftLength = jQuery('.onLeft').length;
var tot = (leftHeight * leftLength) - leftHeight;
var index = 0;
function animate(index) {
jQuery('.left').stop().animate({top: -1 * index * leftHeight});
jQuery('.right').stop().animate({top: -1 * (rightLength - index - 1) * wholeHeight });
}
$('body').bind('mousewheel', function(e) {
if (e.originalEvent.wheelDelta > 0) {
index = Math.max(0, index - 1);
} else {
index = Math.min(index + 1, rightLength - 1);
}
animate(index);
});
});
Related
I have a portfolio grid that has a screenshot of past work in each grid item.
Currently on button click, it calls a function to scroll the screenshot and stop once it reaches the bottom of the image.
I need to reverse the scroll once the button is clicked again. The scroll is created by a setInterval. I have a class of "down" on the button which is removed on click.
I have an if statement that does not work to check if the class of "down" is present and run a scrollUp function.
This is a PHP loop so there are multiple buttons with same class.
I cannot use jQuery.
Thanks for any help!
HTML:
<ul>
<li>
<div class="image-container overflow-hidden height-500">
<img class="item absolute pin-t w-full h-auto pin-l"
src="/image.jpg"/>
</div>
<button class="portScroll down">Scroll Down</button>
</li>
<li class="web-design-portfolio">
<div class="image-container overflow-hidden height-500">
<img class="item absolute pin-t w-full h-auto pin-l"
src="/image.jpg"/>
</div>
<button class="portScroll down">Scroll Down</button>
</li>
</ul>
JS:
function scrollDown() {
var portImg = this.parentNode.parentNode.querySelector('img.item');
var height = portImg.clientHeight;
var pos = 0;
var id = setInterval(frame, 5);
function frame() {
if (pos == height - 500) {
clearInterval(id);
} else {
pos++;
portImg.style.top = - + pos + 'px';
}
}
for (const button of document.querySelectorAll('button.portScroll')) {
button.classList.remove('down');
}
}
for (const button of document.querySelectorAll('button.portScroll')) {
if (button.classList.contains("down")) {
button.addEventListener("click", scrollDown);
} else {
button.addEventListener("click", scrollUp);
}
}
Here is the working Codepen for scroll down:
https://codepen.io/completewebco/pen/bZeVoz
I created a single function that does what is needed. I hope that is OK.
function scrollUpOrDown(_this, state) {
var portImg = _this.parentNode.parentNode.querySelector('img.item');
var height = portImg.clientHeight;
if(state.id > -1) {
clearInterval(state.id);
state.dir *= -1;
}
if(state.pos < 0) {
state.pos = 1;
}
state.id = setInterval(frame, 5);
function frame() {
if ((state.pos == height - 500 && state.dir > 0) || (state.pos == 0 && state.dir < 0)) {
clearInterval(state.id);
} else {
state.pos += state.dir;
portImg.style.top = -+state.pos + "px";
}
}
}
for (const button of document.querySelectorAll("button.portScroll")) {
let scollingState = {
pos: -1,
id: -1,
dir: 1
};
if (button.classList.contains("down")) {
button.addEventListener("click", function(){
scrollUpOrDown(this,scollingState);
});
}
}
https://codepen.io/prtjohanson/pen/QoEyQK
If you are wondering why/how it works, look at the output of this code
var array = [0,1,2,3,4,5];
for(const i in array) {
setTimeout(function(){console.log(i)}, Math.random()*1000)
}
and read https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#Scoping_rules_2
I have two functions, one to show a gallery of images and one for a smooth scroll up icon. The problem is when I use them separately, both of them works. But when I put them in the same file only the first one works. I can t figure out the problem. I am using jquery-2.0.3
Here is my Code:
$(function() {
$('.demo li').picEyes();
// Caching the Scroll Top Element
// console.log("function move to top");
var ScrollButton = $("#scroll");
$(window).scroll(function() {
// console.log($(this).scrollTop());
if ($(this).scrollTop() >= 50) {
ScrollButton.show()
} else {
ScrollButton.hide();
}
});
// Click On Button To Scroll To Top Of The Page
ScrollButton.click(function() {
$("html,body").animate({
scrollTop: 0
}, 800);
});
});
the code of picEyes function:
(function($){
$.fn.picEyes = function(){
var $obj = this;
var num,zg = $obj.length - 1;
var win_w = $(window).width();
var win_h = $(window).height();
var eyeHtml = '<div class="picshade"></div>'
+'<a class="pictures_eyes_close" href="javascript:;"></a>'
+'<div class="pictures_eyes">'
+'<div class="pictures_eyes_in">'
+'<img src="" />'
+'<div class="next"></div>'
+'<div class="prev"></div>'
+'</div>'
+'</div>'
+'<div class="pictures_eyes_indicators"></div>';
$('body').append(eyeHtml);
$obj.click(function() {
$(".picshade").css("height", win_h);
var n = $(this).find("img").attr('src');
$(".pictures_eyes img").attr("src", n);
num = $obj.index(this);
popwin($('.pictures_eyes'));
});
$(".pictures_eyes_close,.picshade,.pictures_eyes").click(function() {
$(".picshade,.pictures_eyes,.pictures_eyes_close,.pictures_eyes_indicators").fadeOut();
$('body').css({'overflow':'auto'});
});
$('.pictures_eyes img').click(function(e){
stopPropagation(e);
});
$(".next").click(function(e){
if(num < zg){
num++;
}else{
num = 0;
}
var xx = $obj.eq(num).find('img').attr("src");
$(".pictures_eyes img").attr("src", xx);
stopPropagation(e);
popwin($('.pictures_eyes'));
});
$(".prev").click(function(e){
if(num > 0){
num--;
}else{
num = zg;
}
var xx = $obj.eq(num).find('img').attr("src");
$(".pictures_eyes img").attr("src", xx);
stopPropagation(e);
popwin($('.pictures_eyes'));
});
function popwin(obj){
$('body').css({'overflow':'hidden'});
var Pwidth = obj.width();
var Pheight = obj.height();
obj.css({left:(win_w - Pwidth)/2,top:(win_h - Pheight)/2}).show();
$('.picshade,.pictures_eyes_close').fadeIn();
indicatorsList();
}
function updatePlace(obj){
var Pwidth = obj.width();
var Pheight = obj.height();
obj.css({left:(win_w - Pwidth)/2,top:(win_h - Pheight)/2});
}
function indicatorsList(){
var indHtml = '';
$obj.each(function(){
var img = $(this).find('img').attr('src');
indHtml +='<img src="'+img+'"/>';
});
$('.pictures_eyes_indicators').html(indHtml).fadeIn();
$('.pictures_eyes_indicators a').eq(num).addClass('current').siblings().removeClass('current');
$('.pictures_eyes_indicators a').click(function(){
$(this).addClass('current').siblings().removeClass('current');
var xx = $(this).find('img').attr("src");
$(".pictures_eyes img").attr("src", xx);
updatePlace($('.pictures_eyes'));
});
}
function stopPropagation(e) {
e = e || window.event;
if(e.stopPropagation) {
e.stopPropagation();
} else {
e.cancelBubble = true;
}
}
}
})(jQuery);
You should add click event handler, when DOM will be ready, do like this:-
$(function () {
$('.demo li').picEyes();
// Caching the Scroll Top Element
// console.log("function move to top");
//var ScrollButton =ScrollButton.click
var ScrollButton = $("#scroll")
$(window).scroll(function () {
// console.log($(this).scrollTop());
if ($(this).scrollTop() >= 50) {
ScrollButton.show()
} else {
ScrollButton.hide();
}
});
// Click On Button To Scroll To Top Of The Page
ScrollButton.click(function () {
$("html,body").animate({
scrollTop: 0
}, 800);
});
});
I bet both scripts have own ScrollButton element, and while gallery is loaded it owerwrites behaviour of other ScrollButton element.
I put the call of picEyes function outside of the main function and somehow worked !
I am a beginner in jQuery. As willing to develop a mobile website, I would like to implement sticky header for enhancing the user experiences.
Here are some codes of my work but it seems not work as calculation of the "top".
HTML:
<div class="fixed-header">
<div class="header_item" id="head_a"> A </div>
<div class="header_item" id="head_b"> B </div>
<div class="header_item" id="head_c"> C </div>
<div class="header_item" id="head_d"> D </div>
<div class="header_item" id="head_e"> E </div>
</div>
javascript and jQuery:
var $totalImageHeight;
$(window).on("load", function() { //Fires when DOM is loaded
getImageSizes();
$(window).resize(function() { //Fires when window is resized
getImageSizes();
});
});
function getImageSizes() {
$(".insurance_item img").each(function(count) {
var $this = $(this);
$imageHeight = $this.height();
$totalImageHeight = $imageHeight * (count + 1);
});
}
var stickyHeaders = (function() {
var $window = $(window),
$stickies;
var load = function(stickies) {
if (typeof stickies === "object" && stickies instanceof jQuery && stickies.length > 0) {
$stickies = stickies.each(function() {
var $thisSticky = $(this).wrap('<div class="followWrap" style="height: 0;"/>');
$thisSticky
.data('originalPosition', $thisSticky.offset().top)
.data('originalHeight', $thisSticky.outerHeight( 75 ))
.parent().height($thisSticky.outerHeight( 75 ));
});
$window.off("scroll.stickies").on("scroll.stickies", function() {
_whenScrolling();
});
}
};
var _whenScrolling = function() {
$stickies.each(function(i) {
var $thisSticky = $(this),
$stickyPosition = $thisSticky.data('originalPosition');
if ($stickyPosition <= $window.scrollTop()) {
var $nextSticky = $stickies.eq(i + 1);
$nextStickyPosition = $totalImageHeight - $nextSticky.data('originalPosition') - $thisSticky.data('originalHeight');
$thisSticky.addClass("fixed").css("top", $nextStickyPosition);
if ($nextSticky.length > 0 && $thisSticky.offset().top >= $nextStickyPosition) {
$thisSticky.addClass("absolute").css("top", $nextStickyPosition);
}
}else{ //scroll up and disable the fixed header
var $prevSticky = $stickies.eq(i - 1);
$thisSticky.removeClass("fixed");
if($prevSticky.length>0&&$window.scrollTop()<=
$thisSticky.data('originalPosition') -
$thisSticky.data('originalHeight')){
$prevSticky.removeClass("absolute").removeAttr("style");
}
}
});
};
return {
load: load
};
})();
$(function() {
stickyHeaders.load($(".header_item"));
});
Sorry for the late answer. I create an new javascript for implementing this function.
Code:
var $window = $(window);
var imageArr = [];
var iOS = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);
console.log(iOS);
$(window).on("load", function() { //Fires when DOM is loaded
getImageSizes();
window.requestAnimationFrame(tick);
$(window).resize(function() { //Fires when window is resized
getImageSizes();
scrollDetect(imageArr);
});
});
function getImageSizes() { //get the numbers of images and its outerHeight
var $items = $(".insurance_item");
for(var c = 0; c < $items.length; c++){
imageArr[c] = $($items[c]).outerHeight();
}
}
function scrollDetect(imageArr){ //show the title header of image once the image is offscreen.
var $items = $('.header_item');
for(var c = 0; c < imageArr.length; c++){
if($window.scrollTop() >= (imageArr[c] * (c+1)) - $('#fixed-header').outerHeight()){
$items.eq(c).show();
}else{
$items.eq(c).hide();
}
}
window.requestAnimationFrame(tick); //prevent the frame lost and make a incorrect calculation
}
function tick(){
scrollDetect(imageArr);
};
May be some better solution for solving this situation, thanks for everyone.
I have a slider rotator on my site but it doesn't rotate items automatically in the boxes - navigation works and rotate but I want it to rotate automatically, right after I enter the site.
This is my js:
$(document).ready(function() {
var nbr = 0;
$('.slider').each(function() {
var slider = $(this);
//get width and height of the wrapper and give it to the UL
var wrapperwidth = $(slider).width() * $(slider).find('ul > li').size();
$(slider).find('ul').css('width', wrapperwidth);
var wrapperheight = $(slider).height();
$(slider).find('ul').css('height', wrapperheight);
//set my li width
var width = $(slider).width();
$(slider).find('ul li').css('width', width);
//set my counter vars
var counter = $(slider).find('ul > li').size();
var decount = 1;
var autocount = 1;
if (counter > 1) {
//create my number navigation
var createNum = 1;
$(slider).after('<ul class="numbers"><li></li></ul>');
var numbers = $(slider).parent().find('.numbers');
$(numbers).find('li:first-child').html(createNum+'_'+nbr).addClass('activenum').attr('id', 'id1_'+nbr);
while ( createNum != counter) {
createNum++;
$(numbers).append("<li id='id"+createNum+"_"+nbr+"'>"+createNum+"_"+nbr+"</li>");
}
//get my number-width (number navigation should always be centered)
var numwidth = $(slider).find('.numbers li:first-child').width() * $(slider).find('.numbers li').size();
$(slider).find('.numbers').css('width', numwidth);
}
nbr++;
});
//make the number clickable
$(".numbers li").click(function() {
var slider = $(this).closest('.sliderWrapper');
var slider0 = $(slider).find('.slider');
var clickednum = $(this).html().split('_')[0] * - $(slider0).width() + $(slider0).width();
$(slider0).find('ul').animate({ left: clickednum }, 400, 'swing', function() { });
$(slider).find('.activenum').removeClass('activenum');
$(this).addClass('activenum');
decount = $(this).html();
});
rotateSwitch = function(sliderW, speed) {
var sliderWrap = sliderW;
play = setInterval(function() {
var nextNum = parseInt($($(sliderWrap).find(".numbers li.activenum")).html().split('_')[0])+1;
if (nextNum > $(sliderWrap).find(".numbers li").length) {
nextNum = 1;
}
//console.log("nextnum: "+nextNum+", numbers length: "+$(sliderWrap).find(".numbers li").length);
$(sliderWrap).find(".numbers li").each(function() {
if( parseInt($(this).html().split('_')[0]) == nextNum )
$(this).click();
});
}, speed);
};
makeAutoSlide = function(sliderWrap, speed) {
if ($(sliderWrap).length > 0 && $(sliderWrap).find(".numbers li").length > 1) {
rotateSwitch(sliderWrap, speed);
$(sliderWrap).find(".slider li").hover(function() {
if ($(sliderWrap).find(".numbers li").length > 1) {
clearInterval(play); //Stop the rotation
}
}, function() {
if ($(sliderWrap).find(".numbers li").length > 1) {
rotateSwitch(sliderWrap, speed); //Resume rotation timer
}
});
}
};
});
I'm not really sure if this is a problem with setInterval and clearInterval or I wrote something wrong.
I put code in jsFiddle, so you know how the structure looks like.
http://jsfiddle.net/gecbjerd/1/
I appreciate for help.
Cheers
function yHandler () {
var show = document.getElementById('show');
var contentHeight = show.offsetHeight;
var yOffset = show.pageYOffset;
var y = yOffset + show.innerHeight;
if(y >= contentHeight) {
alert("ok")
}
}
show.onscroll = yHandler;
how to check if the scrollbar has reached the end of div?
Some code for you to work on:
var scroll = document.getElementById('scroll');
var content = document.getElementById('content');
scroll.onscroll = function(){
var total = scroll.scrollTop + scroll.clientHeight;
if(total == content.clientHeight)
alert('Reached bottom!');
}
http://jsfiddle.net/EY6qP/
Thor's method works perfectly well (+1), but you could also rely on scrollHeight.
(function(scroll){
scroll.onscroll = function(){
if (scroll.scrollTop + scroll.clientHeight == scroll.scrollHeight) {
console.log('hither!');
}
}
})(document.getElementById('scroll'));
Use scrollHeight, scrollTop and clientHeight attributes to detect the scroll bar reached bottom end or not.
function handleScroll() {
var div = document.getElementById("div-id");
if(Math.abs(Math.round(div.scrollHeight - div.scrollTop) - div.clientHeight) > 3) {
console.log("Scroll bar reached bottom end");
return true;
}
return false;
};