Aras Innovator Platform

7.2 Configuration Examples

Overview

This section provides examples that describe how to configure a Tech Doc-Enabled Item to achieve a specified purpose. Each sub-section includes an Objective that identifies the purpose of the example.

7.2.2 Example – Auto-creating hidden elements from Tech Doc Item Properties

7.2.2.1 Objective

Show how Document Elements can be automatically created, using values from the active Technical Document instance which then are included, but not displayed in the editor. This example shows how an Administrator can configure the system to generate S1000D ident-like information at the beginning of a document by using S1000D Data Module (DM) parameters stored as Properties on the Technical Document. In this case, the DM can use the same ‘Ident’ information to identify the purpose of the Technical Document to authors who need to search for existing documents. This example uses XML Elements from an S1000D specification, but it can be used for any Properties added to the Tech Doc-Enabled ItemType.

7.2.2.2 Solution

Use a Content Generator for a container ‘ident’ Document Element that will extract parameter values from the associated Technical Document and add them to the selected node. Use CSS to target nodes within the container and hide the rendering of the corresponding content.

Note
regarding the creation of Content Generator Methods, the first commented line in the code is required - //MethodTemplateName=CSharp:Aras.TDF.ContentGenerator(Strict); It is used to identify the proper method template.

7.2.2.3 Content Generator

//MethodTemplateName=CSharp:Aras.TDF.ContentGenerator(Strict);

// a Document Element object representing the Document Element node that was

// placed in the document and associated with this Content Generator is passed

// into this Method call as 'targetElement'. The cast here is actually not

// necessary since it's the base class type for Document Elements. Container

// nodes will be instantiated as 'DocumentSchemaElement' objects. This is used

// for the 'ident' node.

DocumentSchemaElement targetItem = targetElement as DocumentSchemaElement;

// The Innovator instance is needed so that we can query Properties from the

// Technical Document Item associated with this ident node

Innovator inn = this.Factory.InnovatorInstance;

// The object 'executionContext' is passed into this Method and contains the

// id of the current document. Use it to query for the Tech Doc Properties

Item doc = inn.getItemById( "tp_Block", executionContext.DocumentId );

if(doc == null || doc.isError())

return;

// The targetElement will be null if the case above failed. In this case, the

// input targetItem is not the Document Element Type expected

if (targetItem != null) {

// Content Generators can be executed multiple times for a node by the user

// This call will clear all children of this target node in case this has

// already been called.

targetItem.ClearChilds();

// This should be empty

if (!targetItem.IsEmpty)

{

// Use the doc Item to set properties for non-formatted text nodes

// Note the call to the constructTextNode method below

targetItem.AddChild(constructTextNode("modelic", doc.getProperty("modelic")));

targetItem.AddChild(constructTextNode("sdc", doc.getProperty("sdc")));

targetItem.AddChild(constructTextNode("chapnum", doc.getProperty("chapnum")));

targetItem.AddChild(constructTextNode("subject", doc.getProperty("subject")));

targetItem.AddChild(constructTextNode("discode", doc.getProperty("discode")));

targetItem.AddChild(constructTextNode("incode", doc.getProperty("incode")));

targetItem.AddChild(constructTextNode("itemloc", doc.getProperty("itemloc")));

}

}

} // note the extra closing brace

// This method will construct a node used for non-formatted text in a Technical

// Document. Note that nodes of this type are different than formatted text

// nodes. In this case, the logic within this method is the only way to create

// nodes of this type

DocumentTextNode constructTextNode(string name, string value)

{

XmlNode xmlNode = this.Factory.ConstructElementOrigin(name);

xmlNode.InnerText = value;

DocumentTextNode txtNode = new DocumentTextNode(this.Factory, xmlNode);

return(txtNode);

// Note the absence of a closing node here

7.2.2.4 CSS

.ident .modelic, .ident .sdc, .ident .chapnum, .ident .subject, .ident .discode, .ident .incode, .ident .itemloc

{

display: none;

}

All node names in a schema are used as class names in the generated HTML. As such, you can use the class designator – for example: ‘.ident’ – to refer to the corresponding element in a Technical Document. In this case, the child nodes (‘modelic’, ‘sdc’, ‘chapnum’, etc.) are all children of the ‘ident’ element. So, the example CSS rule - .ident .modelic – targets any node with a class of ‘modelic’ that is a descendent of an ‘ident’ node. For all these types, the CSS ‘display: none’ will cause the browser to hide the contents of the node. In this case, the text. Also, if a ‘modelic’ (or any of the others) were not included as a descendent of an ‘ident’ node, they would display.

7.2.2.5 Schema

<xs:element name="ident">

<xs:complexType>

<xs:sequence>

<xs:element ref="modelic"/>

<xs:element ref="sdc"/>

<xs:element ref="chapnum"/>

<xs:element ref="subject"/>

<xs:element ref="discode"/>

<xs:element ref="incode"/>

<xs:element ref="itemloc"/>

</xs:sequence>

</xs:complexType>

</xs:element>

<xs:element name="modelic"><xs:complexType mixed="true"/></xs:element>

<xs:element name="sdc"><xs:complexType mixed="true"/></xs:element>

<xs:element name="chapnum"><xs:complexType mixed="true"/></xs:element>

<xs:element name="subject"><xs:complexType mixed="true"/></xs:element>

<xs:element name="discode"><xs:complexType mixed="true"/></xs:element>

<xs:element name="incode"><xs:complexType mixed="true"/></xs:element>

<xs:element name="itemloc"><xs:complexType mixed="true"/></xs:element>

The ‘ident’ node is a container. Each child element uses references (for example ref=”modelic”) to identify the corresponding node. Note that these nodes do not extend the aras:text type and instead are declared as a complex type with ‘mixed=true’. These are treated as non-formatted text nodes in Tech Docs.

7.2.3 Example – Auto-creating inline link and text to external references:

7.2.3.1 Objective

Show how inline text content and a ‘refdm’ element, that is used to reference a separate Data Module (DM), can be authored within a Technical Document. S1000D content typically contains paragraphs of text with embedded nodes. In XML-speak, that is referred as ‘mixed content’. The Technical Document Framework does not support this behavior and nodes must either contain only child nodes or text; but not both. In addition, although links in Tech Docs can either refer to content within the same document or content within other Technical Documents, there is no out-of-the-box mechanism to automatically generate link text based on the content that is being referenced.

7.2.3.2 Solution

Use an ‘Item Document Element’ to show how a Document Element within a Technical Document can be used to reference another Technical Document Item in Innovator. Item Document Elements can be configured to always reference a particular ItemType. In this case, use the Technical Document ItemType (‘tp_Block’). Use a Content Generator to query content from the referenced Item to automatically generate link text and use the Content Generator API to format the generated link text as a link to the referenced document. This example also necessitated the creation of a separate (and non-S1000D compliant) node – ‘p’ that will be used for inline text content. Note that the intent here is to use this node solely for inline text content. Use CSS to target p and refdm nodes within the container and force them to render as inline elements when rendered in HTML and PDF.

7.2.3.3 Schema

<xs:element name="para">

<xs:complexType>

<xs:choice maxOccurs="unbounded">

<xs:element ref="p" minOccurs="0" maxOccurs="unbounded" />

<xs:element ref="refdm" minOccurs="0" maxOccurs="unbounded" />

</xs:choice>

</xs:complexType>

</xs:element>

<xs:element name="p">

<xs:complexType>

<xs:complexContent>

<xs:extension base="aras:text"/>

</xs:complexContent>

</xs:complexType>

</xs:element>

<xs:element name="refdm">

<xs:complexType>

<xs:complexContent>

<xs:extension base="aras:itemType">

<xs:choice maxOccurs="1">

<xs:element ref="p" minOccurs="1" maxOccurs="1"/>

</xs:choice>

<xs:attribute name="typeId" type="xs:string" fixed="ED9F61ADA4334D7D94361F426C081DB5" />

</xs:extension>

</xs:complexContent>

</xs:complexType>

</xs:element>

In this schema example, we are treating an S1000D para node as a container with child elements of type ‘p’ and ‘refdm’. In this case, p elements can be interleaved with refdm elements without any restrictions on cardinality or order. The refdm node is configured here to extend the aras:itemType element. When this is done, Document Elements of this type can reference any ItemType specified in the tp_Item PolyItem. For this example, I added the Technical Document ItemType – tp_block – to this PolyItem. For example:

Also, in the schema definition, the addition of the typeId attribute for the refdm element will identify the Item ID for the ItemType to restrict references to. In this case, I added the ItemType ID for the tp_Block ItemType (ED9F61ADA4334D7D94361F426C081DB5): thus, targeting references to only a Technical Document. This is important because we make assumptions about the referenced Item on the Content Generator logic described below.

7.2.3.4 CSS

.para .p, .para .refdm

{

display: inline-block;

padding-right: .5em;

}

These CSS rules target p and refdm classes only when they are descendants of a para element. The styling will render the content of these nodes as inline (instead of the default block). In addition, it adds some right padding to adequately space each p and refdm content.

7.2.3.5 Content Generator

//MethodTemplateName=CSharp:Aras.TDF.ContentGenerator(Strict);

// A Document Element object representing the Document Element node that was

// placed in the document and associated with this Content Generator is passed

// into this Method call as 'targetElement'. The cast here is necessary since

// the base class type for Document Elements is 'DocumentSchemaElement' However,

// this Method uses an Item Document Element since the refdm node is configured

// in the schema as an extension to 'aras:item'. When this Content Generator is

// called, the target Element will include a reference to a Technical Document

// that the user has chosen after they placed the refdm node in the document.

ItemDocumentElement targetItem = targetElement as ItemDocumentElement;

// The targetElement will be null if the case above failed. In this case, the

// input targetItem is not the Document Element Type expected

if (targetItem != null) {

// Content Generators can be executed multiple times for a node by the user

// This call will clear all children of this target node in case this has

// already been called.

targetItem.ClearChilds();

// This should be empty

if (!targetItem.IsEmpty)

{

// The target Item, being of type ItemDocumentElement, will have a

// method (GetItemProperty) to retrieve a Property value of the referenced

// Item. In this case, we want to build the link text based on

// added Properties to the Technical Document ItemType (e.g., chapnum,

// subject, etc.). This code builds that link text

string linkText = targetItem.GetItemProperty("chapnum", " ") + "-";

linkText += targetItem.GetItemProperty("subject", " ") + "-";

linkText += targetItem.GetItemProperty("discode", " ") + ":";

linkText += targetItem.GetItemProperty("incode", " ");

linkText += targetItem.GetItemProperty("itemloc", " ");

// This line will construct a child 'p' node that will be used for the

// link text.

TextDocumentElement pElement = (TextDocumentElement) this.Factory.NewText("p", linkText);

// This line will format the text content of the p node as a link

// and have it reference the same Technical Document Item the user has

// selected when them placed the refdm node. The first argument is the

// id of the Technical Document Item, the second is the id of the node

// within the document. Since the schema locked the referenced ItemType

// to a Technical Document, we know what we can create a link to it. The

// root node in a Technical Document has the same id as the document Item

pElement.Strings[0].SetLink(targetItem.ItemId,targetItem.ItemId);

// Add the p node as a child of the given refdm node

targetItem.AddChild(pElement);

}

}

7.2.4 Example – Using Attributes to apply styling

7.2.4.1 Objective

Provide a mechanism to allow authors to size images in a technical document. By default, images are placed left justified and sized to fit the maximum space within their container. This is typically the full width of the space minus any margins.

7.2.4.2 Solution

Use attribute values together with CSS selectors to target and apply a set of style rules for a selected image. This technique can be applied to any Document Element and any style configuration, including positioning. This example demonstrates two techniques. The first example will show how to use an attribute to identify a select rule. The second uses attribute values to set specific styles typed by the author. The first option is probably the most useful as it is easy for the end user. The second option can provide for greater flexibility (and unwanted consequences)

7.2.4.3 Option A

In this solution an attribute is added to the Image Document Element – Graphic. The attribute name is ‘size’ and there will be three allowed choices: small’, ‘medium’, and ‘large’. Here is the related schema:

7.2.4.4 Schema

<xs:element name="Graphic">

<xs:complexType>

<xs:complexContent>

<xs:extension base="aras:imageType">

<xs:attribute name="size" type="ImageSizeAttType"/>

</xs:extension>

</xs:complexContent>

</xs:complexType>

</xs:element>

<xs:simpleType name="ImageSizeAttType">

<xs:restriction base="xs:string">

<xs:enumeration value="small"/>

<xs:enumeration value="medium"/>

<xs:enumeration value="large"/>

</xs:restriction>

</xs:simpleType>

In this sample, there is an added ‘size’ attribute to the Graphic Document Element and, using a restriction, specified the allowed values of ‘small’, ‘medium’, and ‘large’. The Attribute editor will display these values in a picklist:

CSS:

.Graphic[size='small’] img

{

max-width: 100px;

}

.Graphic[size='medium’] img

{

max-width: 300px;

}

.Graphic[size='large’] img

{

max-width: 600px;

}

These style rules target the img tag using the parent ‘Graphic’ container with a ‘size’ attribute of either ‘small’, ‘medium’, or ‘large’. Of course, other values can be added as well. In addition, other styles can be applied. The example is really showing how the author can use attribute values to assign styling.

7.2.4.5 Option B

In this alternative example, an option is provided to allow the user to set a specific value for size. Here is the related schema:

7.2.4.6 Schema

<xs:element name="Graphic">

<xs:complexType>

<xs:complexContent>

<xs:extension base="aras:imageType">

<xs:attribute name="style" type="xs:string"/>

</xs:extension>

</xs:complexContent>

</xs:complexType>

</xs:element>

In this sample, there is an added ‘style’ attribute to the Graphic Document Element. Note the name ‘style’ is important here. The Attribute editor will display the attribute using a simple string editor:

In this example, we use the value of the attribute to identify a variable – ‘width’ in this case and its value. This is applied to the width style rule in the following CSS:

7.2.4.7 CSS

.Graphic

{

width: var(width);

}

Of course, other style rules can be added as well. This example shows an approach that adds flexibility but requires the user to know more about what they’re typing – Use with caution.

7.2.5 Example – Populating PDF header content from attribute data

7.2.5.1 Objective

Automate the creation, placement, and content for a PDF page header using information from the technical document. In this example, the user wants to use information stored in the attributes of a particular Document Element in the PDF Header of a published document.

7.2.5.2 Solution

Use CSS rules and functions that apply to page-based media to create the PDF header and add static and custom content. Note that this example uses Attributes for the source for some of the content, but another element content can be used as well. For example, the text in a Title Document Element.

In this example, there is an added ‘chapnum’ and ‘modelic’ attribute to a Document Element named ‘ident’. These values can be populated by the Attribute Editor or added by a Content Generator like:

7.2.5.3 Content Generator

// Use Property values from the Technical Documents Item for attribute values

targetItem.SetAttribute(“modelic”, doc.getProperty(“modelic”));

targetItem.SetAttribute(“chapnum”, doc.getProperty(“chapnum”));

7.2.5.4 CSS

@page

{

size: 8.5in × 11.0in;

margin: 40pt 0 40pt 0;

padding-bottom: 1em;

padding-top: 1em;

@top-right

{

content: "Test " string(modelic) ", " string(chapnum);

color: white;

font-family: Tahoma, Geneva, sans-serif;

background-color: #8C0827;

padding-right: 3em;

}

}

.ident

{

string-set: modelic attr(modelic), chapnum attr(chapnum);

}

The Style applied to the PDF output uses @page and the margin identifier @top-right to position the content for the header. In this case, the content is derived from two string sets: ‘modelic’ and ‘chapnum’; which are populated from the attributes of the same name in the ‘.ident’ class DOM elements using the attr() function. Note that only one string-set rule can be used in a group. In this case, we set the value of both string set variables separated by a comma.

Here is the header portion of a generated PDF document. Note that the Header text is as follows:

Static Text – ‘Test’, followed by the value of the modelic attribute (in this case ‘Skyhook’), followed by a comma and space – ‘, ‘, followed by the value of the chapnum attribute (in this case ‘490’).

7.2.6 Example – Creating a Table, in which each row points to individual Parts

7.2.6.1 Objective

Provide a means of auto-generating Table Rows where each Row Object is an Item Document Element, ‘pointing to’ Part Items and the cells of the Row contain individual Part Item Property data.

7.2.6.2 Solution

For this solution, a typical Table Document Element can’t be used because it derives from an aras:table element. The same is true for aras:row and aras:cell elements. Also, the first row of the table – the header row - needs to be auto-created with a cell for each column. Finally, the ‘Row’ Document Elements need to be ‘ItemDocumentElements since each added row should be associated with a selected Item (Part in this example).

7.2.6.3 Schema

For this structure, the top-level node – PartTable – is the container with a required first child of PartHeader, and any number of PartRows. Each PartRow has any number of PartCells; which contain a single Text Document Element. Note the use of default style attributes in this schema. They use ‘display: table/table-row/table-cell’ values, which when used within <div> style attributes treat the PartTable like a standard HTML table, PartHeader/Rows like table rows, and PartCells like table cells, etc.

<xs:element name="PartTable">

<xs:complexType>

<xs:sequence>

<xs:element ref="PartHeader" minOccurs="1" maxOccurs="1"/>

<xs:element ref="PartRow" minOccurs="0" maxOccurs="unbounded"/>

</xs:sequence>

<xs:attribute name="style" default="display:table"/>

</xs:complexType>

</xs:element>

<xs:element name="PartHeader">

<xs:complexType>

<xs:sequence>

<xs:element ref="PartCell" minOccurs="0" maxOccurs="unbounded"/>

</xs:sequence>

<xs:attribute name="style" default="display:table-row" />

</xs:complexType>

</xs:element>

<xs:element name="PartRow">

<xs:complexType>

<xs:complexContent>

<xs:extension base="aras:itemType">

<xs:choice maxOccurs="unbounded">

<xs:element ref="PartCell" minOccurs="0" maxOccurs="unbounded"/>

</xs:choice>

<xs:attribute name="style" default="display:table-row"/>

<xs:attribute name="typeId" type="xs:string" fixed="4F1AC04A2B484F3ABA4E20DB63808A88"/>

</xs:extension>

</xs:complexContent>

</xs:complexType>

</xs:element>

<xs:element name="PartCell">

<xs:complexType>

<xs:sequence>

<xs:element ref="Text" minOccurs="0" maxOccurs="1"/>

</xs:sequence>

<xs:attribute name="style" default="display:table-cell"/>

</xs:complexType>

</xs:element>

7.2.6.4 Content Generator

There needs to be a Content Generator for the PartHeader Document Element, which will be called immediately after the PartTable Document element is placed. This Method will add the PartHeader, PartCells, and Text for all columns required for the table. Similarly, a Content Generator needs to be created for the PartRow Document Elements; which will point to some selected Part (given that they extend aras:itemType and the ‘typeId’ is fixed to the ItemType Id of Part. In Innovator 11.0 SP15, the ability to pass JSON-formatted string content to the Content Generator Method was added. We can use this to pass in the names of Columns and Properties to add for the PartHeader and PartRow Content Generators, respectively. For the PartHeader Document Element, the following JSON is used for this example:

Note the ‘Generator Parameters’ form element. It uses a JSON-configured editor so that JSON elements can be color-coded as shown. Opening the XML Schema Element exposes this form. In this case, a single array element is used – props – with a list of all Properties names to use for the Part Row Contents. The number of array elements determines the number of columns. A similar construct is used for the PartHeader Content Generator; but using Column Names as the array elements.

//MethodTemplateName=CSharp:Aras.TDF.ContentGenerator(Strict);

// The Target Items should be a PartRow Document Element

ItemDocumentElement targetItem = targetElement as ItemDocumentElement;

if (targetItem != null) {

targetItem.ClearChilds();

// if referenced item was set, then

if (!targetItem.IsEmpty)

{

// The configured parameters should contain an array labeled 'props'

// that contains an array of string values to indicate the properties

// to use for the associated referenced Item

if (!this.GenerationParameters.ContainsKey("props"))

{

throw new InvalidOperationException("'props' generation parameter was not passed.");

}

// Create cells for each property name configured as parameters

System.Collections.ArrayList props = (System.Collections.ArrayList) this.GenerationParameters["props"];

foreach(String propName in props)

{

DocumentSchemaElement cellElement = (DocumentSchemaElement) this.Factory.NewElement("PartCell");

cellElement.AddChild(this.Factory.NewText("Text", targetItem.GetItemProperty(propName, " ")));

// Add as a child

targetItem.AddChild(cellElement);

}

}

7.2.6.5 Renderer

The following Editor renderer will display the part number for the node text in the Tree View. This is helpful in identifying the referenced Part in the Tree. Note that this example is using data in the content for the part number, so it assumes that the part number (in this case) is stored in the second column. Note that Render Methods are described in Section 2.3.4.

return

{

constructor: function (args)

{},

// Set the name of the tree node based on the referenced Part

GetTreeName: function(/*WrappedObject*/renderObject)

{

// Get the of the referenced Part

// return the content of the second column - Part Item Number

if(renderObject.origin.childNodes.length > 1)

return renderObject.origin.childNodes[1].text;

else

return "Part";

}

};

7.2.6.6 CSS

The CSS targets each Document Element as follows. Note the use of ‘border-collapse’ for the PartTable class.

.PartCell {

border: 1px solid black;

padding-left: 1em;

padding-right: 1em;

padding-top: 0em;

padding-bottom: 0em;

}

.PartHeader .PartCell

{

background: grey;

text-align: center;

}

.PartHeader .PartCell .Text

{

font-weight: bold;

font-size: 1.2em;

color: white;

}

.PartCell .Text

{

padding: 0em;

}

.PartTable {

border-collapse: collapse;

}