Craft > JavaScript Tips > Scroller

SwansonSoftware Home | Site Index | View With Frames

Final Version 1.2, updated January 8 2004

This example demonstrates how to create a table scroller with some very nice features:

The scroller uses an Internet Explorer behavior to implement the highlight. You could implement highlighting with javascript and not use a behavior, but the behavior makes reuse easier and gives you the ability to set properties of the scroller - e.g. the color when the highlight is on and the color when it is off, and whether it is a single-select or multi-select scroller - by setting custom attributes in the <TABLE> element. For example, here is the html that specifies values for custom attributes defined in the scroller behavior:

<table class="hiliter" OffColor="D5F1FF" OnColor="#FFFFFF">

See About Behaviors for an introduction to Internet Explorer behaviors.

Try it

Code   Description 1  Description 2 Value   
1112  Column1 Desc 1 Column2 Desc 1 0.33 
1113  Column1 Desc 2 Column2 Desc 2 1.63 
1114  Column1 Desc 3 Column2 Desc 3 1.56 
1115  Column1 Desc 4 Column2 Desc 4 1.91 
1116  Column1 Desc 5 Column2 Desc 5 0.27 
1117  Column1 Desc 6 Column2 Desc 6 0.33 
1118  Column1 Desc 7 Column2 Desc 7 1.63 
1119  Column1 Desc 8 Column2 Desc 8 1.56 
1120  Column1 Desc 9 Column2 Desc 9 1.91 
1121  Column1 Desc 10 Column2 Desc 10 0.27 
1122  Column1 Desc 11 Column2 Desc 11 0.33 


To create the behavior, copy the following code to a text file and save it as scroller.htc

/*--------------------------------------------------------------------
 (c) 2001 Gregory Swanson.  All Rights Reserved.

 File: scroller.htc
 
 You may use this code without royalty or reference.
--------------------------------------------------------------------*/
<PUBLIC:COMPONENT>
<PUBLIC:ATTACH EVENT="onmouseover" ONEVENT="Hilite()" />
<PUBLIC:ATTACH EVENT="onmouseout"  ONEVENT="unHilite()" />
<PUBLIC:ATTACH EVENT="onclick"  ONEVENT="selectRow()" />
<PUBLIC:ATTACH EVENT="onselectstart"  ONEVENT="cancelSelect()" />
<PUBLIC:PROPERTY NAME = MultiSelect VALUE = 0 />
<PUBLIC:PROPERTY NAME = OnColor VALUE = "#FFFFFF" />
<PUBLIC:PROPERTY NAME = OffColor VALUE = "#d5f1ff" />
<PUBLIC:PROPERTY NAME = selectedRow />
<PUBLIC:METHOD NAME="InitializeArray" />

<SCRIPT LANGUAGE="JScript">

var arrSelectedRows = new Array();

function cancelSelect()
{
   event.returnValue=false;
}

function Hilite()
{
   if (event.srcElement.tagName == "DIV")
   {
    var objDiv = event.srcElement;
    var objTD = objDiv.parentNode;
   } else {
    var objTD = event.srcElement;
   }

   var objTR = objTD.parentNode;
   if (objTR.tagName == "TR")
   {
    selectedRow = objTR.rowIndex;
    objTR.style.backgroundColor=OnColor;
   }

   return true;
}


function unHilite()
{
   if (event.srcElement.tagName == "SPAN")
   {
    var objSpan = event.srcElement;
    var objTD = objSpan.parentNode;
   } else {
    var objTD = event.srcElement;
   }

   var objTR = objTD.parentNode;

   if (objTR.tagName == "TR")
    objTR.style.backgroundColor=OffColor;

   //Re-select selected (i.e. clicked-on) rows

   for (var i=0; i<arrSelectedRows.length; i++)
   {
    arrSelectedRows[i].style.backgroundColor = OnColor;
   }

   return true;
}

function selectRow()
{

   if (event.srcElement.tagName == "SPAN")
   {
    var objSpan = event.srcElement;
    var objTD = objSpan.parentNode;
   } else {
    var objTD = event.srcElement;
   }

   var objTR = objTD.parentNode;

   if (objTR.tagName == "TR")
   {

      if (MultiSelect == -1)
      {
        if (!window.event.ctrlKey)
        {
           //If user is not pressing Ctrl key, de-select rows.

           var theParent = objTR.parentElement;

           for (var i=0; i<theParent.rows.length; i++)
           {
            theParent.rows[i].style.backgroundColor = OffColor;
           }

           //Reset object styles.
           for (var i=0; i<arrSelectedRows.length; i++)
           {
            arrSelectedRows[i].style.backgroundColor = OffColor;
           }
           InitializeArray();
        }
      } else {
        //De-select any selected rows

        var theParent = objTR.parentElement;

        for (var i=0; i<theParent.rows.length; i++)
        {
           theParent.rows[i].style.backgroundColor = OffColor;
        }

        //Reset object styles.
        for (var i=0; i<arrSelectedRows.length; i++)
        {
           arrSelectedRows[i].style.backgroundColor = OffColor;
        }
        InitializeArray();
      }

      selectedRow = objTR.rowIndex
      arrSelectedRows[arrSelectedRows.length] = objTR;


      //SET selected row''s color.
      objTR.style.backgroundColor = OnColor;

      for (var i=0; i<arrSelectedRows.length; i++)
      {
        arrSelectedRows[i].style.backgroundColor = OnColor;
      }

      return true;
   }
}

