cuca 0.06 → 0.07
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +9 -0
- data/README +43 -34
- data/application_skeleton/app/_layouts/simple.rb +1 -1
- data/application_skeleton/public/dispatch-fwdev.cgi +21 -0
- data/application_skeleton/public/dispatch.cgi +1 -1
- data/application_skeleton/public/dispatch.cgi-old +18 -0
- data/application_skeleton/public/dispatch.fcgi-old +25 -0
- data/application_skeleton/scripts/rack-test.rb +52 -0
- data/application_skeleton/scripts/server-rack-thin.rb +40 -0
- data/application_skeleton/scripts/server-rack-webrick.rb +22 -0
- data/application_skeleton/scripts/server-webrick-cgihandler.rb +26 -0
- data/application_skeleton/scripts/server-webrick.rb +1 -1
- data/lib/cuca.rb +2 -30
- data/lib/cuca/app.rb +35 -30
- data/lib/cuca/app_cgi.rb +289 -0
- data/lib/cuca/config.rb +8 -15
- data/lib/cuca/controller.rb +22 -11
- data/lib/cuca/generator/view.rb +4 -51
- data/lib/cuca/generator_context.rb +42 -0
- data/lib/cuca/layout.rb +1 -1
- data/lib/cuca/session.rb-cgi +171 -0
- data/lib/cuca/sessionpage.rb +13 -2
- data/lib/cuca/stdlib/arform.rb +19 -2
- data/lib/cuca/stdlib/form.rb +6 -3
- data/lib/cuca/stdlib/formelements.rb +33 -8
- data/lib/cuca/stdlib/formelements.rbs +157 -0
- data/lib/cuca/stdlib/listwidget/dblist.rb +10 -6
- data/lib/cuca/stdlib/listwidget/list.rb +24 -4
- data/lib/cuca/widget.rb +11 -14
- data/lib/cuca_cli.rb +14 -0
- data/tests/controller.rb +21 -5
- data/tests/generator_markaby.rb +1 -1
- data/tests/widget.rb +2 -1
- metadata +96 -96
@@ -0,0 +1,42 @@
|
|
1
|
+
# A good context for generators. It will find and run widgets on method_missing.
|
2
|
+
#
|
3
|
+
class GeneratorContext
|
4
|
+
def get_bindings
|
5
|
+
binding
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(assigns, base_object)
|
9
|
+
assigns.each_pair do |k,v|
|
10
|
+
instance_variable_set("@#{k}", v)
|
11
|
+
end
|
12
|
+
@base = base_object
|
13
|
+
end
|
14
|
+
|
15
|
+
def method_missing(sym, *args, &block )
|
16
|
+
class_name = sym.id2name
|
17
|
+
|
18
|
+
|
19
|
+
# 1st try to find method in the base widget
|
20
|
+
if @base.respond_to?(class_name.intern) then
|
21
|
+
return @base.send(class_name, *args, &block)
|
22
|
+
end
|
23
|
+
c = nil
|
24
|
+
# 2nd try to find a widget
|
25
|
+
if Object.const_defined?(class_name+'Widget') then
|
26
|
+
c = Object::const_get(class_name+'Widget')
|
27
|
+
else
|
28
|
+
# ...try to find in action namespace
|
29
|
+
mod = $app.urlmap.action_module
|
30
|
+
c = mod.const_get(class_name+'Widget') if mod.const_defined?(class_name+'Widget')
|
31
|
+
end
|
32
|
+
|
33
|
+
raise NameError.new "Undefined method: #{class_name}" unless c
|
34
|
+
|
35
|
+
widget = c.new({:args => args,
|
36
|
+
:assigns => @assigns },
|
37
|
+
&block)
|
38
|
+
|
39
|
+
return widget.to_s
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
data/lib/cuca/layout.rb
CHANGED
@@ -0,0 +1,171 @@
|
|
1
|
+
|
2
|
+
require 'cgi/session'
|
3
|
+
require 'cgi/session/pstore'
|
4
|
+
|
5
|
+
require 'cuca/app'
|
6
|
+
require 'cuca/widget'
|
7
|
+
require 'cuca/sessionflash'
|
8
|
+
require 'cuca/sessionpage'
|
9
|
+
|
10
|
+
module Cuca
|
11
|
+
|
12
|
+
|
13
|
+
# == Description
|
14
|
+
# Session can be used to store stateful data. It is not loaded by default, to make
|
15
|
+
# use of it you must require this module and tell a controller to use a session.
|
16
|
+
#
|
17
|
+
# == Example Use (permanent data)
|
18
|
+
#
|
19
|
+
# Initialize (using a controller):
|
20
|
+
#
|
21
|
+
# class ApplicationController < Cuca::Controller
|
22
|
+
# use_session
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# Save and Load data (from any widgets e.g. controller):
|
26
|
+
#
|
27
|
+
# class IndexController < ApplicationController
|
28
|
+
#
|
29
|
+
# def run
|
30
|
+
# session[:stuff_to_remember] = "hello world"
|
31
|
+
# @stuff = session[:stuff_to_remember]
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# == Flash Memory
|
36
|
+
#
|
37
|
+
# The flash memory can be used to store temporarily data for the current and
|
38
|
+
# next action. A typical example are messages after a post event, like:
|
39
|
+
#
|
40
|
+
# class LoginController < ApplicationController
|
41
|
+
# (...)
|
42
|
+
# def post
|
43
|
+
# if (params['username'] == 'root' && params['pass'] == 'stuff') then
|
44
|
+
# session.flash[:message] = "You are logged in"
|
45
|
+
# session[:username] = 'root'
|
46
|
+
# stop :redirect => 'index'
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# If you want to keep the flash memory for another cycle you can call:
|
52
|
+
#
|
53
|
+
# session.flash.keep
|
54
|
+
#
|
55
|
+
#
|
56
|
+
# == Page Memory
|
57
|
+
#
|
58
|
+
# Page memory is a container to store data only valid for the current action.
|
59
|
+
# It will be erased once you leave to a different action.
|
60
|
+
# Current request and query parameters (get/post) are automatically available in this
|
61
|
+
# container.
|
62
|
+
#
|
63
|
+
#
|
64
|
+
#
|
65
|
+
# == Configuration
|
66
|
+
#
|
67
|
+
# Session is using some values from App::Config :
|
68
|
+
#
|
69
|
+
# 'session_prefix'
|
70
|
+
# 'session_valid'
|
71
|
+
# 'session_key'
|
72
|
+
#
|
73
|
+
class Session
|
74
|
+
attr_reader :flash
|
75
|
+
attr_reader :page
|
76
|
+
attr_reader :cgi
|
77
|
+
|
78
|
+
private
|
79
|
+
def make_session
|
80
|
+
@sess = CGI::Session.new(@cgi, @session_parameters)
|
81
|
+
end
|
82
|
+
|
83
|
+
public
|
84
|
+
def reset
|
85
|
+
begin
|
86
|
+
@sess.delete
|
87
|
+
rescue
|
88
|
+
end
|
89
|
+
make_session
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
# returns true/false if a session exists
|
94
|
+
def exists?
|
95
|
+
begin
|
96
|
+
p = @session_parameters.clone
|
97
|
+
p['new_session'] = false
|
98
|
+
session = CGI::Session.new(cgi, p)
|
99
|
+
rescue ArgumentError
|
100
|
+
return false
|
101
|
+
end
|
102
|
+
return true
|
103
|
+
end
|
104
|
+
|
105
|
+
def initialize(cgi)
|
106
|
+
@cgi = cgi
|
107
|
+
|
108
|
+
@session_parameters = {
|
109
|
+
'database_manager' => CGI::Session::PStore,
|
110
|
+
'session_key' => App::config["session_key"],
|
111
|
+
'session_path' => '/',
|
112
|
+
# 'new_session' => false,
|
113
|
+
'session_expires' => Time.now + App::config["session_valid"].to_i,
|
114
|
+
'prefix' => App::config["session_prefix"] }
|
115
|
+
|
116
|
+
make_session
|
117
|
+
|
118
|
+
|
119
|
+
@flash = SessionFlash.new(self)
|
120
|
+
@page = SessionPage.new(self)
|
121
|
+
end
|
122
|
+
|
123
|
+
def []=(key, value)
|
124
|
+
@sess[key] = value
|
125
|
+
end
|
126
|
+
|
127
|
+
def [](key)
|
128
|
+
return @sess[key]
|
129
|
+
end
|
130
|
+
|
131
|
+
def close
|
132
|
+
@sess.close
|
133
|
+
end
|
134
|
+
|
135
|
+
def update
|
136
|
+
@sess.update
|
137
|
+
end
|
138
|
+
|
139
|
+
def delete
|
140
|
+
@sess.delete
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
class Controller
|
147
|
+
# This will create filters that initialize the session before the action and
|
148
|
+
# close it afterwards.
|
149
|
+
def self.use_session
|
150
|
+
priority_before_filter('ses_initialize_session')
|
151
|
+
priority_after_filter('ses_close_session')
|
152
|
+
end
|
153
|
+
|
154
|
+
def ses_initialize_session
|
155
|
+
$session = Session.new($app.cgi)
|
156
|
+
end
|
157
|
+
def ses_close_session
|
158
|
+
$session.close
|
159
|
+
# $session = nil
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
class Widget
|
165
|
+
def session
|
166
|
+
$session
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
|
data/lib/cuca/sessionpage.rb
CHANGED
@@ -4,6 +4,7 @@ module Cuca
|
|
4
4
|
# for the current action. Once you leave to another page it will
|
5
5
|
# be erased. (see Cuca::Session)
|
6
6
|
class SessionPage
|
7
|
+
|
7
8
|
private
|
8
9
|
def pagekey
|
9
10
|
"Pk_#{$app.urlmap.script.gsub(/[\/\\]/, '_')}".intern
|
@@ -23,18 +24,28 @@ class SessionPage
|
|
23
24
|
end
|
24
25
|
|
25
26
|
def [](key)
|
26
|
-
pagemem[pagekey][key]
|
27
|
+
pagemem[pagekey][key]
|
27
28
|
end
|
28
29
|
|
29
30
|
def []=(key,value)
|
30
31
|
pagemem[pagekey][key] = value
|
31
32
|
end
|
32
|
-
|
33
|
+
|
33
34
|
# remove a variable from page memory
|
34
35
|
def delete(key)
|
35
36
|
pagemem[pagekey].delete(key)
|
36
37
|
end
|
37
38
|
|
39
|
+
# delete all from current page memory
|
40
|
+
def reset
|
41
|
+
pagemem[pagekey] = {}
|
42
|
+
end
|
43
|
+
|
44
|
+
# access to pagemem
|
45
|
+
def memory
|
46
|
+
pagemem[pagekey]
|
47
|
+
end
|
48
|
+
|
38
49
|
private
|
39
50
|
def expire
|
40
51
|
pagemem.each_pair do |k,v|
|
data/lib/cuca/stdlib/arform.rb
CHANGED
@@ -28,6 +28,8 @@ class ARFormWidget < FormWidget
|
|
28
28
|
# switch off fields on new records
|
29
29
|
# * :diabled_on_update => ['field_name_1', 'field_name_2', ..]
|
30
30
|
# switch off fields on existing records
|
31
|
+
# * :save_attribs => ['attr1', 'attr2']
|
32
|
+
# allow to call a setter even if it's not a db column
|
31
33
|
# * .. options from FormWidgets ...
|
32
34
|
def output(form_name, model, options = {})
|
33
35
|
@model = model
|
@@ -35,8 +37,16 @@ class ARFormWidget < FormWidget
|
|
35
37
|
@disabled_on_create = options[:disabled_on_create] || []
|
36
38
|
@hidden_on_update = options[:hidden_on_update] || []
|
37
39
|
@hidden_on_create = options[:hidden_on_create] || []
|
40
|
+
@save_attribs = options[:save_attribs] || []
|
41
|
+
|
42
|
+
|
43
|
+
setup if self.respond_to?(:setup) # you might want to use a method for setup
|
44
|
+
|
38
45
|
|
39
46
|
options[:default_values] = model.attributes.merge(options[:default_values] || {})
|
47
|
+
@save_attribs.each do |sa|
|
48
|
+
options[:default_values][sa] = model.send(sa.intern) if model.respond_to?(sa.intern)
|
49
|
+
end
|
40
50
|
|
41
51
|
super(form_name, options)
|
42
52
|
end
|
@@ -73,8 +83,15 @@ class ARFormWidget < FormWidget
|
|
73
83
|
@password_fields.each do |pwf|
|
74
84
|
p.delete(pwf) if p[pwf].chomp.empty?
|
75
85
|
end
|
76
|
-
|
77
|
-
|
86
|
+
|
87
|
+
# remove possible additional data that model doesn't support to
|
88
|
+
# p.delete_if { |k,v| !@mode.respond_to?("#{k}=") }
|
89
|
+
|
90
|
+
column_names = @model.class.columns.map { |c| c.name }
|
91
|
+
p.each do |k,v|
|
92
|
+
@model.send("#{k}=".intern, v) if (column_names.include?(k) && @model.respond_to?("#{k}=")) || @save_attribs.include?(k)
|
93
|
+
end
|
94
|
+
# @model.attributes = p
|
78
95
|
|
79
96
|
return true if @model.valid?
|
80
97
|
|
data/lib/cuca/stdlib/form.rb
CHANGED
@@ -71,7 +71,6 @@
|
|
71
71
|
# end
|
72
72
|
# end
|
73
73
|
#
|
74
|
-
|
75
74
|
class FormWidget < Cuca::Widget
|
76
75
|
|
77
76
|
# Returns true if this form was posted
|
@@ -89,7 +88,7 @@ class FormWidget < Cuca::Widget
|
|
89
88
|
# it will get the variables from the options[:default_values]
|
90
89
|
def get_form_variables
|
91
90
|
var = @options[:default_values] || {}
|
92
|
-
params.each_pair { |k,v| var[k] = v } if posted?
|
91
|
+
params.each_pair { |k,v| var[k] = v } if posted? # request_method == 'POST'
|
93
92
|
@variables = {}
|
94
93
|
var.each_pair { |k,v| @variables[k.to_s] = v } # this allows is to pass symbols to default_values
|
95
94
|
@variables
|
@@ -167,5 +166,9 @@ class FormWidget < Cuca::Widget
|
|
167
166
|
form
|
168
167
|
end
|
169
168
|
end
|
169
|
+
|
170
|
+
def self.run(*args)
|
171
|
+
w = self.class.new
|
172
|
+
w.output(args)
|
173
|
+
end
|
170
174
|
end
|
171
|
-
|
@@ -33,7 +33,6 @@ module FormElements
|
|
33
33
|
fe_text(name, attribs)
|
34
34
|
end
|
35
35
|
|
36
|
-
|
37
36
|
def fe_textarea(name, attribs = {})
|
38
37
|
a = { :rows => 5, :cols => 50 }.merge(attribs)
|
39
38
|
"<textarea name='#{name}' #{a2p(a)}>#{get_value(name, attribs)}</textarea>\n"
|
@@ -41,7 +40,8 @@ module FormElements
|
|
41
40
|
|
42
41
|
# build a form start tag
|
43
42
|
def fe_formstart(attribs = {})
|
44
|
-
|
43
|
+
form_name = attribs[:form_name] || @form_name
|
44
|
+
a = {:name=>form_name, :method=>'post', :action=>@post_to }.merge(attribs)
|
45
45
|
"<form #{a2p(a)}>\n"
|
46
46
|
end
|
47
47
|
|
@@ -51,21 +51,46 @@ module FormElements
|
|
51
51
|
attribs.delete(:showvalue)
|
52
52
|
"<input type='password' name='#{name}' value='#{v}' #{a2p(attribs)}>\n"
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
|
+
# :default_value is 'on' or 'off' for checkboxes
|
56
|
+
def fe_checkbox(name, attribs = {})
|
57
|
+
checker_name = "#{name}_checker"
|
58
|
+
newval = !!(request_parameters[name] || query_parameters[name])
|
59
|
+
posted = (request_parameters[checker_name] || query_parameters[checker_name])
|
60
|
+
|
61
|
+
# checkbox html element isn't sent to cgi if not selected
|
62
|
+
# so cuca's page variables won't work - this fixes it for most cases.
|
63
|
+
if (session.page && (posted && !newval)) then
|
64
|
+
session.page[name] = 'off'
|
65
|
+
end
|
66
|
+
|
67
|
+
checked = v[name] && (v[name].to_s != 'off')
|
68
|
+
checked = attribs[:default_value] == 'on' if (!posted and !v[name])
|
69
|
+
|
70
|
+
checkedval = checked ? ' CHECKED' : ''
|
71
|
+
"<input type='checkbox' name='#{name}' #{a2p(attribs)}#{checkedval}>"+
|
72
|
+
"<input type='hidden' name='#{checker_name}' value='1'>\n" # Needed to detect if element was submitted
|
73
|
+
end
|
74
|
+
|
75
|
+
|
55
76
|
|
56
77
|
# this is to build a select box, example:
|
57
78
|
# fe_select('gender', [['f', 'female'],['m','Male']]) or
|
79
|
+
# ...with options parameters...:
|
80
|
+
# fe_select('gender', [['f', 'female', { :id => 'f'} ],['m','Male', {:id=>'m'}]])
|
81
|
+
# ...simple...:
|
58
82
|
# fe_select('gender', ['f','m'])
|
59
83
|
def fe_select(name, options, attribs = {})
|
60
84
|
r = "<select name='#{name}' #{a2p(attribs)}>\n"
|
61
85
|
options.each do |o|
|
62
86
|
ov = o.instance_of?(Array) ? o[0] : o
|
87
|
+
params = o[2].inject('') { |m,(k,v)| m << " #{k}='#{v}'" } rescue ''
|
63
88
|
sel = ''
|
64
|
-
sel = ' selected' if
|
89
|
+
sel = ' selected' if get_value(name, attribs).to_s == ov.to_s
|
65
90
|
if o.instance_of?(Array) then
|
66
|
-
r+="<option value='#{o[0]}'#{sel}>#{o[1]}</option>\n"
|
91
|
+
r+="<option value='#{o[0]}'#{sel}#{params}>#{o[1]}</option>\n"
|
67
92
|
else
|
68
|
-
r+="<option value='#{o}'#{sel}>#{o}</option>\n"
|
93
|
+
r+="<option value='#{o}'#{sel}#{params}>#{o}</option>\n"
|
69
94
|
end
|
70
95
|
end
|
71
96
|
r+="</select>\n"
|
@@ -86,8 +111,8 @@ end
|
|
86
111
|
|
87
112
|
|
88
113
|
r << "\n<select name='#{name}' #{a2p(attribs)}>\n"
|
89
|
-
r << "<option #{"selected" if
|
90
|
-
r << "<option #{"selected" if
|
114
|
+
r << "<option #{"selected" if get_value(name, attribs) == trueval} value='#{trueval}'>#{truename}</option>\n"
|
115
|
+
r << "<option #{"selected" if get_value(name, attribs) == falseval} value='#{falseval}'>#{falsename}</option>\n"
|
91
116
|
r << "</select>\n"
|
92
117
|
end
|
93
118
|
|
@@ -0,0 +1,157 @@
|
|
1
|
+
# mixin this module to build form elements
|
2
|
+
|
3
|
+
module Cuca
|
4
|
+
module FormElements
|
5
|
+
|
6
|
+
private
|
7
|
+
def a2p(attribs)
|
8
|
+
a = attribs.dup
|
9
|
+
a.delete(:default_value) # reserved attribute
|
10
|
+
a.inject([]) { |m,e| m << ((e[1].to_s != '') ? "#{e[0].to_s}='#{e[1].to_s}'" : e[0].to_s) }.join(' ')
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
def twodig(n)
|
15
|
+
n.to_s.length == 1 ? "0"+n.to_s : n.to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
# this allows to pass a :default_value to the set of attribs
|
19
|
+
private
|
20
|
+
def get_value(name, attribs)
|
21
|
+
v[name] || (attribs[:default_value] || '')
|
22
|
+
end
|
23
|
+
|
24
|
+
def fe_text(name, attribs = {})
|
25
|
+
"<input type='text' name='#{name}' value='#{get_value(name, attribs)}' #{a2p(attribs)}>\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
def fe_hidden(name, attribs = {})
|
29
|
+
"<input type='hidden' name='#{name}' value='#{get_value(name, attribs)}' #{a2p(attribs)}>\n"
|
30
|
+
end
|
31
|
+
|
32
|
+
def fe_int(name, attribs = {})
|
33
|
+
fe_text(name, attribs)
|
34
|
+
end
|
35
|
+
|
36
|
+
def fe_textarea(name, attribs = {})
|
37
|
+
a = { :rows => 5, :cols => 50 }.merge(attribs)
|
38
|
+
"<textarea name='#{name}' #{a2p(a)}>#{get_value(name, attribs)}</textarea>\n"
|
39
|
+
end
|
40
|
+
|
41
|
+
# build a form start tag
|
42
|
+
def fe_formstart(attribs = {})
|
43
|
+
form_name = attribs[:form_name] || @form_name
|
44
|
+
a = {:name=>form_name, :method=>'post', :action=>@post_to }.merge(attribs)
|
45
|
+
"<form #{a2p(a)}>\n"
|
46
|
+
end
|
47
|
+
|
48
|
+
# fe password doesn't show passwords content but default (unless :showvalue defined in attribs)
|
49
|
+
def fe_password(name, attribs = {})
|
50
|
+
v = attribs[:showvalue] ? get_value(name, attribs) : ''
|
51
|
+
attribs.delete(:showvalue)
|
52
|
+
"<input type='password' name='#{name}' value='#{v}' #{a2p(attribs)}>\n"
|
53
|
+
end
|
54
|
+
|
55
|
+
def fe_checkbox(name, attribs = {})
|
56
|
+
checker_name = "#{name}_checker"
|
57
|
+
newval = !!(request_parameters[name] || query_parameters[name])
|
58
|
+
posted = (request_parameters[checker_name] || query_parameters[checker_name])
|
59
|
+
|
60
|
+
# checkbox html element isn't sent to cgi if not selected
|
61
|
+
# so cuca's page variables won't work - this fixes it.
|
62
|
+
app.logger.info "TEST #{name} #{posted.inspect} #{newval.inspect}"
|
63
|
+
|
64
|
+
if (session.page && (posted && !newval)) then
|
65
|
+
app.logger.info "Setting OFF #{name} #{posted.inspect} #{newval.inspect}"
|
66
|
+
session.page[name] = 'off'
|
67
|
+
end
|
68
|
+
|
69
|
+
app.logger.info "Checkbox #{name} - #{get_value(name, attribs)}"
|
70
|
+
checked = v[name] != 'off'
|
71
|
+
|
72
|
+
checkedval = checked ? ' CHECKED' : ''
|
73
|
+
"<input type='checkbox' name='#{name}' #{a2p(attribs)}#{checkedval}>\n"
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
|
78
|
+
# this is to build a select box, example:
|
79
|
+
# fe_select('gender', [['f', 'female'],['m','Male']]) or
|
80
|
+
# fe_select('gender', ['f','m'])
|
81
|
+
def fe_select(name, options, attribs = {})
|
82
|
+
r = "<select name='#{name}' #{a2p(attribs)}>\n"
|
83
|
+
options.each do |o|
|
84
|
+
ov = o.instance_of?(Array) ? o[0] : o
|
85
|
+
sel = ''
|
86
|
+
sel = ' selected' if get_value(name, attribs).to_s == ov.to_s
|
87
|
+
if o.instance_of?(Array) then
|
88
|
+
r+="<option value='#{o[0]}'#{sel}>#{o[1]}</option>\n"
|
89
|
+
else
|
90
|
+
r+="<option value='#{o}'#{sel}>#{o}</option>\n"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
r+="</select>\n"
|
94
|
+
end
|
95
|
+
|
96
|
+
def fe_bool(name,attribs = {})
|
97
|
+
r = ''
|
98
|
+
attribs = attribs.dup
|
99
|
+
truename = attribs[:true] || 'true'
|
100
|
+
falsename = attribs[:false] || 'false'
|
101
|
+
trueval = attribs.has_key?(:trueval) ? attribs[:trueval] : 't'
|
102
|
+
falseval = attribs.has_key?(:falseval) ? attribs[:falseval] : 'f'
|
103
|
+
$stderr.puts "#{name}: #{v[name].inspect} #{trueval.inspect} #{falseval.inspect}"
|
104
|
+
attribs.delete(:true)
|
105
|
+
attribs.delete(:false)
|
106
|
+
attribs.delete(:trueval)
|
107
|
+
attribs.delete(:falseval)
|
108
|
+
|
109
|
+
|
110
|
+
r << "\n<select name='#{name}' #{a2p(attribs)}>\n"
|
111
|
+
r << "<option #{"selected" if get_value(name, attribs) == trueval} value='#{trueval}'>#{truename}</option>\n"
|
112
|
+
r << "<option #{"selected" if get_value(name, attribs) == falseval} value='#{falseval}'>#{falsename}</option>\n"
|
113
|
+
r << "</select>\n"
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
def fe_submit(attribs = {})
|
118
|
+
a = { :value => 'Submit', :name=>@submit_name }.merge(attribs)
|
119
|
+
"<input type='submit' #{a2p(a)}>\n"
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
def fe_formend
|
124
|
+
"</form>\n"
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
def fe_datetime(name, attribs = {})
|
129
|
+
require 'date'
|
130
|
+
begin
|
131
|
+
val = v[name].instance_of?(Time) ? v[name] : DateTime.parse(v[name] || 'now')
|
132
|
+
rescue ArgumentError
|
133
|
+
val = DateTime.now
|
134
|
+
end
|
135
|
+
value = "#{val.year}/#{twodig(val.month)}/#{twodig(val.day)} #{val.hour}:#{val.min}"
|
136
|
+
"<input type='text' name='#{name}' value='#{value}' #{a2p(attribs)}>\n"
|
137
|
+
end
|
138
|
+
|
139
|
+
def fe_date(name, attribs = {})
|
140
|
+
require 'date'
|
141
|
+
if v[name].instance_of?(Date) then
|
142
|
+
value = "#{v[name].year}/#{twodig(v[name].month)}/#{twodig(v[name].day)}"
|
143
|
+
end
|
144
|
+
if v[name].nil? || (v[name].instance_of?(String) && v[name].empty?) then
|
145
|
+
value = ''
|
146
|
+
end
|
147
|
+
if value.nil? then
|
148
|
+
val = Date.today
|
149
|
+
value = "#{val.year}/#{twodig(val.month)}/#{twodig(val.day)}"
|
150
|
+
end
|
151
|
+
|
152
|
+
"<input type='text' name='#{name}' value='#{value}' #{a2p(attribs)}> (yyyy/mm/dd)\n"
|
153
|
+
end
|
154
|
+
|
155
|
+
|
156
|
+
end
|
157
|
+
end
|