muck-engine 0.2.26 → 0.2.27
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/Rakefile +1 -9
- data/VERSION +1 -1
- data/app/models/basic_mailer.rb +2 -2
- data/lib/action_mailer/muck_mailer.rb +34 -0
- data/lib/muck_engine.rb +2 -1
- data/muck-engine.gemspec +10 -2
- data/public/javascripts/jquery/jquery.form.js +495 -472
- data/public/javascripts/jquery/jquery.tips.js +5 -0
- data/test/rails_root/app/models/user.rb +4 -0
- data/test/rails_root/app/models/user_session.rb +2 -0
- data/test/rails_root/config/environment.rb +3 -1
- data/test/rails_root/public/javascripts/jquery/jquery.tips.js +5 -0
- data/test/rails_root/test/functional/admin/default_controller_test.rb +3 -1
- metadata +17 -2
data/Rakefile
CHANGED
@@ -57,15 +57,7 @@ begin
|
|
57
57
|
gemspec.add_dependency "validation_reflection"
|
58
58
|
gemspec.add_dependency "will_paginate"
|
59
59
|
gemspec.add_dependency "git"
|
60
|
-
gemspec.
|
61
|
-
db/migrate/*.rb
|
62
|
-
app/**/**/**/*
|
63
|
-
config/*
|
64
|
-
locales/*
|
65
|
-
rails/*
|
66
|
-
test/*
|
67
|
-
lib/**/*
|
68
|
-
public/javascripts/* )
|
60
|
+
gemspec.add_development_dependency "shoulda"
|
69
61
|
end
|
70
62
|
Jeweler::RubyforgeTasks.new do |rubyforge|
|
71
63
|
rubyforge.doc_task = "rdoc"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.27
|
data/app/models/basic_mailer.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
class BasicMailer < ActionMailer::Base
|
2
|
-
|
2
|
+
|
3
3
|
def mail(options)
|
4
4
|
@recipients = options[:recipients] || GlobalConfig.support_email
|
5
5
|
@from = options[:from] || GlobalConfig.email_from
|
@@ -11,5 +11,5 @@ class BasicMailer < ActionMailer::Base
|
|
11
11
|
@charset = options[:charset] || "utf-8"
|
12
12
|
@content_type = options[:content_type] || "text/plain"
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module ActionMailer
|
2
|
+
|
3
|
+
module MuckMailer #:nodoc:
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
# All the methods available to a record that has had <tt>acts_as_muck_user</tt> specified.
|
9
|
+
module InstanceMethods
|
10
|
+
|
11
|
+
protected
|
12
|
+
def muck_setup_email(user)
|
13
|
+
if user.is_a?(String)
|
14
|
+
recipients user
|
15
|
+
else
|
16
|
+
recipients user.email
|
17
|
+
end
|
18
|
+
from "#{GlobalConfig.from_email_name} <#{GlobalConfig.from_email}>"
|
19
|
+
sent_on Time.now
|
20
|
+
content_type "text/html" # There is a bug in Rails that prevents multipart emails from working inside an engine.
|
21
|
+
# See: https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/2263-rails-232-breaks-implicit-multipart-actionmailer-tests#ticket-2263-22
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.included(receiver)
|
27
|
+
receiver.extend ClassMethods
|
28
|
+
receiver.class_eval do
|
29
|
+
include InstanceMethods
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
data/lib/muck_engine.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
|
2
2
|
ActionController::Base.send :include, ActionController::MuckApplication
|
3
3
|
ActiveRecord::Base.send :include, ActiveRecord::MuckModel
|
4
|
+
ActionMailer::Base.send :include, ActionMailer::MuckMailer
|
4
5
|
ActionController::Base.send :helper, MuckEngineHelper
|
5
6
|
ActionController::Base.send :helper, MuckAdminHelper
|
6
7
|
|
@@ -47,7 +48,7 @@ class MuckEngine
|
|
47
48
|
@@muck_dashboard_items << OpenStruct.new(:path => path,
|
48
49
|
:locals => locals)
|
49
50
|
end
|
50
|
-
|
51
|
+
|
51
52
|
end
|
52
53
|
|
53
54
|
# Add a link to admin home
|
data/muck-engine.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{muck-engine}
|
8
|
-
s.version = "0.2.
|
8
|
+
s.version = "0.2.27"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Justin Ball", "Joel Duffin"]
|
12
|
-
s.date = %q{2010-01-
|
12
|
+
s.date = %q{2010-01-20}
|
13
13
|
s.description = %q{The base engine for the muck system. Contains common tables, custom for, css and javascript.}
|
14
14
|
s.email = %q{justin@tatemae.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -65,6 +65,7 @@ Gem::Specification.new do |s|
|
|
65
65
|
"db/migrate/20090426041103_create_states.rb",
|
66
66
|
"install.rb",
|
67
67
|
"lib/action_controller/muck_application.rb",
|
68
|
+
"lib/action_mailer/muck_mailer.rb",
|
68
69
|
"lib/active_record/muck_model.rb",
|
69
70
|
"lib/muck_engine.rb",
|
70
71
|
"lib/muck_engine/initialize_routes.rb",
|
@@ -710,6 +711,8 @@ Gem::Specification.new do |s|
|
|
710
711
|
"test/rails_root/app/controllers/default_controller.rb",
|
711
712
|
"test/rails_root/app/helpers/application_helper.rb",
|
712
713
|
"test/rails_root/app/models/.keep",
|
714
|
+
"test/rails_root/app/models/user.rb",
|
715
|
+
"test/rails_root/app/models/user_session.rb",
|
713
716
|
"test/rails_root/app/views/admin/default/index.html.erb",
|
714
717
|
"test/rails_root/app/views/default/index.html.erb",
|
715
718
|
"test/rails_root/app/views/layouts/default.html.erb",
|
@@ -1308,6 +1311,8 @@ Gem::Specification.new do |s|
|
|
1308
1311
|
"test/rails_root/app/controllers/application_controller.rb",
|
1309
1312
|
"test/rails_root/app/controllers/default_controller.rb",
|
1310
1313
|
"test/rails_root/app/helpers/application_helper.rb",
|
1314
|
+
"test/rails_root/app/models/user.rb",
|
1315
|
+
"test/rails_root/app/models/user_session.rb",
|
1311
1316
|
"test/rails_root/config/boot.rb",
|
1312
1317
|
"test/rails_root/config/environment.rb",
|
1313
1318
|
"test/rails_root/config/environments/development.rb",
|
@@ -1344,15 +1349,18 @@ Gem::Specification.new do |s|
|
|
1344
1349
|
s.add_runtime_dependency(%q<validation_reflection>, [">= 0"])
|
1345
1350
|
s.add_runtime_dependency(%q<will_paginate>, [">= 0"])
|
1346
1351
|
s.add_runtime_dependency(%q<git>, [">= 0"])
|
1352
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
1347
1353
|
else
|
1348
1354
|
s.add_dependency(%q<validation_reflection>, [">= 0"])
|
1349
1355
|
s.add_dependency(%q<will_paginate>, [">= 0"])
|
1350
1356
|
s.add_dependency(%q<git>, [">= 0"])
|
1357
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
1351
1358
|
end
|
1352
1359
|
else
|
1353
1360
|
s.add_dependency(%q<validation_reflection>, [">= 0"])
|
1354
1361
|
s.add_dependency(%q<will_paginate>, [">= 0"])
|
1355
1362
|
s.add_dependency(%q<git>, [">= 0"])
|
1363
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
1356
1364
|
end
|
1357
1365
|
end
|
1358
1366
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
2
|
* jQuery Form Plugin
|
3
|
-
* version: 2.
|
4
|
-
* @requires jQuery v1.2.
|
3
|
+
* version: 2.36 (07-NOV-2009)
|
4
|
+
* @requires jQuery v1.2.6 or later
|
5
5
|
*
|
6
6
|
* Examples and documentation at: http://malsup.com/jquery/form/
|
7
7
|
* Dual licensed under the MIT and GPL licenses:
|
@@ -11,32 +11,32 @@
|
|
11
11
|
;(function($) {
|
12
12
|
|
13
13
|
/*
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
14
|
+
Usage Note:
|
15
|
+
-----------
|
16
|
+
Do not use both ajaxSubmit and ajaxForm on the same form. These
|
17
|
+
functions are intended to be exclusive. Use ajaxSubmit if you want
|
18
|
+
to bind your own submit handler to the form. For example,
|
19
|
+
|
20
|
+
$(document).ready(function() {
|
21
|
+
$('#myForm').bind('submit', function() {
|
22
|
+
$(this).ajaxSubmit({
|
23
|
+
target: '#output'
|
24
|
+
});
|
25
|
+
return false; // <-- important!
|
26
|
+
});
|
27
|
+
});
|
28
|
+
|
29
|
+
Use ajaxForm when you want the plugin to manage all the event binding
|
30
|
+
for you. For example,
|
31
|
+
|
32
|
+
$(document).ready(function() {
|
33
|
+
$('#myForm').ajaxForm({
|
34
|
+
target: '#output'
|
35
|
+
});
|
36
|
+
});
|
37
|
+
|
38
|
+
When using ajaxForm, the ajaxSubmit function will be invoked for you
|
39
|
+
at the appropriate time.
|
40
40
|
*/
|
41
41
|
|
42
42
|
/**
|
@@ -44,184 +44,192 @@
|
|
44
44
|
* an HTML form using AJAX.
|
45
45
|
*/
|
46
46
|
$.fn.ajaxSubmit = function(options) {
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
47
|
+
// fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
|
48
|
+
if (!this.length) {
|
49
|
+
log('ajaxSubmit: skipping submit process - no element selected');
|
50
|
+
return this;
|
51
|
+
}
|
52
|
+
|
53
|
+
if (typeof options == 'function')
|
54
|
+
options = { success: options };
|
55
|
+
|
56
|
+
var url = $.trim(this.attr('action'));
|
57
|
+
if (url) {
|
58
|
+
// clean url (don't include hash vaue)
|
59
|
+
url = (url.match(/^([^#]+)/)||[])[1];
|
60
|
+
}
|
61
|
+
url = url || window.location.href || '';
|
62
|
+
|
63
|
+
options = $.extend({
|
64
|
+
url: url,
|
65
|
+
type: this.attr('method') || 'GET',
|
66
|
+
iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
|
67
|
+
}, options || {});
|
68
|
+
|
69
|
+
// hook for manipulating the form data before it is extracted;
|
70
|
+
// convenient for use with rich editors like tinyMCE or FCKEditor
|
71
|
+
var veto = {};
|
72
|
+
this.trigger('form-pre-serialize', [this, options, veto]);
|
73
|
+
if (veto.veto) {
|
74
|
+
log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
|
75
|
+
return this;
|
76
|
+
}
|
77
|
+
|
78
|
+
// provide opportunity to alter form data before it is serialized
|
79
|
+
if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
|
80
|
+
log('ajaxSubmit: submit aborted via beforeSerialize callback');
|
81
|
+
return this;
|
82
|
+
}
|
83
|
+
|
84
|
+
var a = this.formToArray(options.semantic);
|
85
|
+
if (options.data) {
|
86
|
+
options.extraData = options.data;
|
87
|
+
for (var n in options.data) {
|
88
|
+
if(options.data[n] instanceof Array) {
|
89
|
+
for (var k in options.data[n])
|
90
|
+
a.push( { name: n, value: options.data[n][k] } );
|
91
|
+
}
|
92
|
+
else
|
93
|
+
a.push( { name: n, value: options.data[n] } );
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
// give pre-submit callback an opportunity to abort the submit
|
98
|
+
if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
|
99
|
+
log('ajaxSubmit: submit aborted via beforeSubmit callback');
|
100
|
+
return this;
|
101
|
+
}
|
102
|
+
|
103
|
+
// fire vetoable 'validate' event
|
104
|
+
this.trigger('form-submit-validate', [a, this, options, veto]);
|
105
|
+
if (veto.veto) {
|
106
|
+
log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
|
107
|
+
return this;
|
108
|
+
}
|
109
|
+
|
110
|
+
var q = $.param(a);
|
111
|
+
|
112
|
+
if (options.type.toUpperCase() == 'GET') {
|
113
|
+
options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
|
114
|
+
options.data = null; // data is null for 'get'
|
115
|
+
}
|
116
|
+
else
|
117
|
+
options.data = q; // data is the query string for 'post'
|
118
|
+
|
119
|
+
var $form = this, callbacks = [];
|
120
|
+
if (options.resetForm) callbacks.push(function() { $form.resetForm(); });
|
121
|
+
if (options.clearForm) callbacks.push(function() { $form.clearForm(); });
|
122
|
+
|
123
|
+
// perform a load on the target only if dataType is not provided
|
124
|
+
if (!options.dataType && options.target) {
|
125
|
+
var oldSuccess = options.success || function(){};
|
126
|
+
callbacks.push(function(data) {
|
127
|
+
$(options.target).html(data).each(oldSuccess, arguments);
|
128
|
+
});
|
129
|
+
}
|
130
|
+
else if (options.success)
|
131
|
+
callbacks.push(options.success);
|
132
|
+
|
133
|
+
options.success = function(data, status) {
|
134
|
+
for (var i=0, max=callbacks.length; i < max; i++)
|
135
|
+
callbacks[i].apply(options, [data, status, $form]);
|
136
|
+
};
|
137
|
+
|
138
|
+
// are there files to upload?
|
139
|
+
var files = $('input:file', this).fieldValue();
|
140
|
+
var found = false;
|
141
|
+
for (var j=0; j < files.length; j++)
|
142
|
+
if (files[j])
|
143
|
+
found = true;
|
144
|
+
|
145
|
+
var multipart = false;
|
146
|
+
// var mp = 'multipart/form-data';
|
147
|
+
// multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
|
148
|
+
|
149
|
+
// options.iframe allows user to force iframe mode
|
150
|
+
// 06-NOV-09: now defaulting to iframe mode if file input is detected
|
151
|
+
if ((files.length && options.iframe !== false) || options.iframe || found || multipart) {
|
152
|
+
// hack to fix Safari hang (thanks to Tim Molendijk for this)
|
153
|
+
// see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
|
154
|
+
if (options.closeKeepAlive)
|
155
|
+
$.get(options.closeKeepAlive, fileUpload);
|
156
|
+
else
|
157
|
+
fileUpload();
|
158
|
+
}
|
151
159
|
else
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
var s =
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
160
|
+
$.ajax(options);
|
161
|
+
|
162
|
+
// fire 'notify' event
|
163
|
+
this.trigger('form-submit-notify', [this, options]);
|
164
|
+
return this;
|
165
|
+
|
166
|
+
|
167
|
+
// private function for handling file uploads (hat tip to YAHOO!)
|
168
|
+
function fileUpload() {
|
169
|
+
var form = $form[0];
|
170
|
+
|
171
|
+
if ($(':input[name=submit]', form).length) {
|
172
|
+
alert('Error: Form elements must not be named "submit".');
|
173
|
+
return;
|
174
|
+
}
|
175
|
+
|
176
|
+
var opts = $.extend({}, $.ajaxSettings, options);
|
177
|
+
var s = $.extend(true, {}, $.extend(true, {}, $.ajaxSettings), opts);
|
178
|
+
|
179
|
+
var id = 'jqFormIO' + (new Date().getTime());
|
180
|
+
var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+ opts.iframeSrc +'" />');
|
181
|
+
var io = $io[0];
|
182
|
+
|
183
|
+
$io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
|
184
|
+
|
185
|
+
var xhr = { // mock object
|
186
|
+
aborted: 0,
|
187
|
+
responseText: null,
|
188
|
+
responseXML: null,
|
189
|
+
status: 0,
|
190
|
+
statusText: 'n/a',
|
191
|
+
getAllResponseHeaders: function() {},
|
192
|
+
getResponseHeader: function() {},
|
193
|
+
setRequestHeader: function() {},
|
194
|
+
abort: function() {
|
195
|
+
this.aborted = 1;
|
196
|
+
$io.attr('src', opts.iframeSrc); // abort op in progress
|
197
|
+
}
|
198
|
+
};
|
199
|
+
|
200
|
+
var g = opts.global;
|
201
|
+
// trigger ajax global events so that activity/block indicators work like normal
|
202
|
+
if (g && ! $.active++) $.event.trigger("ajaxStart");
|
203
|
+
if (g) $.event.trigger("ajaxSend", [xhr, opts]);
|
196
204
|
|
197
205
|
if (s.beforeSend && s.beforeSend(xhr, s) === false) {
|
198
|
-
s.global &&
|
206
|
+
s.global && $.active--;
|
207
|
+
return;
|
208
|
+
}
|
209
|
+
if (xhr.aborted)
|
199
210
|
return;
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
setTimeout(function() {
|
223
|
-
// make sure form attrs are set
|
224
|
-
var t = $form.attr('target'), a = $form.attr('action');
|
211
|
+
|
212
|
+
var cbInvoked = 0;
|
213
|
+
var timedOut = 0;
|
214
|
+
|
215
|
+
// add submitting element to data if we know it
|
216
|
+
var sub = form.clk;
|
217
|
+
if (sub) {
|
218
|
+
var n = sub.name;
|
219
|
+
if (n && !sub.disabled) {
|
220
|
+
options.extraData = options.extraData || {};
|
221
|
+
options.extraData[n] = sub.value;
|
222
|
+
if (sub.type == "image") {
|
223
|
+
options.extraData[name+'.x'] = form.clk_x;
|
224
|
+
options.extraData[name+'.y'] = form.clk_y;
|
225
|
+
}
|
226
|
+
}
|
227
|
+
}
|
228
|
+
|
229
|
+
// take a breath so that pending repaints get some cpu time before the upload starts
|
230
|
+
setTimeout(function() {
|
231
|
+
// make sure form attrs are set
|
232
|
+
var t = $form.attr('target'), a = $form.attr('action');
|
225
233
|
|
226
234
|
// update form attrs in IE friendly way
|
227
235
|
form.setAttribute('target',id);
|
@@ -230,112 +238,125 @@ $.fn.ajaxSubmit = function(options) {
|
|
230
238
|
if (form.getAttribute('action') != opts.url)
|
231
239
|
form.setAttribute('action', opts.url);
|
232
240
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
241
|
+
// ie borks in some cases when setting encoding
|
242
|
+
if (! options.skipEncodingOverride) {
|
243
|
+
$form.attr({
|
244
|
+
encoding: 'multipart/form-data',
|
245
|
+
enctype: 'multipart/form-data'
|
246
|
+
});
|
247
|
+
}
|
248
|
+
|
249
|
+
// support timout
|
250
|
+
if (opts.timeout)
|
251
|
+
setTimeout(function() { timedOut = true; cb(); }, opts.timeout);
|
252
|
+
|
253
|
+
// add "extra" data to form if provided in options
|
254
|
+
var extraInputs = [];
|
255
|
+
try {
|
256
|
+
if (options.extraData)
|
257
|
+
for (var n in options.extraData)
|
258
|
+
extraInputs.push(
|
259
|
+
$('<input type="hidden" name="'+n+'" value="'+options.extraData[n]+'" />')
|
260
|
+
.appendTo(form)[0]);
|
261
|
+
|
262
|
+
// add iframe to doc and submit the form
|
263
|
+
$io.appendTo('body');
|
264
|
+
io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
|
265
|
+
form.submit();
|
266
|
+
}
|
267
|
+
finally {
|
268
|
+
// reset attrs and remove "extra" input elements
|
261
269
|
form.setAttribute('action',a);
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
270
|
+
t ? form.setAttribute('target', t) : $form.removeAttr('target');
|
271
|
+
$(extraInputs).remove();
|
272
|
+
}
|
273
|
+
}, 10);
|
274
|
+
|
275
|
+
var domCheckCount = 50;
|
276
|
+
|
277
|
+
function cb() {
|
278
|
+
if (cbInvoked++) return;
|
279
|
+
|
280
|
+
io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);
|
281
|
+
|
282
|
+
var ok = true;
|
283
|
+
try {
|
284
|
+
if (timedOut) throw 'timeout';
|
285
|
+
// extract the server response from the iframe
|
286
|
+
var data, doc;
|
287
|
+
|
288
|
+
doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
|
289
|
+
|
290
|
+
var isXml = opts.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
|
291
|
+
log('isXml='+isXml);
|
292
|
+
if (!isXml && (doc.body == null || doc.body.innerHTML == '')) {
|
293
|
+
if (--domCheckCount) {
|
294
|
+
// in some browsers (Opera) the iframe DOM is not always traversable when
|
295
|
+
// the onload callback fires, so we loop a bit to accommodate
|
296
|
+
cbInvoked = 0;
|
297
|
+
setTimeout(cb, 100);
|
298
|
+
return;
|
299
|
+
}
|
300
|
+
log('Could not access iframe DOM after 50 tries.');
|
301
|
+
return;
|
302
|
+
}
|
303
|
+
|
304
|
+
xhr.responseText = doc.body ? doc.body.innerHTML : null;
|
305
|
+
xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
|
306
|
+
xhr.getResponseHeader = function(header){
|
307
|
+
var headers = {'content-type': opts.dataType};
|
308
|
+
return headers[header];
|
309
|
+
};
|
310
|
+
|
311
|
+
if (opts.dataType == 'json' || opts.dataType == 'script') {
|
312
|
+
// see if user embedded response in textarea
|
313
|
+
var ta = doc.getElementsByTagName('textarea')[0];
|
314
|
+
if (ta)
|
315
|
+
xhr.responseText = ta.value;
|
316
|
+
else {
|
317
|
+
// account for browsers injecting pre around json response
|
318
|
+
var pre = doc.getElementsByTagName('pre')[0];
|
319
|
+
if (pre)
|
320
|
+
xhr.responseText = pre.innerHTML;
|
321
|
+
}
|
322
|
+
}
|
323
|
+
else if (opts.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
|
324
|
+
xhr.responseXML = toXml(xhr.responseText);
|
325
|
+
}
|
326
|
+
data = $.httpData(xhr, opts.dataType);
|
327
|
+
}
|
328
|
+
catch(e){
|
329
|
+
ok = false;
|
330
|
+
$.handleError(opts, xhr, 'error', e);
|
331
|
+
}
|
332
|
+
|
333
|
+
// ordering of these callbacks/triggers is odd, but that's how $.ajax does it
|
334
|
+
if (ok) {
|
335
|
+
opts.success(data, 'success');
|
336
|
+
if (g) $.event.trigger("ajaxSuccess", [xhr, opts]);
|
337
|
+
}
|
338
|
+
if (g) $.event.trigger("ajaxComplete", [xhr, opts]);
|
339
|
+
if (g && ! --$.active) $.event.trigger("ajaxStop");
|
340
|
+
if (opts.complete) opts.complete(xhr, ok ? 'success' : 'error');
|
341
|
+
|
342
|
+
// clean up
|
343
|
+
setTimeout(function() {
|
344
|
+
$io.remove();
|
345
|
+
xhr.responseXML = null;
|
346
|
+
}, 100);
|
347
|
+
};
|
348
|
+
|
349
|
+
function toXml(s, doc) {
|
350
|
+
if (window.ActiveXObject) {
|
351
|
+
doc = new ActiveXObject('Microsoft.XMLDOM');
|
352
|
+
doc.async = 'false';
|
353
|
+
doc.loadXML(s);
|
354
|
+
}
|
355
|
+
else
|
356
|
+
doc = (new DOMParser()).parseFromString(s, 'text/xml');
|
357
|
+
return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null;
|
358
|
+
};
|
359
|
+
};
|
339
360
|
};
|
340
361
|
|
341
362
|
/**
|
@@ -344,9 +365,9 @@ $.fn.ajaxSubmit = function(options) {
|
|
344
365
|
* The advantages of using this method instead of ajaxSubmit() are:
|
345
366
|
*
|
346
367
|
* 1: This method will include coordinates for <input type="image" /> elements (if the element
|
347
|
-
*
|
368
|
+
* is used to submit the form).
|
348
369
|
* 2. This method will include the submit element's name/value data (for the element that was
|
349
|
-
*
|
370
|
+
* used to submit the form).
|
350
371
|
* 3. This method binds the submit() method to the form for you.
|
351
372
|
*
|
352
373
|
* The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely
|
@@ -354,40 +375,42 @@ $.fn.ajaxSubmit = function(options) {
|
|
354
375
|
* the form itself.
|
355
376
|
*/
|
356
377
|
$.fn.ajaxForm = function(options) {
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
378
|
+
return this.ajaxFormUnbind().bind('submit.form-plugin', function() {
|
379
|
+
$(this).ajaxSubmit(options);
|
380
|
+
return false;
|
381
|
+
}).bind('click.form-plugin', function(e) {
|
382
|
+
var target = e.target;
|
383
|
+
var $el = $(target);
|
384
|
+
if (!($el.is(":submit,input:image"))) {
|
385
|
+
// is this a child element of the submit el? (ex: a span within a button)
|
386
|
+
var t = $el.closest(':submit');
|
387
|
+
if (t.length == 0)
|
388
|
+
return;
|
389
|
+
target = t[0];
|
390
|
+
}
|
391
|
+
var form = this;
|
392
|
+
form.clk = target;
|
393
|
+
if (target.type == 'image') {
|
394
|
+
if (e.offsetX != undefined) {
|
395
|
+
form.clk_x = e.offsetX;
|
396
|
+
form.clk_y = e.offsetY;
|
397
|
+
} else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
|
398
|
+
var offset = $el.offset();
|
399
|
+
form.clk_x = e.pageX - offset.left;
|
400
|
+
form.clk_y = e.pageY - offset.top;
|
401
|
+
} else {
|
402
|
+
form.clk_x = e.pageX - target.offsetLeft;
|
403
|
+
form.clk_y = e.pageY - target.offsetTop;
|
404
|
+
}
|
405
|
+
}
|
406
|
+
// clear form vars
|
407
|
+
setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
|
408
|
+
});
|
382
409
|
};
|
383
410
|
|
384
411
|
// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
|
385
412
|
$.fn.ajaxFormUnbind = function() {
|
386
|
-
|
387
|
-
return this.each(function() {
|
388
|
-
$(":submit,input:image", this).unbind('click.form-plugin');
|
389
|
-
});
|
390
|
-
|
413
|
+
return this.unbind('submit.form-plugin click.form-plugin');
|
391
414
|
};
|
392
415
|
|
393
416
|
/**
|
@@ -402,44 +425,44 @@ $.fn.ajaxFormUnbind = function() {
|
|
402
425
|
* ajaxSubmit() and ajaxForm() methods.
|
403
426
|
*/
|
404
427
|
$.fn.formToArray = function(semantic) {
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
428
|
+
var a = [];
|
429
|
+
if (this.length == 0) return a;
|
430
|
+
|
431
|
+
var form = this[0];
|
432
|
+
var els = semantic ? form.getElementsByTagName('*') : form.elements;
|
433
|
+
if (!els) return a;
|
434
|
+
for(var i=0, max=els.length; i < max; i++) {
|
435
|
+
var el = els[i];
|
436
|
+
var n = el.name;
|
437
|
+
if (!n) continue;
|
438
|
+
|
439
|
+
if (semantic && form.clk && el.type == "image") {
|
440
|
+
// handle image inputs on the fly when semantic == true
|
441
|
+
if(!el.disabled && form.clk == el) {
|
442
|
+
a.push({name: n, value: $(el).val()});
|
443
|
+
a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
|
444
|
+
}
|
445
|
+
continue;
|
446
|
+
}
|
447
|
+
|
448
|
+
var v = $.fieldValue(el, true);
|
449
|
+
if (v && v.constructor == Array) {
|
450
|
+
for(var j=0, jmax=v.length; j < jmax; j++)
|
451
|
+
a.push({name: n, value: v[j]});
|
452
|
+
}
|
453
|
+
else if (v !== null && typeof v != 'undefined')
|
454
|
+
a.push({name: n, value: v});
|
455
|
+
}
|
456
|
+
|
457
|
+
if (!semantic && form.clk) {
|
458
|
+
// input type=='image' are not found in elements array! handle it here
|
459
|
+
var $input = $(form.clk), input = $input[0], n = input.name;
|
460
|
+
if (n && !input.disabled && input.type == 'image') {
|
461
|
+
a.push({name: n, value: $input.val()});
|
462
|
+
a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
|
463
|
+
}
|
464
|
+
}
|
465
|
+
return a;
|
443
466
|
};
|
444
467
|
|
445
468
|
/**
|
@@ -447,8 +470,8 @@ $.fn.formToArray = function(semantic) {
|
|
447
470
|
* in the format: name1=value1&name2=value2
|
448
471
|
*/
|
449
472
|
$.fn.formSerialize = function(semantic) {
|
450
|
-
|
451
|
-
|
473
|
+
//hand off to jQuery.param for proper encoding
|
474
|
+
return $.param(this.formToArray(semantic));
|
452
475
|
};
|
453
476
|
|
454
477
|
/**
|
@@ -456,32 +479,32 @@ $.fn.formSerialize = function(semantic) {
|
|
456
479
|
* This method will return a string in the format: name1=value1&name2=value2
|
457
480
|
*/
|
458
481
|
$.fn.fieldSerialize = function(successful) {
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
482
|
+
var a = [];
|
483
|
+
this.each(function() {
|
484
|
+
var n = this.name;
|
485
|
+
if (!n) return;
|
486
|
+
var v = $.fieldValue(this, successful);
|
487
|
+
if (v && v.constructor == Array) {
|
488
|
+
for (var i=0,max=v.length; i < max; i++)
|
489
|
+
a.push({name: n, value: v[i]});
|
490
|
+
}
|
491
|
+
else if (v !== null && typeof v != 'undefined')
|
492
|
+
a.push({name: this.name, value: v});
|
493
|
+
});
|
494
|
+
//hand off to jQuery.param for proper encoding
|
495
|
+
return $.param(a);
|
473
496
|
};
|
474
497
|
|
475
498
|
/**
|
476
499
|
* Returns the value(s) of the element in the matched set. For example, consider the following form:
|
477
500
|
*
|
478
501
|
* <form><fieldset>
|
479
|
-
*
|
480
|
-
*
|
481
|
-
*
|
482
|
-
*
|
483
|
-
*
|
484
|
-
*
|
502
|
+
* <input name="A" type="text" />
|
503
|
+
* <input name="A" type="text" />
|
504
|
+
* <input name="B" type="checkbox" value="B1" />
|
505
|
+
* <input name="B" type="checkbox" value="B2"/>
|
506
|
+
* <input name="C" type="radio" value="C1" />
|
507
|
+
* <input name="C" type="radio" value="C2" />
|
485
508
|
* </fieldset></form>
|
486
509
|
*
|
487
510
|
* var v = $(':text').fieldValue();
|
@@ -508,51 +531,51 @@ $.fn.fieldSerialize = function(successful) {
|
|
508
531
|
* for each element is returned.
|
509
532
|
*
|
510
533
|
* Note: This method *always* returns an array. If no valid value can be determined the
|
511
|
-
*
|
534
|
+
* array will be empty, otherwise it will contain one or more values.
|
512
535
|
*/
|
513
536
|
$.fn.fieldValue = function(successful) {
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
537
|
+
for (var val=[], i=0, max=this.length; i < max; i++) {
|
538
|
+
var el = this[i];
|
539
|
+
var v = $.fieldValue(el, successful);
|
540
|
+
if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length))
|
541
|
+
continue;
|
542
|
+
v.constructor == Array ? $.merge(val, v) : val.push(v);
|
543
|
+
}
|
544
|
+
return val;
|
522
545
|
};
|
523
546
|
|
524
547
|
/**
|
525
548
|
* Returns the value of the field element.
|
526
549
|
*/
|
527
550
|
$.fieldValue = function(el, successful) {
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
551
|
+
var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
|
552
|
+
if (typeof successful == 'undefined') successful = true;
|
553
|
+
|
554
|
+
if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
|
555
|
+
(t == 'checkbox' || t == 'radio') && !el.checked ||
|
556
|
+
(t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
|
557
|
+
tag == 'select' && el.selectedIndex == -1))
|
558
|
+
return null;
|
559
|
+
|
560
|
+
if (tag == 'select') {
|
561
|
+
var index = el.selectedIndex;
|
562
|
+
if (index < 0) return null;
|
563
|
+
var a = [], ops = el.options;
|
564
|
+
var one = (t == 'select-one');
|
565
|
+
var max = (one ? index+1 : ops.length);
|
566
|
+
for(var i=(one ? index : 0); i < max; i++) {
|
567
|
+
var op = ops[i];
|
568
|
+
if (op.selected) {
|
546
569
|
var v = op.value;
|
547
570
|
if (!v) // extra pain for IE...
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
571
|
+
v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
|
572
|
+
if (one) return v;
|
573
|
+
a.push(v);
|
574
|
+
}
|
575
|
+
}
|
576
|
+
return a;
|
577
|
+
}
|
578
|
+
return el.value;
|
556
579
|
};
|
557
580
|
|
558
581
|
/**
|
@@ -564,46 +587,46 @@ $.fieldValue = function(el, successful) {
|
|
564
587
|
* - button elements will *not* be effected
|
565
588
|
*/
|
566
589
|
$.fn.clearForm = function() {
|
567
|
-
|
568
|
-
|
569
|
-
|
590
|
+
return this.each(function() {
|
591
|
+
$('input,select,textarea', this).clearFields();
|
592
|
+
});
|
570
593
|
};
|
571
594
|
|
572
595
|
/**
|
573
596
|
* Clears the selected form elements.
|
574
597
|
*/
|
575
598
|
$.fn.clearFields = $.fn.clearInputs = function() {
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
599
|
+
return this.each(function() {
|
600
|
+
var t = this.type, tag = this.tagName.toLowerCase();
|
601
|
+
if (t == 'text' || t == 'password' || tag == 'textarea')
|
602
|
+
this.value = '';
|
603
|
+
else if (t == 'checkbox' || t == 'radio')
|
604
|
+
this.checked = false;
|
605
|
+
else if (tag == 'select')
|
606
|
+
this.selectedIndex = -1;
|
607
|
+
});
|
585
608
|
};
|
586
609
|
|
587
610
|
/**
|
588
611
|
* Resets the form data. Causes all form elements to be reset to their original value.
|
589
612
|
*/
|
590
613
|
$.fn.resetForm = function() {
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
614
|
+
return this.each(function() {
|
615
|
+
// guard against an input with the name of 'reset'
|
616
|
+
// note that IE reports the reset function as an 'object'
|
617
|
+
if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType))
|
618
|
+
this.reset();
|
619
|
+
});
|
597
620
|
};
|
598
621
|
|
599
622
|
/**
|
600
623
|
* Enables or disables any matching elements.
|
601
624
|
*/
|
602
625
|
$.fn.enable = function(b) {
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
626
|
+
if (b == undefined) b = true;
|
627
|
+
return this.each(function() {
|
628
|
+
this.disabled = !b;
|
629
|
+
});
|
607
630
|
};
|
608
631
|
|
609
632
|
/**
|
@@ -611,27 +634,27 @@ $.fn.enable = function(b) {
|
|
611
634
|
* selects/deselects and matching option elements.
|
612
635
|
*/
|
613
636
|
$.fn.selected = function(select) {
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
637
|
+
if (select == undefined) select = true;
|
638
|
+
return this.each(function() {
|
639
|
+
var t = this.type;
|
640
|
+
if (t == 'checkbox' || t == 'radio')
|
641
|
+
this.checked = select;
|
642
|
+
else if (this.tagName.toLowerCase() == 'option') {
|
643
|
+
var $sel = $(this).parent('select');
|
644
|
+
if (select && $sel[0] && $sel[0].type == 'select-one') {
|
645
|
+
// deselect all other options
|
646
|
+
$sel.find('option').selected(false);
|
647
|
+
}
|
648
|
+
this.selected = select;
|
649
|
+
}
|
650
|
+
});
|
628
651
|
};
|
629
652
|
|
630
653
|
// helper fn for console logging
|
631
654
|
// set $.fn.ajaxSubmit.debug to true to enable debug logging
|
632
655
|
function log() {
|
633
|
-
|
634
|
-
|
656
|
+
if ($.fn.ajaxSubmit.debug && window.console && window.console.log)
|
657
|
+
window.console.log('[jquery.form] ' + Array.prototype.join.call(arguments,''));
|
635
658
|
};
|
636
659
|
|
637
660
|
})(jQuery);
|