function InitializeArray()
{
   arrSelectedRows = null;
   arrSelectedRows = new Array();
}

</SCRIPT>

</PUBLIC:COMPONENT>

End of scroller code.



This is the code for the scroller

Note the declaration for the scoller behavior:

<style type="text/css">
      .hiliter {behavior:url(scroller.htc)}
</style>

The above declaration tells Internet Explorer to load the scroller.htc behavior. The example assumes scroller.htc is located in the same directory as the ASP page.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<title>Scroller</title>
   <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

   <style type="text/css">
      .hiliter {behavior:url(scroller.htc)}

   div.scroller_picklist{
      background-color:#d5f1ff;
      overflow-y:scroll;
      border-style:inset;
      border-width:thin;
      width:650px;
      height:100px;
      margin-right:0.5in;
      margin-left:0.5in;
   }

   div.scroller_header{
      height:20px;
      overflow-y:visible;
      border-bottom-style:none;
      width:653px;
      margin-right:0.5in;
      margin-left:0.5in;
   }

   th.reports_header {
      font-family:"verdana","arial","helvetica","sans-serif";
      font-size:'75%';
      font-weight:bold;
      color:#FFFFFF;
      background-color:#0080C0;
      text-align:center;
   }

   td.picklist{
      font-family:"verdana","arial","helvetica","sans-serif";
      font-size:8pt;
      color:#000000;
      text-align:left;
      cursor:hand;
   }
   </style>

   <script language="JavaScript" type="text/javascript">

   // setReturnValue
   // Retrieves the text from the selected row in the scroller.
   function setReturnValue()
   {
      sReturnText = "";
      var objTD = event.srcElement;
      var objTR = objTD.parentNode;

      for (var i=0;i<objTR.cells.length;i++)
         sReturnText += objTR.cells(i).innerText + ";";

      alert(sReturnText);

      // If this code is in a popup window you would set the
      // return value and close the window here.  The calling
      // page would parse the return value on the delimiter; we
      // have used semicolons for delimiters in this example.
      //if (sReturnText != null)
      //{
      //    window.returnValue = sReturnText;
      //    window.close();
      //}

      return true;
   }
   </script>
   </head>

<body bgcolor="#FFFFFF">
    
<div class="scroller_header">
   <table border="0" cellpadding="0" cellspacing="0" style="border-bottom-style:none">
      <thead>
         <th width='5%' class='reports_header' style='text-align:right;' height='25'>Code </th>
         <th width='20%' class='reports_header' style='text-align:left;'> Description 1</th>
         <th width='20%' class='reports_header' style='text-align:left;'> Description 2</th>
         <th width='10%' class='reports_header' style='text-align:right;'>Value </th>
         <th width='1%' class='reports_header' style='text-align:right;'> </th><!--spacer for scroll bar-->
      </thead>
   </table>
</div>

