Re: Separating Transclusion Mechanisms for Inheritance and Data Binding

2014-04-30 Thread Jan Miksovsky
I just saw Dimitri's reference to my “Filling slots in shadow” blog posts from 
a while back, so I thought I’d follow up with the experiences I’ve had I wrote 
it.

First, I remain convinced that it will be very helpful for Shadow DOM to 
provide a feature like this that allows for parent and child classes to 
cooperatively contribute elements to the same component. This is a key feature 
that enables well-factored user interface components. I started a company 
earlier this year that is building a site entirely on web components, and we’ve 
already hit the limitations of what’s possible without this feature.

Second, my colleagues and I found the pre-existing proposal to let authors 
reproject content into shadow to be an elegant solution to this problem. 
During the brief window when this feature was available in Chrome Canary, we 
quickly made use of it. It felt like a very natural extension of the Shadow DOM 
tree composition concepts we had already learned. That is, in our experience, 
the conceptual load introduced by this feature was low. To the extent the 
developer experience weighs in any decision here, we were completely fine with 
the approach of placing content insertion points inside shadow elements.

Third, we feel a modest amount of impatience to see this feature implemented in 
Chrome again, and for other browsers to adopt this feature as it existed in 
Chrome. It was meeting our needs, and seeing it (even temporarily) removed felt 
like a step backwards. We’re concerned that lack of a solution here will 
discourage people from applying subclassing as a means to factor user interface 
behavior into parent/child component class relationships.

Finally, even given all the above, we view it as more important that all the 
mainstream browsers implement the more fundamental aspects of Shadow DOM with 
all due speed. Our company and its customers are entirely dependent upon web 
components that use Shadow DOM, and while we can rely upon the Polymer library 
for cross-browser compatibility, there is a considerable different in 
performance between native and polyfilled Shadow DOM features. We test on a 
variety of browsers and devices, and while we can run on Mobile Safari or IE, 
performance on those platforms is barely acceptable. We would rather see the 
basics of Shadow DOM be native now, and live without defined semantics for 
parent/child contributions to shadow trees, than wait indefinitely for that 
feature before seeing native implementations of the basics.

I feel like something of an industry outsider in discussions related to web 
standards, and appreciate the range of scenarios those working on standards 
must consider as they debate proposals for changes. I trust the smart folks at 
Apple, Google, and elsewhere to make the right decision here. All I can offer 
here is my company's own practical experience in this domain. For our part, we 
would be very happy to see a solution adopted in the standard that follows the 
general lines of allowing reprojection of content into shadow elements, but 
in the meantime are primarily concerned with seeing native Shadow DOM 
implementations across all browsers.

–Jan

Re: Separating Transclusion Mechanisms for Inheritance and Data Binding

2014-04-28 Thread Dimitri Glazkov
On Sun, Apr 27, 2014 at 2:36 PM, Ryosuke Niwa rn...@apple.com wrote:

 On Apr 22, 2014, at 10:46 AM, Dimitri Glazkov dglaz...@chromium.org
 wrote:

 BTW, here's a jsbin that implements yield/transclude using existing Shadow
 DOM plumbing:

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


 Thanks for an example.  That indeed polyfills the API we're proposing in
 terms of the currently spec'ed API.


Great!



 One important aspect of our proposal is to avoid having to rely on
 shadowRoot property on HTMLElement, which wouldn't exist in Type III
 encapsulation.


Note, that the access to element's shadowRoot happens from the element's
own implementation of a method.

If I were a developer of a framework that implements the idea you
suggested, I would do something like this:
http://jsbin.com/pacim/4/edit




 On Apr 22, 2014, at 11:06 AM, Dimitri Glazkov dglaz...@chromium.org
 wrote:

 Here's a jsbin that uses the shadow-as-function syntax and does the same
 thing:

 http://jsbin.com/peqoz/2/edit


 This one doesn't quite work as intended in that the insertion points in
 MyCardElement's shadow DOM could grab nodes from the light DOM.


