Adaptive Components

An Adaptive Component (AC) allows to encapsulate features or aspects of your site. ACs are stored in the project/extensions directory and have to be registered in the Flow. As soon as an AC is registered, a new custom HTML element named after the AC is available in the content markup. An AC may contain asset files like JavaScript, CSS or images. The processing of the AC element is usually carried out by an XSL transformation included in the AC code. ACs may also add custom DC Properties.

The objectives of Adaptive Components are similar to those of Web Components: they can be shared, replaced and maintained separately from your site without changing the code within the site itself. They hide implementation complexity, help organize a project, provide a means of separating concerns and even give you a server-side Shadow DOM.

HTML is transcoded to UTF-8 when an Adaptive Component is registered.

You may want to take a look at the Best Practices that have emerged from our work with Adaptive Components, too.

Name

Your Adaptive Component should have a unique name. Adaptive Component names must match the XML NCName production and must contain one hyphen character (-). Registering an AC with the name ac-example will allow AC author provided XSLs to processes all occurrences of the <ac-example> element in the processed content. Also, all elements starting with <ac-example- are considered sub-elements of ac-example.

While an AC name can contain more than one hyphen, the processing of the ACs is not possible when an AC is named like possible sub-elements of other registered ACs. For example, when you try to register the ACs ac-foo and ac-foo-bar in the same flow, the AC processor can not clearly identify whether an ac-foo-bar-baz element is a sub element of ac-foo or ac-foo-bar. Therefore, when you try to register ACs whose names clash, FIT throws an exception and aborts the processing of the document. To avoid these conflicts, we strongly recommend to use exactly one hyphen in the name of Adaptive Components.

We also discourage the use of . characters as it may mess up the JavaScript API structure.

File System

The Adaptive Components work as a project extension and therefore have to be defined within their own directory inside the extensions directory of your project.

The name of the directory that the AC is located in must be the same name that is specified in the manifest. Within that directory there must be a manifest.xml file, which defines the AC name, the version and the XSL files that should be used in processing. The AC directory itself is considered private and clients cannot request any files located in that directory. Any assets like JavaScript, CSS or images that have to be delivered to requesting clients must be placed in the public directory of the AC extension.

Example of how the directory structure could look like for an ac-example:

...
|- projects
|   |- {myProject}
|   |   |- extensions
|   |   |   |- ac-example
|   |   |   |   |- public
|   |   |   |   |   |- js
|   |   |   |   |   |   |- api.js
|   |   |   |   |   |- css
|   |   |   |   |   |   |- styles.css
|   |   |   |   |- manifest.xml
|   |   |   |   |- main.xsl
|   |   |- sites
...

Referencing Adaptive Component files

Every file in the AC directory can be referenced by using the FIT protocol. For example the main.xsl file in the example above is accessible as fit://extension/ac-example/main.xsl just as the api.js file is accessible as fit://extension/ac-example/public/js/api.js.

While the directory is called extensions (plural, can contain many extensions) , the FIDJ path starts with fit://extension/ (singular, references exactly one extension).

Manifest

The manifest file is an XML file that registers the Adaptive Component for a FIT project. In order to be successfully registered for the processing in a site’s Flow with the register-ac action the manifest has to be well-formed and follow the restrictions explained in this documentation.

Structure of the Adaptive Component manifest

The adaptive-component element

<adaptive-component name="..." [version="..."] />

The manifest must contain one adaptive-component element, which is the root element of the XML file.

The adaptive-component element must have a name attribute, which defines the name of the Adaptive Component and thus the element name of the Adaptive Component’s entry element.

The adaptive-component element can have the optional version attribute, which is used for caching purposes. If set, the version attribute is used as a key for caching the referenced XSL files that are used in processing the content document. If not set, the last modified time of the respective XSL file is used as a cache key.

The adaptive-component element must contain one or more xslt elements each referencing an XSL file.

The adaptive-component element may contain one or more dc elements.

