edifice-forms 0.3.0

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.
@@ -0,0 +1,4 @@
1
+ Unobtrusive JS Form Extensions for rails 3.1
2
+ ======================================================
3
+
4
+ Builds on jquery-ujs to extend form functionality.
@@ -0,0 +1,3 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1 @@
1
+ //= require_tree ./edifice-forms
@@ -0,0 +1,120 @@
1
+ /**
2
+ * A small jQuery plugin to add 'rails-aware' form functionality.
3
+ *
4
+ * Basically, this understands the 'standard' rails way of structuring forms
5
+ * and makes some functions available to manipulate that.
6
+ */
7
+ (function($) {
8
+ $.fn.rails_form = function(method) {
9
+ if (methods[method]) {
10
+ return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
11
+ } else {
12
+ $.error('Method ' + method + ' does not exist on rails_form');
13
+ }
14
+ };
15
+
16
+ // in these 'this' is the $form
17
+ var methods = {
18
+ fields: function() {
19
+ return this.find('input, textarea, select');
20
+ },
21
+
22
+ error_fields: function() {
23
+ var $form = this;
24
+ return this.rails_form('fields').filter(function() {
25
+ return $form.rails_form('has_error', $(this));
26
+ });
27
+ },
28
+
29
+ submits: function() {
30
+ return this.find('input[type=submit], button[type=submit]');
31
+ },
32
+
33
+ label_for: function($field) {
34
+ return this.find('label[for=' + $field.attr('id') + ']');
35
+ },
36
+
37
+ error_on: function($field) {
38
+ return this.rails_form('label_for', $field).parents('.field_with_errors').next('.formError');
39
+ },
40
+
41
+ has_error: function($field) {
42
+ return $field.parent('.field_with_errors').length > 0;
43
+ },
44
+
45
+ clear_errors: function() {
46
+ var $form = this;
47
+ this.rails_form('fields').each(function() {
48
+ $form.rails_form('clear_error', $(this));
49
+ });
50
+
51
+ // clear base errors too
52
+ this.find('.errors').html('');
53
+ },
54
+
55
+ clear_error: function($field) {
56
+ var id = $field.attr('id');
57
+ if (this.rails_form('has_error', $field)) { $field.unwrap() }
58
+
59
+ this.find('.field_with_errors label[for=' + id + ']')
60
+ .unwrap()
61
+ .next('.formError').remove();
62
+
63
+ // remove from a .errors ul
64
+ this.find('.errors [data-for=' + id + ']').remove();
65
+
66
+ return this;
67
+ },
68
+
69
+ // display standard errors as returned by JSON
70
+ set_errors: function(errors) {
71
+ this.rails_form('clear_errors');
72
+ for (var name in errors) {
73
+ for (var i in errors[name]) {
74
+ this.rails_form('add_error', name, errors[name][i]);
75
+ }
76
+ }
77
+ return this;
78
+ },
79
+
80
+ add_error: function(name, error) {
81
+ var $field = this.rails_form('fields').filter('[name*=' + name + ']');
82
+ $field.filter('.field_with_errors > *').unwrap();
83
+ $field.wrap('<div class="field_with_errors">');
84
+
85
+ // if there is a field, and it has a label, show the error after it
86
+ if ($field.length) {
87
+ var id = $field.attr('id');
88
+ var $label = this.rails_form('label_for', $field);
89
+ var $error = $label.parent().next('.formError');
90
+
91
+ if ($error.length) {
92
+ $error.text(function(i, text) {
93
+ return text + ', ' + error;
94
+ });
95
+ } else {
96
+ $label.after('<div class="formError">' + error + '</div>')
97
+ .wrap('<div class="field_with_errors">');
98
+ }
99
+ }
100
+
101
+ // if there is an .errors list, show the error there
102
+ var $errors = this.find('ul.errors');
103
+ if ($errors.length) {
104
+ var message = name.charAt(0).toUpperCase() + name.substring(1).replace('_', ' ') +
105
+ ' ' + error;
106
+
107
+ var $li = $('<li>' + message + '</li>');
108
+
109
+ if ($field.length) {
110
+ $li.attr('data-for', $field.attr('id'));
111
+ }
112
+
113
+ $errors.append($li);
114
+ }
115
+
116
+ return this;
117
+ }
118
+ };
119
+
120
+ }(jQuery));
@@ -0,0 +1,23 @@
1
+ (function($) {
2
+ var showErrorSelector = 'form[data-show-errors]';
3
+
4
+ $(showErrorSelector).live('ajax:error', function(event, request, status, error) {
5
+ // CLIENT ERROR -- server-side validation failed. -- FIXME -should this be 422 only?
6
+ if (request.status >= 400 && request.status < 500) {
7
+ // if data is html, we replace this content of the form with the content
8
+ // of the form that we've just received back
9
+ var contentType = request.getResponseHeader('Content-Type');
10
+ if (/html/.test(contentType)) {
11
+ // wrap in a div incase there are a bunch of floating elements, pull the form out
12
+ var $new_form = $('<div>' + request.responseText + '</div>').find('#' + $(this).attr('id'));
13
+ $(this).html($new_form.html());
14
+
15
+ } else if (/json/.test(contentType)) {
16
+ // we will be receiving an error object back, we can pass it straight into rails_form.js
17
+ $(this).rails_form('set_errors', $.parseJSON(request.responseText));
18
+ } else {
19
+ throw "edifice-forms/show-errors: Don't know how to handle dataType " + request.dataType;
20
+ }
21
+ }
22
+ });
23
+ }(jQuery));
@@ -0,0 +1,18 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require "edifice-forms/version"
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'edifice-forms'
6
+ s.version = EdificeForms::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.author = 'Tom Coleman'
9
+ s.email = 'tom@percolatestudio.com'
10
+ s.summary = 'Unobtrusive JS Form extensions'
11
+
12
+ s.add_dependency 'jquery-rails'
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+ end
@@ -0,0 +1,12 @@
1
+ require 'edifice-forms/helper'
2
+ require 'edifice-forms/controller'
3
+ require 'edifice-forms/form_model'
4
+ require 'edifice-forms/responder'
5
+
6
+ module EdificeForms
7
+ class Engine < Rails::Engine
8
+ end
9
+ end
10
+
11
+ ActionView::Base.send :include, EdificeForms::Helper
12
+ ActionController::Base.send :include, EdificeForms::Controller
@@ -0,0 +1,11 @@
1
+ module EdificeForms
2
+ module Controller
3
+ def self.included(controller)
4
+ controller.class_eval do
5
+ def self.responder
6
+ EdificeForms::Responder
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,46 @@
1
+ # kind of the evolution of the FormStruct
2
+
3
+ module EdificeForms
4
+ class FormModel
5
+ include ActiveModel::Validations
6
+ include ActiveModel::Conversion
7
+ extend ActiveModel::Naming
8
+ extend ActiveModel::Callbacks
9
+ define_model_callbacks :save
10
+
11
+ # more or less the same as activerecord's one
12
+ class RecordInvalid < Exception
13
+ attr_reader :record
14
+ def initialize(record)
15
+ @record = record
16
+ errors = @record.errors.full_messages.join(", ")
17
+ super(errors)
18
+ end
19
+ end
20
+
21
+ def initialize(attributes = {})
22
+ attributes.each { |n, v| send("#{n}=", v) if respond_to?("#{n}=") }
23
+ end
24
+
25
+ # default implementation, override as necessary
26
+ def save
27
+ run_callbacks :save do
28
+ valid?
29
+ end
30
+ end
31
+
32
+ def save!
33
+ save || raise(RecordInvalid.new(self))
34
+ end
35
+
36
+ def self.create(attributes = {})
37
+ form = new(attributes)
38
+ form.save
39
+ form
40
+ end
41
+
42
+ def persisted?
43
+ false
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,22 @@
1
+ module EdificeForms
2
+ module Helper
3
+ # not sure why there isn't something like this in rails
4
+ #
5
+ # render the errors on an object in a fairly standard way:
6
+ #
7
+ # <ul class="errors">
8
+ # <li data-for="name">Name cannot be blank</li>
9
+ # </ul>
10
+ def render_errors(builder)
11
+ errors = builder.object.errors
12
+ messages = errors.full_messages
13
+ content_tag :ul, :class => :errors do
14
+ output = ''
15
+ errors.each_with_index do |error, i|
16
+ output << content_tag(:li, :'data-for' => "#{builder.object_name}_#{error[0]}") { messages[i] }
17
+ end
18
+ output.html_safe
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,23 @@
1
+ # Basically a standard responder, but if
2
+ module EdificeForms
3
+ class Responder < ActionController::Responder
4
+ protected
5
+ # add the :u_e header to xhr error requests
6
+ def to_html
7
+ if controller.request.xhr? && !get? and has_errors? && default_action
8
+ render :action => default_action, :status => :unprocessable_entity, :layout => nil
9
+ else
10
+ super
11
+ end
12
+ end
13
+
14
+ # actually render something on successful updates
15
+ def to_format
16
+ unless get? or has_errors? or post?
17
+ display resource, :status => :ok
18
+ else
19
+ super
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,3 @@
1
+ module EdificeForms
2
+ VERSION = "0.3.0"
3
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: edifice-forms
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 3
9
+ - 0
10
+ version: 0.3.0
11
+ platform: ruby
12
+ authors:
13
+ - Tom Coleman
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-01-17 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: jquery-rails
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ description:
35
+ email: tom@percolatestudio.com
36
+ executables: []
37
+
38
+ extensions: []
39
+
40
+ extra_rdoc_files: []
41
+
42
+ files:
43
+ - README.md
44
+ - Rakefile
45
+ - app/assets/javascripts/edifice-forms.js
46
+ - app/assets/javascripts/edifice-forms/rails_form.js
47
+ - app/assets/javascripts/edifice-forms/show-errors.js
48
+ - edifice-forms.gemspec
49
+ - lib/edifice-forms.rb
50
+ - lib/edifice-forms/controller.rb
51
+ - lib/edifice-forms/form_model.rb
52
+ - lib/edifice-forms/helper.rb
53
+ - lib/edifice-forms/responder.rb
54
+ - lib/edifice-forms/version.rb
55
+ homepage:
56
+ licenses: []
57
+
58
+ post_install_message:
59
+ rdoc_options: []
60
+
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ hash: 3
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 3
78
+ segments:
79
+ - 0
80
+ version: "0"
81
+ requirements: []
82
+
83
+ rubyforge_project:
84
+ rubygems_version: 1.8.10
85
+ signing_key:
86
+ specification_version: 3
87
+ summary: Unobtrusive JS Form extensions
88
+ test_files: []
89
+
90
+ has_rdoc: