IBM Widgets proposal

From MemberWiki

Jump to: navigation, search

Contents

Abstract

There are a number of widget definitions and providers with a great amount of overlap in approaches and concepts. Each widget definition has its own set of runtime and presentation characteristics. Some consolidation among widget provides may occur but many widget definitions will continue to exist and thrive. The goal of this document is to define a lightweight metadata format and a thin runtime environment that enables application developers and mashup assemblers to create composite assemblies of loosely coupled pre-packaged application components from a variety of widget providers.

Widgets come in many shapes and sizes this document will use the definition of 'web widgets' from Wikipedia.

"A web widget is a portable chunk of code that can be installed and executed within any separate HTML-based web page by an end user without requiring additional compilation. They are derived from the idea of reusable code that has existed for years."

Introduction

There are several efforts within the OpenAjax organization that are key building blocks for the achieving interopability among widgets definitions:

  • Interoperability Work Group - provides the ability to combine JavaScript components from multiple Ajax toolkits within the same Web application and have those components interact with each other.
  • Communications Hub Task Force - defines a publish/subscribe event manager, which enables loose assembly and integration of Ajax components
  • IDE Work Group - industry standards for describing Visual and non-visual Controls and Ajax library APIs for use in design-time and potentially run-time scenarios
  • SMash (Secure Mashup) - a set of techniques and open source JavaScript that runs in today's browsers (without extensions or plugins) and enables secure handling of 3rd party mashup components.

Use Cases

A key umbrella use case for the OpenAjax Widgets is the set of scenarios where an assembler needs to create a single composition that uses multiple Ajax libraries simultaneously. Key use cases for Widgets are portals and mashups, where the assembler creates a page of loosely assembled pre-packaged application components. Portals and mashups typically pull in Ajax-powered components that are built using multiple different Ajax toolkits.

The following are some of the scenarios where developers will find a need for using multiple Ajax libraries simultaneously:

  • Ajax developer finds that a single Ajax library does not meet all of his requirements - In some cases, an Ajax developer might choose to build the majority of his application using a particular Ajax library, but discover that a particular component from that library does not have the features he needs, and therefore would like to incorporate a component from a different Ajax library, leaving the rest of the application unchanged. In other cases, most of the application might be (non-Ajax) DHTML, but the developer would like to incorporate two components of Ajax technology into the application, where the two components come from different Ajax libraries.
  • Mashups - In order to build a composite application from pre-existing application components, a developer (or end-user) is likely to have to combine components based on different Ajax libraries.
  • Portals - Portals support Ajax technologies and represent a variation on composite applications. It is common that different portlets use different Ajax libraries.

Model

The proposed approach does not include the creation of a new component model, but rather a simple metadata layer plus a minimal mapping or adapter layer to the native widget environment. Developers will continue to create widgets in their choice of component models, the goal as stated in the Use Cases is to enable the widget assembler to easily use widgets from a variety of native formats to create composite applications or mashups. The metadata described below is intended to convey enough information so that assembly tools can understand the properties and possible event wiring capabilities of a given widget. The mapping layer will propagate lifecycle events (e.g. onAdd, onDelete) related to the assembly process as well as events for property changes. The metadata also contains required elements which declare conforming toolkit references and configuration information. These elements are placeholders for a more direct mapping to other efforts within the OpenAjax.org, for example the Registry.

Widget Specification Format

Widget

A widget contains a set of attributes that describes characteristics of the widget within a global context. For example, the widget attributes can be used by a composition canvas to place the widget on a palette for use within a composition.

The widget attributes are directly available from the widget wrapper instance managed by the runtime library.

  • title - OPTIONAL string that is the title of the widget that may be used by the composition canvas as decoration around the widget.
  • website - OPTIONAL string that is a URI for the widget author's website
  • description - OPTIONAL string that describes the widget. Can be an attribute or an element. Element has precedence and may contain XHTML markup.
  • height - OPTIONAL positive integer that specifies the height of the area in which the gadget runs. The default height is 200 pixels.
  • width - OPTIONAL positive integer that specifies the width of the area in which the gadget runs. The default height is 200 pixels.
  • author - OPTIONAL comma separated string containing the name(s) of the author(s) of the widget
  • email - OPTIONAL comma separated string containing the email(s) of the authors(s). NOTE: The contents of this value must be in the same occurrence order as the author attribute.
  • thumbnail - OPTIONAL string that gives the URL of a widget thumbnail. This must be an image on a public web site that is not blocked by robots.txt. PNG is the preferred format, though GIF and JPG are also acceptable. Widget thumbnails should be (ED: need default size) X by Y pixels. The URL can be absolute or relative to the assets contain within the widget package.
  • category - OPTIONAL string describing a default categorization of the widget (e.g finance, sports).
  • scaling - OPTIONAL boolean that specifies whether the aspect ratio (height-to-width ratio) of the widget is maintained when the browser is resized. Widgets that can automatically scale vertically should set this to true, but widgets which have a fixed height should set this to false. The default is true.
Image:Warning.gif IDE Widgets Strawman
renamed to preserveAspect.
  • scrolling - OPTIONAL string that provides vertical and/or horizontal scrollbars if the content exceeds the space provided. The value, if present, has the same semantics as the CSS overflow property.
  • scope - OPTIONAL string which specifies the name of the a JavaScript constructor function to use when creating the widget wrapper for an instance of the widget (See Widget Wrapper below), the default value is OpenAjax.gadgets.GadgetWrapper.
Image:Warning.gif IDE Widget Strawman
This is renamed to jsClass
Image:Warning.gif IDE Widget Strawman Additional Attributes
  • about="ur"
  • authorEmail == email above
  • libraryName="string" // e.g., 'extjs' or 'dojo' (jMaki: ++)
  • libraryVersion="#" // e.g., '2.0.2' (none: +)
  • widgetVersion="#" // widget vers@, e.g., 1.2.3 (Adobe,jMaki: ++)
  • specVersion="#" // OpenAjax spec#, e.g., 1.2.3 (jMaki: +++)
  • license="string" // Text that describes license for widget (W3C: +) NOTE: license should be an element, no?
  • icons <icons> // Adobe,jMaki,IBM: +++) <icon size="#" width="#" height="#" src="url" alt="string" /></icons>
Image:Warning.gif Google Gadgets alignment with proposal above
  • Gadgets shares: title, description, author (but only 1), email (but only 1), thumbnail
  • Gadgets does not have: website, height, width, category, scaling (although there is a feature for dynamic height), scrolling, scope
  • Gadgets adds:
    • directory_title (to show while browsing Google gadgets)
    • title_url (hyperlink on title string)
    • author_affiliation
    • author_location
    • screenshot
    • <MayRequire type=plugin|browser|platform value=(eg,flash) min_version=something>optional comment text</MayRequire>

Sample:

GoogleMap
<widget xmlns ="http://openajax.org/widget"
	name="GoogleMap"
	scope="GoogleMap"
	description="This is a simple example of a googlemap widget...">
....
</widget>

Widget Dependencies

A widget can declare the toolkit dependencies, configuration and other widgets on which it depends upon. The require tag within the widget specification contains the following attributes:

  • library - OPTIONAL string specifying the Ajax Toolkit that is used to implement the widget. Conforming OpenAjax libraries names are the allowable values for this attribute. (ED: How will this be managed? OpenAjax Registry?)
  • version - OPTIONAL string specifying the version number of the Ajax Toolkit required. (ED: Can this be combined with the library name from above when interacting with the registry)
  • src - OPTIONAL string representing a URL to a JavaScript file that will be included with the widget.
  • config - OPTIONAL attribute or child describing the configuration for a given library.
Image:Warning.gif IDE Strawman Comment
The library and version from the above are placed in the <widget> tag above.
Image:Warning.gif ED: Comment
For conforming libraries this information can be composition wide, for example, what happens when you have competing configuration requests? IFRAME? Need to integrate with the Registry if appropriate

The <require> tags are ignored when the <content> node is of type "uri". The Gadget's content's composition is completely handled by the URI and is done within its own IFRAME.

