Index: openacs-4/packages/acs-templating/tcl/0-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/tcl/Attic/0-procs.tcl,v
diff -u -r1.7 -r1.7.2.1
--- openacs-4/packages/acs-templating/tcl/0-procs.tcl 14 Sep 2002 18:13:47 -0000 1.7
+++ openacs-4/packages/acs-templating/tcl/0-procs.tcl 5 Mar 2003 14:57:37 -0000 1.7.2.1
@@ -53,7 +53,7 @@
# default settings
variable defaults
- set defaults [list method post section {}]
+ set defaults [list method post section {} mode edit edit_buttons { { "OK" ok } } display_buttons { { "Edit" edit } }]
}
namespace eval wizard {
@@ -105,6 +105,13 @@
Generic wrapper for registered tag handlers.
} {
+ # LARS:
+ # We only ns_register_adptag the tag if it hasn't already been registered
+ # (if the proc doesn't exist).
+ # This makes debugging templating tags so much easier, because you don't have
+ # to restart the server each time.
+ set exists_p [llength [info procs template_tag_$name]]
+
switch [llength $arglist] {
1 {
@@ -119,7 +126,9 @@
return \"\"
}"
- ns_register_adptag $name template_tag_$name
+ if { !$exists_p } {
+ ns_register_adptag $name template_tag_$name
+ }
}
2 {
@@ -139,7 +148,9 @@
return \"\"
}"
- ns_register_adptag $name /$name template_tag_$name
+ if { !$exists_p } {
+ ns_register_adptag $name /$name template_tag_$name
+ }
}
default { error "Invalid number of arguments to tag handler." }
Index: openacs-4/packages/acs-templating/tcl/date-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/tcl/date-procs.tcl,v
diff -u -r1.14 -r1.14.2.1
--- openacs-4/packages/acs-templating/tcl/date-procs.tcl 10 Sep 2002 22:22:15 -0000 1.14
+++ openacs-4/packages/acs-templating/tcl/date-procs.tcl 5 Mar 2003 14:57:37 -0000 1.14.2.1
@@ -230,6 +230,10 @@
return 0
}
sql_date {
+ # LARS: Empty date results in NULL value
+ if { [empty_string_p $date] } {
+ return "NULL"
+ }
set value ""
set format ""
set space ""
@@ -700,7 +704,7 @@
}
ad_proc -public template::widget::dateFragment {
- element_reference fragment size type value } {
+ element_reference fragment size type value {mode edit} } {
Create an input widget for the given date fragment
If type is "t", uses a text widget for the fragment, with the given
size.
@@ -713,39 +717,52 @@
set value [template::util::date::get_property $fragment $value]
set value [template::util::leadingTrim $value]
- if { [info exists element(${fragment}_interval)] } {
- set interval $element(${fragment}_interval)
+ if { ![string equal $mode "edit"] } {
+ set output {}
+ append output ""
+ append output $value
+ return $output
} else {
- # Display text entry for some elements, or if the type is text
- if { [string equal $type t] ||
- [regexp "year|short_year" $fragment] } {
- return "\n"
- } else {
- # Use a default range for others
- set interval [template::util::date::defaultInterval $fragment]
- }
+ if { [info exists element(${fragment}_interval)] } {
+ set interval $element(${fragment}_interval)
+ } else {
+ # Display text entry for some elements, or if the type is text
+ if { [string equal $type t] ||
+ [regexp "year|short_year" $fragment] } {
+ return "\n"
+ } else {
+ # Use a default range for others
+ set interval [template::util::date::defaultInterval $fragment]
+ }
+ }
+ return [template::widget::numericRange "$element(name).$fragment" \
+ $interval $size $value]
}
-
- return [template::widget::numericRange "$element(name).$fragment" \
- $interval $size $value]
}
ad_proc -public template::widget::ampmFragment {
- element_reference fragment size type value } {
+ element_reference fragment size type value {mode edit} } {
Create a widget that shows the am/pm selection
} {
upvar $element_reference element
set value [template::util::date::get_property $fragment $value]
- return [template::widget::menu \
- "$element(name).$fragment" { {A.M. am} {P.M. pm}} $value {}]
+ if { ![string equal $mode "edit"] } {
+ set output {}
+ append output ""
+ append output $value
+ return $output
+ } else {
+ return [template::widget::menu \
+ "$element(name).$fragment" { {A.M. am} {P.M. pm}} $value {}]
+ }
}
ad_proc -public template::widget::monthFragment {
- element_reference fragment size type value } {
+ element_reference fragment size type value {mode edit} } {
Create a month entry widget with short or long month names
} {
@@ -755,13 +772,22 @@
set value [template::util::date::get_property $fragment $value]
- set options [list [list "--" {}]]
- for { set i 1 } { $i <= 12 } { incr i } {
- lappend options [list [template::util::date::monthName $i $size] $i]
+ if { ![string equal $mode "edit"] } {
+ set output {}
+ if { [exists_and_not_null value] } {
+ append output ""
+ append output [template::util::date::monthName $value $size]
+ }
+ return $output
+ } else {
+ set options [list [list "--" {}]]
+ for { set i 1 } { $i <= 12 } { incr i } {
+ lappend options [list [template::util::date::monthName $i $size] $i]
+ }
+
+ return [template::widget::menu \
+ "$element(name).$fragment" $options $value {} ]
}
-
- return [template::widget::menu \
- "$element(name).$fragment" $options $value {} ]
}
@@ -861,12 +887,14 @@
# Output the widget
set fragment_def $template::util::date::fragment_widgets([string toupper $token])
set fragment [lindex $fragment_def 1]
+
append output [template::widget::[lindex $fragment_def 0] \
element \
$fragment \
[lindex $fragment_def 2] \
$type \
- $value]
+ $value \
+ $element(mode)]
# Output the separator
if { [string equal $sep " "] } {
Index: openacs-4/packages/acs-templating/tcl/element-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/tcl/element-procs.tcl,v
diff -u -r1.9.2.2 -r1.9.2.3
--- openacs-4/packages/acs-templating/tcl/element-procs.tcl 26 Feb 2003 21:32:50 -0000 1.9.2.2
+++ openacs-4/packages/acs-templating/tcl/element-procs.tcl 5 Mar 2003 14:57:37 -0000 1.9.2.3
@@ -133,11 +133,15 @@
variable defaults
array set opts $defaults
- template::util::get_opts $args
+ # By default, the form/edit mode is set to the empty string
+ # Can be set to something else if you want
+ set opts(mode) {}
# set the form section
set opts(section) $form_properties(section)
+ template::util::get_opts $args
+
# set a name if none specified
if { ! [info exists opts(name)] } { set opts(name) $opts(id) }
@@ -162,8 +166,16 @@
# check for submission
if { [template::form is_submission $form_id] || [info exists opts(param)] } {
validate $form_id $element_id
- }
+ } elseif { ![empty_string_p [ns_queryget "__edit"]] } {
+ # If the magic __edit button was hit, try to get values from the form still
+ # but don't do any validation
+ set opts(values) [querygetall opts]
+ # be careful not to clobber a default value if one has been specified
+ if { [llength $opts(values)] || ! [info exists opts(value)] } {
+ set opts(value) [lindex $opts(values) 0]
+ }
+ }
}
ad_proc -public template::element::set_properties { form_id element_id args } {
@@ -371,6 +383,7 @@
if { ! [eval $v_code] } {
# value is invalid according to custom validation code
+ # Do some expansion on $value, ${value}, $label, and ${label}
lappend v_errors [string map [list \$value $value \${value} $value \$label $label \${label} $label] $v_message]
set formerror($element_id:$v_name) [lindex $v_errors end]
}
@@ -501,7 +514,11 @@
# Remember that the element has been rendered already
set element(is_rendered) t
- return "$element(before_html) [template::widget::$element(widget) element $tag_attributes] $element(after_html)"
+ if { ![string equal $element(mode) "edit"] && [info exists element(display_value)] && ![string equal $element(widget) "hidden"] } {
+ return "$element(before_html) $element(display_value) $element(after_html)"
+ } else {
+ return "$element(before_html) [template::widget::$element(widget) element $tag_attributes] $element(after_html)"
+ }
}
ad_proc -private template::element::render_help { form_id element_id tag_attributes } {
Index: openacs-4/packages/acs-templating/tcl/form-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/tcl/form-procs.tcl,v
diff -u -r1.7.2.1 -r1.7.2.2
--- openacs-4/packages/acs-templating/tcl/form-procs.tcl 21 Feb 2003 12:25:22 -0000 1.7.2.1
+++ openacs-4/packages/acs-templating/tcl/form-procs.tcl 5 Mar 2003 14:57:37 -0000 1.7.2.2
@@ -28,6 +28,9 @@
api is used to manipulate form elements.
@see template::form::create
+ @see template::form::get_button
+ @see template::form::get_action
+ @see template::form::set_properties
@see template::form::exists
@see template::form::export
@see template::form::get_combined_values
@@ -78,15 +81,30 @@
upvar #$level $id:submission submission
if { [string equal $id request] } {
-
# request is the magic ID for the form holding query parameters
set submission 1
-
} else {
-
+ # If there's a form:id argument, and it's the ID of this form,
+ # we're being submitted
set submission [string equal $id [ns_queryget form:id]]
}
+ set formbutton [get_button $id]
+
+ # If the user hit a button named "cancel", redirect and about
+ if { $submission && [string equal $formbutton "cancel"] && [exists_and_not_null opts(cancel_url)]} {
+ ad_returnredirect $opts(cancel_url)
+ ad_script_abort
+ }
+
+ set formaction [get_action $id]
+
+ # If we were in display mode, and a button was clicked, we should be in edit mode now
+ if { $submission && [string equal [ns_queryget "form:mode"] "display"] } {
+ set opts(mode) "edit"
+ set submission 0
+ }
+
# add elements specified at the time the form is created
if { [info exists opts(elements)] } {
@@ -103,6 +121,100 @@
}
}
+ad_proc -public template::form::set_properties { id args } {
+ Set properties for a form
+
+ @param id The ID of an ATS form object.
+ @param args Properties to set
+} {
+ set level [template::adp_level]
+
+ # form properties
+ upvar #$level $id:properties opts
+
+ template::util::get_opts $args
+}
+
+ad_proc -public template::form::get_button { id } {
+ Find out which button was clicked
+
+ @param id The ID of an ATS form object.
+ @return the name of the button clicked
+} {
+ set level [template::adp_level]
+
+ # keep form properties and a list of the element items
+ upvar #$level $id:button formbutton
+
+ # If we've already found the button, just return that
+ if { [info exists formbutton] } {
+ return $formbutton
+ }
+
+ # Otherwise, find out now
+
+ set formbutton {}
+
+ # If the form isn't being submitted at all, no button was clicked
+ if { ![string equal $id [ns_queryget form:id]] } {
+ return {}
+ }
+
+ # Search the submit form for the button
+ set form [ns_getform]
+
+ if { ![empty_string_p $form] } {
+ set size [ns_set size $form]
+ for { set i 0 } { $i < $size } { incr i } {
+ if { [string match "formbutton:*" [ns_set key $form $i]] } {
+ set formbutton [string range [ns_set key $form $i] [string length "formbutton:"] end]
+ break
+ }
+ }
+ }
+
+ return $formbutton
+}
+
+ad_proc -public template::form::get_action { id } {
+ Find out which action is in progress
+
+ @param id The ID of an ATS form object.
+ @return the name of the action in progress
+} {
+ set level [template::adp_level]
+
+ # keep form properties and a list of the element items
+ upvar #$level $id:action formaction
+
+ # If we've already found the action, just return that
+ if { [info exists formaction] } {
+ return $formaction
+ }
+
+ # Otherwise, find out now
+
+ set formaction {}
+
+ # If the form isn't being submitted at all, there's no action
+ if { ![string equal $id [ns_queryget "form:id"]] } {
+ return {}
+ }
+
+ set formbutton [get_button $id]
+
+ # If we were in display mode, and a button was clicked, we should be in edit mode now
+ if { [string equal [ns_queryget "form:mode"] "display"] && ![empty_string_p $formbutton] } {
+ set formaction $formbutton
+ return $formaction
+ }
+
+ # Otherwise, there should be a form:action variable in the form
+ set formaction [ns_queryget "form:action"]
+
+ return $formaction
+}
+
ad_proc -public template::form::exists { id } {
Determine whether a form exists by checking for its data structures.
@@ -128,6 +240,11 @@
} {
get_reference
+ #
+ # Elements
+ #
+
+
set elements:rowcount 0
foreach element_ref $elements {
@@ -138,7 +255,48 @@
upvar #$level $element_ref elements:${elements:rowcount}
set "elements:${elements:rowcount}(rownum)" ${elements:rowcount}
}
-
+
+ #
+ # Buttons
+ #
+
+ if { [exists_and_not_null form_properties(cancel_url)] && ![exists_and_not_null form_properties(cancel_label)] } {
+ set form_properties(cancel_label) "Cancel"
+ }
+
+ if { [exists_and_not_null form_properties(cancel_url)] } {
+ lappend form_properties(edit_buttons) [list $form_properties(cancel_label) cancel]
+ }
+
+ if { ![template::util::is_nil form_properties(has_submit)] && [template::util::is_true $form_properties(has_submit)] } {
+ set form_properties(edit_buttons) {}
+ }
+
+ if { ![template::util::is_nil form_properties(has_edit)] && [template::util::is_true $form_properties(has_edit)] } {
+ set form_properties(display_buttons) {}
+ }
+
+ if { ![template::util::is_nil form_properties(actions)] && [template::util::is_true $form_properties(actions)] } {
+ set form_properties(display_buttons) $form_properties(actions)
+ }
+
+ set buttons:rowcount 0
+
+ foreach button $form_properties(${form_properties(mode)}_buttons) {
+ incr buttons:rowcount
+
+ set label [lindex $button 0]
+ set name [lindex $button 1]
+
+ if { [string equal $name "ok"] } {
+ # We hard-code the OK button to be wider than it otherwise would
+ set "buttons:${buttons:rowcount}(label)" " $label "
+ } else {
+ set "buttons:${buttons:rowcount}(label)" $label
+ }
+ set "buttons:${buttons:rowcount}(name)" "formbutton:$name"
+ }
+
if { [string equal $style {}] } { set style standard }
set file_stub [template::get_resource_path]/forms/$style
@@ -228,6 +386,9 @@
if { [info exists $id:error] } {
uplevel #$level "upvar 0 $id:error formerror"
+
+ # There were errors on the form, force edit mode
+ set properties(mode) edit
} else {
@@ -237,6 +398,19 @@
if { [info exists formerror] } { unset formerror }
}
+ # Propagate form mode to all form elements
+ foreach element_ref $elements {
+
+ # get a reference by element ID
+ upvar #$level $element_ref element
+
+ # Check if the element has an empty string mode, and in
+ # that case, set to form mode
+ if { [string equal $element(mode) {}] } {
+ set element(mode) $properties(mode)
+ }
+ }
+
# get any additional attributes developer specified to include in form tag
if { [info exists properties(html)] } {
array set attributes $properties(html)
@@ -264,7 +438,15 @@
append output ">"
- append output ""
+ # Export form ID and current form mode
+ append output [export_vars -form { { form\:id $id } { form\:mode $properties(mode) } }]
+
+ # If we're in edit mode, output the action
+ upvar #$level $id:action form_action
+ if { [string equal $properties(mode) "edit"] && [exists_and_not_null form_action] } {
+ upvar #$level $id:action action
+ append output [export_vars -form { { form\:action $form_action } }]
+ }
return $output
}
Index: openacs-4/packages/acs-templating/tcl/parse-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/tcl/parse-procs.tcl,v
diff -u -r1.6 -r1.6.2.1
--- openacs-4/packages/acs-templating/tcl/parse-procs.tcl 15 Sep 2002 22:10:53 -0000 1.6
+++ openacs-4/packages/acs-templating/tcl/parse-procs.tcl 5 Mar 2003 14:57:37 -0000 1.6.2.1
@@ -510,7 +510,7 @@
variable tag_stack
- set last [expr [llength $tag_stack] - 1]
+ set last [expr [llength $tag_stack] - 2]
for { set i $last } { $i >= 0 } { incr i -1 } {
Index: openacs-4/packages/acs-templating/tcl/tag-init.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/tcl/tag-init.tcl,v
diff -u -r1.5.2.1 -r1.5.2.2
--- openacs-4/packages/acs-templating/tcl/tag-init.tcl 17 Feb 2003 00:11:02 -0000 1.5.2.1
+++ openacs-4/packages/acs-templating/tcl/tag-init.tcl 5 Mar 2003 14:57:37 -0000 1.5.2.2
@@ -179,21 +179,47 @@
# Scan the parameter stack backward, looking for the tag name
- set tag_id [template::enclosing_tag multiple]
+ set multiple_tag_id [template::enclosing_tag multiple]
- if { [string equal $tag_id {}] } {
+ if { [string equal $multiple_tag_id {}] } {
error "No enclosing MULTIPLE tag for GROUP tag on column $column"
- }
+ }
- set name [template::tag_attribute $tag_id name]
+ # Get the name of the multiple variable we're looping over
+ set name [template::tag_attribute $multiple_tag_id name]
- set i "__${tag_id}_i"
+ set tag_id [template::current_tag]
+
+ # If we're inside another group tag, we'll need to save and restore that tag's groupnum and groupnum_last_p values
+ # Find enclosing group tag, if one exists
+ set group_tag_id [template::enclosing_tag group]
+
+ # Save groupnum pseudocolumns from surrounding group tag
+ # We don't care about saving groupnum_last_p, since this doesn't work
+ # for group tags that have other group tags inside them, since we can't know
+ # if we're the last row until the inner group tag has eaten up all the
+ # rows between the start of this tag and the end.
+ if { ![empty_string_p $group_tag_id] } {
+ template::adp_append_code "
+ if { \[info exists ${name}(groupnum)\] } {
+ set __${tag_id}_${group_tag_id}_groupnum \$${name}(groupnum)
+ }
+ "
+ }
+
+ set i "__${multiple_tag_id}_i"
# while the value of name(column) stays the same
template::adp_append_code "
set __${tag_id}_group_rowcount 1
while { 1 } {
set ${name}(groupnum) \$__${tag_id}_group_rowcount
+ if { \$$i >= \${$name:rowcount} } {
+ set ${name}(groupnum_last_p) 1
+ } else {
+ upvar 0 ${name}:\[expr \$$i + 1\] $name:next
+ set ${name}(groupnum_last_p) \[expr !\[string equal \${${name}:next($column)} \$${name}($column)\]\]
+ }
"
template::adp_compile_chunk $chunk
@@ -213,6 +239,15 @@
incr __${tag_id}_group_rowcount
}
"
+
+ # Restore saved groupnum pseudocolumns
+ if { ![empty_string_p $group_tag_id] } {
+ template::adp_append_code "
+ if { \[info exists __${tag_id}_${group_tag_id}_groupnum\] } {
+ set ${name}(groupnum) \$__${tag_id}_${group_tag_id}_groupnum
+ }
+ "
+ }
}
# Repeat a template chunk consisting of a grid cell for each row of a
Index: openacs-4/packages/acs-templating/tcl/widget-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/tcl/widget-procs.tcl,v
diff -u -r1.14.2.2 -r1.14.2.3
--- openacs-4/packages/acs-templating/tcl/widget-procs.tcl 26 Feb 2003 21:34:28 -0000 1.14.2.2
+++ openacs-4/packages/acs-templating/tcl/widget-procs.tcl 5 Mar 2003 14:57:37 -0000 1.14.2.3
@@ -71,31 +71,58 @@
if { [info exists element(html)] } {
array set attributes $element(html)
}
-
array set attributes $tag_attributes
+
+ if { [info exists element(value)] } {
+ set value $element(value)
+ } else {
+ set value {}
+ }
- set output ""
+ return $output
+}
+ad_proc -public template::widget::textarea_internal {
+ name
+ attribute_reference
+ {value {}}
+ {mode edit}
+} {
+ upvar $attribute_reference attributes
+
+ if { ![string equal $mode "edit"] } {
+ set output {}
+ if { ![empty_string_p value] } {
+ append output "[ad_quotehtml $value]"
+ }
+ } else {
+ set output ""
+ }
+
return $output
}
+
+
ad_proc -public template::widget::inform { element_reference tag_attributes } {
A static information widget that does not submit any data
} {
@@ -124,22 +151,43 @@
set attributes(id) "$element(form_id):elements:$element(name):$element(value)"
}
- set output ""
+ # This is ugly, but it works: Only export the value when we're on a selected option
+ append output "\[ad_decode \$checked \"checked\" \"\" \"\"\]"
+ }
+ default {
+ if { [info exists element(value)] } {
+ append output [ad_quotehtml $element(value)]
+ append output ""
+ }
+ }
+ }
+ } else {
+ set output ""
}
- append output " />"
-
return $output
}
@@ -209,42 +257,65 @@
return [input button element $tag_attributes]
}
-ad_proc -public template::widget::menu { widget_name options_list values_list \
- attribute_reference } {
+ad_proc -public template::widget::menu {
+ widget_name
+ options_list
+ values_list
+ attribute_reference
+ {mode edit}
+} {
upvar $attribute_reference attributes
-
- set output ""
-
return $output
}
@@ -259,7 +330,7 @@
array set attributes $tag_attributes
return [template::widget::menu \
- $element(name) $element(options) $element(values) attributes]
+ $element(name) $element(options) $element(values) attributes $element(mode)]
}
ad_proc -public template::widget::multiselect { element_reference tag_attributes } {
@@ -285,7 +356,7 @@
}
return [template::widget::menu \
- $element(name) $element(options) $element(values) attributes]
+ $element(name) $element(options) $element(values) attributes $element(mode)]
}
ad_proc -public template::data::transform::search { element_ref } {
@@ -360,38 +431,6 @@
return [list $value]
}
-
-
-ad_proc -public template::widget::textarea { element_reference tag_attributes } {
-
- upvar $element_reference element
-
- if { [info exists element(html)] } {
- array set attributes $element(html)
- }
-
- array set attributes $tag_attributes
-
- set output ""
- return $output
-}
-
ad_proc -public template::widget::comment { element_reference tag_attributes } {
upvar $element_reference element
@@ -408,29 +447,18 @@
append output "$element(history)"
}
- if { [info exists element(header)] } {
- append output "
Index: openacs-4/packages/acs-templating/www/doc/tagref/group.html
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/acs-templating/www/doc/tagref/group.html,v
diff -u -r1.1.1.1 -r1.1.1.1.4.1
--- openacs-4/packages/acs-templating/www/doc/tagref/group.html 13 Mar 2001 22:59:27 -0000 1.1.1.1
+++ openacs-4/packages/acs-templating/www/doc/tagref/group.html 5 Mar 2003 14:58:08 -0000 1.1.1.1.4.1
@@ -19,6 +19,22 @@
It repeats a template section as long as the value of the column
does not change from row to row.
+
The group tag alsos sets two additional values in your
+multirow:
+
+
+
+
groupnum is the rownum within the innermost group tag,
+starting from 1, 2, 3, etc.
+
+
groupnum_last_p is a boolean saying whether this is
+ the last row inside the current group tag, before the value of
+ column changes. Note, however, that this only
+ works inside the inner-mostgroup if you have
+ multiple group tags nested within each other.
+
+
+
Usage
<table>
@@ -36,7 +52,13 @@
<!-- List colors for the same style in a single cell -->
<group column="style">
- @shirts.color@<br>
+ @shirts.color@
+
+ <!-- @shirts.groupnum@ will be the number of the color within the style -->
+
+ <if @shirts.groupnum_last_p@ false>, </if>
+ <else>, or </if>
+
</group>
<!-- End the row if the style is going to change on the next row