Skip to content

Commit dcf8beb

Browse files
author
Justin French
committed
Initial Commit
0 parents  commit dcf8beb

File tree

11 files changed

+712
-0
lines changed

11 files changed

+712
-0
lines changed

MIT-LICENSE

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Copyright (c) 2007 [name of plugin creator]
2+
3+
Permission is hereby granted, free of charge, to any person obtaining
4+
a copy of this software and associated documentation files (the
5+
"Software"), to deal in the Software without restriction, including
6+
without limitation the rights to use, copy, modify, merge, publish,
7+
distribute, sublicense, and/or sell copies of the Software, and to
8+
permit persons to whom the Software is furnished to do so, subject to
9+
the following conditions:
10+
11+
The above copyright notice and this permission notice shall be
12+
included in all copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README

+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
=Formtastic Sneaky Preview
2+
3+
Formtastic is a Rails FormBuilder DSL (with some other goodies) to make it far easier to create beautiful, semantically rich, syntactically awesome, readily stylable and wonderfully accessible HTML forms in your Rails applications.
4+
5+
One day, I finally had enough. Hacked together forms were easy, but awesome forms with decent semantics, rich mark-up and plenty of CSS hooks were incredibly painful. I was discouraged from doing things properly because it was do much mark-up and code to write.
6+
7+
So I opened up a text file, and wrote a DSL for how I'd like to author forms:
8+
9+
<% semantic_form_for @article do |form| %>
10+
11+
<%= form.error_messages %>
12+
13+
<% form.input_field_set "Basic" do %>
14+
<%= form.input :title %>
15+
<%= form.input :body, :rows => 20 %>
16+
<%= form.input :section_id, :include_blank => true %>
17+
<%= form.input :publication_state_id, :as => :radio %>
18+
<%= form.input :author_id, :as => :select %>
19+
<%= form.input :allow_comments, :label => "Allow commenting on this article" %>
20+
<% end %>
21+
22+
<% form.input_field_set "Extra" do %>
23+
<%= form.input :keywords, :required => false, :hint => "Example: ruby, rails, forms" %>
24+
<%= form.input :extract, :required => false, :rows => 5 %>
25+
<%= form.input :description, :required => false, :rows => 5 %>
26+
<%= form.input :url_title, :required => false %>
27+
<% end %>
28+
29+
<% form.button_field_set do %>
30+
<%= form.cancel_button -%>
31+
<%= form.commit_button -%>
32+
<% end %>
33+
34+
<% end %>
35+
36+
I also wrote the accompanying HTML output I expected, favoring something very similar to the fieldsets, lists and other semantic elements Aaron Gustafson presented in <i>Learning to Love Forms</i> <http://www.slideshare.net/AaronGustafson/learning-to-love-forms-web-directions-south-07>, and then hacked together enough Ruby to prove it could be done.
37+
38+
39+
==Configuration
40+
41+
If you wish, put something like this in config/initializers/formtastic_config.rb:
42+
43+
JustinFrench::Formtastic::SemanticFormBuilder.all_fields_required_by_default = false
44+
JustinFrench::Formtastic::SemanticFormBuilder.required_string = "(required)"
45+
JustinFrench::Formtastic::SemanticFormBuilder.optional_string = "(optional)"
46+
47+
48+
==Guiding Principals
49+
50+
* great forms are at the heart of most web applications
51+
* semantically rich (and far more accessible) HTML forms really are possible with the use of appropriate elements like fieldsets & lists
52+
* sometimes more mark-up is better
53+
* stylesheet authors have more options and more control if plenty of structural mark-up, class names and element ids are provided
54+
* it should be easy to write a great form rather than a crappy form
55+
* I'm sick of re-inventing the wheel every time I need a form
56+
* applications with great data modelling and a RESTful architecture are my main consideration
57+
* there's no such thing as a silver bullet and I'll still have to hard-code some things I do
58+
* best practices and common patterns have to start somewhere
59+
60+
61+
62+
==Status
63+
64+
THIS IS DEFINITELY NOT PRODUCTION-READY. THINGS ARE GOING TO CHANGE A LOT.
65+
66+
It's incredibly opinionated, incomplete, a work in progress, messy around the edges, messy in the middle too, tightly coupled to the database, tightly coupled to "my way" of doing things and also incredibly lacking in unit tests so far, but I hope you try it and offer some suggestions and improvements any way.
67+
68+
* Justin's Weblog: http://justinfrench.com
69+
* Justin's email: justin at indent dot com dot au
70+
* Documentation: http://formtastic.justinfrench.com
71+
* SVN repository: http://indent.svnrepository.com/svn/plugins/formtastic/trunk
72+
73+
74+
==Roadmap
75+
76+
* There's plenty of TODOs in the code
77+
* get the basic form_for implementation complete, proven and *well tested* (did I mention how laborious testing form builders is?)
78+
* provide generic, reusable, stylesheets that prove this stuff works
79+
* go back and ensure it works for remote_form_for, etc
80+
* probably do a shortcut like <%= form.inputs :name, :login, :email, :bio %> for those that want the form with zero configuration
81+
82+
83+
==Installation
84+
85+
You know the drill:
86+
87+
cd path/to/your/app
88+
./script/plugin install http://indent.svnrepository.com/svn/plugins/formtastic/trunk
89+
90+
91+
==Usage
92+
93+
The smallest example:
94+
95+
<% semantic_form_for @user do |form| %>
96+
<% form.input_field_set do %>
97+
<%= form.input :name %>
98+
<%= form.input :email %>
99+
<% end %>
100+
<% end %>
101+
102+
With an output something like:
103+
104+
<form id="new-article-form" action="#" method="post">
105+
<fieldset>
106+
<legend><span>Create a new User</span></legend>
107+
<fieldset class="inputs">
108+
<ol>
109+
<li id="user_name_input" class="required string">
110+
<label for="user_name">Name <abbr title="required">*</abbr></label>
111+
<input type="text" id="user_name" name="user[name]" size="50" />
112+
</li>
113+
<li id="user_email_input" class="required string">
114+
<label for="user_email">Email <abbr title="required">*</abbr></label>
115+
<input type="text" id="user_email" name="user[email]" size="50" />
116+
</li>
117+
</ol>
118+
</fieldset>
119+
</fieldset>
120+
</form>
121+
122+
123+
==What about Stylesheets?
124+
125+
It's no where near complete, but there is a sample CSS file here:
126+
http://indent.svnrepository.com/svn/plugins/formtastic/sample/public/stylesheets/formtastic.css
127+
128+
The plan is that a CSS file similar to this will be generated or otherwise made available to your app to give you basic vertical (labels above inputs) and horizontal (labels to the left of inputs), and then if needed, you would write new styles on top to customise the presentation to suit you.
129+
130+
131+
==Compatibility
132+
133+
I'm only testing Formtastic with the latest Rails stable release (2.0.2 at this time).
134+
135+
136+
==But it doesn't do that thing I really need!
137+
138+
Oh noes! It might not ever do it either. We'll see. This is not a silver bullet. I want to make the usual stuff easy, and the unusual stuff possible. That might mean that some of the inputs on your form still have to be hard-coded, but some is better than all, right?
139+
140+
I really hope the plugin will soon be clean and extensible enough to invite others to contribute more complex input types (calendars, etc) to the core.
141+
142+
143+
144+
Copyright (c) 2007 Justin French, released under the MIT license.