Sample:

Library Require
<widget xmlns ="http://openajax.org/widget"
	name="GoogleMap"
	scope="GoogleMap"
	description="This is a simple example of a googlemap widget...">

	<require library='dojo' version="0.9">
	    <config>
	      "parseOnLoad: false, isDebug: true, extraLocale: ['en-us', 'ar-sy', 'es-es', 'zh-cn']"
	    </config>
	</require>
...
</widget>


This section is related to the IDE Issue described here IDE Issue 1

Image:Warning.gif Note about IDE WG
  • One of the approaches being considered by the IDE WG is something akin to Adobe's proposed <assetfile> tag which lists each file (or potentially whole directories) upon which there is some sort of dependency. We have discussed two flavors of assets:
    • Assets that turn into a new element within the HEAD. For example, JavaScript assets often require the insertion of a <script> tag into the HEAD
    • Assets that are required to be included in the deployment. For example, the HTML content might reference an image. That image needs to be included with the web content when deployed.
  • One topic under discussion is to reference Ajax libraries by the name of the JavaScript file(s) that need to be placed in the HEAD as <script> tags. If two widgets need the same Ajax libraries, then presumably they could reference the same <script> tags. However, it seems that even if this approach would be workable for HTML web page which assembles multiple UI controls from various libraries, it may not be workable in mashups scenarios because widgets that use the same Ajax library might pull it down from different locations.

Widget Instance Properties

Widgets contain properties the values of which affect the widgets' behavior and display characteristics. The properties of a widget can be set by the user, using a general purpose property editing tool or a widget specified property editor.

Each property of a widget will contain the following attributes:

  • name - REQUIRED string that is unique within the context of the widget's properties specifying the name of the property.
  • display_name - OPTIONAL string that represents the property name that will be displayed to the end-user while editing the property.
  • description - OPTIONAL string that contains a detailed description of the property that MAY contain XHTML. Can be an attribute or an element. Element has precedence and may contain XHTML markup.
  • short_description - OPTIONAL string that contains an abbreviated description of the property, appropriate for tooltip style of usage.
  • scope - OPTIONAL string specifying the scope of the property regarding the widget instance. Valid values are 'instance' or 'static'. The default value is 'instance'. Instance scope specifies that each instance of the widget contains its own copy of the property. Static scope specifies that properties are global across all instances of the widget. (ED: What about semantics of static as it relates to 'site' widget instances)
  • type - OPTIONAL string that specifies the data type of the property, default value is string. Allowable values are string, boolean, hidden, number, enum, list). (ED: How is this list extensible? QNAMEs?)
  • value - OPTIONAL string the specifies the default value of the property. If the type is an enumeration, this value represents the selected value of the enumeration. If the type of property repeats, the default_value is ignored.
Image:Warning.gif Comment
  • Can be an attribute or an element. Element has precedence and may contain markup (??)
  • topic - OPTIONAL string that specifies a message topic in which the property participates as an event source or target (see OpenAjax_Hub_1.1_Proposed_APIs for more detail).
Image:Warning.gif Comment
  • We need to be clearer about what to do when the property is set to listen or publish but there is no topic specified. I see 2 options:
  1. Ignore the behavior for the property
  2. Default the topic to the name of the property (I like this better)
  • listen - OPTIONAL boolean specifying this property is a target for events delivered to the room property above. Default value is false.
  • publish - OPTIONAL boolean specifying this property is an event source. The event is delivered to the OpenAjax Hub using the room specified above.
  • constraint - OPTIONAL attribute the specifies the constraint to apply to the property. Constraints represent simple restrictions placed on the value of the property. For example, a property can have a limit constraint stating that the value must be between n and m.
  • onChange - OPTIONAL string specifying a JavaScript function or method to invoke when the property changes, if listen is true. The implementation will first check for a function within the scope of the widget and then check for a method on the widget wrapper of the specified name.
  • required - OPTIONAL boolean specifying if this property is required to have a property value, default is false.

