can someone please explain this simple code to ? scroll indicator - javascript

this a simple code a found in the internet to create a scroll indicator but the problem is that I don't understand the logic behind it.... why subtract max Height and inner Height and after that use the result for division , and why multiplying by 100 what is the logic behind this ?
P.S. I know that :
scrollHeight is to return full height of the HTMLdocument.
innerHeight returns the height of the viewable window (with the scrollbar)
pageYoffset is the same thing as ScrollY returns number of pixels scrolled
it's a matter of why using not how to use....
const progressbar = document.querySelector('.scroll--progress');
const scroll = () => {
// return the scroll height of the entier page
const maxHeight = document.body.scrollHeight;
//return the innerheight of the ViewPort
const inner = window.innerHeight;
const a = maxHeight - innerHeight;
const t = Math.round(window.pageYOffset);
const b = (window.scrollY / a) * 100;
//setup the progress bar width
progressbar.style.width = `${b}` + '%';
};
window.addEventListener('scroll', scroll);

There's better cross-compatibility with the use of pageYOffset; I'd not use the scrollY unless there's a scenario that proves it useful. Rare browser-cases?
scrollY and pageYOffset are the same! But all browsers on MDN support pageYOffset.

Related

javascript detect reach bottom mobile [duplicate]

How can I find out what percentage of the vertical scrollbar a user has moved through at any given point?
It's easy enough to trap the onscroll event to fire when the user scrolls down the page, but how do I find out within that event how far they have scrolled? In this case, the percentage particularly is what's important. I'm not particularly worried about a solution for IE6.
Do any of the major frameworks (Dojo, jQuery, Prototype, Mootools) expose this in a simple cross-browser compatible way?
Oct 2016: Fixed. Parentheses in jsbin demo were missing from answer. Oops.
Chrome, Firefox, IE9+. Live Demo on jsbin
var h = document.documentElement,
b = document.body,
st = 'scrollTop',
sh = 'scrollHeight';
var percent = (h[st]||b[st]) / ((h[sh]||b[sh]) - h.clientHeight) * 100;
As function:
function getScrollPercent() {
var h = document.documentElement,
b = document.body,
st = 'scrollTop',
sh = 'scrollHeight';
return (h[st]||b[st]) / ((h[sh]||b[sh]) - h.clientHeight) * 100;
}
If you prefer jQuery (original answer):
$(window).on('scroll', function(){
var s = $(window).scrollTop(),
d = $(document).height(),
c = $(window).height();
var scrollPercent = (s / (d - c)) * 100;
console.clear();
console.log(scrollPercent);
})
html{ height:100%; }
body{ height:300%; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I think I found a good solution that doesn't depend on any library:
/**
* Get current browser viewpane heigtht
*/
function _get_window_height() {
return window.innerHeight ||
document.documentElement.clientHeight ||
document.body.clientHeight || 0;
}
/**
* Get current absolute window scroll position
*/
function _get_window_Yscroll() {
return window.pageYOffset ||
document.body.scrollTop ||
document.documentElement.scrollTop || 0;
}
/**
* Get current absolute document height
*/
function _get_doc_height() {
return Math.max(
document.body.scrollHeight || 0,
document.documentElement.scrollHeight || 0,
document.body.offsetHeight || 0,
document.documentElement.offsetHeight || 0,
document.body.clientHeight || 0,
document.documentElement.clientHeight || 0
);
}
/**
* Get current vertical scroll percentage
*/
function _get_scroll_percentage() {
return (
(_get_window_Yscroll() + _get_window_height()) / _get_doc_height()
) * 100;
}
This should do the trick, no libraries required:
function currentScrollPercentage()
{
return ((document.documentElement.scrollTop + document.body.scrollTop) / (document.documentElement.scrollHeight - document.documentElement.clientHeight) * 100);
}
These worked for me perfectly in Chrome 19.0, FF12, IE9:
function getElementScrollScale(domElement){
return domElement.scrollTop / (domElement.scrollHeight - domElement.clientHeight);
}
function setElementScrollScale(domElement,scale){
domElement.scrollTop = (domElement.scrollHeight - domElement.clientHeight) * scale;
}
A Typescript implementation.
function getScrollPercent(event: Event): number {
const {target} = event;
const {documentElement, body} = target as Document;
const {scrollTop: documentElementScrollTop, scrollHeight: documentElementScrollHeight, clientHeight} = documentElement;
const {scrollTop: bodyScrollTop, scrollHeight: bodyScrollHeight} = body;
const percent = (documentElementScrollTop || bodyScrollTop) / ((documentElementScrollHeight || bodyScrollHeight) - clientHeight) * 100;
return Math.ceil(percent);
}
If you're using Dojo, you can do the following:
var vp = dijit.getViewport();
return (vp.t / (document.documentElement.scrollHeight - vp.h));
Which will return a value between 0 and 1.
This question has been here for a long time, I know, but I stumbled onto it while trying to solve the same problem. Here is how I solved it, in jQuery:
First, I wrapped the thing I wanted to scroll in a div (not semantic, but it helps). Then set the overflow and height on the wrapper.
<div class="content-wrapper" style="overflow: scroll; height:100px">
<div class="content">Lot of content that scrolls</div>
</div>
Finally I was able to calculate the % scroll from these metrics:
var $w = $(this),
scroll_top = $w.scrollTop(),
total_height = $w.find(".content").height(),
viewable_area = $w.height(),
scroll_percent = Math.floor((scroll_top + viewable_area) / total_height * 100);
Here is a fiddle with working example: http://jsfiddle.net/prEGf/
Everyone has great answers, but I just needed an answer as one variable. I didn't need an event listener, I just wanted to get the scrolled percentage. This is what I got:
const scrolledPercentage =
window.scrollY / (document.documentElement.scrollHeight - document.documentElement.clientHeight)
document.addEventListener("scroll", function() {
const height = window.scrollY / (document.documentElement.scrollHeight - document.documentElement.clientHeight)
document.getElementById("height").innerHTML = `Height: ${height}`
})
.container {
position: relative;
height: 200vh;
}
.sticky-div {
position: sticky;
top: 0;
}
<!DOCType>
<html>
<head>
</head>
<body>
<div id="container" class="container">
<div id="height" class="sticky-div">
Height: 0
</div>
</div>
</body>
First attach an event listener to some document you want to keep track
yourDocument.addEventListener("scroll", documentEventListener, false);
Then:
function documentEventListener(){
var currentDocument = this;
var docsWindow = $(currentDocument.defaultView); // This is the window holding the document
var docsWindowHeight = docsWindow.height(); // The viewport of the wrapper window
var scrollTop = $(currentDocument).scrollTop(); // How much we scrolled already, in the viewport
var docHeight = $(currentDocument).height(); // This is the full document height.
var howMuchMoreWeCanScrollDown = docHeight - (docsWindowHeight + scrollTop);
var percentViewed = 100.0 * (1 - howMuchMoreWeCanScrollDown / docHeight);
console.log("More to scroll: "+howMuchMoreWeCanScrollDown+"pixels. Percent Viewed: "+percentViewed+"%");
}
My two cents, the accepted answer in a more "modern" way. Works back to IE9 using #babel/preset-env.
// utilities.js
/**
* #param {Function} onRatioChange The callback when the scroll ratio changes
*/
export const monitorScroll = onRatioChange => {
const html = document.documentElement;
const body = document.body;
window.addEventListener('scroll', () => {
onRatioChange(
(html.scrollTop || body.scrollTop)
/
((html.scrollHeight || body.scrollHeight) - html.clientHeight)
);
});
};
Usage:
// app.js
import { monitorScroll } from './utilities';
monitorScroll(ratio => {
console.log(`${(ratio * 100).toFixed(2)}% of the page`);
});
I reviewed all of these up there but they use more complex approaches to solve. I found this through a mathematical formula; brief.
The formula goes Value/Total * 100. Say Total is 200 u wanna know the percentage of 100 out of 200, you do it 100/200 * 100% = 50% (the value)
pageYOffset = The vertical scroll count without including borders. When you scroll down to bottom you get the maximum count.
offsetHeight = The total height of the page including borders!
clientHeight = The height in pixels without borders but not to the end of content!
When u scroll to bottom u get pageyoffset of 1000 for example, whereas offsetHeight of 1200 and clientHeight of 200. 1200 - 200(clientheight) now u get paggeYOffset value in offsetHeight and so scrollPosition300(300 of 1000)/1000 * 100 = 30%.
`pageOffset = window.pageYOffset;
pageHeight = document.documentElement.offsetHeight;
clientHeight = document.documentElement.clientHeight;
percentage = pageOffset / (pageHeight - clientHeight) * 100 + "%";
console.log(percentage)`
The reason why we must do offsetHeight - clientHeight it is because client heights shows all the available content in px without borders, and offsetheight shows the available content including borders, whereas pageYOffset counts the scrolls made; The scrollbar is quite long to count the whole windows it counts the scrolls itself until reaches the end, the available space in scrollbar is in px pageYOffset, so to reach that number you substract offsetHeight - clientHeight to bring to the lower value of pageYOffset.
i'll update when i get on pc, please leave a comment to make it clear so i don't forget! Thanks :)
Using jQuery
$(window).scrollTop();
will get you the scroll position, you can then work out from there what the percentage is based on the window height.
There is also a standard DOM property scrollTop that you can use like document.body.scrollTop however I'm not sure how this behaves cross-browser, I would assume if there are inconsistencies then the jQuery method accounts for these.
var maxScrollTop = messages.get(0).scrollHeight - messages.height();
var scroll = messages.scrollTop() / maxScrollTop; // [0..1]
I found a way to correct a previous answer, so it works in all cases. Tested on Chrome, Firefox and Safari.
(((document.documentElement.scrollTop + document.body.scrollTop) / (document.documentElement.scrollHeight - document.documentElement.clientHeight) || 0) * 100)

