muck-users 0.2.21 → 0.2.22
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/VERSION +1 -1
- data/app/models/user_mailer.rb +6 -14
- data/lib/muck_users.rb +1 -1
- data/muck-users.gemspec +3 -2
- data/test/rails_root/config/environment.rb +2 -1
- data/test/rails_root/public/images/admin/source/roles.png +0 -0
- data/test/rails_root/public/javascripts/jquery/jquery.form.js +495 -472
- data/test/rails_root/public/javascripts/jquery/jquery.tips.js +5 -0
- metadata +3 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.22
|
data/app/models/user_mailer.rb
CHANGED
@@ -5,50 +5,42 @@ class UserMailer < ActionMailer::Base
|
|
5
5
|
default_url_options[:host] = GlobalConfig.application_url
|
6
6
|
|
7
7
|
def activation_confirmation(user)
|
8
|
-
|
8
|
+
muck_setup_email(user)
|
9
9
|
subject I18n.t('muck.users.activation_complete')
|
10
10
|
body :user => user
|
11
11
|
end
|
12
12
|
|
13
13
|
def activation_instructions(user)
|
14
|
-
|
14
|
+
muck_setup_email(user)
|
15
15
|
subject I18n.t('muck.users.activation_instructions')
|
16
16
|
body :user => user,
|
17
17
|
:account_activation_url => activate_url(user.perishable_token)
|
18
18
|
end
|
19
19
|
|
20
20
|
def password_not_active_instructions(user)
|
21
|
-
|
21
|
+
muck_setup_email(user)
|
22
22
|
subject I18n.t('muck.users.account_not_activated', :application_name => GlobalConfig.application_name)
|
23
23
|
body :user => user
|
24
24
|
end
|
25
25
|
|
26
26
|
def password_reset_instructions(user)
|
27
|
-
|
27
|
+
muck_setup_email(user)
|
28
28
|
subject I18n.t('muck.users.password_reset_email_subject', :application_name => GlobalConfig.application_name)
|
29
29
|
body :user => user
|
30
30
|
end
|
31
31
|
|
32
32
|
def welcome_notification(user)
|
33
|
-
|
33
|
+
muck_setup_email(user)
|
34
34
|
subject I18n.t('muck.users.welcome_email_subject', :application_name => GlobalConfig.application_name)
|
35
35
|
body :user => user,
|
36
36
|
:application_name => GlobalConfig.application_name
|
37
37
|
end
|
38
38
|
|
39
39
|
def username_request(user)
|
40
|
-
|
40
|
+
muck_setup_email(user)
|
41
41
|
subject I18n.t('muck.users.request_username_subject', :application_name => GlobalConfig.application_name)
|
42
42
|
body :user => user,
|
43
43
|
:application_name => GlobalConfig.application_name
|
44
44
|
end
|
45
|
-
|
46
|
-
protected
|
47
|
-
def setup_email(user)
|
48
|
-
recipients user.email
|
49
|
-
from "#{GlobalConfig.from_email_name} <#{GlobalConfig.from_email}>"
|
50
|
-
sent_on Time.now
|
51
|
-
content_type "text/html" # There is a bug in Rails that prevents multipart emails from working inside an engine. See: https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/2263-rails-232-breaks-implicit-multipart-actionmailer-tests#ticket-2263-22
|
52
|
-
end
|
53
45
|
|
54
46
|
end
|
data/lib/muck_users.rb
CHANGED
@@ -13,4 +13,4 @@ I18n.load_path += Dir[ File.join(File.dirname(__FILE__), '..', 'locales', '*.{rb
|
|
13
13
|
MuckEngine.add_muck_admin_nav_item(I18n.translate('muck.engine.admin_users'), '/admin/users', '/images/admin/user.gif') rescue nil
|
14
14
|
|
15
15
|
# Add users to the dashboard
|
16
|
-
MuckEngine.add_muck_dashboard_item('admin/users/dashboard_widget')
|
16
|
+
MuckEngine.add_muck_dashboard_item('admin/users/dashboard_widget') rescue nil
|
data/muck-users.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{muck-users}
|
8
|
-
s.version = "0.2.
|
8
|
+
s.version = "0.2.22"
|
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{Easily add user signup, login and other features to your application}
|
14
14
|
s.email = %q{justin@tatemae.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -698,6 +698,7 @@ Gem::Specification.new do |s|
|
|
698
698
|
"test/rails_root/public/images/admin/roles.gif",
|
699
699
|
"test/rails_root/public/images/admin/source/Home.png",
|
700
700
|
"test/rails_root/public/images/admin/source/User.png",
|
701
|
+
"test/rails_root/public/images/admin/source/roles.png",
|
701
702
|
"test/rails_root/public/images/admin/user.gif",
|
702
703
|
"test/rails_root/public/images/arrow_down.gif",
|
703
704
|
"test/rails_root/public/images/arrow_left.gif",
|
@@ -1,4 +1,4 @@
|
|
1
|
-
RAILS_GEM_VERSION = '2.3.
|
1
|
+
RAILS_GEM_VERSION = '2.3.5' unless defined? RAILS_GEM_VERSION
|
2
2
|
|
3
3
|
require File.join(File.dirname(__FILE__), 'boot')
|
4
4
|
|
@@ -19,6 +19,7 @@ Rails::Initializer.run do |config|
|
|
19
19
|
config.gem "authlogic"
|
20
20
|
config.gem "searchlogic"
|
21
21
|
config.gem "bcrypt-ruby", :lib => "bcrypt"
|
22
|
+
config.gem "overlord"
|
22
23
|
config.gem 'muck-engine', :lib => 'muck_engine'
|
23
24
|
config.plugin_locators << TestGemLocator
|
24
25
|
end
|
Binary file
|
@@ -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);
|
@@ -12,6 +12,11 @@ jQuery(document).ready(function() {
|
|
12
12
|
var tip_text = field.siblings('.tip-text').html();
|
13
13
|
var tip_title = field.siblings('.tip-title').html();
|
14
14
|
var tip_position = field.siblings('.tip-position').html();
|
15
|
+
if(tip_text == null){
|
16
|
+
tip_text = field.parent().siblings('.tip-text').html();
|
17
|
+
tip_title = field.parent().siblings('.tip-title').html();
|
18
|
+
tip_position = field.parent().siblings('.tip-position').html();
|
19
|
+
}
|
15
20
|
if (!tip_position) { tip_position = 'right'; }
|
16
21
|
show_tip(control_id, tip_title, tip_text, tip_position);
|
17
22
|
jQuery("#" + help_id + "-container").addClass("active");
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: muck-users
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.22
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Ball
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2010-01-
|
13
|
+
date: 2010-01-20 00:00:00 -07:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -754,6 +754,7 @@ files:
|
|
754
754
|
- test/rails_root/public/images/admin/roles.gif
|
755
755
|
- test/rails_root/public/images/admin/source/Home.png
|
756
756
|
- test/rails_root/public/images/admin/source/User.png
|
757
|
+
- test/rails_root/public/images/admin/source/roles.png
|
757
758
|
- test/rails_root/public/images/admin/user.gif
|
758
759
|
- test/rails_root/public/images/arrow_down.gif
|
759
760
|
- test/rails_root/public/images/arrow_left.gif
|