TBD:

  • Grouping or batching event changes into a single event.
  • Additionally, the listen/publish/onChange properties only focus on binding NOT on the format of the event payloads. How do we represent more complex properties, for example, a list of locations each of which consists of an address, icon URL and display text?
  • How is Point-to-point wiring accomplished?
  • Need to define true and false and case insensitive (e.g. true == TRUE)
Image:Warning.gif IDE Widget Strawman
  • jsType - is the JavaScript type
  • xsdType - allows for more detailed datatyping via XML Schema Datatypes 1, such as string, boolean, decimal, float, dateTime, anyURI or QName, or custom datatypes using the more advanced features.
  • defaultValue == value (above)
  • access - is either 'readonly' or 'read-write'
  • visibility - is a hint that indicates whether the given property should appear in an inspector dialog. This is designed as an enumeration for future growth, but 'yes' and 'no' will be the only two values initially.
Image:Warning.gif Google Gadgets alignment with proposal above
  • Gadgets uses a similar approach for identifying topics that are published and consumed via publish and listen attributes, but it overloads its name attribute to reflect both the property name and the topic name. For example, to publish your location, you have two properties named lat and long.
  • Gadgets shares: name, display_name, type (Gadgets calls it datatype), value (Gadgets calls it defaultValue), required, listen, publish, onChange (Gadgets calls it on_change)
  • Gadgets does not have: description, short_description, scope, topic, constraint
  • Gadgets' datatype of hidden aligns somewhat with the IDE WG strawman attribute visibility
  • Gadgets supports the following datatypes:
    • string
    • bool
    • enum (of strings, each with a internal name and a display string)
    • hidden (a string, but user does not see it on the preferences editor)
    • list (of strings, unlimited length and dynamically growing)
    • location

Samples:

Widget Properties
<properties name="userProperties" description="General properties available to the user">
	<property name="firstName" display_name="First Name" short_description="Your first name">
		<description>You must specify your <b>first name</b> in this field</description>
	</property>
	<property name="lastName" description="Attribute style of description"/>
</properties>


Statically Scoped property
<properties>
	<property name="bgColor" scope="static" display_name="Share background color" type="number"
		value="100"/>
</properties>


Enumeration Property Sample
<properties>
	<property name="bgColor" type="string" value="red">
	      	<constraint>
			<enum>
				<option value="red">Red</option>
                                <option value="green">Green</option>
                                <option value="blue">Blue</option>
	                </enum>
		</constraint>
	</property>
</properties>


Limit constraint on a numeric property
<properties>
	<property name="rating" type="number" constraint="ratingConstraint"/>
</properties>

<constraint id='ratingConstraint'>
	<limit minx='0' max='0'/>
</constraint>

Widget Content

The widget content consists of an XHTML fragment that is spliced into the composite assembly. The implementation canvas is responsible for performing the page or desktop composition of widgets as defined by the user. The content element contains the widget content or references the content via a URL. A widget may contain several content sections, the content modes supported are:

  • view - the default, which specifies the main view to the widget
  • edit - OPTIONAL section that specifies the Content used to edit the properties of the widget
  • help - OPTIONAL section that specifies the help content of the widget

Below are the attributes of the content section:

  • mode - OPTIONAL string specifying the mode of the content section (see Content section above), default value is "view"
  • href - OPTIONAL string specifying a URL that returns the content of the widget.
  • type - OPTIONAL string specifying how to treat the content contained in the section. Type supported include:
    • html - content is to be spliced inline with the page or assembly canvas
    • url - the href points to the content of the widget, in which case an IFRAME is spliced into the assembly canvas pointing to the widget. NOTE: For url content, the <resource> tags are ignored since the Gadget's content rendering is completely delegated to the URL within its own IFRAME.
    • frame - the content of the section is contained within a IFRAME for security and other runtime related requirements, this is the default
