Most perfomance way to get user scroll position on scroll event - javascript

What is the best-performance way to get window.scroll position when user scrolls the page?
Maybe when the event fires there is some variable witch natively store something like $(window).scrollTop() value and there is no need to call $(window).scrollTop() manually to figure it out?

You can access the scroll via the $(this) keyword.
So you'd do something like this:
$(window).on('scroll', function() {
var scroll = $(this)[0].scrollY
});
That's your alternative. I didn't do any tests to see whether it's better performance wise, but it's an option if you do not want to call the $(window).scrollTop()

Related

Angularjs: What's the correct ways to get correct offsetTop value when page load

Problem:
I Cannot get correct top offset value of DOM element when page just loaded.
The project I'm working on needs to get the offsetTop value of several DOM element when the page just loaded.
The reason is that I need to re-position several DOM element depends on the $window height and their initial position on the webpage.
If the DOM element is all the way down the page, I want to put a fixed bar on the bottom of the page to indicate the users "there's more, but you need to scroll down to see it".
Debugging Phase:
Method I have tried:
angular.element ready event and angular $viewContentLoaded event
Here is my snippet of code of getting the offsetTop of a element
angular.element(document).ready(function(){
var elem = angular.element(document.getElementById('test-element');
console.log(elem[0].getBoundingClientRect().top;
console.log(elem[0].offsetTop);
console.log(elem.offset().top);
});
and
$scope.$on('$viewContentLoaded', function(){
var elem = angular.element(document.getElementById('test-element');
console.log(elem[0].getBoundingClientRect().top;
console.log(elem[0].offsetTop);
console.log(elem.offset().top);
});
Above will all print wrong offsetTop of the element. Then I create a timeout function to test the offsetTop value of the same element, which yield the correct offset top.
$timeout(function(){
var elem = angular.element(document.getElementById('test-element');
console.log(elem[0].getBoundingClientRect().top;
console.log(elem[0].offsetTop);
console.log(elem.offset().top);
},100);
Basically, the timeout function waits 100ms to read the top offset of the same element, whic h gives me a correct offset
Assumption:
My assumptions why this happens because:
I use ngRepeat to produce a table. The content of the table is fetched from database when the page loaded.
$viewContentLoaded and angular.element ready event fire before the ngRepeat render its content. That's a possible reason because when fetching offset in $viewContentLoaded/ready event function, it has no idea of the height/offset the "ngRepeat" table yet.
The reason why $timeout function can get the correct top offset is that when the $timeout function execute its code, ngRepeat finishes its work and everything on the webpage is on stable state.
There exists a timing between $timeout function and $viewContentLoaded/ready event that will give me correct offset value.
Questions:
Is the assumption about ngRepeat/$viewContentLoaded/ready correct?
What's the right way to fetch the top offset for a DOM element when the page just loaded?
Or, what's the right event to fetch the correct offset?
It's a long description of the problem. I hope I made it clear. I'm sorry for any English syntax error.
Thank you a lot.
You should probably fire an event for your ngrepeat's finish, like this:
https://stackoverflow.com/a/15208347/4497117
Then you could catch that exact event in your directive.
This is the closest i have seen to be working (without too much clutter).
Also be aware that if you have visibility toggling (ng-show) at the moment the custom ngrepeat finish event fires, you may still get weird values
Answering #2:
getBoundingClientRect() is relative to the current scroll position and will change as the page scrolls. Hence, to see if an element is outside the current viewport, you could do something like this:
function isOffscreen(el) {
var rect = el.getBoundingClientRect();
return (rect.bottom > 0 || rect.bottom <= window.innerHeight);
}

Triggering Jquery at certain length of page

I'm trying to figure how to trigger an jquery animation when the user scrolls to the middle of the page. Is there a way to set a listener to see if the person scrolls halfway down the page it activates the jquery code?
Using jQuery, you can attach an event handler to the scroll event, which will let you listen to whenever the window is scrolled and determine whether the user has scrolled the appropriate amount.
$(window).scroll(function () {
if (($(window).scrollTop()) > ($(document).height() / 2)) {
// Run animation here
}
});
http://jsfiddle.net/ult_combo/XdqPJ/1/
Think so.. you can look at checking parts of the page using;
setInterval(name_Of_Function,1000);
runs every second, then run a check on there is;
window.pageYOffset // Gives you current horizontal window scroll position for the page.
Firebug is helpful to get more information on these functions. Remember to check in all major browsers as the implementation or values returned may be slightly different between different browsers.
Good reference page I found;
http://www.softcomplex.com/docs/get_window_size_and_scrollbar_position.html
Is there a way to set a listener to see if the person scrolls halfway
down the page it activates the jquery code?
You can get the amount that the user has scrolled with the following:
$("html,body").scrollTop();
so, to trigger an event halfway down the page:
if (($("html,body").scrollTop()) > ($("html,body").height() / 2))
{
// Code that will be triggered
}
You would need a timer to constantly be checking this. You can use setInterval() in Javascript to repeatedly execute a function to check this.
http://api.jquery.com/scrollTop/

Cross-browser method to capture scroll events (or an easier way to temporarily disable scrolling)

I'm trying to execute a Javascript function whenever a user scrolls a page.
I've tried:
<body onscroll="myScrollFunction()">
and this works fine in Firefox but not IE.
I also tried:
window.onscroll = "myScrollFunction()";
but this seems to only perform the function once, similar to an onload event, but further scrolls do not fire the event. My doctype is set to strict; not sure if this makes a difference or not.
How can I get this to work across all browsers?
What I'm trying to accomplish is a way to prevent users from scrolling once a modal is displayed. I'd rather not use
overflow:hidden
because the document shifts slightly when the modal is displayed (to compensate for the scrollbar), so I figured I could capture the scroll function and lock it to the top of the page whenever the modal is displayed. If there is an easier way to do this, please let me know.
Instead of
window.onscroll = myScrollFunction();
which assigns the result of the myScrollFunction() to the onscroll handler, you want
window.onscroll = myScrollFunction;
which assigns the function itself, and will therefore be called on each scroll.
I suggest that instead of doing that, you just give your modal dialog position: fixed; which will fix it to the viewport instead of the page.
Set the <body>'s overflow to hidden while your lightbox is open.
$('body').css('overflow','hidden');
...then return to normal when it closes:
$('body').css('overflow','auto');

Javascript Custom Resize Event [duplicate]

This question already has answers here:
How to detect DIV's dimension changed?
(28 answers)
Closed 7 years ago.
I have a very simple question, or at least it seems that way.
I have a DIV element which will be resized at one moment. I want to be able to capture the resizing moment.
Something like this:
function myFunction(){
alert('The DIV was resized');
}
divElement.addEventListener("resize", myFunction, false);
Does anyone know the answer?
Thanks
As of December 2011, there's no built-in event to detect when a div resizes, just when a window resizes.
Check out this related question: Detecting when a div's height changes using jQuery, and this plugin from the solution to that question: http://benalman.com/projects/jquery-resize-plugin/
With jQuery resize event, you can now bind resize event handlers to
elements other than window, for super-awesome-resizing-greatness!
Why is a plugin needed for the resize event?
Long ago, the powers-that-be decided that the resize event would only
fire on the browser’s window object. Unfortunately, that means that if
you want to know when another element has resized, you need to
manually test its width and height, periodically, for changes. While
this plugin doesn’t do anything fancy internally to obviate that
approach, the interface it provides for binding the event is exactly
the same as what’s already there for window.
For all elements, an internal polling loop is started which
periodically checks for element size changes and triggers the event
when appropriate. The polling loop runs only once the event is
actually bound somewhere, and is stopped when all resize events are
unbound.
Sample Code
// You know this one already, right?
$(window).resize(function(e){
// do something when the window resizes
});
// Well, try this on for size!
$("#unicorns").resize(function(e){
// do something when #unicorns element resizes
});
// And of course, you can still use .bind with namespaces!
$("span.rainbows").bind( "resize.rainbows", function(e){
// do something when any span.rainbows element resizes
});
You can try this plugin - http://benalman.com/code/projects/jquery-resize/examples/resize/
There are various examples. Try resizing your window and see how elements inside container elements adjusted.
Example with js fiddle
In that resize() event is bound to an elements having class "test" and also to the window object and in resize callback of window object $('.test').resize() is called.
e.g.
$('#test_div').bind('resize', function(){
console.log('resized');
});
$(window).resize(function(){
$('#test_div').resize();
});
See this
My first thought is to use a custom event system. You can find a pure javascript one here ( http://www.nczonline.net/blog/2010/03/09/custom-events-in-javascript/ )
After including his code, you can do something like this:
function myFunction(){
alert('The DIV was resized');
}
div_elm = document.getElmentById('div-to-resize');
EventTarget.call(div_elm);
div_elm.addListener("resize", myFunction);
Then later, just add one line to wherever you are resizing the div.
div_elm.width += 100 //or however you are resizing your div
div_elm.fire("resize");
I think that should work for you.
EDIT:
If you are not the one coding the resizing, then my first thought is something like this:
var resizeScannerInterval_id = (function(div) {
var width = div.offsetWidth;
var height = div.offsetHeight;
var interval_id = setInterval(function() {
if( div.offsetWidth != width || div.offsetHeight != height )
width = div.offsetWidth;
height = div.offsetHeight;
div.fire();
}
},250);
})(document.getElementById('div-id'))
There is a very efficient method to determine if a element's size has been changed.
http://marcj.github.io/css-element-queries/
This library has a class ResizeSensor which can be used for resize detection. It uses a event-based approach, so it's damn fast and doesn't waste CPU time.
Please do not use the jQuery onresize plugin as it uses setTimeout() loop to check for changes. THIS IS INCREDIBLY SLOW AND NOT ACCURATE.

scroll event by amount?

I'm currently using a something like this to do stuff on ready and on the scroll event. But I really only need to do stuff each time the page scrolls a full length (window height) and not refire it for every little bitsy scroll. Is there a way to do that using jQuery or native JavaScript?
$(document).ready(function() {
$(window).scroll(function() {
// do stuff
}).scroll(); // Trigger scroll handlers.
});
You can't really fire an event without listening for it, but you can use jQuery's scrollTop() to see if the page is scrolled the same amount as the window height, but it will have to be checked on a certain event, like the scroll event, something like this:
$(window).on('scroll', function() {
if ($(this).scrollTop() > $(window).height()) {
alert("scrolled more than window height");
}
});
There isn't any way to only trigger the scroll at certain points on the page, you'll need to check it everytime... but you might want to consider throttling or debouncing the event.

Categories

Resources