Scroll a div vertically to a desired position using jQuery - javascript

This is a followup question for this:
Scrollpane on the bottom, css is hacky, javascript is hard
I ended up doing the scrolling in the same way explained in the accepted answer.
Now there is a request that one item is selected somehow (eg. as an url parameter or by some javascript calls) I should scroll the pane to the item with the corresponding ID in the scrollpane. Like a link to an anchor () would work!
I want to make a javascript call like this
function scrollTo(id) {
$('#middle').magicallyScrollThatItemWouldBeVisible(itemid);
}
But this is not in jQuery (or at least I don't know of it). So is there a way to make it?
I'll post a simple jsFiddle here:
http://jsfiddle.net/ruisoftware/U6QdQ/4/
Help me write that scrollTo function!
A .animate would be fine too.
UPDATE: If it was not clear I would like it to only align to the left or right side of the panel, it it was overflowed on that side (so the minimum possible amount of scrolling happens)

It's not jQuery, just JavaScript, and I've actually never used it all, so I'm not sure how you would have to mess with it to get it to work in this situation, but there is a scrollIntoView function:
yourElement.scrollIntoView();

Since the elements have a fixed width, you can count the number of elements by using .index() + 1, and animate to this value (after subtracting the container's width).
If you want the element to be centered, use - Math.round(middle.width()/100)*50.
Fiddle: http://jsfiddle.net/U6QdQ/17/
//This code should be run on load / DOMReady
(function($){ //Run on load / DOMReady
$.fn.magicScrollTo = function(){
var middle = $("#middle");
var currentScrollLeft = middle.scrollLeft();
var width = middle.width();
var newScrollLeft = this.offset().left + currentScrollLeft - middle.offset().left;
if(newScrollLeft >= currentScrollLeft && newScrollLeft <= currentScrollLeft + width - this.outerWidth()) return;
if(newScrollLeft > currentScrollLeft){ //If the element is at the right side
newScrollLeft = newScrollLeft - width + this.outerWidth();
}
middle.animate({
scrollLeft: newScrollLeft,
}, 'fast')
}
})(jQuery);
Usage:
//Select the 4rd element, and scroll to it (eq is zero-based):
$('.item').eq(3).magicScrollTo();

Something along these lines would be a good start:
http://jsfiddle.net/vHjJ4/
This will bring the target into the centre of the carousel. I think you will have to add in some extra checks to make sure that it didn't scroll to far, for example if you targeted the first or last element...unless this is built into the scroll function (it might be).

I'm not sure I understand your question exactly, but it sounds like you're asking how to scroll horizontally to the selected item in the bottom pane. If so, try something like this:
//get the position of the element relative to the parent ("middle")
var pos = $("#itemid").position();
if (pos){
$("#middle").scrollLeft(pos.left);
}
From here, you can use the width of middle to center the item if needed.

Related

Get element position relative to screen. (Or alternative solution)

I am aware this had been asked before, but no answer actually did the trick as far as I tested them.
Basically what I need is to change some element styles as soon as it "hits" the top border of the screen while scrolling down. This element is a 'Back to Top' button that will be sitting in a section and start following the user when they scroll pass said section.
I am not asking about CSS properties, I am asking about some JS property or method that allow me to know this. IE:
$('#back').distanceFromTopOfTheScreen() // This value will decrease as I scroll down
I know there are other soultions, but the client has asked for this behavior.
Any idea?
You can :
distance = $('#eleId')[0].getBoundingClientRect().top;
For more about getBoundingClientRect() look at the MDN Documentation
Note: This value change when you're scrolling, it gives you the distance between the top border of the element and the top of the Page
Sometimes JQuery make's everything more confusing than Native Javascript, even forgothing the very basics functions:
window.onscroll = function() { fixPosition()};
function fixPosition() {
var Yplus = 4; //number of lines in every scroll
document.getElementById('element').style.top = document.body.scrollTop + Yplus ;
}
This will allows you to move an "element" static on the window following the scroll.

change start position of horizontal scrollbar without jquery

In Jquery I'm aware you can move the scrollbars' starting location. Is this possible with pure javascript? To clarify, when the user loads the page I simply want the horizontal scrollbar to start scrolled all the way to the right, instead of starting at the left. If there are cross-browser issues, I'm particularly concerned with this working in Chrome.
document.body.scrollLeft = ( divRef.scrollWidth - divRef.offsetWidth ) / 2 ;
NOTE:
This can give odd results with IE8 and earlier.
I've made an example with a div, you can easily adjust this to your body tag, or another div, please see the demo.
var a = document.getElementById('body');
console.log(a.clientWidth)
function moveWin(a) {
window.scrollTo(a.clientWidth,0);
}
moveWin(a)
DEMO
SIDENOTE:
To select the body, simply use
var a = document.getElementsByTagName('body')[0]

Test if element can be seen by the user on an html page

Is there any way to know if an element is visible on an html page?
Like this:
One can probably do it considering the horizontal/vertical scrolling positions, the width/height of the browser window and the position/size of the element on the page, but I have little experience in jQuery so I don't know how to do it. And there might be a simple function one can call, I don't know.
You can use the .is(':visible') selectors to check if an element is currently visible in the DOM.
Edit:
However, as #BenM mentioned, this doesn't check if the elements on your page are actually out of your scrollable range - a great little plugin you could use in that case would be Viewport Selectors for jQuery.
Here is some code that I use to do this. It has been tested to work great.
function isVisible($obj) {
var top = $(window).scrollTop();
var bottom = top + $(window).height();
var objTop = $obj.offset().top;
var objBottom = objTop + $obj.height();
if(objTop < bottom && objBottom > top) {
//some part of $obj is visible on the screen.
//does not consider left/right, only vertical.
}
}

So DOM scrollIntoView aligns top/bottom, but what about left/right?

I would like to scroll horizontally the given element. The only way I find is using ScrollIntoView DOM method, which allows either align the element's bottom with the view bottom or the top - with the view top.
But what if the element is OK with respect to the Y axis, and I only want to scroll it horizontally? How can I align its left with the view left or its right with the view right?
EDIT
Here is more context. I have a YUI table with a horizontal scrollbar. I wish to scroll it programmatically to a certain TD node. I do not think window.scrollTo is of any help to me, since the scrollbar is on a div element, not on the whole page.
EDIT2
Turns out there is a duplicate SO question with the right answer - How can I scroll programmatically a div with its own scrollbars?
Voting to close mine.
I've recently had a problem with a table header that had inputs as filters for each column. Tabbing through the filters would move the focus, but if one of the inputs wasn't visible or if it was partly visible, it would only JUST bring the input into view, and I was asked to bring the full input and column into view. And then I was asked to do the same if tabbing backwards to the left.
This link helped to get me started: http://www.webdeveloper.com/forum/showthread.php?197612-scrollIntoView-horizontal
The short answer is that you want to use:
document.getElementById('myElement').scrollLeft = 50;
or:
$('#myElement')[0].scrollLeft = 50;
Here's my solution (which may be overkill for this question, but maybe it'll help someone):
// I used $.on() because the table was re-created every time the data was refreshed
// #tableWrapper is the div that limits the size of the viewable table
// don't ask me why I had to move the head head AND the body, they were in 2 different tables & divs, I didn't make the page
$('#someParentDiv').on('focus', '#tableWrapper input', function () {
var tableWidth = $('#tableWrapper')[0].offsetWidth;
var cellOffset = $(this).parent()[0].offsetLeft;
var cellWidth = $(this).parent()[0].offsetWidth;
var cellTotalOffset = cellOffset + cellWidth;
// if cell is cut off on the right
if (cellTotalOffset > tableWidth) {
var difference = cellTotalOffset - tableWidth;
$('#tableWrapper').find('.dataTables_scrollHead')[0].scrollLeft = difference;
$('#tableWrapper').find('.dataTables_scrollBody')[0].scrollLeft = difference;
}
// if cell is cut off on the left
else if ($('#tableWrapper').find('.dataTables_scrollHead')[0].scrollLeft > cellOffset) {
$('#tableWrapper').find('.dataTables_scrollHead')[0].scrollLeft = cellOffset;
$('#tableWrapper').find('.dataTables_scrollBody')[0].scrollLeft = cellOffset;
}
});
This is something I used a while back. There might be better and more efficient way of doing it but this gets the work done:
$(".item").click(function(event){
event.preventDefault();
// I broke it down into variable to make it easier to read
var tgt_full = this.href,
parts = tgt_full.split("#"),
tgt_clean = parts[1],
tgt_offset = $("#"+tgt_clean).offset(),
tgt_left = tgt_offset.left;
$('html, body').animate({scrollLeft:tgt_left}, 1000, "easeInOutExpo");
})
You just need to make sure that the item is an a tag with an href that corresponds to the target id element:
HTML:
go to section 1
...
<section id="one"> Section 1</section>
Hope this helps!

JavaScript to scroll long page to DIV

I have a link on a long HTML page. When I click it, I wish a div on another part of the page to be visible in the window by scrolling into view.
A bit like EnsureVisible in other languages.
I've checked out scrollTop and scrollTo but they seem like red herrings.
Can anyone help?
old question, but if anyone finds this through google (as I did) and who does not want to use anchors or jquery; there's a builtin javascriptfunction to 'jump' to an element;
document.getElementById('youridhere').scrollIntoView();
and what's even better; according to the great compatibility-tables on quirksmode, this is supported by all major browsers!
If you don't want to add an extra extension the following code should work with jQuery.
$('a[href=#target]').
click(function(){
var target = $('a[name=target]');
if (target.length)
{
var top = target.offset().top;
$('html,body').animate({scrollTop: top}, 1000);
return false;
}
});
How about the JQuery ScrollTo - see this sample code
You can use Element.scrollIntoView() method as was mentioned above. If you leave it with no parameters inside you will have an instant ugly scroll. To prevent that you can add this parameter - behavior:"smooth".
Example:
document.getElementById('scroll-here-plz').scrollIntoView({behavior: "smooth", block: "start", inline: "nearest"});
Just replace scroll-here-plz with your div or element on a website. And if you see your element at the bottom of your window or the position is not what you would have expected, play with parameter block: "". You can use block: "start", block: "end" or block: "center".
Remember: Always use parameters inside an object {}.
If you would still have problems, go to https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
There is detailed documentation for this method.
Click here to scroll
<A name='myAnchorALongWayDownThePage"></a>
No fancy scrolling but it should take you there.
The difficulty with scrolling is that you may not only need to scroll the page to show a div, but you may need to scroll inside scrollable divs on any number of levels as well.
The scrollTop property is a available on any DOM element, including the document body. By setting it, you can control how far down something is scrolled. You can also use clientHeight and scrollHeight properties to see how much scrolling is needed (scrolling is possible when clientHeight (viewport) is less than scrollHeight (the height of the content).
You can also use the offsetTop property to figure out where in the container an element is located.
To build a truly general purpose "scroll into view" routine from scratch, you would need to start at the node you want to expose, make sure it's in the visible portion of it's parent, then repeat the same for the parent, etc, all the way until you reach the top.
One step of this would look something like this (untested code, not checking edge cases):
function scrollIntoView(node) {
var parent = node.parent;
var parentCHeight = parent.clientHeight;
var parentSHeight = parent.scrollHeight;
if (parentSHeight > parentCHeight) {
var nodeHeight = node.clientHeight;
var nodeOffset = node.offsetTop;
var scrollOffset = nodeOffset + (nodeHeight / 2) - (parentCHeight / 2);
parent.scrollTop = scrollOffset;
}
if (parent.parent) {
scrollIntoView(parent);
}
}
This worked for me
document.getElementById('divElem').scrollIntoView();
Answer posted here - same solution to your problem.
Edit: the JQuery answer is very nice if you want a smooth scroll - I hadn't seen that in action before.
Why not a named anchor?
The property you need is location.hash. For example:
location.hash = 'top'; //would jump to named anchor "top
I don't know how to do the nice scroll animation without the use of dojo or some toolkit like that, but if you just need it to jump to an anchor, location.hash should do it.
(tested on FF3 and Safari 3.1.2)
I can't add a comment to futtta's reply above, but for a smoother scroll use:
onClick="document.getElementById('more').scrollIntoView({block: 'start', behavior: 'smooth'});"
<button onClick="scrollIntoView()"></button>
<br>
<div id="scroll-to"></div>
function scrollIntoView() {
document.getElementById('scroll-to').scrollIntoView({
behavior: 'smooth'
});
}
The scrollIntoView method accepts scroll-Options to animate the scroll.
With smooth scroll
document.getElementById('scroll-to').scrollIntoView({
behavior: 'smooth'
});
No animation
document.getElementById('scroll-to').scrollIntoView();
There is a jQuery plugin for the general case of scrolling to a DOM element, but if performance is an issue (and when is it not?), I would suggest doing it manually. This involves two steps:
Finding the position of the element you are scrolling to.
Scrolling to that position.
quirksmode gives a good explanation of the mechanism behind the former. Here's my preferred solution:
function absoluteOffset(elem) {
return elem.offsetParent && elem.offsetTop + absoluteOffset(elem.offsetParent);
}
It uses casting from null to 0, which isn't proper etiquette in some circles, but I like it :) The second part uses window.scroll. So the rest of the solution is:
function scrollToElement(elem) {
window.scroll(0, absoluteOffset(elem));
}
Voila!
As stated already, Element.scrollIntoView() is a good answer. Since the question says "I have a link on a long HTML page..." I want to mention a relevant detail. If this is done through a functional link it may not produce the desired effect of scrolling to the target div. For example:
HTML:
<a id="link1" href="#">Scroll With Link</a>
JavaScript:
const link = document.getElementById("link1");
link.onclick = showBox12;
function showBox12()
{
const box = document.getElementById("box12");
box.scrollIntoView();
console.log("Showing Box:" + box);
}
Clicking on Scroll With Link will show the message on the console, but it would seem to have no effect because the # will bring the page back to the top. Interestingly, if using href="" one might actually see the page scroll to the div and jump back to the top.
One solution is to use the standard JavaScript to properly disable the link:
<a id="link1" href="javascript:void(0);">Scroll With Link</a>
Now it will go to box12 and stay there.
I use a lightweight javascript plugin that I found works across devices, browsers and operating systems: zenscroll
scrollTop (IIRC) is where in the document the top of the page is scrolled to. scrollTo scrolls the page so that the top of the page is where you specify.
What you need here is some Javascript manipulated styles. Say if you wanted the div off-screen and scroll in from the right you would set the left attribute of the div to the width of the page and then decrease it by a set amount every few seconds until it is where you want.
This should point you in the right direction.
Additional: I'm sorry, I thought you wanted a separate div to 'pop out' from somewhere (sort of like this site does sometimes), and not move the entire page to a section. Proper use of anchors would achieve that effect.
I personally found Josh's jQuery-based answer above to be the best I saw, and worked perfectly for my application... of course, I was already using jQuery... I certainly wouldn't have included the whole jQ library just for that one purpose.
Cheers!
EDIT: OK... so mere seconds after posting this, I saw another answer just below mine (not sure if still below me after an edit) that said to use:
document.getElementById('your_element_ID_here').scrollIntoView();
This works perfectly and in so much less code than the jQuery version! I had no idea that there was a built-in function in JS called .scrollIntoView(), but there it is! So, if you want the fancy animation, go jQuery. Quick n' dirty... use this one!
For smooth scroll this code is useful
$('a[href*=#scrollToDivId]').click(function() {
if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
var target = $(this.hash);
target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
var head_height = $('.header').outerHeight(); // if page has any sticky header get the header height else use 0 here
if (target.length) {
$('html,body').animate({
scrollTop: target.offset().top - head_height
}, 1000);
return false;
}
}
});
Correct me if I'm wrong but I'm reading the question again and again and still think that Angus McCoteup was asking how to set an element to be position: fixed.
Angus McCoteup, check out http://www.cssplay.co.uk/layouts/fixed.html - if you want your DIV to behave like a menu there, have a look at a CSS there

Categories

Resources