Rakefile

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
require 'rake'
2+
require 'rake/testtask'
3+
require 'rake/rdoctask'
4+
5+
desc 'Default: run unit tests.'
6+
task :default => :test
7+
8+
desc 'Test the formtastic plugin.'
9+
Rake::TestTask.new(:test) do |t|
10+
t.libs << 'lib'
11+
t.pattern = 'test/**/*_test.rb'
12+
t.verbose = true
13+
end
14+
15+
desc 'Generate documentation for the formtastic plugin.'
16+
Rake::RDocTask.new(:rdoc) do |rdoc|
17+
rdoc.rdoc_dir = 'rdoc'
18+
rdoc.title = 'Formtastic'
19+
rdoc.options << '--line-numbers' << '--inline-source'
20+
rdoc.rdoc_files.include('README')
21+
rdoc.rdoc_files.include('lib/**/*.rb')
22+
end

docs/dsl.html

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
3+
<head>
4+
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
5+
<meta http-equiv="Content-Language" content="en-us" />
6+
<title>untitled</title>
7+
<meta name="Copyright" content="(c) 2008 Copyright Justin French" />
8+
</head>
9+
10+
<body>
11+
12+
<% semantic_form_for @article do |form| %>
13+
14+
<%= form.error_messages -%>
15+
16+
<% form.input_field_set do %>
17+
<%= form.input :title %>
18+
<%= form.input :body, :rows => 20 %>
19+
<%= form.input :extract, :required => false, :rows => 5 %>
20+
<%= form.input :description, :required => false, :rows => 5 %>
21+
<%= form.input :keywords, :required => false, :hint => "Example: ruby, rails, forms" %>
22+
<%= form.input :section_id, :include_blank => true %>
23+
<%= form.input :publication_state_id, :as => :radio %>
24+
<%= form.input :url_title, :required => false %>
25+
<%= form.input :author_id %>
26+
<%= form.input :allow_comments, :label => "Allow commenting on this article" %>
27+
<% end %>
28+
29+
<% form.button_field_set do %>
30+
<%= form.commit_button -%>
31+
<% end %>
32+
33+
<% end %>
34+
35+
</body>
36+
</html>
37+

