Hi Allen,

Fortunately the state of this is pretty close to what you are suggesting.
We started of with the imperative solution and then went to look at a
declarative version. At this point, the discussion got a bit side tracked.
Lets back up and see what we have for the imperative version:

class MyElement extends HTMLElement {
  constructor() {
    ...
  }
  insertedCallback() {
    // now I'm in document
  }
  attributeChangedCallback(name, value) {
    // ...
  }
  doFunkyThing() {
    // ...
  }
}

// And tell the browser about this new shiny element
document.register('my-element, MyElement);

Fast forward...

For the declarative version we want to be able to associate a <template>
element to be used as the shadow dom for the custom element. We went around
in circles here and this thread was an attempt to start at a different
starting point to see where we would end up.

We initially had (plus/minus irrelevant details)

<element name="my-element">
  <template>
    This is my shadow DOM
    <content></content>
  </template>
  <script>
    class MyElement extends HTMLElement { ... }
    // We need a convenient way to register ('my-element, MyElement) here
  </script>
</element>

More inline...

On Thu, Apr 11, 2013 at 2:14 AM, Allen Wirfs-Brock <al...@wirfs-brock.com>wrote:

>
> On Apr 10, 2013, at 8:47 PM, Rick Waldron wrote:
>
> > cc Allen Wirfs-Brock, Dave Herman
> >
> > Allen, Dave
> >
> > Would you mind reading back through the  thread to provide some deeper
> insight? Thanks
> >
> > Rick
> >
>
> ECMAScript really has a very simply concept of 'this' out-side of a
> function.  It is a reference to the global object.  In all other cases
> 'this' occurs within a function body and is bound as part of a function
> innovation.  It would be a significant change to the ECMAScript semantics
> that are applied to 'this' the content of <script> tags.  I'm sure, it
> would only cause confusion.
>

Unfortunately NodeJS broke this invariant already. `this` inside a module
that has been required is a not the [[Global]] object. This has caused me a
lot of personal porting pain so I agree we must not break this invariant on
the web.


> I'm not at all up on the details and subtitles of what you are trying to
> do with your tempaltes, but regardless, I want to suggest an alternative
> approach that I'm pretty sure in the long run would be more natural for
> JavaScript programmers.
>
> It seems to me, what you are doing with templates is allowing user to
> define new kinds of DOM nodes and that when you "stamp out"  a template you
> are instantiating new instances of that kind of node.  In programming
> language terms, you are enabling markup authors to declarative define new
> "classes" of DOM nodes and to create instance of those classes.  The script
> behaviors you need to associate with a template are essentially the
> "methods" of the user defined classes.  Rather than twisting around the
> interpretation of 'this' in template script blocks and inventing other
> one-off extensions, it would be much better to recognize this class-based
> approach and just let the user define the class.
>
> Using ES6 syntax this could be very easy:
>
> <template bindtotagname="my_yay">
>     <shadowroot>
>         <div>Yay!</div>
>     </shadowroot>
>     <script>
>         class My_yay extends TemplatedNode {
>               constructor () {
>                      // runs when instances are created, can create per
> instance properties
>                      //  can be left out if nothing special is required
>                      }
>                whenBond(...args) {
>                       super(...args);   invoke default behavior inherited
> from TemplatedNode
>                       // my_yay specific behavior
>                       // in methods 'this' binds to an instance
>                      }
>                 anotherMethods() {  // other instance methods, properties
> of My_yay.prototype
>                      }
>                 static  anotherStaticMethods() { }  //properties of My_yay
>           }
>      </script>
> </template>
>
> Many details to work out, but I hope the intent is clear.  You just define
> a JS class corresponding to the template instances. There may be a standard
> template interface with methods such as withBond that are support.  Defaut
> implementations can be provided by a built-in super class.
>
> This can all be expresses, but less clearly and concisely using ES3/5
> syntax.  But since we are talking about a new HTML feature, I'd recommend
> being the first major HTMLfeature to embrace ES6 class syntax.  The class
> extension in ES6 are quite stable and quite easy to implement.  I'm pretty
> sure they will begin appearing in browsers sometime in the next 6 months.
> If webcomponents takes a dependency upon them, it would probably further
> speed up their implementation.
>

The problem here is how do you register `My_yay` as the class that goes
with the tag name `my_yay`. One option could be to use the completion value
but it seems too magical/unreliable. It also does not scale well. I would
like us to be able to put all custom component classes in a single js file:

<element name="my-foo">
  ...
</element>
<element name="my-bar">
  ...
</element>
<element name="my-baz">
  ...
</element>
<script src="my-elements.js></script>

// my-elements.js
someDocument.querySelector('[name=my-foo]').registerConstructor(MyFoo);
someDocument.querySelector('[name=my-bar]').registerConstructor(MyBar);
someDocument.querySelector('[name=my-baz]').registerConstructor(MyBaz);


This calls out for a less verbose and more DRY API.

-- 
erik

Reply via email to