Index: openacs-4/packages/xowiki/xowiki.info
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/xowiki.info,v
diff -u -r1.180.2.77 -r1.180.2.78
--- openacs-4/packages/xowiki/xowiki.info 25 Dec 2021 16:10:20 -0000 1.180.2.77
+++ openacs-4/packages/xowiki/xowiki.info 2 Jan 2022 16:25:10 -0000 1.180.2.78
@@ -10,7 +10,7 @@
t
xowiki
-
+
Gustaf Neumann
A xotcl-based enterprise wiki system with multiple object types
2021-09-15
@@ -55,7 +55,7 @@
BSD-Style
2
-
+
Index: openacs-4/packages/xowiki/tcl/form-field-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/tcl/form-field-procs.tcl,v
diff -u -r1.284.2.182 -r1.284.2.183
--- openacs-4/packages/xowiki/tcl/form-field-procs.tcl 25 Dec 2021 16:10:21 -0000 1.284.2.182
+++ openacs-4/packages/xowiki/tcl/form-field-procs.tcl 2 Jan 2022 16:25:10 -0000 1.284.2.183
@@ -1,4 +1,4 @@
-::xo::library doc {
+xo::library doc {
XoWiki - form fields
@creation-date 2007-06-22
@@ -32,7 +32,115 @@
return $result
}
+ ad_proc dict_to_fc {
+ -name
+ -type
+ dict
+ } {
+ Convert the provided dict into form_constraint syntax (comma
+ separated). The other direction would be more complex, since the
+ fcs are interpreted from left to right, overwriting potentially
+ previous values. The fc-interpretation creates already the form
+ fields, produces intended errors, when certain attributes are not
+ allowed, etc.
+
+ @param name optional form-field name
+ @param type type of the form-field; if not specified,
+ take it from key "_type" of the dict
+ @param dict dict to be converted.
+ } {
+ if {![info exists type]} {
+ set type [dict get $dict _type]
+ dict unset dict _type
+ }
+ set list $type
+ foreach {key value} $dict {
+ lappend list $key=[::xowiki::formfield::FormField fc_encode $value]
+ }
+ if {[info exists name]} {
+ return $name:[info exists name]
+ } else {
+ return [join $list ,]
+ }
+ }
+
+ ad_proc dict_to_spec {{-aspair:boolean false} -name dict} {
+
+ Convert the provided dict into a form-field spec together with the
+ form-field name. When "-aspair" is specified the spec is returned
+ in the list format as used by "create_components". If "-name" is
+ not specified, the name has to be provided via dict member
+ "_name", otherwise an exception is triggered.
+
+ } {
+ if {$dict ne ""} {
+ if {![info exists name]} {
+ set name [dict get $dict _name]
+ dict unset dict _name
+ }
+ if {$aspair_p} {
+ return [list $name [dict_to_fc $dict]]
+ } else {
+ return "$name:[dict_to_fc $dict]"
+ }
+ }
+ }
+
+ ad_proc -private spec_to_dict {-name:required spec} {
+ Convert a single spec to a Tcl dict structure
+ } {
+ dict set result _name $name
+ set elements [split $spec ,]
+ dict set result _type [lindex $elements 0]
+ foreach s [lrange $elements 1 end] {
+ switch -glob -- $s {
+ *=* {
+ set p [string first = $s]
+ set attribute [string range $s 0 $p-1]
+ set value [::xowiki::formfield::FormField fc_decode [string range $s $p+1 end]]
+ dict set result $attribute $value
+ }
+ default {
+ ns_log notice "... spec_to_dict ignores <$s>"
+ }
+ }
+ }
+ return $result
+ }
+
+ ad_proc fc_to_dict {form_constraints} {
+
+ Convert from form_constraint syntax to a dict. This is just a
+ partial implementation to be probably extended in the future. it
+ expects that the type is the first element and ignores everything
+ not in the synteax "*=*", or skips "@*" fields. Don't expect this
+ to be fully reversible.
+
+ } {
+ set result ""
+ foreach fc $form_constraints {
+ #ns_log notice "... fc_to_dict works on <$fc>"
+ if {[regexp {^([^:]+):(.*)$} $fc _ field_name definition]} {
+ if {[string match @* $field_name]} continue
+ dict set result $field_name [spec_to_dict -name $field_name $definition]
+ dict set result $field_name _definition $definition
+ }
+ }
+ return $result
+ }
+
+
+ ad_proc dict_value {dict key {default ""}} {
+
+ Return the dict value of the specified "key" when this member
+ exists. Otherwise return the default.
+
+ } {
+ expr {[dict exists $dict $key] ? [dict get $dict $key] : $default}
+ }
+
+
###########################################################
#
# ::xowiki::formfield::FormField (Base Class)
@@ -150,6 +258,12 @@
return ""
}
+ #
+ # Convenience functions forwarding to procs
+ #
+ FormField instforward dict_to_spec ::xowiki::formfield::dict_to_spec
+ FormField instforward dict_to_fc ::xowiki::formfield::dict_to_fc
+ FormField instforward dict_value ::xowiki::formfield::dict_value
#FormField instproc destroy {} {
# :log "=== FormField DESTROY ====="
@@ -169,8 +283,9 @@
}
#
- # Basic initialize method, doing nothing; should be subclassed by the
- # application classes
+ # Basic initialize method, doing essentially nothing; should be
+ # subclassed by the application classes.
+ #
FormField instproc initialize {} {next}
@@ -508,8 +623,10 @@
}
FormField instproc render {} {
+ #
# In case, we use an asHTML of a FormField, we use this
- # render definition
+ # render definition.
+ #
if {${:inline}} {
# with label, error message, help text
:render_form_widget
@@ -697,37 +814,6 @@
return [list [self]]
}
-
- FormField ad_instproc dict_to_fc {
- -name
- -type
- dict
- } {
-
- Convert the provided dict into form_constraint syntax (comma
- separated). The other direction would be more complex, since the
- fcs are interpreted from left to right, overwriting potentially
- previous values. The fc-interpretation creates already the form
- fields, produces intended errors, when certain attributes are not
- allowed, etc.
-
- @param name optional form-field name
- @param type type of the form-field; if not specified,
- take it from key "_type" of the dict
- @param dict dict to be converted.
- } {
- set result [expr {[info exists name] ? "$name:" : ""}]
- if {![info exists type]} {
- set type [dict get $dict _type]
- dict unset dict _type
- }
- set list $type
- foreach {key value} $dict {
- lappend list $key=[::xowiki::formfield::FormField fc_encode $value]
- }
- return $result[join $list ,]
- }
-
FormField instproc value_if_nothing_is_returned_from_form {default} {
return $default
}
@@ -2664,6 +2750,8 @@
Class create number -superclass FormField -parameter {
min max step value
+ {js_validate false}
+ {js_invalid_msg ""}
{td_CSSclass right}
}
number instproc initialize {} {
@@ -2676,6 +2764,17 @@
::html::input [:get_attributes type id name value {CSSclass class} \
min max step autocomplete placeholder {*}$boolean_atts] {}
:resetBooleanAttributes $boolean_atts
+ if {${:js_validate}} {
+ set invalid_msg ${:js_invalid_msg}
+ template::add_event_listener -event input -id ${:id} -script [subst {
+ const inputField = event.target;
+ if (!inputField.checkValidity()) {
+ if ('$invalid_msg' != "") {
+ inputField.setCustomValidity('$invalid_msg');
+ }
+ }
+ }]
+ }
}
###########################################################
@@ -4038,7 +4137,7 @@
#
###########################################################
- # abstract superclass for select and radio
+ # abstract superclass for "select" and "radio"
Class create ShuffleField -superclass FormField -parameter {
{options ""}
{render_hints ""}
@@ -4750,8 +4849,11 @@
lappend fields [list $rep [:dict_to_fc -type $type $field_fc_dict]]
}
- #:log "text_fields fields\n[join $fields \n]>"
:create_components $fields
+
+ #foreach c [:components] {
+ # :log "... $c [$c name] [$c info class]"
+ #}
}
text_fields instproc set_feedback {feedback_mode} {
Index: openacs-4/packages/xowiki/tcl/test/api-test-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowiki/tcl/test/api-test-procs.tcl,v
diff -u -r1.1.2.13 -r1.1.2.14
--- openacs-4/packages/xowiki/tcl/test/api-test-procs.tcl 31 Dec 2021 11:22:34 -0000 1.1.2.13
+++ openacs-4/packages/xowiki/tcl/test/api-test-procs.tcl 2 Jan 2022 16:25:11 -0000 1.1.2.14
@@ -122,6 +122,82 @@
[::xowiki::hstore::dict_as_hkey $dict] \
{key1=>value1,key2=>"a''b","k''y"=>value3,key4=>"1,2",c=>"before after",d=>"hello world"}
}
+
+aa_register_case \
+ -cats {api smoke production_safe} \
+ -procs {
+ "::xowiki::formfield::dict_to_spec"
+ "::xowiki::formfield::dict_value"
+ "::xowiki::formfield::fc_to_dict"
+
+ "::xowiki::formfield::dict_to_fc"
+ "::xowiki::formfield::FormField proc fc_encode"
+ "::xowiki::formfield::FormField proc fc_decode"
+ } \
+ dict_to_xx {
+
+ Checks conversion from dict to specs and form constraints.
+ dict_to_spec is based on dict_to_fc.
+
+ } {
+ set dict {_name myname _type text label "Hello, world!" enabled 1}
+
+ aa_equals "convert to spec" \
+ [::xowiki::formfield::dict_to_spec $dict] \
+ {myname:text,label=Hello__COMMA__ world!,enabled=1}
+ aa_equals "convert to spec -aspair" \
+ [::xowiki::formfield::dict_to_spec -aspair $dict] \
+ {myname {text,label=Hello__COMMA__ world!,enabled=1}}
+
+ #
+ # Common idiom constructing form constraints
+ #
+ set fc ""; lappend fc \
+ @categories:off @cr_fields:hidden \
+ [::xowiki::formfield::dict_to_spec $dict]
+
+ aa_equals "lappend + dict_to_spec fc idiom" \
+ [concat $fc] \
+ {@categories:off @cr_fields:hidden {myname:text,label=Hello__COMMA__ world!,enabled=1}}
+
+ #
+ # Common idiom to create component structure
+ #
+
+ set struct [subst {
+ [list [::xowiki::formfield::dict_to_spec -aspair $dict]]
+ {pattern {text,default=*,label=#xowf.pool_question_pattern#}}
+ }]
+ aa_equals "lappend + dict_to_spec component structure idiom" \
+ [concat $struct] \
+ {{myname {text,label=Hello__COMMA__ world!,enabled=1}}
+ {pattern {text,default=*,label=#xowf.pool_question_pattern#}}}
+
+ #
+ # fc_to_dct
+ #
+ set fc ""; lappend fc \
+ @categories:off @cr_fields:hidden \
+ [::xowiki::formfield::dict_to_spec $dict]
+
+ aa_equals "fc_to_dict (show results of reverse operation)" \
+ [::xowiki::formfield::fc_to_dict $fc] \
+ {myname {_name myname _type text label {Hello, world!} enabled 1 _definition {text,label=Hello__COMMA__ world!,enabled=1}}}
+
+ #
+ # dict_value
+ #
+ aa_equals "dict_value exists" \
+ [::xowiki::formfield::dict_value $dict label] \
+ {Hello, world!}
+ aa_equals "dict_value not exists, no default" \
+ [::xowiki::formfield::dict_value $dict title] \
+ {}
+ aa_equals "dict_value not exists, default" \
+ [::xowiki::formfield::dict_value $dict title xxx] \
+ {xxx}
+ }
+
#
# Local variables:
# mode: tcl