-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
✨ Visibility trigger support for querySelectorAll #26886
✨ Visibility trigger support for querySelectorAll #26886
Conversation
1b947bf
to
ec0e4ae
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zhouyx Should the tests in test-analytics-root.js
also be applied to theEmbedAnalyticsRoot
within that file?
9b8dc50
to
c978db5
Compare
c978db5
to
7ba9784
Compare
3d508c6
to
74eaef3
Compare
this.root | ||
.getAmpElementOrElements( | ||
context.parentElement || context, | ||
selectors[i], | ||
selectionMethod, | ||
multiSelectorVisibilityOn | ||
) | ||
.then(elements => { | ||
for (let j = 0; j < elements.length; j++) { | ||
unlistenPromises.push( | ||
visibilityManagerPromise.then( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this seem correct?
return this.ampdoc.whenReady().then(() => { | ||
const results = []; | ||
const foundElements = scopedQuerySelectorAll( | ||
dev().assertElement(this.ampdoc.getBody()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you confirm that if embed would get its own ampdoc? If not I think we still need to pass in the context
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Current implantation uses this.getRoot().querySelector(selector)
, which I think is a better approach.
PTAL @zhouyx |
} | ||
const elements = []; | ||
for (let i = 0; i < foundElements.length; i++) { | ||
if (this.contains(foundElements[i])) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this.contains
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Used in the original getAmpElements(), to make sure that the element is a descendant of the analytics-root
: defined here
489b467
to
7683e34
Compare
@zhouyx Ready for another round of review |
for (let i = 0; i < elementsLists.length; i++) { | ||
this.verifyAmpElements_(elementsLists[i], selectors[i]); | ||
for (let j = 0; j < elementsLists[i].length; j++) { | ||
if (uniqueElements.indexOf(elementsLists[i][j]) === -1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little concern about the performance here. Would it be faster to assign a unique attribute to element instead? so that we don't need to iterate the array everytime. Could you please verify?
cc @jridgewell who might know : ) What's the best way to find unique element out of an array?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For small lists, this will be quick enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zhouyx I think the list will be relatively small. What do you think?
4efc09f
to
97c92a9
Compare
@zhouyx Ready for another round of review
Changes in the next PR:
These changes will not change the code flow/structure seen in this PR. |
d30b758
to
0b1f226
Compare
0b1f226
to
c4b9cc5
Compare
'Cannot have selectionMethod defined with an array selector.' | ||
); | ||
return this.getElementsByQuerySelectorAll_(selectors).then((elements) => | ||
elements.filter((element, index) => elements.indexOf(element) === index) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this goes into getElementsByQuerySelectorAll_
as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Won't make a much of a difference when the elements list is small, but it does take O(n^2) time... I'm a bit concerned when one try to select every single <p>
of a document. could you please bench mark the performance with a reasonable element count? Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For a webpage with 30 amp-ad elements and no throttle:
- 0.024ms avg with O(n^2)
elements.filter((element, index) => elements.indexOf(element) === index)
- 0.058ms avg with O(n)
for (let i = 0; i < elements.length; i++) {
if (!elements[i].hasAttribute('special')) {
elements[i].setAttribute('special', 'yes');
returnElements.push(elements[i]);
}
}
Not sure if there's. better way to do O(n)
@zhouyx Ready for review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't reply to the original comment thread, but re https://github.com/ampproject/amphtml/pull/26886/files#discussion_r402566861
Thanks for running the benchmark, I can only think about apply special attribute and remove it afterwards as the way to achieve O(n).
SG, let's go with the your approach.
expect(error).to.match(/required to be an AMP element/); | ||
}); | ||
}); | ||
|
||
describe('get amp elements', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will we deprecate usage of analyticsRoot.getElement()
afterwards? If so is the plan to fix related test in the following PR?
child2.classList.add('i-amphtml-element'); | ||
}); | ||
|
||
it('should find all elements by selector', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ping on this comment : )
457130d
to
215a15b
Compare
215a15b
to
71c6b80
Compare
@zhouyx Can you approve again for the bundle size check? |
Task 2 of #26823
getAmpElement()
=>getAmpElementOrElements
scopedQuerySelectorAll()
for given selectorselectionMethod
is providedgetElement()
of selectorunlistenPromises
Flame Charts:
Before for processConfigs and addTriggers:
After for processConfigs and addTriggers: