0

Is there any way to check if specified html element is in viewport - no window but specified div? I found only one meaningful solution but I can't make it work for me.

According to this question Check if element is visible in div

I created a example here: http://jsfiddle.net/jm91n80u/

This is my html code:

<body style="overflow:hidden;">
<div id="outer" style="position:absolute;left:150px;top:20px;right:100px;bottom:30px;overflow:hidden;border:1px solid blue;">
    <div id="inner" style="position:relative;height:300px;border:1px solid red;width:100px;overflow-y:auto;overflow-x:hidden;">
        <div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">1</div>
        <div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">2</div>
        <div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">3</div>
        <div style="position:relative;width:100%;height:30px;border:1px solid grey;background:yellow;" class="test" id="id1">4</div>
        <div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">5</div>
        <div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">6</div>
        <div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">7</div>
        <div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">8</div>
        <div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">9</div>
        <div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">10</div>
        <div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">11</div>
        <div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">12</div>
        <div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">13</div>
        <div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">14</div>
    </div>
</div>
<div id="result" style="position:absolute;bottom:0px;overflow:hidden;border:1px solid black;height:20px;width:100%;"></div>
</body>

This is a js function

$(document).ready(function () {

    $.belowthefold = function (lookIn, elements, settings) {
        var fold = $(lookIn).height() + $(lookIn).scrollTop();
        return $(elements).filter(function () {
            return fold <= $(this).offset().top - settings.threshold;
        });
    };

    $.abovethetop = function (lookIn, elements, settings) {
        var top = $(lookIn).scrollTop();
        return $(elements).filter(function () {
            return top >= $(this).offset().top + $(this).height() - settings.threshold;
        });
    };

    $.rightofscreen = function (lookIn, elements, settings) {
        var fold = $(lookIn).width() + $(lookIn).scrollLeft() + $(lookIn).offset().width;
        return $(elements).filter(function () {
            return fold <= $(this).offset().left - settings.threshold;
        });
    };

    $.leftofscreen = function (lookIn, elements, settings) {
        var left = $(lookIn).scrollLeft();
        return $(elements).filter(function () {
            return left >= $(this).offset().left + $(this).width() - settings.threshold;
        });
    };

    $("#inner").scrollTop(100);

    var b = $.belowthefold("#inner", ".test", { threshold: 0 }).toArray();
    var t = $.abovethetop("#inner", ".test", { threshold: 0 }).toArray();
    var r = $.rightofscreen("#inner", ".test", { threshold: 0 }).toArray();
    var l = $.leftofscreen("#inner", ".test", { threshold: 0 }).toArray();


    var el = $("#id1")[0];
    
    var bS = "below the fold : ";
    for (var i = 0; i < b.length; i++) {
        bS += $(b[i]).html() + ",";
    }
    var tS = "above the top : ";
    for (var i = 0; i < t.length; i++) {
        tS += $(t[i]).html() + ",";
    }
    var rS = "right of screen : ";
    for (var i = 0; i < r.length; i++) {
        rS += $(r[i]).html() + ",";
    }
    var lS = "left of screen : ";
    for (var i = 0; i < l.length; i++) {
        lS += $(l[i]).html() + ",";
    }

    console.log(bS);
    console.log(tS);
    console.log(rS);
    console.log(lS);
});

What I'm trying to do is get all '.test' elements which are currently invisible (or partial invisible in target solution, any switch will be appreciated) in inner container with information about their position. The result of this should be:

below the fold : 13, 14

above the top : 1,2,3,4

right of screen :

left of screen :

But in this particular case those functions doesn't work. I tried use several other solutions, but each one treats viewport as window.

Can you explain what am I doing wrong? Any help will be appreciated.

Community
  • 1
  • 1
Adam Mrozek
  • 1,410
  • 4
  • 26
  • 49
  • @Tushar This solution does not include items on the left and right and this is not acceptable answer for my question. – Adam Mrozek Jul 17 '15 at 08:16

1 Answers1

2

You should compare div's positions to: viewport size and windows bounds.

Roughly : if(div.top > (window.top + viewport.height )) {/*this is visible*/} else {/*this is not visible*/}

You could even make it more specific (how much area of div ?) if((div.top **+ 50% of div.height**) > (window.top + viewport.height )) {/*this is visible*/}

This post gives some codes Check if element is between 30% and 60% of the viewport

$(document).ready(function() {
    // Get viewport height, gridTop and gridBottom
    var windowHeight = $(window).height(),
        gridTop = windowHeight * .3,
        gridBottom = windowHeight * .6;

$(window).on('scroll', function() {
    // On each scroll check if `li` is in interested viewport
    $('ul li').each(function() {
        var thisTop = $(this).offset().top - $(window).scrollTop(); // Get the `top` of this `li`

        // Check if this element is in the interested viewport
        if (thisTop >= gridTop && (thisTop + $(this).height()) <= gridBottom) {
            $(this).css('background', 'red');
        } else {
            $(this).css('background', 'gray');
        }
    });
});

});

Community
  • 1
  • 1
3pic
  • 1,188
  • 8
  • 26
  • And how should I apply this example for my question? I created new fiddle here http://jsfiddle.net/h4L6d7r2/ but it still doesn't work as expected. – Adam Mrozek Jul 17 '15 at 08:39
  • @AdamMrozek huh isnt it working already ? http://jsfiddle.net/h4L6d7r2/3/ (I updated a bit your jfiddle to understand it... well you put .3 and .6 of the #inner div as limits, you get the right thing isnt it ?) – 3pic Jul 20 '15 at 10:16
  • You may need to compare MIDDLE height of test divs, advanced option. – 3pic Jul 20 '15 at 10:22