Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update location hash when user scrolls to section

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
like image 409
Stretch0 Avatar asked Apr 09 '17 04:04

Stretch0


2 Answers

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>
like image 163
Kuba Avatar answered Oct 23 '22 15:10

Kuba


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.

like image 25
Saharsh Avatar answered Oct 23 '22 16:10

Saharsh