kiss 1.7.4 → 1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/bin/kiss +1 -1
- data/data/scaffold.tgz +0 -0
- data/lib/kiss/action.rb +1 -1
- data/lib/kiss/ext/core.rb +1 -1
- data/lib/kiss/form/field.rb +527 -110
- data/lib/kiss/form.rb +165 -88
- data/lib/kiss.rb +3 -3
- metadata +3 -5
- data/lib/kiss/form/field_types.rb +0 -239
data/lib/kiss/form.rb
CHANGED
@@ -36,29 +36,70 @@ end
|
|
36
36
|
|
37
37
|
class Kiss
|
38
38
|
class Form
|
39
|
+
class Column
|
40
|
+
_attr_accessor :form, :components
|
41
|
+
def initialize(form = nil)
|
42
|
+
@_form = form
|
43
|
+
@_components = []
|
44
|
+
end
|
45
|
+
|
46
|
+
# Renders HTML for form fields.
|
47
|
+
def components_html
|
48
|
+
@_components.map do |component|
|
49
|
+
form.component_html(component)
|
50
|
+
end.join
|
51
|
+
end
|
52
|
+
alias_method :fields_html, :components_html
|
53
|
+
|
54
|
+
# Renders open of form table.
|
55
|
+
def table_html_open
|
56
|
+
%Q(<table class="kiss_form_column" border=0 cellspacing=0><tbody>)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Renders close of form table.
|
60
|
+
def table_html_close
|
61
|
+
'</tbody></table>'
|
62
|
+
end
|
63
|
+
|
64
|
+
def html
|
65
|
+
[
|
66
|
+
'<td class="kiss_form_column">',
|
67
|
+
table_html_open,
|
68
|
+
components_html,
|
69
|
+
table_html_close,
|
70
|
+
'</td>'
|
71
|
+
].join
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class Section
|
76
|
+
_attr_accessor :form, :columns, :current_columns
|
77
|
+
def initialize(form = nil)
|
78
|
+
@_form = form
|
79
|
+
@_columns = [Column.new(form)]
|
80
|
+
end
|
81
|
+
|
82
|
+
def html
|
83
|
+
[
|
84
|
+
'<tr><td>',
|
85
|
+
'<table class="kiss_form_section"><tbody><tr>',
|
86
|
+
columns.map {|column| column.html}.join,
|
87
|
+
'</tr></tbody></table>',
|
88
|
+
'</td></tr>',
|
89
|
+
].join
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
39
93
|
_attr_accessor :fields, :params, :submitted, :has_field_errors, :has_required_fields,
|
40
|
-
:delegate, :controller, :components, :form, :new_object_index
|
94
|
+
:delegate, :controller, :components, :form, :new_object_index, :sections,
|
95
|
+
:current_section, :current_columns
|
41
96
|
dsl_accessor :name, :url, :action, :method, :enctype, :errors, :cancel, :mark_required,
|
42
97
|
:id, :class, :style, :html, :error_class, :field_error_class, :objects_save_order,
|
43
98
|
:object, :prepend_html, :append_html, :year, :timezone
|
44
|
-
|
45
|
-
@@component_types = {
|
46
|
-
:text => TextField,
|
47
|
-
:hidden => HiddenField,
|
48
|
-
:textarea => TextAreaField,
|
49
|
-
:password => PasswordField,
|
50
|
-
:boolean => BooleanField,
|
51
|
-
:file => FileField,
|
52
|
-
:select => SelectField,
|
53
|
-
:radio => RadioField,
|
54
|
-
:checkbox => CheckboxField,
|
55
|
-
:multiselect => MultiSelectField,
|
56
|
-
:submit => SubmitField
|
57
|
-
}
|
58
99
|
|
59
100
|
# Create DSL methods for component types
|
60
101
|
self.class_eval(
|
61
|
-
|
102
|
+
COMPONENT_TYPES.keys.map do |type|
|
62
103
|
"def #{type}(*args, &block); add_component(:#{type}, *args, &block); end; "
|
63
104
|
end.join
|
64
105
|
)
|
@@ -94,6 +135,10 @@ class Kiss
|
|
94
135
|
|
95
136
|
@_method ||= 'post'
|
96
137
|
|
138
|
+
@_sections = [Section.new(self)]
|
139
|
+
@_current_section = @_sections.first
|
140
|
+
@_current_column = @_current_section.columns.first
|
141
|
+
|
97
142
|
@_components = []
|
98
143
|
@_fields = Hashay.new
|
99
144
|
@_object_fields = {}
|
@@ -136,6 +181,17 @@ class Kiss
|
|
136
181
|
end
|
137
182
|
end
|
138
183
|
|
184
|
+
def column_break
|
185
|
+
@_current_column = Column.new(self)
|
186
|
+
@_current_section.columns << @_current_column
|
187
|
+
end
|
188
|
+
|
189
|
+
def section_break
|
190
|
+
@_current_section = Section.new(self)
|
191
|
+
@_current_column = @_current_section.columns.first
|
192
|
+
@_sections << @_current_section
|
193
|
+
end
|
194
|
+
|
139
195
|
# Creates and adds a field to the form, according to specified attributes.
|
140
196
|
def add_field(attrs = {}, &block)
|
141
197
|
attrs = @_with.merge(attrs) if @_with
|
@@ -145,12 +201,11 @@ class Kiss
|
|
145
201
|
name = @_field_name_prefix + name unless @_field_name_prefix.empty?
|
146
202
|
|
147
203
|
type = attrs[:type] ? attrs[:type].to_sym : :text
|
148
|
-
raise "invalid field type '#{type}'" unless
|
204
|
+
raise "invalid field type '#{type}'" unless COMPONENT_TYPES.has_key?(type)
|
149
205
|
|
150
|
-
field =
|
206
|
+
field = COMPONENT_TYPES[type].new(self, attrs.merge(
|
151
207
|
:name => name,
|
152
|
-
:key => key
|
153
|
-
:type => type
|
208
|
+
:key => key
|
154
209
|
), &block)
|
155
210
|
|
156
211
|
field.object = @_object if @_object && !field.object
|
@@ -169,15 +224,9 @@ class Kiss
|
|
169
224
|
|
170
225
|
@_fields[name] = field
|
171
226
|
@_components << field
|
227
|
+
@_current_column.components << field
|
172
228
|
|
173
|
-
|
174
|
-
other_field = field.other_field
|
175
|
-
break unless other_field
|
176
|
-
other_field.form = self
|
177
|
-
@_other_field = @_form.create_field( { :name => @_name + '.other' }.merge(@_other) )
|
178
|
-
end
|
179
|
-
|
180
|
-
@_enctype = 'multipart/form-data' if field.type == :file
|
229
|
+
@_enctype = 'multipart/form-data' if field.is_a?(FileField)
|
181
230
|
|
182
231
|
field
|
183
232
|
end
|
@@ -197,7 +246,7 @@ class Kiss
|
|
197
246
|
attrs.merge!(args.pop) if args.last.is_a?(Hash)
|
198
247
|
attrs[:options] = args if args.size > 0
|
199
248
|
attrs = @_with.merge(attrs) if @_with
|
200
|
-
@_submit =
|
249
|
+
@_submit = COMPONENT_TYPES[:submit].new(self, attrs, &block)
|
201
250
|
else
|
202
251
|
@_submit
|
203
252
|
end
|
@@ -221,8 +270,8 @@ class Kiss
|
|
221
270
|
def values
|
222
271
|
@_values ||= begin
|
223
272
|
hash = {}
|
224
|
-
@_fields.each {|field|
|
225
|
-
hash['submit'] = @_submit.value = params[@_submit.name
|
273
|
+
@_fields.each {|field| field.set_value_to_hash(hash) }
|
274
|
+
hash['submit'] = @_submit.value = params[@_submit.name]
|
226
275
|
hash
|
227
276
|
end
|
228
277
|
end
|
@@ -320,22 +369,14 @@ class Kiss
|
|
320
369
|
|
321
370
|
def set_object_data(obj = @_object)
|
322
371
|
@_object_fields[obj.object_id].values.each do |field|
|
323
|
-
#
|
372
|
+
# skip fields whose name starts with underscore
|
324
373
|
next if field.name =~ /\A\_/
|
325
|
-
#
|
326
|
-
next
|
327
|
-
#
|
328
|
-
next if field.
|
374
|
+
# skip fields with save == false
|
375
|
+
next unless field.save
|
376
|
+
# skip file fields
|
377
|
+
next if field.is_a?(FileField)
|
329
378
|
|
330
|
-
|
331
|
-
value = (field.value != nil || obj.class.db_schema[key].allow_null) ?
|
332
|
-
field.value : (obj.class.db_schema[key][:default] ||= field.format.default)
|
333
|
-
|
334
|
-
if field.digest
|
335
|
-
value = Digest.const_get(field.digest.to_sym).hexdigest(value)
|
336
|
-
end
|
337
|
-
|
338
|
-
obj[key] = value if field.save
|
379
|
+
field.set_value_to_object(obj)
|
339
380
|
end
|
340
381
|
end
|
341
382
|
|
@@ -413,12 +454,18 @@ class Kiss
|
|
413
454
|
(@_errors.size > 0 || @_has_field_errors)
|
414
455
|
end
|
415
456
|
|
457
|
+
# Returns true if user submitted form in this request.
|
458
|
+
def submitted?
|
459
|
+
@_submitted
|
460
|
+
end
|
461
|
+
|
416
462
|
# Returns true if user submitted form with non-cancel submit button
|
417
463
|
# (non-nil submit param, not equal to cancel submit button value).
|
418
|
-
def accepted
|
464
|
+
def accepted?
|
419
465
|
raise 'form missing submit field' unless @_submit
|
420
466
|
return params[@_submit.name] != @_submit.cancel
|
421
467
|
end
|
468
|
+
alias_method :accepted, :accepted?
|
422
469
|
|
423
470
|
# Renders error HTML block for top of form, and returns as string.
|
424
471
|
def errors_html
|
@@ -435,7 +482,7 @@ class Kiss
|
|
435
482
|
@_errors.pop if @_has_field_errors
|
436
483
|
|
437
484
|
plural = @_errors.size > 1 || @_has_field_errors ? 's' : nil
|
438
|
-
%Q(<table class="
|
485
|
+
%Q(<table class="kiss_form_errors"><tr><td>#{content}</td></tr></table>)
|
439
486
|
end
|
440
487
|
|
441
488
|
# Renders current action using form's HTML as action render content.
|
@@ -468,93 +515,115 @@ class Kiss
|
|
468
515
|
styles = []
|
469
516
|
styles.push( <<-EOT
|
470
517
|
table.kiss_form {
|
518
|
+
border: 0;
|
519
|
+
border-collapse: collapse;
|
520
|
+
margin-right: -12px;
|
521
|
+
}
|
522
|
+
table.kiss_form > tbody > tr > td {
|
523
|
+
padding: 0;
|
524
|
+
}
|
525
|
+
|
526
|
+
table.kiss_form_section {
|
527
|
+
border: 0;
|
528
|
+
border-collapse: collapse;
|
529
|
+
}
|
530
|
+
table.kiss_form_section > tbody > tr > td {
|
531
|
+
padding: 0 12px 0 0;
|
532
|
+
}
|
533
|
+
|
534
|
+
td.kiss_form_column {
|
535
|
+
vertical-align: top;
|
536
|
+
}
|
537
|
+
table.kiss_form_column {
|
471
538
|
margin-bottom: 6px;
|
472
539
|
}
|
473
|
-
.
|
474
|
-
padding: 2px
|
540
|
+
table.kiss_form_column > tbody > tr > td {
|
541
|
+
padding: 2px 6px 2px 0;
|
475
542
|
vertical-align: middle;
|
476
543
|
}
|
477
|
-
.
|
544
|
+
.kiss_form_errors {
|
478
545
|
margin-bottom: 4px;
|
479
546
|
}
|
480
|
-
.
|
547
|
+
.kiss_form_errors td {
|
481
548
|
background-color: #ff8;
|
482
549
|
padding: 2px 4px;
|
483
550
|
line-height: 135%;
|
484
551
|
color: #900;
|
485
|
-
border: 1px solid #
|
552
|
+
border: 1px solid #db4;
|
486
553
|
}
|
487
|
-
.
|
554
|
+
.kiss_form_errors td ul {
|
488
555
|
padding-left: 16px;
|
489
556
|
margin: 0;
|
490
557
|
}
|
491
|
-
.kiss_form .
|
492
|
-
padding:
|
558
|
+
.kiss_form .kiss_form_help {
|
559
|
+
padding-bottom: 4px;
|
493
560
|
font-size: 90%;
|
494
561
|
color: #555;
|
495
562
|
}
|
496
|
-
.
|
563
|
+
.kiss_form_required {
|
497
564
|
color: #a21;
|
498
565
|
font-size: 150%;
|
499
566
|
line-height: 50%;
|
500
567
|
position: relative;
|
501
568
|
top: 4px;
|
502
569
|
}
|
503
|
-
.
|
570
|
+
.kiss_form_column td.kiss_form_label {
|
504
571
|
text-align: right;
|
505
572
|
white-space: nowrap;
|
506
573
|
}
|
507
|
-
.
|
574
|
+
.kiss_form_column td.kiss_form_label.error {
|
508
575
|
color: #b10;
|
509
576
|
}
|
510
|
-
.
|
577
|
+
.kiss_form_column tr.kiss_form_prompt td {
|
511
578
|
padding: 8px 3px 0px 4px;
|
512
579
|
}
|
513
|
-
.
|
514
|
-
|
515
|
-
|
516
|
-
.kiss_form input[type="text"],
|
517
|
-
.kiss_form input[type=password],
|
518
|
-
.kiss_form textarea {
|
580
|
+
.kiss_form_column input[type="text"],
|
581
|
+
.kiss_form_column input[type=password],
|
582
|
+
.kiss_form_column textarea {
|
519
583
|
width: 250px;
|
520
584
|
margin-left: 0;
|
521
585
|
margin-right: 0;
|
522
586
|
}
|
523
|
-
.
|
587
|
+
.kiss_form_column table.kiss_form_field_columns {
|
524
588
|
border-spacing: 0;
|
525
589
|
border-collapse: collapse;
|
526
590
|
width: 100%;
|
527
591
|
}
|
528
|
-
.
|
592
|
+
.kiss_form_column table.kiss_form_field_columns td {
|
529
593
|
padding: 0 16px 2px 0;
|
530
594
|
vertical-align: top;
|
531
595
|
}
|
532
|
-
.
|
596
|
+
.kiss_form_column .kiss_form_checkbox .kiss_form_label {
|
533
597
|
vertical-align: top;
|
534
598
|
padding-top: 3px;
|
535
599
|
}
|
536
|
-
.
|
600
|
+
.kiss_form_column .kiss_form_radio .kiss_form_label {
|
537
601
|
vertical-align: top;
|
538
602
|
padding-top: 4px;
|
539
603
|
}
|
540
|
-
.
|
604
|
+
.kiss_form_column .kiss_form_textarea .kiss_form_label {
|
541
605
|
vertical-align: top;
|
542
606
|
padding-top: 3px;
|
543
607
|
}
|
608
|
+
.kiss_form tr.kiss_form_submit td {
|
609
|
+
padding: 0 6px 0 0;
|
610
|
+
text-align: center;
|
611
|
+
}
|
544
612
|
EOT
|
545
613
|
)
|
546
|
-
|
614
|
+
|
615
|
+
if @_error_class == 'kiss_form_error_message'
|
616
|
+
styles.push( <<-EOT
|
547
617
|
.kiss_form_error_message {
|
548
618
|
padding: 1px 4px;
|
549
|
-
border: 1px solid #
|
550
|
-
border-top: 0;
|
551
|
-
border-bottom: 1px solid #db4;
|
619
|
+
border: 1px solid #db4;
|
552
620
|
background-color: #ff8;
|
553
621
|
color: #900;
|
554
622
|
font-size: 90%;
|
555
623
|
line-height: 135%;
|
556
624
|
display: block;
|
557
625
|
float: left;
|
626
|
+
width: 246px;
|
558
627
|
margin-bottom: 2px;
|
559
628
|
}
|
560
629
|
.kiss_form_error_message div {
|
@@ -574,7 +643,8 @@ tr.kiss_form_error_row .kiss_form_error_message {
|
|
574
643
|
margin-bottom: 0;
|
575
644
|
}
|
576
645
|
EOT
|
577
|
-
|
646
|
+
)
|
647
|
+
end
|
578
648
|
style_tag = styles.size == 0 ? '' : "<style>" + styles.join('') + "</style>"
|
579
649
|
|
580
650
|
# combine
|
@@ -586,7 +656,14 @@ EOT
|
|
586
656
|
"</div></form>#{@_append_html}"
|
587
657
|
end
|
588
658
|
|
589
|
-
# Renders form
|
659
|
+
# Renders HTML for form sections.
|
660
|
+
def sections_html
|
661
|
+
sections.map do |section|
|
662
|
+
section.html
|
663
|
+
end.join
|
664
|
+
end
|
665
|
+
|
666
|
+
# Renders HTML for form fields.
|
590
667
|
def components_html
|
591
668
|
@_components.map do |component|
|
592
669
|
component_html(component)
|
@@ -596,22 +673,22 @@ EOT
|
|
596
673
|
|
597
674
|
# Renders open of form table.
|
598
675
|
def table_html_open
|
599
|
-
%Q(<table class="kiss_form" border=0 cellspacing=0>)
|
676
|
+
%Q(<table class="kiss_form" border=0 cellspacing=0><tbody>)
|
600
677
|
end
|
601
678
|
|
602
679
|
def required_legend_html
|
603
680
|
(@_has_required_fields && @_mark_required) ?
|
604
|
-
%Q( <tr><td
|
681
|
+
%Q( <tr><td class="kiss_form_help">Required fields marked by <span class="kiss_form_required">*</span></td></tr> ) : ''
|
605
682
|
end
|
606
683
|
|
607
684
|
# Renders close of form table.
|
608
685
|
def table_html_close
|
609
|
-
'</table>'
|
686
|
+
'</tbody></table>'
|
610
687
|
end
|
611
688
|
|
612
689
|
# Renders form submit buttons.
|
613
690
|
def submit_html
|
614
|
-
@_submit ?
|
691
|
+
@_submit ? %Q(<tr class="kiss_form_submit"><td>#{@_submit.element_html}</td></tr>) : ''
|
615
692
|
end
|
616
693
|
|
617
694
|
# Renders complete form HTML.
|
@@ -620,7 +697,7 @@ EOT
|
|
620
697
|
html_open,
|
621
698
|
table_html_open,
|
622
699
|
required_legend_html,
|
623
|
-
|
700
|
+
sections_html,
|
624
701
|
submit_html,
|
625
702
|
table_html_close,
|
626
703
|
html_close
|
@@ -630,23 +707,23 @@ EOT
|
|
630
707
|
# Renders HTML for specified form field.
|
631
708
|
def component_html(field)
|
632
709
|
field = fields[field.to_s] if (field.is_a?(Symbol) || field.is_a?(String))
|
633
|
-
return field.element_html if field.
|
710
|
+
return field.element_html if field.is_a?(HiddenField)
|
634
711
|
|
635
|
-
type = field.type
|
712
|
+
type = field.class.type
|
636
713
|
prompt = field.prompt
|
637
714
|
label = field.label
|
638
715
|
errors = field.errors_html
|
639
|
-
required = field.required ? %Q(<span class="
|
716
|
+
required = field.required ? %Q(<span class="kiss_form_required">#{@_mark_required}</span> ) : ''
|
640
717
|
|
641
718
|
([
|
642
|
-
prompt ? %Q(<tr class="
|
719
|
+
prompt ? %Q(<tr class="kiss_form_prompt"><td class="kiss_form_label">#{required}</td><td>#{prompt.to_s}</td></tr>) : '',
|
643
720
|
|
644
|
-
%Q(<tr class="
|
721
|
+
%Q(<tr class="kiss_form_#{type}"><td class="kiss_form_label#{errors ? ' error' : ''}">),
|
645
722
|
!prompt ? (required + (label.blank? ? '' : label.to_s + ':' )) : '',
|
646
|
-
%Q(</td><td class="
|
723
|
+
%Q(</td><td class="kiss_form_#{type}">),
|
647
724
|
field.element_html, "</td></tr>"
|
648
725
|
] + (errors ? [
|
649
|
-
'<tr class="kiss_form_error_row"><td class="
|
726
|
+
'<tr class="kiss_form_error_row"><td class="kiss_form_required"></td><td>',
|
650
727
|
errors,
|
651
728
|
'</td></tr>'
|
652
729
|
] : [])).join
|
data/lib/kiss.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# Kiss - A web application framework for Ruby
|
2
|
-
# Copyright (C) 2005-
|
2
|
+
# Copyright (C) 2005-2012 AppJudo Inc.
|
3
3
|
# See LICENSE for details.
|
4
4
|
|
5
|
-
# Author:: Shawn Van Ittersum,
|
6
|
-
# Copyright:: Copyright (c) 2005-
|
5
|
+
# Author:: Shawn Van Ittersum, AppJudo Inc.
|
6
|
+
# Copyright:: Copyright (c) 2005-2012 AppJudo Inc.
|
7
7
|
# License:: MIT X11 License
|
8
8
|
|
9
9
|
require 'rubygems'
|
metadata
CHANGED
@@ -4,9 +4,8 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 1
|
7
|
-
-
|
8
|
-
|
9
|
-
version: 1.7.4
|
7
|
+
- 8
|
8
|
+
version: "1.8"
|
10
9
|
platform: ruby
|
11
10
|
authors:
|
12
11
|
- Shawn Van Ittersum
|
@@ -14,7 +13,7 @@ autorequire:
|
|
14
13
|
bindir: bin
|
15
14
|
cert_chain: []
|
16
15
|
|
17
|
-
date: 2012-02-
|
16
|
+
date: 2012-02-11 00:00:00 -08:00
|
18
17
|
default_executable:
|
19
18
|
dependencies:
|
20
19
|
- !ruby/object:Gem::Dependency
|
@@ -107,7 +106,6 @@ files:
|
|
107
106
|
- lib/kiss/ext/sequel_database.rb
|
108
107
|
- lib/kiss/ext/sequel_mysql_dataset.rb
|
109
108
|
- lib/kiss/form/field.rb
|
110
|
-
- lib/kiss/form/field_types.rb
|
111
109
|
- lib/kiss/form.rb
|
112
110
|
- lib/kiss/format.rb
|
113
111
|
- lib/kiss/html/exception_report.css
|