Loading the List When Forms First Appear

When the user clicks a link on the home page or an option on the Forms menu to display a form view, the list in the left pane of the form is populated. The following diagram shows the XML data loaded into an XML DSO, the hidden SourceTable that is bound to the XML DSO, and ScrollContainer (which contains firstspacer and TargetTable).

The topics in the following procedure describe how the functions in LoadList.js display the initial set of XML records and manage the scroll bars on the list.

To populate the list when the form first appears

  1. Include *List.js in HTML
  2. Call window_onLoad Function
  3. Run Script in doLoad Function
  4. Call getMoreData Function
  5. Call copyRows Function

Include *List.js in HTML

When a form view in the PT application first appears, JavaScript functions populate the list in the left pane with data. These function are part of a JavaScript file available to the *List.htm file, which contains the HTML code for the left pane. The JavaScript files are named after the HTML files they support; for example, the JavaScript file for ActivityList.htm is called ActivityList.js, the file for GroupList.htm is called GroupList.js, and so forth. The following line of script is from GroupList.htm and it shows you how GroupList.js becomes available to the Group form:

<script language="JavaScript" SRC="../Scripts/GroupList.js"></script>

Note  The reason the script resides in the JavaScript files instead of in the *List.htm files is to prevent errors when loading the XML files during the build process. When the script contains any XML reserved characters, the XML DOM fails to load. Another reason to isolate the JavaScript functions from the HTML is that the application only needs one version of the JavaScript functions, because they do not require localization.

Call window_onLoad Function

When a form loads, the first line in the *List.js JavaScript file for the form calls the window_onLoad function, as shown in the following line of code:

window.onload = window_onLoad;

The following code fragment shows the window_onLoad function from Group.js and includes code that implements a parameter named pid, in addition to the id parameter. The pid parameter is used to retrieve the group memberships for a person when the user clicks View Schedule of Classes on the User form. When the form first loads, the id variable is always null. The doLoad function is the event handler for the ondataavailable event of the current XML DSO. Coding Form Views describes the role of the XML Data Source Object (DSO) in the PT application.

function window_onLoad() {
   var xml = '../Scripts/viewData.asp?tableName=group&fieldList=GroupId,Name&sortBy=Name';
   var id = getParam('id');
   if (id != null) xml = xml + '&whereID=' + id;
   var pid = getParam('pid');
   if (pid != null) xml = '../Scripts/viewData.asp?procName=lw_getSchedule&personId=' + pid;
   xmldso.XMLDocument.ondataavailable = doLoad;
   xmldso.XMLDocument.load(xml);
}

Run Script in doLoad Function

The XML data is validated in the doload function; the following code fragment shows the code that checks for errors and displays an alert when an error occurs. The string ('./number') is the pattern used to locate the number tag under the current node.

var docElem = xmldso.XMLDocument.documentElement;
      if (docElem != null) {
         var child = docElem.firstChild;
         if (child != null) {
            if (child.baseName == 'error') {
               var code = child.selectSingleNode('./number').text;
               var desc = child.selectSingleNode('./description').text;
               var src  = child.selectSingleNode('./source').text;
               alert('CODE:\t' + code + '\n' +
                     'DESC:\t' + desc + '\n' +
                     'SRC:\t' + src);
               NoRecords.style.display = '';
               return; 

If no errors exist, the script continues to run. The following code fragment shows the script that sets the TotalRecordCount variable to the number of records in the recordset and then calls the insertPlaceholder function:

TotalRecordCount = xmldso.recordset.recordcount; 
insertPlaceholder()

The following code fragment from insertPlaceholder shows how to dynamically calculate a value for the posHeight property of the DIV element named firstspacer in the *List.htm file. Coding *List.htm in Coding Form Views describes the code elements. SpacerHeight is a variable that contains the value 24 (the unit of measure is pixels). The firstspacer is increased to maximum height (the space required for all the records ) and then decreased as rows are added to the list.

function insertPlaceholder() {
  firstspacer.style.posHeight = TotalRecordCount * SpacerHeight;
}  

Next, the doLoad function associates the onscroll event for ScrollContainer (a DIV in *List.htm) with the testForScroll function and associates the onreadystatechange event for SourceTable (a TABLE in *List.htm) with the readyStateChange property. The doLoad function then calls the getMoreData function to initialize the first set of data.

ScrollContainer.onscroll = testForScroll;
SourceTable.onreadystatechange = readyStateChange;
getMoreData()

Call getMoreData Function

The getMoreData function determines whether to advance the data page of the SourceTable or call the copyRows function. When data is first loaded, copyRows is always called because no data has been copied from the SourceTable (the virtual table that is bound to an XML DSO) to the TargetTable (the table that appears in the left pane). Later, when the user scrolls through the list, the SourceTable may need to advance to the next data page. Scrolling the List describes the process that advances the data page. The following code fragment illustrates this process:

function getMoreData() {
   if (SourceTable.readyState == "complete") {
      // don't go to next page until all data in the SourceTable has been copied
      var r = SourceTable.rows;
      if (r.length > 0) {
         var lastRow = SourceTable.rows[r.length-1];
         if (lastRow.recordNumber > LastRecordNumber)
            copyRows();
         else
            SourceTable.nextPage();

Call copyRows Function

Script in the copyRows function tracks the last row of data copied to the TargetTable, thereby determining whether all data has been copied from the SourceTable. If no data remains in the SourceTable, the script sets the event handler for the onScroll event of ScrollContainer and the event handler for the onreadystatechange event of SourceTable to null, because no further data transfer is necessary. The following code fragment shows this process:

if (row.recordNumber <= LastRecordNumber) {
     ScrollContainer.onscroll = null;
     SourceTable.onreadystatechange = null;

The following code fragment from the copyRows function shows the script that creates the new element in the TargetTable and then calls the function formatCell. Inserting Cells with formatCell describes how cells are added to a table on the fly.

var copyRow = TargetBody.insertRow();
var copyCell = copyRow.insertCell();
copyCell.innerHTML = formatCell(row);

The script uses classes to assigns different colors to odd and even rows in the table. The cascading style sheet (Forms.css)contains the evenrow and oddrow classes. The following code fragment shows how to implement "oddrow" and "evenrow" classes from Forms.css (a cascading style sheet):

 if (LastRecordNumber & 1)
         copyRow.className = "oddrow";
      else
         copyRow.className = "evenrow";

The script associates functions from LoadList.js with events for the new row; the following code fragment shows this process. The selectColor function is the event handler for the new row. Functions in LoadList.js describes how this function provides a callback to a function in the *List.js file when the user clicks a row in the list.

copyCell.onmouseover = inColor;
copyCell.onmouseout  = outColor;
copyCell.onclick     = selectColor; 

Note  The design of the PT application's user interface specifies that odd and even rows in this list appear in alternating colors. To keep the colors alternating properly, the entire list must be reloaded whenever a user adds or deletes an entry. If all rows in a list are the same color, rows can be added or deleted without repeating the load process.