I need some help regarding auto scroll to each div or element when the user will use the scroll button in the mouse. Here goes the scenario
Suppose this is my structure of the page..
<div id="main-wrap">
<div class="my-div-1">
<p>here goes my content 1</p>
<img src="/images/sample-1" alt="sample-1"/>
</div>
<div class="my-div-2">
<p>here goes my content 2</p>
<img src="/images/sample-2" alt="sample-2"/>
</div>
<div class="my-div-3">
<p>here goes my content 3</p>
<img src="/images/sample-3" alt="sample-3"/>
</div>
</div><!-- end of main-wrap id -->
-Now suppose my each div has got enough content to make the page long. Suppose the user is on my-div-1 and when the viewer uses the scroll button to scroll down, instead of scrolling through the whole div, i want it to scroll automatically to the my-div-2.
I hope my explanation make sense here.
Is there any way to sort it out by using javascript and jquery?
I will appreciate any response..Thanks in advance.
Here's a fiddle with what you want: http://jsfiddle.net/3qxhY/9/
Source of plugin used in code (debounce/throttle plugin): http://benalman.com/projects/jquery-throttle-debounce-plugin/
Code
// debounce/throttle plugin
(function(b,c){var $=b.jQuery||b.Cowboy||(b.Cowboy={}),a;$.throttle=a=function(e,f,j,i){var h,d=0;if(typeof f!=="boolean"){i=j;j=f;f=c}function g(){var o=this,m=+new Date()-d,n=arguments;function l(){d=+new Date();j.apply(o,n)}function k(){h=c}if(i&&!h){l()}h&&clearTimeout(h);if(i===c&&m>e){l()}else{if(f!==true){h=setTimeout(i?k:l,i===c?e-m:e)}}}if($.guid){g.guid=j.guid=j.guid||$.guid++}return g};$.debounce=function(d,e,f){return f===c?a(d,e,false):a(d,f,e!==false)}})(this);
//elements you want to scroll to go here
divs = [$(".my-div-1"),$(".my-div-2"),$(".my-div-3")];
var lastScrollTop = 0; //we'll update this on every scroll and compare it to the last scroll to determine the scroll direction
var run = true;
$(window).scroll($.debounce(250, true, function () { //debounce so it only runs once per scroll
var st = $(window).scrollTop();
if (st > lastScrollTop) { // if the scrollTop when the scroll event fires is larger than the last scroll, we can assume the scroll was in a downward direction
$.each(divs, function (i, v) {
((v.offset().top - $(window).scrollTop()) < 0) && (next = i + 1); //compare each elements offset to the windows offset to determine which element we're currently scrolling through
});
run = (next != divs.length) ? true : false; //dont run if we are at the last div
} else {
$.each(divs, function (i, v) {
((v.offset().top - $(window).scrollTop()) < 0) && (next = i);
});
run = true;
}
if (run) {
$('html, body').animate({
scrollTop: divs[next].offset().top
}, 1000,'linear', function() {
lastScrollTop = $(window).scrollTop();
});
} else { lastScrollTop = $(window).scrollTop(); }
}));
Related
I have three divs, each one with some hidden content. When you click on a div, its content is being displayed by sliding down. And at the same time, I'm using scrollTop to make the browser scroll to the top of the block thats been clicked on. The HTML looks like this:
<div class="blocks block1"></div>
<div class="content block1_content"></div>
<div class="blocks block2"></div>
<div class="content block2_content"></div>
<div class="blocks block3"></div>
<div class="content block3_content"></div>
However, im having problems with parts of the scrollTop animation. Here is the JS:
$('.blocks').on("click", function() {
if (!$(this).hasClass('expanded')) {
collapseExpandedFunction();
$('html, body').animate({
scrollTop: $(this).offset().top
}, 500);
$(this).addClass('expanded');
$(this).next().slideDown();
} else if ($(this).hasClass('expanded')) {
collapseExpandedFunction();
}
});
collapseExpandedFunction = function() {
$('.blocks.expanded').removeClass('expanded');
$('.content').slideUp();
};
I made an jsfiddle to easier demonstrate the problem: https://jsfiddle.net/ss53ckyk/3/
Explaination:
If you start toggle the green block and then toggle the red or blue, it's all good. The greens content is being hidden, while the red/blue is displayed and scrolled to the top of the block.
The problem is if you start from the top and moving down. If you first toggle the red one and then either blue or green, the browser won't scroll down correctly.
Another thing i'd like is to make the slideDown happen after the scrollTop animation is done.
Hopefully someone can help me out!
EDIT:
There should only be one blocks content visible at a time. For example, if you click the red once and then the blue, the content of the red should slide up, while the blue is showing.
The asynchronous nature of javascript is causing your issues; namely .slidUp() function. When this event is triggered, it fires an asynchronous event, which is non-blocking to the rest of the function. Therefore, the animate top will take a snapshot of the DOM at a particular moment in time while the .slidUp() function is actioning. Replacing the .slidUp() and .slidDown() with .show() and .hide() to resolve this, but this doesn't provide the responsiveness you require. One thought would be to capture the offsets of each previous content div and use that in the scrollTop function.
EDIT :
Based on the edit, you need to make few adjustments in your code which calculates the scrolltop position based on scrollposition and adding margin based on the corresponding .content div
$(document).ready(function() {
var addMargin = false;
$('.blocks').on("click", function() {
if (!$(this).hasClass('expanded')) {
collapseExpandedFunction();
var doc = document.documentElement;
var ele = this;
var nextEle = $(ele).next();
$(this).addClass('expanded');
var margin = 0;
var scrollTo = 0;
if($(ele).hasClass('expanded'))
{
if(addMargin)
margin = $(nextEle).css('height').replace('px','');
scrollTo = $(ele).offset().top - margin;
}
if(doc.scrollTop != 0 && doc.scrollTop > scrollTo && addMargin)
{
console.log(margin);
scrollTo = scrollTo + 200;
}
$('html, body').animate({
scrollTop: scrollTo
}, 500, function()
{
$(ele).next().slideDown();
});
} else if ($(this).hasClass('expanded')) {
collapseExpandedFunction();
}
});
collapseExpandedFunction = function()
{
$('.blocks.expanded').removeClass('expanded');
$('.content').slideUp();
addMargin = false;
};
window.onscroll = function (e) {
addMargin = true;
}
});
Here's the working code : https://jsfiddle.net/ss53ckyk/13/
in the fiddle you will see at the center of the page a DIV that contains text next to an img.
When I scroll down/up I need to effect with jquery/javascript only the div who's the closest to the navbar-below. all the divs as the same class so I effect them all-not what I need
For example:
what I am trying to achieve : when I scroll down,the closest div to the navbar(yellow bar) will be painted(the div) green,so if I scroll down and the navbar "collapse" with the div with will paint in green, and when he passes him and "disapper" it will go back to original color and the next div will paint in green. is it possible?
Here's the JS FIDDLE: http://jsfiddle.net/nnkekjsy/3/
When I referred to div I meant this section :
<div class="x" id="inside_center">
<div class="left_side" id="left_inside_center">sddsadasasdsadLorem </div>
<div class="right_side" id="right_inside_center"><img src="http://img-9gag-lol.9cache.com/photo/a7KwPAr_460s.jpg"></div>
</div>
JQUERY :
I added my jquery,as you can see it works only for the first one,and then stuck.. i need to "pass" it along the others div below him when the are getting to the same point. any ideas? :
$(document).ready(function() {
$(window).scroll(function() {
var scrollVal = $(this).scrollTop();
var navHeight = $("#div_menu").outerHeight();
if ( scrollVal > 55) {
$('#left_inside_center').css({'position':'fixed','top' :navHeight+'px'});
} else {
$('#left_inside_center').css({'position':'static','top':'auto'});
}
});
});
Are you looking for some thing like this?
http://jsfiddle.net/mcozkpv3/1/
This is just quick hack to find closes elements based on distance and selecting it. add data-did attribute to each item div.
$(document).ready(function () {
$(window).scroll(function () {
$('[data-did]').each(function (i, e) {
var dist = $(e).offset().top - $('#div_menu').offset().top
if (dist < 80) {
$(e).addClass('closest');
} else {
$(e).removeClass('closest');
}
});
var scrollVal = $(this).scrollTop();
var navHeight = $("#div_menu").outerHeight();
if (scrollVal > 55) {
// $('#left_inside_center').css({'position':'fixed','top' :navHeight+'px'});
} else {
$('#left_inside_center').css({
'position': 'static',
'top': 'auto'
});
}
});
});
Hi please help me with my fiddle HERE
I have this div
<div id='divdiv' style="height: 200px; overflow:scroll">
<span id='content'>
Scroll down!Scroll down!
Scroll down!Scroll down!
Scroll down!Scroll down!
Scroll down!Scroll down!
Scroll down!Scroll down!
Scroll down!Scroll down!
</span>
<i id="selectedElement">s</i>
</div>
this div has overflow and I have scroll event that trigger when <i id="selectedElement">s</i> is visible in div
//function to check if target element is visible
function isElementVisible(elementToBeChecked)
{
var TopView = $('#divdiv').scrollTop();
var BotView = TopView + $('#divdiv').height();
var TopElement = $(elementToBeChecked).offset().top;
var BotElement = TopElement + $(elementToBeChecked).height();
return ((BotElement <= BotView) && (TopElement >= TopView));
}
//scroll event
$('#divdiv').scroll(function () {
isOnView = isElementVisible("#selectedElement");
if(isOnView){
$('#content').append('<br>a<br>a<br>a<br>a<br>a<br>a<br>a');
}else{ // If not visible
}
});
if the <i id="selectedElement">s</i> is visible i added some value '<br>a<br>a<br>a<br>a<br>a<br>a<br>a' just to test if i reach the bottom but I can't make it work.
it should function as
when the target element is visible i will load some content then user will scroll again to bottom and when the target element is "again" visible i will load some more content again
I have updated the fiddle here.
This appends a random number to the 'content' div as soon as it reaches the bottom.
function appendContent()
{
if ($('#divdiv')[0].scrollHeight <= $('#divdiv')[0].scrollTop + $('#divdiv').height() ) {
return true;
}
else
return false;
}
$('#divdiv').scroll(function () {
if(appendContent()){
$('#content').append('<br>' + Math.random());
}else{ // If not visible
}
});
Check this Demo Fiddle
Use this
$('#divdiv').scrollTop($('#divdiv').prop("scrollHeight"));
OR
$('#divdiv').scrollTop($('#divdiv')[0].scrollHeight);
scrollTop() scrolls the div to the bottom.
prop("scrollHeight") gives your the actual height, and not default display height - height().
I am developing a webpage and I wanted to know how to go about making animations based on where the page currently is.
What I mean is that :
for example, the Markup below
<body>
<div id = "header">
<p> header content goes here</p>
</div>
<div id = "content">
<div id = "first">
<p>when I sroll into this region I want the background to darken up(and information appears) and an arrow to appear at the bottom showing prompting to scroll down</p>
</div>
<div id = "second">
<p>when I sroll into this region I want the navbar to to change appearace and display info relative to that div only </p>
</div>
<div id = "third">
<p>when I scroll into this region I want a another effect to occur</p>
</div>
</div>
<div id = "footer">
<p>footer content goes here</p>
</div>
</body>
if the web page loads and I scroll into each of the three divs in the then i want to have a defined effect in action.
How do I do I go about that in JavaScript(Jquery)? or if anyone knows of any good sources where i can learn this technique i will love to know
Thank you all
Something like this should do the trick, either inside the pageLoad or $(document).ready methods:
var last,
docHeight= $(window).height(),
firstTop = $("#first").offset().top,
firstBottom = firstTop - docHeight,
secondTop = $("#second").offset().top,
secondBottom = secondTop - docHeight,
thirdTop = $("#third").offset().top,
thirdBottom = thirdTop - docHeight;
$(document).scroll(function(){
var thisTop = $(this).scrollTop();
if(thisTop <= thirdTop && thisTop >= thirdBottom){//#third is now visible
if(last != 3)//check if we're already in #third
console.log("entered third");//we entered #third for the first time, trigger effect
last = 3;
} else if (thisTop <= secondTop && thisTop >= secondBottom){
if(last != 2)
console.log("entered second");
last = 2;
} else if (thisTop <= firstTop && thisTop >= firstBottom){
if(last != 1)
console.log("entered first");
last = 1
} else
last = 0;
})
It attaches to the $(document).scroll event, and using jquery's scrollTop() for the document, and offset().top of the elements, determines which one has been scrolled to. It also keeps a variable with the last element that was scrolled to, so the console.log statements are only fired when the element is scrolled to originally, thus it won't fire while scrolling through the element.
working jsfiddle
I had a similar issue recently. I found the free and open-source divPeek library to be excellent.
https://github.com/davidhalford/DivPeek
No need to reinvent the wheel, especially if it has already been invented! :)
I'm currently using a combination of smooth scroll and IDs/anchor tags to scroll to content on my site. The code below is getting the ID of the next 'section' in the DOM, and adding it's ID as the 'view next section' href, so once it's clicked, it'll scroll to the top of that div. Then, it iterates through, updating the href with the next ID each time etc until the last section is seen and it scrolls back to the top. Pretty straightforward.
The only problem is that the 'sections' are fullscreen images, so as it's scrolling to the top of the next section, if you resize the browser, the top position of that section (where we scrolled to) has moved, and means the position is lost.
I've created a JSFiddle. You can see this happening after you click the arrow to visit the next section then resize the window: http://jsfiddle.net/WFQ9t/3/
I'm wanting to keep this top position fixed at all times so even if you resize the browser, the scroll position is updated to reflect this.
Thanks in advance,
R
var firstSectionID = $('body .each-section').eq(1).attr('id');
$('.next-section').attr('href', '#' + firstSectionID);
var i = 1;
$('.next-section').click(function() {
var nextSectionID = $('body .each-section').eq(i).attr('id');
i++;
$('.next-section').attr('href', '#' + nextSectionID);
var numberOfSections = $('body .each-section').length;
var lastSectionID = $('body .each-section').eq(numberOfSections).attr('id');
if ($('.next-section').attr('href') == '#' + lastSectionID ) {
$('.next-section').attr('href', '#introduction');
i = 1;
}
});
Ok, Please check out this fiddle: http://jsfiddle.net/WFQ9t/9/
The few things I did were:
Made some global variables to handle the screen number (which screen you're on and also the initial window height. You will use this when the screen loads and also when you click on the .next-session arrow.
var initWinHeight = $(window).height();
var numSection = 0;
Then I tossed those variables into your resizeContent() function
resizeContent(initWinHeight, numSection)
so that it will work on load and resize
I made the body move around where it needs to, to accomodate for the movement of the divs (I still don't understand what divs are moving when the regular animation happens).
$('body').css({
top: (((windowHeight - initWinHeight)*numSection)*-1) + "px"
});
Then in your click function, I add 1 to the section number, reset the initial window height and then also reset the body to top:0. The normal animation you have already puts the next section at the top of the page.
numSection++;
initWinHeight = $(window).height();
$('body').css({top:"0px"}, 1000);
Finally, I reset the numSections counter when you reach the last page (You might have to make this 0 instead of 1)
numSection = 0;
The fiddle has all of this in the correct places, these are just the steps I took to change the code.
Here is a solution that i found, but I dont use anchor links at this point, i use classes
Here is my HTML code:
<section class="section">
Section 1
</section>
<section class="section">
Section 2
</section>
<section class="section">
Section 3
</section>
<section class="section">
Section 4
</section>
And here is my jQuery/Javascript code,
I actually used a preety simple way:
$('.section').first().addClass('active');
/* handle the mousewheel event together with
DOMMouseScroll to work on cross browser */
$(document).on('mousewheel DOMMouseScroll', function (e) {
e.preventDefault();//prevent the default mousewheel scrolling
var active = $('.section.active');
//get the delta to determine the mousewheel scrol UP and DOWN
var delta = e.originalEvent.detail < 0 || e.originalEvent.wheelDelta > 0 ? 1 : -1;
//if the delta value is negative, the user is scrolling down
if (delta < 0) {
next = active.next();
//check if the next section exist and animate the anchoring
if (next.hasClass('section')) {
var timer = setTimeout(function () {
$('body, html').animate({
scrollTop: next.offset().top
}, 800);
next.addClass('active')
.siblings().removeClass('active');
clearTimeout(timer);
}, 200);
}
} else {
prev = active.prev();
if (prev.length) {
var timer = setTimeout(function () {
$('body, html').animate({
scrollTop: prev.offset().top
}, 800);
prev.addClass('active')
.siblings().removeClass('active');
clearTimeout(timer);
}, 200);
}
}
});
/*THE SIMPLE SOLUTION*/
$(window).resize(function(){
var active = $('.section.active')
$('body, html').animate({
scrollTop: active.offset().top
}, 10);
});