I have simple JS function that's animate page scroll to selected anchor by id
all anchor in my page have different offset value and position
tip: I user masonry effect
but does not work correctly
function scrollToAnchor(aid) {
var aTag = $("a[id='" + aid + "']");
$('html,body').animate({ scrollTop: aTag.position().top }, 'slow');
}
You should use offset instead of position().
But I know by experience that Masonry by default doesn't use position absolute & top, left but it uses a css3-transform instead. And this means that .left and .top will output 0 instead of the css3-transform-value.
Related
I have a list of items. When I click on one item (project) it opens (this is ok) and it scrolls to the top of the page (the wrong top!). The problem occurs when I have an opened item and I decide to open the one below: the top position is increased by the opened project height and the second project I click goes too far over the top.
Following the FIDDLE below: if I open project1 and then I click on project2, this goes on the wrong top. Same if I try to open any project below another opened one.
JS
$('.accordion-section-title').on('click', function () {
var idName = $(this).attr('id');
$('html, body').animate({
scrollTop: $("#" + idName).offset().top
}, 500);
});
Here's the FIDDLE
The problem seems to be the .slideUp() and .slideDown() methods are animated at the same time the window is scrolling. By the time the window has scrolled to the right Y coordinate, the accordion sections' heights have been altered, thus causing the window to end up in the wrong position.
I'm sure there are other ways to accomplish correct scroll positions, but my first thought was to store the initial Y positions once the page is loaded. This can be done this way:
$('.accordion-section-title').each(function() {
$(this).data('ypos', $(this).offset().top)
})
Each .accordion-section-title element will have its Y position stored in a data attribute called ypos. Later when you scroll the window, don't scroll to the elements position, but rather to its stored initial position. In other words, change scrollTop: $("#" + idName).offset().top to scrollTop: $("#" + idName).data('ypos'). Put together with your code it will look like the following:
$('.accordion-section-title').on('click', function(e) {
var idName = $(this).attr('id');
$('html, body').animate({
scrollTop: $("#" + idName).data('ypos') - 10
}, 500);
});
You can see how it plays out in this fiddle
When I click my button, I append a new div. I would like that, if any part of the div is not visible to the window, scroll untill it shows.
So if it is upwards from the center of the window, scroll up JUST until you see it's top, and if it is downwards from the center, scroll down just until you see its bottom.
In my searchings I found https://api.jquery.com/scrollTop/ , but that doesn't seem to be what I'm describing
I only want to scroll enough to display it entirely on screen, not always on top
Check this working fiddle for the solution.
You can use scrollTop() to scroll to any div. First we need to find the direction of the scroll to correctly provide the value for scrollTop() function. This can be found using position().
$('#button4').click(function() {
// check if the div lies below the button
if ($('#div3').position().top - $('#button4').position().top > 0) {
// in this case we need to add shift
var shift = $(window).height() - $('#div3').height();
} else {
var shift = 0;
}
$(window).scrollTop($('#div3').offset().top - shift);
});
Alternatively if you wish to check the position of the div relative to the current viewport (or the center of the current window view) you can use getBoundingClientRect() like:
$('#button4').click(function() {
// check if the div lies below the viewport
if ($('#div3')[0].getBoundingClientRect().top > 0) {
// in this case we need to add shift
var shift = $(window).height() - $('#div3').height();
} else {
var shift = 0;
}
$(window).scrollTop($('#div3').offset().top - shift);
});
Here is the alternate fiddle.
So if you are using jQuery.
//scroll top of element
var $myNewElement = $(".new-element-class");
$('html, body').scrollTop($myNewElement.offset().top)
I think this should work. Make sure your div is appended before calling the scrollTop function.
If I understand correctly, this jsfiddle is what you are looking for.
I also added a simple animation so the document doesn't awkwardly jump around the viewport.
Features
If a new element is created, and part of that new element is below the current viewport, the document will be scrolled until the bottom of the viewport is shown. Vice versa if part of the new element is above the current viewport.
If the new element is completely visible within the current viewport, no scrolling will occur.
All scrolling effects are animated.
A configurable offset (Leave some padding instead of scrolling to the very edge of the new element)
How it works
When the button is clicked, a new div element is appended.
$('section').append('<div>');
Next, we figure out if this div is above the current viewport using the below function:
function isElementAboveViewport(element) {
return $(element).offset().top < $(window).scrollTop();
}
in an if statement:
if (isElementAboveViewport($('section > div:last-child'))) {
...
}
If the condition is truthy, we scroll! (offset is configurable - In the JS fiddle, I used 40 which is the height of the button covering the top 40px of the viewport)
$('html, body').animate({
scrollTop: $('section > div:last-child').offset().top - offset
}, 1000);
Now, we check if the new element is below the current viewport with a similar function:
function isElementBelowViewport(element) {
return $(element).offset().top + $(element).height() > $(window).scrollTop() + $(window).height();
}
If the element is too far down in the document, we scroll! (Again, offset is configurable)
$('html, body').animate({
scrollTop: $('section > div:last-child').offset().top + $('section > div:last-child').height() - $(window).height() + offset
}, 1000);
Please let me know if this is what you were looking for and/or if you have any questions about how it works.
I am using the below function to scroll to a Div inside a Div.
It works but the car stays at last position so if the user scrolls it flashes to the original position. To clarify the scroll bar is actually at the top of the div but the user sees to bottom element but when user scrolls up he or she doesn't get the expected result of moving to the element right above the last they get bumped to the top.
jQuery.fn.scrollTo = function (elem, speed) {
$(this).animate({
scrollTop: $(this).scrollTop() - $(this).offset().top + $(elem).offset().top
}, speed == undefined ? 1000 : speed);
return this;
};
onclick="$('#usermessageDiv').scrollTo('.last_usermessage', 2000);"
$('.small-chat-box .content').slimScroll({
height: '234px',
railOpacity: 0.4
});
<div id="usermessageDiv" class="content" style="overflow: scroll; width: auto; height: 234px;">
The image below shows where the bar is vs the 2nd lower red arrow where the scroll bar should be in regards to the view shown.
SlimScroll has a scrollTo setting that you should use instead of your scrollTo function.
scrollTo - Jumps to the specified scroll value. Can be called on any
element with slimScroll already enabled. Example:
$(element).slimScroll({ scrollTo: '50px' });
You will need to use jQuery's position() method to get the scroll distance of the target element relative to the parent. If you need detailed help with that, please post some HTML for the usermessageDiv.
I want to show a hyperlinks "prev" "next".
Clicking on "next hyperlink should scroll textarea to next location.
Clicking on "prev" hyperlink should scroll textarea to previous location.
The locations to jump in textarea are known e.g. line: 10, then line 40 , 50 , 70 , 101 , ....
textarea has a fixed height.
You can use pagination.
I prefer using styled pagination with jquery-
http://flaviusmatis.github.com/simplePagination.js/#page-20
This will help you sure.
As per need you want to go next, you need to give position for your current text-block or you can use margin property.
Try this out :- http://jsfiddle.net/MCK8g/
$(function(){
$("#prev").on("click",function(){
$("html, body").animate({ scrollTop: -500 + window.pageYOffset }, 600);
});
$("#next").on("click",function(){
$("html, body").animate({ scrollTop: 500 + window.pageYOffset }, 600);
});
});
Change the factor "500" depending upon the required scroll.
Googled, first hit..
function scrollToLine($textarea, lineNumber) {
var lineHeight = parseInt($textarea.css('line-height'));
$textarea.scrollTop(lineNumber * lineHeight);
}
https://makandracards.com/makandra/8247-scroll-a-textarea-to-a-given-line-with-jquery
(the solution is using jQuery)
as mentioned their it only works if the line-height is set in pixels,
if not, a link with a workaround is also given in the post, see
jQuery: scroll textarea to given position
I have been trying to create a menu panel with jQuery that can be seen here by clicking the Preview button on top:
$(function(){
// hide all panels first
$('div[id*="panel"]').hide();
// make the panels absolute positioned
$('div[id*="panel"]').css('position', 'absolute');
// show the panel based on rel attribute of the current hovered link
$('#menu a').hover(function(){
var link_rel = $(this).attr('rel');
//get the position of the hovered element
var pos = $(this).offset();
// set z-index of previous panels low
$('div[id*="panel"]').css('z-index', '0');
// get the panel near by hovered element now
$('div#' + link_rel).css({
'left': pos.left + 'px',
'top': pos.top + 'px',
'zIndex': '5000'
});
// finaly show the relevant hidden panel
$('div#' + link_rel).fadeIn('slow');
// hide it back when mouse arrow moves away
$('div#' + link_rel).hover(function(){}, function(){
$(this).fadeOut('slow');
});
}, function(){});
});
http://jsbin.com/amexi/edit
If you hover over Link Two or Link Three, the black panel comes perfectly replacing the respective blue link, however if you hover the Link One, the black panel comes little below that link. What's wrong here? How can I fix this?
You need to account for the margin automatically applied to <ul> elements.
If you look at your page with Firebug, you'll notice Firefox applies a top and bottom margin of 16px.
As stated above, you can apply a margin-top value of -16px to the .left class to get your intended behaviour.
http://jsbin.com/amexi/3/edit
Check out http://jsbin.com/amexi/5/edit
I just can't figure out why the TOP is identical on all the popups BUT the actual position of them all is different. Makes no sense. Its almost like a negative margin.
The main problem I found is that you didnt move the popup into the position of the link + offset it to the .top + .height.