package provide Form 1.0 namespace eval Form { variable inherit { -type -maxlength -size -inline -disabled -readonly -template -class -onfocus -onblur -onselect -onchange } variable field_fields { -type -maxlength -name -size -value -legend -label -prolog -epilog -inline -acronym -alt -checked -disabled -readonly -tabindex -src -onfocus -onblur -onselect -onchange -class -rows -cols } variable defaults { -method post -type text -maxlength 64 -size 30 -inline 1 } proc parse_field {name f fieldset} { set field [dict create -label $name -name $name] # grab defaults from fieldset variable inherit dict for {k v} $fieldset { if {$k in $inherit} { dict set field $k $v } } variable field_fields foreach {key val} $f { if {$key in $field_fields} { dict set field $key $val } else { error "Unknown argument $key in field $name" } } return $field } proc parse_fieldset {name fs form} { set fieldset [dict create -label $name -inline 0] # grab defaults from form variable inherit dict for {k v} $form { if {$k in $inherit} { dict set fieldset $k $v } } set fields {} foreach {key val} $fs { if {[string match -* $key]} { dict set fieldset $key $val } else { lappend fields $key dict set fieldset $key [parse_field $key $val $fieldset] } } dict set fieldset -fields $fields return $fieldset } proc parse {text args} { variable defaults set form [dict merge $defaults $args] set fieldsets {} foreach {key val} $text { if {[string match -* $key]} { dict set form $key $val } else { lappend fieldsets $key dict set form $key [parse_fieldset $key $val $form] } } dict set form -fieldsets $fieldsets return $form } proc label {text} { set result {} foreach word [split $text] { if {$word eq ""} continue if {[string length $word] > 3} { lappend result [string totitle $word] } else { lappend result $word } } return [join $result] } proc html {form args} { set form [parse $form {*}$args] if {[dict exists $form -record]} { set record [dict get $form -record] #puts stderr "form html record: $record" Debug {form html record: $record} } else { set record [dict create] } set html "" if {[dict exists $form -class]} { set class [dict get $form -class] } else { set class Form } if {[dict exists $form -action]} { append html "<form class='$class' action='[dict get $form -action]' method='[dict get $form -method]'>\n" } if {[dict exists $form -prolog]} { append html [dict get $form -prolog] \n } foreach fsn [dict get $form -fieldsets] { set fs [dict get $form $fsn] append html <fieldset> \n append html <legend> [label [dict get $fs -label]] </legend> \n if {[dict exists $fs -prolog]} { append html [dict get $form -prolog] \n } foreach fn [dict get $fs -fields] { set f [dict get $form $fsn $fn] if {[dict get $f -type] ne "hidden"} { if {![dict get $f -inline]} { append html <p> } append html <label> if {[dict exists $f -acronym]} { append html "<acronym title='[dict get $f -acronym]'>" append html [label [dict get $f -label]] append html </acronym> append html ": " } else { append html [label [dict get $f -label]] ": " } append html </label> } if {[dict exists $f -type] && ([dict get $f -type] eq "textarea")} { append html <textarea set attrs {type name readonly rows cols} } else { append html <input set attrs {type maxlength name size alt readonly} } foreach x $attrs { if {[dict exists $f -$x]} { append html " $x='[dict get $f -$x]'" } } if {[dict exists $f -name]} { set name [dict get $f -name] } else { set name $fn } if {[dict exists $f -type] && ([dict get $f -type] ne "textarea")} { if {[dict exists $f -value]} { append html " value='[dict get $f -value]'" } elseif {[dict exists $record $name]} { #puts stderr "REC: $name / [dict get $record $name] / [armour [dict get $record $name]] / $record" append html " value='[armour [dict get $record $name]]'" } elseif {[dict exists $form -template] && ([dict get $form -template] ne "")} { set t [dict get $form -template] append html " value='[string map [list % $name] $t]'" } append html /> \n } else { append html > \n if {[dict exists $f -value]} { append html [dict get $f -value] } elseif {[dict exists $form -template] && ([dict get $form -template] ne "")} { set t [dict get $form -template] append html [string map [list % [dict get $f -name]] $t] } append html </textarea> \n } if {[dict exists $f -legend]} { append html [dict get $f -legend] } if {![dict get $f -inline]} { append html </p> } if {[dict exists $f -text]} { append html <p> [dict get $f -text] </p> \n } } if {[dict exists $fs -epilog]} { append html <p> [dict get $fs -epilog] </p> \n } append html </fieldset> \n } if {[dict exists $form -epilog]} { append html [dict get $form -epilog] \n } if {[dict exists $form -submit]} { append html "<input type='submit' value='[dict get $form -submit]'/>" \n } if {[dict exists $form -action]} { append html </form> } return $html } proc load {path args} { set fd [open $path] set content [read $fd] close $fd if {$args ne {}} { set content [string map $args $content] } #puts stderr "Load: $content" return [html $content] } namespace export -clear * namespace ensemble create -subcommands {} } if {[info exists argv0] && ($argv0 eq [info script])} { puts "<html><head></head><body>" puts [Form html { -submit "Create New Account" -prolog "<p>This is a form to enter your account details</p>" -epilog "<p>When you create the account instructions will be emailed to you. Make sure your email address is correct.</p>" details { -label "Account Details" -inline 1 user { -acronym "Your preferred username (only letters, numbers and spaces)" } email { -acronym "Your email address" -value moop } hidden { -type hidden } } passwords { -text "Type in your preferred password, twice. Leaving it blank will generate a random password for you." -type password -inline 1 password {} repeat {} } personal { -label "Personal Information" name { -name fullname -acronym "Full name to be used in email." } phone { -acronym "Phone number for official contact" } } } -action http:moop.html] puts "</body>\n</html>" }
HJG On my Tcl 8.4 installation, I get an error 'invalid command name "dict" ... line 165'.RLH dict is in 8.5...but I think that there was a backport to 8.4, if you want to try it.MHo Changed {expand} to {*}