Interpolating element as it scrolls through window

I'm trying to interpolate a percentage as an element moves through the window as you scroll.
Basically, when the top of the element meets the bottom of the window, that returns 0%. When the bottom of the element meets the top of the window, that returns 100%.
So far I can interpolate using the middle of the element, but I can't figure out how to get it to start at the top and bottom instead of the middle.
Heres a Demo
$(document).ready(()=>{
//Element Vars - Test for Element 3
const $interpolateTarget = $('#element3');
const elementH = $interpolateTarget.height();
const elementY = $interpolateTarget.offset().top;
//Window Vars
const windowH = $(window).height()
let scrollY;
let interpolation;
let middlePoint;
$(window).scroll((event)=>{
scrollY = $(window).scrollTop()
pctOfWindow = elementH / windowH
//Calculate middle of element and compare to middle of window
middleY = elementH / 2 + elementY - scrollY
windowMiddleY = windowH / 2
interpolation = middleY / windowMiddleY / 2
//Convert to percentage and reverse
interpolation = (interpolation * 100 - 100 ) * -1
updateInfo(scrollY, interpolation);
})
})
Any Help would be greatly appreciated, thanks!
I think you need to consider the document height instead of the window height. The following may help you.
updateInfo(scrollY, 100 * $(document).scrollTop() / ($(document).height() - $(window).height()));
$(document).scrollTop() : how much is scrolled in the entire document
$(document).height() : actual document height
$(document).height() - $(window).height() : scrollable document height
Seems I figured it out, changed elementH / 2 + elementY - scrollY to elementH + elementY - scrollY

