*.pageYOffset, *.scrollY, *.scrollTop always logging undefined - javascript

My JS needs to know how far the user is scrolled down the page.
If I run this code:
document.addEventListener('scroll', event => console.log(document.pageYOffset));
...or do the same thing with scrollY ... or scrollTop ... or swap 'document' in for 'window' ... the console hears the event as I scroll, but always logs 'undefined'. This happens across multiple HTML documents, in Chrome and Firefox, whether I have any CSS reset on or not. What am I doing wrong?

It's window.pageYOffset not document.pageYOffset. Refer What is the difference between window, screen, and document in JavaScript?

Related

In a Browser, Break on Window Scroll

In Chrome Devtools, you can break javascript on changing a DOM element's attributes, or on subtree modifications of an element.
I'm working on some legacy code that has some javascript that scrolls to the top of the page under certain situations, and I want to find the JS that does this.
Is there a way, in Devtools, so break on scroll events?
It could be jQuery or Prototype.js or event base JS that does it, and I've searched the codebase for .scrollTop or .animate, and I've found plenty of those, but none that are causing my issue.
I have no additional idea about actually breaking than the ones presented.
But i suspect it is not scrolling that causes the issue, but a '#' in the html.
x
is a very common pattern. when you forget (or something prevents) the "return false", the # (empty anchor) will be navigated to, which causes a scroll to top.
Check if the url has a # at the end after clicking!
You can inject this line of JS using the console to trigger the debugger when the scroll position changes programatically.
window.__defineSetter__("pageYOffset", function(){
debugger;
});
Then, view the call stack to see what triggered it.
If you don't want to activate the debugger, you can print the stack trace istead with the following code:
window.__defineSetter__("pageYOffset", function(){
console.log(new Error().stack);
});
Another option is to replace the windows scroll, scrollTo and scrollBy method with your own.
window.__defineGetter__('scroll', function(){
console.log('window.scroll getter :' + new Error().stack);
return function(x,y){
debugger; //or print stack trace
oldScroll(x,y);
}
});
Repeat for scrollTo and scrollBy.

Scrolling window before QUnit test

I'm using QUnit and trying to test if on scroll event one of the variables is modified. Simplified source example is below:
$(window).on("scroll.singleJob",function(e) {
if($(window).scrollTop()>10) mycompany.somevar=10;
});
My QUnit test is as follow:
test("should attach panel once window scrolled down past certain point", function() {
$(window).scrollTop(1000);
ok(mycompany.somevar==10,"lozenges panel is sticky");
});
Now, I believe that window should be scrolled, test ran and mycompany.somevar set to 10. The problem is that $(window).scrollTop(1000); dosen't do anything and the code runs as the window is not scrolled. I also tried QUnit.config.scrolltop = false; but with no luck.
So my question is how to scroll the fixture window so the test will run as the window was scrolled?
Use the scrollTo method with two parameters:
window.scrollTo(0,1000)
References
Working with Windows: Manipulating Windows
Events:Scroll and Mousewheel
CSSOM View Module

Getting scrollTop to work in IE Quirks Mode from an iframe within an iframe

I'm having a rather frustrating time trying to force my page to scroll back to the top after submitting a form.
The code I'm trialling this with is simple:
$('body').prepend('Click here');
$('body').on("click", "#testing", function() {
window.top.$('body, html').animate({ scrollTop: 0 }, 0);
});
This works, as intended, on FireFox - but not Internet Explorer.
It's worth noting that I'm using the UWA widget format and my code is essentially embedded within two iframes. There is an iframe for the HTML template and iframe containing this widget. I have control over neither of these frames, nor can I give you the full code because it is literally thousands of lines of horribly-written, misaligned HTML and JavaScript.
Here are some facts that I've put together to see if anyone can spot the problem because I'm don't really know where to begin looking:
In FireFox, this code works fine - clicking the link instantly scrolls the whole page to the top
If I open the IE console the Page Default Standard is "Quirks Mode". Changing this to "IE9 Standards" fixes the problem, i.e. clicking the link scrolls the whole page back to the top
Changing window.top to window.parent works in neither browser
Changing window.top to window.parent.parent also works in FF but doesn't work in IE
Changing animate({ scrollTop: 0 }, 0); to scrollTop(0) works in FF but doesn't work in IE
If I run the following alerts in IE, bizarrely (to me), here is the output:
alert(typeof window.parent); // object
alert(typeof window.top); // object
alert(typeof window.parent.parent); // object
alert(typeof window.parent.$('html')); // object
alert(typeof window.parent.$('body')); // object
alert(window.parent.offset().top); // alert doesn't trigger, no further alerts run until this line is commented
alert(window.parent.parent.offset().top); // alert doesn't trigger, no further alerts run until this line is commented
alert(window.parent.$('html').offset().top); // 0
alert(window.parent.$('body').offset().top); // 0
alert(window.top.$('html').offset().top); // 0
alert(window.top.$('body').offset().top); // 0
In short, it looks like window.top is accessible and so is the $('html') element from there... so why can't I get my page to scroll unless I force standards mode in my browser?

run code after window ready and scrolled

I see a difference between FF and Chrome (Version 22.0.1229.94 m) in this matter. FF is right (I would say).
when scrolling down a page and hitting then refreshing it, the callback of
$(window).ready(function(){
console.log( $(document).scrollTop() );
});
The console should say the amount scrolled after the window was ready, but in Chrome it's always 0
How can I show the get the amount of scrollTop in Chrome?
like some said in the comments, Chrome load the page, and then scroll it down.
Therefor when jQuery event is fired, the scroll is at 0.
You can do some work around like that :
$(document).ready(function() {
function getScroll() {
var scroll = $(window).scrollTop();
...
}
getScroll();
$(window).scroll(getScroll);
});​
So in Chrome $(window).scroll(); will be fired just after the page is loaded.
EDIT: tested there http://fiddle.jshell.net/azaret/Mt65R/show/light/
Problem is that document.ready() in Chrome is executed before the browser scrolls down to the previous point and that is why you always get a zero value. A solution is provided here: Get vertical position of scrollbar for a webpage on pageload when the url contains an anchor

Javascript function call across HTML windows

According to this page I should be able to call parameters and functions of child windows, but it is not working for me.
var w = window.open("index.html");
console.log(w);
console.log(w.foo);
console.log(w) shows that there is a function named foo but console.log(w.foo) outputs undefined. Is this a security issue?
EDIT Here is some more functionality:
child.html (omitting the body):
<head>
<script type="text/javascript">
test = 123 ;
function foo(arg){
//do something
}
</script>
</head>
parent.html:
var w = window.open("child.html");
console.log(w);
//outputs all the methods and parameters
console.log(w.foo);
//outputs 'undefined'
console.log(w.test);
//outputs 'undefined'
EDIT 2 Also I should explain why I need to pass arguments as someone will inevitably ask me why I can't 'just hard code it'. I have an HTML canvas element, and every time the user right clicks, there is a right click menu with the option 'list shapes underneath'.
When the user clicks this menu item, I want to pass a list of all the shapes underneath that click and to display it in a new window. Here are the problems I am facing:
I can't pass it as an argument b/c I don't know whether the window has been loaded (I can't seem to change the onload function either)
I can't have the child window query the parent window b/c the right click menu disappears after clicking it.
The problem is that you are not giving the DOM of the child window a chance to load before trying to inspect its contents.
console.log(w) appeared to work by displaying Window or similar immediately, but in fact it's just that by the time your human fingers got around to expanding the item details in the console, the properties and methods were present.
When I inject a delay with help from a Firebug breakpoint, I can see the child window's properties like this just fine.
This question talks about adding onLoad event listeners for children. Using its accepted answer, how about:
<script type="text/javascript">
// parent.html
var w;
function lol() {
console.log(w.foo);
console.log(w.test);
}
w = window.open("child.html");
console.log(w);
w.addEventListener('load', lol, true);
</script>
(I was also able to achieve success with a 1s setTimeout delay.)
The answer is rather simple if you look at your code logically
The following two calls will only work inside the window you open.
console.log(w.foo);
//outputs 'undefined'
console.log(w.test);
//outputs 'undefined'
i.e.
console.log(foo);
in the parent window javascript, and
console.log(window.parent.foo);
in the child window javascript.

Categories