Image:Warning.gif Google Gadgets alignment with proposal above
  • Gadgets allows for 3 types of content: "html", "uri", and "inline". Gadgets' "html" type roughly aligns with our "frame" type. Gadgets' "uri" type roughly aligns with our "uri" type. However, Gadgets' has a different attitude about its "inline" type (which roughly aligns with our "html" type). They warn users against building this sort of widget except when the widget needs access to the rest of the Web page (e.g., the widget acts differently based on the text content of the host page) and various features become unavailable, such as the ability to talk to a remote site.

Content Examples:

Simple Content
<content mode="view" type="html">
	Hello World, widget content
</content>


HREF Content
<content mode="view" type="uri" href="http://www.acme.com/widgetcontent.xml"/>

Widget Lifecycle Management

A composition canvas will need the ability to:

  • Create a widget and add it to the composition surface
  • Query the properties of a widget along with their current values
  • Update the properties of a widget
  • Persist the properties of a widget
  • Remove a widget from the composition canvas
  • Wire event producers with event consumers
  •  ??? Enumerate the widgets on the canvas ???

Communication between the widget and the host environment is accomplished through the Widget Wrapper instance.

Image:Warning.gif Comments on Lifecycle

The IDE WG will probably have many of the same lifecycle issues as described in Widget Lifecycle Management. Additionally an IDE may not actually instantiate the widgets during design time, that is, a widget may simply have a static design view. This dramatically changes the developers experience of the widget during development. In the browser based aggregation of widgets approach (browser mashups), the widgets are actually live, additionally the line between design and run time is blurred. For example, a single widgets can be "taken" out of run mode to design mode and back again. Different things need to happen in the more traditional IDE view of widget composition vs. browser canvas based mashups.

Image:Warning.gif Google Gadgets alignment with proposal above
  • Gadgets has an onload handler mechanism whereby the JavaScript for the widget calls __IG_RegisterOnloadHandler to identify the callback function for when the widget is loaded

Widget Wrapper

Each instance of a widget is represented using a JavaScript object which provides the communication between the host environment and the native widget executing in a given widget toolkit. The optional scope attribute of the widget specifies the name of a JavaScript constructor function to be used when instantiating a given widget, the default value is OpenAjax.gadgets.GadgetWrapper.

The GadgetWrapper class is defined as follows:

NOTE: Implementations of the GadgetWrapper may contain a more elaborate interface, however, additional protocol is considered implementation specific and SHOULD NOT be used as a general purpose interface.

Wrapper Interface
/**
*Generic wrapper classes for widgets
* @constructor
*/
OpenAjax.widgets.WidgetWrapper = function() {};

with (OpenAjax.widgets.WidgetWrapper) {
	/**
	  * Sets the value of the specified property name to the value
	  * @param {String} propertyName This is the name of the property
	  * @param {Object} value The value of the property
	*/
	prototype.setPropertyValue = function(propertyName, value) {};

	/**
	  * Returns the current value of the requested property name.
	  * @param {String} propertyName This is the name of the property to retrieve
	  *
	*/
	prototype.getPropertyValue = function(propertyName) {};

	/**
	  * This method requests that the wrapper save the current state of the widget properties.
	  * The same method operates asynchronously, if you wish to determine the success/failire
	  * of the method pass a callback parameter.
	  * @param {Function} saveCallback This is a function that is invoked with the result of the
	  * save operation
	 */
	prototype.save = function(saveCallback) {};

}

The saveCallback signature is as follows:

/**
  * Save callback exemplar
  * @param {XMLHttpRequest} xhrUsed Queryable for the status codes, etc
  * @param {WidgetWrapper} The widget instance whose values were just saved
*/
function saveCallback(xhrUsed, widgetWrapper) {}

Widget Creation

The composition canvas uses the widget description document to determine the runtime characteristics of the widget. Adding a widget to a composition consists of the following steps:

  • Load the widget description document
  • Determine the requested content mode of the widget (e.g. view, edit, help)
  • Locate the content and splice the content into the composition canvas (ED: TBD locale expansion)
  • Register the subscribers with the OpenAjax Hub as defined in the description document

The implementation will transform the widget document expanding the _WIDGETID_ eye-catcher to the actual ID to the widget being created. IDs are required to be unique within the context of the assembly canvas.

