How are Shadow DOM events from under <content> displayed?

I am trying to understand what events that occur in the light of the DOM look when they are received in the shadow DOM using the <content> element. I am reading the Shadow DOM W3C Draft , and I do not quite understand it, but it seems that the events should be “redirected” in terms of the EventListener Attachment.

In cases where the event path passes through several node trees, event information about the purpose of the event is configured in order to maintain encapsulation. Targeting punching is the process of computing relative goals for each ancestor node in which an event is sent. The relative target is node, which most accurately represents the target of the dispatched event for a given ancestor, while supporting encapsulation.

and

When sending an event:

  • The target and currentTarget attributes should return relative targets for the node on which event listeners are called

So, here is a simple Polymer user element that simply puts its children in a container and adds an EventListener clicker to the container (in the DOM DOW). In this case, the child is a button.

 <!DOCTYPE html> <html> <head> <script src="bower_components/platform/platform.js"></script> <link rel="import" href="bower_components/polymer/polymer.html"> </head> <body unresolved> <polymer-element name="foo-bar"> <template> <div id="internal-container" style="background-color:red; width:100%;"> <content></content> </div> </template> <script> Polymer("foo-bar", { clickHandler: function(event) { console.log(event); var element = event.target; while (element) { console.log(element.tagName, element.id); element = element.parentElement; } }, ready: function() { this.shadowRoot.querySelector('#internal-container').addEventListener('click', this.clickHandler); } }); </script> </polymer-element> <foo-bar id="custom-element"> <button>Click me</button> </foo-bar> </body> </html> 

When I run this on the Chrome channel 38.0.2075.0, when I click the button, I get:

 MouseEvent {dataTransfer: null, toElement: button, fromElement: null, y: 19, x: 53…}altKey: falsebubbles: truebutton: 0cancelBubble: falsecancelable: truecharCode: 0clientX: 53clientY: 19clipboardData: undefinedctrlKey: falsecurrentTarget: nulldataTransfer: nulldefaultPrevented: falsedetail: 1eventPhase: 0fromElement: nullkeyCode: 0layerX: 53layerY: 19metaKey: falsemovementX: 0movementY: 0offsetX: 45offsetY: 10pageX: 53pageY: 19path: NodeList[0]relatedTarget: nullreturnValue: truescreenX: 472screenY: 113shiftKey: falsesrcElement: buttontarget: buttontimeStamp: 1404078533176toElement: buttontype: "click"view: WindowwebkitMovementX: 0webkitMovementY: 0which: 1x: 53y: 19__proto__: MouseEvent test.html:17 BUTTON test.html:20 FOO-BAR custom-element test.html:20 BODY test.html:20 HTML test.html:20 

and when I click on the container, I get:

 MouseEvent {dataTransfer: null, toElement: div#internal-container, fromElement: null, y: 15, x: 82…} test.html:17 DIV internal-container test.html:20 

This way I get the event target in either the light or shadow DOM, depending on which DOM the source element was in. I expected to get the target from the DOM DOM in both cases, because where the EventListener is installed. My questions:

  • This is how it should work, and
  • If so, is there an alternative way to get events that bubble from the light DOM redirected to the shadow DOM?

In the event that someone wants to ask, “What are you trying to do?”, I am not trying to do anything specifically other than understanding behavior.

+7
polymer web-component shadow-dom
source share
1 answer

Shadow house events are complex. I am trying to capture the braindump below.

  • Is this the way it should work?

Yeah. If you test in Chrome, you get your own shadow house.


I wrote a section on event retargeting in an HTML5Rocks article - Shadow DOM 301 . In principle, re-targeting means that events originating from the shadow look as if they are originating from the element itself.

In your example, you are registering an event inside a shadow house, so it is still visible. If you also add a 'click' listener outside the element, the target will look as if it came from the element:

 <script> var el = document.querySelector('#custom-element'); el.addEventListener('click', function(e) { console.log(e.target.tagName); // logs FOO-Bar }); </script> 

http://jsbin.com/womususe/1/edit

'Click' event templates. This is why you see BUTTON in your top example. Why do you even see this? You see this because the button is not part of your shadow house. This is in light of the dom and purpose of the element. It is important to remember that the light DOM nodes are still logically in the main document. They do not move into the shadow space, they are simply displayed at the <content> input points.


By the way, for your examples there are several polymerized corrections:

  • this.shadowRoot.querySelector('#internalcontainer')this.$.internalcontainer . this.$.ID Polymer "automatic node search".
  • You do not need to use addEventListener() . Use <div id="internalcontainer" on-click="{{clickHandler}}"> . This is a declarative event handler.
+12
source share

All Articles