I've managed to implement a scrolling progress bar that works fine (copied the one from w3schools). My issue is that before the user starts scrolling, I want the progress bar to not start from 0 but from 10% (width). It looks fine initially, but after you start scrolling, it resets to 0, and when you scroll back up it scrolls back to a value of 0.
Here's a fiddle to show what I mean: https://jsfiddle.net/z3s4hqvj/
Also, here's my code:
window.onscroll = function() {myFunction()};
function myFunction() {
var winScroll = document.body.scrollTop || document.documentElement.scrollTop;
var height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
var scrolled = (winScroll / height) * 96;
document.getElementById("myBar").style.width = scrolled + "%";
};
Try this little tweak.
window.onscroll = function() {myFunction()};
function myFunction() {
var winScroll = document.body.scrollTop || document.documentElement.scrollTop;
var height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
var scrolled = (winScroll / height) * 96;
if(scrolled>10){
document.getElementById("myBar").style.width = scrolled + "%";
}
};
Related
I have a progress bar on my body. When I click on a button a div appear, we can scoll on this div and I would liked to have also a progress bar for this one. I took the Jquery code of the progress bar
MY JSFIDDLE
window.onscroll = function() {
myFunction()
};
function myFunction() {
var winScroll = document.body.scrollTop || document.documentElement.scrollTop;
var height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
var scrolled = (winScroll / height) * 100;
document.getElementById("myBar").style.height = scrolled + "%";
}
$('button').click(function() {
if ($(this).hasClass("clicked")) {
$(this).text("Open ↓");
} else {
$(this).text("Close ↑");
}
$('.blue-container').toggleClass('In');
$('body').toggleClass('hideOverflow');
$(this).toggleClass("clicked");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="progress-container">
<div class="progress-bar" id="myBar"></div>
</div>
<button> Open ↓</button>
<div class='blue-container'>
<div class='blue'>
<p>Hello ! Scroll down. I would like to have a progress bar for this div, like the body.</p>
</div>
</div>
You need to create same progress setter function like you've set on window, except this one should use blue container scrollable element for scroll position measurement.
Remember that after your blue box is closed, you don't need setting progress from this box anymore, so you should unbind setter function ($scroller.off('scroll', progressSetter)). It will be bound again after next opening of blue box.
window.onscroll = function() {myFunction()};
function myFunction() {
var winScroll = document.body.scrollTop || document.documentElement.scrollTop;
var height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
var scrolled = (winScroll / height) * 100;
document.getElementById("myBar").style.height = scrolled + "%";
}
$('button').on('click', function() {
var $container = $('.blue-container'),
$scroller = $container.find('.blue'),
$btn = $(this),
$bar = $('#myBar'),
progressSetter = function () {
var height = $scroller[0].scrollHeight - $scroller.outerHeight();
$bar.css({
height: $scroller.scrollTop() / height * 100 + '%'
});
};
if ($btn.hasClass("clicked")) {
$btn.text("Open ↓");
$scroller.off('scroll', progressSetter)
} else {
$btn.text("Close ↑");
$scroller.on('scroll', progressSetter)
}
$container.toggleClass('In');
$('body').toggleClass('hideOverflow');
$btn.toggleClass("clicked");
});
https://jsfiddle.net/uo34ru7d/76/
As I can see, you used example code from tutorial. Try to figure out how this scrolling bound functions work (and event binding itself) and you will be able to create one function for both window and your blue container, make that your homework ;)
I have a half visible (using max-height) div that contains some text, I want to add the length of page scrolled to the max-height. I used
var topScroll = window.pageYOffset || document.documentElement.scrollTop;
But its returning 60 instead of 60px or 50 instead of 50 px that's making my max height 60xxx px 50xxx px.
My JavaScript code:
var topScroll = window.pageYOffset || document.documentElement.scrollTop;
topScroll = parseInt(topScroll);
$('#' + topScroll ).append("px");
console.log(""+topScroll);
var elem = document.getElementById("content");
var articleHeight = window.getComputedStyle(elem, null).getPropertyValue("max-height");
$(window).scroll(function (){
var x = topScroll + articleHeight ;
$('.article-on').css('max-height',x);
console.log(""+x);
});
I'm trying to get margin-top and margin-bottom to center my <div>. This JavaScript, which I wrote, works. However, if the site is cached once, CTRL+F5 refresh causes the script to receive a wrong clientHeight. Refreshing second time, retrieves the correct clientHeight.
I've tried using window.load and this works. However, it is so slow that the <div> loads and after 2 seconds, it shifts to the middle.
<script type="text/javascript">
var height = $(window).height();
var clientHeight = document.getElementById('account-wall').clientHeight;
var calc_height = (height - clientHeight) / 2;
document.getElementById("account-wall").style.marginTop = calc_height + 'px';
document.getElementById("account-wall").style.marginBottom = calc_height + 'px';
</script>
<script type="text/javascript">
$(window).load(function() {
var height = $(window).height();
console.log(height);
var clientHeight = $('.account-wall').height();
console.log(clientHeight);
var calc_height = (height - clientHeight) / 2;
document.getElementById("account-wall").style.marginTop = calc_height + 'px';
document.getElementById("account-wall").style.marginBottom = calc_height + 'px';
});
</script>
Use a resize event since you need it to be centered even if the window.height changes. To make sure it is centered from the beggining use .resize() to trigger the event.
$(window).on('resize', function(event){
var height = $(window).height();
console.log(height);
var clientHeight = $('.account-wall').height();
console.log(clientHeight);
var calc_height = (height - clientHeight)/2;
document.getElementById("account-wall").style.marginTop = calc_height+'px';
document.getElementById("account-wall").style.marginBottom = calc_height+'px';
}).resize();
You can scroll to an element using a url with a hashtag and the elements ID:
window.location.href = "#ID"
This will scrol so that the top of the element is at the top of the browser. How would I scroll to an element so that it's vertically centered?
you can scroll up right after the navigation happens:
addEventListener("hashchange", function(){
setTimeout(function(){
document[
document.documentElement.scrollTop ?
"documentElement":
"body"
].scrollTop-= (innerHeight/2.1);
}, 1);
}, false);
this will cause the focused element to appear half-way up the screen, vertically centered.
the 2.1 causes it to scroll just under half the screen, since there will be some room at the top already. you can adjust the ".1" to match your desired effect (baseline, middle, etc).
obligatory fiddle link: http://jsfiddle.net/ckhafLzq/2/
This is what I have achieved:
function centerScroll(element) {
if (!(element instanceof Element)) {
throw new TypeError("Element expected");
}
var bodyRect = document.body.getBoundingClientRect();
var elementRect = element.getBoundingClientRect();
var left = elementRect.left - bodyRect.left;
var top = elementRect.top - bodyRect.top;
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
var elementWidth = element.offsetWidth;
var elementHeight = element.offsetHeight;
var x = left - Math.max(0, (windowWidth - elementWidth) / 2);
var y = top - Math.max(0, (windowHeight - elementHeight) / 2);
window.scrollTo(x, y);
return [x, y];
}
No, there's no built-in way, you'd have to write that yourself:
function center_element_vertically(elt) {
var rect = elt.getBoundingClientRect();
window.scrollTo(0, rect.top + window.pageYOffset -
(window.innerHeight - rect.height)/2);
}
Alternatives without writing your own code: you could scroll so that the element was at the bottom by passing false to scrollIntoView, or scroll only if the element is not already visible by calling scrollIntoViewIfNeeded, available only in Chrome AFAIK.
I have a simple JS module that calculates the percentage of the current scroll position.
var scrollPercent = (function() {
"use strict";
var module = {
config: {
},
init: function() {
return this.percent();
},
percent: function() {
var windowHeight = this.getWindowHeight();
var docHeight = this.getDocHeight();
var scrollPosition = this.getScrollPosition();
var result = ((scrollPosition + windowHeight) / docHeight) * 100;
return Math.floor(result);
},
getScrollPosition: function() {
return (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
},
getWindowHeight: function() {
return window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight || 0;
},
getDocHeight: function() {
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
);
}
};
return module;
});
var scroller = new scrollPercent;
window.onscroll = function(event) {
console.log(scroller.init());
};
This is working as expected, if the window height is 500px and the doc height is 1000px, then the initial scroll position is 50%. If you were to scroll to the bottom it would be 100%.
What I would like to do is have my initial value be 1% and when scrolling to the bottom it return 100% (like it is now).
The problem is that my initial value of 50% is based off the window height (half the page is showing). For some reason I can't figure out the necessary math to have it start at 1% and go to 100% when reaching the bottom.
So, after a bunch of fiddling I came across your solution...
You have to take into consideration the current position of the document and the scroll bar. So if you want to get it between 0-100 you have to exclude the height of the window in your docHeight.
In your function I created a variable called initDiff and basically used this to calculate your value between 0-100.
This is how I set up your init function. Notice docHeight. Also, notice initDiff which calculates a difference that needs to be subtracted from your result. I don't use any scroll positioning because the initDiff is calculated for when the scroll-bar positioning is 0
init: function() {
var windowHeight = this.getWindowHeight();
var docHeight = this.getDocHeight() - windowHeight;
initDiff = (windowHeight / docHeight) * 100;
console.log('Difference : ' + initDiff);
return this.percent();
}
Below is your percent function that I changed up a bit. Again, docHeight takes into consideration the current height of the window. Your result, once you take out the windowHeight from docHeight your number generally ranged from something like 50-150, it all depends on the window height. What I do is "keep" that number, but I calculate that difference. So for that range, your initDiff will be 50. If the range was 56-156 your initDiff will be 56
percent: function() {
var windowHeight = this.getWindowHeight();
var docHeight = this.getDocHeight() - windowHeight;
var scrollPosition = this.getScrollPosition();
var result = ((scrollPosition + windowHeight) / docHeight) * 100 - initDiff;
console.log('Window Height : ' + windowHeight);
console.log('Document Height : ' + docHeight);
console.log('Scroll Position : ' + scrollPosition);
return Math.floor(result);
}
Here is the fiddle : http://jsfiddle.net/XNVNj/2/
Just look at your console. Should explain it all.