Help me understand what you mean here. Which nodes will these insertion
points grab? Would love an example.

:DG


Re: Separating Transclusion Mechanisms for Inheritance and Data Binding

2014-04-28 Thread Dimitri Glazkov
Possibly relevant to the conversation: Jan Miksovsky (cc'd) had been
thinking in this problem space for a while, and has a couple of great blog
posts on the topic:

http://blog.quickui.org/2013/11/08/filling-slots-in-shadow/

http://blog.quickui.org/2013/06/11/puzzle-define-html-custom-element-subclasses-that-can-fill-in-base-class-insertion-points/

:DG


Re: Separating Transclusion Mechanisms for Inheritance and Data Binding

2014-04-27 Thread Ryosuke Niwa

On Apr 22, 2014, at 10:22 AM, Dimitri Glazkov dglaz...@chromium.org wrote:

 
 
 
 On Thu, Apr 17, 2014 at 2:42 AM, Ryosuke Niwa rn...@apple.com wrote:
 Review: Template Inheritance in the Current Specification
 
 In the current specification, a super class doesn't define any hooks for 
 subclasses.  Instead, it defines insertion points into which nodes from the 
 original DOM (light DOM) is inserted, and then subclasses use shadow 
 element to replace elements that get distributed into superclass's insertion 
 points.
 
 Consider my-card element used as follows:
   my-card
   span class=nameRyosuke Niwa/span
   span class=emailrn...@apple.com/span
   /my-card
 
 Suppose this element's shadow DOM looks like this:
 Name: content select=.name/content
 Email: content select=.email/content
 
 Then in the composed tree, the first span is distributed into the first 
 content element and the second span is distributed into the second content 
 element as follows:
   my-card
 !-- shadow root begin --
 Name: content select=.name
   !-- distribution begin --
   span class=nameRyosuke Niwa/span
   !-- distribution end --
 /content
 Email: content select=.email
   !-- distribution begin --
   span class=emailrn...@apple.com/span
   !-- distribution end --
   /content
 !-- shadow root end --
   /my-card
 
 If I had my-webkitten-card that always as WebKitten as a name that inherits 
 from my-card, its shadow DOM may look like this:
   shadow
 span class=nameWebKitten/span
 content/content
 span class=emailkit...@webkit.org/span
   /shadow
 
 If I had an instance of my-webkitten-card as follows:
   my-webkitten-card
   span class=nameRyosuke Niwa/span
   span class=emailrn...@webkit.org/span
   /my-webkitten-card
 
 Then its composed tree will look like this:
   my-webkitten-card
 !-- my-webkitten-card's shadow root begin --
   shadow
   !-- my-card's shadow root begin --
   Name: content select=.name
 !-- distribution begin --
 span class=nameWebKitten/span
 span class=nameRyosuke Niwa/span
 !-- distribution end --
   /content
   Email: content select=.email
 !-- distribution begin --
 span class=emailrn...@webkit.org/span
 span class=emailkit...@webkit.org/span
 !-- distribution end --
   /content
   !-- my-card's shadow root end --
 /shadow
 !-- my-webkitten-card's shadow root end --
   /my-webkitten-card
 
 Here, my-card's shadow DOM was inserted into where the shadow element existed 
 in my-webkitten-card's shadow DOM, and the insertion points inside my-card's 
 shadow DOM got nodes distributed from shadow element's children including 
 nodes inside content element.  If we didn't have the content element inside 
 my-webkitten-card with name and email classes, then we would only see 
 WebKitten and kit...@webkit.org distributed into my-card's insertion points 
 as in:
 
   my-webkitten-card
 !-- my-webkitten-card's shadow root begin --
 shadow
   !-- my-card's shadow root begin --
   Name:
   content select=.name
 !-- distribution begin --
   span class=nameWebKitten/span
 !-- distribution end --
   /content
   Email:
   content select=.email
 !-- distribution begin --
   span class=emailkit...@webkit.org/span
 !-- distribution end --
   /content
   !-- my-card's shadow root end --
 /shadow
 !-- my-webkitten-card's shadow root end --
   /my-webkitten-card
 
 Separating Transclusion Mechanisms for Inheritance and Data Binding
 
 The current model mixes data binding and inheritance if we consider 
 distributing nodes from the light DOM as a form of data binding.  Namely, 
 distributing nodes from my-card's or my-webkitten-card's light DOM is data 
 binding where the data model is DOM whereas distributing nodes from 
 my-webkitten-card's shadow element into my-card's insertion points is an 
 inheritance hook.
 
 Furthermore, the transclusion mechanism for inheritance happens backwards.  
 Instead of a superclass defining a transclusion points for its subclasses to 
 use, the subclasses are overriding the meaning of insertion points in the 
 superclass by injecting nodes.  This is how existing JS libraries and 
 frameworks do template inheritance.
 
 For example, the following two JS template libraries that support inheritance 
 both allow superclass template to define named blocks that could be 
 overridden by subclass templates:
 http://paularmstrong.github.io/swig/docs/#inheritance
 http://jlongster.github.io/nunjucks/templating.html#template-inheritance
 
 An example from Nunjucks:
 If we have a template parent.html that looks like this:
 
 {% block header %}
 This is the default content
 {% endblock %}
 
 section class=left
   {% block left %}{% endblock %}
 /section
 
 section class=right
   {% block right %}
   This is more content
   {% endblock %}
 

Re: Separating Transclusion Mechanisms for Inheritance and Data Binding

2014-04-27 Thread Ryosuke Niwa
On Apr 22, 2014, at 10:13 AM, Dimitri Glazkov dglaz...@chromium.org wrote:
 On Thu, Apr 17, 2014 at 2:42 AM, Ryosuke Niwa rn...@apple.com wrote:
 Review: Template Inheritance in the Current Specification
 
 In the current specification, a super class doesn't define any hooks for 
 subclasses.  Instead, it defines insertion points into which nodes from the 
 original DOM (light DOM) is inserted, and then subclasses use shadow 
 element to replace elements that get distributed into superclass's insertion 
 points.
 
 Consider my-card element used as follows:
   my-card
   span class=nameRyosuke Niwa/span
   span class=emailrn...@apple.com/span
   /my-card
 
 Suppose this element's shadow DOM looks like this:
 Name: content select=.name/content
 Email: content select=.email/content
 
 Then in the composed tree, the first span is distributed into the first 
 content element and the second span is distributed into the second content 
 element as follows:
   my-card
 !-- shadow root begin --
 Name: content select=.name
   !-- distribution begin --
   span class=nameRyosuke Niwa/span
   !-- distribution end --
 /content
 Email: content select=.email
   !-- distribution begin --
   span class=emailrn...@apple.com/span
   !-- distribution end --
   /content
 !-- shadow root end --
   /my-card
 
 If I had my-webkitten-card that always as WebKitten as a name that inherits 
 from my-card, its shadow DOM may look like this:
   shadow
 span class=nameWebKitten/span
 content/content
 span class=emailkit...@webkit.org/span
   /shadow
 
 If I had an instance of my-webkitten-card as follows:
   my-webkitten-card
   span class=nameRyosuke Niwa/span
   span class=emailrn...@webkit.org/span
   /my-webkitten-card
 
 Then its composed tree will look like this:
   my-webkitten-card
 !-- my-webkitten-card's shadow root begin --
   shadow
   !-- my-card's shadow root begin --
   Name: content select=.name
 !-- distribution begin --
 span class=nameWebKitten/span
 span class=nameRyosuke Niwa/span
 !-- distribution end --
   /content
   Email: content select=.email
 !-- distribution begin --
 span class=emailrn...@webkit.org/span
 span class=emailkit...@webkit.org/span
 !-- distribution end --
   /content
   !-- my-card's shadow root end --
 /shadow
 !-- my-webkitten-card's shadow root end --
   /my-webkitten-card
 
 Here, my-card's shadow DOM was inserted into where the shadow element existed 
 in my-webkitten-card's shadow DOM, and the insertion points inside my-card's 
 shadow DOM got nodes distributed from shadow element's children including 
 nodes inside content element.  If we didn't have the content element inside 
 my-webkitten-card with name and email classes, then we would only see 
 WebKitten and kit...@webkit.org distributed into my-card's insertion points 
 as in:
 
   my-webkitten-card
 !-- my-webkitten-card's shadow root begin --
 shadow
   !-- my-card's shadow root begin --
   Name:
   content select=.name
 !-- distribution begin --
   span class=nameWebKitten/span
 !-- distribution end --
   /content
   Email:
   content select=.email
 !-- distribution begin --
   span class=emailkit...@webkit.org/span
 !-- distribution end --
   /content
   !-- my-card's shadow root end --
 /shadow
 !-- my-webkitten-card's shadow root end --
   /my-webkitten-card
 
 Can you help me understand the problems you illustrated with the examples 
 better? What's the desired behavior? Where does the problem arise? This is 
 both for my-webkitten-card and for random-element examples. I would love to 
 have these to start chewing on them.

Sorry, maybe my description wasn't clear.  This example doesn't demonstrate any 
issues.  I was simply describing what the current specification does.

- R. Niwa



Re: Separating Transclusion Mechanisms for Inheritance and Data Binding

2014-04-27 Thread Ryosuke Niwa
On Apr 22, 2014, at 10:46 AM, Dimitri Glazkov dglaz...@chromium.org wrote:

 BTW, here's a jsbin that implements yield/transclude using existing Shadow 
 DOM plumbing:
 
 http://jsbin.com/pacim/1/edit


Thanks for an example.  That indeed polyfills the API we're proposing in terms 
of the currently spec'ed API.

One important aspect of our proposal is to avoid having to rely on shadowRoot 
property on HTMLElement, which wouldn't exist in Type III encapsulation.

On Apr 22, 2014, at 11:06 AM, Dimitri Glazkov dglaz...@chromium.org wrote:

 Here's a jsbin that uses the shadow-as-function syntax and does the same 
 thing:
 
 http://jsbin.com/peqoz/2/edit

This one doesn't quite work as intended in that the insertion points in 
MyCardElement's shadow DOM could grab nodes from the light DOM.

- R. Niwa



Re: Separating Transclusion Mechanisms for Inheritance and Data Binding

2014-04-22 Thread Dimitri Glazkov
On Thu, Apr 17, 2014 at 2:42 AM, Ryosuke Niwa rn...@apple.com wrote:

 *Review: Template Inheritance in the Current Specification*

 In the current specification, a super class doesn't define any hooks for
 subclasses.  Instead, it defines insertion points into which nodes from the
 original DOM (light DOM) is inserted, and then subclasses use shadow
 element to replace elements that get distributed into superclass's
 insertion points.

 Consider my-card element used as follows:
   my-card
   span class=nameRyosuke Niwa/span
   span class=emailrn...@apple.com/span
   /my-card

 Suppose this element's shadow DOM looks like this:
 Name: content select=.name/content
 Email: content select=.email/content

 Then in the composed tree, the first span is distributed into the first
 content element and the second span is distributed into the second content
 element as follows:
   my-card
 !-- shadow root begin --
 Name: content select=.name
   !-- distribution begin --
   span class=nameRyosuke Niwa/span
   !-- distribution end --
 /content
 Email: content select=.email
   !-- distribution begin --
   span class=emailrn...@apple.com/span
   !-- distribution end --
   /content
 !-- shadow root end --
   /my-card

 If I had my-webkitten-card that always as WebKitten as a name that
 inherits from my-card, its shadow DOM may look like this:
   shadow
 span class=nameWebKitten/span
 content/content
 span class=emailkit...@webkit.org/span
   /shadow

 If I had an instance of my-webkitten-card as follows:
   my-webkitten-card
   span class=nameRyosuke Niwa/span
   span class=emailrn...@webkit.org/span
   /my-webkitten-card

 Then its composed tree will look like this:
   my-webkitten-card
 !-- my-webkitten-card's shadow root begin --
   shadow
   !-- my-card's shadow root begin --
   Name: content select=.name
 !-- distribution begin --
 span class=nameWebKitten/span
 span class=nameRyosuke Niwa/span
 !-- distribution end --
   /content
   Email: content select=.email
 !-- distribution begin --
 span class=emailrn...@webkit.org/span
 span class=emailkit...@webkit.org/span
 !-- distribution end --
   /content
   !-- my-card's shadow root end --
 /shadow
 !-- my-webkitten-card's shadow root end --
   /my-webkitten-card

 Here, my-card's shadow DOM was inserted into where the shadow element
 existed in my-webkitten-card's shadow DOM, and the insertion points inside
 my-card's shadow DOM got nodes distributed from shadow element's children
 including nodes inside content element.  If we didn't have the content
 element inside my-webkitten-card with name and email classes, then we
 would only see WebKitten and kit...@webkit.org distributed into my-card's
 insertion points as in:

   my-webkitten-card
 !-- my-webkitten-card's shadow root begin --
 shadow
   !-- my-card's shadow root begin --
   Name:
   content select=.name
 !-- distribution begin --
   span class=nameWebKitten/span
 !-- distribution end --
   /content
   Email:
   content select=.email
 !-- distribution begin --
   span class=emailkit...@webkit.org/span
 !-- distribution end --
   /content
   !-- my-card's shadow root end --
 /shadow
 !-- my-webkitten-card's shadow root end --
   /my-webkitten-card


Can you help me understand the problems you illustrated with the examples
better? What's the desired behavior? Where does the problem arise? This is
both for my-webkitten-card and for random-element examples. I would love to
have these to start chewing on them.

:DG


Re: Separating Transclusion Mechanisms for Inheritance and Data Binding

2014-04-22 Thread Dimitri Glazkov
On Thu, Apr 17, 2014 at 2:42 AM, Ryosuke Niwa rn...@apple.com wrote:

 *Review: Template Inheritance in the Current Specification*

 In the current specification, a super class doesn't define any hooks for
 subclasses.  Instead, it defines insertion points into which nodes from the
 original DOM (light DOM) is inserted, and then subclasses use shadow
 element to replace elements that get distributed into superclass's
 insertion points.

 Consider my-card element used as follows:
   my-card
   span class=nameRyosuke Niwa/span
   span class=emailrn...@apple.com/span
   /my-card

 Suppose this element's shadow DOM looks like this:
 Name: content select=.name/content
 Email: content select=.email/content

 Then in the composed tree, the first span is distributed into the first
 content element and the second span is distributed into the second content
 element as follows:
   my-card
 !-- shadow root begin --
 Name: content select=.name
   !-- distribution begin --
   span class=nameRyosuke Niwa/span
   !-- distribution end --
 /content
 Email: content select=.email
   !-- distribution begin --
   span class=emailrn...@apple.com/span
   !-- distribution end --
   /content
 !-- shadow root end --
   /my-card

 If I had my-webkitten-card that always as WebKitten as a name that
 inherits from my-card, its shadow DOM may look like this:
   shadow
 span class=nameWebKitten/span
 content/content
 span class=emailkit...@webkit.org/span
   /shadow

 If I had an instance of my-webkitten-card as follows:
   my-webkitten-card
   span class=nameRyosuke Niwa/span
   span class=emailrn...@webkit.org/span
   /my-webkitten-card

 Then its composed tree will look like this:
   my-webkitten-card
 !-- my-webkitten-card's shadow root begin --
   shadow
   !-- my-card's shadow root begin --
   Name: content select=.name
 !-- distribution begin --
 span class=nameWebKitten/span
 span class=nameRyosuke Niwa/span
 !-- distribution end --
   /content
   Email: content select=.email
 !-- distribution begin --
 span class=emailrn...@webkit.org/span
 span class=emailkit...@webkit.org/span
 !-- distribution end --
   /content
   !-- my-card's shadow root end --
 /shadow
 !-- my-webkitten-card's shadow root end --
   /my-webkitten-card

 Here, my-card's shadow DOM was inserted into where the shadow element
 existed in my-webkitten-card's shadow DOM, and the insertion points inside
 my-card's shadow DOM got nodes distributed from shadow element's children
 including nodes inside content element.  If we didn't have the content
 element inside my-webkitten-card with name and email classes, then we
 would only see WebKitten and kit...@webkit.org distributed into my-card's
 insertion points as in:

   my-webkitten-card
 !-- my-webkitten-card's shadow root begin --
 shadow
   !-- my-card's shadow root begin --
   Name:
   content select=.name
 !-- distribution begin --
   span class=nameWebKitten/span
 !-- distribution end --
   /content
   Email:
   content select=.email
 !-- distribution begin --
   span class=emailkit...@webkit.org/span
 !-- distribution end --
   /content
   !-- my-card's shadow root end --
 /shadow
 !-- my-webkitten-card's shadow root end --
   /my-webkitten-card

 *Separating Transclusion Mechanisms for Inheritance and Data Binding*

 The current model mixes data binding and inheritance if we consider
 distributing nodes from the light DOM as a form of data binding.  Namely,
 distributing nodes from my-card's or my-webkitten-card's light DOM is data
 binding where the data model is DOM whereas distributing nodes from
 my-webkitten-card's shadow element into my-card's insertion points is an
 inheritance hook.

 Furthermore, the transclusion mechanism for inheritance happens backwards.
  Instead of a superclass defining a transclusion points for its subclasses
 to use, the subclasses are overriding the meaning of insertion points in
 the superclass by injecting nodes.  This is how existing JS libraries and
 frameworks do template inheritance.

 For example, the following two JS template libraries that support
 inheritance both allow superclass template to define named blocks that
 could be overridden by subclass templates:
 http://paularmstrong.github.io/swig/docs/#inheritance
 http://jlongster.github.io/nunjucks/templating.html#template-inheritance

 An example from Nunjucks:

 If we have a template parent.html that looks like this:

 {% block header %}This is the default content{% endblock %}
 section class=left  {% block left %}{% endblock %}/section
 section class=right  {% block right %}  This is more content  {% endblock 
 %}/section

 And we render this template:

 {% extends parent.html %}
 {% block left %}This is the left side!{% endblock %}
 {% block right 

Re: Separating Transclusion Mechanisms for Inheritance and Data Binding

2014-04-22 Thread Dimitri Glazkov
BTW, here's a jsbin that implements yield/transclude using existing Shadow
DOM plumbing:

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

:DG


Re: Separating Transclusion Mechanisms for Inheritance and Data Binding

2014-04-22 Thread Dimitri Glazkov
Here's a jsbin that uses the shadow-as-function syntax and does the same
thing:

http://jsbin.com/peqoz/2/edit

:DG


On Tue, Apr 22, 2014 at 10:46 AM, Dimitri Glazkov dglaz...@chromium.orgwrote:

 BTW, here's a jsbin that implements yield/transclude using existing Shadow
 DOM plumbing:

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

 :DG



Re: Separating Transclusion Mechanisms for Inheritance and Data Binding

2014-04-22 Thread Erik Bryn
*claps for sharing JSBin*

Would love to see more of this on public-webapps when possible :)


On Tue, Apr 22, 2014 at 10:46 AM, Dimitri Glazkov dglaz...@chromium.orgwrote:

 BTW, here's a jsbin that implements yield/transclude using existing Shadow
 DOM plumbing:

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

 :DG