Make JavaScript image movement while scrolling smoother

I have a background image that gets moved while scrolling. When the page is scrolled to top, the top edge of the background image touches to top edge of the window and when scrolled down 100%, the bottom image edge touches the bottom window edge.
This is my working code:
document.addEventListener('scroll', function() {
var backgroundImage = document.querySelector('#background img');
var scrollHeight = document.body.scrollHeight;
var scrollTop = document.body.scrollTop;
var innerHeight = window.innerHeight;
backgroundImage.style.top = (((backgroundImage.scrollHeight - innerHeight) / 100) * ((scrollTop / (innerHeight - scrollHeight)) * 100)) + 'px';
});
The result is what I'm expecting, but the scrolling gets extremely laggy. Is there a possibility to make this animation smoother?
EDIT
I added requestAnimationFrame like so:
document.addEventListener('scroll', function() { requestAnimationFrame(process); });
function process() {
// calculation code goes here
}
This makes the scrolling much smoother and the image movement is kinda perfect. But still the DOM isn't scrolling really smooth. Better, though not good. Any ideas for further improvements?
Using CSS transforms might help... I use a 3d transform here, hopefully giving you even more performance thanks to hardware acceleration.
The code would look something like this:
var updateImgPosition = function () {
var backgroundImage = document.querySelector('#background img');
var scrollHeight = document.body.scrollHeight;
var scrollTop = document.body.scrollTop;
var innerHeight = window.innerHeight;
backgroundImage.style.webkitTransform = "translate3d(0,"+ (((backgroundImage.scrollHeight - innerHeight) / 100) * ((scrollTop / (innerHeight - scrollHeight)) * 100)) + "px,0)"
};
document.addEventListener('scroll', updateImgPosition)
UPDATED DEMO

Making JavaScript Custom ScrollBar

