handy_form 0.0.1
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/.gitignore +3 -0
- data/Gemfile +4 -0
- data/Rakefile +2 -0
- data/TODO +4 -0
- data/css/forms.css +40 -0
- data/handy_form.gemspec +23 -0
- data/lib/handy_form/builder.rb +138 -0
- data/lib/handy_form/helpers.rb +81 -0
- data/lib/handy_form/railtie.rb +16 -0
- data/lib/handy_form/tasks.rake +12 -0
- data/lib/handy_form/version.rb +3 -0
- data/lib/handy_form.rb +4 -0
- metadata +106 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
data/css/forms.css
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
/*
|
2
|
+
* Handy Forms
|
3
|
+
***************/
|
4
|
+
|
5
|
+
.handy_form .text_field_row input,
|
6
|
+
.handy_form .password_field_row input,
|
7
|
+
.handy_form .select_row select,
|
8
|
+
.handy_form .text_area_row textarea,
|
9
|
+
.handy_form .check_box_row input,
|
10
|
+
.handy_form .radio_button_row input {
|
11
|
+
font-size: 14px;
|
12
|
+
padding: 3px;
|
13
|
+
width: 150px;
|
14
|
+
}
|
15
|
+
|
16
|
+
.handy_form label {
|
17
|
+
font-size: 12px;
|
18
|
+
margin-right: 5px;
|
19
|
+
}
|
20
|
+
|
21
|
+
.handy_form .hint {
|
22
|
+
font-size: 11px;
|
23
|
+
color: #aaa;
|
24
|
+
}
|
25
|
+
|
26
|
+
.handy_form.stacked label,
|
27
|
+
.row.stacked label {
|
28
|
+
display: block;
|
29
|
+
clear: both;
|
30
|
+
padding-left: 0;
|
31
|
+
padding-bottom: 0;
|
32
|
+
}
|
33
|
+
|
34
|
+
.handy_form .row {
|
35
|
+
margin-bottom: 18px;
|
36
|
+
}
|
37
|
+
|
38
|
+
.handy_form .error-message {
|
39
|
+
color: red;
|
40
|
+
}
|
data/handy_form.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path("../lib/handy_form/version", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "handy_form"
|
6
|
+
s.version = HandyForm::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ["Peter Bui"]
|
9
|
+
s.email = ["peter@paydrotalks.com"]
|
10
|
+
s.homepage = "http://rubygems.org/gems/handy_form"
|
11
|
+
s.summary = "A handy Rails 3 Form Builder"
|
12
|
+
s.description = "Builds forms with a standard template that has labels, hints, and validations"
|
13
|
+
|
14
|
+
s.required_rubygems_version = ">= 1.3.6"
|
15
|
+
s.rubyforge_project = "handy_form"
|
16
|
+
|
17
|
+
s.add_development_dependency "bundler", ">= 1.0.0"
|
18
|
+
s.add_runtime_dependency "rails", ">= 3.0"
|
19
|
+
|
20
|
+
s.files = `git ls-files`.split("\n")
|
21
|
+
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
22
|
+
s.require_path = 'lib'
|
23
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module HandyForm
|
2
|
+
class Builder < ::ActionView::Helpers::FormBuilder
|
3
|
+
(field_helpers -
|
4
|
+
["form_for", "fields_for",
|
5
|
+
"apply_form_for_options!", "label",
|
6
|
+
"hidden_field"]
|
7
|
+
).each do |selector|
|
8
|
+
define_method(selector) do |method, *args|
|
9
|
+
options = args.extract_options!
|
10
|
+
|
11
|
+
# Remove the handy-related options from the above options
|
12
|
+
# This will keep the handy_options from being displayed when the
|
13
|
+
# field is composed below.
|
14
|
+
handy_options = extract_handy_options!(options)
|
15
|
+
|
16
|
+
# Build the field as if it weren't modified, allowing HandyForm to use
|
17
|
+
# whatever Rails decides is the representation of the current field.
|
18
|
+
# This allows Rails to be upgraded without HandyForm breaking.
|
19
|
+
field = super(method, *(args << options))
|
20
|
+
|
21
|
+
# Build the label for the field as well. Again, we let Rails handle
|
22
|
+
# this.
|
23
|
+
field_label = build_label(method, handy_options.delete(:label))
|
24
|
+
|
25
|
+
# If checkbox or radio, place input first
|
26
|
+
if field_first?(selector) && !handy_options.has_key?(:input_first)
|
27
|
+
handy_options[:input_first] = true
|
28
|
+
end
|
29
|
+
|
30
|
+
# Add the selector (input type) to the wrapper so that
|
31
|
+
# CSS rules can target the whole row.
|
32
|
+
add_selector_to_wrapper_class!(selector, handy_options)
|
33
|
+
|
34
|
+
# Add any error messages to handy options.
|
35
|
+
if object.errors[method.to_s].any?
|
36
|
+
add_errors!(method, handy_options)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Now combine everything!
|
40
|
+
@template.handy_field_wrapper(field, field_label, handy_options)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Allows this all handy_form_for objects to behave like the normal form
|
45
|
+
# builder in partials.
|
46
|
+
#
|
47
|
+
# e.g., this will use the "_form.html.erb" partial in the current view
|
48
|
+
# directory.
|
49
|
+
# <%= handy_form_for(@user) do |f| %>
|
50
|
+
# <%= render :partial => f %>
|
51
|
+
# <% end %>
|
52
|
+
#
|
53
|
+
def self.model_name
|
54
|
+
@model_name ||= Struct.new(:partial_path).new("form")
|
55
|
+
end
|
56
|
+
|
57
|
+
def extract_handy_options!(options)
|
58
|
+
options.extract!(:error, :hint, :label, :wrapper, :input_first)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Build's a label for the given ActiveModel method
|
62
|
+
#
|
63
|
+
# When options = false, then no label is built
|
64
|
+
# When options is a string, then the value for the label is the string
|
65
|
+
# When options is a hash, hash[:text] will become the value for the label
|
66
|
+
# and all other options are passed into Rails' label builder.
|
67
|
+
# Otherwise, the label is built off of the method.
|
68
|
+
def build_label(method, options)
|
69
|
+
return "" if options == false
|
70
|
+
|
71
|
+
text = nil
|
72
|
+
label_options = {}
|
73
|
+
|
74
|
+
text = method.to_s.humanize
|
75
|
+
case options
|
76
|
+
when String
|
77
|
+
text = options
|
78
|
+
when Hash
|
79
|
+
if !options[:text].blank?
|
80
|
+
text = options.delete(:text)
|
81
|
+
end
|
82
|
+
label_options = options
|
83
|
+
end
|
84
|
+
|
85
|
+
label(method, text, label_options)
|
86
|
+
end
|
87
|
+
alias_method :label_for, :build_label
|
88
|
+
|
89
|
+
def errors_for(method, options = {})
|
90
|
+
return "" unless object.errors[method.to_s].any?
|
91
|
+
add_errors!(method, options)
|
92
|
+
@template.error_tag(options[:error])
|
93
|
+
end
|
94
|
+
|
95
|
+
def hint(method, options = {})
|
96
|
+
@template.hint_tag(options)
|
97
|
+
end
|
98
|
+
|
99
|
+
protected
|
100
|
+
|
101
|
+
def field_first?(selector)
|
102
|
+
["check_box", "radio_button"].include?(selector.to_s)
|
103
|
+
end
|
104
|
+
|
105
|
+
def add_selector_to_wrapper_class!(selector, options = {})
|
106
|
+
options[:wrapper] ||= {}
|
107
|
+
|
108
|
+
# This allows for CSS targeting for selector types
|
109
|
+
options[:wrapper][:class] = "#{selector}_row " +
|
110
|
+
"#{options[:wrapper][:class]}"
|
111
|
+
|
112
|
+
options[:wrapper][:class].strip!
|
113
|
+
end
|
114
|
+
|
115
|
+
def add_errors!(method, options)
|
116
|
+
return if object.errors[method.to_s].empty?
|
117
|
+
|
118
|
+
options[:wrapper] ||= {}
|
119
|
+
options[:wrapper][:class] = "error #{options[:wrapper][:class]}".strip
|
120
|
+
|
121
|
+
case options[:error]
|
122
|
+
when nil
|
123
|
+
options[:error] = {}
|
124
|
+
options[:error][:text] = object.errors[method.to_s]
|
125
|
+
when Hash
|
126
|
+
options[:error][:text] = object.errors[method.to_s]
|
127
|
+
when String
|
128
|
+
options[:error] = {:text => [options[:error]]}
|
129
|
+
when Array
|
130
|
+
options[:error] = {:text => options[:error]}
|
131
|
+
else
|
132
|
+
raise "Unknown error type #{options[:error].inspect} " +
|
133
|
+
"for :error option"
|
134
|
+
end
|
135
|
+
options[:error] ||= {}
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module HandyForm
|
2
|
+
module Helpers
|
3
|
+
def handy_form_for(record_or_name_or_array, *args, &proc)
|
4
|
+
raise ArgumentError, "Missing block" unless block_given?
|
5
|
+
options = args.extract_options!
|
6
|
+
merge_builder_options! options
|
7
|
+
form_for(record_or_name_or_array, *(args << options), &proc)
|
8
|
+
end
|
9
|
+
|
10
|
+
def merge_builder_options!(options)
|
11
|
+
options.merge!(:builder => HandyForm::Builder)
|
12
|
+
options[:html] ||= {}
|
13
|
+
options[:html][:class] = "handy_form #{options[:html][:class]}".strip
|
14
|
+
end
|
15
|
+
|
16
|
+
def handy_field_wrapper(field, field_label, options = {})
|
17
|
+
options[:wrapper] ||= {}
|
18
|
+
merge_option_strings!(options[:wrapper], :class, "row")
|
19
|
+
|
20
|
+
hint = hint_tag(options.delete(:hint))
|
21
|
+
error = error_tag(options.delete(:error))
|
22
|
+
|
23
|
+
unless options.delete(:input_first)
|
24
|
+
content_tag(:div, (
|
25
|
+
field_label.html_safe + field.html_safe +
|
26
|
+
hint.html_safe + error.html_safe
|
27
|
+
), options[:wrapper]).html_safe
|
28
|
+
else
|
29
|
+
content_tag(:div, (field.html_safe + field_label.html_safe + hint.html_safe + error.html_safe), options[:wrapper]).html_safe
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def hint_tag(options)
|
34
|
+
return "" if options.nil?
|
35
|
+
case options
|
36
|
+
when String
|
37
|
+
text = options
|
38
|
+
options = {:class => "hint"}
|
39
|
+
when Hash
|
40
|
+
text = options.delete(:text)
|
41
|
+
merge_option_strings!(options, :class, "error-message")
|
42
|
+
end
|
43
|
+
|
44
|
+
content_tag(:div, text, options)
|
45
|
+
end
|
46
|
+
|
47
|
+
def error_tag(options)
|
48
|
+
return "" if options.nil?
|
49
|
+
case options
|
50
|
+
when String
|
51
|
+
text = options
|
52
|
+
options = {:class => "error-message"}
|
53
|
+
when Hash
|
54
|
+
text = build_error_string(options.delete(:text))
|
55
|
+
merge_option_strings!(options, :class, "error-message")
|
56
|
+
end
|
57
|
+
|
58
|
+
content_tag(:div, text, options)
|
59
|
+
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
|
63
|
+
def build_error_string(messages)
|
64
|
+
if messages.size == 1
|
65
|
+
messages.first
|
66
|
+
else
|
67
|
+
content_tag :ul do
|
68
|
+
items = ""
|
69
|
+
messages.each do |message|
|
70
|
+
items << content_tag(:li, message)
|
71
|
+
end
|
72
|
+
items
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def merge_option_strings!(hash, key, str)
|
78
|
+
hash[key] = "#{str} #{hash[key]}".strip
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'handy_form'
|
2
|
+
require 'rails'
|
3
|
+
|
4
|
+
module HandyForm
|
5
|
+
class Railtie < Rails::Railtie
|
6
|
+
initializer "handy_form.initializer" do |app|
|
7
|
+
::ActionView::Base.class_eval do
|
8
|
+
include HandyForm::Helpers
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
rake_tasks do
|
13
|
+
load "handy_form/tasks.rake"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
namespace :handy_form do
|
2
|
+
desc "Copy handy_form css files into your rails application"
|
3
|
+
task :css_install do
|
4
|
+
gemdir = File.join(File.dirname(__FILE__), "..", "..",)
|
5
|
+
print "\nCopying 'forms.css' to rails' public/stylesheets dir ... "
|
6
|
+
FileUtils.cp(
|
7
|
+
File.join(gemdir, "css", "forms.css"),
|
8
|
+
Rails.root.join("public", "stylesheets")
|
9
|
+
)
|
10
|
+
puts "Done."
|
11
|
+
end
|
12
|
+
end
|
data/lib/handy_form.rb
ADDED
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: handy_form
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Peter Bui
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-01-13 00:00:00 -08:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: bundler
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 1
|
30
|
+
- 0
|
31
|
+
- 0
|
32
|
+
version: 1.0.0
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rails
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
segments:
|
44
|
+
- 3
|
45
|
+
- 0
|
46
|
+
version: "3.0"
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id002
|
49
|
+
description: Builds forms with a standard template that has labels, hints, and validations
|
50
|
+
email:
|
51
|
+
- peter@paydrotalks.com
|
52
|
+
executables: []
|
53
|
+
|
54
|
+
extensions: []
|
55
|
+
|
56
|
+
extra_rdoc_files: []
|
57
|
+
|
58
|
+
files:
|
59
|
+
- .gitignore
|
60
|
+
- Gemfile
|
61
|
+
- Rakefile
|
62
|
+
- TODO
|
63
|
+
- css/forms.css
|
64
|
+
- handy_form.gemspec
|
65
|
+
- lib/handy_form.rb
|
66
|
+
- lib/handy_form/builder.rb
|
67
|
+
- lib/handy_form/helpers.rb
|
68
|
+
- lib/handy_form/railtie.rb
|
69
|
+
- lib/handy_form/tasks.rake
|
70
|
+
- lib/handy_form/version.rb
|
71
|
+
has_rdoc: true
|
72
|
+
homepage: http://rubygems.org/gems/handy_form
|
73
|
+
licenses: []
|
74
|
+
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options: []
|
77
|
+
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
version: "0"
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
segments:
|
94
|
+
- 1
|
95
|
+
- 3
|
96
|
+
- 6
|
97
|
+
version: 1.3.6
|
98
|
+
requirements: []
|
99
|
+
|
100
|
+
rubyforge_project: handy_form
|
101
|
+
rubygems_version: 1.3.7
|
102
|
+
signing_key:
|
103
|
+
specification_version: 3
|
104
|
+
summary: A handy Rails 3 Form Builder
|
105
|
+
test_files: []
|
106
|
+
|