| [8597867d] | 1 | # javascript.tcl -- |
|---|
| 2 | # |
|---|
| 3 | # This file contains procedures that create HTML and Java Script |
|---|
| 4 | # functions that implement objects such as: |
|---|
| 5 | # |
|---|
| 6 | # paired multi-selection boxes |
|---|
| 7 | # guarded submit buttons |
|---|
| 8 | # parent and child checkboxes |
|---|
| 9 | # |
|---|
| 10 | # Copyright (c) 1998-2000 by Ajuba Solutions. |
|---|
| 11 | # |
|---|
| 12 | # See the file "license.terms" for information on usage and redistribution |
|---|
| 13 | # of this file, and for a DISCLAIMER OF ALL WARRANTIES. |
|---|
| 14 | # |
|---|
| 15 | # RCS: @(#) $Id: javascript.tcl,v 1.5 2005/09/30 05:36:39 andreas_kupries Exp $ |
|---|
| 16 | |
|---|
| 17 | package require Tcl 8 |
|---|
| 18 | package require ncgi 1 |
|---|
| 19 | package provide javascript 1.0.2 |
|---|
| 20 | |
|---|
| 21 | |
|---|
| 22 | namespace eval ::javascript { |
|---|
| 23 | |
|---|
| 24 | # The SelectionObjList namespace variable is used to keep the list of |
|---|
| 25 | # selection boxes that were created as parts of paired multi-selection |
|---|
| 26 | # boxes. When a submit button is made for pages that have paired |
|---|
| 27 | # multi-selection boxes, we set a hidden field to store the initial values |
|---|
| 28 | # in the box. |
|---|
| 29 | |
|---|
| 30 | variable SelectionObjList {} |
|---|
| 31 | } |
|---|
| 32 | |
|---|
| 33 | # ::javascript::BeginJS -- |
|---|
| 34 | # |
|---|
| 35 | # Create HTML code to begin a java script program. |
|---|
| 36 | # |
|---|
| 37 | # Arguments: |
|---|
| 38 | # none. |
|---|
| 39 | # |
|---|
| 40 | # Results: |
|---|
| 41 | # Returns HTML code. |
|---|
| 42 | |
|---|
| 43 | proc ::javascript::BeginJS {} { |
|---|
| 44 | return "\n<SCRIPT LANGUAGE=\"JavaScript\">\n" |
|---|
| 45 | } |
|---|
| 46 | |
|---|
| 47 | # ::javascript::EndJS -- |
|---|
| 48 | # |
|---|
| 49 | # Create HTML code to end a java script program. |
|---|
| 50 | # |
|---|
| 51 | # Arguments: |
|---|
| 52 | # none. |
|---|
| 53 | # |
|---|
| 54 | # Results: |
|---|
| 55 | # Returns HTML code. |
|---|
| 56 | |
|---|
| 57 | proc ::javascript::EndJS {} { |
|---|
| 58 | return "\n</SCRIPT>\n" |
|---|
| 59 | } |
|---|
| 60 | |
|---|
| 61 | # ::javascript::MakeMultiSel -- |
|---|
| 62 | # |
|---|
| 63 | # Construct HTML code to create a multi-selection box. |
|---|
| 64 | # |
|---|
| 65 | # Arguments: |
|---|
| 66 | # id The suffix of all HTML objects in this megawidget. |
|---|
| 67 | # side Either "left" or "right". |
|---|
| 68 | # eltValues The values to populate the selection box with. |
|---|
| 69 | # eltNames The values to populate the selection box with. |
|---|
| 70 | # emptyElts The number of empty box entry to stuff in the |
|---|
| 71 | # Selection box as placeholders for elts to be added. |
|---|
| 72 | # length The number of elts to show before adding a vertical |
|---|
| 73 | # scrollbar. |
|---|
| 74 | # minWidth Number of spaces to determin the minimum box width. |
|---|
| 75 | # |
|---|
| 76 | # Results: |
|---|
| 77 | # Returns HTML to show the selection box. |
|---|
| 78 | |
|---|
| 79 | proc ::javascript::MakeMultiSel {id side eltValues eltNames emptyElts \ |
|---|
| 80 | length minWidth} { |
|---|
| 81 | |
|---|
| 82 | variable SelectionObjList |
|---|
| 83 | |
|---|
| 84 | # Add this selection box to the list. |
|---|
| 85 | |
|---|
| 86 | set name "$side$id" |
|---|
| 87 | lappend SelectionObjList $name |
|---|
| 88 | |
|---|
| 89 | # Create the selection box and populate it with elts. |
|---|
| 90 | |
|---|
| 91 | set html "" |
|---|
| 92 | append html "<select name=$name multiple size=$length>" |
|---|
| 93 | foreach elt $eltValues name $eltNames { |
|---|
| 94 | set encodedElt [ncgi::encode $elt] |
|---|
| 95 | append html "<option value=$encodedElt>$name" |
|---|
| 96 | } |
|---|
| 97 | |
|---|
| 98 | # Add empty values for the remaining elements. |
|---|
| 99 | |
|---|
| 100 | for {set i 0} {$i < $emptyElts} {incr i} { |
|---|
| 101 | append html "<option value=\"\"> " |
|---|
| 102 | } |
|---|
| 103 | |
|---|
| 104 | # Add an empty value with text that is as wide as the minWidth. |
|---|
| 105 | |
|---|
| 106 | set filler "" |
|---|
| 107 | for {set i 0} {$i < $minWidth} {incr i} { |
|---|
| 108 | append filler " " |
|---|
| 109 | } |
|---|
| 110 | append html "<option value=\"\">$filler" |
|---|
| 111 | |
|---|
| 112 | append html "</select>" |
|---|
| 113 | return $html |
|---|
| 114 | } |
|---|
| 115 | |
|---|
| 116 | # ::javascript::MakeClickProc -- |
|---|
| 117 | # |
|---|
| 118 | # Create a "moveSelected$id" java script procedure to move selected items |
|---|
| 119 | # from one selection box to the other. |
|---|
| 120 | # |
|---|
| 121 | # Arguments: |
|---|
| 122 | # id The suffix of all objects in this multiselection megawidget. |
|---|
| 123 | # |
|---|
| 124 | # Results: |
|---|
| 125 | # Returns java script code. |
|---|
| 126 | |
|---|
| 127 | proc ::javascript::MakeClickProc {id} { |
|---|
| 128 | |
|---|
| 129 | set result "\nfunction moveSelected${id}(fromObj,toObj) \{\n" |
|---|
| 130 | |
|---|
| 131 | # If nothing is selected, do nothing. |
|---|
| 132 | |
|---|
| 133 | append result "\n if (fromObj.selectedIndex > -1) \{" |
|---|
| 134 | |
|---|
| 135 | # Find the first empty element in the toObj. |
|---|
| 136 | |
|---|
| 137 | append result { |
|---|
| 138 | for (var k = 0; toObj.options[k].value != ""; k++) {} |
|---|
| 139 | } |
|---|
| 140 | |
|---|
| 141 | # Move the selected elements from the fromObj to the end of the toObj. |
|---|
| 142 | # Shift the objects in the fromObj to fill any empty spots. |
|---|
| 143 | # Clear out any extra slots in the fromObj. |
|---|
| 144 | # Deselect any selected elements (deselect with both 'selected = false' |
|---|
| 145 | # and by setting selectedIndex to -1, because setting selectedIndex to |
|---|
| 146 | # -1 didn't seem to clear selection on all windows browsers. |
|---|
| 147 | |
|---|
| 148 | append result { |
|---|
| 149 | for (var i = fromObj.selectedIndex, j = fromObj.selectedIndex; fromObj.options[i].value != ""; i++) { |
|---|
| 150 | if (fromObj.options[i].selected) { |
|---|
| 151 | toObj.options[k].text = fromObj.options[i].text |
|---|
| 152 | toObj.options[k++].value = fromObj.options[i].value |
|---|
| 153 | fromObj.options[i].selected = false |
|---|
| 154 | } else { |
|---|
| 155 | fromObj.options[j].text = fromObj.options[i].text |
|---|
| 156 | fromObj.options[j++].value = fromObj.options[i].value |
|---|
| 157 | } |
|---|
| 158 | } |
|---|
| 159 | for (; j < i; j++) { |
|---|
| 160 | fromObj.options[j].text = "" |
|---|
| 161 | fromObj.options[j].value = "" |
|---|
| 162 | } |
|---|
| 163 | fromObj.selectedIndex = -1 |
|---|
| 164 | } |
|---|
| 165 | |
|---|
| 166 | # Close the if statement and the function |
|---|
| 167 | |
|---|
| 168 | append result " \} |
|---|
| 169 | \} |
|---|
| 170 | " |
|---|
| 171 | return $result |
|---|
| 172 | } |
|---|
| 173 | |
|---|
| 174 | # ::javascript::makeSelectorWidget -- |
|---|
| 175 | # |
|---|
| 176 | # Construct HTML code to create a dual-multi-selection megawidget. This |
|---|
| 177 | # megawidget consists of two side-by-side multi-selection boxes |
|---|
| 178 | # separated by a left arrow and a right arrow button. The right arrow |
|---|
| 179 | # button moves all items selected in the left box to the right box. The |
|---|
| 180 | # left arrow button moves all items selected in the right box to the left |
|---|
| 181 | # box. |
|---|
| 182 | # |
|---|
| 183 | # Arguments: |
|---|
| 184 | # id The suffix of all HTML objects in this megawidget. |
|---|
| 185 | # leftLabel The text that appears above the left selection box. |
|---|
| 186 | # leftValueList The values of items in the left selection box. |
|---|
| 187 | # leftNameList The names to appear in the left selection box. |
|---|
| 188 | # rightLabel The text that appears above the right selection box. |
|---|
| 189 | # rightValueList The values of items in the right selection box. |
|---|
| 190 | # rightNameList The names to appear in the right selection box. |
|---|
| 191 | # length (optional) The number of elts to show before adding a |
|---|
| 192 | # vertical scrollbar. Defaults to 8. |
|---|
| 193 | # minWidth (optional) The number of spaces to determin the |
|---|
| 194 | # minimum box width. Defaults to 32. |
|---|
| 195 | # |
|---|
| 196 | # Results: |
|---|
| 197 | # Returns HTML to show the dual-multi-selection megawidget. |
|---|
| 198 | |
|---|
| 199 | proc ::javascript::makeSelectorWidget {id leftLabel leftValueList leftNameList \ |
|---|
| 200 | rightLabel rightValueList rightNameList {length 8} {minWidth 32}} { |
|---|
| 201 | |
|---|
| 202 | set html "" |
|---|
| 203 | append html [BeginJS] \ |
|---|
| 204 | [MakeClickProc $id] \ |
|---|
| 205 | [EndJS] |
|---|
| 206 | |
|---|
| 207 | append html "<table border=0 cellspacing=0 cellpadding=2>\n<tr><th>" \ |
|---|
| 208 | $leftLabel "</th><th></th><th>" $rightLabel "</th></tr>\n<tr>" |
|---|
| 209 | |
|---|
| 210 | set leftLen [llength $leftValueList] |
|---|
| 211 | set rightLen [llength $rightValueList] |
|---|
| 212 | set len [expr {$leftLen + $rightLen}] |
|---|
| 213 | |
|---|
| 214 | append html "<td valign=top colspan=1>" \ |
|---|
| 215 | [MakeMultiSel $id "left" $leftValueList $leftNameList \ |
|---|
| 216 | $rightLen $length $minWidth] \ |
|---|
| 217 | " </td>\n" |
|---|
| 218 | |
|---|
| 219 | append html "<td>" \ |
|---|
| 220 | "<table border=0 cellspacing=0 cellpadding=2>\n" |
|---|
| 221 | |
|---|
| 222 | set args "this.form.left${id},this.form.right${id}" |
|---|
| 223 | |
|---|
| 224 | append html "<tr><td><input type=button name=left${id}Button |
|---|
| 225 | onClick=\"moveSelected${id}(${args})\" value=\" >> \"></td></tr>" |
|---|
| 226 | |
|---|
| 227 | set args "this.form.right${id},this.form.left${id}" |
|---|
| 228 | |
|---|
| 229 | append html "<tr><td><input type=button name=right${id}Button |
|---|
| 230 | onClick=\"moveSelected${id}(${args})\" value=\" << \"></td></tr>" |
|---|
| 231 | |
|---|
| 232 | append html "</table>\n" \ |
|---|
| 233 | "</td>\n" |
|---|
| 234 | |
|---|
| 235 | append html "<td valign=top colspan=1>" \ |
|---|
| 236 | [MakeMultiSel $id "right" $rightValueList $rightNameList \ |
|---|
| 237 | $leftLen $length $minWidth] \ |
|---|
| 238 | " </td>\n" |
|---|
| 239 | |
|---|
| 240 | append html "</tr>\n" \ |
|---|
| 241 | "</table>\n" |
|---|
| 242 | |
|---|
| 243 | # Add a hidden field to collect the data. |
|---|
| 244 | |
|---|
| 245 | append html "<input type=hidden name=valleft${id} " \ |
|---|
| 246 | "value=\"$leftValueList\">\n" \ |
|---|
| 247 | "<input type=hidden name=valright${id} " \ |
|---|
| 248 | "value=\"$rightValueList\">\n" |
|---|
| 249 | |
|---|
| 250 | return $html |
|---|
| 251 | } |
|---|
| 252 | |
|---|
| 253 | # ::javascript::makeSubmitButton -- |
|---|
| 254 | # |
|---|
| 255 | # Create an HTML submit button that resets a hidden field for each |
|---|
| 256 | # registered multi-selection box. |
|---|
| 257 | # |
|---|
| 258 | # Arguments: |
|---|
| 259 | # name the name of the HTML button object to create. |
|---|
| 260 | # value the label of the HTML button object to create. |
|---|
| 261 | # |
|---|
| 262 | # Results: |
|---|
| 263 | # Returns HTML submit button code. |
|---|
| 264 | |
|---|
| 265 | proc ::javascript::makeSubmitButton {name value} { |
|---|
| 266 | variable SelectionObjList |
|---|
| 267 | set html "" |
|---|
| 268 | |
|---|
| 269 | # Create the java script procedure that gathers the current values for each |
|---|
| 270 | # registered multi-selection box. |
|---|
| 271 | |
|---|
| 272 | append html [BeginJS] |
|---|
| 273 | append html "\nfunction getSelections(form) \{\n" |
|---|
| 274 | |
|---|
| 275 | # For each registered selection box, reset hidden field to |
|---|
| 276 | # store nonempty values. |
|---|
| 277 | |
|---|
| 278 | foreach obj $SelectionObjList { |
|---|
| 279 | set selObj "form.$obj" |
|---|
| 280 | set hiddenObj "form.val$obj" |
|---|
| 281 | append html " var tmp$obj = \"\"\n" |
|---|
| 282 | append html " for (var i$obj = 0; i$obj < $selObj.length; i$obj++) {\n" |
|---|
| 283 | append html " if ($selObj.options\[i$obj\].value == \"\") {\n" |
|---|
| 284 | append html " break\n" |
|---|
| 285 | append html " }\n" |
|---|
| 286 | append html " tmp$obj += \" \" + $selObj.options\[i$obj\].value\n" |
|---|
| 287 | append html " }\n" |
|---|
| 288 | append html " $hiddenObj.value = tmp$obj \n" |
|---|
| 289 | } |
|---|
| 290 | append html "\}\n" |
|---|
| 291 | append html [EndJS] |
|---|
| 292 | |
|---|
| 293 | # Empty the selection box for the next page. |
|---|
| 294 | |
|---|
| 295 | set SelectionObjList {} |
|---|
| 296 | |
|---|
| 297 | # Create the HTML submit button. |
|---|
| 298 | |
|---|
| 299 | append html "<input type=submit name=\"$name\" value=\"$value\" |
|---|
| 300 | onClick=\"getSelections(this.form)\">" |
|---|
| 301 | |
|---|
| 302 | return $html |
|---|
| 303 | } |
|---|
| 304 | |
|---|
| 305 | # ::javascript::makeProtectedSubmitButton -- |
|---|
| 306 | # |
|---|
| 307 | # Create an HTML submit button that prompts the user with a |
|---|
| 308 | # continue/cancel shutdown warning before the form is submitted. |
|---|
| 309 | # |
|---|
| 310 | # Arguments: |
|---|
| 311 | # name the name of the HTML button object to create. |
|---|
| 312 | # value the label of the HTML button object to create. |
|---|
| 313 | # msg The message to display when the button is pressed. |
|---|
| 314 | # |
|---|
| 315 | # Results: |
|---|
| 316 | # Returns HTML submit button code. |
|---|
| 317 | |
|---|
| 318 | proc ::javascript::makeProtectedSubmitButton {name value msg} { |
|---|
| 319 | set html "" |
|---|
| 320 | |
|---|
| 321 | # Create the java script procedure that gives the user the option to cancel |
|---|
| 322 | # the server shutdown request. |
|---|
| 323 | |
|---|
| 324 | append html [BeginJS] |
|---|
| 325 | append html "\nfunction areYouSure${name}(form) \{\n" |
|---|
| 326 | append html " if (confirm(\"$msg\")) \{\n" |
|---|
| 327 | append html " return true\n" |
|---|
| 328 | append html " \} else \{\n" |
|---|
| 329 | append html " return false\n" |
|---|
| 330 | append html " \}\n" |
|---|
| 331 | append html "\}\n" |
|---|
| 332 | append html [EndJS] |
|---|
| 333 | |
|---|
| 334 | # Create the HTML submit button. |
|---|
| 335 | |
|---|
| 336 | append html "<input type=submit name=\"$name\" value=\"$value\" |
|---|
| 337 | onClick=\"return areYouSure${name}(this.form)\">" |
|---|
| 338 | |
|---|
| 339 | return $html |
|---|
| 340 | } |
|---|
| 341 | |
|---|
| 342 | # ::javascript::makeMasterButton -- |
|---|
| 343 | # |
|---|
| 344 | # Create an HTML button that sets it's slave checkboxs to the boolean |
|---|
| 345 | # value. |
|---|
| 346 | # |
|---|
| 347 | # Arguments: |
|---|
| 348 | # master the name of the child's parent html checkbox object. |
|---|
| 349 | # value the value of the master. |
|---|
| 350 | # slaves the name of child html checkbox object to create. |
|---|
| 351 | # boolean the java script boolean value that will be given to all the |
|---|
| 352 | # slaves. Must be true or false. |
|---|
| 353 | # |
|---|
| 354 | # Results: |
|---|
| 355 | # Returns HTML code to create the child checkbox. |
|---|
| 356 | |
|---|
| 357 | proc ::javascript::makeMasterButton {master value slavePattern boolean} { |
|---|
| 358 | set html "" |
|---|
| 359 | |
|---|
| 360 | # Create the java script "checkMaster$name" proc that gets called when the |
|---|
| 361 | # master checkbox is selected or de-selected. |
|---|
| 362 | |
|---|
| 363 | append html [BeginJS] |
|---|
| 364 | append html "\nfunction checkMaster${master}(form) \{\n" |
|---|
| 365 | append html " for (var i = 0; i < form.elements.length; i++) \{\n" |
|---|
| 366 | append html " if (form.elements\[i\].name.match('$slavePattern')) \{\n" |
|---|
| 367 | append html " form.elements\[i\].checked = $boolean \n" |
|---|
| 368 | append html " \}\n" |
|---|
| 369 | append html " \}\n" |
|---|
| 370 | |
|---|
| 371 | append html "\}\n" |
|---|
| 372 | append html [EndJS] |
|---|
| 373 | |
|---|
| 374 | # Create the HTML button object. |
|---|
| 375 | |
|---|
| 376 | append html "<input type=button name=\"$master\" value=\"$value\" " \ |
|---|
| 377 | "onClick=\"checkMaster${master}(this.form)\">\n" |
|---|
| 378 | |
|---|
| 379 | return $html |
|---|
| 380 | } |
|---|
| 381 | |
|---|
| 382 | # ::javascript::makeParentCheckbox -- |
|---|
| 383 | # |
|---|
| 384 | # Create an HTML checkbox and tie its value to that of it's child |
|---|
| 385 | # checkbox. If the parent is unchecked, the child is automatically |
|---|
| 386 | # unchecked. |
|---|
| 387 | # |
|---|
| 388 | # Arguments: |
|---|
| 389 | # parentName the name of parent html checkbox object to create. |
|---|
| 390 | # childName the name of the parent's child html checkbox object |
|---|
| 391 | # Results: |
|---|
| 392 | # Returns HTML code to create the child checkbox. |
|---|
| 393 | |
|---|
| 394 | proc ::javascript::makeParentCheckbox {parentName childName} { |
|---|
| 395 | set parentObj "form.$parentName" |
|---|
| 396 | set childObj "form.$childName" |
|---|
| 397 | set html "" |
|---|
| 398 | |
|---|
| 399 | # Create the java script "checkParent$name" proc that gets called when the |
|---|
| 400 | # parent checkbox is selected or de-selected. |
|---|
| 401 | |
|---|
| 402 | append html [BeginJS] |
|---|
| 403 | append html "\nfunction checkParent${parentName}(form) \{\n" |
|---|
| 404 | append html " if (!$parentObj.checked && $childObj.checked) \{\n" |
|---|
| 405 | append html " $childObj.checked = false\n" |
|---|
| 406 | append html " \}\n" |
|---|
| 407 | append html "\}\n" |
|---|
| 408 | append html [EndJS] |
|---|
| 409 | |
|---|
| 410 | # Create the HTML checkbox object. |
|---|
| 411 | |
|---|
| 412 | append html "<input type=checkbox name=$parentName value=1 " \ |
|---|
| 413 | "onClick=\"checkParent${parentName}(this.form)\">" |
|---|
| 414 | |
|---|
| 415 | return $html |
|---|
| 416 | } |
|---|
| 417 | |
|---|
| 418 | # ::javascript::makeChildCheckbox -- |
|---|
| 419 | # |
|---|
| 420 | # Create an HTML checkbox and tie its value to that of it's parent |
|---|
| 421 | # checkbox. If the child is checked, the parent is automatically |
|---|
| 422 | # checked. |
|---|
| 423 | # |
|---|
| 424 | # Arguments: |
|---|
| 425 | # parentName the name of the child's parent html checkbox object |
|---|
| 426 | # childName the name of child html checkbox object to create. |
|---|
| 427 | # |
|---|
| 428 | # Results: |
|---|
| 429 | # Returns HTML code to create the child checkbox. |
|---|
| 430 | |
|---|
| 431 | proc ::javascript::makeChildCheckbox {parentName childName} { |
|---|
| 432 | set parentObj "form.$parentName" |
|---|
| 433 | set childObj "form.$childName" |
|---|
| 434 | set html "" |
|---|
| 435 | |
|---|
| 436 | # Create the java script "checkChild$name" proc that gets called when the |
|---|
| 437 | # child checkbox is selected or de-selected. |
|---|
| 438 | |
|---|
| 439 | append html [BeginJS] |
|---|
| 440 | append html "\nfunction checkChild${childName}(form) \{\n" |
|---|
| 441 | append html " if ($childObj.checked && !$parentObj.checked) \{\n" |
|---|
| 442 | append html " $parentObj.checked = true\n" |
|---|
| 443 | append html " \}\n" |
|---|
| 444 | append html "\}\n" |
|---|
| 445 | append html [EndJS] |
|---|
| 446 | |
|---|
| 447 | # Create the HTML checkbox object. |
|---|
| 448 | |
|---|
| 449 | append html "<input type=checkbox name=$childName value=1 " \ |
|---|
| 450 | "onClick=\"checkChild${childName}(this.form)\">" |
|---|
| 451 | |
|---|
| 452 | return $html |
|---|
| 453 | } |
|---|