Sample Content before Expansion
<content type='html'>
    		<div id="__WIDGETID__map" style="width: 100%; height: 430px"></div>
		</div>
</content>

After replacement the content may look like this:

Sample Content after Expansion
<content type='html'>
    		<div id="ID_1234567890map" style="width: 100%; height: 430px"></div>
		</div>
</content>

The expansion enables the same widget fragment to be used multiple times on a single composition and avoid name collisions.

NOTE: It is not intended that the widget description document be the persistent format for widgets on a particular composition canvas. Implementations are free to persist the property values and wiring relationships in a more appropriate (efficient) scheme.

Image:Warning.gif ED: Note
Do widgets need to describe when a page refresh is needed or they only run in an IFRAME mode? <WEV> no. the widget should only be responsible for its own content. one way to keep the responsibility for page refresh with the hub is to have the hub consume a refresh message.</WEV>

Is there a factory for widgets from conforming Toolkits? <WEV> then you need a factory factory;</WEV>

Widget Destruction

The predefined onDelete event is triggered on a widget before it is removed from the composition canvas. This event is synchronous so that the widget has an opportunity to free up resources before the widget's removal. It is the responsibility of the composition canvas to remove any additional adornment associated with managing the widget from the canvas. Additionally, the implementation is responsible for unwiring the widget from the OpenAjax Hub, that is, removing listeners via the unsubscribe call.

Widget Property Management

The list of supported properties, types, names, definition and wiring capabilities are contained in the Widget document. The composition canvas will consult the metadata document and use the public API of the WidgetWrapper to query and set the values of the properties exposed by a given widget. The WidgetWrapper implementation is responsible for persisting the widget properties.

Additional Sections/Topics in progress...

OpenAjax Hub Integration

The listen and publish property modifiers defined in the Widget Instance Properties section above are used to wire the widget to the OpenAjax Hub V 1.1. The implementation is responsible for opening a connection to the Hub, adding listeners to the Hub and publishing property change events to the Hub.

CSS

Image:Warning.gif ED: Note
  • Requirements

Mixing widgets from a variety of toolkit poses interesting challenges especially if each widget uses different styles. We have the following requirements:

  • Widgets need to be able to load style sheets dynamically. Do we expand the WidgetWrapper with a service factory protocol that enables dynamically loading style sheets?
  • The style sections can be defined in the content section of the widgets.
  • Do we formalize the dependencies on style sheets so that an implementation can optimized/redefine as appropriate?
  • Do we support any type of 'themes' across widgets?

Translations

The translation into difference locales will be down using a simple macro style expansion mechanism that is employed during the widget preparation phase.

Image:Warning.gif ED: Note
  • What is the format of message bundles?
  • What do the eye-catchers look like in the widget description document?)

Widget Event Handling

Widgets can both produce and consume events that are mediated by the OpenAjax Hub. The scenarios for widget interaction include:

  • Browser Page to Browser Page communication
  • Browser Page to Widget communication
  • Widget to Widget communication

Predefined Events

Implementations will support a set of predefined events that are delivered to the WidgetWrapper during assembly and runtime.

Image:Warning.gif ED: Note
  • Examples are: onAdd, onDelete...
  • TBD...
Image:Warning.gif Google Gadgets alignment with proposal above
  • Gadgets defines some standard topics. (Not sure if this is the same as "predefined events")
    • rawquery - Either the literal text of the user's query, or keywords used to match a context
    • finance_portfolio - Stock watchlist/portfolio
    • finance_symbol - Stock symbol
    • finance_symbol_quote - Stock market data for a symbol
    • lat - Latitude (in microdegrees) for geographical targeting
    • long - Longitude (in microdegrees) for geographical targeting

Sample Transformation

XSLT for Transforming Gadget-to-OAA Gadgets

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml"/>

<xsl:template match="/Module">
  <widget xmlns="http://openajax.org/widget">
    <xsl:apply-templates select="ModulePrefs"/>
    <properties>
      <xsl:apply-templates select="UserPref"/>
    </properties>
    <xsl:apply-templates select="Content"/> 
  </widget>