I said “JavaScript”. I'm trying to make my own JavaScript custom scrollbar. It's almost successful. The problem is that I can't get an accurate multiplier for the scrolling speed. This is my code:
var elem = document.getElementById('scroll-area'),
track = elem.children[1],
thumb = track.children[0],
height = parseInt(elem.offsetHeight, 10),
cntHeight = parseInt(elem.children[0].offsetHeight, 10),
trcHeight = parseInt(track.offsetHeight, 10),
distance = cntHeight - height,
mean = 50, // For multiplier (go faster or slower)
current = 0;
elem.children[0].style.top = current + "px"; // Set default `top` value as `0` for initiation
thumb.style.height = Math.round(trcHeight * height / cntHeight) + 'px'; // Set the scrollbar thumb hight
var doScroll = function (e) {
// cross-browser wheel delta
e = window.event || e;
var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
// (1 = scroll-up, -1 = scroll-down)
// Always check the scroll distance, make sure that the scroll distance value will not
// increased more than the content height and/or less than zero
if ((delta == -1 && current * mean >= -distance) || (delta == 1 && current * mean < 0)) {
current = current + delta;
}
// Move element up or down by updating the `top` value
elem.children[0].style.top = (current * mean) + 'px';
thumb.style.top = 0 - Math.round(trcHeight * (current * mean) / cntHeight) + 'px';
e.preventDefault();
};
if (elem.addEventListener) {
elem.addEventListener("mousewheel", doScroll, false);
elem.addEventListener("DOMMouseScroll", doScroll, false);
} else {
elem.attachEvent("onmousewheel", doScroll);
}
And the markup:
<div id="scroll-area">
<div><!-- CONTENT --></div>
<span class="scrollbar-track"><span class="scrollbar-thumb"></span></span>
</div>
My problem is on mean = 50. When you scroll the container until the bottom of content, the red line that I made in the demo page should stop right at the bottom of the container, not higher than that.
Anyone have an idea for the accurate result?
PS: I also want to add a function that will enable user to scroll the content by dragging the scrollbar thumb. But I think I want to focus on this issue first. Thanks for your help.
DEMO: http://jsfiddle.net/tovic/2B8Ye/
You could have done this much much easier.
Instead of calculating the top property for the container you can set its scrollTop property, and you guess what - you don't have to check if the content moves upper than 0 or lower than height because scrollTop property can not be set to a value smaller than 0 or greater than container's height!
Here's your modified fiddle
Notice that I had to wrap everything with additional <div id="everything">...</div> so the scrollbar won't be scrolled together with the #scroll-area div.
Also I assume using clientHeight instead of offsetHeight for .scroll-content div to include padding in the cntHeight variable.
More info on the scrollTop property you can find in this article.

Live Detect Browser Size - jQuery / JavaScript

Is there a jQuery plugin or a way using straight JavaScript to detect browser size.
I'd prefer it is the results were 'live', so if the width or height changes, so would the results.
JavaScript
function jsUpdateSize(){
// Get the dimensions of the viewport
var width = window.innerWidth ||
document.documentElement.clientWidth ||
document.body.clientWidth;
var height = window.innerHeight ||
document.documentElement.clientHeight ||
document.body.clientHeight;
document.getElementById('jsWidth').innerHTML = width; // Display the width
document.getElementById('jsHeight').innerHTML = height;// Display the height
};
window.onload = jsUpdateSize; // When the page first loads
window.onresize = jsUpdateSize; // When the browser changes size
jQuery
function jqUpdateSize(){
// Get the dimensions of the viewport
var width = $(window).width();
var height = $(window).height();
$('#jqWidth').html(width); // Display the width
$('#jqHeight').html(height); // Display the height
};
$(document).ready(jqUpdateSize); // When the page first loads
$(window).resize(jqUpdateSize); // When the browser changes size
jsfiddle demo
Edit: Updated the JavaScript code to support IE8 and earlier.
you can use
function onresize (){
var h = $(window).height(), w= $(window).width();
$('#resultboxid').html('height= ' + h + ' width: ' w);
}
$(window).resize(onresize );
onresize ();// first time;
html:
<span id=resultboxid></span>
This should return the visible area:
document.body.offsetWidth
document.body.offsetHeight
I guess this is always equal to the browser size?
use width and height variable anywhere you want... when ever browser size change it will change variable value too..
$(window).resize(function() {
width = $(this).width());
height = $(this).height());
});
Do you mean something like this window.innerHeight; window.innerWidth $(window).height(); $(window).width()
You can try adding even listener on re-size like
window.addEventListener('resize',CheckBrowserSize,false);
function CheckBrowserSize()
{
var ResX= document.body.offsetHeight;
var ResY= document.body.offsetWidth;
}

Categories

Resources