Class ::xowiki::formfield::FormField (public)
::xotcl::Class ::xowiki::formfield::FormField\ [ -language_specific language_specific ]
Defined in /var/www/openacs/packages/xowiki/tcl/form-field-procs.tcl
Base FormField class. FormFields are objects, which can be outputted as well in ad_forms or asHTML included in wiki pages. FormFields support: - validation - help_text - error messages - internationalized pretty_values and inherit properties of the original datatypes via slots (e.g. for boolean entries). FormFields can be subclassed to ensure tailor-ability and high reuse. todo: at some later time, this could go into xotcl-core.
- Switches:
- -language_specific (optional)
- this parameter decides that the value collected by this formfield should be transparently stored as a message key. The translation language is that of the current package, determined by 'use_connection_locale' package parameter, connection locale and system settings.
- Testcases:
- No testcase defined.
Source code: namespace eval ::xowiki::formfield {} ::nsf::object::alloc ::xotcl::Class ::xowiki::formfield::FormField {set :__default_metaclass ::xotcl::Class set :__default_superclass ::xotcl::Object set :abstract 1 set :cond_regexp {^([^=?]+)[?]([^:]*)[:](.*)$}} ::xowiki::formfield::FormField proc fc_decode string { return [string map [list __COMMA__ ,] $string] } ::xowiki::formfield::FormField proc interprete_condition {-package_id -object: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 [$object evaluate_form_field_condition $cond] } return $success } ::xowiki::formfield::FormField proc fc_encode string { return [string map [list , __COMMA__] $string] } ::xowiki::formfield::FormField proc get_from_name {object:object name} { # # Get a form field via name. The provided names are unique for a # form. If multiple forms should be rendered simultaneously, we # have to extend the addressing mechanism. # # todo: we could speed this up by an index if needed foreach f [::xowiki::formfield::FormField info instances -closure] { if {[$f name] eq $name} { if {![$f exists object]} { #ad_log warning "strange, $f [$f name] was created without object but fits name" return $f } elseif {$object eq [$f object]} { return $f } } } #:msg not-found-$object-$name return "" } ::xowiki::formfield::FormField proc get_single_spec {-package_id -object:object string} { if {[regexp ${:cond_regexp} $string _ condition true_spec false_spec]} { if {[:interprete_condition -package_id $package_id -object $object $condition]} { return [:get_single_spec -package_id $package_id -object $object $true_spec] } else { return [:get_single_spec -package_id $package_id -object $object $false_spec] } } return $string } ::xowiki::formfield::FormField instproc answer_check=answer_words {} { # # Correct, when the answer is equal to the provided (sequence of) # words, but white-space is ignored. When the first word is # "*lower*" then the provided answer of the student is converted # to lowercase before the comparison is performed; as a # consequence the comparison is not case sensitive. Note that the # answer_words have to be provided in lowercase as well. # set d [:process_correct_when_modifier] dict with d { return [expr {$value eq $words}] } } ::xowiki::formfield::FormField instproc render_error_msg {} { #ns_log notice "render_error_msg: field ${:name} has errorMsg (reported [info exists :error_reported]) '${:error_msg}'" if {${:error_msg} ne "" && ![info exists :error_reported]} { ::html::div -class form-error { set label ${:label} ;# needed for error_msg; TODO: we should provide a substitution_list similar to "_" ::html::t [::xo::localize ${:error_msg}] :render_localizer set :error_reported 1 } } } ::xowiki::formfield::FormField instproc convert_to_internal {} { # To be overloaded. } ::xowiki::formfield::FormField instproc answer_check=contains-not {} { # # Correct, when answer does not contain any of the provided # words. Just a negation of "contains". # return [expr {[:answer_check=contains] ? 0 : 1}] } ::xowiki::formfield::FormField instproc escape_message_keys value { # # Can be overloaded, when e.g. no escaping of message keys or # other representations of message keys are desired. # return [xo::escape_message_keys $value] } ::xowiki::formfield::FormField instproc repeat range { if {[info exists :__initialized_repeat]} return set oldClass [:info class] :class ::xowiki::formfield::repeatContainer if {$oldClass ne [:info class]} { :reset_parameter set :__state reset } if {$range ne ""} { if {[regexp {^(\d*)[.][.](\d*)$} $range _ low high]} { if {$low ne ""} {set :min $low} if {$high ne ""} {set :max $high} if {${:min} > ${:max}} { error "invalid range '$range' specified (lower limit ${:min} must not be larger than higher limit ${:max})" } if {${:min} < 0 || ${:max} < 1} { error "invalid range '$range' specified (max ${:max} must be at least 1) " } } else { error "invalid range '$range' specified (must be of form 'min..max')" } } :initialize } ::xowiki::formfield::FormField instproc answer_check=le {} { set d [:process_correct_when_modifier] dict with d { return [expr {$value ne "" && $value <= [lindex $words 0]}] } } ::xowiki::formfield::FormField instproc convert_to_external value { # To be overloaded. return $value } ::xowiki::formfield::FormField instproc render_word_statistics {} { #ns_log notice ":render_word_statistics: ${:word_statistics_option}" if {${:word_statistics_option} eq "word_cloud"} { # stopword list based on lucene, added a few more terms set stopWords { a about an and are as at be but by do does for from how if in into is it no not of on or such that the their then there these they this to vs was what when where who will with } set jsWords {} foreach {word freq} [lsort -decreasing -integer -stride 2 -index 1 ${:word_statistics}] { if {$word in $stopWords} continue lappend jsWords [subst {{text: "$word", weight: $freq}}] } set tsp [clock clicks -microseconds] set height [expr {(12*[llength $jsWords]/10) + 250}] # set js [subst { # var jqcloud_$tsp = \[ # [join $jsWords ",\n"] # \]; # \$('#jqcloud_$tsp').jQCloud(jqcloud_$tsp, {autoResize: true, width: 500, steps: 5, height: $height}); # }] set js [subst { var jqcloud_$tsp = \[ [join $jsWords ",\n"] \]; \$('#jqcloud_$tsp').jQCloud(jqcloud_$tsp, {autoResize: true, width: 500, height: $height}); }] template::add_script -order 20 -src https://cdn.jsdelivr.net/npm/jqcloud2@2.0.3/dist/jqcloud.min.js template::head::add_css -href https://cdn.jsdelivr.net/npm/jqcloud2@2.0.3/dist/jqcloud.min.css security::csp::require script-src https://cdn.jsdelivr.net security::csp::require style-src https://cdn.jsdelivr.net template::add_body_script -script $js ::html::div -class "jq-cloud" -id jqcloud_$tsp {} } else { ::html::ul { foreach {word freq} [lsort -decreasing -integer -stride 2 -index 1 ${:word_statistics}] { html::li { html::t "$freq: $word" } lappend jsWords [subst {{text: "$word", weight: $freq}}] } } } } ::xowiki::formfield::FormField instproc repeat_add_label label { if {[info exists :__initialized_repeat]} return set :repeat_add_label $label } ::xowiki::formfield::FormField instproc render_answer_statistics {} { #ns_log notice ":answer_statistics: ${:answer_statistics}" ::html::ul { foreach {answer freq} [lsort -decreasing -integer -stride 2 -index 1 ${:answer_statistics}] { html::li { html::t "$freq: $answer" } } } } ::xowiki::formfield::FormField instproc set_is_repeat_template is_template { # :msg "${:name} set is_repeat_template $is_template" if {$is_template} { set :is_repeat_template true } else { unset :is_repeat_template } } ::xowiki::formfield::FormField instproc resetBooleanAttributes atts { # # Unset the temporary boolean attributes which were set by method # "booleanAttributes". # foreach att $atts { lassign $att var value if {[info exists :$var]} {unset :$var} } } ::xowiki::formfield::FormField instproc CSSclass_list_add {attrName value} { # # Convenience function to add a CSS class to the existing values # in "attrName". The function is named somewhat similar to the # JavaScript function "classList.add" # if {$value ne ""} { if {[info exists :$attrName]} { append :$attrName " " $value } else { set :$attrName $value } } } ::xowiki::formfield::FormField instproc config_from_spec spec { #:log "config_from_spec ${:name} spec <$spec> [:info class] [[:info class] exists abstract]" if {[[:info class] exists abstract]} { # had earlier here: [:info class] eq [self class] # Check, whether the actual class is a concrete class (mapped to # concrete field type) or an abstract class. Since # config_from_spec can be called multiple times, we want to do # the reclassing only once. if {[:isclass ::xowiki::formfield::${:type}]} { :class ::xowiki::formfield::${:type} } else { :class ::xowiki::formfield::text } # set missing instance vars with defaults :set_instance_vars_defaults } regsub -all -- {,\s+} $spec , spec foreach s [split $spec ,] { :interprete_single_spec [FormField fc_decode $s] } #:msg "${:name}: after specs" set :__state after_specs #:log "INITIALIZE ${:name} due to config_from_spec" :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 {[:value] eq "" && [info exists :default] && ${:default} ne ""} { #:msg "+++ reset value to [:default]" :value ${:default} } if {[lang::util::translator_mode_p]} { :mixin add "::xo::TRN-Mode" } } ::xowiki::formfield::FormField instproc pretty_value v { #:log "mapping $v" return [string map [list & "&" < "<" > ">" \" """ ' "'" @ "@"] $v] } ::xowiki::formfield::FormField instproc render_collapsed {-id:required {-label ""} -inner_method} { ::xowiki::BootstrapCollapseButton new -id $id -label $label -toggle "collapse" -direction "down" ::html::div -id "$id" -class "collapse" { :$inner_method } } ::xowiki::formfield::FormField instproc render_item {} { ::html::div [:get_attributes {form_item_wrapper_CSSclass class}] { if {[:error_msg] ne ""} { set CSSclass form-label-error } else { set CSSclass form-label } if {[::template::CSS toolkit] eq "bootstrap5"} { ::html::label -class "${:form_label_CSSclass} [lindex [split ${:name} .] end]" -for ${:id} { ::html::t ${:label} } if {${:required} && ${:mode} eq "edit"} { ::html::div -class form-required-mark { ::html::t " (#acs-templating.required#)" } } } else { ::html::div -class $CSSclass { ::html::label -class "${:form_label_CSSclass} [lindex [split ${:name} .] end]" -for ${:id} { ::html::t ${:label} } if {${:required} && ${:mode} eq "edit"} { ::html::div -class form-required-mark { ::html::t " (#acs-templating.required#)" } } } } :render_form_widget :render_help_text :render_error_msg html::t \n } } ::xowiki::formfield::FormField instproc make_correct {} { # # Set the form_field to a correct value, currently based on # :correct_when. We could use here :answer when available. # Modified instance variables # # - :help_text is cleared to avoid stray per-user-feedback, # We could as well provide teacher-level feedback here. # - :form_widget_CSSclass is altered to "correct" or "unknown". # #ns_log notice "FormField make_correct ${:name}: [info exists :answer] [info exists :correct_when]" set :form_widget_CSSclass unknown if {[info exists :correct_when]} { # # Try to get a correct value from the correct_when spec # set predicate [lindex ${:correct_when} 0] set args [lrange ${:correct_when} 1 end] switch $predicate { "match" {set correct $args} "eq" {set correct $args} "gt" {set correct "> $args"} "ge" {set correct ">= $args"} "lt" {set correct "< $args"} "le" {set correct "<= $args"} "contains" {set correct "... [join $args { ... }] ..."} "answer_words" {set correct "... [join $args { ... }] ..."} "in" {set correct "... [join args { OR }] ..."} "btwn" {set correct "[lindex $args 0] <= X <= [lindex $args 1]"} } if {[info exists correct]} { :value $correct set :form_widget_CSSclass correct #ns_log notice "FormField make_correct ${:name}: value '${:value}'" } else { ns_log notice "FormField make_correct ${:name}: not handled: correct_when '${:correct_when}' " } } else { ns_log notice "FormField make_correct ${:name}: not handled: answer? [info exists :answer]" } set :help_text "" ;# we could provide a teacher-level feedback here. } ::xowiki::formfield::FormField instproc answer_check=eq {} { set d [:process_correct_when_modifier] dict with d { return [expr {$value eq [lindex $words 0]}] } } ::xowiki::formfield::FormField instproc answer_check=contains {} { # # Correct, when answer contains any of the provided words. # set d [:process_correct_when_modifier] foreach word [dict get $d words] { if {[string match *$word* [dict get $d value]]} { return 1 } } return 0 } ::xowiki::formfield::FormField instproc pretty_image {-parent_id:required {-revision_id ""} entry_name} { if {$entry_name eq "" || ${:value} eq ""} return set item_ref [${:object} item_ref -default_lang [${:object} lang] -parent_id $parent_id $entry_name] set label ${:label} ;# the label is used for alt and title if {$label eq [dict get $item_ref stripped_name]} { # # The label is apparently the default. For Photo.form instances, # this is always "image". In such cases, use the title of the # parent object as label. # set label [${:object} title] } set l [::xowiki::Link create new -page ${:object} -type "image" -lang [dict get $item_ref prefix] -stripped_name [dict get $item_ref stripped_name] -label $label -parent_id [dict get $item_ref parent_id] -item_id [dict get $item_ref item_id] -destroy_on_cleanup] if {[:istype file]} { if {$revision_id ne ""} { $l revision_id $revision_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 bottom left right geometry } { if {[info exists :$option]} {$l set $option [set :$option]} } set html [$l render] return $html } ::xowiki::formfield::FormField instproc answer_check=lt {} { set d [:process_correct_when_modifier] dict with d { return [expr {$value ne "" && $value < [lindex $words 0]}] } } ::xowiki::formfield::FormField instproc validate obj:object { # use the 'value' method to deal e.g. with compound fields set value [:value] #:msg "[:info class] value=$value req=${:required} // ${:value} //" if {${:required} && $value eq "" && ![:istype ::xowiki::formfield::hidden] } { return [_ acs-templating.Element_is_required [list label ${:label}]] } # #:log "++ ${:name} [:info class] validator=[:validator] ([llength [:validator]]) value=$value" foreach validator [:validator] { set errorMsg "" # # The validator might set the variable errorMsg in this scope. # set success 1 set validator_method check=$validator set proc_info [:procsearch $validator_method] #:log "++ ${:name}: field-level validator exists '$validator_method' ? [expr {$proc_info ne {}}]" if {$proc_info ne ""} { # # We have a slot checker, call it. # #:msg "++ call-field level validator $validator_method '$value'" set success [:validation_check $validator_method $value] } #:log "++ ${:name} [:info class] validator=[:validator] ([llength [:validator]]) value=$value -> $success" 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] #:log "++ ${:name}: page-level validator exists ? [expr {$proc_info ne {}}]" if {$proc_info ne ""} { set success [$obj $validator_method $value] #: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]] #:msg "__langPkg?[info exists __langPkg]" if {![info exists __langPkg]} { set __langPkg "xowiki" } #:log "calling $__langPkg.$cl-validate_$validator with [list value $value errorMsg $errorMsg] on level [info level]" set msg [_ $__langPkg.$cl-validate_$validator [list value $value errorMsg $errorMsg]] if {$msg eq ""} { set msg "validation of field '$validator' failed, '$errorMsg', no message key '$__langPkg.$cl-validate_$validator' provided" :log "++ ${:name}: VALIDATION FAILED <$msg>" } return $msg } } return "" } ::xowiki::formfield::FormField instproc same_value {v1 v2} { if {$v1 eq $v2} {return 1} return 0 } ::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 ${:locale} $key] } return $v } ::xowiki::formfield::FormField instproc is_disabled {} { return [expr {[info exists :disabled] && [string is true -strict ${:disabled}]}] } ::xowiki::formfield::FormField instproc set_disabled disable { #:msg "${:name} set disabled $disable" if {$disable} { set :disabled true } else { unset -nocomplain :disabled } } ::xowiki::formfield::FormField instproc answer_check=btwn {} { set d [:process_correct_when_modifier] dict with d { return [expr {$value >= [lindex $words 0] && $value <= [lindex $words 1]}] } } ::xowiki::formfield::FormField instproc answer_check=ge {} { set d [:process_correct_when_modifier] dict with d { return [expr {$value >= [lindex $words 0]}] } } ::xowiki::formfield::FormField instproc process_correct_when_modifier {} { # # Return a dict containing "words", "value" and "modifier", # skipping and processing optional parameters (just "-nocase" for # now). When "-nocase" is used, "value" and "words" are translated # to lowercase such that the result comparison is not case # sensitive. # set value [string trim [regsub -all -- {[ ]+} ${:value} " "]] set firstword [lindex ${:correct_when} 1] if {$firstword eq "-nocase" || [string match "*lower*" $firstword]} { set value [string tolower $value] set words [string tolower [lrange ${:correct_when} 2 end]] set modifier nocase } else { set words [lrange ${:correct_when} 1 end] set modifier "" } return [list op [lindex ${:correct_when} 0] words $words value $value modifier $modifier] } ::xowiki::formfield::FormField instproc field_value v { if {[info exists :show_raw_value]} { return $v } else { return [:pretty_value $v] } } ::xowiki::formfield::FormField instproc validation_check {validator_method value} { return [:uplevel [list :$validator_method $value]] } ::xowiki::formfield::FormField instproc reset_on_validation_error args { # # We don't actually do anything here, but subclassess can overload it. # } ::xowiki::formfield::FormField instproc render_disabled_as_div CSSclass { set attributes [:get_attributes id] lappend attributes class $CSSclass ::html::div $attributes { if {[info exists :value_with_markup]} { ::html::t -disableOutputEscaping ${:value_with_markup} } else { ::html::t [:value] } } } ::xowiki::formfield::FormField instproc answer_is_correct {} { # # Return correctness of the answer based on the instance variables # ":correct_when" and ":answer". Possible results are # # - 1: correct # - -1: incorrect # - 0: can't say (or report back, that no evaluation should be # provided for this field) # # This method is free of side-effects (no instance variables are updated). # #:log "CORRECT? ${:name} ([:info class]): value=${:value}, answer=[expr {[info exists :answer]?${:answer}:{NONE}}]" if {[info exists :correct_when] && ${:correct_when} ne ""} { set op [lindex ${:correct_when} 0] #:log "CORRECT? ${:name} with op=$op '${:correct_when}'" if {[:procsearch answer_check=$op] ne ""} { set r [:answer_check=$op] if {$r == 0} { return -1 } { return 1 } } elseif { $op eq ""} { return 0 } else { error "invalid operator '$op'" } } elseif {![info exists :answer]} { return 0 } elseif {${:value} ne ${:answer}} { #:msg "v='${:value}' NE a='[:answer]'" #:log "... answer_is_correct value comparison '${:value}' NE a='${:answer}'" return -1 } else { #:log "... answer_is_correct value comparison OK" return 1 } } ::xowiki::formfield::FormField instproc render_localizer {} { # Just an empty fall-back method. # This method will be overloaded in trn mode by a mixin. } ::xowiki::formfield::FormField instproc stats_record_count {} { # # This method is just called in situation, where the parent_id is # an instantiated object (via answer_is_correct). The parent # object is the actual workflow. # set reporting_obj ::[${:object} parent_id] $reporting_obj stats_record_count ${:name} } ::xowiki::formfield::FormField instproc has_instance_variable {var value} { if {[info exists :$var] && [set :$var] eq $value} {return 1} return 0 } ::xowiki::formfield::FormField instproc leaf_components {} { # # We want to be able to be able to call leaf_components on # arbitrary form-fields, so return for non-composite fields just a # list with a single element. # return [list [self]] } ::xowiki::formfield::FormField instproc answer_check=match {} { set d [:process_correct_when_modifier] dict with d { return [string match [lindex $words 0] $value] } } ::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 field of type string. # set value [:value] if {${:mode} ne "edit"} { html::t -disableOutputEscaping [:pretty_value $value] return } if {[info exists :validate_via_ajax] && [:validator] ne ""} { set ajaxhelper 1 ::xowiki::Includelet require_YUI_JS -ajaxhelper 0 "yahoo/yahoo-min.js" ::xowiki::Includelet require_YUI_JS -ajaxhelper 0 "dom/dom-min.js" ::xowiki::Includelet require_YUI_JS -ajaxhelper 0 "event/event-min.js" ::xowiki::Includelet require_YUI_JS -ajaxhelper 0 "connection/connection-min.js" ::xo::Page requireJS "/resources/xowiki/yui-form-field-validate.js" set package_url [[${:object} package_id] package_url] ::xo::Page requireJS "YAHOO.xo_form_field_validate.add('${:id}','$package_url');" } set booleanAtts [:booleanAttributes required readonly disabled multiple formnovalidate autofocus] # # We do not want i18n substitutions in the input fields. So, save # away the original value and pass the escaped value to the tDOM # renderer. # set old_value ${:value} set :value [:escape_message_keys $old_value] ::html::input [:get_attributes type size maxlength id name value style autocomplete pattern placeholder {CSSclass class} {*}$booleanAtts] {} # # Reset values to original content # :resetBooleanAttributes $booleanAtts set :value $old_value :handle_transmit_always $value set :__rendered 1 } ::xowiki::formfield::FormField instproc booleanAttributes args { # # Special handling of HTML boolean attributes, since they require a # different coding; it would be nice, if tDOM would care for this. # set pairs "" foreach att $args { if {[info exists :$att] && [set :$att]} { set :__#$att $att lappend pairs [list __#$att $att] } } return $pairs } ::xowiki::formfield::FormField instproc render_result_statistics {} { # # In case, there are result_statistics, use a "progress bar" to # visualize correct answers. # # Currently, this is bootstrap only, unless pie charts are used. # if {[info exists :result_statistics] && [dict exists ${:result_statistics} count]} { set result_count [dict get ${:result_statistics} count] #ns_log notice "??? render_result_statistics: ${:name}: ${:result_statistics}" if {$result_count > 0} { ::html::div -class "progress" { set correctCount [expr {[dict exists ${:result_statistics} correct] ? [dict get ${:result_statistics} correct] : 0}] set percentage [format %2.0f [expr {$correctCount * 100.0 / $result_count}]] ::html::div -class "progress-bar progress-bar-success" -role "progressbar" -aria-valuenow $percentage -aria-valuemin "0" -aria-valuemax "100" -style "width:$percentage%" { ::html::t "$percentage %" } } } } if {[info exists :answer_statistics]} { :render_collapsed -id answers-[clock clicks -microseconds] -label "#xowiki.answers#" -inner_method render_answer_statistics } if {[info exists :word_statistics]} { ns_log notice ":word_statistics: ${:word_statistics}" if {${:word_statistics_option} eq "word_cloud"} { :render_modal -id words-[clock clicks -microseconds] -label "#xowiki.words#" -inner_method render_word_statistics } else { # # The following is not used for the word cloud, since the # placement of the words in the word cloud does not work in # collapsed mode. # :render_collapsed -id words-[clock clicks -microseconds] -label "#xowiki.words#" -inner_method render_word_statistics } } } ::xowiki::formfield::FormField instproc set_feedback feedback_mode { # # Set instance variables based on correctness of an answer. # # - :form_widget_CSSclass # - :evaluated_answer_result # - :value (highlights potentially partial results, e.g. "contains") # - :help_text # set correct [:answer_is_correct] #:log "${:name} [:info class]: correct? $correct" switch -- $correct { 0 { set result "unknown" } -1 { set result "incorrect"} 1 { set result "correct" } } :form_widget_CSSclass $result set :evaluated_answer_result $result if {$correct == 0} { return ${:evaluated_answer_result} } set feedback "" if {[info exists :feedback_answer_$result]} { set feedback [set :feedback_answer_$result] } else { set feedback [_ xowf.answer_$result] } if {$feedback_mode > 1} { #ns_log notice "${:name} set_feedback $feedback_mode=[info exists :correct_when] " "correction?[info exists :correction] " "correction_data?[info exists :correction_data] " "============" if {[info exists :correct_when]} { append feedback " ${:correct_when}" } elseif {[info exists :correction]} { append feedback " ${:correction}" if {[info exists :correction_data]} { #append feedback " ${:correction_data}" if {[info exists :grading]} { if {${:grading} in {"" "exact"}} { set score [expr {${:evaluated_answer_result} eq "correct" ? 100.0 : 0.0}] dict set :correction_data scores ${:grading} $score } if {[dict exists ${:correction_data} scores ${:grading}] } { # # We end up here for # - MC (xowiki::formfield::checkbox) and # - SC (xowiki::formfield::radio) # - Reorder (::xowiki::formfield::reorder_box) # set grading_score [dict get ${:correction_data} scores ${:grading}] if {$grading_score < 0} { set grading_score 0.0 } #:log "=== ${:name} grading '${:grading}' => $grading_score" if {[info exists :test_item_points] && ${:test_item_points} ne ""} { set points [format %.2f [expr {${:test_item_points} * $grading_score / 100.0}]] dict set :correction_data points $points #append feedback " correct: $grading_score " append feedback " points: $points of [format %.2f ${:test_item_points}]" } else { append feedback " grading_score $grading_score" } #${:object} set_property -new 1 grading_score $grading_score set :grading_score $grading_score #ns_log notice "=== ${:name} SET GRADING score $grading_score" } else { ns_log notice "=== ${:name} == no scores for grading '${:grading}': ${:correction_data}" } } else { set :grading_score "" ns_log notice "=== ${:name} == no grading available" } } else { ns_log notice "=== ${:name} NO correction_data available" } } else { ns_log notice "=== ${:name} NO correct_when and no :correction" } # # When the widget class supports "disabled_as_div", we # can try to highlight matches from :correct_when. # if {[info exists :disabled_as_div] && [info exists :correct_when]} { # # When render_as_div might or might not require output # escaping. When we have a markup produced form match # highlighting, the code sets :value_with_markup for # rendering. Otherwise, the plain :value is used. # #ns_log notice "CHECK matches in ${:name} '${:correct_when}'" set :value [ns_quotehtml ${:value}] set saved_correct_when ${:correct_when} set op [lindex ${:correct_when} 0] if {$op in {contains contains-not}} { set :correct_when "AND [list ${:correct_when}]" set op AND } set dicts {} if {$op eq "AND"} { foreach clause [lrange ${:correct_when} 1 end] { set :correct_when $clause lappend dicts [:process_correct_when_modifier] } } set :correct_when $saved_correct_when set annotated_value ${:value} #ns_log notice "CHECK matches in ${:name} dicts <$dicts>" foreach d $dicts { if {[dict get $d op] in {contains contains-not}} { set CSSclass [dict get $d op] # # Mark matches in the div element. # set nocase [expr {[dict get $d modifier] eq "nocase" ? "-nocase" : ""}] #ns_log notice "CHECK matches in ${:name} nocase=$nocase words=[dict get $d words]" foreach word [dict get $d words] { # # We need here probably more escapes, or we should be more # restrictive on allowed content in the "contains" clause. # set word [string map {* \\* ( \\( ) \\)} $word] set nrSubst [regsub -all {*}$nocase -- [ns_quotehtml $word] $annotated_value "<span class='match-$CSSclass'>&</span>" annotated_value ] #ns_log notice "MATCH $word -> $nrSubst" } } } if {$annotated_value ne ${:value}} { set :value_with_markup $annotated_value } } } #:log "==== ${:name} setting feedback $feedback" set :help_text $feedback return ${:evaluated_answer_result} } ::xowiki::formfield::FormField instproc render {} { # # In case, we use an asHTML of a FormField, we use this # render definition. # if {${:inline}} { # with label, error message, help text :render_form_widget } else { # without label, error message, help text :render_item } set :__rendered 1 } ::xowiki::formfield::FormField instproc behavior mixin { # # Specify the behavior of a form field via # per object mixins # set pkgctx [[${:object} package_id] context] if {[$pkgctx exists embedded_context]} { set ctx [$pkgctx set embedded_context] set classname ${ctx}::$mixin #:msg ctx=$ctx-viewer=$mixin,found=[:isclass $classname] # TODO: search different places for the mixin. Special namespace? if {[:isclass $classname]} { if {[info exists :per_object_behavior]} { :mixin delete ${:per_object_behavior} } :mixin add $classname set :per_object_behavior $classname } else { :msg "Could not find mixin '$mixin'" } } } ::xowiki::formfield::FormField instproc asWidgetSpec {} { set spec ${:widget_type} if {[info exists :spell]} { append spec ",[expr {${:spell} ? {} : {no}}]spell" } if {!${:required}} { append spec ",optional" } if {[info exists :editor]} { append spec " {options {editor ${:editor}}} " } append spec " {label " [list ${:label}] "} " if {[string match "*bootstrap*" [subsite::get_theme]]} { # TODO: we need a better solution for this if {[::template::CSS toolkit] eq "bootstrap5" && ([:hasclass ::xowiki::formfield::radio] || [:hasclass ::xowiki::formfield::checkbox]) } { array set :html {class "form-check-input"} } else { array set :html {class "form-control"} } } if {[info exists :html]} { append spec " {html {" foreach {key value} [array get :html] { append spec $key " " [list $value] " " } append spec "}} " } if {[info exists :options]} { append spec " {options " [list ${:options}] "} " } if {[info exists :format]} { append spec " {format " [list ${:format}] "} " } if {${:help_text} ne ""} { if {[string match "#*#" ${:help_text}]} { set internationalized [:localize ${:help_text}] append spec " {help_text {$internationalized}}" } else { append spec " {help_text {${:help_text}}}" } } #ns_log notice "${:name} === asWidgetSpec return $spec" return $spec } ::xowiki::formfield::FormField instproc add_statistics {{-options ""}} { # # The FormField based incremental statistic counter is deprecated, # since for randomization, it is necessary to reinitialized # form-fields of an exam multiple times (different students have # different alternatives, etc.). Therefore, statistics have to be # collected in general on the level of the workflow object (via # $reporting_obj stats_record_*). # dict incr :result_statistics count #ns_log notice "[self] enumeration add_statistics count -> [dict get ${:result_statistics} count]" if {[info exists :evaluated_answer_result] && ${:evaluated_answer_result} eq "correct"} { #ns_log notice "[self] enumeration add_statistics count -> [dict get ${:result_statistics} count] correct" dict incr :result_statistics correct #ns_log notice "??? add_statistics ${:name}: ${:result_statistics}" } dict incr :answer_statistics ${:value} } ::nsf::method::property ::xowiki::formfield::FormField add_statistics deprecated true ::xowiki::formfield::FormField instproc answer_check=gt {} { set d [:process_correct_when_modifier] dict with d { return [expr {$value > [lindex $words 0]}] } } ::xowiki::formfield::FormField instproc value_if_nothing_is_returned_from_form default { return $default } ::xowiki::formfield::FormField instproc init {} { if {![info exists :label]} { set :label [string totitle ${:name}] } if {![info exists :id]} { set :id ${:name} } set :html(id) ${:id} #if {[info exists :default]} {set :value [:default]} # # An invalid spec could leave the broken formfield object behind. # try { :config_from_spec ${:spec} } on error {errmsg} { :destroy error $errmsg } } ::xowiki::formfield::FormField instproc render_help_text {} { if {${:help_text} ne ""} { html::div -class [:form_help_text_CSSclass] { html::span -class "info-sign" { } html::t ${:help_text} } } } ::xowiki::formfield::FormField instproc interprete_single_spec s { if {$s eq ""} return #ns_log notice "${:name} interprete_single_spec '$s'" 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 {set :required false} required {set :required true; :remove_omit} omit {:mixin add ::xowiki::formfield::omit} noomit {:remove_omit} disabled {:set_disabled true} readonly {:readonly true} enabled {:set_disabled false} label=* {:label [lindex [split $s =] 1]} help_text=* {:help_text [lindex [split $s =] 1]} *=* { set p [string first = $s] set attribute [string range $s 0 $p-1] set value [string range $s $p+1 end] set definition_class [lindex [:procsearch $attribute] 0] set method [:info methods $attribute] if {[string match "::xotcl::*" $definition_class] || $method eq ""} { error [_ xowiki.error-form_constraint-unknown_attribute [list class [:info class] name ${:name} entry $attribute]] } ad_try { # # 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] } :$attribute $value } on error {errMsg} { error "Error during setting attribute '$attribute' to value '$value': $errMsg" } } default { # Check, if the spec value $s is a class. set old_class [:info class] # Don't allow one to use namespaced values, since we would run # into a recursive loop for richtext::wym (could be altered there as well). if {[:isclass ::xowiki::formfield::$s] && ![string match "*:*" $s]} { :class ::xowiki::formfield::$s :remove_omit if {$old_class ne [:info class]} { #:msg "${:name}: reset class from $old_class to [:info class]" :reset_parameter set :__state reset #:log "INITIALIZE ${:name} due to reclassing old $old_class to new [:info class]" :initialize } } else { if {$s ne ""} { error [_ xowiki.error-form_constraint-unknown_spec_entry [list name ${:name} entry $s x "Unknown spec entry for entry '$s'"]] } } } } } ::xowiki::formfield::FormField instproc handle_transmit_always value { # # Disabled fields are not returned by the browsers. For some # fields, we require to be sent. Therefore, we include in these # cases the value in an additional hidden field. Maybe we should # change in the future the "name" of the disabled entry to keep # some hypothetical html-checker quiet. # if {[:is_disabled] && [info exists :transmit_field_always]} { ::html::div { ::html::input [list type hidden name ${:name} value $value] {} } } } ::xowiki::formfield::FormField instproc render_form_widget {} { # This method provides the form-widget wrapper if {0} { # no wrapper for form-widget (label + input) :render_input } else { set CSSclass [expr {[info exists :form_widget_CSSclass] ? ${:form_widget_CSSclass} : ""}] if {${:error_msg} ne ""} { append CSSclass " form-widget-error" } set atts [list class $CSSclass] if {${:inline}} { lappend atts style "display: inline;" } ::html::div $atts { :render_input } } } ::xowiki::formfield::FormField instproc is_repeat_template_p {} { return [expr {[info exists :is_repeat_template] && ${:is_repeat_template} == "true"}] } ::xowiki::formfield::FormField instproc answer_check=in {} { # # Correct, when answer is in the given set. # set d [:process_correct_when_modifier] dict with d { return [expr {$value in $words}] } } ::xowiki::formfield::FormField instproc describe {{-field_name ""}} { set d "" # # The dict keys of the result should correspond as far as possible # to message keys to ease multi-language communication. # set qa [${:object} property question] #ns_log notice "FormField describe gets question attributes <$qa> from ${:object}" foreach {key name} { question.minutes Minutes question.points Points question.grading grading question.show_max show_max } { if {[dict exists $qa $key]} { dict set d $name [dict get $qa $key] } } switch [:info class] { ::xowiki::formfield::radio - ::xowiki::formfield::checkbox { # mc and sc interaction set type [expr {[:info class] eq "::xowiki::formfield::checkbox" ? "MC" : "SC"}] # # The factual (displayed) answer is in ${:answer}, but we want # to see the list of possibilities, so use the data from the # original spec. # foreach s [split ${:spec} ,] { if {[regexp {^answer=(.*)$} $s . answer]} { break } } dict set d choice_options [llength ${answer}] dict set d nrcorrect [llength [lsearch -exact -all ${answer} t]] dict set d shuffle ${:shuffle_kind} #dict set d all [:serialize] } ::xowiki::formfield::text_fields { set type ShortText # short text interaction # # The factual (displayed) answer is in ${:answer}, but we want # to see the list of possibilities, so use the data from the # original spec (here in $options) # foreach s [split ${:spec} ,] { #ns_log warning "s=$s" if {[regexp {^options=(.*)$} $s . options]} { break } } dict set d all ${:spec} dict set d sub_questions [llength ${options}] dict set d shuffle ${:shuffle_kind} } ::xowiki::formfield::textarea { set type Text } ::xowiki::formfield::pool_question_placeholder { set type PoolQuestion set item_dict [:QM get_pool_questions -field_name $field_name ${:object} ""] set counts "" foreach {key value} $item_dict { dict incr counts [dict get $item_dict $key item_type] } dict set d available_pool_items [dict size $item_dict] dict set d available_pool_item_stats $counts } ::xowiki::formfield::reorder_box { set type Reorder } ::xowiki::formfield::file { set type Upload } ::xowiki::formfield::form_page { set type Composite } default { set type [:info class] ns_log warning "describe: class [:info class] not handled" } } dict set d type $type #ns_log notice "describe [:info class] [${:object} name] -> $d" dict set d question_title [${:object} title] return $d } ::xowiki::formfield::FormField instproc initialize {} next ::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 {[info exists :per_object_behavior]} { # remove per-object mixin from the "behavior" :mixin delete ${:per_object_behavior} unset :per_object_behavior } #:msg "reset along [:info precedence]" foreach c [: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 set :$var [$s default] set $key 1 } } :set_disabled false } ::xowiki::formfield::FormField instproc render_modal {-id:required {-label ""} -inner_method} { ::xowiki::BootstrapCollapseButton new -id $id -label $label -toggle "modal" -direction "down" ::html::div -id "$id" -class "modal fade" -tabindex -1 -role dialog aria-hidden "true" { ::html::div -class "modal-dialog" -role document { ::html::div -class "modal-content" { ::html::div -class "modal-header" { ::html::h5 -class "modal-title" { ::html::t $label } ::html::button -type "button" -class "close" -data-dismiss "modal" -aria-label "Close" { ::html::span -aria-hidden "true" { ::html::t -disableOutputEscaping "×" } } ::html::div -class "modal-body" { #::html::t ... :$inner_method } ::html::div -class "modal-footer" { ::html::button -type "button" -class "btn [::template::CSS class btn-default]" -data-dismiss "modal" { ::html::t Close } } } } } } } ::xowiki::formfield::FormField instproc answer_check=AND {} { set results "" # # The AND clause iterates over the list elements and reduces the # composite AND into multiple simple clauses and overwrites (! # danger) these in the instance variable "correct_when", but # resets these at the end. # set composite_correct_when ${:correct_when} ns_log notice "${:name} ... answercheck ${:correct_when}" foreach clause [lrange ${:correct_when} 1 end] { set :correct_when $clause ns_log notice "${:name} ... AND '$clause' for '${:value}' -> [:answer_is_correct]" lappend results [:answer_is_correct] } set :correct_when $composite_correct_when ns_log notice "${:name} $composite_correct_when => $results" if {0 in $results} { # # When one element is undecided, all is undecided. # return 0 } # # If one element is wrong, all is wrong # return [expr {-1 ni $results}] } ::xowiki::formfield::FormField instproc remove_omit {} { set m ::xowiki::formfield::omit if {[:ismixin $m]} {:mixin delete $m} } ::xowiki::formfield::FormField instproc word_statistics flavor { # # Word statistics based on :value. It is assumed here, that the # value is basically a string with whitespace. # regsub -all -- {\s} ${:value} " " value foreach w [split $value " "] { dict incr :word_statistics [string tolower $w] } set :word_statistics_option $flavor } ::xowiki::formfield::FormField instforward dict_value ::xowiki::formfield::dict_value ::xowiki::formfield::FormField instforward dict_to_spec ::xowiki::formfield::dict_to_spec ::xowiki::formfield::FormField instforward dict_to_fc ::xowiki::formfield::dict_to_fc ::xowiki::formfield::FormField instparametercmd slot ::xowiki::formfield::FormField instparametercmd correct_when ::xowiki::formfield::FormField instparametercmd form_help_text_CSSclass ::xowiki::formfield::FormField instparametercmd inline ::xowiki::formfield::FormField instparametercmd error_msg ::xowiki::formfield::FormField instparametercmd autofocus ::xowiki::formfield::FormField instparametercmd test_item_points ::xowiki::formfield::FormField instparametercmd multiple ::xowiki::formfield::FormField instparametercmd readonly ::xowiki::formfield::FormField instparametercmd show_raw_value ::xowiki::formfield::FormField instparametercmd feedback_answer_incorrect ::xowiki::formfield::FormField instparametercmd validate_via_ajax ::xowiki::formfield::FormField instparametercmd disabled_as_div ::xowiki::formfield::FormField instparametercmd id ::xowiki::formfield::FormField instparametercmd CSSclass ::xowiki::formfield::FormField instparametercmd answer ::xowiki::formfield::FormField instparametercmd test_item_minutes ::xowiki::formfield::FormField instparametercmd title ::xowiki::formfield::FormField instparametercmd spec ::xowiki::formfield::FormField instparametercmd value ::xowiki::formfield::FormField instparametercmd label ::xowiki::formfield::FormField instparametercmd style ::xowiki::formfield::FormField instparametercmd placeholder ::xowiki::formfield::FormField instparametercmd form_button_CSSclass ::xowiki::formfield::FormField instparametercmd pattern ::xowiki::formfield::FormField instparametercmd object ::xowiki::formfield::FormField instparametercmd form_item_wrapper_CSSclass ::xowiki::formfield::FormField instparametercmd locale ::xowiki::formfield::FormField instparametercmd form_label_CSSclass ::xowiki::formfield::FormField instparametercmd display_field ::xowiki::formfield::FormField instparametercmd name ::xowiki::formfield::FormField instparametercmd required ::xowiki::formfield::FormField instparametercmd autocomplete ::xowiki::formfield::FormField instparametercmd formnovalidate ::xowiki::formfield::FormField instparametercmd mode ::xowiki::formfield::FormField instparametercmd td_CSSclass ::xowiki::formfield::FormField instparametercmd type ::xowiki::formfield::FormField instparametercmd label_noquote ::xowiki::formfield::FormField instparametercmd form_button_wrapper_CSSclass ::xowiki::formfield::FormField instparametercmd form_widget_CSSclass ::xowiki::formfield::FormField instparametercmd default ::xowiki::formfield::FormField instparametercmd help_text ::xowiki::formfield::FormField instparametercmd validator ::xowiki::formfield::FormField instparametercmd test_item_in_position ::xowiki::formfield::FormField instparametercmd disabled ::xowiki::formfield::FormField instparametercmd in_position ::xowiki::formfield::FormField instparametercmd grading ::xowiki::formfield::FormField instparametercmd feedback_answer_correct ::xowiki::formfield::FormField instparametercmd hide_value ::nsf::relation::set ::xowiki::formfield::FormField superclass ::xo::tdom::Object ::nx::slotObj -container slot ::xowiki::formfield::FormField ::xowiki::formfield::FormField::slot eval {set :__parameter { {CSSclass form-control} {form_item_wrapper_CSSclass form-group} {form_label_CSSclass ""} {form_widget_CSSclass ""} {form_button_CSSclass "btn btn-default"} {form_button_wrapper_CSSclass ""} {form_help_text_CSSclass help-block} }} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::grading {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::grading set :methodname grading set :multiplicity 1..1 set :name grading set :parameterSpec -grading set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::feedback_answer_correct {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::feedback_answer_correct set :methodname feedback_answer_correct set :multiplicity 1..1 set :name feedback_answer_correct set :parameterSpec -feedback_answer_correct set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::inline {set :accessor public set :configurable true set :convert false set :default false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::inline set :methodname inline set :multiplicity 1..1 set :name inline set :parameterSpec {-inline:substdefault false} set :per-object false set :position 0 set :required false set :substdefault 0b111 set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::form_item_wrapper_CSSclass {set :accessor public set :configurable true set :convert false set :default form-group set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::form_item_wrapper_CSSclass set :methodname form_item_wrapper_CSSclass set :multiplicity 1..1 set :name form_item_wrapper_CSSclass set :parameterSpec {-form_item_wrapper_CSSclass:substdefault form-group} set :per-object false set :position 0 set :required false set :substdefault 0b111 set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::disabled {set :accessor public set :configurable true set :convert false set :default 0 set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::disabled set :methodname disabled set :multiplicity 1..1 set :name disabled set :parameterSpec {-disabled:substdefault 0} set :per-object false set :position 0 set :required false set :substdefault 0b111 set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::spec {set :accessor public set :configurable true set :convert false set :default {} set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::spec set :methodname spec set :multiplicity 1..1 set :name spec set :parameterSpec {-spec:substdefault {}} set :per-object false set :position 0 set :required false set :substdefault 0b111 set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::placeholder {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::placeholder set :methodname placeholder set :multiplicity 1..1 set :name placeholder set :parameterSpec -placeholder set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::help_text {set :accessor public set :configurable true set :convert false set :default {} set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::help_text set :methodname help_text set :multiplicity 1..1 set :name help_text set :parameterSpec {-help_text:substdefault {}} set :per-object false set :position 0 set :required false set :substdefault 0b111 set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::show_raw_value {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::show_raw_value set :methodname show_raw_value set :multiplicity 1..1 set :name show_raw_value set :parameterSpec -show_raw_value set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::form_help_text_CSSclass {set :accessor public set :configurable true set :convert false set :default help-block set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::form_help_text_CSSclass set :methodname form_help_text_CSSclass set :multiplicity 1..1 set :name form_help_text_CSSclass set :parameterSpec {-form_help_text_CSSclass:substdefault help-block} set :per-object false set :position 0 set :required false set :substdefault 0b111 set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::validator {set :accessor public set :configurable true set :convert false set :default {} set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::validator set :methodname validator set :multiplicity 1..1 set :name validator set :parameterSpec {-validator:substdefault {}} set :per-object false set :position 0 set :required false set :substdefault 0b111 set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::form_label_CSSclass {set :accessor public set :configurable true set :convert false set :default {} set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::form_label_CSSclass set :methodname form_label_CSSclass set :multiplicity 1..1 set :name form_label_CSSclass set :parameterSpec {-form_label_CSSclass:substdefault {}} set :per-object false set :position 0 set :required false set :substdefault 0b111 set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::title {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::title set :methodname title set :multiplicity 1..1 set :name title set :parameterSpec -title set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::value {set :accessor public set :configurable true set :convert false set :default {} set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::value set :methodname value set :multiplicity 1..1 set :name value set :parameterSpec {-value:substdefault {}} set :per-object false set :position 0 set :required false set :substdefault 0b111 set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::form_button_CSSclass {set :accessor public set :configurable true set :convert false set :default {btn btn-default} set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::form_button_CSSclass set :methodname form_button_CSSclass set :multiplicity 1..1 set :name form_button_CSSclass set :parameterSpec {-form_button_CSSclass:substdefault {btn btn-default}} set :per-object false set :position 0 set :required false set :substdefault 0b111 set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::td_CSSclass {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::td_CSSclass set :methodname td_CSSclass set :multiplicity 1..1 set :name td_CSSclass set :parameterSpec -td_CSSclass set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::answer {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::answer set :methodname answer set :multiplicity 1..1 set :name answer set :parameterSpec -answer set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::label {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::label set :methodname label set :multiplicity 1..1 set :name label set :parameterSpec -label set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::style {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::style set :methodname style set :multiplicity 1..1 set :name style set :parameterSpec -style set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::name {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::name set :methodname name set :multiplicity 1..1 set :name name set :parameterSpec -name set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::test_item_points {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::test_item_points set :methodname test_item_points set :multiplicity 1..1 set :name test_item_points set :parameterSpec -test_item_points set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::autocomplete {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::autocomplete set :methodname autocomplete set :multiplicity 1..1 set :name autocomplete set :parameterSpec -autocomplete set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::multiple {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::multiple set :methodname multiple set :multiplicity 1..1 set :name multiple set :parameterSpec -multiple set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::disabled_as_div {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::disabled_as_div set :methodname disabled_as_div set :multiplicity 1..1 set :name disabled_as_div set :parameterSpec -disabled_as_div set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::mode {set :accessor public set :configurable true set :convert false set :default edit set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::mode set :methodname mode set :multiplicity 1..1 set :name mode set :parameterSpec {-mode:substdefault edit} set :per-object false set :position 0 set :required false set :substdefault 0b111 set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::hide_value {set :accessor public set :configurable true set :convert false set :default false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::hide_value set :methodname hide_value set :multiplicity 1..1 set :name hide_value set :parameterSpec {-hide_value:substdefault false} set :per-object false set :position 0 set :required false set :substdefault 0b111 set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::readonly {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::readonly set :methodname readonly set :multiplicity 1..1 set :name readonly set :parameterSpec -readonly set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::error_msg {set :accessor public set :configurable true set :convert false set :default {} set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::error_msg set :methodname error_msg set :multiplicity 1..1 set :name error_msg set :parameterSpec {-error_msg:substdefault {}} set :per-object false set :position 0 set :required false set :substdefault 0b111 set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::autofocus {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::autofocus set :methodname autofocus set :multiplicity 1..1 set :name autofocus set :parameterSpec -autofocus set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::display_field {set :accessor public set :configurable true set :convert false set :default true set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::display_field set :methodname display_field set :multiplicity 1..1 set :name display_field set :parameterSpec {-display_field:substdefault true} set :per-object false set :position 0 set :required false set :substdefault 0b111 set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::type {set :accessor public set :configurable true set :convert false set :default text set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::type set :methodname type set :multiplicity 1..1 set :name type set :parameterSpec {-type:substdefault text} set :per-object false set :position 0 set :required false set :substdefault 0b111 set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::in_position {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::in_position set :methodname in_position set :multiplicity 1..1 set :name in_position set :parameterSpec -in_position set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::form_widget_CSSclass {set :accessor public set :configurable true set :convert false set :default {} set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::form_widget_CSSclass set :methodname form_widget_CSSclass set :multiplicity 1..1 set :name form_widget_CSSclass set :parameterSpec {-form_widget_CSSclass:substdefault {}} set :per-object false set :position 0 set :required false set :substdefault 0b111 set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::form_button_wrapper_CSSclass {set :accessor public set :configurable true set :convert false set :default {} set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::form_button_wrapper_CSSclass set :methodname form_button_wrapper_CSSclass set :multiplicity 1..1 set :name form_button_wrapper_CSSclass set :parameterSpec {-form_button_wrapper_CSSclass:substdefault {}} set :per-object false set :position 0 set :required false set :substdefault 0b111 set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::CSSclass {set :accessor public set :configurable true set :convert false set :default form-control set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::CSSclass set :methodname CSSclass set :multiplicity 1..1 set :name CSSclass set :parameterSpec {-CSSclass:substdefault form-control} set :per-object false set :position 0 set :required false set :substdefault 0b111 set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::object {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::object set :methodname object set :multiplicity 1..1 set :name object set :parameterSpec -object set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::locale {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::locale set :methodname locale set :multiplicity 1..1 set :name locale set :parameterSpec -locale set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::label_noquote {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::label_noquote set :methodname label_noquote set :multiplicity 1..1 set :name label_noquote set :parameterSpec -label_noquote set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::formnovalidate {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::formnovalidate set :methodname formnovalidate set :multiplicity 1..1 set :name formnovalidate set :parameterSpec -formnovalidate set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::validate_via_ajax {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::validate_via_ajax set :methodname validate_via_ajax set :multiplicity 1..1 set :name validate_via_ajax set :parameterSpec -validate_via_ajax set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::feedback_answer_incorrect {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::feedback_answer_incorrect set :methodname feedback_answer_incorrect set :multiplicity 1..1 set :name feedback_answer_incorrect set :parameterSpec -feedback_answer_incorrect set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::pattern {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::pattern set :methodname pattern set :multiplicity 1..1 set :name pattern set :parameterSpec -pattern set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::test_item_in_position {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::test_item_in_position set :methodname test_item_in_position set :multiplicity 1..1 set :name test_item_in_position set :parameterSpec -test_item_in_position set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::slot {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::slot set :methodname slot set :multiplicity 1..1 set :name slot set :parameterSpec -slot set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::test_item_minutes {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::test_item_minutes set :methodname test_item_minutes set :multiplicity 1..1 set :name test_item_minutes set :parameterSpec -test_item_minutes set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::correct_when {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::correct_when set :methodname correct_when set :multiplicity 1..1 set :name correct_when set :parameterSpec -correct_when set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::id {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::id set :methodname id set :multiplicity 1..1 set :name id set :parameterSpec -id set :per-object false set :position 0 set :required false set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::required {set :accessor public set :configurable true set :convert false set :default false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::required set :methodname required set :multiplicity 1..1 set :name required set :parameterSpec {-required:substdefault false} set :per-object false set :position 0 set :required false set :substdefault 0b111 set :trace none : init} ::nsf::object::alloc ::xotcl::Attribute ::xowiki::formfield::FormField::slot::default {set :accessor public set :configurable true set :convert false set :defaultmethods {} set :disposition alias set :domain ::xowiki::formfield::FormField set :incremental 0 set :manager ::xowiki::formfield::FormField::slot::default set :methodname default set :multiplicity 1..1 set :name default set :parameterSpec -default set :per-object false set :position 0 set :required false set :trace none : init}XQL Not present: Generic, PostgreSQL, Oracle
![[i]](/resources/acs-subsite/ZoomIn16.gif)