General Interface is an open source project hosted by the Dojo Foundation

Common Data Format (CDF)

Common Data Format (CDF)

The Common Data Format (CDF) is an XML Schema that provides an abstraction layer for client data. It allows components of an application to use a single data format. Benefits include the ability to share data among components, reliably transfer data between client controls using drag-and-drop, and perform data mapping. Component data can be inserted or updated without using XSLT. The jsx3.xml.CDF interface also defines a common set of methods for manipulating data. The jsx3.xml.CDF.Document class, which implements the CDF interface, can also be used to expose the CDF convenience methods on an XML document.

Components that consume structured data require CDF. These components include:

  • Menu
  • Tree
  • Select and Combo
  • Matrix
  • Charting

There are two ways to work with CDF documents:

  • Through a CDF component, such as Matrix and Tree
  • Directly with the API. See the jsx3.xml.CDF.Document class in the online API help in General Interface Builder.

CDF Schema

The CDF schema is described by the following XSD:

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <xsd:element name="data">
  <xsd:complexType>
   <xsd:sequence>
    <xsd:element type="cdfrecord" name="record"
     maxOccurs="unbounded" minOccurs="0"/>
   </xsd:sequence>
   <xsd:attribute name="jsxid">
    <xsd:simpleType>
     <xsd:restriction base="xsd:string">
      <xsd:enumeration value="jsxroot"/>
     </xsd:restriction>
    </xsd:simpleType>
   </xsd:attribute>
  </xsd:complexType>
 </xsd:element>

  <xsd:complexType name="cdfrecord">
   <xsd:sequence>
    <xsd:element type="cdfrecord" name="record"
     maxOccurs="unbounded" minOccurs="0"/>
   </xsd:sequence>
   <xsd:attribute name="jsxtip" type="xsd:string"/>
   <xsd:attribute name="jsxvalue" type="xsd:string"/>
   <xsd:attribute name="jsxdivider" type="xsd:string"/>
   <xsd:attribute name="jsxtext" type="xsd:string"/>
   <xsd:attribute name="jsxstyle" type="xsd:string"/>
   <xsd:attribute name="jsxkeycode" type="xsd:string"/>
   <xsd:attribute name="jsxunselectable" type="xsd:string"/>
   <xsd:attribute name="jsxexecute" type="xsd:string"/>
   <xsd:attribute name="jsxgroupname" type="xsd:string"/>
   <xsd:attribute name="jsximg" type="xsd:string"/>
   <xsd:attribute name="jsxselected" type="xsd:string"/>
   <xsd:attribute name="jsxid" use="required" type="xsd:string"/>
  </xsd:complexType>

</xsd:schema>

The CDF schema is an open schema that can be extended using custom entities and attributes. In the following example, the jsxtext and jsxid attributes are system attributes with special meaning. The jsxid attribute is required for a record in the CDF. This attribute acts as a key and should be a unique value. The number and name attributes are custom, developer-defined attributes.

<?xml version="1.0"?>
<data name="" number="" jsxid="jsxroot">
  <record name="a" number="0" jsxid="null" jsxtext="Select a
    State"/>
  <record name="b" number="1" jsxid="AL" jsxtext="ALABAMA"/>
  <record name="c" number="2" jsxid="AK" jsxtext="ALASKA"/>
  <record name="d" number="3" jsxid="AZ" jsxtext="ARIZONA"/>
  <record name="e" number="4" jsxid="AR" jsxtext="ARKANSAS"/>
  <record name="f" number="5" jsxid="CA" jsxtext="CALIFORNIA"/>
  <record name="g" number="6" jsxid="CO" jsxtext="COLORADO"/>
  <record name="h" number="7" jsxid="CT" jsxtext="CONNECTICUT"/>
  <record name="i" number="8" jsxid="DE" jsxtext="DELAWARE"/>
  ...
  <record name="Y" number="50" jsxid="WI" jsxtext="WISCONSIN"/>
  <record name="Z" number="51" jsxid="WY" jsxtext="WYOMING"/>
</data>

CDF Structural Elements

CDF documents consist of an XML declaration and a data element that contains all records. Usually, the data element also contains at least one record element with attributes.

Depending on the component, a record can represent a table row, a node in a tree, a menu item, and so on. Although the record element isn't required, at least one record is required for a CDF component to display data.

