Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support check if is visible inside of a an element with overflow: scroll #11

Open
togakangaroo opened this issue Dec 10, 2013 · 14 comments
Assignees

Comments

@togakangaroo
Copy link

Currently this only checks visibility on the window object.

Paradoxically, if it is inside a div with overflow: scroll it will report "true" even if the element is not on the page.

This is really anti-intuitive, jquery-visible really should check scroll visibility as well

@samatcd
Copy link
Member

samatcd commented Dec 16, 2013

This is a little utility plugin — Checking overflow/scroll position of all elements (where you'd possibly need to consider multiple nested scrolling elements) will probably bloat this plugin too much to be broadly useful. This might be the domain of a separate plugin?

@samatcd samatcd closed this as completed Dec 16, 2013
@samatcd
Copy link
Member

samatcd commented Dec 16, 2013

You may be interested in this though — it might solve your particular problem?

https://github.com/tlaverdure/jquery-visible/commit/48c4c8dcc4a6dce2a02bfe11c5007d1adea14b01

@togakangaroo
Copy link
Author

That makes perfect sense, the problem is one of naming though. A decent percentage of people coming to this plugin would be looking for precisely the more complex behavior.

As much as it would be nice to change the name that's of course not pragmatic (and a bit insulting to your project), it would help save those people time however if there was a big bold warning on the main page as to what this plugin can and cannot do (perhaps with a suggestion as to alternatives).

@samatcd
Copy link
Member

samatcd commented Dec 16, 2013

I've added a note to that effect on the Readme under Limitations.

One option would be to give the ability to define which viewport is used when running the check, allowing you to specify the element to target. We could then recursively call the plugin on it's parents to check for visibility — that would allow us to provide this functionality without adding too much code bulk.

@samatcd samatcd reopened this Dec 16, 2013
@ghost ghost assigned samatcd Dec 16, 2013
@m4olivei
Copy link

m4olivei commented Aug 6, 2014

@samatdf I think that would be a great addition. Most of the time when your wanting to check on an element visibility, you know that it's in a container that has overflow: scroll and you want to check visibility against that container.

@samatcd
Copy link
Member

samatcd commented Aug 6, 2014

Cool, if there are some people interested in this I'll definitely take a look.

@neverthemachineforever
Copy link

👍 Currently encountering this exact problem. I think the nested overflow: scroll would be insane to solve, but something like specifying a single scrolling container within which the element resides would be awesome.

@ljowen
Copy link

ljowen commented Oct 27, 2014

Take a look at http://api.jqueryui.com/scrollParent/
Returns the first parent of the element set to overflow: scroll.
Obviously doesn't solve multiple scrollable ancestors but may be useful for a single nested scrollable.

@yor-so
Copy link

yor-so commented Jul 9, 2015

So far, I haven't found a way to check if an element is visible inside a div with "overflow: scroll". Every solution just check if the element is visible inside the viewport. If there could be some way to add that functionality, that would be awesome.
As it was said before, this could be done in a way that it check only his parent, or specifically said in respect to which element check visibility

@julkue
Copy link

julkue commented Sep 15, 2015

👍

@Fordi
Copy link

Fordi commented Mar 3, 2017

To see if an element is visible in nested scrolled containers, get the client rect for the element and its chain of parents. Filter out those parents for which don't have one of overflow: scroll, overflow-x: scroll, or overflow-y: scroll. Now, grab the boundingClientRects for the element and each of its parents (Element#getBoundingClientRect), and get the intersection of all of them (max of lefts and tops, min of rights and bottoms). If left < right and top < bottom, the element is, in part, visible, and the intersected rect represents what part of it is.

Gimme a minute, and I'll write a quick function around that.

@Fordi
Copy link

Fordi commented Mar 3, 2017

/**
 * Determines whether an element is contained in the visible viewport of its scrolled parents
 * 
 * @param goDeep If false or undefined, just check the immediate scroll parent.  
 *               If truthy, check all scroll parents up to the Document.
 * @return Object A bounding box representing the element's visible portion:
 *         left: left edge of the visible portion of the element relative to the screen
 *         top: top edge of the visible portion of the element relative to the screen
 *         right: right edge of the visible portion of the element relative to the screen
 *         bottom: bottom edge of the visible portion of the element relative to the screen
 *         width: width of the element
 *         height: height of the element
 *         isVisible: whether any part of the element can be seen
 *         isContained: whether all of the element can be seen
 *         visibleWidth: width of the visible portion of the element
 *         visibleHeight: width of the visible portion of the element
 */

jQuery.fn.visibleInScroll = function (goDeep) {
    var parent = $(this[0]).scrollParent()[0],
        elRect = this[0].getBoundingClientRect(),
        rects = [ parent.getBoundingClientRect() ];
    elRect = {
        left: elRect.left, 
        top: elRect.top, 
        right: elRect.right, 
        bottom: elRect.bottom,
        width: elRect.width,
        height: elRect.height,
        visibleWidth: elRect.width,
        visibleHeight: elRect.height,
        isVisible: true,
        isContained: true
    };
    var elWidth = elRect.width,
        elHeight = elRect.height;
    if (parent === this[0].ownerDocument) {
        return elRect;
    }
    
    while (parent !== this[0].ownerDocument && parent !== null) {
        if (parent.scrollWidth > parent.clientWidth || parent.scrollHeight > parent.clientHeight) {
            rects.push(parent.getBoundingClientRect());
        }
        if (rects.length && goDeep) { break; }
        parent = $(parent).scrollParent()[0];
    }
    if (!goDeep) {
        rects.length = 1;
    }
    for (var i = 0; i < rects.length; i += 1) {
        var rect = rects[i];
        elRect.left = Math.max(elRect.left, rect.left);
        elRect.top = Math.max(elRect.top, rect.top);
        elRect.right = Math.min(elRect.right, rect.right);
        elRect.bottom = Math.min(elRect.bottom, rect.bottom);
    }
    elRect.visibleWidth = Math.max(0, elRect.right - elRect.left);
    elRect.visibleHeight = elRect.visibleWidth && Math.max(0, elRect.bottom - elRect.top);
    if (!elRect.visibleHeight) { elRect.visibleWidth = 0; }
    elRect.isVisible = elRect.visibleWidth > 0 && elRect.visibleHeight > 0;
    elRect.isContained = elRect.visibleWidth === elRect.width && elRect.visibleHeight === elRect.height;
    return elRect;
};

@samatcd samatcd closed this as completed Mar 5, 2017
@samatcd samatcd reopened this Mar 5, 2017
@ahmu83
Copy link

ahmu83 commented Jun 7, 2021

I am getting this error when i use that function @Fordi Uncaught TypeError: $(...).scrollParent is not a function

`

$('.scroll-el').on('scroll resize', function (event) {

  var el = $(this);
  var item = el.find('.item');

  item.each(function(index, el) {

    var el2 = $(el);
    var val = el2.visibleInScroll() ? '1' : '0';

    el2.attr( 'data-visible', val );

  });

});

`

@Fordi
Copy link

Fordi commented Jun 7, 2021

That's weird? $(...).scrollParent() is provided by jQuery UI; you're using that, right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants