Html Components(htc) Information

29/07/2009 10:30

HTML Components

Componentizing Web Applications

This version:
http://www.w3.org/TR/1998/NOTE-HTMLComponents-19981023
Latest version:
http://www.w3.org/TR/NOTE-HTMLComponents
Editor:
Chris Wilson (Microsoft)
Additional contributors:
Dave Massy (Microsoft)
Sara Williams (Microsoft)
Rebecca Norlander (Microsoft)
Lanie Kurata (Microsoft)
Thomas Reardon (Microsoft)

Status of This Document

This document is a submission to the World Wide Web Consortium (see Submission Request, W3C Staff Comment). It is intended for review and comment by W3C members.

This document is a NOTE made available by the W3 Consortium for discussion only. This indicates no endorsement of its content, nor that the Consortium has, is, or will be allocating any resources to the issues addressed by this NOTE.

Abstract

The growth of HTML with scripting as an application platform has exploded recently.   One limiting factor of this growth is that there is no way to formalize the services that an HTML application can provide, or to allow them to be reused as components in another HTML page or application.  HTML Components address this shortcoming; an HTML Component (HTC for short) provides a mechanism for reusable encapsulation of a component implemented in HTML, stylesheets and script.

Componentization is a powerful paradigm that allows component users to build applications using 'building blocks' of functionality without having to implement those building blocks themselves, or necessarily understand how the building works in fine detail.  This method makes building complex applications easier by breaking them down into more manageable chunks and allowing the building blocks to be reused in other applications.  HTML Components brings this powerful development method to Web applications. 


Contents

  1. Overview
  2. Component Architecture - the <COMPONENT> Element
  3. Defining Properties - the <PROPERTY> Element
  4. Defining Methods - the <METHOD> Element
  5. Defining Events - the <EVENT> Element
  6. Attaching Events with the <ATTACH> Element
  7. Component-specific Events and Object Model
  8. Linking Components to HTML Elements
  9. Example

1. Overview

To develop Web applications today, a site designer frequently must write a large amount of script to achieve desired dynamic effects.  These scripts are typically hard-wired to the particular page; if the content of the page changes, the scripts may have to be rewritten, since there is no way of abstracting one from the other.  HTML Components provide this ability. 

An HTML Component is essentially just an HTML page wrapped up in some special descriptors that define what properties and methods are exposed by the Component, and what events are defined by and attached to by the HTC.  In order to provide an easy path for HTML developers to move to developing components, an HTC is literally a normal HTML file with a few defined XML elements inserted in the document.  This gives an easy and consistent migration path for existing HTML applications.

HTML Components are useful in a number of situations - one use is associating an HTML Component with a particular element in an HTML page, and allowing the Component to provide the event handling, firing of custom events and other object model services (properties and methods) to the HTML page. Another possible use for HTCs is to provide cross-domain scripting access; the HTC could declare which properties, methods and events are allowed to be accessed from outside the domain.

HTML Components are built on HTML for a number of reasons - HTML has a robust and well-known set of semantics, and already has widely supported scripting and object model semantics.  HTML Components can contain regular HTML elements - but visual elements and text content are not by default to be rendered in place of any HTML element that the Component may be attached to.

NOTE: Although the descriptions in this document do not show them (since a particular namespace would need to be chosen), all HTC elements need to be namespaced, with a proper namespace definition in the <HTML> tag.  This set of component-specific elements is not an addition to HTML; it is a set of new XML elements that can be added to the document. The examples reflect this requirement.  The HTC elements should be found in the HEAD of the HTML.

2. Component Architecture - the <COMPONENT> Element

The <COMPONENT> element serves as a container to identify an HTML Component.  It is not required; however, in many instances it may be useful in order to help the consumer of the HTML Component determine that an event was in fact fired from this particular component .  The <COMPONENT> element serves to bind together the properties, methods and events as well as to provide a location for the identifier of this HTC.

Syntax

string>

Attributes

URN
Required. String, in Uniform Resource Name (URN) format, that uniquely identifies the component. This allows events to be uniquely identified when multiple behaviors may be firing events of the same name, by setting a srcURN property on the event object to the URN of the behavior that fired the event.

Element Information

Number of occurrences None or One per Component interface exposed
Parent elements None
Child elements ATTACH, EVENT, METHOD, PROPERTY

3. Defining Properties - the <PROPERTY> Element

The <PROPERTY> element defines a property of the HTML Component to be exposed to the HTC consumer.

Syntax

string
    ID = string
    GET = string
    PUT = string
    PERSIST = string
>

Attributes

NAME
Required. String that identifies the property to the containing document. By default, the NAME specified is used to refer to the property within the Component.
ID
Optional. String that can be used to identify this property element within the Component (similar to the HTML ID attribute).
GET
Optional. String that specifies the function to be called when the value of the property is retrieved.
PUT
Optional. String that specifies the function to be called when the value of the property is set.
PERSIST
Optional. Boolean that specifies whether or not the property should be persisted as part of the page if the HTC consumer supports persistence of HTML documents.

Object Model Methods

propertyID.fireChange()
The HTML Component can call this method on a <PROPERTY> element to inform the containing document that the value of the property has changed by causing the onpropertychange event to fire on the element to which the Component is attached.

Element Information

Number of occurrences Any number
Parent elements COMPONENT or None
Child elements None

Remarks

In XML, an empty element is denoted by the start tag ending with a "/>". Therefore, a <PROPERTY> element can be written as:

By specifying a NAME attribute similar to a standard property already defined for the element that invokes it, a Component can override the element's normal property with that name.

Example

The following example implements an example of providing state properties from the mouse events through an HTML Component. The HTC exposes a 'hovering' property to the containing document to indicate whether the mouse cursor is currently positioned over the element or not.


<PUBLIC:PROPERTY NAME="hovering" GET="get_hovering"/>
<PUBLIC:ATTACH EVENT="onmouseover" HANDLER="event_onmouseover" />
<PUBLIC:ATTACH EVENT="onmouseout" HANDLER="event_onmouseout" />

<SCRIPT LANGUAGE="JScript">
var mouseover = false;

function event_onmouseover()
{
   mouseover = true;
}

function event_onmouseout()
{
   mouseover = false;
}

function get_hovering()
{
   return mouseover;
}

4. Defining Methods - the <METHOD> Element

The <METHOD> element defines a method of the HTML Component (HTC) to be exposed to the HTC consumer.

Syntax

string
/>

Attributes

NAME
Required. String that specifies the name of the method that is exposed to the containing document. By default, the NAME attribute is also used to refer to the method within the component, unless the INTERNALNAME attribute is specified.

Element Information

Number of occurrences Any number
Parent elements COMPONENT or None
Child elements None

Remarks

By specifying a NAME attribute similar to a standard method name already defined for the element, a Component can override the element's implementation for that method..

Example

The following code demonstrates how to use the METHOD tag to expose the startFlying() method from the HTC to the containing document.


<PUBLIC:METHOD NAME="startFlying" />

<SCRIPT LANGUAGE="JScript" >
function startFlying()
{
   // insert flying code here
}
</SCRIPT>

For more of this sample, see the Example section.

5. Defining Events - the <EVENT> Element

Defines an event that the HTML Component that will use to communicate with the HTC consumer.  This event may be a predefined HTML event (e.g. the onmouseover event), or it may be a new "custom event" that the Component defines here. In either case, the <EVENT> element defines that the Component wants to either fire or handle this event for the consumer.

Syntax

string
    ID = string
/>

Attributes

NAME
Required. String that specifies the name of the event that is exposed to the HTC consumer.
ID
Optional. String that identifies the event tag within the component.

Methods

this.fire([oEvent])
Fires the event to the HTC consumer. This method has an optional oEvent parameter that specifies an event object containing context information.  The details of the event object is to be defined by a future release of the W3C Document Object Model.

Element Information

Number of occurrences Any number
Parent elements COMPONENT or None
Child elements None

Remarks

By specifying the same NAME attribute as a standard event already defined for the element, a behavior can override the element's default event handler for that event.

Events defined for a behavior do not bubble and only fire on the element to which the behavior is attached.

Example

The following example is derived from a calculator behavior sample. Whenever the result changes, the HTC fires a custom onResultChange event back to the page, passing the result as an additional property on the event object.  This example presupposes a createEventObject() method - the Document Object Model does not yet cover events, so this usage may be temporary.


<PUBLIC:EVENT NAME="onResultChange" ID="eventOnResultChange" />

<SCRIPT LANGUAGE="JScript">

function doCalc()
{
   :
   oEvent = createEventObject();
   oEvent.result = sResult;
   eventOnResultChange.fire (oEvent);

}

Here's what the containing page looks like:


<HEAD>
<STYLE>
   LK\:CALC    { behavior:url(engine.htc); } 
</STYLE>
</HEAD>

<LK:CALC ID="myCalc" onResultChange="resultWindow.innerText=window.event.result">
<TABLE>
<TR><DIV ID="resultWindow" STYLE="border: '.025cm solid gray'" ALIGN=RIGHT>0.</DIV></TR>
<TR><TD><INPUT TYPE=BUTTON VALUE=" 7 "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" 8 "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" 9 "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" / "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" C "></TD>
</TR>
<TR><TD><INPUT TYPE=BUTTON VALUE=" 4 "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" 5 "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" 6 "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" * "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" % " DISABLED></TD>
</TR>
<TR><TD><INPUT TYPE=BUTTON VALUE=" 1 "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" 2 "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" 3 "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" - "></TD>
    <TD><INPUT TYPE=BUTTON VALUE="1/x" DISABLED></TD>
</TR>
<TR><TD><INPUT TYPE=BUTTON VALUE=" 0 "></TD>
    <TD><INPUT TYPE=BUTTON VALUE="+/-"></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" . "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" + "></TD>
    <TD><INPUT TYPE=BUTTON VALUE=" = "></TD>
</TR>

</TABLE>
</LK:CALC>
</HTML>

6. Attaching Events with the <ATTACH> Element

The <ATTACH> element is used to bind a function in the HTC to an event so that the function gets called whenever the event fires on the component's element.

Syntax


Attributes

EVENT
Required. String that specifies the name of an Object Model event, or either of the HTC-specific events, oncontentchange or ondocumentready.
FOR
Optional. String value that identifies the object for which the event is fired.
document The component should attach events to and send events to the document object.
element The component should attach events to and send events to the element object.
window The component should attach events to and send events to the window object.
HANDLER
Required. String that specifies the name of the function to handle the event.
URN
Optional. String that specifies the URN of the source of the event to attach to. This is useful when multiple sources of the event exist.

Element Information

Number of occurrences Any number
Parent elements COMPONENT or None
Child elements None

Remarks

When the specified event fires on the element to which the component is attached, the element's event handler is called first, before that of the component.

Example

The following example implements an expanding/collapsing table of contents using an HTC. The HTC attaches to the element's onclick event and expands or collapses the list every time the onclick event is received. In addition, it attaches to the element's onmouseover and onmouseout events to implement mouseover highlighting effect, as the expandable list items are hovered over.  This example makes use of the 'element' object, described in section 7.


<PUBLIC:PROPERTY NAME="child" />
<PUBLIC:ATTACH EVENT="onclick" HANDLER="onclick_handler" />
<PUBLIC:ATTACH EVENT="onmouseover" HANDLER="onmouseover_handler" />
<PUBLIC:ATTACH EVENT="onmouseout" HANDLER="onmouseout_handler" />

<SCRIPT LANGUAGE="JScript">
function onmouseover_handler()
{
   element.style.color = "red";
}

function onmouseout_handler()
{
   element.style.color = "black";
}

function onclick_handler()
{
   var i;
   var sDisplay;

   // Determine current state of the list (i.e. expanded or collapsed)
   // based on the current display property of the child.
   bCollapsed = (document.all(child).style.display == "none");
   
   if (bCollapsed)
   {
      element.style.listStyleImage = "url('/workshop/graphics/blueminus.gif')";
      element.style.display = "";
   }
   else
   {
      element.style.listStyleImage = "url('/workshop/graphics/blueplus.gif')";
      element.style.display = "none";
   }
}
</SCRIPT>

7. Component-specific Events and Object Model

HTML Components also have two events that are specific to Components.  These events are specific to the relationship between a Component and its host.

ondocumentready

The ondocumentready event fires when the behavior's containing document has been parsed.

Example

The following sample demonstrates basic usage of the ondocumentready event on a page.

ondocumentready HANDLER=documentready_handler />

<SCRIPT LANGUAGE="JScript">
function documentready_handler()
{
   window.alert ("The ondocumentready event fired.");
}
</SCRIPT>

oncontentchange

The 'oncontentchange' event fires when the element to which the Component is attached has been parsed, or whenever the content of the element changes.

Example

The following sample code demonstrates basic usage of the oncontentchange event on a page.


<PUBLIC:ATTACH EVENT="oncontentchange" HANDLER="contentchange_handler" />

<SCRIPT LANGUAGE="JScript">
function contentchange_handler()
{
   window.alert ("The oncontentchange event fired.");
}
</SCRIPT>
</HTML>

In addition, HTCs expose an "element" object to object model consumers inside the HTML Component, which is the same Element object exposed in the original document's object model.  This allows the HTC to direct access and affect the HTML element to which it is attached.  See the section 6 for an example of how this can be used.

8. Linking Components to HTML Elements

This section is not normative.  This document presupposes a mechanism for linking HTML Components to elements in an HTML document. Some of the examples in this document use a linking mechanism based on CSS stylesheets that has not been approved by the W3C.  This linking mechanism is still under discussion, and may change significantly.

The linking mechanism used in the examples in this document is a new property that would need to be added to Cascading Style Sheets:

'behavior'
Value:   <uri> | none | inherit
Initial:   none
Applies to:   all elements
Inherited:   no
Percentages:   N/A
Media:   all

This property links an element to a handler that may handle dynamic behavior through the object model of that element. For the purpose of this document (the HTC description), this handler must be an HTML Component.

9. Example

The following code demonstrates a flying effect component, which allows a page author to easily add dynamic movement effects to their pages. This component makes use an inline style object model that has not yet been approved by the Document Object Model Working Group.

This component makes use of most of the HTML Component features - it uses properties to allow the page author to control the type of flying effect, methods to start/stop the effect, and events to both set up the properties needed in the page and notify the page when the effect is finished (via a custom event).


<PUBLIC:METHOD NAME="start" />
<PUBLIC:METHOD NAME="stop" />
<PUBLIC:PROPERTY NAME="direction" GET="getDir" SET="setDir" />
<PUBLIC:EVENT NAME="onFlyFinished" />
<PUBLIC:ATTACH EVENT="onclick" HANDLER="onClick" />

<SCRIPT LANGUAGE="ECMAScript" >
var direction = 0;	// 0 = left, 1 = top, 2 = right, 3 = bottom
var x = 0;
var y = 0;
var xScaler = 0;
var yScaler = 0;
var bFlying = false;
var timer;

function start()
{
    switch ( direction )
    {
    case 0:	// left
	x = -100;
	xScaler = 5;
	y = 0;
	yScaler = 0;
	break;
    case 1:	// top
	x = 0;
	xScaler = 0;
	y = -100;
	yScaler = 5;
	break;
    case 0:	// right
	x = 100;
	xScaler = -5;
	y = 0;
	yScaler = 0;
	break;
    default:	// bottom
	x = 0;
	xScaler = 0;
	y = 100;
	yScaler = -5;
	break;
    }
    bFlying = true;
    element.style.position = "relative";
    tick();
}

function stop()
{
    if ( bFlying )
    {
        window.clearTimeout( timer );
        element.style.left = "0";
        element.style.top = "0";
        bFlying = false;
        var eventElem = document.getElementsByTagname( "public:event" )[0];
        var oEvent = createEventObject();
        eventElem.fire( oEvent );
    }
}

function setDir( dir )
{
    if ( dir == "left" )
	direction = 0;
    else if ( dir == "top" )
	direction = 1;
    else if ( dir == "right" )
	direction = 2;
    else 
	direction = 3;
}

function getDir()
{
    switch ( direction )
    {
    case 0:
	return "left";
	break;
    case 1:
	return "top";
	break;
    case 0:
	return "right";
	break;
    default:
	return "bottom";
	break;
    }
}

function tick()
{
    element.style.left = x;
    element.style.top = y;
    x += xScaler;
    y += yScaler;
    if ( x == 0 && y == 0 )
	stop();
    else
	timer = window.setTimeout( "tick()", 100 );
}

function onClick()
{
    alert( "x is '" + x + "%', y is '" + y + "%'." );
}

</SCRIPT>

The HTML page that uses this might look like this:


<HEAD>
<STYLE>
#flier { 
    behavior: url( fly.htc );
    text-align: center;
}
</STYLE>
</HEAD>
<BODY>
<H1 ID=flier>Flying titles!</H1>
<P><BUTTON onclick="document.getElementsByTagname( "H1" )[0].stop();">Stop</BUTTON></P>

<SCRIPT>
var flyingElem = document.getElementsByTagname( "H1" )[0];
flyingElem.onFlyFinished = "alert('finished flying!');"
flyingElem.direction = "left";
flyingElem.start();
</SCRIPT>
</BODY>
</HTML>
Back