I'm trying to do the following:
Open a div with slideToggle
Move the users window to the top of the div with scrollTop
Then basically reverse the process when the user closes the div.
I have the whole process almost finished, but I am having one problem. When I open the div my window doesn't move to the top of the div. But when I close the div my window does move to where I want it.
Here is my jQuery code:
// Find the location of a div (x, y)
function divLoc(object) {
var topCord = 0;
// If browser supports offsetParent
if(object.offsetParent) {
do {
topCord += object.offsetHeight;
}
while (object === object.offsetParent);
return topCord;
}
}
$("#open").click(function () {
var newInfo = document.getElementById("newInfo");
var location = divLoc(newInfo);
$("#newInfo").slideToggle('slow', function() {
$('html,body').animate({ scrollTop: location }, 2000);
});
});
And I uploaded an example of the problem on jsFiddle: Here
You need change slide function:
$("#newInfo").slideToggle('slow', function() {
var self = $(this)
$('html,body').animate({ scrollTop: self.offset().top }, 2000);
});
http://jsfiddle.net/hSHz5/
Related
I'm using this simple code, and it's working fine.
$("#mydiv").animate({ scrollTop: $('#mydiv')[0].scrollHeight}, 20000)
What I would like is to after the bottom has been reached immediately go back to the top of the page and start scrolling down slowly again. How would one achive something like this in JQuery?
Thank you guys!
you can jump back to the top of your page using the following javascript function:
function jump(elementId){
var location = document.getElementById(elementId).offsetTop;
window.scrollTo(0, location);
}
just use the id of some element at the top of your page.
Not sure what you are trying to do and what "reload" means but here is a quick snippet to get you started:
JSnippet Demo
As you can see its configurable and easy to understand:
$(function() {
var pageScan = {
speed : 10000,
loop : true,
delayRestart : 1000,
start : function(){
pageHeight = $('body').height() - window.innerHeight;
pageScan.proc(pageHeight);
},
proc : function(to){
$("body").animate(
{scrollTop: to},
pageScan.speed,
"linear",
function(){
if (pageScan.loop) {
setTimeout(function() {
window.scrollTo(0, 0);
pageScan.start();
}, pageScan.delayRestart);
}
});
}
};
pageScan.start();
});
We could do something easier like this:
(function (){
var div = $('#myDiv'),
infiniteScroll = function () {
//---gets the bottom of the page value
var bottomHeight = div[0].scrollHeight;
var callback1 = function () {
//once it gets into this callback function
//it resets the position to zero
div.scrollTop(0);
//invokes again the function infinite scroll
infiniteScroll();
};
div.animate({scrollTop:bottomHeight},20000,callback1)
};
//starts the function for the very first time
infiniteScroll();
})();
I created a codepen so you can see it working and play with it:
http://codepen.io/dieggger/pen/VLoZWv?editors=101
I have the following problem. What I want is when the user clicks in the navigation bar on "Contact" it will link to the contact page. This is a single page. When you are on contact and then clicking at the bottom of the page on, for example "Over ons" it should be redirect to the homepage (single page) and stop at that section. This works, but when you come from another page, the current section is overlapped by the header.
The jQuery code will not use the offset of the header, only when you are navigation inside the index.html.
Is there a way to fix the issue, so the section will not be overlapped by the header?
Live example:
http://codepen.io/anon/pen/NqxxQd
jQuery code:
// An offset to push the content down from the top
var offset = $('#header').outerHeight();
$('#primary-navwrapper li:not(.prev-page, .next-page), .list-of-links li').find('a[href^="#"]').click(function(event) {
event.preventDefault();
$('#primary-navwrapper li a').removeClass("current");
$(this).addClass("current");
var anchorId = $(this).attr("href");
var target = $(anchorId).offset().top - offset;
$('html, body').animate({ scrollTop: target }, 500, function () {
window.location.hash = anchorId;
});
});
function setActiveListElements(event){
// Get the offset of the window from the top of page
var windowPos = $(window).scrollTop();
$('#primary-navwrapper li a[href^="#"]').each(function() {
var anchorId = $(this);
var target = $(anchorId.attr("href"));
var offsetTop = target.position().top - offset;
if (target.length > 0) {
if (target.position().top - offset <= windowPos && (target.position().top + target.height() + offset ) > windowPos) {
$('#primary-navwrapper li a').removeClass("current");
anchorId.addClass("current");
}
}
});
}
$(window).scroll(function() {
setActiveListElements();
//updateLocationHash();
});
Your code to scroll down to each section needs to be placed in it's own function called something sensible like FireActiveElement. Give it one parameter that sends through your anchorId string. Your click listener then needs to call that function.
So you have a function similar to:
function FireActiveElement(anchorId) {
var target = $(anchorId).offset().top - offset;
$('html, body').animate({
scrollTop: target
}, 500, function () {
window.location.hash = anchorId;
});
}
Then, what you can do is something like this:
function CheckHash() {
if (window.location.hash) {
FireActiveElement(window.location.hash);
}
}
Then you'll need to add that function as a callback to your body fade in:
$('body').fadeIn(500, CheckHash);
Difficult to test this works myself, but hope that helps you.
P.S.
If you need to have more things that are fired upon page load, you might want to change the fadeIn slightly to something like:
$('body').fadeIn(500, function() {
CheckHash();
// Examples:
SomeOtherFunction();
FireMeOnPageLoad();
});
I'm looking for a code that scrolls up to the top of the currently active panel heading of my bootstrap 3 html/css accordion. The closest solution I've found on stackoverflow is the snippet of js below.
This snippet works fairly well, but when a panel heading gets clicked the page scrolls such that the very top of the panel content is flush with the top of the screen. Is there a way to modify this so that the scrolling effect will result in the panel "heading" (as opposed to the top of panel content area) being visible at the top of the screen?
$(function () {
$('#accordion').on('shown.bs.collapse', function (e) {
var offset = $('.panel.panel-default > .panel-collapse.in').offset();
if(offset)$('html,body').scrollTop(offset.top); }); });
Let me know if I should be sharing the bootstrap accordion html as well.
I used this and it works fine you can adjust the -20 after the .offset().top if you need to tweak it up or down a little.
$(function () {
$('#accordion').on('shown.bs.collapse', function (e) {
var offset = $('.panel.panel-default > .panel-collapse.in').offset();
if(offset) {
$('html,body').animate({
scrollTop: $('.panel-title a').offset().top -20
}, 500);
}
});
});
This is to target the specific .panel-heading clicked as per James Wilson's comment on the accepted answer.
$(function () {
$('#accordion').on('shown.bs.collapse', function (e) {
var offset = $(this).find('.collapse.in').prev('.panel-heading');
if(offset) {
$('html,body').animate({
scrollTop: $(offset).offset().top -20
}, 500);
}
});
});
All I changed from gigelsmith's accepted answer is 'var offset' and the scrollTop's target.
I couldn't get the answer above to work, perhaps I'm missing something but I can't see how the scrollTop line above relates to the currently opened accordion item so used the following code instead. Hope it helps someone else:
$(function () {
$('#accordion').on('shown.bs.collapse', function (e) {
var offset = $('.panel.panel-default > .panel-collapse.in').offset();
if(offset) {
$('html,body').animate({
scrollTop: $('.panel-collapse.in').siblings('.panel-heading').offset().top
}, 500);
}
});
});
Always animate looks a bit too much so this is my version to only do the job when heading is over the visible part.
(note that I use a data-accordion-focus to apply the fix)
$('[data-accordion-focus]').on('shown.bs.collapse', function (e) {
var headingTop = $(e.target).prev('.panel-heading').offset().top - 5;
var visibleTop = $(window).scrollTop();
if (headingTop < visibleTop) {
$('html,body').animate({
scrollTop: headingTop
}, 500);
}
});
By using .panel-default as selector of .on(), you can scroll to the active panel.
$('#accordion').on('shown.bs.collapse', '.panel-default', function (e) {
$('html,body').animate({
scrollTop: $(this).offset().top
}, 500);
});
Please check what i did yet http://jsfiddle.net/dUVmh/1/ .
About the animation i want to achieve is that:
When you first scroll down the page then window scroll to #green DIV. After that if you again scroll down window scroll to #yellow DIV & same at the time of scrollup (fom #yellow to #green).
About the issue:
You can see the animation it's stuck on #green DIV.
$(window).scroll(function(){
if($(this).scrollTop() > 0) {
$("html, body").animate({ scrollTop: $('#green').offset().top }, 1000);
}
else if($(this).scrollTop() > 1000) {
$("html, body").animate({ scrollTop: $('#yellow').offset().top }, 1000);
}
else{
$("html, body").animate({ scrollTop: $('#red').offset().top }, 1000);
}
});
I didn't have much experience in JS.
Thanks i advance :)
This was a fun problem to work on.
This solution places the divs into an array, and remembers the array index of the element that was last scrolled to. Once a scroll event is triggered it checks to see if the new scrollTop is above or below the current divs top offset and moves to the next or previous div in the array accordingly.
This solution allows you to have many divs. I tried to remove the flickering you get when you scroll to fast, but the only way to do that I believe would be to disable the scrollbars during animation.
http://jsfiddle.net/dUVmh/35/
$(function() {
var divs = [],
body = $('body, html'),
currentDiv = 0,
timeout;
$('div').each(function() {
divs.push($(this));
});
// we only need to capture the first scroll event triggered and then
// add another listener once we have done our animation
var scrollListen = function() {
$(window).one('scroll', function() {
doScroll($(this).scrollTop());
});
};
// Without the timeout, the scroll event would be triggered again too soon
var scrollEnd = function() {
clearTimeout(timeout);
timeout = setTimeout(function() {
scrollListen();
}, 10);
};
// checks if the scroll direction was up and down and animates
// the body scrollTop to the next or previous div
var doScroll = function(scrollTop) {
var direction = scrollTop - divs[currentDiv].offset().top;
if (direction > 0 && currentDiv + 1 < divs.length) {
nextDiv = currentDiv + 1;
} else if (currentDiv - 1 > -1) {
nextDiv = currentDiv - 1;
}
if (currentDiv === nextDiv) {
scrollEnd();
}
body.animate({
scrollTop: divs[nextDiv].offset().top
}, 1000, function() {
currentDiv = nextDiv;
scrollEnd();
});
};
scrollListen();
});
Edit: Firefox scrollTop required to be changed on html and not body. Also fixed a problem with firefox calling scrollListen more than once at a time.
The problem is that the $(window).scroll(function()) gets called over and over again when scrolling through the ScrollTop animation with jQuery.
Here is a possible solution that checks if it is currently scrolling or not and only executes the ScrollTop animation once.
http://jsfiddle.net/dUVmh/29/
Side note: It might be a good idea to check which direction the user is scrolling (up or down) and depending on that scroll to the next div to the top or to the down.
You can check that be saving the last scrollTop position and comparing it with the current one.
UPDATE: Here's a solution that takes the scroll direction into account: http://jsfiddle.net/dUVmh/36/
I am trying to make a carousel of sorts. I am kind of stuck with hiding and displaying the next and precious buttons once a div moves to the far left and right of its container.
I think i have everything correct regarding calculating the widths but for some reason when you click the buttons, elements stay hidden irrespective of the conditional comments which should dictate when they should be hidden or shown.
Here is a link to what i have thus far. Click the MoveLeft and MoveRight buttons. http://www.ehbeat.com/test/
<script type="text/javascript">
$(document).ready(function () {
//Check width of Gallery div
var galleryWidth = $("#Gallery").innerWidth();
//Check width of GalleryItem
var galleryItemWidth = $(".GalleryItem").innerWidth();
//Check distance from left
var position = $('.GalleryItem').position();
var galleryItemLeft = position.left;
$(".MoveRight").click(function () {
$(".GalleryItem").animate({
"left": "+=50px"
}, "slow");
$(".GalleryItem2").animate({
"left": "+=100px"
}, "slow");
});
$(".MoveLeft").click(function () {
$(".GalleryItem").animate({
"left": "-=50px"
}, "slow");
$(".GalleryItem2").animate({
"left": "-=100px"
}, "slow");
});
$(".Controls").live('click', function () {
if (galleryItemLeft >= "0") {
$('.MoveRight').hide();
}
else {
$('.MoveRight').show();
}
});
if (galleryItemWidth == galleryWidth - galleryItemWidth) {
$('.MoveLeft').hide();
}
});
</script>
It looks like you setup all of your variables inside the $(document).ready() call.
This means that while they're being set on load, they're not getting updated with each click.
Your galleryItemLeft, galleryItemWidth and galleryItemWidth variables need to be updated on each click, so I'd recommend re-assigning the values in each click (by moving the assignment into the live functions)
Edit Also, as your last if statement is excluded from any click function, it'll need to be relocated to inside the live click events as well.
-Chris
Chris is right, code should look like this:
$(".Controls").live('click', function() {
position = $('.GalleryItem').position();
galleryItemLeft = position.left;
if(galleryItemLeft > "0") {
$('.MoveRight').hide();}
else{
$('.MoveRight').show();
}
if(galleryItemWidth == galleryWidth - galleryItemWidth) {
$('.MoveLeft').hide();
}
});