Hierarchical structures, such as submenus, can also be defined by nesting records within records. Entities by any other name, such as a node named lookup as opposed to record, are not displayed on-screen, but can be useful for organizing information within the CDF model. If additional hierarchies are described by nesting records, the view displays these where relevant. Currently, the Matrix, Menu, and Tree controls visualize hierarchical relationships, while the other controls flatten these out. Consider the following CDF structures and their visual representations as defined by the Menu class.

Underlying CDF Model On-screen View
<data jsxid="jsxroot"/>rOj
<data jsxid="jsxroot">
  <record jsxid="1" jsxtext="New"/>
  <record jsxid="2" jsxtext="Open"/>
  <record jsxid="3" jsxtext="Save"/>
</data>
<data jsxid="jsxroot">
  <record jsxid="1" jsxtext="New"/>
  <record jsxid="2" jsxtext="Open">
    <record jsxid="2a" jsxtext="Image..."/>
    <record jsxid="2b" jsxtext="Document..."/>
  </record>
  <record jsxid="3" jsxtext="Save"/>
</data>
<data jsxid="jsxroot">
  <record jsxid="2" jsxtext="Font">
    <record jsxid="2a" jsxtext="Bold"
      jsxgroupname="font" jsxselected="1"/>
    <record jsxid="2b" jsxtext="Underline"
      jsxgroupname="font"/>
    <record jsxid="2c" jsxtext="Italic"
      jsxgroupname="font"/>
  </record>
  <record jsxid="3" jsxtext="Color"/>
</data>
<data jsxid="jsxroot">
  <record jsxid="1a" jsxtext="Bold"/>
  <record jsxid="1b" jsxtext="Underline"
    jsxdivider="1"/>
  <record jsxid="1c" jsxtext="Italic"
    jsximg="x.gif"/>
  <lookups jsxid="2">
    <record jsxid="3" jsxtext="IL"/>
    <record jsxid="4" jsxtext="MA"/>
    <record jsxid="5" jsxtext="NV"/>
    <record jsxid="6" jsxtext="WI"/>
  </lookups>
</data>

CDF System Attributes

System attributes are reserved attributes used by General Interface to render CDF components. Each component has an associated XSL file for transforming CDF code into HTML for display in your application. The system attributes listed in are referenced in the component XSL.

The jsxid attribute is required for all CDF components and must be a unique value. Support for optional attributes varies according to component. The jsxtext and jsximg attributes are commonly used and apply to most CDF components.

Attribute Component Description
jsxdisabled Button, Checkbox, ImageButton, Menu, RadioButton, ToolbarButton Disables the record so that a user cannot select it. The record text is displayed in a grey color. Specify a value of 1 to disable the record.
jsxdivider Menu Creates a linear divider between the current record and the preceding record. Specify a value of 1 to display the divider.
jsxexecute Matrix, Menu, Tree, Table Allows an event to run a program function when the event fires. A function name or a string of JavaScript statements can be specified. Separate multiple statements with a semicolon (;) character. For example, jsxexecute="var a=12;var b='5';"
jsxgroupname Matrix, Menu Adds the record to a group that can be used by multiple CDF records or components. Records in a group are mutually exclusive options. For example, a menu for selecting fonts allows only one font option to be chosen.
jsxid all Uniquely identifies the CDF record. This value can be user-defined or automatically generated using the getKey() method (jsx3.xml.CDF). This attribute is required.
jsximg Matrix, Menu, Tree, Table References a graphic file to use as an icon. Specify the file path relative to the project directory, for example, images/icon.gif. Image position depends on the component. For best results, use a 16x16 transparent GIF file.
jsxkeycode Menu Defines a keyboard shortcut for calling the record. Specify any named key, such as Tab, Alt, Shift, or Ctrl, and use the plus character (+) as a delimiter. For example, jsxkeycode="ctrl+e".
jsxnomask Button, Checkbox, ImageButton, Menu, RadioButton, ToolbarButton (when used as a Matrix mask) Disables a visible mask (checkbox, radio button, menu, and so on) so it's hidden and a user can't select it. Specify a value of 1 to hide the mask for that row.
jsxselected Matrix, Menu, Tree, Table Specifies whether the record is selected or not selected by default. Specify a value of 1 to define the record as selected.
jsxstyle Matrix, Menu, Tree, Select, Table Applies a CSS style to this record. Specify any CSS code. For example, jsxstyle="font-weight:bold;".
jsxtext Matrix, Tree, Select, Menu, Table Defines the visible text for the record. For example, in a menu component, the value of this attribute is the name of the menu item as displayed in the application.
jsxtip Matrix, Tree, Select, Menu, Table Defines the tooltip text to display when the cursor hovers over the record. For example, jsxtip="Type your address here".
jsxunselectable Matrix, Tree, Table Specifies whether a tree node or list item can be selected by end users. Specify a value of 1 to prevent the record from being selected. When the value of this attribute is 1, the execute method for the record cannot be called.
Any CDF attribute value of jsxtext, jsxtip, jsximg, jsxkeyode, jsxstyle, or jsxclass in the form of {xxx} is replaced with the dynamic property xxxif it exists. If the property doesn't exist, then the value isn't changed. Dynamic properties come from the server owning the CDF control. The conversion occurs when the XML document is retrieved from source and before it's placed in the cache. For more information, see the API for CDF.convertProperties().