<div class="scroller_picklist">

   <!-- 
   Here we use the hiliter behavior, whose code is in the scroller.htc file.
   Behaviors can be written and compiled in C++, but scroller.htc is written
   in xml. The hiliter behavior exports four properties, we are interested
   in OffColor and OnColor.  Note how they are used in the table element below.
   -->
   <table class="hiliter" OffColor="D5F1FF" OnColor="#FFFFFF" border="0"
    cellspacing="0" cellpadding="1" style="table-layout:fixed;">

   <tr onclick='setReturnValue();' ondblclick='setReturnValue();doOK();'>
      <td class="picklist" width="5%" style="text-align:right;">1112 </td>
      <td class="picklist" width="20%">Column1 Desc 1</td>
      <td class="picklist" width="20%">Column2 Desc 1</td>
      <td class="picklist" width="10%" style="text-align:right;">0.33 </td>
   </tr>

   <tr onclick='setReturnValue();' ondblclick='setReturnValue();doOK();'>
      <td class="picklist" width="5%" style="text-align:right;">1113 </td>
      <td class="picklist" width="20%">Column1 Desc 2</td>
      <td class="picklist" width="20%">Column2 Desc 2</td>
      <td class="picklist" width="10%" style="text-align:right;">1.63 </td>
   </tr>

   <tr onclick='setReturnValue();' ondblclick='setReturnValue();doOK();'>
      <td class="picklist" width="5%" style="text-align:right;">1114 </td>
      <td class="picklist" width="20%">Column1 Desc 3</td>
      <td class="picklist" width="20%">Column2 Desc 3</td>
      <td class="picklist" width="10%" style="text-align:right;">1.56 </td>
   </tr>

   <tr onclick='setReturnValue();' ondblclick='setReturnValue();doOK();'>
      <td class="picklist" width="5%" style="text-align:right;">1115 </td>
      <td class="picklist" width="20%">Column1 Desc 4</td>
      <td class="picklist" width="20%">Column2 Desc 4</td>
      <td class="picklist" width="10%" style="text-align:right;">1.91 </td>
   </tr>

   <tr onclick='setReturnValue();' ondblclick='setReturnValue();doOK();'>
      <td class="picklist" width="5%" style="text-align:right;">1116 </td>
      <td class="picklist" width="20%">Column1 Desc 5</td>
      <td class="picklist" width="20%">Column2 Desc 5</td>
      <td class="picklist" width="10%" style="text-align:right;">0.27 </td>
   </tr>

   <tr onclick='setReturnValue();' ondblclick='setReturnValue();doOK();'>
      <td class="picklist" width="5%" style="text-align:right;">1117 </td>
      <td class="picklist" width="20%">Column1 Desc 6</td>
      <td class="picklist" width="20%">Column2 Desc 6</td>
      <td class="picklist" width="10%" style="text-align:right;">0.33 </td>
   </tr>

   <tr onclick='setReturnValue();' ondblclick='setReturnValue();doOK();'>
      <td class="picklist" width="5%" style="text-align:right;">1118 </td>
      <td class="picklist" width="20%">Column1 Desc 7</td>
      <td class="picklist" width="20%">Column2 Desc 7</td>
      <td class="picklist" width="10%" style="text-align:right;">1.63 </td>
   </tr>

   <tr onclick='setReturnValue();' ondblclick='setReturnValue();doOK();'>
      <td class="picklist" width="5%" style="text-align:right;">1119 </td>
      <td class="picklist" width="20%">Column1 Desc 8</td>
      <td class="picklist" width="20%">Column2 Desc 8</td>
      <td class="picklist" width="10%" style="text-align:right;">1.56 </td>
   </tr>

   <tr onclick='setReturnValue();' ondblclick='setReturnValue();doOK();'>
      <td class="picklist" width="5%" style="text-align:right;">1120 </td>
      <td class="picklist" width="20%">Column1 Desc 9</td>
      <td class="picklist" width="20%">Column2 Desc 9</td>
      <td class="picklist" width="10%" style="text-align:right;">1.91 </td>
   </tr>

   <tr onclick='setReturnValue();' ondblclick='setReturnValue();doOK();'>
      <td class="picklist" width="5%" style="text-align:right;">1121 </td>
      <td class="picklist" width="20%">Column1 Desc 10</td>
      <td class="picklist" width="20%">Column2 Desc 10</td>
      <td class="picklist" width="10%" style="text-align:right;">0.27 </td>
   </tr>

   <tr onclick='setReturnValue();' ondblclick='setReturnValue();doOK();'>
      <td class="picklist" width="5%" style="text-align:right;">1122 </td>
      <td class="picklist" width="20%">Column1 Desc 11</td>
      <td class="picklist" width="20%">Column2 Desc 11</td>
      <td class="picklist" width="10%" style="text-align:right;">0.33 </td>
   </tr>

   </table>
</div>
</body>
</html>


Retrieve data in selected row

This JavaScript code demonstrates how you would open the scroller in a modal dialog box and retrieve the user's selection

function ShowCodes(intLoop)
{

   // Show the list and put the user's selection in wndShow.

   var sParams = getDialogSetup(880,300);
   var wndShow = window.showModalDialog ("lookup.htm","Lookup",sParams);
   var undefined;


   // If the user made a selection, parse out the information.
   if (!(wndShow==undefined)){

      // Display string returned - for testing
      //alert(wndShow);

      // Parse out each field from the returned string.
      // Fields are separated by a semicolon.

      //****************************************************************
      // Field one
      var strVal = '';

      // Get the position of the first semicolon
      var intPosition = wndShow.indexOf(';');

      // Parse out the value from beginning of string up to intPosition.
      strVal = wndShow.slice(0,intPosition);

      fieldOne.value = strVal;
      //****************************************************************

      // Get the position of the next semicolon and parse out next value
      strVal = '';

      intPosition += 1;

      var intPositionNext = wndShow.indexOf(';',intPosition);

      strVal = wndShow.slice(intPosition, intPositionNext);

      tableCellTwo.innerText = strVal;
      //****************************************************************

      // Get the position of the next semicolon and parse out next value
      strVal = '';

      intPosition = intPositionNext + 1;

      var intPositionNext = wndShow.indexOf(';',intPosition);

      strVal = wndShow.slice(intPosition, intPositionNext);

      fieldTwo.value = strVal;
      //****************************************************************

      // Get the position of the next semicolon and parse out next value
      strVal = '';

      intPosition = intPositionNext + 1;

      var intPositionNext = wndShow.indexOf(';',intPosition);

      strVal = wndShow.slice(intPosition, intPositionNext);

      fieldThree.value = strVal;
      //****************************************************************
   }
}
Top of page