PluginProbe
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions / 110815
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions v110815
260913 260909 260829 260814 260805 110710 110731 110812 110815 110912 110913 110915 110926 110927 111002 111003 111011 111017 111029 111105 111206 111216 111220 120213 120219 All 188 releases
s2member / includes / s2member.js

s2member.js in s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions 110815, at includes/s2member.js

527 lines 23.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Core JavaScript file for the s2Member plugin.
3 *
4 * This is the development version of the code.
5 * Which ultimately produces s2member-min.js.
6 *
7 * Copyright: © 2009-2011
8 * {@link http://www.websharks-inc.com/ WebSharks, Inc.}
9 * ( coded in the USA )
10 *
11 * Released under the terms of the GNU General Public License.
12 * You should have received a copy of the GNU General Public License,
13 * along with this software. In the main directory, see: /licensing/
14 * If not, see: {@link http://www.gnu.org/licenses/}.
15 *
16 * @package s2Member
17 * @since 3.0
18 */
19 /*
20 Scripting routines handled on document ready state.
21 */
22 jQuery(document).ready (function($)
23 {
24 ws_plugin__s2member_uniqueFilesDownloaded = []; /* Real-time counts. */
25 /* This is used in case a user downloads multiple files from a single page. */
26 /**/
27 var bpRegisterSlug = '<?php echo c_ws_plugin__s2member_utils_strings::esc_sq (preg_quote ((c_ws_plugin__s2member_utils_conds::bp_is_installed ()) ? "/" . ltrim (BP_REGISTER_SLUG,"/") : ""), "/"); ?>';
28 var bpxProfileSlug = '<?php echo c_ws_plugin__s2member_utils_strings::esc_sq (preg_quote ((c_ws_plugin__s2member_utils_conds::bp_is_installed ()) ? "/" . ltrim (BP_XPROFILE_SLUG,"/") : ""), "/"); ?>';
29 /**/
30 if (S2MEMBER_CURRENT_USER_IS_LOGGED_IN && S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY < S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED)
31 {
32 $('a[href*="s2member_file_download"]').click (function()
33 {
34 if (!this.href.match (/s2member_file_download_key\=(.+)/i))
35 {
36 var c = '** Please Confirm This File Download **\n\n';
37 c += 'You\'ve downloaded ' + S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY + ' protected file' + ((S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY !== 1) ? 's' : '') + ' in the last ' + S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS + ' days.\n\n';
38 c += 'You\'re entitled to ' + ((S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED) ? 'UNLIMITED downloads though ( so, no worries ).' : S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED + ' unique downloads every ' + S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS + ' day period.');
39 /**/
40 if (this.href.match (/s2member_skip_confirmation/i) || confirm(c))
41 {
42 if ($.inArray (this.href, ws_plugin__s2member_uniqueFilesDownloaded) === -1) /* Real-time counting. */
43 ws_plugin__s2member_uniqueFilesDownloaded.push (this.href), S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY++;
44 return true; /* Allow. */
45 }
46 else /* Disallow. */
47 return false;
48 }
49 else /* Allow. */
50 return true;
51 });
52 }
53 /*
54 Deals with form field validation on Profile editing panels.
55 `[s2Member-Profile /]` could appear on any Post/Page/Widget.
56 */
57 if (!location.href.match (/\/wp-admin\//))
58 {
59 $('input#ws-plugin--s2member-profile-password1, input#ws-plugin--s2member-profile-password2').keyup (function()
60 {
61 ws_plugin__s2member_passwordStrength($('input#ws-plugin--s2member-profile-login'), $('input#ws-plugin--s2member-profile-password1'), $('input#ws-plugin--s2member-profile-password2'), $('div#ws-plugin--s2member-profile-password-strength'));
62 });
63 /**/
64 $('form#ws-plugin--s2member-profile').submit (function()
65 {
66 var context = this, label = '', error = '', errors = '';
67 /**/
68 var $password1 = $('input#ws-plugin--s2member-profile-password1', context);
69 var $password2 = $('input#ws-plugin--s2member-profile-password2', context);
70 /**/
71 var $submissionButton = $('input#ws-plugin--s2member-profile-submit', context);
72 /**/
73 $(':input', context).each (function() /* Go through them all together. */
74 {
75 var id = $.trim ($(this).attr ('id')).replace (/-[0-9]+$/g, ''); /* Remove numeric suffixes. */
76 /**/
77 if (id && (label = $.trim ($('label[for="' + id + '"]', context).first ().children ('strong').first ().text ().replace (/[\r\n\t]+/g, ' '))))
78 {
79 if (error = ws_plugin__s2member_validationErrors(label, this, context))
80 errors += error + '\n\n'; /* Collect errors. */
81 }
82 });
83 /**/
84 if (errors = $.trim (errors))
85 {
86 alert('— Oops, you missed something: —\n\n' + errors);
87 /**/
88 return false;
89 }
90 /**/
91 else if ($.trim ($password1.val ()) && $.trim ($password1.val ()) !== $.trim ($password2.val ()))
92 {
93 alert('— Oops, you missed something: —\n\nPasswords do not match up. Please try again.');
94 /**/
95 return false;
96 }
97 /**/
98 ws_plugin__s2member_animateProcessing($submissionButton);
99 /**/
100 return true;
101 });
102 }
103 /*
104 Attach form submission handler to `/wp-signup.php`.
105 */
106 if (location.href.match (/\/wp-signup\.php/))
107 {
108 $('div#content > div.mu_register > form#setupform').submit (function()
109 {
110 var context = this, label = '', error = '', errors = '';
111 /**/
112 $('input#user_email', context).attr ('data-expected', 'email');
113 /**/
114 var $submissionButton = $('p.submit input[type="submit"]', context);
115 /**/
116 $('input#user_name, input#user_email, input#blogname, input#blog_title, input#captcha_code', context).attr ({'aria-required': 'true'});
117 /**/
118 $(':input', context).each (function() /* Go through them all together. */
119 {
120 var id = $.trim ($(this).attr ('id')).replace (/-[0-9]+$/g, ''); /* Remove numeric suffixes. */
121 /**/
122 if (id && (label = $.trim ($('label[for="' + id + '"]', context).first ().text ().replace (/[\r\n\t]+/g, ' '))))
123 {
124 if (error = ws_plugin__s2member_validationErrors(label, this, context))
125 errors += error + '\n\n'; /* Collect errors. */
126 }
127 });
128 /**/
129 if (errors = $.trim (errors))
130 {
131 alert('— Oops, you missed something: —\n\n' + errors);
132 /**/
133 return false;
134 }
135 /**/
136 ws_plugin__s2member_animateProcessing($submissionButton);
137 /**/
138 return true;
139 });
140 }
141 /*
142 Attach form submission handler to `/wp-login.php?action=register`.
143 */
144 else if (location.href.match (/\/wp-login\.php/))
145 {
146 $('input#ws-plugin--s2member-custom-reg-field-user-pass1, input#ws-plugin--s2member-custom-reg-field-user-pass2').keyup (function()
147 {
148 ws_plugin__s2member_passwordStrength($('input#user_login'), $('input#ws-plugin--s2member-custom-reg-field-user-pass1'), $('input#ws-plugin--s2member-custom-reg-field-user-pass2'), $('div#ws-plugin--s2member-custom-reg-field-user-pass-strength'));
149 });
150 /**/
151 $('div#login > form#registerform input#wp-submit').attr ('tabindex', '1000'); /* Makes plenty of room ( i.e. tab indexes ) for Custom Registration Fields. */
152 /**/
153 $('div#login > form#registerform').submit (function()
154 {
155 var context = this, label = '', error = '', errors = '';
156 /**/
157 $('input#user_email', context).attr ('data-expected', 'email');
158 /**/
159 var $pass1 = $('input#ws-plugin--s2member-custom-reg-field-user-pass1[aria-required="true"]', context);
160 var $pass2 = $('input#ws-plugin--s2member-custom-reg-field-user-pass2', context);
161 /**/
162 var $submissionButton = $('input#wp-submit', context); /* Registration submission button. */
163 /**/
164 $('input#user_login, input#user_email, input#captcha_code', context).attr ({'aria-required': 'true'});
165 /**/
166 $(':input', context).each (function() /* Go through them all together. */
167 {
168 var id = $.trim ($(this).attr ('id')).replace (/-[0-9]+$/g, ''); /* Remove numeric suffixes. */
169 /**/
170 if ($.inArray (id, ['user_login', 'user_email', 'captcha_code']) !== -1) /* No for="" attribute on these fields. */
171 {
172 if ((label = $.trim ($(this).parent ('label').text ().replace (/[\r\n\t]+/g, ' ')))) /* Use label. */
173 {
174 if (error = ws_plugin__s2member_validationErrors(label, this, context))
175 errors += error + '\n\n'; /* Collect errors. */
176 }
177 }
178 else if (id && (label = $.trim ($('label[for="' + id + '"]', context).first ().children ('span').first ().text ().replace (/[\r\n\t]+/g, ' '))))
179 {
180 if (error = ws_plugin__s2member_validationErrors(label, this, context))
181 errors += error + '\n\n'; /* Collect errors. */
182 }
183 });
184 /**/
185 if (errors = $.trim (errors))
186 {
187 alert('— Oops, you missed something: —\n\n' + errors);
188 /**/
189 return false;
190 }
191 /**/
192 else if ($pass1.length && $.trim ($pass1.val ()) !== $.trim ($pass2.val ()))
193 {
194 alert('— Oops, you missed something: —\n\nPasswords do not match up. Please try again.');
195 /**/
196 return false;
197 }
198 /**/
199 ws_plugin__s2member_animateProcessing($submissionButton);
200 /**/
201 return true;
202 });
203 }
204 /*
205 Attach form submission handler to `/wp-admin/(user/)?profile.php`.
206 */
207 else if (location.href.match (/\/wp-admin\/(user\/)?profile\.php/))
208 {
209 $('form#your-profile').submit (function() /* Validation. */
210 {
211 var context = this, label = '', error = '', errors = '';
212 /**/
213 $('input#email', context).attr ('data-expected', 'email');
214 /**/
215 $(':input[id^="ws-plugin--s2member-profile-"]', context).each (function() /* Go through them all together. */
216 {
217 var id = $.trim ($(this).attr ('id')).replace (/-[0-9]+$/g, ''); /* Remove numeric suffixes. */
218 /**/
219 if (id && (label = $.trim ($('label[for="' + id + '"]', context).first ().text ().replace (/[\r\n\t]+/g, ' '))))
220 {
221 if (error = ws_plugin__s2member_validationErrors(label, this, context))
222 errors += error + '\n\n'; /* Collect errors. */
223 }
224 });
225 /**/
226 if (errors = $.trim (errors))
227 {
228 alert('— Oops, you missed something: —\n\n' + errors);
229 /**/
230 return false;
231 }
232 /**/
233 return true;
234 });
235 }
236 /*
237 Attach form submission handler to `/register` for BuddyPress.
238 */
239 else if (bpRegisterSlug && location.href.match (bpRegisterSlug))
240 {
241 $('body.registration form div#ws-plugin--s2member-custom-reg-fields-4bp-section').closest ('form').submit (function()
242 {
243 var context = this, label = '', error = '', errors = '';
244 /**/
245 $('input#signup_email', context).attr ('data-expected', 'email');
246 /**/
247 $('input#signup_username, input#signup_email, input#signup_password, input#field_1', context).attr ({'aria-required': 'true'});
248 /**/
249 $(':input', context).each (function() /* Go through them all together. */
250 {
251 var id = $.trim ($(this).attr ('id')).replace (/-[0-9]+$/g, ''); /* Remove numeric suffixes. */
252 /**/
253 if (id && (label = $.trim ($('label[for="' + id + '"]', context).first ().text ().replace (/[\r\n\t]+/g, ' '))))
254 {
255 if (error = ws_plugin__s2member_validationErrors(label, this, context))
256 errors += error + '\n\n'; /* Collect errors. */
257 }
258 });
259 /**/
260 if (errors = $.trim (errors))
261 {
262 alert('— Oops, you missed something: —\n\n' + errors);
263 /**/
264 return false;
265 }
266 /**/
267 return true;
268 });
269 }
270 /*
271 Attach form submission handler to `/profile/edit/` for BuddyPress.
272 */
273 else if (bpxProfileSlug && location.href.match (bpxProfileSlug) && location.href.match (/\/edit\//))
274 {
275 $('body.logged-in.profile.profile-edit input.ws-plugin--s2member-profile-field-4bp[type = "text"]').closest ('form').submit (function()
276 {
277 var context = this, label = '', error = '', errors = '';
278 /**/
279 $('input#field_1', context).attr ({'aria-required': 'true'});
280 /**/
281 $(':input', context).each (function() /* Go through them all together. */
282 {
283 var id = $.trim ($(this).attr ('id')).replace (/-[0-9]+$/g, ''); /* Remove numeric suffixes. */
284 /**/
285 if (id && (label = $.trim ($('label[for="' + id + '"]', context).first ().text ().replace (/[\r\n\t]+/g, ' '))))
286 {
287 if (error = ws_plugin__s2member_validationErrors(label, this, context))
288 errors += error + '\n\n'; /* Collect errors. */
289 }
290 });
291 /**/
292 if (errors = $.trim (errors))
293 {
294 alert('— Oops, you missed something: —\n\n' + errors);
295 /**/
296 return false;
297 }
298 /**/
299 return true;
300 });
301 }
302 /*
303 Password strength. Accecpts jQuery objects.
304 */
305 ws_plugin__s2member_passwordStrength = function($username, $pass1, $pass2, $result)
306 {
307 if ($username instanceof jQuery && $pass1 instanceof jQuery && $pass2 instanceof jQuery && $result instanceof jQuery && typeof passwordStrength === 'function' && typeof pwsL10n === 'object')
308 {
309 $result.removeClass ('ws-plugin--s2member-password-strength-short ws-plugin--s2member-password-strength-bad ws-plugin--s2member-password-strength-good ws-plugin--s2member-password-strength-strong ws-plugin--s2member-password-strength-mismatch');
310 /**/
311 switch (passwordStrength($pass1.val (), $username.val (), $pass2.val ())) /* Uses WordPress® script: `password-strength-meter` and `pwsL10n`. */
312 {
313 case 1:
314 $result.addClass ('ws-plugin--s2member-password-strength-short').html (pwsL10n['short']);
315 break;
316 case 2:
317 $result.addClass ('ws-plugin--s2member-password-strength-bad').html (pwsL10n['bad']);
318 break;
319 case 3:
320 $result.addClass ('ws-plugin--s2member-password-strength-good').html (pwsL10n['good']);
321 break;
322 case 4:
323 $result.addClass ('ws-plugin--s2member-password-strength-strong').html (pwsL10n['strong']);
324 break;
325 case 5:
326 $result.addClass ('ws-plugin--s2member-password-strength-mismatch').html (pwsL10n['mismatch']);
327 break;
328 default:
329 $result.addClass ('ws-plugin--s2member-password-strength-short').html (pwsL10n['short']);
330 }
331 }
332 /**/
333 return; /* Return for uniformity. */
334 };
335 /*
336 Handles JavaScript validation errors.
337 */
338 ws_plugin__s2member_validationErrors = function(label, field, context, required, expected)
339 {
340 if (typeof label === 'string' && label && typeof field === 'object' && typeof context === 'object')
341 if (typeof field.tagName === 'string' && field.tagName.match (/^(input|textarea|select)$/i) && !field.disabled)
342 {
343 var tag = field.tagName.toLowerCase (), $field = $(field), type = $.trim ($field.attr ('type')).toLowerCase (), name = $.trim ($field.attr ('name')), value = $field.val ();
344 var required = ( typeof required === 'boolean') ? required : ($field.attr ('aria-required') === 'true'), expected = ( typeof expected === 'string') ? expected : $.trim ($field.attr ('data-expected'));
345 /**/
346 var forcePersonalEmails = ('<?php echo strlen($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_force_personal_emails"]); ?>' > 0) ? true : false;
347 var nonPersonalEmailUsers = new RegExp('^(<?php echo c_ws_plugin__s2member_utils_strings::esc_sq(implode("|", preg_split("/[\r\n\t ;,]+/", preg_quote($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_force_personal_emails"], "/")))); ?>)@', 'i');
348 /**/
349 if (tag === 'input' && type === 'checkbox' && name.match (/\[\]$/))
350 {
351 if (typeof field.id === 'string' && field.id.match (/-0$/))
352 if (required && !$('input[name="' + name.replace (/([\[\]])/g, '\$1') + '"]:checked', context).length)
353 return label + '\nPlease check at least one of the boxes.';
354 }
355 else if (tag === 'input' && type === 'checkbox')
356 {
357 if (required && !field.checked)
358 return label + '\nRequired. This box must be checked.';
359 }
360 else if (tag === 'input' && type === 'radio')
361 {
362 if (typeof field.id === 'string' && field.id.match (/-0$/))
363 if (required && !$('input[name="' + name.replace (/([\[\]])/g, '\$1') + '"]:checked', context).length)
364 return label + '\nPlease select one of the options.';
365 }
366 else if (tag === 'select' && $field.attr ('multiple'))
367 {
368 if (required && (!(value instanceof Array) || !value.length))
369 return label + '\nPlease select at least one of the options.';
370 }
371 else if (typeof value !== 'string' || (required && !(value = $.trim (value)).length))
372 {
373 return label + '\nThis is a required field, please try again.';
374 }
375 else if ((value = $.trim (value)).length && ((tag === 'input' && type.match (/^(text|password)$/i)) || tag === 'textarea') && typeof expected === 'string' && expected.length)
376 {
377 if (expected === 'numeric-wp-commas' && (!value.match (/^[0-9\.,]+$/) || isNaN(value.replace (/,/g, ''))))
378 {
379 return label + '\nMust be numeric ( with or without decimals, commas allowed ).';
380 }
381 else if (expected === 'numeric' && (!value.match (/^[0-9\.]+$/) || isNaN(value)))
382 {
383 return label + '\nMust be numeric ( with or without decimals, no commas ).';
384 }
385 else if (expected === 'integer' && (!value.match (/^[0-9]+$/) || isNaN(value)))
386 {
387 return label + '\nMust be an integer ( a whole number, without any decimals ).';
388 }
389 else if (expected === 'integer-gt-0' && (!value.match (/^[0-9]+$/) || isNaN(value) || value <= 0))
390 {
391 return label + '\nMust be an integer > 0 ( whole number, no decimals, greater than 0 ).';
392 }
393 else if (expected === 'float' && (!value.match (/^[0-9\.]+$/) || !value.match (/[0-9]/) || !value.match (/\./) || isNaN(value)))
394 {
395 return label + '\nMust be a float ( floating point number, decimals required ).';
396 }
397 else if (expected === 'float-gt-0' && (!value.match (/^[0-9\.]+$/) || !value.match (/[0-9]/) || !value.match (/\./) || isNaN(value) || value <= 0))
398 {
399 return label + '\nMust be a float > 0 ( floating point number, decimals required, greater than 0 ).';
400 }
401 else if (expected === 'date' && !value.match (/^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/))
402 {
403 return label + '\nMust be a date ( required date format: dd/mm/yyyy ).';
404 }
405 else if (expected === 'email' && !value.match (/^([a-z_~0-9\+\-]+)(((\.?)([a-z_~0-9\+\-]+))*)(@)([a-z0-9]+)(((-*)([a-z0-9]+))*)(((\.)([a-z0-9]+)(((-*)([a-z0-9]+))*))*)(\.)([a-z]{2,6})$/i))
406 {
407 return label + '\nMust be a valid email address.';
408 }
409 else if (expected === 'email' && forcePersonalEmails && value.match (nonPersonalEmailUsers))
410 {
411 return label + '\nPlease use a personal email address.\nAddresses like <' + value.split ('@')[0] + '@> are problematic.';
412 }
413 else if (expected === 'url' && !value.match (/^http(s?)\:\/\/(.{5,})$/i))
414 {
415 return label + '\nMust be a full URL ( starting with http or https ).';
416 }
417 else if (expected === 'domain' && !value.match (/^([a-z0-9]+)(((-*)([a-z0-9]+))*)(((\.)([a-z0-9]+)(((-*)([a-z0-9]+))*))*)(\.)([a-z]{2,6})$/i))
418 {
419 return label + '\nMust be a domain name ( domain name only, without http ).';
420 }
421 else if (expected === 'phone' && (!value.match (/^[0-9 \(\)\-]+$/) || value.replace (/[^0-9]/g, '').length !== 10))
422 {
423 return label + '\nMust be a phone # ( 10 digits w/possible hyphens,spaces,brackets ).';
424 }
425 else if (expected === 'uszip' && !value.match (/^[0-9]{5}(-[0-9]{4})?$/))
426 {
427 return label + '\nMust be a US zipcode ( 5-9 digits w/possible hyphen ).';
428 }
429 else if (expected === 'cazip' && !value.match (/^[0-9A-Z]{3}( ?)[0-9A-Z]{3}$/i))
430 {
431 return label + '\nMust be a Canadian zipcode ( 6 alpha-numerics w/possible space ).';
432 }
433 else if (expected === 'uczip' && !value.match (/^[0-9]{5}(-[0-9]{4})?$/) && !value.match (/^[0-9A-Z]{3}( ?)[0-9A-Z]{3}$/i))
434 {
435 return label + '\nMust be a zipcode ( either a US or Canadian zipcode ).';
436 }
437 else if (expected.match (/^alphanumerics-spaces-punctuation-([0-9]+)(-e)?$/) && !value.match (/^[a-z 0-9,\.\/\?\:;"'\{\}\[\]\|\\\+\=_\-\(\)\*&\^%\$#@\!`~]+$/i))
438 {
439 return label + '\nPlease use alphanumerics, spaces & punctuation only.';
440 }
441 else if (expected.match (/^alphanumerics-spaces-([0-9]+)(-e)?$/) && !value.match (/^[a-z 0-9]+$/i))
442 {
443 return label + '\nPlease use alphanumerics & spaces only.';
444 }
445 else if (expected.match (/^alphanumerics-punctuation-([0-9]+)(-e)?$/) && !value.match (/^[a-z0-9,\.\/\?\:;"'\{\}\[\]\|\\\+\=_\-\(\)\*&\^%\$#@\!`~]+$/i))
446 {
447 return label + '\nPlease use alphanumerics & punctuation only ( no spaces ).';
448 }
449 else if (expected.match (/^alphanumerics-([0-9]+)(-e)?$/) && !value.match (/^[a-z0-9]+$/i))
450 {
451 return label + '\nPlease use alphanumerics only ( no spaces/punctuation ).';
452 }
453 else if (expected.match (/^alphabetics-([0-9]+)(-e)?$/) && !value.match (/^[a-z]+$/i))
454 {
455 return label + '\nPlease use alphabetics only ( no digits/spaces/punctuation ).';
456 }
457 else if (expected.match (/^numerics-([0-9]+)(-e)?$/) && !value.match (/^[0-9]+$/i))
458 {
459 return label + '\nPlease use numeric digits only.';
460 }
461 else if (expected.match (/^(any|alphanumerics-spaces-punctuation|alphanumerics-spaces|alphanumerics-punctuation|alphanumerics|alphabetics|numerics)-([0-9]+)(-e)?$/))
462 {
463 var split = expected.split ('-'), length = Number(split[1]), exactLength = (split.length > 2) ? Number(split[2]) : '';
464 /**/
465 if (exactLength && value.length !== length) /* An exact length is required? */
466 return label + '\nMust be exactly ' + length + ' ' + ((split[0] === 'numerics') ? 'digit' : 'character') + ((length > 1) ? 's' : '') + '.';
467 /**/
468 else if (value.length < length) /* Otherwise, we interpret as the minimum length. */
469 return label + '\nMust be at least ' + length + ' ' + ((split[0] === 'numerics') ? 'digit' : 'character') + ((length > 1) ? 's' : '') + '.';
470 }
471 }
472 }
473 /**/
474 return '';
475 };
476 /**/
477 ws_plugin__s2member_animateProcessingConfig = {originalText: '', interval: null, speed: 100}, ws_plugin__s2member_animateProcessing = function($obj, reset)
478 {
479 if ($obj instanceof jQuery) /* This function expects a valid jQuery object. */
480 {
481 if (reset) /* Resets back to originalText value ( also clears interval ). */
482 {
483 clearInterval(ws_plugin__s2member_animateProcessingConfig.interval);
484 /**/
485 if (ws_plugin__s2member_animateProcessingConfig.originalText) /* ? */
486 $obj.val (ws_plugin__s2member_animateProcessingConfig.originalText);
487 /**/
488 return; /* No need to proceed any further. Return now upon reset. */
489 }
490 /**/
491 $obj.first ().each (function() /* Interval routine configured here. */
492 {
493 var $this = $(this), i = 0, dir = 'r', dots = ['.', '..', '...'];
494 /**/
495 ws_plugin__s2member_animateProcessingConfig.originalText = $this.val ();
496 /**/
497 clearInterval(ws_plugin__s2member_animateProcessingConfig.interval);
498 /**/
499 ws_plugin__s2member_animateProcessingConfig.interval = setInterval(function()
500 {
501 if (dir === 'r') /* Right... */
502 {
503 if (i + 1 <= dots.length - 1)
504 i = i + 1, dir = 'r';
505 else /* Switch direction. */
506 i = i - 1, dir = 'l';
507 }
508 /**/
509 else if (dir === 'l') /* Left.. */
510 {
511 if (i - 1 >= 0)
512 i = i - 1, dir = 'l';
513 else /* Switch direction. */
514 i = i + 1, dir = 'r';
515 }
516 /**/
517 for (var _dots = dots[i], l = dots[i].length; l < dots.length; l++)
518 {
519 _dots += ' '; /* Prevents jumping. */
520 }
521 /**/
522 $this.val ('Processing' + _dots);
523 }, ws_plugin__s2member_animateProcessingConfig.speed);
524 });
525 }
526 };
527 });