ezframe 0.0.1 → 0.0.3
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +11 -4
- data/app_template/asset/image/favicon.ico +0 -0
- data/app_template/asset/js/ezframe.js +288 -0
- data/app_template/config/generic.yml +3 -0
- data/app_template/config/materialize.yml +5 -0
- data/{example/chat → app_template}/config.ru +2 -10
- data/app_template/pages/basic.rb +5 -0
- data/exe/create_table.rb +1 -0
- data/exe/setup.rb +15 -0
- data/ezframe.gemspec +3 -4
- data/lib/ezframe/auth.rb +15 -12
- data/lib/ezframe/column_set.rb +68 -28
- data/lib/ezframe/column_type.rb +231 -68
- data/lib/ezframe/config.rb +4 -0
- data/lib/ezframe/controller.rb +20 -10
- data/lib/ezframe/database.rb +10 -3
- data/lib/ezframe/ht.rb +167 -0
- data/lib/ezframe/html.rb +28 -4
- data/lib/ezframe/japanese_utils.rb +40 -0
- data/lib/ezframe/{pages.rb → loader.rb} +3 -0
- data/lib/ezframe/materialize.rb +55 -20
- data/lib/ezframe/model.rb +0 -2
- data/lib/ezframe/page_base.rb +18 -12
- data/lib/ezframe/page_kit.rb +12 -33
- data/lib/ezframe/template.rb +20 -15
- data/lib/ezframe/util.rb +5 -0
- data/lib/ezframe/version.rb +1 -1
- data/lib/ezframe.rb +5 -4
- metadata +27 -70
- data/example/auth/Gemfile +0 -8
- data/example/auth/asset/css/materialize.min.css +0 -13
- data/example/auth/asset/js/common.js +0 -200
- data/example/auth/asset/js/htmlgen.js +0 -79
- data/example/auth/columns/user.yml +0 -12
- data/example/auth/config/view_conf.yml +0 -3
- data/example/auth/config.ru +0 -26
- data/example/auth/pages/app.rb +0 -61
- data/example/auth/template/base.html +0 -12
- data/example/chat/Gemfile +0 -9
- data/example/chat/asset/css/materialize.min.css +0 -13
- data/example/chat/asset/js/common.js +0 -200
- data/example/chat/asset/js/htmlgen.js +0 -79
- data/example/chat/columns/belong.yml +0 -6
- data/example/chat/columns/channel.yml +0 -3
- data/example/chat/columns/talk.yml +0 -6
- data/example/chat/columns/user.yml +0 -12
- data/example/chat/config/view_conf.yml +0 -3
- data/example/chat/pages/app.rb +0 -59
- data/example/chat/template/base.html +0 -12
- data/example/todo/Gemfile +0 -8
- data/example/todo/asset/css/datatable.css +0 -54
- data/example/todo/asset/css/materialize.min.css +0 -13
- data/example/todo/asset/js/common.js +0 -135
- data/example/todo/asset/js/datatable.js +0 -1814
- data/example/todo/asset/js/htmlgen.js +0 -79
- data/example/todo/asset/js/init.js +0 -3
- data/example/todo/asset/js/materialize.min.js +0 -6
- data/example/todo/asset/js/mydatatable.js +0 -9
- data/example/todo/asset/js/mymaterialize.js +0 -22
- data/example/todo/columns/todo.yml +0 -9
- data/example/todo/config/view_conf.yml +0 -3
- data/example/todo/config.ru +0 -15
- data/example/todo/pages/app.rb +0 -93
- data/example/todo/template/base.html +0 -12
- data/exe/myrackup +0 -5
- data/lib/ezframe/hthash.rb +0 -116
data/lib/ezframe/column_type.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require "date"
|
2
3
|
|
3
4
|
module Ezframe
|
4
5
|
class TypeBase
|
5
|
-
attr_accessor :attribute, :parent
|
6
|
-
attr_writer :value
|
6
|
+
attr_accessor :attribute, :parent, :error
|
7
7
|
|
8
8
|
def self.get_class(key)
|
9
9
|
return nil unless key
|
@@ -25,13 +25,13 @@ module Ezframe
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def initialize(attr = nil)
|
28
|
-
@attribute = attr
|
28
|
+
@attribute = attr || {}
|
29
29
|
end
|
30
30
|
|
31
31
|
def key
|
32
|
-
@attribute[:key]
|
33
|
-
end
|
34
|
-
|
32
|
+
@attribute[:key]
|
33
|
+
end
|
34
|
+
|
35
35
|
def label
|
36
36
|
return nil if @attribute[:hidden]
|
37
37
|
@attribute[:label]
|
@@ -41,8 +41,8 @@ module Ezframe
|
|
41
41
|
@value
|
42
42
|
end
|
43
43
|
|
44
|
-
def
|
45
|
-
@value
|
44
|
+
def value=(v)
|
45
|
+
@value = v
|
46
46
|
end
|
47
47
|
|
48
48
|
def db_type
|
@@ -53,134 +53,295 @@ module Ezframe
|
|
53
53
|
value
|
54
54
|
end
|
55
55
|
|
56
|
-
def form
|
56
|
+
def form(opts = {})
|
57
57
|
nil
|
58
58
|
end
|
59
|
+
|
60
|
+
def form_html(opts = {})
|
61
|
+
form_h = form(opts)
|
62
|
+
return nil unless form_h
|
63
|
+
return Html.convert(form_h)
|
64
|
+
end
|
65
|
+
|
66
|
+
def view(opts = {})
|
67
|
+
return nil if no_view?
|
68
|
+
@value
|
69
|
+
end
|
70
|
+
|
71
|
+
def validate
|
72
|
+
if !@value || @value.empty?
|
73
|
+
if @attribute[:must]
|
74
|
+
@error = "必須項目です。"
|
75
|
+
return @error
|
76
|
+
end
|
77
|
+
end
|
78
|
+
return nil
|
79
|
+
end
|
80
|
+
|
81
|
+
def no_edit?
|
82
|
+
return ((@attribute[:hidden] || @attribute[:no_edit]) && !@attribute[:force])
|
83
|
+
end
|
84
|
+
|
85
|
+
def no_view?
|
86
|
+
return (@attribute[:hidden] && !@attribute[:force])
|
87
|
+
end
|
59
88
|
end
|
60
89
|
|
61
|
-
class
|
90
|
+
class TextType < TypeBase
|
62
91
|
def normalize
|
63
|
-
@value
|
92
|
+
return unless @value
|
93
|
+
@value = @value.to_s
|
94
|
+
@value.gsub!(/ /, " ")
|
95
|
+
@value.gsub!(/\s+/, " ")
|
96
|
+
@value.strip!
|
64
97
|
end
|
65
98
|
|
66
|
-
def
|
67
|
-
|
68
|
-
|
99
|
+
def value=(v)
|
100
|
+
super(v)
|
101
|
+
normalize
|
102
|
+
end
|
103
|
+
|
104
|
+
def form(opts = {})
|
105
|
+
return nil if no_edit? && !opts[:force]
|
106
|
+
h = { tag: "input", type: "text", name: @attribute[:key], key: @attribute[:key], label: @attribute[:label], value: @value || "" }
|
107
|
+
h[:size] = @attribute[:size] if @attribute[:size]
|
108
|
+
h
|
69
109
|
end
|
70
110
|
|
71
111
|
def db_type
|
72
|
-
"
|
112
|
+
"text"
|
73
113
|
end
|
74
114
|
end
|
75
115
|
|
76
|
-
class IntType <
|
77
|
-
def view
|
78
|
-
return nil if
|
79
|
-
Util.add_comma(@value.to_i)
|
116
|
+
class IntType < TextType
|
117
|
+
def view(opts = {})
|
118
|
+
return nil if no_view? && !opts[:force]
|
119
|
+
return Util.add_comma(@value.to_i)
|
80
120
|
end
|
81
121
|
|
82
|
-
def
|
83
|
-
|
84
|
-
|
122
|
+
def value=(v)
|
123
|
+
if v.nil?
|
124
|
+
@value = nil
|
125
|
+
return
|
126
|
+
end
|
127
|
+
if v.is_a?(String)
|
128
|
+
v = v.tr("0-9", "0-9").strip
|
129
|
+
end
|
130
|
+
@value = v.to_i
|
131
|
+
end
|
132
|
+
|
133
|
+
def form(opts = {})
|
134
|
+
return nil if no_edit? && !opts[:force]
|
135
|
+
{ tag: "input", type: "number", key: @attribute[:key], label: @attribute[:label], value: @value || "" }
|
85
136
|
end
|
86
137
|
|
87
138
|
def db_type
|
88
139
|
"int"
|
89
140
|
end
|
141
|
+
|
142
|
+
|
90
143
|
end
|
91
144
|
|
92
145
|
class ForeignType < IntType
|
93
|
-
def view
|
146
|
+
def view(opts = {})
|
147
|
+
return nil if no_view? && !opts[:force]
|
94
148
|
dataset = @parent.db.dataset[self.type.inner]
|
95
149
|
data = dataset.get(id: @value)
|
96
|
-
data[@attribute[:view]]
|
150
|
+
return data[@attribute[:view]]
|
151
|
+
end
|
152
|
+
|
153
|
+
def form
|
154
|
+
return nil
|
97
155
|
end
|
98
156
|
end
|
99
|
-
|
157
|
+
|
100
158
|
class IdType < IntType
|
101
159
|
def label
|
102
|
-
return nil if
|
103
|
-
"ID"
|
160
|
+
return nil if no_view?
|
161
|
+
return "ID"
|
162
|
+
end
|
163
|
+
|
164
|
+
def form(opts = {})
|
165
|
+
return nil
|
104
166
|
end
|
105
167
|
end
|
106
168
|
|
107
|
-
class PasswordType <
|
108
|
-
def form
|
109
|
-
|
169
|
+
class PasswordType < TextType
|
170
|
+
def form(opts = {})
|
171
|
+
return nil if no_edit? && !opts[:force]
|
172
|
+
return { tag: "input", type: "password", label: @attribute[:label], value: @value || "" }
|
110
173
|
end
|
111
174
|
|
112
175
|
def db_value
|
113
|
-
value
|
176
|
+
return value
|
114
177
|
end
|
115
178
|
end
|
116
179
|
|
117
180
|
class SelectType < TypeBase
|
118
|
-
def form
|
119
|
-
return nil if
|
120
|
-
|
181
|
+
def form(opts = {})
|
182
|
+
return nil if no_edit? && !opts[:force]
|
183
|
+
# puts "selectType: #{@attribute[:items].inspect}"
|
184
|
+
return { tag: "select", key: @attribute[:key], label: @attribute[:label], items: @attribute[:items], value: @value }
|
121
185
|
end
|
122
186
|
|
123
187
|
def db_type
|
124
|
-
"
|
188
|
+
return "text"
|
125
189
|
end
|
126
190
|
end
|
127
191
|
|
128
192
|
class CheckboxType < TypeBase
|
129
|
-
def form
|
130
|
-
return nil if
|
131
|
-
{ tag: "checkbox", key: @attribute[:key], name: @attribute[:key], value: parent[:id].value, label: @attribute[:label] }
|
193
|
+
def form(opts = {})
|
194
|
+
return nil if no_edit? && !opts[:force]
|
195
|
+
return { tag: "checkbox", key: @attribute[:key], name: @attribute[:key], value: parent[:id].value, label: @attribute[:label] }
|
132
196
|
end
|
133
197
|
|
134
198
|
def db_type
|
135
|
-
"int"
|
199
|
+
return "int"
|
136
200
|
end
|
137
201
|
end
|
138
202
|
|
139
|
-
class DateType <
|
140
|
-
def form
|
203
|
+
class DateType < TextType
|
204
|
+
def form(opts = {})
|
205
|
+
return nil if no_edit? && !opts[:force]
|
141
206
|
h = super
|
142
|
-
|
143
|
-
|
207
|
+
if h
|
208
|
+
# h[:type] = 'date'
|
209
|
+
h[:type] = "text"
|
210
|
+
h[:class] = "datepicker"
|
211
|
+
h[:value] = value || ""
|
212
|
+
end
|
213
|
+
return h
|
144
214
|
end
|
145
215
|
|
146
216
|
def db_type
|
147
|
-
"
|
217
|
+
"date"
|
218
|
+
end
|
219
|
+
|
220
|
+
def value
|
221
|
+
if @value.is_a?(Date) || @value.is_a?(Time)
|
222
|
+
return "%d-%02d-%02d" % [@value.year, @value.mon, @value.mday]
|
223
|
+
end
|
224
|
+
return @value
|
225
|
+
end
|
226
|
+
|
227
|
+
def value=(v)
|
228
|
+
if v.nil?
|
229
|
+
@value = nil
|
230
|
+
return
|
231
|
+
end
|
232
|
+
if v.is_a?(String)
|
233
|
+
if v.strip.empty?
|
234
|
+
@value = nil
|
235
|
+
return
|
236
|
+
end
|
237
|
+
y, m, d = v.split(/[\-\/]/)
|
238
|
+
# puts "date=#{v.inspect}"
|
239
|
+
@value = Date.new(y.to_i, m.to_i, d.to_i)
|
240
|
+
return
|
241
|
+
end
|
242
|
+
if v.is_a?(Date) || v.is_a?(Time)
|
243
|
+
@value = v
|
244
|
+
else
|
245
|
+
mylog "[WARN] illegal value for date type: #{v.inspect}"
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
def view(opts = {})
|
250
|
+
return nil if no_view? && !opts[:force]
|
251
|
+
if @value.is_a?(Time) || @value.is_a?(Date)
|
252
|
+
return "#{@value.year}/#{@value.mon}/#{@value.mday}"
|
253
|
+
else
|
254
|
+
return @value
|
255
|
+
end
|
148
256
|
end
|
149
257
|
end
|
150
|
-
|
151
|
-
class
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
258
|
+
|
259
|
+
class TimeType < TextType
|
260
|
+
end
|
261
|
+
|
262
|
+
class DatetimeType < DateType
|
263
|
+
def db_type
|
264
|
+
"timestamp"
|
156
265
|
end
|
157
266
|
end
|
158
267
|
|
159
|
-
class
|
160
|
-
def form
|
268
|
+
class BirthdayType < DateType
|
269
|
+
def form(opts = {})
|
270
|
+
return nil if no_edit? && !opts[:force]
|
271
|
+
prefix = @attribute[:key]
|
272
|
+
now = Time.now
|
273
|
+
year_list = []
|
274
|
+
110.times do |y|
|
275
|
+
year = now.year - y - 10
|
276
|
+
year_list.push [year, "#{year}年 (#{Japanese.convert_wareki(year)})"]
|
277
|
+
end
|
278
|
+
mon_list = (1..12).map { |m| [m, "#{m}月"] }
|
279
|
+
mon_list.unshift([0, "(月)"])
|
280
|
+
mday_list = (1..31).map { |d| [d, "#{d}日"] }
|
281
|
+
mday_list.unshift([0, "(日)"])
|
282
|
+
return [Ht.select(name: "#{prefix}_year", items: year_list),
|
283
|
+
Ht.select(name: "#{prefix}_mon", items: mon_list),
|
284
|
+
Ht.select(name: "#{prefix}_mday", items: mday_list)]
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
class EmailType < TextType
|
289
|
+
def form(opts = {})
|
290
|
+
return nil if no_edit? && !opts[:force]
|
161
291
|
h = super
|
162
|
-
h[:type] =
|
163
|
-
h
|
292
|
+
h[:type] = "email" if h
|
293
|
+
return h
|
294
|
+
end
|
295
|
+
|
296
|
+
def normalize
|
297
|
+
return unless @value
|
298
|
+
@value = NKF.nkf('-w -Z4', @value)
|
299
|
+
end
|
300
|
+
|
301
|
+
def validate
|
302
|
+
super
|
303
|
+
return @error if @error
|
304
|
+
if email_format?
|
305
|
+
@error = "形式が正しくありません"
|
306
|
+
return @error
|
307
|
+
end
|
308
|
+
return nil
|
309
|
+
end
|
310
|
+
|
311
|
+
def email_format?
|
312
|
+
return nil unless @value
|
313
|
+
return @value =~ /^[a-zA-Z0-9.!\#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
|
164
314
|
end
|
165
315
|
end
|
166
316
|
|
167
|
-
class
|
317
|
+
class TelType < TextType
|
318
|
+
def validate
|
319
|
+
super
|
320
|
+
return @error if @error
|
321
|
+
unless /^0\d{9,10}$/ =~ @value
|
322
|
+
@error = "形式が正しくありません"
|
323
|
+
return @error
|
324
|
+
end
|
325
|
+
end
|
168
326
|
end
|
169
327
|
|
170
|
-
class
|
171
|
-
|
172
|
-
|
173
|
-
|
328
|
+
class JpnameType < TextType
|
329
|
+
end
|
330
|
+
|
331
|
+
class JpnameKanaType < TextType
|
332
|
+
def normalize
|
333
|
+
return unless @value
|
334
|
+
super
|
335
|
+
@value.tr!("ァ-ン", "ぁ-ん")
|
174
336
|
end
|
175
337
|
|
176
338
|
def validation
|
177
339
|
unless /^[ぁ-ん ]+$/ =~ @value
|
178
|
-
|
340
|
+
"ひらがなのみで入力してください。"
|
179
341
|
end
|
180
342
|
end
|
181
343
|
end
|
182
344
|
|
183
|
-
#
|
184
345
|
class PrefectureType < SelectType
|
185
346
|
def initialize(attr)
|
186
347
|
super(attr)
|
@@ -195,26 +356,28 @@ module Ezframe
|
|
195
356
|
@pref_a.each_with_index { |p, i| @pref_h[i] = p }
|
196
357
|
end
|
197
358
|
|
198
|
-
def form
|
359
|
+
def form(opts = {})
|
360
|
+
return nil if no_edit? && !opts[:force]
|
199
361
|
h = super
|
200
362
|
h[:items] = @pref_h
|
201
|
-
h
|
363
|
+
return h
|
202
364
|
end
|
203
365
|
|
204
366
|
def view
|
205
|
-
@pref_h[@value.to_i]
|
367
|
+
return @pref_h[@value.to_i]
|
206
368
|
end
|
207
369
|
end
|
208
370
|
|
209
371
|
# Japanese Zipcode type column
|
210
|
-
class ZipcodeType <
|
211
|
-
def view
|
372
|
+
class ZipcodeType < TextType
|
373
|
+
def view(opts = {})
|
374
|
+
return nil if no_view? && !opts[:force]
|
212
375
|
return "" unless @value
|
213
|
-
@value.to_s.gsub(/(\d{3})(\d{4})/) { "#{$1}-#{$2}" }
|
376
|
+
return @value.to_s.gsub(/(\d{3})(\d{4})/) { "#{$1}-#{$2}" }
|
214
377
|
end
|
215
378
|
|
216
379
|
def db_type
|
217
|
-
"
|
380
|
+
return "text"
|
218
381
|
end
|
219
382
|
end
|
220
383
|
end
|
data/lib/ezframe/config.rb
CHANGED
data/lib/ezframe/controller.rb
CHANGED
@@ -9,22 +9,33 @@ module Ezframe
|
|
9
9
|
Model.init
|
10
10
|
model = Model.get_clone
|
11
11
|
Auth.init_warden
|
12
|
-
|
12
|
+
@request.env["model"] = model
|
13
|
+
# Auth.model = model
|
13
14
|
|
14
15
|
mylog("exec: path=#{request.path_info} params=#{request.params}")
|
15
16
|
klass, method = PageBase::decide_route(request.path_info)
|
16
|
-
|
17
|
+
unless klass
|
18
|
+
response.status = 404
|
19
|
+
response['Content-Type'] = 'text/html; charset=utf-8'
|
20
|
+
response.body = [ Html.convert(Ht.p("file not found")) ]
|
21
|
+
return
|
22
|
+
end
|
23
|
+
method = "default" if !method || method=="undefined"
|
17
24
|
page = klass.new(request, model)
|
18
25
|
if request.post?
|
19
26
|
method_full_name = "public_#{method}_post"
|
20
27
|
else
|
21
28
|
method_full_name = "public_#{method}_page"
|
22
29
|
end
|
23
|
-
|
30
|
+
if page.auth
|
31
|
+
warden.authenticate!
|
32
|
+
end
|
24
33
|
# request.env["rack.session"]["kamatest"]="usable"
|
25
|
-
mylog "method: #{klass}.#{method_full_name}"
|
26
|
-
mylog "rack.session.id=#{request.env['rack.session'].id}"
|
34
|
+
# mylog "method: #{klass}.#{method_full_name}"
|
35
|
+
#mylog "rack.session.id=#{request.env['rack.session'].id}"
|
27
36
|
mylog "rack.session.keys=#{request.env['rack.session'].keys}"
|
37
|
+
#mylog "warden=#{request.env['warden'].inspect}"
|
38
|
+
mylog "klass=#{klass}, method=#{method_full_name}"
|
28
39
|
body = if page.respond_to?(method_full_name)
|
29
40
|
page.send(method_full_name)
|
30
41
|
else
|
@@ -41,11 +52,10 @@ module Ezframe
|
|
41
52
|
response.status = 200
|
42
53
|
end
|
43
54
|
|
44
|
-
|
45
|
-
|
46
|
-
response.
|
47
|
-
|
48
|
-
end
|
55
|
+
# def file_not_found(response)
|
56
|
+
# response.body = ['path not found']
|
57
|
+
# response.status = 404
|
58
|
+
# end
|
49
59
|
|
50
60
|
def warden
|
51
61
|
@request.env["warden"]
|
data/lib/ezframe/database.rb
CHANGED
@@ -5,13 +5,15 @@ module Ezframe
|
|
5
5
|
class Database
|
6
6
|
attr_accessor :sequel
|
7
7
|
|
8
|
-
def initialize(dbfile =
|
8
|
+
def initialize(dbfile = nil)
|
9
9
|
@dbfile = dbfile
|
10
10
|
connect
|
11
11
|
end
|
12
12
|
|
13
13
|
def connect
|
14
|
-
@
|
14
|
+
@dbfile ||= ENV["EZFRAME_DB"] || Config[:database] || "sqlite://db/devel.sqlite"
|
15
|
+
puts "Database.connect: dbfile=#{@dbfile}"
|
16
|
+
@sequel = Sequel.connect(@dbfile, loggers: [Logger.new($stdout)])
|
15
17
|
end
|
16
18
|
|
17
19
|
def exec(sql)
|
@@ -26,8 +28,13 @@ module Ezframe
|
|
26
28
|
%w[id created_at updated_at].each do |key|
|
27
29
|
dbtype_h.delete(key.to_sym)
|
28
30
|
end
|
31
|
+
puts "create_table: #{table_name}"
|
29
32
|
@sequel.create_table(table_name) do
|
30
|
-
|
33
|
+
# if @dbfile.index("postgresql")
|
34
|
+
serial :id
|
35
|
+
# else
|
36
|
+
#primary_key :id, auto_increment: true
|
37
|
+
#end
|
31
38
|
dbtype_h.each do |key, dbtype|
|
32
39
|
column(key, dbtype)
|
33
40
|
end
|
data/lib/ezframe/ht.rb
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
# HTMLを中間表現としてのハッシュであるhthashを生成するためのクラス
|
2
|
+
module Ezframe
|
3
|
+
module Ht
|
4
|
+
class << self
|
5
|
+
# メソッド名の名前のタグのhthashを生成
|
6
|
+
def wrap_tag(opts = {})
|
7
|
+
if opts.is_a?(String) || opts.is_a?(Array)
|
8
|
+
h = { child: opts }
|
9
|
+
elsif opts.is_a?(Hash)
|
10
|
+
if opts[:tag] && !__callee__.to_s.index("wrap_tag")
|
11
|
+
h = { child: opts }
|
12
|
+
else
|
13
|
+
h = opts.dup
|
14
|
+
end
|
15
|
+
else
|
16
|
+
mylog("wrap_tag: unknown type: #{opts.inspect}")
|
17
|
+
return nil
|
18
|
+
end
|
19
|
+
h[:tag] ||= __callee__.to_s
|
20
|
+
raise "no tag" if h[:tag] == "wrap_tag"
|
21
|
+
return h
|
22
|
+
end
|
23
|
+
|
24
|
+
alias_method :script, :wrap_tag
|
25
|
+
|
26
|
+
alias_method :h1, :wrap_tag
|
27
|
+
alias_method :h2, :wrap_tag
|
28
|
+
alias_method :h3, :wrap_tag
|
29
|
+
alias_method :h4, :wrap_tag
|
30
|
+
alias_method :h5, :wrap_tag
|
31
|
+
alias_method :h6, :wrap_tag
|
32
|
+
alias_method :p, :wrap_tag
|
33
|
+
alias_method :br, :wrap_tag
|
34
|
+
alias_method :hr, :wrap_tag
|
35
|
+
alias_method :div, :wrap_tag
|
36
|
+
alias_method :span, :wrap_tag
|
37
|
+
alias_method :i, :wrap_tag
|
38
|
+
alias_method :strong, :wrap_tag
|
39
|
+
alias_method :ul, :wrap_tag
|
40
|
+
alias_method :ol, :wrap_tag
|
41
|
+
alias_method :li, :wrap_tag
|
42
|
+
alias_method :table, :wrap_tag
|
43
|
+
alias_method :thead, :wrap_tag
|
44
|
+
alias_method :tbody, :wrap_tag
|
45
|
+
alias_method :tr, :wrap_tag
|
46
|
+
alias_method :th, :wrap_tag
|
47
|
+
alias_method :td, :wrap_tag
|
48
|
+
alias_method :img, :wrap_tag
|
49
|
+
alias_method :a, :wrap_tag
|
50
|
+
alias_method :form, :wrap_tag
|
51
|
+
alias_method :input, :wrap_tag
|
52
|
+
alias_method :select, :wrap_tag
|
53
|
+
alias_method :textarea, :wrap_tag
|
54
|
+
alias_method :label, :wrap_tag
|
55
|
+
alias_method :fieldset, :wrap_tag
|
56
|
+
alias_method :nav, :wrap_tag
|
57
|
+
alias_method :footer, :wrap_tag
|
58
|
+
|
59
|
+
alias_method :small, :wrap_tag
|
60
|
+
|
61
|
+
alias_method :checkbox, :wrap_tag
|
62
|
+
alias_method :radio, :wrap_tag
|
63
|
+
|
64
|
+
# materialize用のiconメソッド
|
65
|
+
# 引数が文字列だったら、それをname属性とする
|
66
|
+
def icon(arg)
|
67
|
+
if arg.is_a?(Hash)
|
68
|
+
h = arg.clone
|
69
|
+
h[:tag] = "icon"
|
70
|
+
return wrap_tag(h)
|
71
|
+
elsif arg.is_a?(String)
|
72
|
+
return { tag: "icon", name: arg }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# buttonタグにはデフォルトでtype=button属性を付ける
|
77
|
+
def button(arg)
|
78
|
+
arg[:tag] = "button"
|
79
|
+
unless arg[:type]
|
80
|
+
arg[:type] = "button"
|
81
|
+
end
|
82
|
+
wrap_tag(arg)
|
83
|
+
end
|
84
|
+
|
85
|
+
def multi_div(class_a, child)
|
86
|
+
class_a.reverse.each do |klass|
|
87
|
+
child = Ht.div(class: klass, child: child)
|
88
|
+
end
|
89
|
+
return child
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# 配列を<UL><OL>要素に変換するためのクラス
|
94
|
+
class List < Array
|
95
|
+
attr_accessor :tag
|
96
|
+
def to_h(opts = {})
|
97
|
+
return nil if self.empty?
|
98
|
+
child = self.map do |elem|
|
99
|
+
{ tag: "li", child: elem }
|
100
|
+
end
|
101
|
+
h = { tag: @tag, child: child }
|
102
|
+
h.update(opts)
|
103
|
+
return h
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# 配列を<UL>要素に変換するためのクラス
|
108
|
+
class Ul < List
|
109
|
+
def to_h(opts = {})
|
110
|
+
@tag = "ul"
|
111
|
+
return super(opts)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# 配列を<OL>要素に変換するためのクラス
|
116
|
+
class Ol < List
|
117
|
+
def to_h(opts = {})
|
118
|
+
@tag = "ol"
|
119
|
+
return super(opts)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# テーブルを生成するためのクラス
|
124
|
+
# @matrix ... テーブルの内容となる二次元配列
|
125
|
+
# @header ... テーブルの先頭に付ける項目名の配列
|
126
|
+
# @class_a ... <table><tr><td>の各ノードにそれぞれ設定したいclass属性を配列として定義
|
127
|
+
class Table
|
128
|
+
attr_accessor :class_a, :header, :matrix
|
129
|
+
|
130
|
+
def initialize(matrix = nil)
|
131
|
+
set(matrix) if matrix
|
132
|
+
@matrix ||= []
|
133
|
+
end
|
134
|
+
|
135
|
+
def set(matrix)
|
136
|
+
@matrix = matrix
|
137
|
+
end
|
138
|
+
|
139
|
+
def add_row(row)
|
140
|
+
@matrix.push(row)
|
141
|
+
end
|
142
|
+
|
143
|
+
def to_h
|
144
|
+
table_class, tr_class, td_class = @class_a
|
145
|
+
max_col = 0
|
146
|
+
@matrix.each { |row| max_col = row.length if max_col < row.length }
|
147
|
+
tr_a = @matrix.map do |row|
|
148
|
+
add_attr = nil
|
149
|
+
add_attr = { colspan: max_col - row.length + 1 } if row.length < max_col
|
150
|
+
td_a = row.map do |v|
|
151
|
+
td = Ht.td(child: v)
|
152
|
+
td.add_class(td_class) if td_class
|
153
|
+
td
|
154
|
+
end
|
155
|
+
td_a[0].update(add_attr) if add_attr
|
156
|
+
tr = Ht.tr(class: tr_class, child: td_a)
|
157
|
+
tr.add_class(tr_class) if tr_class
|
158
|
+
tr
|
159
|
+
end
|
160
|
+
tr_a.unshift( Ht.thead(child: Ht.tr(child: @header.map {|v| Ht.th(child: v) }) )) if @header
|
161
|
+
tb = Ht.table(child: tr_a)
|
162
|
+
tb.add_class(table_class) if table_class
|
163
|
+
tb
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|