cuca 0.06 → 0.07
Sign up to get free protection for your applications and to get access to all the features.
- 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
|