0

I coded this:

// Click Function

$('body').on('click', 'a', function() {
  $('a.active').removeClass('active');
  $(this).addClass('active');
});


// Scroll Function

const sectionIsInViewport = document.querySelector('section');

observer = new IntersectionObserver((callback) => {
  console.log('This section is now in the viewport.');
});

observer.observe(sectionIsInViewport);
* {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
  font-size: 30px;
  text-decoration: none;
  color: inherit;
}

body {
  display: flex;
  cursor: default;
}

#left,
#right {
  width: 50%;
  height: 100vh;
  overflow-y: scroll;
  scroll-behavior: smooth;
}

#left {
  background-color: rgb(220, 220, 220);
}

#right {
  background-color: rgb(200, 200, 200);
}

.media {
  padding: 10px;
  padding-bottom: 0;
}

.media:nth-last-child(1) {
  margin-bottom: 10px;
}

img {
  display: block;
  width: 100%;
}

.link {
  cursor: pointer;
}

.active {
  background-color: black;
  color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="left">
  <a class="link active" href="#landscapes">Landscapes</a>
  <a class="link" href="#cats">Cats</a>
  <a class="link" href="#food">Food</a>
</div>

<div id="right">

  <section id="landscapes">
    <article class="media">
      <img src="https://upload.wikimedia.org/wikipedia/commons/8/8d/Freudenberg_sg_Switzerland.jpg">
    </article>
    <article class="media">
      <img src="https://i.pinimg.com/originals/ae/99/54/ae995473d0b73efd9b32b5cd029d9396.jpg">
    </article>
    <div class="media">
      <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/ac/Rural_landscape.JPG/1200px-Rural_landscape.JPG">
    </div>
    <article class="media">
      <img src="https://upload.wikimedia.org/wikipedia/commons/8/8d/Freudenberg_sg_Switzerland.jpg">
    </article>
  </section>

  <section id="cats">
    <article class="media">
      <img src="https://img.webmd.com/dtmcms/live/webmd/consumer_assets/site_images/article_thumbnails/other/cat_relaxing_on_patio_other/1800x1200_cat_relaxing_on_patio_other.jpg">
    </article>
  </section>

  <section id="food">
    <article class="media">
      <img src="https://post.healthline.com/wp-content/uploads/2020/09/healthy-eating-ingredients-1200x628-facebook-1200x628.jpg">
    </article>
    <article class="media">
      <img src="https://theculturetrip.com/wp-content/uploads/2017/07/3566479001_c9707436f9_b.jpg">
    </article>
  </section>

</div>

In general, it works. But: If you scroll in the right area, the .active link should update automatically. So if you scroll for example to the section #food, the corresponding link should be .active.

I tried to work with Intersection Observer, but I am not sure if it's the best tool for it. And would it make sense to work with React? If yes, why?

Can somebody help me please? Would be soooooo thankful. <3<3<3

Anna_B
  • 820
  • 1
  • 4
  • 23

1 Answers1

0

I think that IntersectionObserver is perfect for what you want. How does this suit your needs?

// Click Function

$('body').on('click', 'a', function() {
  $('a.active').removeClass('active');
  $(this).addClass('active');
});


// Scroll Function

const mediaInViewport = document.querySelectorAll('.media');

observer = new IntersectionObserver((entries, observer) => {
  console.log('Next Media in Viewport');
  entries.forEach((entry) => {
    if (entry.target && entry.isIntersecting) {
      entry.target.classList.add('active');
      
      const closestParent = entry.target.closest('section');
      if (closestParent) {
        const selector = closestParent.id;
        const links = document.querySelectorAll('.link');
        for (const link of links) {
          const split = link.href.split('#');
          if (split.length >= 2) {
            const local = split[1];
            if (local === selector) {
              link.classList.add('active');
            }
          }
        }
      }
    } 
  });
}, {threshold: 0.7 } );

window.addEventListener('DOMContentLoaded', () => {
  setTimeout( // Wait for images to fully load
      () => {
      mediaInViewport.forEach((item) => {
        observer.observe(item);
      });
    }
  , 1000);
});
* {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
  font-size: 30px;
  text-decoration: none;
  color: inherit;
}

body {
  display: flex;
  cursor: default;
}

#left,
#right {
  width: 50%;
  height: 100vh;
  overflow-y: scroll;
  scroll-behavior: smooth;
}

#left {
  background-color: rgb(220, 220, 220);
}

#right {
  background-color: rgb(200, 200, 200);
}

.media {
  padding: 10px;
  padding-bottom: 0;
}

.media:nth-last-child(1) {
  margin-bottom: 10px;
}

img {
  display: block;
  width: 100%;
}

.link {
  cursor: pointer;
}

.active {
  background-color: black;
  color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="left">
  <a class="link active" href="#landscape">Landscapes</a>
  <a class="link" href="#cats">Cats</a>
  <a class="link" href="#food">Food</a>
</div>

<div id="right">

  <section id="landscape">
    <article class="media">
      <img src="https://upload.wikimedia.org/wikipedia/commons/8/8d/Freudenberg_sg_Switzerland.jpg">
    </article>
    <article class="media">
      <img src="https://i.pinimg.com/originals/ae/99/54/ae995473d0b73efd9b32b5cd029d9396.jpg">
    </article>
    <div class="media">
      <img src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/ac/Rural_landscape.JPG/1200px-Rural_landscape.JPG">
    </div>
    <article class="media">
      <img src="https://upload.wikimedia.org/wikipedia/commons/8/8d/Freudenberg_sg_Switzerland.jpg">
    </article>
  </section>

  <section id="cats">
    <article class="media">
      <img src="https://img.webmd.com/dtmcms/live/webmd/consumer_assets/site_images/article_thumbnails/other/cat_relaxing_on_patio_other/1800x1200_cat_relaxing_on_patio_other.jpg">
    </article>
  </section>

  <section id="food">
    <article class="media food">
      <img src="https://post.healthline.com/wp-content/uploads/2020/09/healthy-eating-ingredients-1200x628-facebook-1200x628.jpg">
    </article>
    <article class="media food">
      <img src="https://theculturetrip.com/wp-content/uploads/2017/07/3566479001_c9707436f9_b.jpg">
    </article>
  </section>
Robbie Cook
  • 164
  • 1
  • 6
  • Hello, thank you for your answer! Unfortunately, the links on the left side do not update. They should get the ".active" class, if the corresponding area is in the viewport. – Anna_B Nov 09 '20 at 01:10
  • Hi. I should have added this now. However, it should be noted that this is probably stretching the limits of native Javascript. Frameworks like React or svelte would handle dynamic behaviour like this better. – Robbie Cook Nov 09 '20 at 01:27
  • Thanks for the update! Maybe it was not clear: Always only one link should have the class ".active". Is it easy to do that? – Anna_B Nov 09 '20 at 02:20
  • I could do that. Maybe it is not clear: this code is an *example* of how to do this -- not a complete program to achieve your specific needs. I expect you to be able to modify this yourself instead of expecting me to do it for you. – Robbie Cook Nov 09 '20 at 21:57