| 
				   | 
				
| Line 14: | 
Line 14: | 
 | * Not component-specific, could be used for workers, <code><iframes></code>, intents  |  | * Not component-specific, could be used for workers, <code><iframes></code>, intents  | 
 | * Same definitions can be used cross-language (not limited to JavaScript)  |  | * Same definitions can be used cross-language (not limited to JavaScript)  | 
 | 
  |  | 
 | = Example =
  |  | 
 | 
  |  | 
 | The following could be the IDL declaration for a contact in a contact list. User-defined names MUST start with an upper case letter.
  |  | 
 | 
  |  | 
 |   <idl name="Contact" type="object">
  |  | 
 |             <property name="firstName" type="string" optional/>
  |  | 
 |             <property name="lastName" type="string" optional/>
  |  | 
 |             <property name="name" type="string" get="getName"/>
  |  | 
 |             <property name="phone" type="string" optional/>
  |  | 
 |             <property name="email" type="string" optional/>
  |  | 
 |   </idl>
  |  | 
 | 
  |  | 
 | The contact list itself can make use of this type:
  |  | 
 | 
  |  | 
 |   <idl name="ContactList" type="interface">
  |  | 
 |       <function name="addContact" type="unsigned long"> <!-- returns index -->
  |  | 
 |           <param name="contact" type="Contact" throws="OUT_OF_BOUNDS_EXCEPTION"/>
  |  | 
 |           <param name="index" type="unsigned integer" optional/>
  |  | 
 |       </function>
  |  | 
 |       <function name="removeContact" type="unsigned long" throws="OUT_OF_BOUNDS_EXCEPTION"> <!-- requires index, throws if out of bounds -->
  |  | 
 |           <param name="index" type="unsigned integer">
  |  | 
 |       </function>
  |  | 
 |       <function name="clear" type="void"/>
  |  | 
 |       <property name="selectedIndex" type="unsigned integer" get set throws="OUT_OF_BOUNDS_EXCEPTION"/>
  |  | 
 |   </idl>
  |  | 
 | 
  |  | 
 | Also, setting up a user-defined event to communicate between a contact and a contact list:
  |  | 
 | 
  |  | 
 |   <idl name="ContactSelectedEvent" type="event">
  |  | 
 |       <property name="index" type="unsigned integer"/>
  |  | 
 |   </idl>
  |  | 
 | 
  |  | 
 | Using the above types, we declare a component that implements a single contact:
  |  | 
 | 
  |  | 
 |   <element name="x-contact" class="ContactElement">
  |  | 
 |       <implements idl="Contact"/>
  |  | 
 |       <events>
  |  | 
 |           <listen type="click"/>
  |  | 
 |           <emit type="ContactSelectedEvent"/>
  |  | 
 |       <events>
  |  | 
 |       <script type="javascript">
  |  | 
 |           function onclick() { dispatchEvent(new ContactSelectedEvent()); }
  |  | 
 |           get name() { var s = ""; if (firstName) s = firstName; if (s && lastName) s += " "; if (lastName) s += lastName; return lastName; }
  |  | 
 |       </script>
  |  | 
 |       <template>
  |  | 
 |           <div>
  |  | 
 |               ... nicely formatted contact here ...
  |  | 
 |           </div>
  |  | 
 |       </template>
  |  | 
 |   </element>
  |  | 
 | 
  |  | 
 | ... and an element that handles the whole list:
  |  | 
 | 
  |  | 
 |   <element name="x-contactlist" class="ContactListElement">
  |  | 
 |       <implements idl="ContactList"/>
  |  | 
 |       <events>
  |  | 
 |           <listen type="ContactSelectedEvent"/>
  |  | 
 |       <events>
  |  | 
 |       <script type="javascript">
  |  | 
 |           function onContactSelectedEvent(evt) {
  |  | 
 |           }
  |  | 
 |           function addContact(contact, index) {
  |  | 
 |               appendChild(new ContactElement());
  |  | 
 |           }
  |  | 
 |           function removeContact(index) {
  |  | 
 |               ...
  |  | 
 |           }
  |  | 
 |           function clear(evt) {
  |  | 
 |               ...
  |  | 
 |           }
  |  | 
 |       </script>
  |  | 
 |       <template>
  |  | 
 |           <div>
  |  | 
 |               ... nicely formatted contact list here, consisting of <x-contact> elements ...
  |  | 
 |           </div>
  |  | 
 |       </template>
  |  | 
 |   </element>
  |  | 
 | 
  |  | 
 | <span style="color: darkred">'''ISSUE:'''</span> Avoid the complexity of [https://developer.mozilla.org/en/XBL/XBL_1.0_Reference/Elements#handler XBL1's <code>handler</code> element]!
  |  | 
 | 
  |  | 
 | == Conversion Example ==
  |  | 
 | 
  |  | 
 | The above could be converted to the following boilerplate by the browser, in the case of confined components:
  |  | 
 | 
  |  | 
 | === Document side ===
  |  | 
 | 
  |  | 
 |   class Contact
  |  | 
 |   {
  |  | 
 |     firstName: null,
  |  | 
 |     lastName: null,
  |  | 
 |     phone: null,
  |  | 
 |     email: null,
  |  | 
 |   }
  |  | 
 | 
  |  | 
 |   class ContactElement
  |  | 
 |   {
  |  | 
 |     constructor() {
  |  | 
 |       HTMLElement.call(this);
  |  | 
 |       addEventListener('click', onclick);
  |  | 
 |     }
  |  | 
 |     function addContact(contact, index) { /* native implementation, calling addContact on the shadow tree, return value is deferred */ }
  |  | 
 |     function removeContact(index) { /* native implementation, calling removeContact on the shadow tree */ }
  |  | 
 |     function clear() { /* native implementation, calling clear on the shadow tree */ }
  |  | 
 |     get selectedIndex() { /* native implementation, calling the getter for selectedIndex on the shadow tree, return value is deferred */ }
  |  | 
 |     set selectedIndex(value) { /* native implementation, calling the setter for selectedIndex on the shadow tree */ }
  |  | 
 |   }
  |  | 
 |   Element.register('x-contact', ContactElement);
  |  | 
 | 
  |  | 
 | 
  |  | 
 |   class ContactListElement
  |  | 
 |   {
  |  | 
 |     constructor() {
  |  | 
 |       HTMLElement.call(this);
  |  | 
 |     }
  |  | 
 |     function addContact(contact, index) { /* native implementation, calling addContact on the shadow tree, return value is deferred */ }
  |  | 
 |     function removeContact(index) { /* native implementation, calling removeContact on the shadow tree */ }
  |  | 
 |     function clear() { /* native implementation, calling clear on the shadow tree */ }
  |  | 
 |     get selectedIndex() { /* native implementation, calling the getter for selectedIndex on the shadow tree, return value is deferred */ }
  |  | 
 |     set selectedIndex(value) { /* native implementation, calling the setter for selectedIndex on the shadow tree */ }
  |  | 
 |   }
  |  | 
 |   Element.register('x-contact', ContactElement);
  |  |