2

THE AIM

After refreshing the browser, I would like that the user stays in the menu/content they were before refreshing.

THE PROBLEM

After refreshing the browser, the content of the particular menu in which the user was before refreshing is shown as active (i.e. it is shown on the screen). However, the menu icon of that particular content is NOT shown as active (i.e. it does not show a black colour).

I am struggling in selecting the anchor element (where the icon is found) of the current href (the one the user was in before refreshing which is the same after refreshing).

THE ATTEMPT

$(document).ready(function() {

        $('a[class^=menu]').click(function() {
          $('a[class^=menu]').removeClass('active');
          $('div[class^=content]').removeClass('active');

          if($(this).hasClass('menu-1')) {
            $('.menu-1').addClass('active');
            $('.content-1').addClass('active');
          }

          if($(this).hasClass('menu-2')) {
            $('.menu-2').addClass('active');
            $('.content-2').addClass('active');
          }

          if($(this).hasClass('menu-3')) {
            $('.menu-3').addClass('active');
            $('.content-3').addClass('active');
          }
        });

        if (window.location.hash.substr(1) != '') {
          $('a[class^=menu],div[class^=content]').removeClass('active');

          // making the content active
          $('#' + window.location.hash.substr(1)).addClass('active');

          // making the menu active
          $('a[href="' + window.location.hash.substr(1) + '"]').addClass("active");

        }

      });
    .container {
      margin: 0 auto;
      background-color: #eee;
      border: 1px solid lightgrey;
      width: 20vw;
      height: 90vh;
      font-family: sans-serif;
      position: relative;
    }

    header {
      background-color: lightgreen;
      padding: 5px;
      text-align: center;
      text-transform: uppercase;
    }

    .bottom-navbar {
      position: absolute;
      bottom: 0;
      width: 100%;
      padding: 6px 0;
      overflow: hidden;
      background-color: lightgreen;
      border-top: 1px solid var(--color-grey-dark-3);
      z-index: 50;
      display: flex;
      justify-content: space-between;
    }

    .bottom-navbar>a {
      display: block;
      color: green;
      text-align: center;
      text-decoration: none;
      font-size: 20px;
      padding: 0 10px;
    }

    .bottom-navbar>a.active {
      color: black;
    }

    .menu-1.active,
    .menu-2.active,
    .menu-3.active {
      color: black;
    }

    .content-1,
    .content-2,
    .content-3 {
      display: none;
    }

    .content-1.active,
    .content-2.active,
    .content-3.active {
      display: block;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translateX(-50%) translateY(-50%);
    }
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css">
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

 
 <div class="container">
    <header>My header</header>
    <div class="main-content">
      <div class="content-1 active" id="firstPage">House content</div>
      <div class="content-2" id="secondPage">Map content</div>
      <div class="content-3" id="thirdPage">Explore content</div>
      <div class="bottom-navbar">
        <a href="mywebsite#firstPage" class="menu-1 active"><i class="fa fa-home"></i></a>
        <a href="mywebsite#secondPage" class="menu-2"><i class="fa fa-map"></i></a>
        <a href="mywebsite#thirdPage" class="menu-3"><i class="fa fa-search"></i></a>
      </div>
    </div>
 </div>

Thanks for your help and suggestions.

Joehat
  • 979
  • 1
  • 9
  • 36
  • Why do you have three classes `menu-x` and `content-x` if they all have the same css properties? It would be easier to select them it they were just called `menu` and `content`. If you want to identify them specifically in DOM, use `id` or `name`. – Maciej B. Nowak Dec 04 '19 at 12:17
  • set the value in localstorage or session store and use that value on reload if the data is not sensitive – user6250770 Dec 04 '19 at 12:18
  • @user6250770 also, would you mind clarifying what you mean by "if the data is not sensitive"? – Joehat Dec 04 '19 at 12:43
  • 1
    https://jsfiddle.net/Guruprasad_Rao/9kedou2q/1/ follow this to know more about settinga nd getting data from local storage – user6250770 Dec 04 '19 at 12:52
  • 1
    sensitive data means, if it's not effect your business. local storage is like any one can see the data in console of any browser. – user6250770 Dec 04 '19 at 12:53

2 Answers2

2

the problem that you had was that your were looking for the wrong href.

you were trying to find a[href="secondPage"] but it should be a[href="mywebsite#secondPage"]

also I changed the way you were selecting the classes and adding them to be active. this way is more dynamic.

note: in the JS file, there is a variable called hash, now it points to be #secondPage in order to fake that we are on the second page, you can change the value, re run it and it will pick a new active item. you just need to replace hash to be window.location.hash, also I took it out to a variable so you don't call it every time.

