proc fc_decode
::xowiki::formfield::FormField proc fc_decode string {
return [string map [list __COMMA__ ,] $string]
}
proc fc_encode
::xowiki::formfield::FormField proc fc_encode string {
return [string map [list , __COMMA__] $string]
}
proc get_single_spec
::xowiki::formfield::FormField proc get_single_spec {-package_id -object string} {
if {[regexp [my set cond_regexp] $string _ condition true_spec false_spec]} {
if {[my interprete_condition -package_id $package_id -object $object $condition]} {
return [my get_single_spec -package_id $package_id -object $object $true_spec]
} else {
return [my get_single_spec -package_id $package_id -object $object $false_spec]
}
}
return $string
}
proc interprete_condition
::xowiki::formfield::FormField proc interprete_condition {-package_id -object cond} {
if {[::xo::cc info methods role=$cond] ne ""} {
if {$cond eq "creator"} {
set success [::xo::cc role=$cond -object $object -user_id [::xo::cc user_id] -package_id $package_id]
} else {
set success [::xo::cc role=$cond -user_id [::xo::cc user_id] -package_id $package_id]
}
} else {
set success 0
}
return $success
}
instproc answer_check=btwn
::xowiki::formfield::FormField instproc answer_check=btwn {} {
my instvar value
set arg1 [lindex [my correct_when] 1]
set arg2 [lindex [my correct_when] 2]
return [expr {$value >= $arg1 && $value <= $arg2}]
}
instproc answer_check=eq
::xowiki::formfield::FormField instproc answer_check=eq {} {
my instvar value
set arg1 [lindex [my correct_when] 1]
return [expr {$value eq $arg1}]
}
instproc answer_check=ge
::xowiki::formfield::FormField instproc answer_check=ge {} {
my instvar value
set arg1 [lindex [my correct_when] 1]
return [expr {$value >= $arg1}]
}
instproc answer_check=gt
::xowiki::formfield::FormField instproc answer_check=gt {} {
my instvar value
set arg1 [lindex [my correct_when] 1]
return [expr {$value > $arg1}]
}
instproc answer_check=in
::xowiki::formfield::FormField instproc answer_check=in {} {
my instvar value
set values [lrange [my correct_when] 1 end]
return [expr {[lsearch -exact $values $value] > -1}]
}
instproc answer_check=le
::xowiki::formfield::FormField instproc answer_check=le {} {
my instvar value
set arg1 [lindex [my correct_when] 1]
return [expr {$value <= $arg1}]
}
instproc answer_check=lt
::xowiki::formfield::FormField instproc answer_check=lt {} {
my instvar value
set arg1 [lindex [my correct_when] 1]
return [expr {$value < $arg1}]
}
instproc answer_check=match
::xowiki::formfield::FormField instproc answer_check=match {} {
return [string match [lindex [my correct_when] 1] [my value]]
}
instproc answer_is_correct
::xowiki::formfield::FormField instproc answer_is_correct {} {
if {[my exists correct_when]} {
set op [lindex [my correct_when] 0]
if {[my procsearch answer_check=$op] ne ""} {
set r [my answer_check=$op]
if {$r == 0} {return -1} {return 1}
} else {
error "invalid operator '$op'"
}
} elseif {![my exists answer]} {
return 0
} elseif {[my value] ne [my answer]} {
return -1
} else {
return 1
}
}
instproc asWidgetSpec
::xowiki::formfield::FormField instproc asWidgetSpec {} {
my instvar widget_type options label help_text format html display_html
set spec $widget_type
if {[my exists spell]} {append spec ",[expr {[my spell] ? {} : {no}}]spell"}
if {![my required]} {append spec ",optional"}
append spec " {label " [list $label] "} "
if {[my exists html]} {
append spec " {html {"
foreach {key value} [array get html] {
append spec $key " " [list $value] " "
}
append spec "}} "
}
if {[my exists options]} {
append spec " {options " [list $options] "} "
}
if {[my exists format]} {
append spec " {format " [list $format] "} "
}
if {$help_text ne ""} {
if {[string match "#*#" $help_text]} {
set internationalized [_ [string trim $help_text #]]
append spec " {help_text {$internationalized}}"
} else {
append spec " {help_text {$help_text}}"
}
}
return $spec
}
instproc behavior
::xowiki::formfield::FormField instproc behavior mixin {
#
# Specify the behavior of a form field via
# per object mixins
#
set obj [my object]
set pkgctx [[$obj package_id] context]
if {[$pkgctx exists embedded_context]} {
set ctx [$pkgctx set embedded_context]
set classname ${ctx}::$mixin
#my msg ctx=$ctx-viewer=$mixin,found=[my isclass $classname]
# TODO: search different places for the mixin. Special namespace?
if {[my isclass $classname]} {
if {[my exists per_object_behavior]} {
my mixin delete [my set per_object_behavior]
}
my mixin add $classname
my set per_object_behavior $classname
} else {
my msg "Could not find mixin '$mixin'"
}
}
}
instproc config_from_spec
::xowiki::formfield::FormField instproc config_from_spec spec {
#my log "spec=$spec [my info class] [[my info class] exists abstract]"
my instvar type
if {[[my info class] exists abstract]} {
# had earlier here: [my info class] eq [self class]
# Check, wether the actual class is a concrete class (mapped to
# concrete field type) or an abstact class. Since
# config_from_spec can be called multiple times, we want to do
# the reclassing only once.
if {[my isclass ::xowiki::formfield::$type]} {
my class ::xowiki::formfield::$type
} else {
my class ::xowiki::formfield::text
}
# TODO: reset_parameter? needed?
::xotcl::Class::Parameter searchDefaults [self]; # TODO: will be different in xotcl 1.6.*
}
regsub -all {,\s+} $spec , spec
foreach s [split $spec ,] {
my interprete_single_spec [FormField fc_decode $s]
}
#my msg "[my name]: after specs"
my set __state after_specs
my initialize
#
# It is possible, that a default value of a form field is changed through a spec.
# Since only the configuration might set values, checking value for "" seems safe here.
#
if {[my value] eq "" && [my exists default] && [my default] ne ""} {
#my msg "+++ reset value to [my default]"
my value [my default]
}
if {[lang::util::translator_mode_p]} {
my mixin "::xo::TRN-Mode"
}
}
instproc convert_to_external
::xowiki::formfield::FormField instproc convert_to_external value {
# to be overloaded
return $value
}
instproc convert_to_internal
::xowiki::formfield::FormField instproc convert_to_internal {} {
# to be overloaded
}
instproc field_value
::xowiki::formfield::FormField instproc field_value v {
if {[my exists show_raw_value]} {
return $v
} else {
return [my pretty_value]
}
}
instproc has_instance_variable
::xowiki::formfield::FormField instproc has_instance_variable {var value} {
if {[my exists $var] && [my set $var] eq $value} {return 1}
return 0
}
instproc init
::xowiki::formfield::FormField instproc init {} {
if {![my exists label]} {my label [string totitle [my name]]}
if {![my exists id]} {my id [my name]}
if {[my exists id]} {my set html(id) [my id]}
#if {[my exists default]} {my set value [my default]}
my config_from_spec [my spec]
}
instproc interprete_single_spec
::xowiki::formfield::FormField instproc interprete_single_spec s {
if {$s eq ""} return
set object [my object]
set package_id [$object package_id]
set s [::xowiki::formfield::FormField get_single_spec -object $object -package_id $package_id $s]
switch -glob -- $s {
optional {my set required false}
required {my set required true; my remove_omit}
omit {my mixin add ::xowiki::formfield::omit}
noomit {my remove_omit}
disabled {my set_disabled true}
enabled {my set_disabled false}
label=* {my label [lindex [split $s =] 1]}
help_text=* {my help_text [lindex [split $s =] 1]}
*=* {
set p [string first = $s]
set attribute [string range $s 0 [expr {$p-1}]]
set value [string range $s [expr {$p+1}] end]
set definition_class [lindex [my procsearch $attribute] 0]
if {[string match "::xotcl::*" $definition_class] || $definition_class eq ""} {
error [_ xowiki.error-form_constraint-unknown_attribute [list name [my name] entry $attribute]]
}
if {[catch {
#
# We want to allow a programmer to use e.g. options=[xowiki::locales]
#
# Note: do not allow users to use [] via forms, since they might
# execute arbitrary commands. The validator for the form fields
# makes sure, that the input specs are free from square brackets.
#
if {[string match {\[*\]} $value]} {
set value [subst $value]
}
my $attribute $value
} errMsg]} {
error "Error during setting attribute '$attribute' to value '$value': $errMsg"
}
}
default {
# Check, if the spec value $s is a class.
set old_class [my info class]
# Don't allow to use namespaced values, since we would run
# into a recursive loop for richtext::wym (could be altered there as well).
if {[my isclass ::xowiki::formfield::$s] && ![string match "*:*" $s]} {
my class ::xowiki::formfield::$s
my remove_omit
if {$old_class ne [my info class]} {
#my msg "[my name]: reset class from $old_class to [my info class]"
my reset_parameter
my set __state reset
my initialize
}
#my msg "[my name] [self] [my info class] before searchDefaults, validator='[my validator]'"
#::xotcl::Class::Parameter searchDefaults [self]; # TODO: will be different in xotcl 1.6.*
#my msg "[my name] [self] [my info class] after searchDefaults, validator='[my validator]'"
} else {
if {$s ne ""} {
error [_ xowiki.error-form_constraint-unknown_spec_entry [list name [my name] entry $s x "Unknown spec entry for entry '$s'"]]
}
}
}
}
}
instproc localize
::xowiki::formfield::FormField instproc localize v {
# We localize in pretty_value the message keys in the
# language of the item (not the connection item).
if {[regexp "^#(.*)#$" $v _ key]} {
return [lang::message::lookup [my locale] $key]
}
return $v
}
instproc pretty_image
::xowiki::formfield::FormField instproc pretty_image {-parent_id entry_name} {
if {$entry_name eq ""} return
my instvar object
set l [::xowiki::Link new -destroy_on_cleanup -name $entry_name -page $object -type image -label [my label] -parent_id $parent_id]
foreach option {
href cssclass
float width height
padding padding-right padding-left padding-top padding-bottom
margin margin-left margin-right margin-top margin-bottom
border border-width position top botton left right
} {
if {[my exists $option]} {$l set $option [my set $option]}
}
set html [$l render]
return $html
}
instproc pretty_value
::xowiki::formfield::FormField instproc pretty_value v {
#my log "mapping $v"
return [string map [list & "&" < "<" > ">" \" """ ' "'" @ "@"] $v]
}
instproc remove_omit
::xowiki::formfield::FormField instproc remove_omit {} {
set m ::xowiki::formfield::omit
if {[my ismixin $m]} {my mixin delete $m}
}
instproc render
::xowiki::formfield::FormField instproc render {} {
# In case, we use an asHTML of a FormField, we use this
# render definition
if {[my inline]} {
# with label, error message, help text
my render_form_widget
} else {
# without label, error message, help text
my render_item
}
my set __rendered 1
}
instproc render_error_msg
::xowiki::formfield::FormField instproc render_error_msg {} {
if {[my error_msg] ne ""} {
::html::div -class form-error {
my instvar label
::html::t [::xo::localize [my error_msg]]
my render_localizer
my set error_reported 1
}
}
}
instproc render_form_widget
::xowiki::formfield::FormField instproc render_form_widget {} {
# This method provides the form-widget wrapper
set class form-widget
if {[my exists form-widget-CSSclass]} {append class " [my form-widget-CSSclass]"}
::html::div -class $class { my render_input }
}
instproc render_help_text
::xowiki::formfield::FormField instproc render_help_text {} {
set text [my help_text]
if {$text ne ""} {
html::div -class form-help-text {
html::img -src "/shared/images/info.gif" -alt {[i]} -title {Help text} -width "12" -height 9 -border 0 -style "margin-right: 5px" {}
html::t $text
}
}
}
instproc render_input
::xowiki::formfield::FormField instproc render_input {} {
# This is the most general widget content renderer.
# If no special renderer is defined, we fall back to this one,
# which is in most cases a simple input fied of type string.
::html::input [my get_attributes type size maxlength id name value disabled {CSSclass class}] {}
my set __rendered 1
}
instproc render_item
::xowiki::formfield::FormField instproc render_item {} {
::html::div -class form-item-wrapper {
::html::div -class form-label {
::html::label -for [my id] {
::html::t [my label]
}
if {[my required]} {
::html::div -class form-required-mark {
::html::t " (obligatorio)"
}
}
}
my render_form_widget
my render_help_text
my render_error_msg
html::t \n
}
}
instproc render_localizer
::xowiki::formfield::FormField instproc render_localizer {} {
# Just an empty fall-back method.
# This method will be overloaded in trn mode by a mixin.
}
instproc reset_parameter
::xowiki::formfield::FormField instproc reset_parameter {} {
# reset application specific parameters (defined below ::xowiki::formfield::FormField)
# such that searchDefaults will pick up the new defaults, when a form field
# is reclassed.
if {[my exists per_object_behavior]} {
# remove per-object mixin from the "behavior"
my mixin delete [my set per_object_behavior]
my unset per_object_behavior
}
#my msg "reset along [my info precedence]"
foreach c [my info precedence] {
if {$c eq "::xowiki::formfield::FormField"} break
foreach s [$c info slots] {
if {![$s exists default]} continue
set var [$s name]
set key processed($var)
if {[info exists $key]} continue
my set $var [$s default]
set $key 1
}
}
if {[my exists disabled]} {
my set_disabled 0
}
}
instproc set_disabled
::xowiki::formfield::FormField instproc set_disabled disable {
#my msg "[my name] set disabled $disable"
if {$disable} {
my set disabled true
} else {
my unset -nocomplain disabled
}
}
instproc validate
::xowiki::formfield::FormField instproc validate obj {
my instvar name required
# use the 'value' method to deal e.g. with compound fields
set value [my value]
if {$required && $value eq "" && ![my istype ::xowiki::formfield::hidden]} {
my instvar label
return [_ acs-templating.Element_is_required]
}
#
#my msg "++ [my name] [my info class] validator=[my validator] ([llength [my validator]]) value=$value"
foreach validator [my validator] {
set errorMsg ""
#
# The validator might set the variable errorMsg in this scope.
#
set success 1
set validator_method check=$validator
set proc_info [my procsearch $validator_method]
#my msg "++ [my name]: field-level validator exists '$validator_method' ? [expr {$proc_info ne {}}]"
if {$proc_info ne ""} {
# we have a slot checker, call it
#my msg "++ call-field level validator $validator_method '$value'"
set success [my $validator_method $value]
}
if {$success == 1} {
# the previous check was ok, check now for a validator on the
# object level
set validator_method validate=$validator
set proc_info [$obj procsearch $validator_method]
#my msg "++ [my name]: page-level validator exists ? [expr {$proc_info ne {}}]"
if {$proc_info ne ""} {
set success [$obj $validator_method $value]
#my msg "++ call page-level validator $validator_method '$value' returns $success"
}
}
if {$success == 0} {
#
# We have an error message. Get the class name from procsearch and construct
# a message key based on the class and the name of the validator.
#
set cl [namespace tail [lindex $proc_info 0]]
return [_ xowiki.$cl-validate_$validator [list value $value errorMsg $errorMsg]]
#return [::lang::message::lookup "" xowiki.$cl-validate_$validator %errorMsg% [list value $value errorMsg $errorMsg] 1]
}
}
return ""
}
instproc value_if_nothing_is_returned_from_from
::xowiki::formfield::FormField instproc value_if_nothing_is_returned_from_from default {
return $default
}