CDF records can also include custom attributes. Custom attribute names can be any string except names of system attributes. To add attributes to a CDF record, call the insertRecordProperty() method. You can also manually edit the CDF document on the file system, or open the cached file in General Interface Builder.

Creating CDF Documents

CDF documents are created both at design time and at runtime.

There are several ways to create CDF documents:

  • Create a new XML file that conforms to the CDF schema
  • Create a new instance of a CDF component
  • Instantiate a CDF using the API
  • Map a parent element to a CDF in the XML Mapping Utility
  • Transform an existing XML document using the API

Creating an XML File

To create a new CDF document in your project,

  1. Choose File > New > XML Document.
  2. Select CDF Document from the list to add the basic template for a CDF document.
  3. Press Ctrl+Spacebar again to add templates for attributes, additional records, or an XML header declaration.

Creating a new CDF Component

When you drag a CDF component, such as Matrix or any other component that implements the jsx3.xml.Cacheable interface, to the work area in General Interface Builder, a CDF document is automatically created in the Local Data Cache palette. This document, which contains default data, is associated with the component for the length of the browser session.

If you do not explicitly set an XML Cache ID for a CDF-type control, such as matrix, menu, and select, an ID is automatically generated by the system. The naming convention is a concatenation of the control ID. For example, object.getId() plus an _XML suffix. An ID looks similar to the following: _jsx_1_5_XML.

Instantiating a CDF Document Using the API

A CDF component isn't required for creating a CDF. Instead, you can instantiate a CDF directly using the factory method, jsx3.xml.CDF.Document.newDocument.

In this code example, a new XML document that represents an empty CDF document is created:

var oDoc = jsx3.xml.CDF.Document.newDocument();
var o = new Object();
o.jsxid = jsx3.xml.CDF.getKey();
o.jsxtext = "hello";
oDoc.insertRecord(o);
oDoc;
sampleWSDLMapping1.getCache().setDocument("foo",oDoc);

This is a good choice if a CDF component isn't required. For example, the Properties Editor palette in General Interface Builder uses the API to create the CDF on the fly at runtime and generate the list of available properties for the selected component in the work area.

For method details for the jsx3.xml.CDF.Document class, see the online API help in General Interface Builder.

Mapping a Parent Element to a CDF Document

For outbound requests, map an element to the CDF Document option in the Type drop-down list in the Mappings table of the XML Mapping Utility. A new CDF document is automatically created when the response is received.

Transforming an existing XML Document

You can use method calls to the jsx3.xml.Template class to transform an existing XML document. Using these methods, you can apply XSLT to an existing XML document to transform the XML into the CDF format. The following sample JavaScript code illustrates how to load and transform an XML file into CDF.

var myXML =  new jsx3.xml.Document();
myXML.load("JSXAPPS/myProjectDir/xml/nonCDF.xml");
var myXSL =  new jsx3.xml.XslDocument();
myXSL.load("JSXAPPS/myProjectDir/xsl/CDF.xsl");
myXSL.transform();

For method details, see the online API help in General Interface Builder.

Accessing CDF Data

Data in CDF documents can be accessed using JavaScript object notation or XML record format.

Accessing a CDF Document Directly

If you want to access the CDF document that belongs to a control, you simply call the {{getXML()}}method. The XML source document and the CDF source document are synonymous for the CDF controls, such as matrix, menu, select and so on. For example.

// get a handle to the matrix
var objMatrix =  myServer.getJSXByName("myMatrix");
var objCDF =     objMatrix.getXML();

Getting a Handle to a CDF Document

