Widgets
CheckBoxTreeWidget
History
Documentation
The Checkbox Tree Component
How it works
How to Use
@file widgetcheckboxtree.htm
<< declarations >>
<< html >>
<< head >>
<< CSS >>
<< Checkbox Tree Functions >>
<< data >>
<< drawCheckboxTree >>
<< Figure out the Styling >>
<< Create the Checkbox Html >>
<< Create the Button Html >>
<< Add the Html for the Row >>
<< Add Border >>
<< checkbox >>
<< Check or uncheck the checkbox >>
<< Toggle the Children >>
<< Toggle the Parents >>
<< Utility Tree Functions >>
<< collapse functions >>
<< Other Functions >>
<< onload >>
<< body >>
Deprecated
<< toggle >>
<< checkbox >>
<< drawTreeSelect old version>>
DHTML Components
Copyleft 2002 by Joe Orr
CheckboxTree Widget
Creates a tree of checkboxes. For more information see the documentation nodes under this node.
Author: Joe Orr orrj@nycircuits.com
Copyleft 2002 Joe Orr
Created April 2001
version 1.0 April 18, 2001
DOM2 compatibility added (e.g. Netscape) Nov 20, 2002
For TODO items, search this file for TODO.
For documentation see child nodes of this node.
@nocolor
This component is used for drawing a tree of checkboxes. Clicking on a checkbox
checks or unchecks all descendant checkboxes, and checks or unchecks parent
branches as necessary. The tree can be made collapsible or not.
The scripts are not packaged as a single object, because the functions which
check and uncheck a branch, and open and close branches, use a DOM collection.
This allows the functions to be attached directly to a checkbox. The functions
could also be used with other checkbox collections than that of the
Checkbox Tree Component contained in this file.
See the Leo File for more info.
The drawCheckboxTree function creates a checkbox for each line of data in
its "items" associative array. Each checkbox gets the following attributes:
id = this.container + "Items" (this.container is the id of the div tag
in which the component will be drawn.
ccode = key of one item of data
cvalue = value of one item of data
rowIndex = This is a counter that increments by one for each checkbox added to
the tree. The reason this is called a rowIndex is that each checkbox
has its own row. There are never two checkboxes in the same row.
colIndex = The checkboxes are displayed in a table, and this index indicates
what column a given checkbox is in. This is equivalent to the "depth"
of a node.
onclick = "toggleTree(this)"
The following diagram might be helpful for understanding the
role of the rowIndex and colIndex attributes:
col1 col2
_______________
row1 |check1 | |
row2 | |check2 |
row3 |check3 | |
row4 | |check4 |
|_______|_______|
Since all of the checkboxes get the same name/id, they can be accessed via
the DOM as a collection with the same name as the ID.
The tree manipulation functions access this collection by asking
the object that was clicked on (this) what its id is.
A number of general purpose tree manipulation functions have been
created such as getParent, getSiblings, etc. These functions take
as input an html element which has colIndex and rowIndex attributes,
and return an element or collection of elements as appropriate.
The function for setting the checkboxes of a tree branch on or off
is called toggleTree. It is attached to a checkbox as toggleTree(this).
The checkbox itself is passed to the toggleTree function. The function
can get the rowIndex and colIndex of the checkbox from the checkbox
attributes. It can also get the value of the id of the checkbox, so
it knows which collection of checkboxes to manipulate. Since it
knows which collection of checkboxes to manipulate, and knows the
position of checkbox that was clicked, it can perform any tree
type operation on the collection of checkboxes.
To deploy this component, include the functions in the Checkbox Tree Functions
node in your webpage. Then to draw the component on the page:
var myCheckboxTree = new clsCheckboxTree(myItems, "CheckboxTree");
myCheckboxTree.draw();
The "myItems" parameter is an associative array (i.e., a function) containing
keys with semi-colon delimited values. The second parameter is the id of
the div tag or other element where you want the component to be placed.
@language html
<< declarations >>
<< html >>
@code
<!-- This page is HEAVILY documented in LEO. For documentation for this page, see the LEO source file.
This page was created from a LEO source file named "widgets.leo".
-->
@code
<html>
<head>
<< head >>
</head>
<body
bgcolor="gainsboro"
topmargin="2"
leftmargin="2"
marginheight="2"
marginwidth="2"
onload="window_onload()"
>
<< body >>
</body>
</html>
@code
<title>CheckboxTree Demo</title>
<< CSS >>
<script>
<< Checkbox Tree Functions >>
<< Other Functions >>
</script>
@code
<style type="text/css">
BODY {font-family:Arial,sans-serif; font-size:8pt; font-weight:100;}
TD {font-family:Arial,sans-serif; font-size:8pt; font-weight:100; text-transform:capitalize;}
SELECT {font-family:Arial,sans-serif; font-size:12px; font-weight:normal}
OPTION {font-family:Arial,sans-serif; font-size:12px; font-weight:normal}
TH {font-family:Arial,sans-serif; font-size:12px; font-weight:bold; text-align:left}
BUTTON {font-size:14; font-weight:bold; width:30; text-align:center}
INPUT {font-family:Arial; font-size:10pt;}
.treeSelect {}
.line1 {background-color:red; line-height:1px;}
.spacer1 {background-color:white; line-height:4px;}
.spacerCell {width:40}
.topicLine {background-color:#B1CCCE}
.nodeButton {font-family:Arial,sans-serif;font-size:16px; width=14; line-height:12px; text-align:center; cursor:hand}
.nodeButtonImage {cursor:hand;}
</style>
@code
// a function which serves as an associative array to hold the data
function items() {
}
var myItems = new items();
var myItemsArray = new Array();
<< data >>
/**
* clsCheckboxTree: Constructor for tree select object
*
* @treeData an object container the tree data as an associative array
* @container the id of the div tag (or other element) in which the checkbox tree
* widget will be drawn.
* @collapsible if true, nodes will open and close
* @hasBorder if true, component will have an outside border
*
**/
function clsCheckboxTree(treeData, container, collapsible, hasBorder) {
this.items = treeData;
this.container = container;
this.itemsID = container + 'Items';
// can open and close nodes?
this.collapsible = collapsible;
// display in scrolling window in window?
this.hasBorder = hasBorder;
// use text +/- button instead of graphic?
this.textButton = false;
}
// function to draw the CheckboxTree html
<< drawCheckboxTree >>
// function to handle turning checkboxes on and off
<< checkbox >>
// functions to open or close nodes
<< collapse functions>>
// Only the drawCheckboxTree gets attached to the
// object, because the checkbox and collapse
// functions are not methods but rather functions
// that operate on collections of nodes. Each of
// these nodes knows which DOM collection it is a
// member of, and this is all that is needed to
// make them operate in synch. For more information,
// see the LEO documentation.
clsCheckboxTree.prototype.draw = drawCheckboxTree;
@code
// load the data into the associative array
myItems["170,171"] = "INFLATION;NOTE;VARIABLE";
myItems["168,169"] = "INFLATION;TREASURY;BOND";
myItems["114,115,177"] = "LONG TERM;AGENCY;BOND";
myItems["116"] = "LONG TERM;AGENCY;ZERO";
myItems["1,39,70,75,137,138,139,172,175,211,212,213,214,215,216,217"] = "LONG TERM;CORP;BOND";
myItems["8,174,224"] = "LONG TERM;CORP;MTN";
myItems["173,225"] = "LONG TERM;CORP;MTN NO-EOM";
myItems["17,30,31,32,33,34,35,36,42,43,44,45,46,47,48,49"] = "LONG TERM;EURO;BOND";
myItems["9,14"] = "LONG TERM;TREASURY;BOND";
myItems["10,11,15"] = "LONG TERM;TREASURY;NOTE";
myItems["77"] = "LONG TERM;TREASURY;ZERO";
myItems["203,204,205,206"] = "MUNICIPAL;CD;INT AT MAT";
myItems["197"] = "MUNICIPAL;CP;DISCOUNT";
myItems["198"] = "MUNICIPAL;CP;INT AT MAT";
myItems["210"] = "MUNICIPAL;NOTE;MTN AT MAT";
myItems["207,208,209"] = "MUNICIPAL;NOTE;VAR AT MAT";
myItems["81"] = "OTHER;LTD PARTNR;LTD";
myItems["83"] = "OTHER;REV CREDIT;REV";
myItems["78"] = "OTHER;STOCK;COMMON";
myItems["118,119,120,121"] = "OTHER;STOCK;PREFERRED";
myItems["132"] = "OTHER;WARRANT;BOND";
myItems["80"] = "OTHER;WARRANT;COMMON";
myItems["105"] = "SHORT TERM;ABS;DISCOUNT";
myItems["104"] = "SHORT TERM;ABS;INT AT MAT";
myItems["112"] = "SHORT TERM;ABS;TERM";
myItems["128"] = "SHORT TERM;AGENCY;BOND";
myItems["12,13"] = "SHORT TERM;AGENCY;DISCOUNT";
myItems["65"] = "SHORT TERM;BA;DISCOUNT";
myItems["21,22,23,41"] = "SHORT TERM;CD;DISCOUNT";
myItems["190"] = "SHORT TERM;CD;EUEU CD";
myItems["196"] = "SHORT TERM;CD;EURO CD";
myItems["193"] = "SHORT TERM;CD;EURYEN CD";
myItems["20,24,25,26"] = "SHORT TERM;CD;INT AT MAT";
myItems["189"] = "SHORT TERM;CD;STERLG. CD";
myItems["19,27,28,29,38"] = "SHORT TERM;CD;TERM";
myItems["192"] = "SHORT TERM;CD;YENYEN CD";
myItems["63"] = "SHORT TERM;CP;DISCOUNT";
myItems["195"] = "SHORT TERM;CP;EURYEN CP";
myItems["64"] = "SHORT TERM;CP;INT AT MAT";
myItems["194"] = "SHORT TERM;CP;YENYEN CP";
myItems["102"] = "SHORT TERM;LOAN PART;INT AT MAT";
myItems["106"] = "SHORT TERM;LOC;DISCOUNT";
myItems["99,100"] = "SHORT TERM;NOTE;BANK NOTE";
myItems["113"] = "SHORT TERM;NOTE;BOND";
myItems["107,122,123,124,133,134,145,146,147"] = "SHORT TERM;NOTE;FLOATER";
myItems["160,163,166"] = "SHORT TERM;NOTE;FLT AT MAT";
myItems["101,140,176"] = "SHORT TERM;NOTE;MTN";
myItems["167"] = "SHORT TERM;NOTE;MTN AT MAT";
myItems["150,153,157"] = "SHORT TERM;NOTE;VAR AT MAT";
myItems["108,125,126,127,135,136,141,142,143,144"] = "SHORT TERM;NOTE;VARIABLE";
myItems["103"] = "SHORT TERM;REPO;INT AT MAT";
myItems["98"] = "SHORT TERM;TIME DEPO;INT AT MAT";
myItems["129"] = "SHORT TERM;TREASURY;BOND";
myItems["187"] = "SHORT TERM;TREASURY;BTBILL";
myItems["188"] = "SHORT TERM;TREASURY;FTBILL";
myItems["185"] = "SHORT TERM;TREASURY;GTBILL";
myItems["184"] = "SHORT TERM;TREASURY;ITBILL";
myItems["182"] = "SHORT TERM;TREASURY;JTBILL";
myItems["130"] = "SHORT TERM;TREASURY;NOTE";
myItems["191"] = "SHORT TERM;TREASURY;NTBILL";
myItems["16,131"] = "SHORT TERM;TREASURY;TBILL";
myItems["183"] = "SHORT TERM;TREASURY;UTBILL";
myItems["66,67,84,109,110,111,178,218,219,220"] = "STRUCTURED;MULTI;ABS";
myItems["68,69,74"] = "STRUCTURED;MULTI;CMO";
myItems["89,90,91"] = "STRUCTURED;MULTI;MPT";
myItems["92,93,94,95,96,97,179,180,181"] = "STRUCTURED;SINGLE;ABS";
myItems["55,221,222,223"] = "STRUCTURED;SINGLE;MBS";
myItems["85,86,87,88"] = "STRUCTURED;SINGLE;PRJCT LOAN";
myItems["59"] = "STRUCTURED;SINGLE;TBA - MBS";
@code
function drawCheckboxTree() {
var cells; // will hold one row of data
var oldCells = new Array(); // will remember data from last row for this cell
var cellKey;
var cellValue;
var cellCode;
var dhtmlCheckbox;
var dhtmlCheckboxTree = '<table border="0" cellpadding="1" width="300" align="center" cellspacing="1" bgcolor="white">';
// find out the number of columns by extracting the columns of the first item
for (rowKey in this.items) {
cells = this.items[rowKey].split(";");
break;
}
numCols = cells.length;
// oldCells remembers what was in a given column in the last row.
// initialize this to a value that should never match. We need to
// initialize this so that the oldCells array has the same number
// of columns as does the data
for (c = 0; c < numCols; c++) oldCells[c] = "no way jose";
var c; // cell (column) index
var r = 0; // row index
for (rowKey in this.items) {
cells = this.items[rowKey].split(";");
for (c = 0; c < numCols; c++) {
cellValue = cells[c].toLowerCase();
// skip cells that have repeat info for the column
if (oldCells[c] == cellValue && c < numCols -1) {
oldCells[c] = cellValue; // save it
continue;
}
oldCells[c] = cellValue; // save it
<< figure out the styling >>
<< create the checkbox html >>
// if the checkbox tree is supposed to be collapsible, add a +/- button
// We have to give this an attribute called "linkedID" that indicates which
// checkbox collection this button is linked to. We also have to give it
// rowIndex and colIndex attributes, just like the checkbox elements.
if (this.collapsible && c < numCols - 1) {
<< create the button html >>
}
// If we've found a cell that we are going to write out, make a row
// for it, with the TD colspan equal to the number of remaining cols
// and with TD elements preceding it equal in number to c (the col index)
<< add the HTML for the row >>
}
}
dhtmlCheckboxTree += '</table>';
<< add border >>
// we've got the table built, now stick it in the DIV or other tag that
// was specified when this object was constructed.
eval('var ' + this.container + ' = document.getElementById("' + this.container + '")');
eval(this.container + ".innerHTML = dhtmlCheckboxTree;");
}
@code
switch (c) {
case 0: cellClass = "topicLine"; break;
default: cellClass = "";
}
@code
strJS = 'onclick="toggleTree(this);"';
cellKey = rowKey;
// if this isn't a bottom level node (leaf node), we don't want it to
// submit a value, so erase the key
if (c != numCols - 1) cellKey = "";
dhtmlCheckbox = '<input type="checkbox" '
+ 'id="' + this.itemsID + '" '
+ 'name="' + this.itemsID + '" '
+ 'cvalue="' + cellValue + '" '
+ 'ccode="' + cellKey + '" '
+ 'rowIndex = "' + r + '" '
+ 'colIndex = "' + c + '" '
+ strJS
+ '>';
@code
// if it is a text button, the + or - text character will be used for the
// button, otherwise an image will be used.
if (this.textButton) {
buttonHTML =
' <table align="left" '
+ 'style="border:1px solid #000000; height:14px; cursor:hand" bgcolor="gainsboro" cellspacing="0"'
+ ' cellpadding="0">'
+ ' <tr>'
+ ' <td align="center"'
+ ' class="nodeButton"'
+ ' rowIndex = "' + r + '" '
+ ' colIndex = "' + c + '" '
+ ' linkedID="' + this.itemsID + '"'
+ ' onclick="toggleNodeOpen(this)">'
+ '−' // this is a unicode minus sign
+ ' </td>'
+ '</tr>'
+ '</table>';
} else {
buttonHTML =
' <img src="minus.gif"'
+ ' class="nodeButtonImage" '
+ ' rowIndex = "' + r + '" '
+ ' colIndex = "' + c + '" '
+ ' linkedID="' + this.itemsID + '"'
+ ' onclick="toggleNodeOpen(this)">';
+ ' >';
}
dhtmlCheckbox = buttonHTML + dhtmlCheckbox;
@code
r++;
dhtmlCheckboxTree += '<tr class="' + cellClass + '">';
for (i = 0; i < c; i++) dhtmlCheckboxTree += '<td class="spacerCell"> </td>';
dhtmlCheckboxTree +=
'<td colspan="' + (numCols - c) + '">'
+ dhtmlCheckbox
+ cellValue
+ '</td>';
dhtmlCheckboxTree += '</tr>';
@code
// add a border by putting the table in a table if this was chosen in the constructor
if (this.hasBorder) {
dhtmlCheckboxTree =
'<table align="center" cellpadding=0 cellpadding=0 bgcolor="#B1CCCE"><tr><td>'
+ dhtmlCheckboxTree
+ '</td></tr></table>';
}
@code
/** toggleTree Set all checkboxes of a given branch.
* @me the checkbox element that was clicked on. All descendant and ancestor
* nodes will be set accordingly. For more documentation, see the LEO file.
*/
function toggleTree (me) {
flagIt(me, me.checked);
toggleChildren(me, me.checked);
toggleParents(me, me.checked);
}
<< Check or uncheck the checkbox >>
<< Toggle the Children >>
<< Toggle the Parents >>
<< Utility Tree Functions >>
@code
/**
* flagIt check or uncheck a checkbox and add a style.
*
* @me the checkbox to be marked.
* @markValue true or false: whether to check the box
*
**/
function flagIt(me, markValue) {
me.checked = markValue;
// Following block is for highlighting the cell which contains the selected checkbox.
//if (markValue) {
// if (me.colIndex == 2) me.parentElement.style.backgroundColor = 'aquamarine';
//} else {
// // TODO: save and restore the existing style
// if (me.colIndex != 0) me.parentElement.style.backgroundColor = 'white';
// //if (me.colIndex == 0) me.parentElement.style.backgroundColor = "#B1CCCE";
//}
}
@code
/**
* toggleChildren This is a recursive function that uses getChildren to get a list
* of children checkboxes and then sets their values to checked or unchecked.
*
* @me item (an element with colIndex and rowIndex attributes)
* @checkValue true or false: set checkbox value
*
* For more documentation, see the LEO file for this program.
*/
function toggleChildren(me, checkValue) {
var i = 0;
var children = getChildren(me);
if (children.length == 0) return;
for (i = 0; i < children.length; i++) {
flagIt(children[i], checkValue);
//recurse
toggleChildren(children[i], checkValue);
}
}
@code
/**
* toggleParents turn all ancestor checkboxes on or off (recursive).
* of children checkboxes and then sets their values to checked or unchecked.
*
* @me item (an element with colIndex and rowIndex attributes)
* @checkValue true or false: set checkbox value
*
* For more documentation, see the LEO file for this program.
*/
function toggleParents(me, checkValue) {
var i = 0;
// If we are turning the checkbox off, we need to first
// check and see if there are any siblings besides the current item
// that are checked on. If there are, we don't.
if (! checkValue) {
var siblings = getSiblings(me);
var rowIndex = me.rowIndex;
for (i = 0; i < siblings.length; i++) {
if (siblings[i].checked != checkValue && siblings[i].getAttribute('rowIndex') != rowIndex) return;
}
}
// get the parent, if there is one, flag it
var parent = getParent(me);
if (parent == undefined) return;
flagIt(parent, checkValue);
// recurse
toggleParents(parent, checkValue);
}
@code
// For documentation, see the LEO file for this program
function getSiblings(me) {
var siblings = new Array();
siblings = getChildren(getParent(me));
return siblings;
}
// getParent get parent of item that was clicked on.
// For more documentation, see the LEO file.
function getParent(me) {
var r = me.getAttribute('rowIndex') / 1;
if (me.colIndex == 0) return;
eval("var startColIndex = " + me.id + "[r].getAttribute('colIndex');");
startColIndex = startColIndex / 1;
var parent;
for (i = r - 1; i >= 0; i--) {
eval ("if (" + me.id + "[i].getAttribute('colIndex') < startColIndex) parent = " + me.id + "[i];");
if (parent != undefined) return parent;
}
}
// getChildren get the immediate descendant items of the current item
// For more documentation, see the LEO file for this program
function getChildren(me) {
var i = 0;
// return an empty array if there are no children
if (me == undefined) return new Array();
var r = me.getAttribute("rowIndex") / 1;
// Loop thru the item collection. For comments on this, see the getParent function.
eval("var startColIndex = " + me.id + "[r].getAttribute('colIndex');");
startColIndex = startColIndex / 1;
var children = new Array();
var colIndex;
eval (
"for (i = r + 1; i < " + me.id + ".length; i++) {"
+ " colIndex = " + me.id + "[i].getAttribute('colIndex');"
+ " if (colIndex <= startColIndex) break;"
+ " if (colIndex == startColIndex + 1) children.push(" + me.id + "[i]);"
+ "}"
);
return children;
}
@code
// toggleNodeOpen close or open all lower nodes
// @me element (+/- node button) that was clicked
//
// for more documentation, see the LEO file for this program
function toggleNodeOpen(me) {
// first figure out whether we are supposed to close or open
// this node
var display;
// if it is a text button...
if (me.tagName == 'TD') {
if (me.innerHTML == '+') {
// The minus sign is unicode 8722. This
// is different than the keyboard hyphen (-).
me.innerHTML = "−";
display = 'block';
} else {
me.innerHTML = "+";
display = 'none';
}
} else { // it's an image button
var src = me.src;
if (src.search(/plus/) != -1) {
// The minus sign is unicode 8722. This
// is different than the keyboard hyphen (-).
me.src = src.replace(/plus/, 'minus');
display = 'block';
} else {
me.src = src.replace(/minus/, 'plus');
display = 'none';
}
}
eval ('var maxR = ' + me.linkedID + '.length');
var rowIndex = me.rowIndex / 1;
var colIndex = me.colIndex;
// Loop through the elements either hiding or showing. When we
// get to an element that is "higher" in the tree, i.e. has a lower
// column number than the element that was clicked on, exit the loop.
eval (
"for (r = rowIndex + 1; r < maxR; r++) {"
+ " if (" + me.linkedID + "(r).colIndex <= colIndex) break;"
+ me.linkedID + "(r).parentElement.parentElement.style.display = '" + display + "';"
+ "}"
);
}
// This function is used when attaching a collapse behavior to
// a checkbox. Not deployed in current implementation.
// For more documentation, see the LEO file for this program.
function collapse(colIndex, itemsID) {
if (colIndex == undefined) colIndex = 0;
var r = 0;
var children;
eval (
"do {"
+ " if (" + itemsID + "(r).colIndex == colIndex) {"
+ " display = 'none';"
+ " if (" + itemsID + "(r).checked) display = 'block';"
+ " r++;"
+ " do {"
+ " " + itemsID + "(r).parentElement.parentElement.style.display = display;"
+ " r++;"
+ " if (r >= " + itemsID + ".length) break;"
+ " } while (" + itemsID + "(r).colIndex > colIndex);"
+ " } else {"
+ " r++;"
+ " }"
+ "} while (r < " + itemsID + ".length);"
);
}
@code
var myCheckboxTree = new clsCheckboxTree(myItems, "CheckboxTree", true, false);
<< onload >>
@code
var CheckboxTreeItems;
function window_onload() {
// draw the checkboxtree
myCheckboxTree.draw();
// loop thru the checkboxes and set the ones that have been
var r = 0;
var ccode = "";
var item;
CheckboxTreeItems =document.getElementsByName("CheckboxTreeItems");
for (r = 0; r < CheckboxTreeItems.length; r++) {
// get next checkbox
item = CheckboxTreeItems[r];
// if the ccode attribute is blank, it means the checkbox isn't a leaf
// node checkbox, i.e. it doesn't have any data value
if (item.ccode == "") continue;
}
// set the focus to the first checkbox, bc otherwise it will
// get set to one of the submit buttons, which looks ugly
//CheckboxTreeItems[0].focus();
}
@code
<script>
var CheckboxTreeItemsCollapseFlag;
</script>
<br>
<div
id="CheckboxTree"
style="position:absolute; top: 0; width:316; height:440 ; overflow-y:scroll">
</div>
<form name="submitForm" action="wherever.jsp" method="post" >
<input type=hidden name=data>
<input type=hidden name=action>
</form>
<div style="position:absolute; width:316; top:460">
</div>
@code
function toggleTreeOff (me, r) {
// toggle all child nodes off
var prevColIndex = 0;
for (i = r; i < criteriaItem.length; i++) {
if (criteriaItem(i).colIndex < prevColIndex) break;
criteriaItem(i).checked = false;
prevColIndex = criteriaItem(i).colIndex;
}
var minColIndex = 9999;
var siblings;
var parent;
siblings = getSiblings(criteriaItem(i));
while (siblings != undefined) {
for (item in siblings) {
if (item.checked) return;
parent = getParent(criteriaItem(i));
siblings = getSiblings(parent);
}
}
// var foundSiblingChecked;
// var oldColIndex = me.colIndex;
// for (i = r - 1; i >= 0; i--) {
// colIndex = criteriaItem(i).colIndex;
// if (siblingIsChecked(criteriaItem(i)) break;
// oldColdIndex = colIndex;
// if (minColIndex > colIndex) criteriaItem(i).checked = false;
// if (colIndex == 0) break;
// minColIndex = Math.min(colIndex, minColIndex);
// }
}
function toggleTreeOn (me, r) {
// toggle all child nodes on
var startColIndex = me.colIndex;
for (i = r + 1; i < criteriaItem.length; i++) {
if (criteriaItem(i).colIndex <= startColIndex) break;
criteriaItem(i).checked = true;
}
// toggle all parent nodes on
var minColIndex = 9999;
for (i = r; i >= 0; i--) {
colIndex = criteriaItem(i).colIndex;
if (minColIndex > colIndex) criteriaItem(i).checked = true;
if (colIndex == 0) break;
minColIndex = Math.min(colIndex, minColIndex);
}
return;
}
@code
/** checkGroup
*
*@me a TD element
*@colIndex the column index of the TD element
*
**/
function toggleTree(me, colIndex, maxColIndex, checkValue) {
toggleChildren(me, colIndex, maxColIndex, checkValue);
toggleParents(me, colIndex, maxColIndex, checkValue);
}
function toggleChildren(me, colIndex, maxColIndex, checkValue) {
try {
if (checkValue == undefined) checkValue = me.firstChild.checked;
var myRow = me.parentElement;
var nextRow = myRow.nextSibling;
if (colIndex < maxColIndex) colIndex++;
nextCell = nextRow.cells(colIndex);
myCheckbox = nextCell.firstChild;
myCheckbox.checked = checkValue;
} catch (e) {
return;
}
//recurse
toggleChildren(myCheckbox.parentElement, colIndex, maxColIndex, checkValue);
}
function toggleParents(me, colIndex, maxColIndex, checkValue) {
try {
if (checkValue == undefined) checkValue = me.firstChild.checked;
var myRow = me.parentElement;
var nextRow = myRow.previousSibling;
if (colIndex == nextRow.cells.length - 1) {
nextCell = nextRow.cells(colIndex);
} else {
colIndex--;
nextCell = nextRow.cells(colIndex);
}
myCheckbox = nextCell.firstChild;
myCheckbox.checked = checkValue;
} catch (e) {
return;
}
//recurse
toggleParents(myCheckbox.parentElement, colIndex, maxColIndex, checkValue);
}
@code
// function to draw the treeselect widget
function drawTreeSelect() {
var cells;
var oldCell;
var oldCells = new Array();
var cellValue;
var cellCode;
var cellHTML;
var newSetFlag;
var dhtmlTreeSelect = '<table bgcolor="white" border="0" align="center" width="300" cellspacing="0" cellpadding="0">';
for (rowKey in this.items) {
dhtmlTreeSelect += '<tr>';
cells = this.items[rowKey].split(";");
for (c = 0; c < cells.length; c++) {
cellValue = cells[c].toLowerCase();
if (oldCells.length == cells.length) {
if (cellValue == oldCells[c] && c < cells.length - 1) {
cellValue = "";
} else {
if (c == 0) newSetFlag = true;
}
}
if (newSetFlag){dhtmlTreeSelect +=
"<tr><td class='spacer1'> </td><td></td><td></td></tr>" +
"<tr class='line1'><td class='line1'> </td><td></td><td></td></tr>" +
"<tr><td class='spacer1'> </td><td></td><td></td></tr>";
newSetFlag = false;
}
oldCells[c] = cells[c].toLowerCase();
cellHTML = " ";
if (cellValue != "") {
cellHTML = '<input type="checkbox" id="criteriaItem" cvalue="'
+ cellValue + '" ccode="' + rowKey + '">' + cellValue;
}
dhtmlTreeSelect += '<td nowrap>' + cellHTML + '</td>';
}
dhtmlTreeSelect += '</tr>';
}
// dhtmlTreeSelect +=
// "<tr><td class='spacer1'> </td><td></td><td></td></tr>" +
// "<tr class='line1'><td class='line1'> </td><td></td><td></td></tr>" +
// "<tr><td class='spacer1'> </td><td></td><td></td></tr>";
dhtmlTreeSelect += '</table>';
dhtmlTreeSelect = '<table bgcolor="red" align="center" cellpadding="1"><tr><td>' + dhtmlTreeSelect + '</td></tr></table>';
eval(this.container + ".innerHTML = dhtmlTreeSelect;");
}