I'm using the Waypoints plugin to create some fancy navigation on scroll. So that I can force the user to scroll to the next/previous Waypoint, I'm attempting to collect the vertical scroll position of the current, active and next Waypoint:
$('.waypoint').waypoint(function(direction) {
var
currentWpId = this.element.id,
currentWpPos = $('#'+currentWpId).scrollTop(),
nextWpPost = $('#'+currentWpId).next().scrollTop(),
prevWpPost = $('#'+currentWpId).prev().scrollTop();
console.log( currentWpPos );
console.log( nextWpPost );
console.log( prevWpPost );
});
Unfortunately jQuery's scrollTop() function returns 0 for all elements. After doing some reading I believe this is a result of the elements having height: 100%; which I cannot remove due to some other CSS requirements. (Although I'm not certain this is the root cause of the issue.) Is there a way around this?
After looking for some alternative solutions, I thought to myself the Waypoints
plugin must know the values I'm trying to acquire to trigger a waypoint event! When looking at the this element, that indeed seems to be the case:
So, as an alternative, is there a way to acquire any array/object of all the Waypoint objects so I can grab these triggerPoint values?
scrollTop returns the scroll value of a scrollable element. For example, $(window).scrollTop() returns how much a user has scrolled on the page. I believe you have this confused with the element's position in the document, which you can get by calling .offset(). Offset will return a an object with top and left coordinates. In the end, you're looking for $(elem).offset().top.
Related
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.
Is there a way in javascript to bind an event handler to a horizontal scroll as opposed to the generic scroll event which is fired when the user scrolls horizontally and vertically? I want to trigger an event only when the user scrolls horizontally.
I searched around for an answer to this question, but couldn't seem to find anything.
Thanks!
P.S. My apologies if I'm using some terminology incorrectly. I'm fairly new to javascript.
UPDATE
Thanks so much for all your answers! In summary, it looks like you are all saying that this isn't supported in javascript, but I that I can accomplish the functionality with something like this (using jQuery) (jsFiddle):
var oldScrollTop = $(window).scrollTop();
$(window).bind('scroll', function () {
if (oldScrollTop == $(window).scrollTop())
//scrolled horizontally
else {
//scrolled vertically
oldScrollTop = $(window).scrollTop();
}
});
That's all I needed to know. Thanks again!
Answering from my phone, so unable to provide code at the moment.
What you'll need to do is subscribe to the scroll event. There isn't a specific one for vertical/horizontal.
Next, you'll need to get some measurements about the current display area. You'll need to measure the window.clientHeight and window.clientWidth.
Next, get window.top and window.left. This will tell you where position of the viewport is, ie if it's greater than 0 then scroll bars have been used.
It's pretty simple math from here to get what you need. If no one else has provided a code example in the next few hours I'll try to do so.
Edit:
A bit further information.
You must capture the scroll event. You also need to store the initial window.top and window.left properties somewhere. Whenever the scroll event happens, do a simple check to see if the current top/left values differ from the stores value.
At this point, if either are different you can trigger your own custom events to indicate vertical or horizontal scrolling. If you are using jQuery, this is very easy. If you are writing js without library assistance, it's easy too but a little more involved.
Do some searches for event dispatching in js.
You can then write any other code you want to subscribe to your custom events without needing to tie them together with method calls.
I wrote a jQuery plugin for you that lets you attach functions to the scrollh event.
See it in action at jsfiddle.net.
/* Enable "scrollh" event jQuery plugin */
(function ($) {
$.fn.enableHScroll = function() {
function handler(el) {
var lastPos = el
.on('scroll', function() {
var newPos = $(this).scrollLeft();
if (newPos !== lastPos) {
$(this).trigger('scrollh', newPos - lastPos);
lastPos = newPos;
}
})
.scrollLeft();
}
return this.each(function() {
var el = $(this);
if (!el.data('hScrollEnabled')) {
el.data('hScrollEnabled', true);
handler(el);
}
});
}
}(jQuery));
It's this easy to use:
$('#container')
.enableHScroll()
.on('scrollh', function(obj, offset) {
$('#info').val(offset);
});
Please note that scroll events come very fast. Even if you click in the scrollbar to jump to a new position, many scroll events are generated. You may want to adjust this code to wait a short time and accumulate all the changes in position during that time before firing the hscroll event.
You can use the same scroll event, but within your handler use the scrollLeft function to see if the scrollbar moved horizontally from the last time the event was fired. If the scrollbar did not move then just return from your handler. Otherwise update your variable to the new position and take action.
You can check if the the x value of the page changes and ignore your y value.
If the x value changes: There is your horizontal scroll.
With page-load, store the initial scrollbar positions for both in two variables (presumably both will be 0). Next, whenever a scroll event occurs, find the scrollleft and scrolltop properties. If the scrollleft property's value is different and scrolltop's value is same as compared to their earlier values, that's a horizontal scroll. Then set the values of the variables to the new scroll values.
No, there is no special event for scroll horizontal (it is for global scroll), but you can try to check the position of content by property .scrollLeft and if it's different from the previous value it means that the user scrolled content horizontally.
The error I'm having is the following:
To the right of my page, I have a list of interesting points (displayed on a map to the left of the page).
Because the list is so long, I am using iScroll 4 (great plugin).
However, what I would like to do is fire an event when the user has scrolled the list, so I can check which items are currently visible to the user. iScroll already has an event set up for that, so I have a function that fires when needed. However, I cannot seem to get the proper coordinates of my list items.
What happens is the following:
When the list loads, I get an .offset() value for the first element. offset.top = 35, because my list starts 35px lower than the top edge of the page. This is good.
When I scroll the list; say I pull it down for 500px; I would expect the new location to be 35px - 500px = -465px. However, it sill says 35. Scrolling though the list does not affect the elemen'ts coordinates even though it has moved.
How can I get the actual coordinates?
Playing with iScroll, I think I found the solution. the offset() function is javascript refering to the #scroller div, which doesn't change. However internally, iScroll uses its own x and y properties.
So you can refer to the iScroll offset like this
var myScroll = new iScroll(...)
alert(myScroll.y) // -- will return your offset (negative number)
add in iscroll.js
getScrollY: function () { var that = this; return that.y; },
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.
I have a list of search results in a <div> element with a static height and overflow: auto; in the style. I would like to load only the first x number of search results (e.g. 20), and load another x results as the user scrolls to the bottom of the element containing the search results.
Can anyone explain to me how I would do this? I found a few examples, but all of those use the scroll value of the entire document, not a single <div>. I am using jQuery, if it matters.
Sounds to me like you'd like to detect the scroll bars position when it is near the end. Found this when googling around on the jquery group. Its proposed solution with a little added documentation if needed:
$.fn.isNearTheEnd = function() {
// remember inside of $.fn.whatever = function() {}
// this is the jQuery object the function is called on.
// this[0] is DOMElement
return this[0].scrollTop + this.height() >= this[0].scrollHeight;
};
// an example.
$("#content").bind("scroll", function() {
if ($(this).isNearTheEnd()) // load some content
});
If you compare the div's .top() + .height() to the window's .scrollTop + .height then you could tell when you're at the bottom of that div, and then trigger the next content load...