ku3lka
Last Updated: February 25, 2016
·
827
· ilyaigpetrov
Linus

On Backward Compatibility of the Native Shadow DOM

Native shadow DOM, jQuery, bootstrap.js and other "lagacy" tools don't play nice together because of retargeting.

So, currently you have to make a choice between webcomponents and your cozy libraries.

Feedback

article discusses problems with libraries that were never intended for shadow dom, not really a polymer problem at this point just a growing pain of new technology for the web

I don't feel "we have new web, drop all your code written in the last years, rewrite everything" is a right way. I aslo think developers should know jQuery won't work with Native Shadow DOM and maybe take it as a challenge.

Google Polymer and Native Shadow DOM

WebComponents and Google Polymer is a new shiny solution for client-side complexity decomposition

in the spirit of single responsibility principle and UNIX philosophy of modularity and reusability.

One benefit of using WebComponents is CSS encapsulation:

1. CSS definitions of a component shouldn't leak in the global namespace (upper boundary).

2. CSS definitions of the document shouldn't be applied to the component (lower boundary).

Upper boundary comes with Polymer out of the box, but for the lower boundary you have to

configure Polymer to use native shadow DOM:

<script>
  window.Polymer = window.Polymer || {};
  window.Polymer.dom = 'shadow'; // Use native shadow. This will be a default option in the future.
</script>
<link rel="import" href="./bower_components/polymer/polymer.html">

Now we have fully style-encapsulated components, cool.

Retargeting and jQuery

Lets invite bootstrap.js to the party.

So, you are including bootstrap.css, bootstrap.js and jQuery as a dependency.

Then you figure out events has no effect, e.g. dropdowns don't work.

The problem is that all events dispatched from under your component's shadow root are disguised

as if coming from the uppermost shadow host.

That's called retargeting, from the very moment event is dispatched

it has shadow host in the Event.target readonly property, not a button clicked.

And there is no option to turn it off. Even if you create your own Event

you need some element to dispatch it from (a target) and dispatching from

the under shadow root entails retargeting.

bootstrap.js and jQuery are written without retargeting in mind, e.g. bootstrap contains
code like:

$(document).on('click', '[data-toggle="dropdown"]',...)

And when your click-event is fired, it seems like coming from a custom-element.

jQuery may distinct retargeted events by analyzing Event.path property but currently it doesn't.

Solutions?

  • You may write a patch for jQuery to make it work with native shadow DOM.
  • You may achieve lower bound css encapsulation by crazy hacks like making snapshot of
    element's styles computed in some "clean" css-scope and applying it programatically to
    reset unwanted styles (just an idea, maybe not feasible).
  • You may drop native shadow DOM (and lower bound css encapsulation) by:
    • placing your stuff not under the shadow root but in the light DOM;
    • turning off native shadow in Polymer settings, Polymer will switch to shady DOM shim.
  • Wait for fixes. Maybe there solutions already when you read this.
  • Override addEventListener to disguise retargeting and make sure jQuery selectors work under shadow boundary. <small>(Drop me a line if you want me to try this, motivate me)</small> Also you may run legacy code in your custom scope with overriden window and document objects like I did here with Babel.
Say Thanks
Respond