Reputation: 66560
In Fireofx and IE to get the scrollTop you need to get it from html and in chrome from body element.
Is there a way to detect that without browser sniffing?
var html = document.querySelector('html');
var body = document.querySelector('body');
var input = document.querySelector('input');
window.addEventListener('scroll', function() {
input.value = html.scrollTop + ' ' + body.scrollTop;
});
body {
height: 1000px;
}
input {
position: fixed;
top: 10px;
}
<input/>
I need to detect which element to scroll because I need to change scrollTop from my code.
Upvotes: 1
Views: 90
Reputation: 66560
I came up with this hack, it add pre tag that trigger scrollbar, set scrollTop and check which element have it changed:
var html = $('html');
var body = $('body');
var scrollTop = body.scrollTop() || html.scrollTop();
var pre = $('<pre/>').appendTo('body');
pre.html(new Array(1000).join('\n'));
$('body,html').scrollTop(10);
var scrollObject;
if (body.scrollTop() == 10) {
console.log('body');
scrollObject = body;
body.scrollTop(scrollTop);
} else if ($('html').scrollTop() == 10) {
console.log('html');
scrollObject = html;
html.scrollTop(scrollTop);
}
pre.remove();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Upvotes: 0
Reputation: 35491
Can you just test either for truthiness (assuming 0
means not there)?
function getScrollTop() {
return html.scrollTop || body.scrollTop || 0;
}
var html = document.querySelector('html');
var body = document.querySelector('body');
var input = document.querySelector('input');
window.addEventListener('scroll', function() {
input.value = getScrollTop();
});
body {
height: 1000px;
}
input {
position: fixed;
top: 10px;
}
<input/>
As far as updating the scroll top, you can create a setter function that sets the appropriate browser property. The way you build this setter is by manually triggering a scroll when the page loads and determining which property changed.
function setScrollTopUpdater(cb) {
var html = document.querySelector('html');
var body = document.querySelector('body');
// temporary listener to determine which scroll property updated
// and create an appropriate scroll top setter
window.addEventListener('scroll', function temp() {
if (html.scrollTop > 0) {
// return a function that updates the firefox prop
cb(function(x) {
html.scrollTop = x;
});
} else {
// return a function that updates the chrome prop
cb(function(x) {
body.scrollTop = x;
});
}
window.removeEventListener('scroll', temp);
});
// trigger scroll by 1 pixel
window.scrollTo(window.scrollX, window.scrollY + 1);
}
var updateScrollTop = null;
setScrollTopUpdater(function(updater) {
updateScrollTop = updater;
});
setTimeout(() => {
window.addEventListener('scroll', function demo() {
document.querySelector('input').value = window.scrollY;
});
updateScrollTop(200);
}, 2000)
body {
height: 1000px;
background: #018bbc;
}
input {
position: fixed;
top: 10px;
}
<input placeholder="Will set scrollTop to 200"/>
Upvotes: 1
Reputation: 1860
you can simply check for both values of html.scrollTop
and body.scrollTop
:
if
they're both 0 than the scrolltop is 0using !html.scrollTop
will return true
if it's value is equals to zero or undefined
else if
html.scrollTop
is bigger than 0
(exist) than scrolltop is html.scrollTopelse if
body.scrollTop
is bigger than 0
(chrome) than scrolltop is body.scrollTopin this example I'm storing scrolltop value in a var called myScrollTop
var myScrollTop
if (!html.scrollTop && !body.scrollTop) {
myScrollTop = 0
} else if (html.scrollTop) {
myScrollTop = html.scrollTop
} else if (body.scrollTop) {
myScrollTop = body.scrollTop
}
you can also wrap the code in a function and return the value to the caller
function myScrollTop() {
if (!html.scrollTop && !body.scrollTop) {
return 0
} else if (html.scrollTop) {
return html.scrollTop
} else if (body.scrollTop) {
return body.scrollTop
}
}
or the shorter version
function myScrollTop() {
return html.scrollTop || body.scrollTop || 0
}
now you can get the value of scroll top by calling myScrollTop()
console.log(myScrollTop())
Upvotes: 0
Reputation: 4474
If life was simple, you could use this event handler property. But I.E throws a spanner in the works with no browser support for it. You could of course always write some code to step around IE if this isn't available.
if (!('scrollingElement' in document)) (function() {
alert('IE is a pain in the arse');
}
window.addEventListener('scroll', function(event) {
alert(event.scrollingElement);
});
Upvotes: 1