A user account is required in order to edit this wiki, but we've had to disable public user registrations due to spam.

To request an account, ask an autoconfirmed user on Chat (such as one of these permanent autoconfirmed members).

Component Model Strawman: Element Registration: Difference between revisions

From WHATWG Wiki
Jump to navigation Jump to search
Line 80: Line 80:


</pre>
</pre>
The <tt>create</tt> callback can also be set by the <tt>create</tt> attribute on <tt>element</tt> element. The attribute value is invoked as an expression and
should return a function object.
The returned function object is set to  <code>create</code> property of the
<tt>element</tt> element.
<pre>
<head>
  <element name="x-comment"
    create="function() { new HTMLElement('x-comment'); }">
  </element>
</head>
</pre>


If the callback function has <tt>HTMLElement</tt> in its prototype chain,
If the callback function has <tt>HTMLElement</tt> in its prototype chain,
Line 121: Line 105:


     HTMLRegistrationElement.current.create = function() { return new Comment(); };
     HTMLRegistrationElement.current.create = function() { return new Comment(); };
    </script>
  </element>
<!-- Markup 3 -->
  <element name="x-comment" create="Comment">
    <script>
    class Comment : HTMLElement {
      ....
    };
     </script>
     </script>
   </element>
   </element>
Line 150: Line 125:
     HTMLRegistrationElement.current.create = function() {
     HTMLRegistrationElement.current.create = function() {
       return new HTMLElement(element.name);
       return new HTMLElement(element.name);
    };
    </script>
  </element>
</pre>
=== The <tt>create</tt> attribute ===
A <tt>create</tt> callback can also be set by the <tt>create</tt> attribute on <tt>element</tt> element.
Once the attribute value is set, that is invoked as an expression.
The expression should return a function object.
And the returned function object is set to  <code>create</code> property of the <tt>element</tt> element.
<pre>
<head>
  <element name="x-comment"
    create="function() { new HTMLElement('x-comment'); }">
  </element>
</head>
</pre>
This is especially useful if you have a class-style constructor. It can be given like this.
<pre>
  <element name="x-comment" create="Comment">
    <script>
    class Comment : HTMLElement {
      ....
     };
     };
     </script>
     </script>

Revision as of 18:59, 27 October 2011

Overview

With the Element Registration mechanism. page authors can tell new element names and its behavior to agents.

The element element and HTMLRegistrationElement

The HTMLRegistrationElement represents an author-registered element definition.

Here is the simplest example which registeres an element named "x-comment" whose instance implements HTMLElement


// Imperative API
var element = document.createElement("element");
element.name = "x-comment";
document.head.appendChild(element);
// Shorter form.
HTMLRegistrationElement.register("x-comment");

<!-- Markup API -->
<head>
  <element name="x-comment"></element>
</head>

Scripting

The script element

The element element allows script elements in its children. These script blocks are evaluated over a global object. Before the evaluation, HTMLRegistrationElement.current is set to the enclosing element element. These script blocks can be used for providing lifecycle callback definitions for the registering element.


<head>
  <element name="x-comment">
    <script>
     var shouldBeXComment = HTMLRegistrationElement.current.name;
    <script>
  </element>
</head>

The create callback

The HTMLRegistrationElement provide a pair of lifecycle callbacks for the element instance creation including the tree construction.

The first callback, create is invoked when an agent need a new element instance of the registered element. create callback should return new element instance which matches the registered element specification.


// Imperative API
var element = document.createElement("element");
element.name = "x-comment";
element.create = function() { return new HTMLElement("x-comment"); };
document.head.appendChild(element);
// Shorter form.
HTMLRegistrationElement.register("x-comment", function() { ... });

<!-- Markup API -->
<head>
  <element name="x-comment">
    <script>
    HTMLRegistrationElement.current.create = function() {
      return new HTMLElement("x-comment");
    };
    </script>
  </element>
</head>

If the callback function has HTMLElement in its prototype chain, it is invoked as a constructor. Thus following three markup and one imperative examples have same meaning.


<!-- Markup 1 -->
  <element name="x-comment">
    <script>
    class Comment : HTMLElement {
       ....
    };

    HTMLRegistrationElement.current.create = Comment;
    </script>
  </element>

<!-- Markup 2 -->
  <element name="x-comment">
    <script>
    class Comment : HTMLElement {
       ....
    };

    HTMLRegistrationElement.current.create = function() { return new Comment(); };
    </script>
  </element>

// Imperative
class Comment : HTMLElement {
  ...
};

HTMLRegistrationElement.register("x-comment", Comment);

If no create callback is given, its default behavior is something like this:


  <element name="x-comment">
    <script>
    var element = this;
    HTMLRegistrationElement.current.create = function() {
      return new HTMLElement(element.name);
    };
    </script>
  </element>

The create attribute

A create callback can also be set by the create attribute on element element. Once the attribute value is set, that is invoked as an expression. The expression should return a function object. And the returned function object is set to create property of the element element.


<head>
  <element name="x-comment" 
    create="function() { new HTMLElement('x-comment'); }">
  </element>
</head>

This is especially useful if you have a class-style constructor. It can be given like this.


  <element name="x-comment" create="Comment">
    <script>
    class Comment : HTMLElement {
       ....
    };
    </script>
  </element>

The setup callback

The second lifecycle callback, setup is called after an instance creation. If the instance is created by the agent's tree construction, it will be called as a part of the "close" phase. On setup, the attributes and child elements for the element are already set by the agent. So this callback is useful for building its visual like the shadow tree.


// Imperative API
var element = document.createElement("element");
...
element.setup = function() {
  this.shadow = new ShadowRoot(this);
  ...;
};
...

<!-- Markup API -->
<head>
  <element name="x-comment">
    <script>
     ...
     HTMLRegistrationElement.current.setup = function() {
       // "this" points the newly created element instance.
       this.shadow = new ShadowRoot(this); 
       ...;
     };
    </script>
  </element>
</head>

If no setup callback is given by the author, agent invokes the default behavior. It is something like this:

function defaultSetup() {
  if (this.setup instanceof Function)
    this.setup();
}

So if we define setup for the registered element, it will be called as a setup callback.


 <element name="x-comment" create="Comment">
   <script>
   class Comment : HTMLElement {
     setup(shadow) {
       // should be called.
     }
   }
   </script>
 </element>

Styling

The element element also allows the style element as its children. The style given by the element is a part of document stylesheet. Authors can use the style element to provide the style for the registering element.



<head>
  <element name="x-comment">
    <style>
    x-comment {
       color: gray;
    }
    </style>
  </element>
</head>

Shadow Tree Construction and the template element

The element element helps to construct a shadow tree for newly created elements. If element element has a template element as its child, The agent creates shadow tree from the template element before invoking the setup callback, then invokes it with the shadow root.


<!-- Markup API -->
<head>
  <element name="x-comment">
    <template>
      <div>...</div>
    </template>
    <script>
     ...
     HTMLRegistrationElement.current.setup = function(shadow) {
       // setup using the shadow instance.
     };
    </script>
  </element>
</head>

HTMLRegistrationElement interface

[Callback=AcceptConstructor]
interface HTMLRegistrationCreateCallback {
 HTMLElement create();
};

[Callback]
interface HTMLRegistrationSetupCallback {
 void setup(ShadowRoot shadow = null);
};

[Constructor]
interface HTMLRegistrationElement {
  attribute String name;
  attribute HTMLRegistrationCreateCallback create;
  attribute HTMLRegistrationSetupCallback setup;
};