docs/output.html

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
3+
<head>
4+
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
5+
<meta http-equiv="Content-Language" content="en-us" />
6+
<title>untitled</title>
7+
<meta name="Copyright" content="(c) 2008 Copyright Justin French" />
8+
</head>
9+
10+
<body>
11+
12+
13+
<form id="new-article-form" action="#" method="post">
14+
<fieldset>
15+
16+
<legend><span>Create a new Article</span></legend>
17+
18+
<div id="errors">
19+
<p>We encountered <strong>2 errors</strong> while trying to process this form:</p>
20+
<ol>
21+
<li><a href="#article_title_input">title</a> must be provided</li>
22+
<li><a href="#article_section_id_input">section</a> must be provided</li>
23+
</ol>
24+
</div>
25+
26+
<fieldset class="inputs">
27+
<ol>
28+
<li id="article_title_input" class="required string error">
29+
<label for="article_title">Title</label>
30+
<input type="text" id="article_title" name="article[title]" size="50" />
31+
<p class="error"><strong>title must be provided</strong></p>
32+
</li>
33+
34+
<li id="article_body_input" class="required text">
35+
<label for="article_body">Body</label>
36+
<textarea id="article_body" name="article[body]" rows="20" cols="50"></textarea>
37+
</li>
38+
39+
<li id="article_extract_input" class="optional text">
40+
<label for="article_extract">Extract</label>
41+
<textarea id="article_extract" name="article[extract]" rows="5" cols="50"></textarea>
42+
<p class="hint">An interesting passage or quote extracted from the article.</p>
43+
</li>
44+
45+
<li id="article_keywords_input" class="optional string">
46+
<label for="article_keywords">Keywords</label>
47+
<input type="text" id="article_keywords" name="article[keywords]" size="50" />
48+
<p class="hint">ruby, rails, forms, internets, remarkability</p>
49+
</li>
50+
51+
<li id="article_section_id_input" class="required select error">
52+
<label for="article_section_id">Section</lable>
53+
<select id="article_section_id" name="article[section_id]">
54+
<option value=""></option>
55+
<option value="1">Blog</option>
56+
<option value="2">Projects</option>
57+
</select>
58+
<p class="error"><strong>section must be provided</strong></p>
59+
</li>
60+
61+
<li id="article_publication_state_id_input" class="required radio">
62+
<fieldset>
63+
<legend><span>Publication State</span></legend>
64+
<ol>
65+
<li>
66+
<label><input type="radio" id="article_publication_state_id_1" name="article[publication_state_id]" value="1" /> draft (hidden)</label>
67+
</li>
68+
<li>
69+
<label><input type="radio" id="article_publication_state_id_2" name="article[publication_state_id]" value="2" checked="checked" /> ready for publication (hidden)</label>
70+
</li>
71+
<li>
72+
<label><input type="radio" id="article_publication_state_id_3" name="article[publication_state_id]" value="3" checked="checked" /> published (visible)</label>
73+
</li>
74+
</ol>
75+
</fieldset>
76+
</li>
77+
78+
<li id="article_allow_comments_input" class="required checkbox">
79+
<input type="hidden" id="article_allow_comments_0" name="article[allow_comments]" value="0" />
80+
<label><input type="checkbox" id="article_allow_comments_1" name="article[allow_comments]" value="1" /> Allow commenting on this article</label>
81+
</li>
82+
</ol>
83+
</fieldset>
84+
85+
<fieldset class="buttons">
86+
<ol>
87+
<li class="primary">
88+
<input type="submit" name="commit" value="Create new Article" />
89+
</li>
90+
</ol>
91+
</fieldset>
92+
93+
</fieldset>
94+
</form>
95+
96+
</body>
97+
</html>
98+

init.rb

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
require File.join(File.dirname(__FILE__), 'lib', 'justin_french', 'formtastic')
2+
ActionView::Base.send :include, JustinFrench::Formtastic::SemanticFormHelper

install.rb

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
puts IO.read(File.join(File.dirname(__FILE__), 'README'))

0 commit comments

Comments
 (0)