edifice 0.5.0 → 0.6.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.
@@ -1,3 +1,3 @@
1
1
  module Edifice
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -0,0 +1,103 @@
1
+ // add methods to a form element so it can be easily manipulated
2
+ //
3
+ // add client side validation
4
+ // understands:
5
+ // - rails form structures
6
+ // - rails form errors in JSON
7
+ // - etc
8
+ (function($) {
9
+ $.fn.edifice_form = function() {
10
+ $.extend(this, methods);
11
+ return this;
12
+ };
13
+
14
+ // VALIDATORS:
15
+ // validators expect a form element and return true or an error message
16
+ $.fn.edifice_form.validators = {
17
+ not_empty: function($input) {
18
+ return $input.val() ? true : 'must not be empty';
19
+ }
20
+ };
21
+
22
+
23
+ // in these 'this' is the $form
24
+ var methods = {
25
+ fields: function() {
26
+ return this.find('input, textarea, select');
27
+ },
28
+
29
+ error_fields: function() {
30
+ var $form = this;
31
+ return this.fields().filter(function() {
32
+ return $form.has_error($(this));
33
+ });
34
+ },
35
+
36
+ submits: function() {
37
+ return this.find('input[type=submit], button[type=submit]');
38
+ },
39
+
40
+ valid: function() {
41
+ var $form = this, valid = true;
42
+
43
+ this.fields().each(function() {
44
+ if (!$form.validate($(this))) { valid = false; }
45
+ });
46
+
47
+ return valid;
48
+ },
49
+
50
+ // 'prepare' a validator --> validator returns true or an error string
51
+ set_validator: function($field, validator) {
52
+ if (typeof validator === 'string') {
53
+ validator = $.fn.edifice_form.validators[validator] || validator;
54
+ if (typeof validator !== 'function') { throw "Validator not defined: '" + validator + "'"; }
55
+ };
56
+ $field.data('validator', validator);
57
+ },
58
+
59
+ // validate a single field
60
+ validate: function($field) {
61
+ var validator;
62
+ if (validator = $field.data('validator')) {
63
+ var error = validator($field), valid = error === true;
64
+ this.clear_error($field);
65
+ if (!valid) {
66
+ this.add_error($field, error);
67
+ }
68
+
69
+ return valid;
70
+ } else {
71
+ return true;
72
+ }
73
+ },
74
+
75
+ has_error: function($field) {
76
+ return $field.parent('.field_with_errors').length > 0;
77
+ },
78
+
79
+ clear_error: function($field) {
80
+ var id = $field.attr('id');
81
+ if (this.has_error($field)) { $field.unwrap() }
82
+
83
+ this.find('.field_with_errors label[for=' + id + ']')
84
+ .unwrap()
85
+ .next('.formError').remove();
86
+ },
87
+
88
+ add_error: function($field, error) {
89
+ var id = $field.attr('id');
90
+ $field.wrap('<div class="field_with_errors">');
91
+ this.find('label[for=' + id + ']')
92
+ .wrap('<div class="field_with_errors">')
93
+ .after('<div class="formError">' + error + '</div>');
94
+ },
95
+
96
+ set_errors: function(errors) {
97
+ for (var name in errors) {
98
+ this.add_error(this.fields().filter('[name*=' + name + ']'), errors[name][0]);
99
+ }
100
+ }
101
+ };
102
+
103
+ }(jQuery));
@@ -1,105 +1,138 @@
1
1
  (function($) {
2
- $.edifice = $.edifice || {};
3
-
4
- // add methods to a form element so it can be easily manipulated
5
- //
6
- // add client side validation
7
- // understands:
8
- // - rails form structures
9
- // - rails form errors in JSON
10
- // - etc
11
- $.fn.edifice_form = function() {
12
- $.extend(this, methods);
13
- return this;
14
- };
15
-
16
- // VALIDATORS:
17
- // validators expect a form element and return true or an error message
18
- $.fn.edifice_form.validators = {
19
- not_empty: function($input) {
20
- return $input.val() ? true : 'must not be empty';
21
- }
2
+ var defaults = {
3
+ status_element: this, // element to set to .submitting/.success/.error as we submit
4
+ // a hash of input selector -> validation functions/names
5
+ validators: {},
6
+ // stop the form from submitting and use ajax
7
+ ajax: true,
8
+ // type of data to pass around (and thus what's seen by e.g. success)
9
+ dataType: 'html'
22
10
  };
23
11
 
12
+ // EVENTS that fire during the course of the life of the submission:
13
+ // submit, invalid, success | error (+ user_error | server_error), complete
14
+ //
15
+ // -> success,errors + complete are all passed the data you would expect from
16
+ // jQuery.ajax
17
+ //
18
+ // obviously on submit + invalid fire for non-ajax forms
24
19
 
25
- // in these 'this' is the $form
26
- var methods = {
27
- fields: function() {
28
- return this.find('input, textarea, select');
29
- },
20
+ $.edifice_widgets.form = function() { return this.each(form); }
30
21
 
31
- error_fields: function() {
32
- var $form = this;
33
- return this.fields().filter(function() {
34
- return $form.has_error($(this));
35
- });
36
- },
22
+ function form() {
23
+ var $form = $(this).edifice_form();
24
+ $form.settings = $form.read_options(defaults);
25
+ $.extend($form, methods);
37
26
 
38
- submits: function() {
39
- return this.find('input[type=submit], button[type=submit]');
27
+ $form.initialize();
28
+ }
29
+ var methods = {
30
+ initialize: function() {
31
+ this.prepare_validators();
32
+ this.prepare_submit();
40
33
  },
41
34
 
42
- valid: function() {
43
- var $form = this, valid = true;
35
+ prepare_validators: function() {
36
+ var $form = this;
44
37
 
45
- this.fields().each(function() {
46
- if (!$form.validate($(this))) { valid = false; }
38
+ // setup validators from settings
39
+ for (var selector in $form.settings.validators) {
40
+ $form.set_validator($(selector), $form.settings.validators[selector]);
41
+ }
42
+
43
+ // setup validators from html
44
+ $form.fields().filter('[data-widget-validator]').each(function() {
45
+ $form.set_validator($(this), $(this).attr('data-widget-validator'));
47
46
  });
48
47
 
49
- return valid;
50
- },
51
-
52
- // 'prepare' a validator --> validator returns true or an error string
53
- set_validator: function($field, validator) {
54
- if (typeof validator === 'string') {
55
- validator = $.fn.edifice_form.validators[validator] || validator;
56
- if (typeof validator !== 'function') { throw "Validator not defined: '" + validator + "'"; }
57
- };
58
- $field.data('validator', validator);
48
+ // listen to validator
49
+ this.fields().live('change.ajax_form focusout.ajax_form', function() {
50
+ $form.validate($(this));
51
+ });
59
52
  },
60
53
 
61
- // validate a single field
62
- validate: function($field) {
63
- var validator;
64
- if (validator = $field.data('validator')) {
65
- var error = validator($field), valid = error === true;
66
- this.clear_error($field);
67
- if (!valid) {
68
- this.add_error($field, error);
54
+ prepare_submit: function() {
55
+ var $form = this;
56
+ this.submit(function(event) {
57
+ // do pre-submit validations
58
+ if (!$form.valid()) {
59
+ $form.trigger('invalid');
60
+ $form.focus_error();
61
+ return false; // we are done.
69
62
  }
63
+
64
+ $form.submits().attr('disabled', true); // disable submit buttons
65
+
66
+ // TODO - set status class
67
+ if ($form.settings.ajax && $form.settings.ajax !== 'false') {
68
+ // send up the form and process the results
69
+ $.ajax({
70
+ url: $form.attr('action'), type: $form.attr('method'),
71
+ dataType: $form.settings.dataType,
72
+ data: $.param($form.serializeArray()),
73
+ cache: false,
74
+ error: function (x, t, e) { $form.error(x, t, e); },
75
+ success: function (data, status) {
76
+ $form.trigger('success', data, status);
77
+ },
78
+ complete: function (request, text_status) {
79
+ $form.trigger('complete', request, text_status);
70
80
 
71
- return valid;
72
- } else {
73
- return true;
74
- }
75
- },
76
-
77
- has_error: function($field) {
78
- return $field.parent('.field_with_errors').length > 0;
81
+ $form.submits().removeAttr('disabled');
82
+ }
83
+ });
84
+ event.preventDefault();
85
+ return false;
86
+ }
87
+
88
+ });
79
89
  },
80
90
 
81
- clear_error: function($field) {
82
- var id = $field.attr('id');
83
- if (this.has_error($field)) { $field.unwrap() }
84
-
85
- this.find('.field_with_errors label[for=' + id + ']')
86
- .unwrap()
87
- .next('.formError').remove();
91
+ // focus the first error
92
+ focus_error: function() {
93
+ this.error_fields().eq(0).focus();
88
94
  },
89
95
 
90
- add_error: function($field, error) {
91
- var id = $field.attr('id');
92
- $field.wrap('<div class="field_with_errors">');
93
- this.find('label[for=' + id + ']')
94
- .wrap('<div class="field_with_errors">')
95
- .after('<div class="formError">' + error + '</div>');
96
+ error: function(request, text_status, error) {
97
+ this.trigger('error', request, status, error);
98
+
99
+ // handle the different possible errors that we can see
100
+ if (request.status >= 400 && request.status < 500) {
101
+ // CLIENT ERROR -- server-side validation failed.
102
+ this.trigger('client_error', request, status, error);
103
+
104
+ // if data is html, we replace this content of the form with the content
105
+ // of the form that we've just received back
106
+ if (this.settings.dataType === 'html') {
107
+ // wrap in a div incase there are a bunch of floating elements, pull the form out
108
+ var $new_form = $('<div>').append(request.responseText).find('#' + this.attr('id'));
109
+
110
+ this.html($new_form.html());
111
+ this.prepare_validators();
112
+
113
+ } else if (this.settings.dataType === 'json') {
114
+ // we will be receiving an error object back, we can pass it straight into form.js
115
+ this.set_errors($.parseJSON(request.responseText));
116
+ } else {
117
+ throw "Don't know how to handle dataType " + this.settings.dataType;
118
+ }
119
+
120
+ this.focus_error();
121
+ } else if (x.status >= 500 && x.status < 600) {
122
+ // a SERVER ERROR -- something unrecoverable happened on the server
123
+ this.trigger('server_error', request, status, error);
124
+
125
+ // we aren't going to do anything here.
126
+ // FIXME: we should probably have a way to set this behaviour at the application level.
127
+ // for instance, you probably just want to redirect to somewhere, or show a dialog,
128
+ // or popup something or.....?
129
+ } else {
130
+ // some other kind of error. Revisit
131
+ alert('Form failed. Please try again.');
132
+ }
133
+
134
+
96
135
  },
136
+ }
97
137
 
98
- set_errors: function(errors) {
99
- for (var name in errors) {
100
- this.add_error(this.fields().filter('[name*=' + name + ']'), errors[name][0]);
101
- }
102
- }
103
- };
104
-
105
138
  }(jQuery));
@@ -1,5 +1,5 @@
1
1
  <h1>Edit your Post</h1>
2
- <%= form_for @post, :html => {:'data-widget' => 'ajax_form', :'data-widget-dataType' => 'json',
2
+ <%= form_for @post, :html => {:'data-widget' => 'form', :'data-widget-ajax' => false,
3
3
  :'data-widget-validators' => ActiveSupport::JSON.encode({'#post_title' => 'not_empty'})} do |f| %>
4
4
  <%= f.label :email %>
5
5
  <%= f.error_message_on :email %>
@@ -38,7 +38,7 @@ module Rails3
38
38
 
39
39
  # JavaScript files you want as :defaults (application.js is always included).
40
40
  config.action_view.javascript_expansions[:defaults] = %w(
41
- jquery-1.5.1 edifice/framework edifice/form edifice/ajax_form
41
+ jquery-1.5.1 edifice/framework edifice/edifice_form edifice/form
42
42
  )
43
43
 
44
44
  # Configure the default encoding used in templates for Ruby 1.9.
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: edifice
3
3
  version: !ruby/object:Gem::Version
4
- hash: 11
4
+ hash: 7
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 5
8
+ - 6
9
9
  - 0
10
- version: 0.5.0
10
+ version: 0.6.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Tom Coleman
@@ -48,7 +48,7 @@ files:
48
48
  - lib/edifice/railtie.rb
49
49
  - lib/edifice/responder.rb
50
50
  - lib/edifice/version.rb
51
- - lib/public/javascripts/edifice/ajax_form.js
51
+ - lib/public/javascripts/edifice/edifice_form.js
52
52
  - lib/public/javascripts/edifice/form.js
53
53
  - lib/public/javascripts/edifice/framework.js
54
54
  - lib/tasks/edifice.rake
@@ -1,127 +0,0 @@
1
- (function($) {
2
- var defaults = {
3
- status_element: this, // element to set to .submitting/.success/.error as we submit
4
- // a hash of input selector -> validation functions/names
5
- validators: {},
6
- // type of data to pass around (and thus what's seen by e.g. success)
7
- dataType: 'html'
8
- };
9
-
10
- // EVENTS that fire during the course of the life of the submission:
11
- // submit, invalid, success | error (+ user_error | server_error), complete
12
- //
13
- // -> success,errors + complete are all passed the data you would expect from
14
- // jQuery.ajax
15
-
16
- $.edifice_widgets.ajax_form = function() { return this.each(ajax_form); }
17
-
18
- function ajax_form() {
19
- var $form = $(this).edifice_form();
20
- $form.settings = $form.read_options(defaults);
21
- $.extend($form, methods);
22
-
23
- $form.initialize();
24
- }
25
- var methods = {
26
- initialize: function() {
27
- this.prepare_validators();
28
- this.prepare_submit();
29
- },
30
-
31
- prepare_validators: function() {
32
- var $form = this;
33
-
34
- // setup validators from settings
35
- for (var selector in $form.settings.validators) {
36
- $form.set_validator($(selector), $form.settings.validators[selector]);
37
- }
38
-
39
- // setup validators from html
40
- $form.fields().filter('[data-widget-validator]').each(function() {
41
- $form.set_validator($(this), $(this).attr('data-widget-validator'));
42
- });
43
-
44
- // listen to validator
45
- this.fields().live('change.ajax_form focusout.ajax_form', function() {
46
- $form.validate($(this));
47
- });
48
- },
49
-
50
- prepare_submit: function() {
51
- var $form = this;
52
- this.submit(function(event) {
53
- event.preventDefault();
54
-
55
- // do pre-submit validations
56
- if (!$form.valid()) {
57
- $form.trigger('invalid');
58
- $form.error_fields().eq(0).focus(); // focus the first error
59
- return false; // we are done.
60
- }
61
-
62
- $form.submits().attr('disabled', true); // disable submit buttons
63
-
64
- // TODO - set status class
65
-
66
- // send up the form and process the results
67
- $.ajax({
68
- url: $form.attr('action'), type: $form.attr('method'),
69
- dataType: $form.settings.dataType,
70
- data: $.param($form.serializeArray()),
71
- cache: false,
72
- error: function (x, t, e) { $form.error(x, t, e); },
73
- success: function (data, status) {
74
- $form.trigger('success', data, status);
75
- },
76
- complete: function (request, text_status) {
77
- $form.trigger('complete', request, text_status);
78
-
79
- $form.submits().removeAttr('disabled');
80
- }
81
- });
82
-
83
- return false;
84
- });
85
- },
86
-
87
- error: function(request, text_status, error) {
88
- this.trigger('error', request, status, error);
89
-
90
- // handle the different possible errors that we can see
91
- if (request.status >= 400 && request.status < 500) {
92
- // CLIENT ERROR -- server-side validation failed.
93
- this.trigger('client_error', request, status, error);
94
-
95
- // if data is html, we replace this content of the form with the content
96
- // of the form that we've just received back
97
- if (this.settings.dataType === 'html') {
98
- // wrap in a div incase there are a bunch of floating elements, pull the form out
99
- var $new_form = $('<div>').append(request.responseText).find('#' + this.attr('id'));
100
-
101
- this.html($new_form.html());
102
- this.prepare_validators();
103
-
104
- } else if (this.settings.dataType === 'json') {
105
- // we will be receiving an error object back, we can pass it straight into form.js
106
- this.set_errors($.parseJSON(request.responseText));
107
- } else {
108
- throw "Don't know how to handle dataType " + this.settings.dataType;
109
- }
110
- } else if (x.status >= 500 && x.status < 600) {
111
- // a SERVER ERROR -- something unrecoverable happened on the server
112
- this.trigger('server_error', request, status, error);
113
-
114
- // we aren't going to do anything here.
115
- // FIXME: we should probably have a way to set this behaviour at the application level.
116
- // for instance, you probably just want to redirect to somewhere, or show a dialog,
117
- // or popup something or.....?
118
- } else {
119
- // some other kind of error. Revisit
120
- alert('Form failed. Please try again.');
121
- }
122
-
123
-
124
- },
125
- }
126
-
127
- }(jQuery));