0

Could you please tell me how how to highlight bottom li when user scrolling in a div? I have one container div, in which there are four divs. In the footer I also have four li (first, second, third,fourth). I want to select the li (background become red)when the user scrolls the respectively div's.

Example

When the code runs, the first li should be selected it background become red because the first div is in the view port. If the user scrolls and moves to the second div, the second li should be selected. And so on.

I tried like that

https://jsbin.com/giwizufotu/edit?html,css,js,output

(function(){
  'use strict';
  $(function(){
    $( "#container" ).scroll(function() {
      console.log('scrlling');
      if (elementInViewport2($('#first'))) {
        // The element is visible, do something
        console.log('first visible')
    } else {
         console.log('second visible')
    }
    });
  })

  function elementInViewport2(el) {
  var top = el.offsetTop;
  var left = el.offsetLeft;
  var width = el.offsetWidth;
  var height = el.offsetHeight;

  while(el.offsetParent) {
    el = el.offsetParent;
    top += el.offsetTop;
    left += el.offsetLeft;
  }

  return (
    top < (window.pageYOffset + window.innerHeight) &&
    left < (window.pageXOffset + window.innerWidth) &&
    (top + height) > window.pageYOffset &&
    (left + width) > window.pageXOffset
  );
}

})()

I don't want to use plugin

user5711656
  • 2,157
  • 3
  • 23
  • 46
  • Since all the `li`'s is bigger than viewport. the logic you have will not work properly. A better approach would be to check their top position relative to the viewport, and then decide how far from viewport top it should be to consider it in view – Ason Feb 15 '17 at 08:41
  • could you please share view in fiddle or jsbin – user5711656 Feb 15 '17 at 09:01

3 Answers3

0

https://jsbin.com/borohoheji/edit?html,css,js,console,output

Look at what i did i check if the element is visible with .is(':visible')

You can work from there and do exactly what you want

Mawcel
  • 1,870
  • 12
  • 22
0

Change your code to:

    (function(){
  'use strict';
  $(function(){
    $( "#container" ).scroll(function() {
      console.log('scrlling');
      if (elementInViewport($('#first'))) {
    // The element is visible, do something
        console.log('first visible')
    } else {
         console.log('second visible')
    }
    });
    $( "#container >div" ).hover(
      function() {
        $(this).css('color', 'yellow');
      });
  })
Ton
  • 250
  • 2
  • 11
  • The _$("#container >div")_ selects every div in _#container_ The _.hover_ limits it to only when a div gets a mouseover and the _.css_ sets the color to a highlight. Just change the CSS to what you want.. – Ton Feb 15 '17 at 09:12
0

First, do the following :

  • give all the text divs a classname eg 'para', to make them more readily selectable as a collection.
  • establish a ul.fC li.active {...} directive in your style sheet to give the desired visual effect.

Then :

(function() {
    'use strict';
    $(function() {
        var $container = $("#container"),
            $paras = $container.children(".para"), // the four text divs.
            $listElements = $(".footer ul.fC li"), // the four li elements in the footer.
            oldIndex = -1;
        $container.scroll(function() {
            var index = $paras.index($paras.filter(visibleY).eq(0)); // position of the first visible text div.
            if(index !== oldIndex) { // avoid unnecessary work
                $listElements.eq(oldIndex).removeClass('active'); // remove highlight
                $listElements.eq(index).addClass('active'); // add highlight
                oldIndex = index; // remember index for next event turn
            }
        }).trigger('scroll');
        function visibleY() {
            // based on http://stackoverflow.com/a/21627295/3478010
            var el = this; // because function is called as a .filter() callback.
            var rect = el.getBoundingClientRect(), 
                top = rect.top, 
                height = rect.height, 
                el = el.parentNode;
            do {
                rect = el.getBoundingClientRect();
                if (top <= rect.bottom === false) return false;
                // Check if the element is out of view due to a container scrolling
                if ((top + height) <= rect.top) return false
                el = el.parentNode;
            } while (el != document.body);
            // Check its within the document viewport
            return top <= document.documentElement.clientHeight;
        };
    });
})();

As written above, the change of style will happen in response to paras exiting/entering the container's top edge.

The behaviour can be changed to respond to paras exiting/entering the container's bottom edge by replacing :

var index = $paras.index($paras.filter(visibleY).eq(0)); // position of the first visible para.

with :

var index = $paras.index($paras.filter(visibleY).last()); // position of the last visible para.

Choose whichever is more desirable.

Roamer-1888
  • 18,384
  • 5
  • 29
  • 42