I want to update the window.location.hash value when the user get's to a certain point on the page.
e.g. if a user scrolls to a div with an ID = 'about', I want the url to update.
The same way as if you click a link that auto scrolls you to an anchor on a page, it updates the hash in the URL.
I envision doing this by detecting if an element is visible and if it is, then updating window.location.hash = elementsID
Open to other suggestions.
I am using React and trying to avoid JQuery so vanilla JS suggestions would be greatly appreciated. Thanks.
edit:
Thanks for the suggestions. Manage to put together a solution with vanilla JS and implement it in a react component. Code still needs cleaning up but you get the gist
class HomeView extends React.Component{
constructor () {
super();
this.state = {
hash: '#'
}
this.elements = {}
}
componentDidMount(){
this.scrollListener();
}
componentDidUpdate(prevProps){
if(this.props.location.hash !== prevProps.location.hash){
this.scrollToHash(this.props.location.hash)
}
}
scrollListener(){
window.addEventListener('scroll', (event) => {
if(window.pageYOffset > 0 && window.pageYOffset < this.elements.about.offsetTop - 200){
const hash = '#';
this.setState({hash: hash}, () => {
history.pushState('', '', hash);
this.updateHashState(hash);
})
} else if(window.pageYOffset > this.elements.about.offsetTop - 200 && window.pageYOffset < this.elements.skills.offsetTop - 200) {
const hash = '#about';
this.setState({hash: hash}, () => {
history.pushState('', '', hash);
this.updateHashState(hash);
})
} else if(window.pageYOffset > this.elements.skills.offsetTop - 200 && window.pageYOffset < this.elements.contact.offsetTop - 200) {
const hash = '#skills';
this.setState({hash: hash}, () => {
history.pushState('', '', hash);
this.updateHashState(hash);
})
}else if(window.pageYOffset > this.elements.skills.offsetTop - 200) {
const hash = '#contact';
this.setState({hash: hash}, () => {
history.pushState('', '', hash);
this.updateHashState(hash);
})
}
})
}
updateHashState(hash) {
switch(hash){
case '#about':
this.setState({
forward: '#skills',
back: '#'
})
break;
case '#skills':
this.setState({
forward: '#contact',
back: '#about'
})
break;
case '#contact':
this.setState({
forward: '',
back: '#skills'
})
break;
default:
this.setState({
forward: '#about',
back: ''
})
break;
}
}
render(){
return(
...
)
}
}
export default HomeView
Look at my proposition. jQuery code will catch all <section>
selectors after document loaded and set appropriate hash from data-hash
attribute while you scroll.
$(document).ready(function(){
var sections = {};
$(".section").each(function(){
var hash = $(this).data("hash"),
topOffset = $(this).offset().top;
sections[topOffset] = hash;
});
$(window).scroll(function(e){
var scrollTop = $(window).scrollTop();
setHash(scrollTop);
});
function setHash(st){
var hash = "";
for(section in sections){
if (section < st + ($(window).height()/2)) hash = sections[section];
}
console.log(`SETTING HASH: ${hash}`);
window.location.hash = hash;
}
});
section{
position: relative;
display: block;
width: 100%;
height: 800px;
background: #fff;
border-bottom: 1px solid #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="section" data-hash="about">
#about
</section>
<section class="section" data-hash="works">
#works
</section>
<section class="section" data-hash="contact">
#contact
</section>
Just as another idea, updating the hash by taking the scroll value is more robust. Can be done in jQuery using scrollTop()
.
$(window).scroll(
function(){
if($(this).scrollTop() > 100 && $(this).scrollTop() < 200){
window.location.hash = "your_hash_name";
}else{
window.location.hash = "";
}
}
);
This updates the location.hash
value once you scroll between (100, 200)
pixels.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With