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

feat(elementhandle): introduce elementHandle.isIntersectingViewport() method. #2673

Merged
merged 7 commits into from
Jul 12, 2018
Merged

feat(elementhandle): introduce elementHandle.isIntersectingViewport() method. #2673

merged 7 commits into from
Jul 12, 2018

Conversation

b-ponomarenko
Copy link
Contributor

Add API to define is element visible in viewport via Intersection Observer

References #2629

@googlebot
Copy link

Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

📝 Please visit https://cla.developers.google.com/ to sign.

Once you've signed (or fixed any issues), please reply here (e.g. I signed it!) and we'll verify it.


What to do if you already signed the CLA

Individual signers
Corporate signers

@b-ponomarenko
Copy link
Contributor Author

I signed it!

@googlebot
Copy link

CLAs look good, thanks!

@b-ponomarenko b-ponomarenko changed the title feat(ElementHandle) Add isDisplayed method to ElementHandle featutre: Add isDisplayed method to ElementHandle Jun 4, 2018
@b-ponomarenko b-ponomarenko changed the title featutre: Add isDisplayed method to ElementHandle feat: Add isDisplayed method to ElementHandle Jun 4, 2018
@b-ponomarenko
Copy link
Contributor Author

Can I rerun node6 (windows)?

@b-ponomarenko
Copy link
Contributor Author

@aslushnikov please check

Copy link
Contributor

@aslushnikov aslushnikov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this looks promising

As part of this PR, let's change waitForSelector implementation to use intersection observer; this way we won't have inconsistencies like this:

const e = await page.waitForSelector('div', {visible: true});
await e.isVisible(); // false

docs/api.md Outdated
@@ -219,6 +219,7 @@
* [elementHandle.getProperties()](#elementhandlegetproperties)
* [elementHandle.getProperty(propertyName)](#elementhandlegetpropertypropertyname)
* [elementHandle.hover()](#elementhandlehover)
* [elementHandle.isDisplayed()](#elementhandleisdisplayed)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

elementHandle.isVisible() is better since it aligns with waitForSelector's "visible" option.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I will rename to isVisible

resolve(entries[0].isIntersecting);
observer.unobserve(node);
};
const observer = new IntersectionObserver(callback, { root: null, rootMargin: '0px', threshold: 1.0 });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so when will the callback be called? Is it always called initially?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it will be called initially and then unobserve from the node

const box = await page.$('.box');

expect(await box.isDisplayed()).toBe(false);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we also add a test that checks for the truthy value?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'll add this test case soon

@@ -0,0 +1,23 @@
<html>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's use page.setContent instead of a separate asset.

@JoelEinbinder
Copy link
Collaborator

If we change waitForSelector to use intersection observer, won’t that cause elements below the fold to be considered invisible? That’s a pretty major change, and I’m not sure if it makes that feature more or less useful. “Visible” vs “would visible if you scroll down” is hard to define. And it conflicts with the original use case for this feature, which was to report elements ina carousel as invisible even though they could be scrolled to horizontally.

@aslushnikov
Copy link
Contributor

won’t that cause elements below the fold to be considered invisible?

@JoelEinbinder These will be considered invisible. This is a very good point though, we might need to postpone this till 2.0.

That’s a pretty major change, and I’m not sure if it makes that feature more or less useful.

Usefulness is debatable, but API sanity will improve:

  • Our current isVisible is more like isClickable, it's quite quirky with a huge grey area of what is considered "visible".
  • Visibility defined by intersection observer is aligned with a natural perception of visibility, it's easy to explain and understand.

Add API to define is element visible in viewport via Intersection Observer

References #2629
@b-ponomarenko
Copy link
Contributor Author

b-ponomarenko commented Jun 12, 2018

@aslushnikov change implementation of _waitForSelectorOrXPath, but in some cases this test fails (when I run this test in single mode almost always test passed), what can be wrong?

upd
no longer relevant, understood the problem and fix

@b-ponomarenko
Copy link
Contributor Author

@aslushnikov please check PR

@aslushnikov aslushnikov mentioned this pull request Jun 19, 2018
13 tasks
@aslushnikov
Copy link
Contributor

@aslushnikov please check PR

@b-ponomarenko We discussed this PR with @JoelEinbinder one more time.

Summary:

  • there are two types of visibility: visible-in-viewport (this implementation) and displayed-in-page (currently used for visible option in waitForSelector)
  • both make perfect sense from API standpoint: visible-in-viewport comes handy to detect what user sees, and displayed-in-page is more like "interactable", e.g. something that could be clicked.
  • changing waitForSelector's visible semantics from displayed-in-page to visible-in-viewport is a breaking change; we can't afford it yet.

So the way forward with this:

  • disregard my suggestion on using IntersectionObserver for waitForSelector. (Sorry for misguiding you)
  • introduce a new distinct method on ElementHandle, e.g. ElementHandle.isVisibleInViewport, that uses Intersection Observer.

As a part of 2.0 effort, we might want to do a better job separating "interactivity" vs "visibility", e.g. renaming visible into interactable. I've added a bullet.

…ElementHandle.isVisible to ElementHandle.isVisibleInViewport
@b-ponomarenko
Copy link
Contributor Author

b-ponomarenko commented Jun 20, 2018

@aslushnikov I canceled using Intersection Observer in _waitForSelectorOrXPath. What's next? Really, maybe rename visible property to interactable or some other property name, and move current implementation via Intersection Observer to visible property?

@aslushnikov aslushnikov changed the title feat: Add isDisplayed method to ElementHandle feat(elementhandle): introduce elementHandle.isIntersectingViewport() method. Jul 12, 2018
Copy link
Contributor

@aslushnikov aslushnikov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discussed this with @JoelEinbinder and renamed into elementHandle.isIntersectingViewport(). Thanks for the PR!

@aslushnikov aslushnikov merged commit 96c558d into puppeteer:master Jul 12, 2018
@justnpT
Copy link

justnpT commented Mar 7, 2019

I wouldn't be so sure that inputElement.isIntersectingViewport() is true only when an element is visible for human eyes, I have a case where element didn't yet appear as visible for eyes and
await element.isIntersectingViewport()
returns true

@aslushnikov
Copy link
Contributor

I have a case where element didn't yet appear as visible for eyes and
await element.isIntersectingViewport()
returns true

@justnpT interesting! Can you please file a new issue with a repro for your usecase?

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

Successfully merging this pull request may close these issues.

None yet

5 participants