Custom Task Panes in the Information Lookup Developer Sample Form [InfoPath 2003 SDK Documentation]

Applies to:

Microsoft Office InfoPath 2003

For information on Service Pack 1 updates to working with secondary data sources, see About secondary data sources in the InfoPath Developer's Reference.

The Microsoft Office InfoPath Information Lookup developer sample uses a custom task pane to display a catalog of the products available to be ordered. Custom task panes can be as simple as a static HTML page that contains instructions for filling out the form, or they can be as complicated as a Dynamic HTML (DHTML) page that changes its content based on choices that a user makes when filling out the form. The CatalogTaskPane.htm file contains the basic structure of the task pane for this sample form. It also includes script to support the category toggling functionality of the Catalog task pane. The Catalog task pane calls the LoadCatalog custom function defined in the form's script file (script.js) to dynamically create the list of available products from the ProductCatalog secondary data source. Another script call to the InsertCatalogItem function allows the Catalog task pane to insert items from the catalog into the order form when a user double-clicks the item.

To create a custom task pane, you must first create an .html file by using an HTML editor such as Microsoft FrontPage. You associate this .html file with a form by using the Advanced tab in the Form Options dialog box, which is available on the Tools menu in design mode. The Advanced tab allows you to add the .html file and any other supporting files, such as a cascading style sheet (.css) file, using the Resource Manager. (The Resource Manager can also be accessed by clicking Resource Manager on the Tools menu in design mode.) After the .html file has been added as a resource, you can select the Enable custom task pane check box and set the name and location of your custom task pane.

Note  You must add the .html file to the form using the Resource Manager before you can make the file a custom task pane.

The XDocument::OnSwitchView event handler

Whenever you switch from one view to another in an InfoPath form, the OnSwitchView event handler fires. This event handler is used to make any necessary changes to the form or its data for display in the new view.

In the Information Lookup developer sample form, the Catalog task pane should appear only in the Basic Order view, and not in the Shipping view. To accomplish this, the Information Lookup developer sample form uses the OnSwitchView event handler to set the Visible property of the task pane to true when the Basic Order view is active, and false otherwise.

function XDocument::OnSwitchView(eventObj)
{
   // Show the form template's task pane only in the Basic Order view.
   if (gobjTaskPane == null)
      gobjTaskPane = XDocument.View.Window.TaskPanes.Item(0);
   gobjTaskPane.Visible = (XDocument.View.Name == "Basic Order");
}

Note  The form's custom task pane is always the first element (index 0) of the TaskPanes collection.

Accessing the InfoPath object model from a custom task pane

A static HTML page that provides additional information to users filling out an InfoPath form can be useful in its own right, but custom task panes can also take actions in the form. For example, you might want to have functionality in your custom task pane that adds information to a repeating table in the form. For this reason, a custom task pane may access the object model of the InfoPath form in which it is hosted.

To access the InfoPath object model from a custom task pane, use the window.external.Window.XDocument property. For convenience, you could add an "Init" function to your custom task pane to retrieve a global reference to the XDocument object in the InfoPath object model. This eliminates the need to retrieve the reference each time you want to call into the InfoPath object model.

var gobjXDocument = null;
function Init()
{
   gobjXDocument = window.external.Window.XDocument;
}

Call the Init function from the onLoad event of your custom task pane:

<body onLoad="Init()">

The XDocument.Extension property

The Extension property of the XDocument object allows you to access methods defined in the form's script file as if they were built-in methods of the InfoPath object model. Maintaining your script methods in InfoPath can be easier than keeping them in the custom task pane's HTML file.

catalogDIV.innerHTML = gobjXDocument.Extension.LoadCatalog();

The LoadCatalog script method

The LoadCatalog script method is defined in the form's script file. The Catalog task pane calls the LoadCatalog script method in its Init function when the task pane is loaded, to dynamically create the list of available products in the catalog. The first step in this process is to retrieve a reference to the ProductCatalog secondary data source's XML Document Object Model (DOM):

// Load the catalog data.
domXML = XDocument.GetDOM("ProductCatalog");

Next, the catalog.xsl transform file is loaded into a new DomDocument object. The catalog.xsl transform file is used to transform the data in the ProductCatalog secondary data source. The transform takes the XML data stored in the ProductCatalog XML DOM and produces an HTML table.

// Load the catalog data.
domXML = XDocument.GetDOM("ProductCatalog");

