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

Feature Capture Event #91

Merged
merged 2 commits into from
Sep 9, 2020
Merged

Feature Capture Event #91

merged 2 commits into from
Sep 9, 2020

Conversation

vipulbhj
Copy link
Contributor

@vipulbhj vipulbhj commented Sep 5, 2020

First draft implementation for #33

node.addEventListener(eventName, patchedHandler);
let isCaptureEvent = eventName.endWith('Capture');
if(isCaptureEvent) {
let cleanedEventName = eventName.replace('Capture', '');
Copy link
Collaborator

Choose a reason for hiding this comment

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

As we are passing attrName for mapping patched handler. We can do this logic inside getEventName only.

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, making the update

if(isCaptureEvent) {
let cleanedEventName = eventName.replace('Capture', '');
node.addEventListener(cleanedEventName, patchedHandler);
} else {
Copy link
Collaborator

Choose a reason for hiding this comment

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

No need to have if/else, we can just do.

node.addEventListener(cleanedEventName, patchedHandler, isCaptureEvent);

If it is false it will assign it in bubble phase.

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 that indeed is cleaner 👍
Will update this

src/utils.js Outdated
@@ -21,7 +21,9 @@ export function getNodeName(node) {
}

export function getEventName(attrName) {
return attrName.replace('on', '').toLowerCase();
let eventName = attrName.replace('on', '').toLowerCase();
if(eventName.endsWith('capture')) return eventName.replace('capture', '');
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I could add the capture replace in the same code itself, but it would be better if we only remove it my removing capture from the end via substring

Just not sure, if thats reasonable for some event to have capture in its name

Copy link
Collaborator

Choose a reason for hiding this comment

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

Actually there are two, gotpointercapture and lostpointercapture.
https://developer.mozilla.org/en-US/docs/Web/Events

I don't see preact handling it. https://github.com/preactjs/preact/blob/master/src/diff/props.js#L92

Have to check react if they handle it differently

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also you can replace on and capture together using regex.

.replace(/^on(.*?)(Capture$|$)/, '$1')

@@ -56,7 +56,8 @@ function setAttribute(node, attrName, attrValue, oldAttrValue, isSvgAttribute) {

// if the event is getting added first time add a listener
} else if (!oldAttrValue && attrValue) {
node.addEventListener(eventName, patchedHandler);
let isCaptureEvent = attrName.endWith('Capture');
Copy link
Collaborator

@s-yadav s-yadav Sep 5, 2020

Choose a reason for hiding this comment

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

Define it outside, so you can use it to remove the event listener as well.

src/utils.js Outdated
@@ -21,7 +21,9 @@ export function getNodeName(node) {
}

export function getEventName(attrName) {
return attrName.replace('on', '').toLowerCase();
let eventName = attrName.replace('on', '').toLowerCase();
if(eventName.endsWith('capture')) return eventName.replace('capture', '');
Copy link
Collaborator

Choose a reason for hiding this comment

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

Actually there are two, gotpointercapture and lostpointercapture.
https://developer.mozilla.org/en-US/docs/Web/Events

I don't see preact handling it. https://github.com/preactjs/preact/blob/master/src/diff/props.js#L92

Have to check react if they handle it differently

src/utils.js Outdated
@@ -21,7 +21,9 @@ export function getNodeName(node) {
}

export function getEventName(attrName) {
return attrName.replace('on', '').toLowerCase();
let eventName = attrName.replace('on', '').toLowerCase();
if(eventName.endsWith('capture')) return eventName.replace('capture', '');
Copy link
Collaborator

Choose a reason for hiding this comment

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

Also you can replace on and capture together using regex.

.replace(/^on(.*?)(Capture$|$)/, '$1')

@@ -49,14 +49,15 @@ function setAttribute(node, attrName, attrValue, oldAttrValue, isSvgAttribute) {

// get patched event handler
const patchedHandler = getPatchedEventHandler(node, attrName, attrValue);

const isCaptureEvent = attrName.endWith('Capture');
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
const isCaptureEvent = attrName.endWith('Capture');
const isCaptureEvent = attrName.endsWith('Capture');

Copy link
Collaborator

Choose a reason for hiding this comment

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

We will also need to add support for onGotPointerCapture, and onLostPointerCapture as well. React does handle it.
Also, we can have a capture phase on these events, so this becomes more tricky. You can try the below logic in browser.

const para = document.querySelector('p');

para.addEventListener('gotpointercapture', () => {
  console.log('I\'ve been captured!')
}, false);

para.addEventListener('pointerdown', (event) => {
  para.setPointerCapture(event.pointerId);
});

document.body.addEventListener('gotpointercapture', () => {
  console.log('budy I\'ve been captured!')
}, false);

document.body.addEventListener('pointerdown', (event) => {
  para.setPointerCapture(event.pointerId);
});

So ideally even this onGotPointerCaptureCapture and onLostPointerCaptureCapture is valid event.

We will have to add Edge case for this two events.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should we handle it the way react does ?
We can also check for these specific events and then do the special logic.

Copy link
Collaborator

Choose a reason for hiding this comment

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

We can handle it in the same way.
https://www.measurethat.net/Benchmarks/Show/9484/0/substr-vs-endswith

We will also have to take care of getEventName method for this

src/utils.js Outdated
@@ -21,6 +21,11 @@ export function getNodeName(node) {
}

export function getEventName(attrName) {
const isSpecialCaptureEvent = attrName.substr(-7) === 'Capture' && attrName.substr(-14, 7) !== 'Pointer';
Copy link
Collaborator

Choose a reason for hiding this comment

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

This logic we should put on updateAttribute method to find isCaptureEvent event. This case handles both the normal capture case and special case. So it's not just the isSpecialCaptureEvent

And we can pass isCaptureEvent as param in this function.

@@ -50,7 +50,7 @@ function setAttribute(node, attrName, attrValue, oldAttrValue, isSvgAttribute) {
// get patched event handler
const patchedHandler = getPatchedEventHandler(node, attrName, attrValue);

const isCaptureEvent = attrName.endWith('Capture');
const isCaptureEvent = attrName.substr(-7) === "Capture";
Copy link
Collaborator

Choose a reason for hiding this comment

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

This will break for the special case. We can use the logic below here and pass isCaptureEvent as param to getEventName, just check if getEventName is getting called from anywhere else.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

why will this break ?

src/utils.js Outdated
Comment on lines 25 to 29
if(isSpecialCaptureEvent) {
// Capture -> 7 , on -> 2 ; 7 + 2 = 9;
return attrName.replace('on', '').substr(0, (attrName.length - 9)).toLowerCase();
}
return attrName.replace(/^on(.*?)(Capture$|$)/, '$1').toLowerCase();
Copy link
Collaborator

@s-yadav s-yadav Sep 9, 2020

Choose a reason for hiding this comment

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

if (isCapture) attrName = attrName.replace(/Capture$/, '');
return attrName.replace('on', '').toLowerCase();

added suggested improvements

capture added to removeEventListener and getEventName

Made the appropriate changes

Review Changes done
@s-yadav s-yadav merged commit ffc3710 into brahmosjs:master Sep 9, 2020
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.

2 participants