</xsl:template>

<xsl:template match="ModulePrefs">
    <xsl:if test="@title!=''">
      <xsl:attribute name="name">
        <xsl:value-of select="@title" />
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@author_link!=''">
      <xsl:attribute name="website">
        <xsl:value-of select="@author_link" />
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@description!=''">
      <xsl:attribute name="description">
        <xsl:value-of select="@description" />
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@height!=''">
      <xsl:attribute name="height">
        <xsl:value-of select="@height" />
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@width!=''">
      <xsl:attribute name="width">
        <xsl:value-of select="@width" />
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@author_email!=''">
      <xsl:attribute name="email">
        <xsl:value-of select="@author_email" />
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@author!=''">
      <xsl:attribute name="author">
        <xsl:value-of select="@author" />
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@thumbnail!=''">
      <xsl:attribute name="thumbnail">
        <xsl:value-of select="@thumbnail" />
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@scaling!=''">
      <xsl:attribute name="scaling">
        <xsl:value-of select="@scaling" />
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@scrolling='true' or @scrolling='TRUE' ">
      <xsl:attribute name="scrolling">auto</xsl:attribute>
    </xsl:if>
    <xsl:if test="@scrolling='false' or @scrolling='false' ">
      <xsl:attribute name="scrolling">none</xsl:attribute>
    </xsl:if>
</xsl:template>

<xsl:template match="UserPref">
  <xsl:element name="property">
    <xsl:if test="@name!=''">
      <xsl:attribute name="name">
        <xsl:value-of select="@name" />
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@display_name!=''">
      <xsl:attribute name="display_name">
        <xsl:value-of select="@display_name" />
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@required!=''">
      <xsl:attribute name="required">
        <xsl:value-of select="@required" />
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@default_value!=''">
      <xsl:attribute name="value">
        <xsl:value-of select="@default_value" />
      </xsl:attribute>
    </xsl:if>
    <xsl:choose>
      <xsl:when test="@datatype=''">
        <xsl:attribute name="type">string</xsl:attribute>
      </xsl:when>
      <xsl:when test="@datatype='bool'">
        <xsl:attribute name="type">boolean</xsl:attribute>
      </xsl:when>
      <xsl:when test="@datatype='list'">
        <xsl:attribute name="type">HELP</xsl:attribute>
      </xsl:when>
      <xsl:when test="@datatype='location'">
        <xsl:attribute name="type">HELP</xsl:attribute>
      </xsl:when>
      <xsl:when test="@datatype='enum'">
        <xsl:element name="constraint">
          <xsl:element name="enum">
            <xsl:apply-templates select="EnumValue"/>
          </xsl:element>
        </xsl:element>
      </xsl:when>
      <xsl:otherwise>
          <xsl:attribute name="type">
            <xsl:value-of select="@datatype" />
          </xsl:attribute>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:element>
</xsl:template>

<xsl:template match="EnumValue">
  <xsl:element name="option">
        <xsl:attribute name="value">
            <xsl:value-of select="@value" />            
        </xsl:attribute>
        <xsl:value-of select="@display_value" />            
  </xsl:element>
</xsl:template>

<xsl:template match="Content">
  <xsl:element name="content">
    <xsl:attribute name="mode">view</xsl:attribute>
    <xsl:choose>
      <xsl:when test="@type='html-inline'">
        <xsl:attribute name="type">html</xsl:attribute>
        <xsl:value-of select="."  />
      </xsl:when>
      <xsl:when test="@type='url'">
        <xsl:attribute name="type">uri</xsl:attribute>
        <xsl:attribute name="href">
          <xsl:value-of select="@href" />
        </xsl:attribute>
      </xsl:when>
      <xsl:when test="@type='cdata'">
        <xsl:attribute name="type">HELP</xsl:attribute>        
      </xsl:when>
      <xsl:otherwise>
        <xsl:attribute name="type">frame</xsl:attribute>
        <xsl:value-of select="."  />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:element>
</xsl:template>

</xsl:stylesheet>
Personal tools