edifice-forms 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: