-
Notifications
You must be signed in to change notification settings - Fork 142
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
✨⚗ [RUMF-1355] add selector with stable attributes #1684
✨⚗ [RUMF-1355] add selector with stable attributes #1684
Conversation
8bb7293
to
2714cd9
Compare
2714cd9
to
a47d95b
Compare
Codecov Report
@@ Coverage Diff @@
## main #1684 +/- ##
==========================================
+ Coverage 90.76% 90.77% +0.01%
==========================================
Files 127 127
Lines 4709 4727 +18
Branches 1052 1054 +2
==========================================
+ Hits 4274 4291 +17
- Misses 435 436 +1
📣 Codecov can now indicate which changes are the most critical in Pull Requests. Learn more |
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.
Great!
packages/rum-core/src/domain/rumEventsCollection/action/getSelectorsFromElement.ts
Outdated
Show resolved
Hide resolved
packages/rum-core/src/domain/rumEventsCollection/action/getSelectorsFromElement.ts
Outdated
Show resolved
Hide resolved
] | ||
|
||
export function getSelectorsFromElement(element: Element, actionNameAttribute: string | undefined) { | ||
const attributeSelectors = STABLE_ATTRIBUTES.map((attribute) => getAttributeSelector.bind(null, attribute)) |
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.
🥜 nitpick: we could compute stable attribute selectors once instead of doing it at each call
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.
❓ question: why is getAttributeSelector
called using bind
? also doesn't getAttributeSelector
need an arg of type element
?
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.
bind
does not call the function. bind
returns a new function with some arguments defined (cf doc). Basically,
STABLE_ATTRIBUTES.map((attribute) => getAttributeSelector.bind(null, attribute))
is the same as
STABLE_ATTRIBUTES.map((attribute) => (element: Element) => getAttributeSelector(attribute, element))
Would it be clearer?
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.
Ah so we are using it as a form of currying? Thanks for the clarification
I personally wouldn't use bind
unless we care about this
; but that is more personal preference.
packages/rum-core/src/domain/rumEventsCollection/action/getSelectorsFromElement.ts
Outdated
Show resolved
Hide resolved
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.
Awesome work!
] | ||
|
||
export function getSelectorsFromElement(element: Element, actionNameAttribute: string | undefined) { | ||
const attributeSelectors = STABLE_ATTRIBUTES.map((attribute) => getAttributeSelector.bind(null, attribute)) |
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.
❓ question: why is getAttributeSelector
called using bind
? also doesn't getAttributeSelector
need an arg of type element
?
function isSelectorUniqueGlobally(element: Element, selector: string): boolean { | ||
return element.ownerDocument.body.querySelectorAll(selector).length === 1 | ||
} | ||
|
||
function isSelectorUniqueAmongChildren(element: Element, selector: string): boolean { | ||
for (let i = 0; i < element.parentElement!.children.length; i++) { | ||
const sibling = element.parentElement!.children[i] | ||
if (sibling !== element && elementMatches(sibling, selector)) { | ||
return false | ||
} | ||
} | ||
return true | ||
} |
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.
👏 praise: great naming
function computeClickActionBase(event: MouseEvent & { target: Element }, actionNameAttribute?: string) { | ||
let target: ClickAction['target'] | ||
let position: ClickAction['position'] | ||
|
||
if (isExperimentalFeatureEnabled('clickmap')) { | ||
const rect = event.target.getBoundingClientRect() | ||
target = assign( | ||
{ | ||
width: Math.round(rect.width), | ||
height: Math.round(rect.height), | ||
}, | ||
getSelectorsFromElement(event.target, actionNameAttribute) | ||
) | ||
position = { | ||
// Use clientX and Y because for SVG element offsetX and Y are relatives to the <svg> element | ||
x: Math.round(event.clientX - rect.left), | ||
y: Math.round(event.clientY - rect.top), | ||
} | ||
} | ||
|
||
return { | ||
type: 'click', | ||
target, | ||
position, | ||
name: getActionNameFromElement(event.target, actionNameAttribute), | ||
event, | ||
startClocks: clocksNow(), | ||
} | ||
} |
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.
Motivation
Use common "stable" attributes to improve CSS selector generation for heatmaps.
Changes
actionNameAttribute
option to the function used to compute selectorsTesting
I have gone over the contributing documentation.