// Load the catalog xsl from the form.
domXSL = new ActiveXObject("MSXML2.DomDocument.5.0");
domXSL.async = false;
domXSL.load("catalog.xsl");

// Transform the data and insert it into the DIV element..
return domXML.transformNode(domXSL);

Finally, the code copies the resulting HTML table into the InnerHTML property of its catalogDIV container element. This causes the table to be displayed in the Catalog task pane, in which users can browse through its choices.

catalogDIV.innerHTML = gobjXDocument.Extension.LoadCatalog();

The InsertCatalogItem script method

When a user double-clicks a product in the Catalog task pane, its selectCatalogItem function is called with the productID attribute of the product that was selected. The selectCatalogItem function calls the InsertCatalogItem function, which is defined in the form's script file, to add the product to the order.

First, the InsertCatalogItem function looks up the product information in the ProductCatalog secondary data source. As with the Customers (USA) secondary data source in the msoxd_customerId::OnAfterChange event handler, the SelectionNamespaces property of the ProductCatalog secondary data source must be set before it can be searched for product information:

// Get the product information that corresponds to this product 
// from the ProductCatalog auxiliary DOM.

XDocument.GetDOM("ProductCatalog").setProperty("SelectionNamespaces",
   'xmlns:q="http://schemas.microsoft.com/office/infopath/2003/ado/queryFields"' + 
   'xmlns:d="http://schemas.microsoft.com/office/infopath/2003/ado/dataFields"' + 
   'xmlns:dfs="http://schemas.microsoft.com/office/infopath/2003/dataFormSolution"');

objProductLookupNode = XDocument.GetDOM("ProductCatalog")
   .selectSingleNode("//d:Products[@ProductID='" + strProductId + "']");

After the appropriate product has been found, the InsertCatalogItem function uses the CreateNode helper function to create a new XML element for it:

// Create a node for the new item to be inserted into the XML document.
objItemNode = CreateNode(dom, "item");
objItemNode.appendChild(CreateNode(dom, "productId", strProductId));
objItemNode.appendChild(CreateNode(dom, "productName", 
   objProductLookupNode.getAttribute("ProductName") || ""));
objItemNode.appendChild(CreateNode(dom, "quantityPerUnit", 
   objProductLookupNode.getAttribute("QuantityPerUnit") || ""));
objItemNode.appendChild(CreateNode(dom, "unitPrice", 
   objProductLookupNode.getAttribute("UnitPrice") || ""));
objSupplierNode =
  objProductLookupNode.selectSingleNode("d:Suppliers/@CompanyName");
objItemNode.appendChild(CreateNode(dom, "supplierCompany", 
   objSupplierNode ? objSupplierNode.text : ""));

Finally, the new XML element is added as a child of the "/liSample/order" element in the form's underlying XML document. This causes the new product to show up in the order table in the Basic Order view.

Accessing the DHTML object model of a custom task pane from InfoPath

Although the Information Lookup developer sample form doesn't do so, it is possible for script in an InfoPath form to access the DHTML object model of a custom task pane to perform actions or call script functions. To access the DHTML object model of the custom task pane from script in the form, use the HTMLDocument property of the first task pane (index 0) in the Taskpanes collection:

var objTaskPane = XDocument.View.Window.TaskPanes.Item(0).HTMLDocument;

For convenience, you could add a function to retrieve a reference to the DHTML object model. Unlike the XDocument object of the InfoPath object model, this value should not be cached, because the custom task pane may or may not be visible when the script is executed. If the reference is cached and the task pane is not visible, unexpected results can occur.

Function GetTaskPaneHTMLDocument()
   ' Ensure that view has loaded before trying to access the task pane.
   Dim objXDocView
   Set objXDocView = XDocument.View

   If (Not(objXDocView Is Nothing)) Then

      ' Get a reference to the custom task pane. It is
      ' always the 0-th task pane in the Taskpanes 
      ' collection.
      Dim objTaskPaneDoc
      Set objTaskPaneDoc = 
         objXDocView.Window.TaskPanes.Item(0).HTMLDocument
         
      ' Ensure that the task pane is completely loaded.
      If (objTaskPaneDoc.readyState = "complete") Then

         'Return the HTMLDocument reference.
         Set GetTaskPaneHTMLDocument = objTaskPaneDoc
      Else
      
         'If the task pane isn't loaded, return nothing.
         Set GetTaskPaneHTMLDocument = Nothing
      End If
   End If
End Function