storefront 0.5.1 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +1 -1
- data/lib/storefront.rb +1 -0
- data/lib/storefront/components/form.rb +2 -4
- data/lib/storefront/components/form/base.rb +40 -38
- data/lib/storefront/components/form/builder.rb +98 -96
- data/lib/storefront/components/form/errors.rb +22 -20
- data/lib/storefront/components/form/field.rb +75 -73
- data/lib/storefront/components/form/fieldset.rb +32 -30
- data/lib/storefront/components/form/hint.rb +23 -21
- data/lib/storefront/components/form/input.rb +143 -141
- data/lib/storefront/components/form/inputs.rb +4 -2
- data/lib/storefront/components/form/inputs/checkbox.rb +8 -6
- data/lib/storefront/components/form/inputs/date.rb +9 -7
- data/lib/storefront/components/form/inputs/file.rb +8 -6
- data/lib/storefront/components/form/inputs/hidden.rb +7 -5
- data/lib/storefront/components/form/inputs/radio.rb +6 -4
- data/lib/storefront/components/form/inputs/range.rb +8 -6
- data/lib/storefront/components/form/inputs/select.rb +52 -50
- data/lib/storefront/components/form/inputs/string.rb +64 -62
- data/lib/storefront/components/form/inputs/submit.rb +17 -15
- data/lib/storefront/components/form/inputs/textarea.rb +13 -11
- data/lib/storefront/components/form/inputs/value.rb +11 -9
- data/lib/storefront/components/form/label.rb +24 -22
- metadata +1 -1
data/Rakefile
CHANGED
@@ -5,7 +5,7 @@ require 'rake/gempackagetask'
|
|
5
5
|
spec = Gem::Specification.new do |s|
|
6
6
|
s.name = "storefront"
|
7
7
|
s.authors = ["Lance Pollard"]
|
8
|
-
s.version = "0.5.
|
8
|
+
s.version = "0.5.2"
|
9
9
|
s.description = "Opinionated Forms, Tables, and Widgets for Rails and Sinatra"
|
10
10
|
s.summary = "A simple and semantic FormBuilder, TableBuilder, Locale Interpolator, and Widget API for Rails 3 and Sinatra"
|
11
11
|
s.homepage = "http://github.com/viatropos/storefront"
|
data/lib/storefront.rb
CHANGED
@@ -22,5 +22,6 @@ require "storefront/configuration"
|
|
22
22
|
|
23
23
|
Dir["#{this}/storefront/helpers/**/*"].each { |path| require path unless ::File.directory?(path) }
|
24
24
|
require "storefront/components/base"
|
25
|
+
require "storefront/components/form"
|
25
26
|
Dir["#{this}/storefront/components/**/*"].each { |path| require path unless ::File.directory?(path) }
|
26
27
|
Dir["#{this}/storefront/models/**/*"].each { |path| require path unless ::File.directory?(path) }
|
@@ -1,8 +1,6 @@
|
|
1
|
-
require 'storefront/components/form/base'
|
2
|
-
|
3
1
|
module Storefront
|
4
2
|
module Components
|
5
|
-
class Form < Base
|
3
|
+
class Form < ::Storefront::Components::Base
|
6
4
|
attr_reader :model, :template, :tabindex, :access_keys, :attributes
|
7
5
|
delegate :object, :parent, :to => :model
|
8
6
|
|
@@ -11,7 +9,7 @@ module Storefront
|
|
11
9
|
@template = template
|
12
10
|
@model = Storefront::Model.new(:object => extract_object!(args.shift))
|
13
11
|
@attributes = extract_attributes!(options)
|
14
|
-
@builder = Storefront::Form::Builder.new(
|
12
|
+
@builder = Storefront::Components::Form::Builder.new(
|
15
13
|
:template => template,
|
16
14
|
:tabindex => 1,
|
17
15
|
:access_keys => {},
|
@@ -1,49 +1,51 @@
|
|
1
1
|
module Storefront
|
2
|
-
|
3
|
-
class
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
protected
|
2
|
+
module Components
|
3
|
+
class Form
|
4
|
+
class Base < Storefront::Components::Base
|
5
|
+
include Storefront::Helpers::ContentHelper
|
6
|
+
include Storefront::Helpers::DomHelper
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
@template = options[:template]
|
10
|
+
@model = options[:model]
|
11
|
+
@attribute = options[:attribute]
|
12
|
+
@parent_index = options[:parent_index]
|
13
|
+
@index = options[:index]
|
14
|
+
@tabindex = options[:tabindex]
|
15
|
+
@access_keys = options[:access_keys]
|
16
|
+
@attributes = clone_attributes(options.except(:template, :model, :attribute, :access_keys, :index, :tabindex))
|
17
|
+
end
|
19
18
|
|
20
|
-
|
21
|
-
attr_accessor :attributes, :value, :label, :access_keys, :tabindex, :input_type
|
19
|
+
protected
|
22
20
|
|
23
|
-
|
24
|
-
|
25
|
-
options[:index] ||= index
|
26
|
-
options[:attribute] ||= attribute
|
27
|
-
options[:template] ||= template
|
28
|
-
options
|
29
|
-
end
|
21
|
+
attr_accessor :template, :model, :attribute, :index, :parent_index
|
22
|
+
attr_accessor :attributes, :value, :label, :access_keys, :tabindex, :input_type
|
30
23
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
24
|
+
def default_options!(options = {})
|
25
|
+
options[:model] ||= model
|
26
|
+
options[:index] ||= index
|
27
|
+
options[:attribute] ||= attribute
|
28
|
+
options[:template] ||= template
|
29
|
+
options
|
30
|
+
end
|
35
31
|
|
36
|
-
|
37
|
-
|
38
|
-
|
32
|
+
def config
|
33
|
+
Storefront.configuration
|
34
|
+
end
|
35
|
+
alias_method :storefront_config, :config
|
39
36
|
|
40
|
-
|
41
|
-
|
42
|
-
return default.to_s unless default.is_a?(::Symbol)
|
43
|
-
attribute = default
|
37
|
+
def value?
|
38
|
+
@value.present?
|
44
39
|
end
|
40
|
+
|
41
|
+
def localize(key, attribute, default, options = {})
|
42
|
+
if default.present?
|
43
|
+
return default.to_s unless default.is_a?(::Symbol)
|
44
|
+
attribute = default
|
45
|
+
end
|
45
46
|
|
46
|
-
|
47
|
+
t?(attribute, options.reverse_merge(:scope => :"forms.#{key}", :model => model.object))
|
48
|
+
end
|
47
49
|
end
|
48
50
|
end
|
49
51
|
end
|
@@ -1,123 +1,125 @@
|
|
1
1
|
module Storefront
|
2
|
-
|
3
|
-
class
|
4
|
-
|
2
|
+
module Components
|
3
|
+
class Form
|
4
|
+
class Builder < Storefront::Components::Form::Base
|
5
|
+
delegate :object, :parent, :to => :model
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
def fieldset(*args, &block)
|
8
|
+
options = default_options!(args.extract_options!)
|
9
|
+
options[:label] ||= args.shift
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
Storefront::Components::Form::Fieldset.new(options).render(&block)
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
14
|
+
def fields(*args, &block)
|
15
|
+
options = args.extract_options!
|
16
|
+
options[:as] = :fields
|
17
|
+
options[:label] ||= false
|
18
|
+
attr_name = args.shift || attribute.name
|
19
|
+
template.capture_haml do
|
20
|
+
result = field attr_name, options do |_field|
|
21
|
+
template.haml_concat fieldset(&block).gsub(/\n$/, "")
|
22
|
+
end
|
23
|
+
template.haml_concat result.gsub(/\n$/, "")
|
21
24
|
end
|
22
|
-
template.haml_concat result.gsub(/\n$/, "")
|
23
25
|
end
|
24
|
-
end
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
def fields_for(*args, &block)
|
28
|
+
options = args.extract_options!
|
29
|
+
attribute = args.shift
|
30
|
+
macro = model.macro_for(attribute)
|
31
|
+
attr_name = nil
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
if options[:as] == :object
|
34
|
+
attr_name = attribute.to_s
|
35
|
+
else
|
36
|
+
attr_name = config.rename_nested_attributes ? "#{attribute}_attributes" : attribute.to_s
|
37
|
+
end
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
|
39
|
+
# do something here for counts
|
40
|
+
sub_parent = model.object
|
41
|
+
sub_object = args.shift
|
41
42
|
|
42
|
-
|
43
|
+
index = options.delete(:index)
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
unless index.present? && index.is_a?(::String)
|
46
|
+
if sub_object.blank? && index.present?
|
47
|
+
sub_object = sub_parent.send(attribute)[index]
|
48
|
+
elsif index.blank? && sub_object.present? && macro == :has_many
|
49
|
+
index = sub_parent.send(attribute).index(sub_object)
|
50
|
+
end
|
49
51
|
end
|
50
|
-
end
|
51
52
|
|
52
|
-
|
53
|
-
|
53
|
+
sub_object ||= model.default(attribute) || model.to_s.camelize.constantize.new
|
54
|
+
keys = [model.keys, attr_name]
|
54
55
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
56
|
+
model = Storefront::ModelProxy.new(
|
57
|
+
:object => sub_object,
|
58
|
+
:parent => sub_parent,
|
59
|
+
:keys => keys
|
60
|
+
)
|
60
61
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
62
|
+
options.merge!(
|
63
|
+
:template => template,
|
64
|
+
:model => model,
|
65
|
+
:parent_index => index,
|
66
|
+
:access_keys => access_keys,
|
67
|
+
:tabindex => tabindex
|
68
|
+
)
|
69
|
+
Storefront::Components::Form::Builder.new(options).render(&block)
|
70
|
+
end
|
70
71
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
72
|
+
def field(*args, &block)
|
73
|
+
options = args.extract_options!
|
74
|
+
attribute_name = args.shift || attribute.name
|
75
|
+
attribute = Storefront::Attribute.new(
|
76
|
+
:name => attribute_name,
|
77
|
+
:model => @model,
|
78
|
+
:required => options[:required] == true,
|
79
|
+
:disabled => options[:disabled] == true,
|
80
|
+
:top_level => options[:attribute] == false
|
81
|
+
)
|
81
82
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
83
|
+
options.reverse_merge!(
|
84
|
+
:template => template,
|
85
|
+
:model => model,
|
86
|
+
:attribute => attribute,
|
87
|
+
:parent_index => parent_index,
|
88
|
+
:index => index,
|
89
|
+
:field_html => options[:field_html] || {},
|
90
|
+
:input_html => options[:input_html] || {},
|
91
|
+
:label_html => options[:label_html] || {},
|
92
|
+
:error_html => options[:error_html] || {},
|
93
|
+
:hint_html => options[:hint_html] || {}
|
94
|
+
)
|
94
95
|
|
95
|
-
|
96
|
-
|
96
|
+
Storefront::Components::Form::Field.new(options).render(&block)
|
97
|
+
end
|
97
98
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
99
|
+
def button(*args, &block)
|
100
|
+
options = args.extract_options!
|
101
|
+
options.reverse_merge!(:as => :submit)
|
102
|
+
options[:value] = args.shift || "Submit"
|
103
|
+
field(options[:value], options, &block)
|
104
|
+
end
|
104
105
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
106
|
+
def submit(*args, &block)
|
107
|
+
template.capture_haml do
|
108
|
+
result = fieldset :class => config.submit_fieldset_class do |fields|
|
109
|
+
template.haml_concat fields.button(*args).gsub(/\n$/, "")
|
110
|
+
yield(fields) if block_given?
|
111
|
+
end
|
112
|
+
template.haml_concat result.gsub(/\n$/, "")
|
110
113
|
end
|
111
|
-
template.haml_concat result.gsub(/\n$/, "")
|
112
114
|
end
|
113
|
-
end
|
114
115
|
|
115
|
-
|
116
|
-
|
117
|
-
|
116
|
+
def partial(path, options = {})
|
117
|
+
@template.render :partial => path, :locals => options.merge(:fields => self)
|
118
|
+
end
|
118
119
|
|
119
|
-
|
120
|
-
|
120
|
+
def render(&block)
|
121
|
+
yield(self)
|
122
|
+
end
|
121
123
|
end
|
122
124
|
end
|
123
125
|
end
|
@@ -1,26 +1,28 @@
|
|
1
1
|
module Storefront
|
2
|
-
|
3
|
-
class
|
4
|
-
|
5
|
-
|
2
|
+
module Components
|
3
|
+
class Form
|
4
|
+
class Errors < Storefront::Components::Form::Base
|
5
|
+
def initialize(options = {})
|
6
|
+
super
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
8
|
+
attributes.merge!(options[:error_html]) if options[:error_html]
|
9
|
+
attributes.delete :error_html
|
10
|
+
attributes.delete :error
|
11
|
+
# error
|
12
|
+
merge_class! @attributes, config.error_class
|
13
|
+
# aria-invalid = true|grammar|spelling
|
14
|
+
# aria-hidden
|
15
|
+
attributes[:id] ||= attribute.to_id(:type => :error, :index => index, :parent_index => parent_index) if config.id_enabled_on.include?("error")
|
16
|
+
@value = model.errors_for(attribute.name)
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
def render(&block)
|
20
|
+
template.capture_haml do
|
21
|
+
if value.present?
|
22
|
+
template.haml_tag config.error_tag, value.join("\n").html_safe.gsub(/\n$/, ""), attributes
|
23
|
+
elsif config.always_include_error_tag
|
24
|
+
template.haml_tag config.error_tag, attributes
|
25
|
+
end
|
24
26
|
end
|
25
27
|
end
|
26
28
|
end
|
@@ -1,101 +1,103 @@
|
|
1
1
|
module Storefront
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
2
|
+
module Components
|
3
|
+
class Form
|
4
|
+
# input :name, :as => :string, :class => "string something", :label_method => x, :value_method => y
|
5
|
+
# disabled, readonly, accesskey, tabindex
|
6
|
+
# button, checkbox, color, date, datetime, datetime-local, email, file, hidden, image, month, number, password, radio, range , reset, search, submit, tel, text, time, url, week
|
7
|
+
# input :phone, :mask => /\d\d\d-\d\d\d-\d\d\d\d/, :hint => "Enter your phone number", :tip => "This is so we can call you."
|
8
|
+
class Field < Storefront::Components::Form::Builder
|
9
|
+
def initialize(options = {})
|
10
|
+
super
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
# input type
|
13
|
+
options[:as] ||= attribute.input_type(options)
|
14
|
+
@input_type = options[:as]
|
15
|
+
@inputs = []
|
15
16
|
|
16
|
-
|
17
|
+
# class
|
17
18
|
|
18
|
-
|
19
|
+
classes = [config.field_class, input_type]
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
21
|
+
unless [:submit, :fieldset].include?(input_type)
|
22
|
+
classes += [
|
23
|
+
attribute.required? ? config.required_class : config.optional_class,
|
24
|
+
attribute.errors? ? config.error_class : config.valid_class,
|
25
|
+
]
|
26
|
+
if options[:validate] != false && attribute.validations.present?
|
27
|
+
classes << config.validate_class
|
28
|
+
end
|
27
29
|
end
|
28
|
-
end
|
29
30
|
|
30
|
-
|
31
|
+
merge_class! attributes, *classes.compact.uniq.map(&:to_s)
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
# id
|
34
|
+
if attributes[:id].blank? && config.id_enabled_on.include?("field")
|
35
|
+
attributes[:id] = attribute.to_id(:type => :field, :index => index, :parent_index => parent_index)
|
36
|
+
end
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
38
|
+
unless [:hidden, :submit].include?(input_type)
|
39
|
+
# errors
|
40
|
+
@errors = Storefront::Components::Form::Errors.new(options.slice(:rich_input, :error_html, :error, :model, :index, :parent_index, :attribute, :template))
|
40
41
|
|
41
|
-
|
42
|
-
|
42
|
+
# label
|
43
|
+
@label = Storefront::Components::Form::Label.new(options.slice(:rich_input, :label_html, :label, :model, :index, :parent_index, :attribute, :template))
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
|
45
|
+
# hint
|
46
|
+
@hints = Storefront::Components::Form::Hint.new(options.slice(:rich_input, :hint_html, :hint, :model, :index, :parent_index, :attribute, :template))
|
47
|
+
end
|
47
48
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
49
|
+
unless input_type == :fieldset
|
50
|
+
# inputs
|
51
|
+
@input_attributes = default_options!.merge(attributes.except(:id, :class, :field_html, :attributes, :error_html, :label_html, :hint_html))
|
52
|
+
end
|
52
53
|
|
53
|
-
|
54
|
+
merge_class! options[:field_html], attributes[:class]
|
54
55
|
|
55
|
-
|
56
|
-
|
56
|
+
@attributes = options[:field_html].merge(:id => attributes[:id])
|
57
|
+
end
|
57
58
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
59
|
+
def input(*args)
|
60
|
+
#@tabindex = @tabindex + 1
|
61
|
+
options = args.extract_options!
|
62
|
+
key = args.shift || attribute.name
|
63
|
+
@inputs << input_for(input_type, key, options)
|
64
|
+
end
|
64
65
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
66
|
+
def render(&block)
|
67
|
+
template.capture_haml do
|
68
|
+
template.haml_tag :li, attributes do
|
69
|
+
input(attribute.name) unless block_given?
|
70
|
+
elements = extract_elements!(attributes)
|
70
71
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
72
|
+
result = elements.map do |element|
|
73
|
+
Array(send(element)).map(&:render)
|
74
|
+
end
|
75
|
+
template.haml_concat result.flatten.join.gsub(/\n$/, "") if result.present?
|
75
76
|
|
76
|
-
|
77
|
+
yield(self) if block_given? # template.capture_haml(self, &block)
|
78
|
+
end
|
77
79
|
end
|
78
80
|
end
|
79
|
-
end
|
80
81
|
|
81
|
-
|
82
|
-
|
82
|
+
protected
|
83
|
+
attr_reader :errors, :labels, :inputs, :hints, :label, :input_type
|
83
84
|
|
84
|
-
|
85
|
-
|
86
|
-
|
85
|
+
def input_for(key, attribute, options = {})
|
86
|
+
Storefront::Components::Form::Input.find(key.to_sym).new(@input_attributes.merge(options))
|
87
|
+
end
|
87
88
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
89
|
+
def extract_elements!(options = {})
|
90
|
+
elements = []
|
91
|
+
if [:hidden, :submit].include?(input_type)
|
92
|
+
elements << :inputs
|
93
|
+
else
|
94
|
+
if @label.present? && @label.value?
|
95
|
+
elements << :label
|
96
|
+
end
|
97
|
+
elements = elements.concat [:inputs, :hints, :errors]
|
95
98
|
end
|
96
|
-
elements
|
99
|
+
elements
|
97
100
|
end
|
98
|
-
elements
|
99
101
|
end
|
100
102
|
end
|
101
103
|
end
|