// just replace this with "window.location.hash"
const hash = "#secondPage";
$(document).ready(function() {

  $('a[class^=menu]').click(function() {
    // we remove the active classes.
    $('a[class^=menu]').removeClass('active');
    $('div[class^=content]').removeClass('active');

    // we get the item that was clicked and select the item
    // in a dynamic way.
    const clickedClass = $(this).attr('class');
    const [identifier, number] = clickedClass.split('-')

    $(`.${clickedClass}`).addClass('active');
    $(`.content-${number}`).addClass('active');

  });


  const active = hash.substr(1);
  if (active != '') {
    $('a[class^=menu],div[class^=content]').removeClass('active');


    // making the content active
    $(`#${active}`).addClass('active');


    // making the menu active
    $(`a[href="mywebsite#${active}"]`).addClass("active")

  }

});
.container {
  margin: 0 auto;
  background-color: #eee;
  border: 1px solid lightgrey;
  width: 20vw;
  height: 90vh;
  font-family: sans-serif;
  position: relative;
}

header {
  background-color: lightgreen;
  padding: 5px;
  text-align: center;
  text-transform: uppercase;
}

.bottom-navbar {
  position: absolute;
  bottom: 0;
  width: 100%;
  padding: 6px 0;
  overflow: hidden;
  background-color: lightgreen;
  border-top: 1px solid var(--color-grey-dark-3);
  z-index: 50;
  display: flex;
  justify-content: space-between;
}

.bottom-navbar>a {
  display: block;
  color: green;
  text-align: center;
  text-decoration: none;
  font-size: 20px;
  padding: 0 10px;
}

.bottom-navbar>a.active {
  color: black;
}

.menu-1.active,
.menu-2.active,
.menu-3.active {
  color: black;
}

.content-1,
.content-2,
.content-3 {
  display: none;
}

.content-1.active,
.content-2.active,
.content-3.active {
  display: block;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translateX(-50%) translateY(-50%);
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>


<div class="container">
  <header>My header</header>
  <div class="main-content">
    <div class="content-1 active" id="firstPage">House content</div>
    <div class="content-2" id="secondPage">Map content</div>
    <div class="content-3" id="thirdPage">Explore content</div>
    <div class="bottom-navbar">
      <a href="mywebsite#firstPage" class="menu-1 active"><i class="fa fa-home"></i></a>
      <a href="mywebsite#secondPage" class="menu-2"><i class="fa fa-map"></i></a>
      <a href="mywebsite#thirdPage" class="menu-3"><i class="fa fa-search"></i></a>
    </div>
  </div>
</div>
Prince Hernandez
  • 3,623
  • 1
  • 10
  • 19
  • thanks. However, now neither the content nor the menu is shown as active when first opening the browser or when refreshing it... – Joehat Dec 04 '19 at 13:03
  • 1
    @Joehat I have just copied the whole code to a new index.html to test it locally and it works perfectly. `/index.html#firstPage` selects the first content and first icon `/index.html#secondPage` selects the second content and second icon and actually the `/index.html#thirdPage` selects the third content and third icon. did you change the `hash` variable that I put at the top of the JS File? – Prince Hernandez Dec 04 '19 at 13:16
  • I actually typed "window.location.hash" instead of window.location.hash, that's why it wasn't working. Thanks! – Joehat Dec 04 '19 at 13:21
  • would you mind clarifying your use of ` instead of ' or "? Is the first time I see it... – Joehat Dec 04 '19 at 13:31
  • 1
    basically, with ` you can add a varible inside the string, for example: var myName = 'foo' console.log(`my name is: ${foo}`) which is the same as: console.log('my name is:' + foo) always the variables are inside ${ } .... and I use it because for me it makes everything easier to read, compare your: $('a[href="' + window.location.hash.substr(1) + '"]') to mine: $(`a[href="mywebsite#${active}"]`) see the difference? less code, less errors haha. – Prince Hernandez Dec 04 '19 at 14:03
1

This sounds like you want to add a class to the navigation if its the same as the current page url?

If you want to do this client-side something like this will work. This could also be handled by the server (php/c#)

$(function(){
    var current = location.pathname;
    $('#nav li a').each(function(){
        var $this = $(this);
        // if the current path is like this link, make it active
        if($this.attr('href').indexOf(current) !== -1){
            $this.addClass('active');
        }
    })
})

Similar thread/issue - anwser from here from Rob M Add Active Navigation Class Based on URL

webbist
  • 456
  • 4
  • 19
  • this made all of the icons active after refreshing instead of just the one which was active before refreshing... any suggestion on how to improve it to get what I am aiming? – Joehat Dec 04 '19 at 12:38
  • Could you let me know the href of the links? Are they all the same url but different hashes, or query strings? – webbist Dec 04 '19 at 14:34
  • they have the same URL but different hashes. With your answer, the links did work if I remember correctly, i.e. after refreshing the browser, the link was related to the menu/content before the browser was refreshed. @PrinceHernandez answer solved my problem. However, it wouldn't hurt knowing another approach. I would appreciate it if you could help me understand why your suggestion hasn't worked. – Joehat Dec 04 '19 at 18:44
  • My suggestion assumed different urls, it was matching the href to the location.pathname – webbist Dec 05 '19 at 09:38