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 for shadow dom #30

Open
isidrok opened this issue Apr 25, 2020 · 5 comments
Open

Support for shadow dom #30

isidrok opened this issue Apr 25, 2020 · 5 comments

Comments

@isidrok
Copy link

isidrok commented Apr 25, 2020

Intercepting clicks made on anchors inside shadow roots looking for the anchor closest to the event target doesn't work since events are re-targeted to the shadow root host element.

The anchor can be found in the event path with the following code:

function findA(e){
  var i = 0, p = e.path || e.composedPath && e.composedPath(), a = p && p[i];
  while(a && a.tagName !== 'A') a = p[++i];
  return a;
}

Note that this will only work for shadow roots configured with mode set to open since elements inside closed ones don't appear in the event path.

Can submit a PR if you agree with the proposed change

@lukeed
Copy link
Owner

lukeed commented Apr 26, 2020

Hmm... isn't the point of Shadow DOM is to hide it away from the parent container?
I don't use WC but iirc, you have to use mode: 'open' and manually proxy/bubble events should you want them to be accessed.

I'll have to think about this for now. Will open it up for feedback from others who've hopefully had more experience. Thanks for the suggestion!

@isidrok
Copy link
Author

isidrok commented Apr 26, 2020

Yes, the point is encapsulation but that doesn't mean event delegation should not work.

It is true that you need to properly configure events your components manually dispatch if you want them to exit shadow root boundaries composed:true and some native events won't cross shadow root boundaries but most of them do.

You can read more about it here https://developers.google.com/web/fundamentals/web-components/shadowdom#events

Thanks for considering.

Edit: a fallback may be needed for browsers that don't support event.path or event.composedPath (IE and old Edge that I'm aware of) the good thing is since these browsers don't support custom elements event re-targetting should not happen and event.target.closest('a') should work.

@tomg7
Copy link

tomg7 commented Sep 22, 2020

Please consider implementing this feature as navaid does not work with Shadow DOM (and libraries like LitElement that uses Shadow DOM by default) without it.

I added @isidrok's code to navaid's click function as var x = e.target.closest('a') || findA(e) and tested it in one of my LitElement based projects where I would like to replace Page.js with navaid. It works fine for me.

You might also want to take a look at the relevant pull request from Page.js .

I think this feature would be really useful as Shadow DOM is supported in all modern browsers and its usage is rising.

Thanks

@ba55ie
Copy link

ba55ie commented Sep 7, 2021

Yes please! :)

It's hard to find a simple and robust router that supports Shadow DOM (Web Components) and navaid seems to tick all the boxes.

By adding a few lines of code navaid will support a current web standard and make a lot of some developers happy. ;)

@zerodevx
Copy link

FWIW, I'll maintain a forked version that supports shadow-dom anchor links, where the only change is from this:

var x = e.target.closest('a'), y = x && x.getAttribute('href');

to this:

var x = e.composedPath, x = e.path || x && x() || [e.target], 
  x = x[0].closest('a'), y = x && x.getAttribute('href');

Install with:

$ npm i @zerodevx/navaid

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

5 participants