# javascript.tcl --
#
# This file contains procedures that create HTML and Java Script
# functions that implement objects such as:
#
# paired multi-selection boxes
# guarded submit buttons
# parent and child checkboxes
#
# Copyright (c) 1998-2000 by Ajuba Solutions.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: javascript.tcl,v 1.5 2005/09/30 05:36:39 andreas_kupries Exp $
package require Tcl 8
package require ncgi 1
package provide javascript 1.0.2
namespace eval ::javascript {
# The SelectionObjList namespace variable is used to keep the list of
# selection boxes that were created as parts of paired multi-selection
# boxes. When a submit button is made for pages that have paired
# multi-selection boxes, we set a hidden field to store the initial values
# in the box.
variable SelectionObjList {}
}
# ::javascript::BeginJS --
#
# Create HTML code to begin a java script program.
#
# Arguments:
# none.
#
# Results:
# Returns HTML code.
proc ::javascript::BeginJS {} {
return "\n\n"
}
# ::javascript::MakeMultiSel --
#
# Construct HTML code to create a multi-selection box.
#
# Arguments:
# id The suffix of all HTML objects in this megawidget.
# side Either "left" or "right".
# eltValues The values to populate the selection box with.
# eltNames The values to populate the selection box with.
# emptyElts The number of empty box entry to stuff in the
# Selection box as placeholders for elts to be added.
# length The number of elts to show before adding a vertical
# scrollbar.
# minWidth Number of spaces to determin the minimum box width.
#
# Results:
# Returns HTML to show the selection box.
proc ::javascript::MakeMultiSel {id side eltValues eltNames emptyElts \
length minWidth} {
variable SelectionObjList
# Add this selection box to the list.
set name "$side$id"
lappend SelectionObjList $name
# Create the selection box and populate it with elts.
set html ""
append html ""
return $html
}
# ::javascript::MakeClickProc --
#
# Create a "moveSelected$id" java script procedure to move selected items
# from one selection box to the other.
#
# Arguments:
# id The suffix of all objects in this multiselection megawidget.
#
# Results:
# Returns java script code.
proc ::javascript::MakeClickProc {id} {
set result "\nfunction moveSelected${id}(fromObj,toObj) \{\n"
# If nothing is selected, do nothing.
append result "\n if (fromObj.selectedIndex > -1) \{"
# Find the first empty element in the toObj.
append result {
for (var k = 0; toObj.options[k].value != ""; k++) {}
}
# Move the selected elements from the fromObj to the end of the toObj.
# Shift the objects in the fromObj to fill any empty spots.
# Clear out any extra slots in the fromObj.
# Deselect any selected elements (deselect with both 'selected = false'
# and by setting selectedIndex to -1, because setting selectedIndex to
# -1 didn't seem to clear selection on all windows browsers.
append result {
for (var i = fromObj.selectedIndex, j = fromObj.selectedIndex; fromObj.options[i].value != ""; i++) {
if (fromObj.options[i].selected) {
toObj.options[k].text = fromObj.options[i].text
toObj.options[k++].value = fromObj.options[i].value
fromObj.options[i].selected = false
} else {
fromObj.options[j].text = fromObj.options[i].text
fromObj.options[j++].value = fromObj.options[i].value
}
}
for (; j < i; j++) {
fromObj.options[j].text = ""
fromObj.options[j].value = ""
}
fromObj.selectedIndex = -1
}
# Close the if statement and the function
append result " \}
\}
"
return $result
}
# ::javascript::makeSelectorWidget --
#
# Construct HTML code to create a dual-multi-selection megawidget. This
# megawidget consists of two side-by-side multi-selection boxes
# separated by a left arrow and a right arrow button. The right arrow
# button moves all items selected in the left box to the right box. The
# left arrow button moves all items selected in the right box to the left
# box.
#
# Arguments:
# id The suffix of all HTML objects in this megawidget.
# leftLabel The text that appears above the left selection box.
# leftValueList The values of items in the left selection box.
# leftNameList The names to appear in the left selection box.
# rightLabel The text that appears above the right selection box.
# rightValueList The values of items in the right selection box.
# rightNameList The names to appear in the right selection box.
# length (optional) The number of elts to show before adding a
# vertical scrollbar. Defaults to 8.
# minWidth (optional) The number of spaces to determin the
# minimum box width. Defaults to 32.
#
# Results:
# Returns HTML to show the dual-multi-selection megawidget.
proc ::javascript::makeSelectorWidget {id leftLabel leftValueList leftNameList \
rightLabel rightValueList rightNameList {length 8} {minWidth 32}} {
set html ""
append html [BeginJS] \
[MakeClickProc $id] \
[EndJS]
append html "
\n
" \
$leftLabel "
" $rightLabel "
\n
"
set leftLen [llength $leftValueList]
set rightLen [llength $rightValueList]
set len [expr {$leftLen + $rightLen}]
append html "
\n"
# Add a hidden field to collect the data.
append html "\n" \
"\n"
return $html
}
# ::javascript::makeSubmitButton --
#
# Create an HTML submit button that resets a hidden field for each
# registered multi-selection box.
#
# Arguments:
# name the name of the HTML button object to create.
# value the label of the HTML button object to create.
#
# Results:
# Returns HTML submit button code.
proc ::javascript::makeSubmitButton {name value} {
variable SelectionObjList
set html ""
# Create the java script procedure that gathers the current values for each
# registered multi-selection box.
append html [BeginJS]
append html "\nfunction getSelections(form) \{\n"
# For each registered selection box, reset hidden field to
# store nonempty values.
foreach obj $SelectionObjList {
set selObj "form.$obj"
set hiddenObj "form.val$obj"
append html " var tmp$obj = \"\"\n"
append html " for (var i$obj = 0; i$obj < $selObj.length; i$obj++) {\n"
append html " if ($selObj.options\[i$obj\].value == \"\") {\n"
append html " break\n"
append html " }\n"
append html " tmp$obj += \" \" + $selObj.options\[i$obj\].value\n"
append html " }\n"
append html " $hiddenObj.value = tmp$obj \n"
}
append html "\}\n"
append html [EndJS]
# Empty the selection box for the next page.
set SelectionObjList {}
# Create the HTML submit button.
append html ""
return $html
}
# ::javascript::makeProtectedSubmitButton --
#
# Create an HTML submit button that prompts the user with a
# continue/cancel shutdown warning before the form is submitted.
#
# Arguments:
# name the name of the HTML button object to create.
# value the label of the HTML button object to create.
# msg The message to display when the button is pressed.
#
# Results:
# Returns HTML submit button code.
proc ::javascript::makeProtectedSubmitButton {name value msg} {
set html ""
# Create the java script procedure that gives the user the option to cancel
# the server shutdown request.
append html [BeginJS]
append html "\nfunction areYouSure${name}(form) \{\n"
append html " if (confirm(\"$msg\")) \{\n"
append html " return true\n"
append html " \} else \{\n"
append html " return false\n"
append html " \}\n"
append html "\}\n"
append html [EndJS]
# Create the HTML submit button.
append html ""
return $html
}
# ::javascript::makeMasterButton --
#
# Create an HTML button that sets it's slave checkboxs to the boolean
# value.
#
# Arguments:
# master the name of the child's parent html checkbox object.
# value the value of the master.
# slaves the name of child html checkbox object to create.
# boolean the java script boolean value that will be given to all the
# slaves. Must be true or false.
#
# Results:
# Returns HTML code to create the child checkbox.
proc ::javascript::makeMasterButton {master value slavePattern boolean} {
set html ""
# Create the java script "checkMaster$name" proc that gets called when the
# master checkbox is selected or de-selected.
append html [BeginJS]
append html "\nfunction checkMaster${master}(form) \{\n"
append html " for (var i = 0; i < form.elements.length; i++) \{\n"
append html " if (form.elements\[i\].name.match('$slavePattern')) \{\n"
append html " form.elements\[i\].checked = $boolean \n"
append html " \}\n"
append html " \}\n"
append html "\}\n"
append html [EndJS]
# Create the HTML button object.
append html "\n"
return $html
}
# ::javascript::makeParentCheckbox --
#
# Create an HTML checkbox and tie its value to that of it's child
# checkbox. If the parent is unchecked, the child is automatically
# unchecked.
#
# Arguments:
# parentName the name of parent html checkbox object to create.
# childName the name of the parent's child html checkbox object
# Results:
# Returns HTML code to create the child checkbox.
proc ::javascript::makeParentCheckbox {parentName childName} {
set parentObj "form.$parentName"
set childObj "form.$childName"
set html ""
# Create the java script "checkParent$name" proc that gets called when the
# parent checkbox is selected or de-selected.
append html [BeginJS]
append html "\nfunction checkParent${parentName}(form) \{\n"
append html " if (!$parentObj.checked && $childObj.checked) \{\n"
append html " $childObj.checked = false\n"
append html " \}\n"
append html "\}\n"
append html [EndJS]
# Create the HTML checkbox object.
append html ""
return $html
}
# ::javascript::makeChildCheckbox --
#
# Create an HTML checkbox and tie its value to that of it's parent
# checkbox. If the child is checked, the parent is automatically
# checked.
#
# Arguments:
# parentName the name of the child's parent html checkbox object
# childName the name of child html checkbox object to create.
#
# Results:
# Returns HTML code to create the child checkbox.
proc ::javascript::makeChildCheckbox {parentName childName} {
set parentObj "form.$parentName"
set childObj "form.$childName"
set html ""
# Create the java script "checkChild$name" proc that gets called when the
# child checkbox is selected or de-selected.
append html [BeginJS]
append html "\nfunction checkChild${childName}(form) \{\n"
append html " if ($childObj.checked && !$parentObj.checked) \{\n"
append html " $parentObj.checked = true\n"
append html " \}\n"
append html "\}\n"
append html [EndJS]
# Create the HTML checkbox object.
append html ""
return $html
}