To access data in a CDF document of a CDF component, first get a handle to the document in one of the following ways:

  • From cache, by calling the getDocument() method (jsx3.app.Cache). This method takes the name of the cached CDF document as input, which is system-defined by default. For example,
    myserver.getCache().getDocument("myDocument");

    To avoid working with the system-defined name, use the XML Cache ID property to specify a name for the CDF document or access the CDF document through the object.

  • From an object, by calling the getXML() method (jsx3.xml.Cacheable). All CDF components implement the jsx3.xml.Cacheable interface, which provides this method. For example,
    var objXML = myCdfControl.getXML();

    The result of this method call is a jsx3.xml.Document instance.

    If you've instantiated a CDF directly and aren't using a CDF component, you don't need to get a handle to the CDF document.

Accessing a Node

You can access a record node within a CDF document in one of the following ways:

  • By calling the selectSingleNode() method (jsx3.xml.Entity) for the CDF document and passing the appropriate XSL query. The following code example returns the node with element name record and jsxid value of 12.
    myCdfDocument.selectSingleNode(//record\[@jsxid='12']);

    * From an object that implements the CDF interface, by calling the getRecordNode() method (jsx3.xml.CDF). For example,

    myObject.getRecordNode(12);

Using CDF Methods

This section gives an overview of CDF methods and describes how to use the methods to interact with a CDF document.

CDF Methods Overview

The following table provides an overview of available methods defined by the jsx3.xml.CDFinterface. For detailed method descriptions, including input and output information, see the online API help in General Interface Builder.

Method Summary
getKey Generates a unique identifier for use as the jsxidattribute for a CDF record. This value persists only for the length of the browser session. Unique values that persist across browser sessions must be generated by the developer.
newDocument A factory method for creating a new CDF document containing the following XML: <data jsxid="jsxroot"/>
adoptRecord Transfers a CDF record between components. The record must have a unique jsxidvalue to be transferred. If no CDF document exists for the adopting parent, a document is created and added to the cache. If successful, this method returns a jsx3.xml.Entity instance, which is an object handle to the transferred record. The view for the record is automatically updated.
adoptRecordBefore Equivalent to adoptRecord, except that the to-be relationship is as a previousSibling to the CDF record identified by the parameter, strSiblingRecordId.
deleteRecord Deletes a CDF record from the component CDF document. If successful, this method returns a jsx3.xml.Entity instance, which is an object handle to the deleted record node. Updating the view for the record is optional.
deleteRecordProperty Deletes a specific property from a CDF record. The record must have a unique jsxid value. Do not call this method to delete the jsxid property.
getRecord Returns a JavaScript object that is a clone of the specified CDF record. Any updates to this clone doesn't affect the original record unless you call object.insertRecord() and pass the modified clone as the input parameter.
getRecordNode Returns a jsx3.xml.Entity instance representing the actual object handle to the CDF record. Updating this object also directly updates the model. To synchronize the view after an update, call the following: object.redrawRecord(strRecordId,jsx3.xml.CDF.UPDATE);
insertRecord Inserts a new record into the CDF document for the component. If no CDF document exists for the component, a document is created and added to the cache. If a record with the same jsxid value already exists, the existing record is updated.
insertRecordBefore Creates a new CDF record and inserts it into the CDF data source of this object, before the record identified by the parameter, strSiblingRecordId.
insertRecordNode Inserts a new record node into the control's XML-formatted data source. If no CDF document exists for the component, a document is created and added to the cache. If a record with the samejsxid value already exists, the existing record is updated. This function is for inserting records as XML node entities rather than JavaScript objects.
insertRecordProperty Inserts a new CDF attribute and corresponding value for the specified CDF record. The attribute can be one of the system attributes defined in CDF System Attributes or a custom attribute. Updating the view for the record is optional.

Adding Records

Use the insertRecord() and insertRecordNode() methods to add records to a CDF document. The two methods are functionally equivalent, but insertRecord() takes a JavaScript object as input, while insertRecordNode() takes an XML entity. With insertRecord(), you specify the jsxid attribute, along with any other CDF attributes for the record, as properties of the object.

insertRecord Example

The following sample JavaScript code illustrates how to add records to a Matrix component using insertRecord() :

// get a handle to the matrix
var objMatrix = myServer.getJSXByName("myMatrix");

// new CDF record
var objRecord =   new Object();
objRecord.jsxid = jsx3.CDF.getKey();
objRecord.Date =  myServer.getJSXByName("dateEntry").getValue();
objRecord.Security =
   myServer.getJSXByName("securityEntry").getValue();
objRecord.Open =  myServer.getJSXByName("openEntry").getValue();
objRecord.High =  myServer.getJSXByName("highEntry").getValue();

// insert the record and pass true so it is redrawn without repaint
objMatrix.insertRecord(objRecord, null, true);

In this example, the new CDF record object is objRecord. The first property defined for this object, jsxid, is a required system attribute that must be unique. The getKey() method is used to generate a unique jsxid value for this record. Other properties, Date, Security, Open, and High, become custom attributes of the CDF record. Values for these properties are provided by components in the application.

In addition to a JavaScript object, the insertRecord() call takes two parameters — the numeric identifier (jsxidvalue of a parent object) and an optional Boolean parameter for a redraw operation. When null is specified for the second parameter, as in this example, the record is added to the root element of the CDF document.

Since this example adds a single record, the overhead associated with redrawing the record is insignificant. When adding multiple records, such as in a loop, consider passing a value of false for this parameter and repainting the entire component after all records are added. For details, see Redrawing and Repainting Records.

Creating Record Hierarchies

By default, the structure of a CDF document is flat without hierarchical relationships between records. To create an hierarchical CDF document, specify the optional strParentRecordId parameter when calling either insertRecord() or insertRecordNode(). This parameter takes the jsxid value of a parent record, and when a value is specified, the record is added as a child of the parent record.

Updating Records

When you add a record that has the same jsxid value as an existing record in the CDF document, the existing record is replaced. Make sure jsxid values are unique before adding records. For details, see Generating Unique Identifiers.

You can use the insertRecordProperty() method to add attributes to an existing record in a CDF document. Specify the jsxidvalue of the record to modify, along with the attribute name and attribute value. The following sample illustrates how to add an attribute to an existing record within an ID (jsxid) of 58:

objList.insertRecordProperty("58","mypropname","mypropvalue");

The process of removing attributes is similar. Using deleteRecordProperty(), specify the jsxidvalue of the record to modify and the name of the attribute to remove. Although not specifically restricted by the API, do not remove the jsxid attribute from a record. The following sample JavaScript code illustrates how to remove an attribute from an existing record:

objList.deleteRecordProperty("11","jsximg");

In both of the preceding examples, the record is automatically refreshed to reflect the change in the application. You could also pass a value of false for the optional bRedraw parameter to prevent the redraw operation. For details on optimizing redraw and repaint operations, see Redrawing and Repainting Records.

Deleting Records

Use the deleteRecord() method to delete a record from a CDF document. This method returns an object handle to the XML entity instance that was removed. The following sample JavaScript code illustrates how to delete an existing record:

var objMatrix = myServer.getJSXByName("myMatrix");
objMatrix.deleteRecord(strRecordId);

Generating Unique Identifiers

The jsxid attribute must be unique among all records for the component. If users need to drag records from one component to another, the jsxid attribute must be unique across multiple components. There are several ways to ensure uniqueness.

If the content of the CDF document is built programmatically by your application, you can use the jsx3.xml.CDF.getKey() method to generate a unique value for the jsxid attribute. The generated value is guaranteed unique across multiple components for the browser session. For an example, see Adding Records.

If the content of the CDF document is built outside of your application, you can use any key value in an XML attribute as the jsxidvalue. If no key value exists in the original XML when transforming the XML into CDF, use the XPath generate-id function to generate a unique value.

Redrawing and Repainting Records

After adding, modifying, or deleting records, the on-screen representation for the record will need to be synchronized. A changed record can be redrawn or the entire component can be repainted. Context and the impact on application performance determine which operation is more appropriate.

In general, repainting the component affects all records and is resource-intensive. Repainting the component should be avoided unless a sizable number of records are modified. For example, if many records are added in an iterative manner, it can be more efficient to repaint the component once, after all additions have been made. To repaint a component, call the repaint() method for the specific component.

CDF methods, with the exception of the adoptRecord()}}method, accept an optional Boolean parameter that signifies whether the on-screen view should be immediately updated to reflect the update to the in-memory model. A value of {{true, which is the default value, redraws the record after modification. For the adoptRecord() method, both controls (the former and new parent) are redrawn.

Counting Records

You can count the number of records in a CDF document by querying for all records and calling the getLength() method on the object that is returned. The following sample illustrates this for the List control.

var objXML = myList.getXML();
var objNodes = objXML.selectNodes("//record");
alert("The number of records is: " + objNodes.size());

First, call the getXML() method for the object, then the selectNodes() method (jsx3.xml.Entity) for the XML entity, passing the path for the nodes to select. This method returns a handle to the jsx3.util.List object containing all record nodes in the CDF document. Calling the getLength() method on this object returns the number of CDF records.

Contents

Searching General Interface Docs

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.