The xslt element

<xslt src="..."/>

The xslt element must be a child node of the adaptive-component element and must have one src attribute that references the XSL file that should be used in processing. The file can be referenced by using either an absolute path or a path relative to the manifest file.

The dc element

The dc element must be a child node of the adaptive-component element and can contain zero or more set-dc elements as documented in the set-dc Flow Action. Those set-dc elements will be parsed when the register-ac Flow Action for the respective AC is processed.

Note: in the delivery context on the server there is no difference between undefined properties and properties with the boolean value false. In the delivery context on the client though there is a difference between properties that are undefined or false. We recommend to set your delivery context properties even if they equal the boolean false so working with the delivery context in the client yields expected results. In case of dynamic assigment with e.g. choose or if it is important to set an otherwise case with a default value assignment. This produces the same results in the client and on the server.

Example manifest file

<adaptive-component name="ac-example" version="0.1">
  <xslt src="main.xsl" />
  <dc>
    <set-dc property="ac/ac-example/mode" value="full"/>
  </dc>
</adaptive-component>

Adaptive Component XSL

The XSL used for AC transformation has to follow certain rules.

XSL template, variable and mode conventions

All templates defined have to use the name of the AC as their mode. For example:

<xsl:template match="ac-example" mode="ac-example">

or

<xsl:template match="ac-example-element" mode="ac-example">.

Every element with a name equal to the name of the AC and elements whose names start with {ac-name}- will be applied in this mode. If the mode is not set accordingly or the name of the matched element does not follow these rules the template will be ignored.

The templates should use xsl:apply-templates without mode and select attributes so the child elements of the matched element can be processed correctly.

Every named template has to use a name that starts with the name of the AC. Any named templates with names that do not follow this rule will be ignored.

Every top-level xsl:variable has to use a name that starts with the name of the AC. Any variable that does not follow this rule will be ignored.

Adding resources to the document head

When processing the Adaptive Component FIT will try to call a named template that allows you to add elements to the document head. The name of this template must be {ac-name}-head. There is no other way for an AC to add elements to the document head.

The {ac-name}-head template will be called whether there is an ac-name element in the document to be processed or not. Make use of <xsl:if test="//ac-name"> or the like in case you want to deliver your resources conditionally.

Example XSL

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

  <!-- variables and params have to be prefixed with ac-name- -->
  <xsl:variable name="ac-example-mode" select="$dc/ac/ac-example/mode" />

  <!-- named template to add resources -->
  <xsl:template name="ac-example-head">
    <link id="AC__example_css_ext" rel="stylesheet" href="fit://extension/ac-example/public/css/styles.css" />
    <script id="AC__example_js_ext" src="fit://extension/ac-example/public/js/api.js" /> <style id="AC__example_css_int"> ... <!-- inline css --> ... </style> <script id="AC__example_js_int"> ... <!-- inline script --> ... </script>
  </xsl:template>

  <!-- "entry level" match, mode has to be ac-example -->
  <xsl:template match="ac-example" mode="ac-example">
    ...
    <!-- no @mode, so brings us back to fit processing -->
    <xsl:apply-templates />
    ...
  </xsl:template>

  <!-- sub element match, mode has to be ac-example -->
  <xsl:template match="ac-example-element" mode="ac-example">
    ...
    <!-- no @mode, so brings us back to FIT processing -->
    <xsl:apply-templates />
    ...
  </xsl:template>

  <!-- obviously evil template, which will be ignored because it does not have a mode and the matched element does not follow the rules on naming ACs either -->
  <xsl:template match="body/*">
    mwahahahaha
  </xsl:template>

</xsl:stylesheet>

System ACs

Some Adaptive Components are considered part of FIT and are usually referenced to as System ACs. These System ACs include for example ac-stage or ac-phonelink.

Overriding System ACs

If you want to register your own AC with the same name as a System AC, all you need to do is name your AC the same in the respective manifest and XSL files.