0

I have 3 div sections on my page, header, content and and a footer and a each of them has a carousel. I need to check somehow which one of them is fully visible so that I can perform action accordingly. I should when one of them is fully visible enable going through carousel images in the section that is currently fully visible. I have tried with this script:

$(document).ready(function () {
  var coverImage = $('.magazine-hero'),
      carousel = $('.carousel'),
      carouselVisible = isElementInViewport(carousel),
      coverEventBinded = false;
      carouselEventBinded = false;

  if (carouselVisible && !carouselEventBinded ) {
    $(document).on('keyup', null, 'right', function(){ $('.next').click(); });
    $(document).on('keyup', null, 'left', function(){ $('.previous').click(); });
    carouselEventBinded = true;
  }

  window.onscroll = function() {
    coverVisible = isElementInViewport(coverImage);
    carouselVisible = isElementInViewport(carousel);

    if (coverVisible && !coverEventBinded ) {
      $(document).on('keyup', null, 'right', forward);
      $(document).on('keyup', null, 'left', back);
      coverEventBinded = true;
    }

    if (carouselVisible && !carouselEventBinded ) {
      $(document).on('keyup', null, 'right', function(){ $('.next').click(); });
      $(document).on('keyup', null, 'left', function(){ $('.previous').click(); });
      carouselEventBinded = true;
    }
  }
});

function isElementInViewport(el) {
  var rect = el[0].getBoundingClientRect();

  return rect.bottom > rect.height &&
        rect.top < (window.innerHeight || document.documentElement.clientHeight) &&
        rect.right > 0 &&
        rect.left < (window.innerWidth || document.documentElement.clientWidth);
}

But that doesn't work, because when I am scrolling down and the upper div is still visible I am able to navigate carousels of both sections. How can I fix that?

Update

I have updated my script, now I am trying to see if the cover is visible and then bind key events for navigating covers, and if it is not visible I am unbiding the events for covers navigation, and biding the events for carousels:

$(document).ready(function () {
  var coverImage = $('.magazine-hero'),
      headerCarousel = $('.header-carousel'),
      headerCarouselVisible = isElementInViewport(headerCarousel),
      coverEventBinded = false,
      carouselEventBinded = false;

  if (headerCarouselVisible && !carouselEventBinded ) {
    $(document).on('keyup', null, 'right', function(){ $('.next').click(); });
    $(document).on('keyup', null, 'left', function(){ $('.previous').click(); });
    carouselEventBinded = true;
  }

  window.onscroll = function() {
    coverVisible = isElementInViewport(coverImage);
    headerCarouselVisible = isElementInViewport(headerCarousel);

console.log('Cover visible ' + coverVisible);
console.log('Event binded ' + coverEventBinded);

    if (coverVisible && !coverEventBinded) {
      $(document).unbind('keyup', null, 'right', function(){ $('.next').click(); });
      $(document).unbind('keyup', null, 'left', function(){ $('.previous').click(); });
      $(document).on('keyup', null, 'right', forward);
      $(document).on('keyup', null, 'left', back);
      coverEventBinded = true;
      carouselEventBinded = false;
    }
    else {
      $(document).unbind('keyup', null, 'right', forward);
      $(document).unbind('keyup', null, 'left', back);
      $(document).on('keyup', null, 'right', function(){ $('.next').click(); });
      $(document).on('keyup', null, 'left', function(){ $('.previous').click(); });
      carouselEventBinded = true;
      coverEventBinded = false;
    }
  }
});


function isElementInViewport(el) {
  var rect = el[0].getBoundingClientRect();

console.log('Bottom ' + rect.bottom);
console.log('Height ' + rect.height);
console.log('Client height ' + document.documentElement.clientHeight);
console.log('Window height ' + window.innerHeight);

  return rect.bottom > 0 &&
        rect.top < (window.innerHeight || document.documentElement.clientHeight) &&
        rect.right > 0 &&
        rect.left < (window.innerWidth || document.documentElement.clientWidth);
}

The issue I have now, is that sometimes even when the bottom is a minus value or less than 0, I get true for coverVisible. And also sometimes the coverEventBinded is true when it shouldn't be true. I am not sure what is wrong with the script, that it behaves this way?

Leff
  • 1,968
  • 24
  • 97
  • 201
  • 1
    what do you mean by "fully visible" ? it's either visible or not I think – niceman May 23 '17 at 14:25
  • By fully visible I mean that you can see it in its full height – Leff May 23 '17 at 14:26
  • I am not hiding divs – Leff May 23 '17 at 14:27
  • ahh you mean the user will scroll and they're now seeing header,content or footer and you want to check which one ? – niceman May 23 '17 at 14:28
  • Yes, I forgot to mention that – Leff May 23 '17 at 14:29
  • in that case duplicate – niceman May 23 '17 at 14:30
  • 1
    Possible duplicate of [How to tell if a DOM element is visible in the current viewport?](https://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport) – niceman May 23 '17 at 14:30
  • Does your problem is that you may have 2 carousels fully in viewport at the same time? – Louys Patrice Bessette May 23 '17 at 14:31
  • @niceman I have already seen this solution and have tried to work with it, but the above mentioned scenario happens to me, because I have 3 sections it is a different case scenario, so that answer didn't help me – Leff May 23 '17 at 14:31
  • no, at no point two of the sections are visible with their full height in the viewport – Leff May 23 '17 at 14:33
  • So please, clarify this *«But that doesn't work, because when I am scrolling down and the upper div is still visible I am able to navigate carousels of both sections.»* – Louys Patrice Bessette May 23 '17 at 14:35
  • hmm so when the upper div is visible but in small size, you want it to stop, ok the answer isn't a duplicate(you should mention your findings next time) but the function `getBoundingClientRect` can still be used – niceman May 23 '17 at 14:36
  • Well, when I scroll and still see the bottom part of the upper div, and the upper half of the bottom div, I can navigate carousels of both sections – Leff May 23 '17 at 14:37
  • @LouysPatriceBessette he wants the carousel that occupies the most of the viewport to play even when there are others occupying a small section of the viewport – niceman May 23 '17 at 14:38
  • @niceman exactly, I want the one that is visible the most to have enabled navigation – Leff May 23 '17 at 14:38
  • I think you should iterate the `.carousel` elements in `isFullyVisible(el)`... You actually run the function on the collection of all three elements. The function should then return a array of boolean like (false,true,false)... This way you'd know exactly which is visible. It can be done many ways.... probably. – Louys Patrice Bessette May 23 '17 at 14:40
  • You have to more clearly define fully visible. – Dr Upvote May 23 '17 at 14:43
  • But the boolean you get from `isFullyVisible(el)` can't indicate exactly which is visible because you run the function on an element collection. So that is what you have to fix ;) – Louys Patrice Bessette May 23 '17 at 14:44
  • May I suggest https://github.com/zeusdeux/isInViewport :) I think `tolerance` is what you want – niceman May 23 '17 at 14:45
  • @niceman: good plugin suggestion, but OP would also have to run the test on each carousel instead of the `.carousel` collection. So it doesn't solve anything about the issue. – Louys Patrice Bessette May 23 '17 at 14:47
  • @LouysPatriceBessette hmm OP can call `.inViewPort` on `$('.carousel')` but hmmm yes you're right – niceman May 23 '17 at 14:49
  • 1
    yes, I will fix that – Leff May 23 '17 at 14:52
  • 1
    ok I think I found exactly what you want, check it out https://github.com/andyexeter/most-visible – niceman May 23 '17 at 14:54

0 Answers0