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

menu-pages-s.js in s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions 260909, at src/includes/menu-pages/menu-pages-s.js

1,329 lines 85.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Core JavaScript routines for s2Member menu pages.
3 *
4 * Copyright: © 2009-2011
5 * {@link http://websharks-inc.com/ WebSharks, Inc.}
6 * (coded in the USA)
7 *
8 * Released under the terms of the GNU General Public License.
9 * You should have received a copy of the GNU General Public License,
10 * along with this software. In the main directory, see: /licensing/
11 * If not, see: {@link http://www.gnu.org/licenses/}.
12 *
13 * @package s2Member\Menu_Pages
14 * @since 3.0
15 */
16 jQuery(document).ready(function($)
17 {
18 var esc_attr = esc_html = function(string/* Convert special characters. */)
19 {
20 if(/[&\<\>"']/.test(string = String(string)))
21 string = string.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;'),
22 string = string.replace(/"/g, '&quot;').replace(/'/g, '&#039;');
23 return string;
24 };
25 ws_plugin__s2member_generateSecurityKey = /* Generates a unique Security Key. */ function(obj)
26 {
27 if(!obj) obj = '#ws-plugin--s2member-sec-encryption-key';
28
29 var mt_rand = /* The JS equivalent to mt_rand(). */ function(min, max)
30 {
31 min = (arguments.length < 1) ? 0 : min;
32 max = (arguments.length < 2) ? 2147483647 : max;
33
34 return Math.floor(Math.random() * (max-min+1))+min;
35 };
36 var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#%^&*()';
37
38 for(var i = 0, key = ''; i < 64; i++)
39 key += chars.substr(mt_rand(0, chars.length-1), 1);
40
41 $(obj).val(key);
42
43 return false;
44 };
45 if(location.href.match /* Any & all s2Member pages. */(/page\=ws-plugin--s2member/))
46 {
47 $('input.ws-plugin--s2member-update-roles-button, input.ws-plugin--s2member-reset-roles-button').click(function()
48 {
49 var $this = /* Save $(this) into $this. */ $(this);
50 $this.val /* Indicate loading status (please wait). */('one moment please ...');
51
52 var levels = '<?php echo (int)$GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; ?>';
53 var resetUpdate = ($this.hasClass('ws-plugin--s2member-reset-roles-button')) ? 'Reset' : 'Update';
54
55 $.post(ajaxurl, {action: 'ws_plugin__s2member_update_roles_via_ajax', ws_plugin__s2member_update_roles_via_ajax: '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (wp_create_nonce ("ws-plugin--s2member-update-roles-via-ajax")); ?>'}, function(response)
56 {
57 if(response === '1')
58 alert('s2Member\'s Roles/Capabilities '+((resetUpdate.toLowerCase() === 'reset') ? 'have been successfully reset' : 'updated successfully')+'.\nYour installation of s2Member has Membership Levels 0-'+levels+'.'), $this.val(resetUpdate+' Roles/Capabilities');
59
60 else if(response === 'l' /* Locked? */)
61 alert('Sorry, your request failed.\ns2Member\'s Roles/Capabilities are locked by Filter:\nws_plugin__s2member_lock_roles_caps'), $this.val(resetUpdate+' Roles/Capabilities');
62
63 else // Default response message here.
64 alert('Sorry, your request failed.\nAccess denied. Do you have the ability to `create_users`?'), $this.val(resetUpdate+' Roles/Capabilities');
65 });
66 return false;
67 });
68 }
69 if(location.href.match(/page\=ws-plugin--s2member-logs/))
70 {
71 $('input#ws-plugin--s2member-gateway-debug-logs-extensive-1').click(function()
72 {
73 var $this = $(this), thisChecked = (this.checked) ? true : false;
74 if(thisChecked) $('input#ws-plugin--s2member-gateway-debug-logs-1').attr('checked', 'checked');
75 });
76 var $toggles = $('a.ws-plugin--s2member-log-file-viewport-toggle'); $toggles.click(function()
77 {
78 $('textarea#ws-plugin--s2member-log-file-viewer').each(function()
79 {
80 var $viewer = $(this); // There is only one viewer.
81
82 if($viewer.attr('data-state') !== 'expanded') // Not expanded yet?
83 {
84 $viewer.css({'height': ($viewer.prop('scrollHeight')+50)+'px', 'overflow-y':'auto'});
85 $toggles.html('&#8657; normalize viewport &#10073;');
86 $viewer.attr('data-state', 'expanded');
87 }
88 else // Already expanded. We need to toggle it back to a normalized state in this case.
89 {
90 $viewer.css({'height': 'auto', 'overflow-y':'scroll'});
91 $toggles.html('&#8659; expand viewport &#8659;');
92 $viewer.attr('data-state', 'scrolling');
93 }
94 });
95 return false; // Prevents location.hash jumps.
96 });
97 }
98 if(location.href.match(/page\=ws-plugin--s2member-mms-ops/))
99 {
100 $('select#ws-plugin--s2member-mms-registration-file').change(function()
101 {
102 if /* Expand/collapse relevant options; based on file selection. */($(this).val() === 'wp-signup')
103 {
104 var gv = $('select#ws-plugin--s2member-mms-registration-grants').val(), l0v = $('input#ws-plugin--s2member-mms-registration-blogs-level0').val();
105 $('div#ws-plugin--s2member-mms-registration-support-package-details-wrapper').show(), $('div.ws-plugin--s2member-mms-registration-wp-login, table.ws-plugin--s2member-mms-registration-wp-login').hide(), $('div.ws-plugin--s2member-mms-registration-wp-signup, table.ws-plugin--s2member-mms-registration-wp-signup').show();
106 $('div.ws-plugin--s2member-mms-registration-wp-signup-blogs-level0, table.ws-plugin--s2member-mms-registration-wp-signup-blogs-level0')[((gv === 'all') ? 'show' : 'hide')]();
107 $('input#ws-plugin--s2member-mms-registration-blogs-level0').val(((gv === 'all') ? ((l0v > 0) ? l0v : '1') : '0'));
108 }
109 else if /* Expand/collapse relevant options. */($(this).val() === 'wp-login')
110 {
111 var gv = $('select#ws-plugin--s2member-mms-registration-grants').val(), l0v = $('input#ws-plugin--s2member-mms-registration-blogs-level0').val();
112 $('div#ws-plugin--s2member-mms-registration-support-package-details-wrapper').hide(), $('div.ws-plugin--s2member-mms-registration-wp-login, table.ws-plugin--s2member-mms-registration-wp-login').show(), $('div.ws-plugin--s2member-mms-registration-wp-signup, table.ws-plugin--s2member-mms-registration-wp-signup').hide();
113 $('div.ws-plugin--s2member-mms-registration-wp-signup-blogs-level0, table.ws-plugin--s2member-mms-registration-wp-signup-blogs-level0').hide();
114 $('input#ws-plugin--s2member-mms-registration-blogs-level0').val('0');
115 }
116 }).trigger /* Fire on ready too. */('change');
117
118 $('select#ws-plugin--s2member-mms-registration-grants').change(function()
119 {
120 $('select#ws-plugin--s2member-mms-registration-file').trigger('change');
121 });
122 }
123 if(location.href.match(/page\=ws-plugin--s2member-gen-ops/))
124 {
125 ws_plugin__s2member_enableSecurityKey = /* Allow Security Key editing?? */ function()
126 {
127 //260810 Warn about the concrete effects of changing the configured encryption key.
128 if(confirm('Edit Security Encryption Key?\n\nChanging this key will invalidate existing data that was encrypted with the current effective key, which can include access links, registration/tracking cookies, pending transaction-return data, and values encrypted through s2Member\'s API.\n\nContinue only if you intend to change or recover the key. Keep the current key backed up; s2Member also retains a history of recent Security Encryption Keys configured in s2Member.'))
129 $('input#ws-plugin--s2member-sec-encryption-key').removeAttr('disabled');
130
131 return false;
132 };
133 ws_plugin__s2member_securityKeyHistory = /* Displays history of Keys. */ function()
134 {
135 $('div#ws-plugin--s2member-sec-encryption-key-history').toggle();
136
137 return false;
138 };
139 $('select#ws-plugin--s2member-new-user-emails-enabled').change(function()
140 {
141 var $pluggable = $('input#ws-plugin--s2member-pluggables-wp-new-user-notification'), $this = $(this), $newUserEmails = $('div#ws-plugin--s2member-new-user-emails');
142
143 if($pluggable.val() === '0' || $this.val() === '0')
144 {
145 ($pluggable.val() === '0') ? $this.attr('disabled', 'disabled') : $this.removeAttr('disabled');
146 $(':input', $newUserEmails).attr('disabled', 'disabled'), $newUserEmails.css('opacity', '0.5');
147 }
148 else // Else we allow the emails to be customized.
149 $this.removeAttr('disabled'), $(':input', $newUserEmails).removeAttr('disabled'), $newUserEmails.css('opacity', '');
150
151 }).trigger /* Fire on ready too. */('change');
152
153 $('select#ws-plugin--s2member-login-reg-design-enabled').change(function()
154 {
155 var $this = $(this), $loginRegDesign = $('div#ws-plugin--s2member-login-reg-design');
156
157 if($this.val() === '0') // Disable this section.
158 $(':input', $loginRegDesign).attr('disabled', 'disabled'), $loginRegDesign.css('opacity', '0.5'), $loginRegDesign.hide();
159
160 else // Else we allow login/registration design.
161 $(':input', $loginRegDesign).removeAttr('disabled'), $loginRegDesign.css('opacity', ''), $loginRegDesign.show();
162
163 }).trigger /* Fire on ready too. */('change');
164
165 $('select#ws-plugin--s2member-custom-reg-password').change(function()
166 {
167 var $this = $(this), $newUserNotification = $('div#ws-plugin--s2member-new-user-email-details');
168
169 if($this.val() === '1') // Disable this section.
170 $newUserNotification.css('opacity', '0.5');
171 else $newUserNotification.css('opacity', '');
172
173 }).trigger /* Fire on ready too. */('change');
174
175 if($('input#ws-plugin--s2member-custom-reg-fields').length && $('div#ws-plugin--s2member-custom-reg-field-configuration').length)
176 {
177 ( /* Wrap these routines inside a function to keep variables within relative scope. */function()
178 {
179 var i, fieldDefaults, tools, table, $tools, $table;
180 var $fields = $('input#ws-plugin--s2member-custom-reg-fields');
181 var $configuration = $('div#ws-plugin--s2member-custom-reg-field-configuration');
182 var fields = ($fields.val()) ? $.JSON.parse($fields.val()) : [];
183
184 fields = /* Force fields to an array. */ (fields instanceof Array) ? fields : [];
185
186 fieldDefaults = {section: 'no', sectitle: '', id: '', label: '', type: 'text', deflt: '', options: '', expected: '', required: 'yes', levels: 'all', editable: 'yes', classes: '', styles: '', attrs: ''};
187
188 for(i = 0; i < fields.length; i++)
189 fields[i] = /* Extend, based on defaults (for future proofing). */ $.extend(true, {
190 }, fieldDefaults, fields[i]);
191
192 tools = '<div id="ws-plugin--s2member-custom-reg-field-configuration-tools"></div>', table = '<table id="ws-plugin--s2member-custom-reg-field-configuration-table"></table>';
193
194 $configuration.html /* Add tools div & table div to configuration div (i.e., div#ws-plugin--s2member-custom-reg-field-configuration). */(tools+table);
195
196 $tools = $('div#ws-plugin--s2member-custom-reg-field-configuration-tools'), $table = $('table#ws-plugin--s2member-custom-reg-field-configuration-table');
197
198 ws_plugin__s2member_customRegFieldSectionChange = function(select)
199 {
200 var section = /* Current selection (no|yes, selected by site owner). */ $(select).val();
201
202 var sectitle_trs = 'tr.ws-plugin--s2member-custom-reg-field-configuration-tools-form-sectitle';
203
204 (section === 'yes') ? $(sectitle_trs).css('display', '') : $(sectitle_trs).css('display', 'none');
205 };
206 ws_plugin__s2member_customRegFieldTypeChange = /* Handle change events here. */ function(select)
207 {
208 var type = /* Current selection (type of Field, selected by site owner). */ $(select).val();
209
210 var deflt_trs = 'tr.ws-plugin--s2member-custom-reg-field-configuration-tools-form-deflt', options_trs = 'tr.ws-plugin--s2member-custom-reg-field-configuration-tools-form-options', expected_trs = 'tr.ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected';
211
212 (type.match(/^(text|textarea)$/)) ? $(deflt_trs).css('display', '') : $(deflt_trs).css('display', 'none');
213 (type.match(/^(select|selects|checkboxes|radios)$/)) ? $(options_trs).css('display', '') : $(options_trs).css('display', 'none');
214 (type.match(/^(text|textarea)$/)) ? $(expected_trs).css('display', '') : $(expected_trs).css('display', 'none');
215 };
216 ws_plugin__s2member_customRegFieldDelete = function(index)
217 {
218 var newFields = /* Build array. */ new Array();
219
220 for(var i = 0; i < fields.length; i++)
221 if /* Omit index. */(i !== index)
222 newFields.push(fields[i]);
223
224 fields = newFields, updateFields(), buildTable();
225 };
226 ws_plugin__s2member_customRegFieldMoveUp = function(index)
227 {
228 if(typeof fields[index] === 'object' && typeof fields[index-1] === 'object')
229 {
230 var prevFieldObj = fields[index-1], thisFieldObj = fields[index];
231
232 fields[index-1] = thisFieldObj, fields[index] = prevFieldObj;
233
234 updateFields(), buildTable();
235 }
236 };
237 ws_plugin__s2member_customRegFieldMoveDown = function(index)
238 {
239 if(typeof fields[index] === 'object' && typeof fields[index+1] === 'object')
240 {
241 var nextFieldObj = fields[index+1], thisFieldObj = fields[index];
242
243 fields[index+1] = thisFieldObj, fields[index] = nextFieldObj;
244
245 updateFields(), buildTable();
246 }
247 };
248 ws_plugin__s2member_customRegFieldCreate = function()
249 {
250 var $table = $('table#ws-plugin--s2member-custom-reg-field-configuration-tools-form'), field = {};
251
252 $(':input[property]', $table).each( /* Go through each property value. */function()
253 {
254 var $this = $(this), property = $this.attr('property'), val = $.trim($this.val());
255
256 field[property] = val;
257 });
258 if /* If it can be validated. */((field = validateField(field)))
259 {
260 fields.push(field), updateFields(), buildTools(), buildTable(), scrollReset();
261
262 setTimeout( /* A momentary delay here for usability. */function()
263 {
264 var row = 'tr.ws-plugin--s2member-custom-reg-field-configuration-table-row-'+(fields.length-1);
265 alert('Field created successfully.\n* Remember to "Save All Changes".');
266 //$(row).effect('highlight');
267 }, 500);
268 }
269 };
270 ws_plugin__s2member_customRegFieldUpdate = function(index)
271 {
272 var $table = $('table#ws-plugin--s2member-custom-reg-field-configuration-tools-form'), field = {};
273
274 $(':input[property]', $table).each( /* Go through each property value. */function()
275 {
276 var $this = $(this), property = $this.attr('property'), val = $.trim($this.val());
277
278 field[property] = val;
279 });
280 if /* If it validates. */((field = validateField(field, index)))
281 {
282 fields[index] = field, updateFields(), buildTools(), buildTable(), scrollReset();
283
284 setTimeout( /* A momentary delay here for usability. */function()
285 {
286 var row = 'tr.ws-plugin--s2member-custom-reg-field-configuration-table-row-'+index;
287 alert('Field updated successfully.\n* Remember to "Save All Changes".');
288 //$(row).effect('highlight');
289 }, 500);
290 }
291 };
292 ws_plugin__s2member_customRegFieldAdd = /* Add new field links. */ function()
293 {
294 buildTools /* No need to reset scroll position. */(true);
295 };
296 ws_plugin__s2member_customRegFieldEdit = /* Edit links. */ function(index)
297 {
298 buildTools(false, index), scrollReset();
299 };
300 ws_plugin__s2member_customRegFieldCancel = /* Cancel form. */ function()
301 {
302 buildTools(), scrollReset();
303 };
304 var validateField = function(field, index)
305 {
306 var editing = ( typeof index === 'number' && typeof fields[index] === 'object') ? true : false, errors = [], options, i;
307
308 if(typeof field !== 'object' || typeof (field = $.extend(true, {}, fieldDefaults, field)) !== 'object')
309 {
310 alert('Invalid field object. Please try again.');
311 return false;
312 }
313 field.sectitle = (field.section === 'yes') ? field.sectitle : '';
314 field.deflt = (field.type.match(/^(text|textarea)$/)) ? field.deflt : '';
315 field.deflt = (field.type.match(/^(text)$/)) ? field.deflt.replace(/[\r\n\t ]+/g, ' ') : field.deflt;
316 field.options = (field.type.match(/^(select|selects|checkboxes|radios)$/)) ? field.options : '';
317 field.expected = (field.type.match(/^(text|textarea)$/)) ? field.expected : '';
318
319 if /* Every Field must have a unique ID. */(!field.id)
320 {
321 errors.push('Unique Field ID:\nThis is required. Please try again.');
322 }
323 else if(fieldIdExists(field.id) && (!editing || field.id !== fields[index].id))
324 {
325 errors.push('Unique Field ID:\nThat Field ID already exists. Please try again.');
326 }
327
328 if /* Every Field must have a label. */(!field.label)
329 {
330 errors.push('Field Label/Description:\nThis is required. Please try again.');
331 }
332
333 if(field.type.match(/^(select|selects|checkboxes|radios)$/) && !field.options)
334 {
335 errors.push('Option Configuration File:\nThis is required. Please try again.');
336 }
337 else if(field.type.match(/^(select|selects|checkboxes|radios)$/))
338 {
339 for(i = 0; i < (options = field.options.split(/[\r\n]+/)).length; i++)
340 {
341 if(!(options[i] = $.trim(options[i])).match(/^([^\|]*)(\|)([^\|]*)(\|default)?$/))
342 {
343 errors.push('Option Configuration File:\nInvalid configuration at line #'+(i+1)+'.');
344 break; // Break now. There could potentially be lots of lines with errors.
345 }
346 }
347 field.options = /* Clean up. */ $.trim(options.join('\n'));
348 }
349
350 if(!(field.levels = field.levels.replace(/ /g, '')))
351 {
352 errors.push('Applicable Levels:\nThis is required. Please try again.');
353 }
354 else if(!field.levels.match(/^(all|[0-9,]+)$/))
355 {
356 errors.push('Applicable Levels:\nShould be comma-delimited Levels, or just type: all.\n(examples: 0,1,2,3,4 or type the word: all)');
357 }
358
359 if(field.classes && field.classes.match(/[^a-z 0-9 _ \-]/i))
360 {
361 errors.push('CSS Classes:\nContains invalid characters. Please try again.\n(only: alphanumerics, underscores, hyphens, spaces)');
362 }
363
364 if(field.styles && field.styles.match(/["\=\>\<]/))
365 {
366 errors.push('CSS Styles:\nContains invalid characters. Please try again.\n(do NOT use these characters: = " < >)');
367 }
368
369 if(field.attrs && field.attrs.match(/[\>\<]/))
370 {
371 errors.push('Other Attributes:\nContains invalid characters. Please try again.\n(do NOT use these characters: < >)');
372 }
373
374 if /* Errors? */(errors.length > 0)
375 {
376 alert(errors.join('\n\n'));
377 return false;
378 }
379 else // Return.
380 return field;
381 };
382 var updateFields = /* Update hidden input value. */ function()
383 {
384 $fields.val(((fields.length > 0) ? $.JSON.stringify(fields) : ''));
385 };
386 var fieldId2Var = /* Convert ids to variables. */ function(fieldId)
387 {
388 return ( typeof fieldId === 'string') ? $.trim(fieldId).toLowerCase().replace(/[^a-z0-9]/g, '_') : '';
389 };
390 var fieldTypeDesc = function(type)
391 {
392 var types = {text: 'Text (single line)', textarea: 'Textarea (multi-line)', select: 'Select Menu (drop-down)', selects: 'Select Menu (multi-option)', checkbox: 'Checkbox (single)', pre_checkbox: 'Checkbox (pre-checked)', checkboxes: 'Checkboxes (multi-option)', radios: 'Radio Buttons (multi-option)'};
393
394 if(typeof types[type] === 'string')
395 return types[type];
396
397 return /* Default. */ '';
398 };
399 var fieldIdExists = /* Already exists? */ function(fieldId)
400 {
401 for(var i = 0; i < fields.length; i++)
402 if(fields[i].id === fieldId)
403 return true;
404 };
405 var scrollReset = /* Return to Custom Fields section. */ function()
406 {
407 scrollTo(0, $('div.ws-plugin--s2member-custom-reg-fields-section').offset()['top']-100);
408 };
409 var buildTools = /* This builds tools into the configuration. */ function(adding, index)
410 {
411 var i = 0, html = '', form = '', w = 0, h = 0, editing = ( typeof index === 'number' && typeof fields[index] === 'object') ? true : false, displayForm = (adding || editing) ? true : false, field = (editing) ? $.extend(true, {
412 }, fieldDefaults, fields[index]) : fieldDefaults;
413
414 html += /* Click to add a new Custom Registration/Profile Field. */ '<a href="#" onclick="ws_plugin__s2member_customRegFieldAdd(); return false;">Add New Field</a>';
415
416 tb_remove /* Remove an existing thickbox. */(), $('div#ws-plugin--s2member-custom-reg-field-configuration-thickbox-tools-form').remove();
417
418 if /* Do we need to display the adding/editing form at all? */(displayForm)
419 {
420 form += '<div id="ws-plugin--s2member-custom-reg-field-configuration-thickbox-tools-form">';
421
422 form += '<table id="ws-plugin--s2member-custom-reg-field-configuration-tools-form">';
423 form += '<tbody>';
424
425 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-section">';
426 form += '<td colspan="2">';
427 form += '<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-section">Starts A New Section?</label>';
428 form += '</td>';
429 form += '</tr>';
430
431 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-section">';
432 form += '<td colspan="2">';
433 form += '<select property="section" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-section" onchange="ws_plugin__s2member_customRegFieldSectionChange(this);">';
434 form += '<option value="no"'+((field.section === 'no') ? ' selected="selected"' : '')+'">No (this Field flows normally)</option>';
435 form += '<option value="yes"'+((field.section === 'yes') ? ' selected="selected"' : '')+'">Yes (this Field begins a new section)</option>';
436 form += '</select><br />';
437 form += '<small>Optional. Allows Fields to be grouped into sections.</small>';
438 form += '</td>';
439 form += '</tr>';
440
441 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-sectitle ws-plugin--s2member-custom-reg-field-configuration-tools-form-section"'+((field.section === 'yes') ? '' : ' style="display:none;"')+'><td colspan="2"><hr /></td></tr>';
442
443 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-sectitle ws-plugin--s2member-custom-reg-field-configuration-tools-form-section"'+((field.section === 'yes') ? '' : ' style="display:none;"')+'>';
444 form += '<td colspan="2">';
445 form += 'Title for this new section? (optional)<br />';
446 form += '<input type="text" property="sectitle" autocomplete="off" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-sectitle" value="'+esc_attr(field.sectitle)+'" /><br />';
447 form += '<small>If empty, a simple divider will be used by default.</small>';
448 form += '</td>';
449 form += '</tr>';
450
451 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-type"><td colspan="2">&nbsp;</td></tr>';
452
453 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type">';
454 form += '<td colspan="2">';
455 form += '<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type">Form Field Type: *</label>';
456 form += '</td>';
457 form += '</tr>';
458
459 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type">';
460 form += '<td colspan="2">';
461 form += '<select property="type" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type" onchange="ws_plugin__s2member_customRegFieldTypeChange(this);">';
462 form += '<option value="text"'+((field.type === 'text') ? ' selected="selected"' : '')+'">'+esc_html(fieldTypeDesc('text'))+'</option>';
463 form += '<option value="textarea"'+((field.type === 'textarea') ? ' selected="selected"' : '')+'">'+esc_html(fieldTypeDesc('textarea'))+'</option>';
464 form += '<option value="select"'+((field.type === 'select') ? ' selected="selected"' : '')+'">'+esc_html(fieldTypeDesc('select'))+'</option>';
465 form += '<option value="selects"'+((field.type === 'selects') ? ' selected="selected"' : '')+'">'+esc_html(fieldTypeDesc('selects'))+'</option>';
466 form += '<option value="checkbox"'+((field.type === 'checkbox') ? ' selected="selected"' : '')+'">'+esc_html(fieldTypeDesc('checkbox'))+'</option>';
467 form += '<option value="pre_checkbox"'+((field.type === 'pre_checkbox') ? ' selected="selected"' : '')+'">'+esc_html(fieldTypeDesc('pre_checkbox'))+'</option>';
468 form += '<option value="checkboxes"'+((field.type === 'checkboxes') ? ' selected="selected"' : '')+'">'+esc_html(fieldTypeDesc('checkboxes'))+'</option>';
469 form += '<option value="radios"'+((field.type === 'radios') ? ' selected="selected"' : '')+'">'+esc_html(fieldTypeDesc('radios'))+'</option>';
470 form += '</select><br />';
471 form += '<small>The options below may change, based on the Field Type you choose here.</small>';
472 form += '</td>';
473 form += '</tr>';
474
475 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-label"><td colspan="2">&nbsp;</td></tr>';
476
477 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-label">';
478 form += '<td colspan="2">';
479 form += '<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-label">Field Label/Desc: *</label>';
480 form += '</td>';
481 form += '</tr>';
482
483 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-label">';
484 form += '<td colspan="2">';
485 form += '<input type="text" property="label" autocomplete="off" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-label" value="'+esc_attr(field.label)+'" /><br />';
486 form += '<small>Examples: <code>Choose Country</code>, <code>Street Address</code></small>';
487 form += '</td>';
488 form += '</tr>';
489
490 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-id"><td colspan="2">&nbsp;</td></tr>';
491
492 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-id">';
493 form += '<td colspan="2">';
494 form += '<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-id">Unique Field ID: *</label></label>';
495 form += '</td>';
496 form += '</tr>';
497
498 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-id">';
499 form += '<td colspan="2">';
500 form += '<input type="text" property="id" maxlength="25" autocomplete="off" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-id" value="'+esc_attr(field.id)+'" /><br />';
501 form += '<small>Examples: <code>country_code</code>, <code>street_address</code></small><br />';
502 form += '<small>e.g., <code>[s2Get user_field="country_code" /]</code></small>';
503 form += '</td>';
504 form += '</tr>';
505
506 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-required"><td colspan="2">&nbsp;</td></tr>';
507
508 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">';
509 form += '<td colspan="2">';
510 form += '<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">Field Required: *</label>';
511 form += '</td>';
512 form += '</tr>';
513
514 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">';
515 form += '<td colspan="2">';
516 form += '<select property="required" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">';
517 form += '<option value="yes"'+((field.required === 'yes') ? ' selected="selected"' : '')+'">Yes (required)</option>';
518 form += '<option value="no"'+((field.required === 'no') ? ' selected="selected"' : '')+'">No (optional)</option>';
519 form += '</select><br />';
520 form += '<small>If <code>yes</code>, only Users/Members will be "required" to enter this field.</small><br />';
521 form += '<small>* Administrators are exempt from this requirement.</small>';
522 form += '</td>';
523 form += '</tr>';
524
525 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-deflt"'+((field.type.match(/^(text|textarea)$/)) ? '' : ' style="display:none;"')+'><td colspan="2">&nbsp;</td></tr>';
526
527 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-deflt"'+((field.type.match(/^(text|textarea)$/)) ? '' : ' style="display:none;"')+'>';
528 form += '<td colspan="2">';
529 form += '<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-deflt">Default Text Value: (optional)</label>';
530 form += '</td>';
531 form += '</tr>';
532
533 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-deflt"'+((field.type.match(/^(text|textarea)$/)) ? '' : ' style="display:none;"')+'>';
534 form += '<td colspan="2">';
535 form += '<textarea property="deflt" wrap="off" spellcheck="false" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-deflt" rows="1">'+esc_html(field.deflt)+'</textarea><br />';
536 form += '<small>Default value before user input is received.</small>';
537 form += '</td>';
538 form += '</tr>';
539
540 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-options"'+((field.type.match(/^(select|selects|checkboxes|radios)$/)) ? '' : ' style="display:none;"')+'><td colspan="2">&nbsp;</td></tr>';
541
542 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options"'+((field.type.match(/^(select|selects|checkboxes|radios)$/)) ? '' : ' style="display:none;"')+'>';
543 form += '<td colspan="2">';
544 form += '<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options">Option Configuration File: * (one option per line)</label><br />';
545 form += '<small>Use a pipe <code>|</code> delimited format: <code>option value|option label</code></small>';
546 form += '</td>';
547 form += '</tr>';
548
549 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options"'+((field.type.match(/^(select|selects|checkboxes|radios)$/)) ? '' : ' style="display:none;"')+'>';
550 form += '<td colspan="2">';
551 form += '<textarea property="options" wrap="off" spellcheck="false" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options" rows="3">'+esc_html(field.options)+'</textarea><br />';
552 form += 'Here is a quick example:<br />';
553 form += '<small>You can also specify a <em>default</em> option:</small><br />';
554 form += '<code>US|United States|default</code><br />';
555 form += '<code>CA|Canada</code><br />';
556 form += '<code>VI|Virgin Islands (U.S.)</code>';
557 form += '</td>';
558 form += '</tr>';
559
560 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected"'+((field.type.match(/^(text|textarea)$/)) ? '' : ' style="display:none;"')+'><td colspan="2">&nbsp;</td></tr>';
561
562 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected"'+((field.type.match(/^(text|textarea)$/)) ? '' : ' style="display:none;"')+'>';
563 form += '<td colspan="2">';
564 form += '<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected">Expected Format: *</label>';
565 form += '</td>';
566 form += '</tr>';
567
568 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected"'+((field.type.match(/^(text|textarea)$/)) ? '' : ' style="display:none;"')+'>';
569 form += '<td colspan="2">';
570 form += '<select property="expected" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected">';
571
572 form += '<option value=""'+((field.expected === '') ? ' selected="selected"' : '')+'">Anything Goes</option>';
573 form += '<option disabled="disabled"></option>';
574
575 form += '<optgroup label="Specific Input Types">';
576 form += '<option value="numeric-wp-commas"'+((field.expected === 'numeric-wp-commas') ? ' selected="selected"' : '')+'">Numeric (with or without decimals, commas allowed)</option>';
577 form += '<option value="numeric"'+((field.expected === 'numeric') ? ' selected="selected"' : '')+'">Numeric (with or without decimals, no commas)</option>';
578 form += '<option value="integer"'+((field.expected === 'integer') ? ' selected="selected"' : '')+'">Integer (whole number, without any decimals)</option>';
579 form += '<option value="integer-gt-0"'+((field.expected === 'integer-gt-0') ? ' selected="selected"' : '')+'">Integer > 0 (whole number, no decimals, greater than 0)</option>';
580 form += '<option value="float"'+((field.expected === 'float') ? ' selected="selected"' : '')+'">Float (floating point number, decimals required)</option>';
581 form += '<option value="float-gt-0"'+((field.expected === 'float-gt-0') ? ' selected="selected"' : '')+'">Float > 0 (floating point number, decimals required, greater than 0)</option>';
582 form += '<option value="date"'+((field.expected === 'date') ? ' selected="selected"' : '')+'">Date (required date format: dd/mm/yyyy)</option>';
583 form += '<option value="email"'+((field.expected === 'email') ? ' selected="selected"' : '')+'">Email (require valid email)</option>';
584 form += '<option value="url"'+((field.expected === 'url') ? ' selected="selected"' : '')+'">Full URL (starting with http or https)</option>';
585 form += '<option value="domain"'+((field.expected === 'domain') ? ' selected="selected"' : '')+'">Domain Name (domain name only, without http)</option>';
586 form += '<option value="phone"'+((field.expected === 'phone') ? ' selected="selected"' : '')+'">Phone # (10 digits w/possible hyphens,spaces,brackets)</option>';
587 form += '<option value="uszip"'+((field.expected === 'uszip') ? ' selected="selected"' : '')+'">US Zipcode (5-9 digits w/possible hyphen)</option>';
588 form += '<option value="cazip"'+((field.expected === 'cazip') ? ' selected="selected"' : '')+'">Canadian Zipcode (6 alpha-numerics w/possible space)</option>';
589 form += '<option value="uczip"'+((field.expected === 'uczip') ? ' selected="selected"' : '')+'">US/Canadian Zipcode (either a US or Canadian zipcode)</option>';
590 form += '<option value="ukpostcode"'+((field.expected === 'ukpostcode') ? ' selected="selected"' : '')+'">UK Postcode (valid UK postcode format)</option>';
591 form += '</optgroup>';
592
593 form += '<option disabled="disabled"></option>';
594
595 form += '<optgroup label="Any Character Combination">';
596 for(i = 1; i <= 25; i++)
597 {
598 form += '<option value="any-'+i+'"'+((field.expected === 'any-'+i) ? ' selected="selected"' : '')+'">Any Character Combination ('+i+' character minimum)</option>';
599 form += '<option value="any-'+i+'-e"'+((field.expected === 'any-'+i+'-e') ? ' selected="selected"' : '')+'">Any Character Combination (exactly '+i+' character'+((i > 1) ? 's' : '')+')</option>';
600 }
601 form += '</optgroup>';
602
603 form += '<option disabled="disabled"></option>';
604
605 form += '<optgroup label="Alphanumerics, Spaces &amp; Punctuation Only">';
606 for(i = 1; i <= 25; i++)
607 {
608 form += '<option value="alphanumerics-spaces-punctuation-'+i+'"'+((field.expected === 'alphanumerics-spaces-punctuation-'+i) ? ' selected="selected"' : '')+'">Alphanumerics, Spaces &amp; Punctuation ('+i+' character minimum)</option>';
609 form += '<option value="alphanumerics-spaces-punctuation-'+i+'-e"'+((field.expected === 'alphanumerics-spaces-punctuation-'+i+'-e') ? ' selected="selected"' : '')+'">Alphanumerics, Spaces &amp; Punctuation (exactly '+i+' character'+((i > 1) ? 's' : '')+')</option>';
610 }
611 form += '</optgroup>';
612
613 form += '<option disabled="disabled"></option>';
614
615 form += '<optgroup label="Alphanumerics &amp; Spaces Only">';
616 for(i = 1; i <= 25; i++)
617 {
618 form += '<option value="alphanumerics-spaces-'+i+'"'+((field.expected === 'alphanumerics-spaces-'+i) ? ' selected="selected"' : '')+'">Alphanumerics &amp; Spaces ('+i+' character minimum)</option>';
619 form += '<option value="alphanumerics-spaces-'+i+'-e"'+((field.expected === 'alphanumerics-spaces-'+i+'-e') ? ' selected="selected"' : '')+'">Alphanumerics &amp; Spaces (exactly '+i+' character'+((i > 1) ? 's' : '')+')</option>';
620 }
621 form += '</optgroup>';
622
623 form += '<option disabled="disabled"></option>';
624
625 form += '<optgroup label="Alphanumerics &amp; Punctuation Only">';
626 for(i = 1; i <= 25; i++)
627 {
628 form += '<option value="alphanumerics-punctuation-'+i+'"'+((field.expected === 'alphanumerics-punctuation-'+i) ? ' selected="selected"' : '')+'">Alphanumerics &amp; Punctuation ('+i+' character minimum)</option>';
629 form += '<option value="alphanumerics-punctuation-'+i+'-e"'+((field.expected === 'alphanumerics-punctuation-'+i+'-e') ? ' selected="selected"' : '')+'">Alphanumerics &amp; Punctuation (exactly '+i+' character'+((i > 1) ? 's' : '')+')</option>';
630 }
631 form += '</optgroup>';
632
633 form += '<option disabled="disabled"></option>';
634
635 form += '<optgroup label="Alphanumerics Only">';
636 for(i = 1; i <= 25; i++)
637 {
638 form += '<option value="alphanumerics-'+i+'"'+((field.expected === 'alphanumerics-'+i) ? ' selected="selected"' : '')+'">Alphanumerics ('+i+' character minimum)</option>';
639 form += '<option value="alphanumerics-'+i+'-e"'+((field.expected === 'alphanumerics-'+i+'-e') ? ' selected="selected"' : '')+'">Alphanumerics (exactly '+i+' character'+((i > 1) ? 's' : '')+')</option>';
640 }
641 form += '</optgroup>';
642
643 form += '<option disabled="disabled"></option>';
644
645 form += '<optgroup label="Alphabetics Only">';
646 for(i = 1; i <= 25; i++)
647 {
648 form += '<option value="alphabetics-'+i+'"'+((field.expected === 'alphabetics-'+i) ? ' selected="selected"' : '')+'">Alphabetics ('+i+' character minimum)</option>';
649 form += '<option value="alphabetics-'+i+'-e"'+((field.expected === 'alphabetics-'+i+'-e') ? ' selected="selected"' : '')+'">Alphabetics (exactly '+i+' character'+((i > 1) ? 's' : '')+')</option>';
650 }
651 form += '</optgroup>';
652
653 form += '<option disabled="disabled"></option>';
654
655 form += '<optgroup label="Numeric Digits Only">';
656 for(i = 1; i <= 25; i++)
657 {
658 form += '<option value="numerics-'+i+'"'+((field.expected === 'numerics-'+i) ? ' selected="selected"' : '')+'">Numeric Digits ('+i+' digit minimum)</option>';
659 form += '<option value="numerics-'+i+'-e"'+((field.expected === 'numerics-'+i+'-e') ? ' selected="selected"' : '')+'">Numeric Digits (exactly '+i+' digit'+((i > 1) ? 's' : '')+')</option>';
660 }
661 form += '</optgroup>';
662
663 form += '</select><br />';
664 form += '<small>Only Users/Members will be required to meet this criteria.</small><br />';
665 form += '<small>* Administrators are exempt from this.</small>';
666 form += '</td>';
667 form += '</tr>';
668
669 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels"><td colspan="2">&nbsp;</td></tr>';
670
671 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels">';
672 form += '<td colspan="2">';
673 form += '<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels">Applicable Membership Levels: *</label>';
674 form += '</td>';
675 form += '</tr>';
676
677 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels">';
678 form += '<td colspan="2">';
679 form += '<input type="text" property="levels" autocomplete="off" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels" value="'+esc_attr(field.levels)+'" /><br />';
680 form += '<small>Please use comma-delimited Level #\'s: <code>0,1,2,3,4</code> or type: <code>all</code>.</small><br />';
681 form += '<small>This allows you to enable this field - only at specific Membership Levels.</small>';
682 form += '</td>';
683 form += '</tr>';
684
685 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable"><td colspan="2">&nbsp;</td></tr>';
686
687 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">';
688 form += '<td colspan="2">';
689 form += '<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">Allow Profile Edits: *</label>';
690 form += '</td>';
691 form += '</tr>';
692
693 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">';
694 form += '<td colspan="2">';
695 form += '<select property="editable" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">';
696 form += '<option value="yes"'+((field.editable === 'yes') ? ' selected="selected"' : '')+'">Yes (editable)</option>';
697 form += '<option value="no"'+((field.editable === 'no') ? ' selected="selected"' : '')+'">No (uneditable after registration)</option>';
698 form += '<option value="no-invisible"'+((field.editable === 'no-invisible') ? ' selected="selected"' : '')+'">No (uneditable &amp; totally invisible after registration)</option>';
699 form += '<option value="no-always-invisible"'+((field.editable === 'no-always-invisible') ? ' selected="selected"' : '')+'">No (uneditable &amp; totally invisible, both during &amp; after registration)</option>';
700 form += '<option value="yes-invisible"'+((field.editable === 'yes-invisible') ? ' selected="selected"' : '')+'">Yes (editable after registration / invisible during registration)</option>';
701 form += '</select><br />';
702 form += '<small>If <code>No</code>, this field will be un-editable after registration.</small><br />';
703 form += '<small>* Administrators are exempt from this.</small>';
704 form += '</td>';
705 form += '</tr>';
706
707 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes"><td colspan="2">&nbsp;</td></tr>';
708
709 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes">';
710 form += '<td colspan="2">';
711 form += '<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes">CSS Classes: (optional)</label>';
712 form += '</td>';
713 form += '</tr>';
714
715 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes">';
716 form += '<td colspan="2">';
717 form += '<input type="text" property="classes" autocomplete="off" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes" value="'+esc_attr(field.classes)+'" /><br />';
718 form += '<small>Example: <code>my-style-1 my-style-2</code></small>';
719 form += '</td>';
720 form += '</tr>';
721
722 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles"><td colspan="2">&nbsp;</td></tr>';
723
724 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles">';
725 form += '<td colspan="2">';
726 form += '<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles">CSS Styles: (optional)</label>';
727 form += '</td>';
728 form += '</tr>';
729
730 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles">';
731 form += '<td colspan="2">';
732 form += '<input type="text" property="styles" autocomplete="off" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles" value="'+esc_attr(field.styles)+'" /><br />';
733 form += '<small>Example: <code>color:#000000; background:#FFFFFF;</code></small>';
734 form += '</td>';
735 form += '</tr>';
736
737 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs"><td colspan="2">&nbsp;</td></tr>';
738
739 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs">';
740 form += '<td colspan="2">';
741 form += '<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs">Other Attributes: (optional)</label>';
742 form += '</td>';
743 form += '</tr>';
744
745 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs">';
746 form += '<td colspan="2">';
747 form += '<input type="text" property="attrs" autocomplete="off" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs" value="'+esc_attr(field.attrs)+'" /><br />';
748 form += '<small>Example: <code>onkeyup="" onblur=""</code></small>';
749 form += '</td>';
750 form += '</tr>';
751
752 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer ws-plugin--s2member-custom-reg-field-configuration-tools-form-buttons"><td colspan="2">&nbsp;</td></tr>';
753
754 form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-buttons">';
755 form += '<td align="left">';
756 form += '<input type="button" value="Cancel" onclick="ws_plugin__s2member_customRegFieldCancel();" />';
757 form += '</td>';
758 form += '<td align="right">';
759 form += '<input type="button" value="'+((editing) ? 'Update This Field' : 'Create Registration Field')+'" onclick="'+((editing) ? 'ws_plugin__s2member_customRegFieldUpdate('+index+');' : 'ws_plugin__s2member_customRegFieldCreate();')+'" />';
760 form += '</td>';
761 form += '</tr>';
762
763 form += '</tbody>';
764 form += '</table>';
765
766 form += '<div>';
767
768 $('body').append(form);
769
770 tb_show(((editing) ? 'Editing Registration/Profile Field' : 'New Custom Registration/Profile Field'), '#TB_inline?inlineId=ws-plugin--s2member-custom-reg-field-configuration-thickbox-tools-form');
771
772 $('table#ws-plugin--s2member-custom-reg-field-configuration-tools-form').show();
773 }
774 $tools.html(html);
775 };
776 var buildTable = /* This builds the table of existing fields. */ function()
777 {
778 var l = fields.length, i = 0, html = '', eo = 'o';
779
780 html += '<tbody>';
781
782 html += '<tr>';
783 html += '<th>Order</th>';
784 html += '<th>Field Type</th>';
785 html += '<th>Unique ID</th>';
786 html += '<th>Required</th>';
787 html += '<th>Levels</th>';
788 html += '<th>- Tools -</th>';
789 html += '</tr>';
790
791 if /* Any fields? */(fields.length > 0)
792 {
793 for(i = 0; i < fields.length; i++)
794 {
795 html += '<tr class="'+esc_attr((eo = (eo === 'o') ? 'e' : 'o'))+((fields[i].section === 'yes') ? ' s' : '')+' ws-plugin--s2member-custom-reg-field-configuration-table-row-'+i+'">'; // Odd/even + row identifier.
796 html += '<td nowrap="nowrap"><a class="ws-plugin--s2member-custom-reg-field-configuration-move-up" href="#" onclick="ws_plugin__s2member_customRegFieldMoveUp('+i+'); return false;"></a><a class="ws-plugin--s2member-custom-reg-field-configuration-move-down" href="#" onclick="ws_plugin__s2member_customRegFieldMoveDown('+i+'); return false;"></a></td>';
797 html += '<td nowrap="nowrap">'+esc_html(fieldTypeDesc(fields[i].type))+'</td>';
798 html += '<td nowrap="nowrap">'+esc_html(fields[i].id)+'</td>';
799 html += '<td nowrap="nowrap">'+esc_html(fields[i].required)+'</td>';
800 html += '<td nowrap="nowrap">'+esc_html(fields[i].levels)+'</td>';
801 html += '<td nowrap="nowrap"><a class="ws-plugin--s2member-custom-reg-field-configuration-edit" href="#" onclick="ws_plugin__s2member_customRegFieldEdit('+i+'); return false;"></a><a class="ws-plugin--s2member-custom-reg-field-configuration-delete" href="#" onclick="ws_plugin__s2member_customRegFieldDelete('+i+'); return false;"></a></td>';
802 html += '</tr>';
803 }
804 }
805 else // Otherwise, there are no fields configured yet.
806 {
807 html += /* There are no fields yet. */ '<tr>';
808 html += '<td colspan="6">No Custom Fields are configured.</td>';
809 html += '</tr>';
810 }
811
812 html += '</tbody>';
813
814 $table.html(html);
815 };
816 buildTools(), buildTable();
817 })();
818 }
819 }
820 if(location.href.match(/page\=ws-plugin--s2member-res-ops/))
821 {
822 $('input#ws-plugin--s2member-brute-force-restrictions-reset-button').click(function()
823 {
824 var $this = /* Save $(this) into $this. */ $(this);
825 $this.val /* Indicate loading status (please wait). */('one moment please ...');
826
827 $.post(ajaxurl, {action: 'ws_plugin__s2member_delete_reset_all_ip_restrictions_via_ajax', ws_plugin__s2member_delete_reset_all_ip_restrictions_via_ajax: '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (wp_create_nonce ("ws-plugin--s2member-delete-reset-all-ip-restrictions-via-ajax")); ?>'}, function(response)
828 {
829 alert('s2Member\'s Brute Force Restriction Logs have all been reset.'), $this.val('Reset Brute Force Logs');
830 });
831
832 return false;
833 });
834 $('input#ws-plugin--s2member-ip-restrictions-reset-button').click(function()
835 {
836 var $this = /* Save $(this) into $this. */ $(this);
837 $this.val /* Indicate loading status (please wait). */('one moment please ...');
838
839 $.post(ajaxurl, {action: 'ws_plugin__s2member_delete_reset_all_ip_restrictions_via_ajax', ws_plugin__s2member_delete_reset_all_ip_restrictions_via_ajax: '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (wp_create_nonce ("ws-plugin--s2member-delete-reset-all-ip-restrictions-via-ajax")); ?>'}, function(response)
840 {
841 alert('s2Member\'s IP Restriction Logs have all been reset.'), $this.val('Reset IP Restriction Logs');
842 });
843 return false;
844 });
845 $('div.ws-plugin--s2member-query-level-access-section input[type="checkbox"][name="ws_plugin__s2member_filter_wp_query\[\]"]').change(function()
846 {
847 var thisChange = /* Record value associated with change event. Allows for intutitive unchecking. */ $(this).val();
848
849 $('div.ws-plugin--s2member-query-level-access-section input[type="checkbox"][name="ws_plugin__s2member_filter_wp_query\[\]"]').each(function()
850 {
851 var $this = $(this), val = $this.val(), checkboxes = 'input[type="checkbox"]';
852
853 if /* All sub-items get checked/disabled. */(val === 'all' && this.checked)
854 $this.nextAll(checkboxes).attr({'checked': 'checked', 'disabled': 'disabled'});
855
856 else if(val === 'all' && !this.checked)
857 {
858 $this.nextAll(checkboxes).removeAttr('disabled');
859 (thisChange === 'all') ? $this.nextAll(checkboxes).removeAttr('checked') : null;
860 }
861 });
862 }).last().trigger('change');
863 }
864 if(location.href.match(/page\=ws-plugin--s2member-down-ops/))
865 {
866 var updateCloudFrontPrivateKey = /* Attaches to events below. */ function()
867 {
868 var $hiddenPrivateKey = $('input#ws-plugin--s2member-amazon-cf-files-private-key');
869 var $visiblePrivateKeyEntry = $('textarea#ws-plugin--s2member-amazon-cf-files-private-key-entry');
870 var hiddenPrivateKeyValue = $.trim($hiddenPrivateKey.val()), visiblePrivateKeyEntryValue = $.trim($visiblePrivateKeyEntry.val());
871
872 if((hiddenPrivateKeyValue && !visiblePrivateKeyEntryValue) || visiblePrivateKeyEntryValue.match /* 9679.toString(16).toUpperCase() = 25CF. */(/[^\r\n\u25CF]/))
873 $hiddenPrivateKey.val(visiblePrivateKeyEntryValue), $visiblePrivateKeyEntry.val(visiblePrivateKeyEntryValue.replace(/[^\r\n]/g, String.fromCharCode(9679)));
874 };
875 $('form#ws-plugin--s2member-options-form').submit(updateCloudFrontPrivateKey);
876 $('textarea#ws-plugin--s2member-amazon-cf-files-private-key-entry').change(updateCloudFrontPrivateKey).trigger('change');
877
878 var updateCloudFrontDistroCfgs = /* Attaches to events below. */ function()
879 {
880 var $hiddenPrivateKey = $('input#ws-plugin--s2member-amazon-cf-files-private-key');
881 var $visiblePrivateKeyId = $('input#ws-plugin--s2member-amazon-cf-files-private-key-id');
882
883 var $autoConfigDistros = $('input#ws-plugin--s2member-amazon-cf-files-auto-configure-distros');
884 var $autoConfigDistrosStatus = $('input#ws-plugin--s2member-amazon-cf-files-distros-auto-config-status');
885
886 var autoConfigDistrosStatusValue = $.trim($autoConfigDistrosStatus.val());
887 var hiddenPrivateKeyValue = $.trim($hiddenPrivateKey.val()), visiblePrivateKeyIdValue = $.trim($visiblePrivateKeyId.val());
888 var hiddenPrivateKeyPrevConfigValue = $.trim($hiddenPrivateKey.attr('data-s-prev-config-value')), visiblePrivateKeyIdPrevConfigValue = $.trim($visiblePrivateKeyId.attr('data-s-prev-config-value'));
889
890 if(autoConfigDistrosStatusValue === 'configured' && ((visiblePrivateKeyIdPrevConfigValue && visiblePrivateKeyIdValue !== visiblePrivateKeyIdPrevConfigValue) || (hiddenPrivateKeyPrevConfigValue && hiddenPrivateKeyValue !== hiddenPrivateKeyPrevConfigValue)))
891 {
892 alert('s2Member will need to delete and re-configure your Amazon CloudFront distributions if you change this. When you\'re done editing, click (Save All Changes) below.');
893 $autoConfigDistros.attr /* Forcibly check. */('checked', 'checked');
894 }
895 else if(autoConfigDistrosStatusValue !== 'configured' && visiblePrivateKeyIdValue && hiddenPrivateKeyValue)
896 {
897 alert('s2Member will need to auto-configure your Amazon CloudFront distributions for you. When you\'re done editing, click (Save All Changes) below.');
898 $autoConfigDistros.attr /* Forcibly check. */('checked', 'checked');
899 }
900 };
901 $('input#ws-plugin--s2member-amazon-cf-files-private-key-id').change(updateCloudFrontDistroCfgs);
902 $('textarea#ws-plugin--s2member-amazon-cf-files-private-key-entry').change(updateCloudFrontDistroCfgs);
903
904 $('input#ws-plugin--s2member-amazon-cf-files-auto-configure-distros-w-cnames').change(function()
905 {
906 var $this = $(this), thisChecked = (this.checked) ? true : false;
907 var $autoConfigDistros = $('input#ws-plugin--s2member-amazon-cf-files-auto-configure-distros');
908 var $autoConfigDistroCnames = $('div#ws-plugin--s2member-amazon-cf-files-auto-configure-distro-cnames');
909
910 (thisChecked) ? $autoConfigDistroCnames.show() : $autoConfigDistroCnames.hide();
911 (thisChecked) ? $autoConfigDistros.attr('checked', 'checked') : null;
912
913 }).trigger('change');
914 }
915 if(location.href.match(/page\=ws-plugin--s2member-paypal-ops/))
916 {
917 $('select#ws-plugin--s2member-auto-eot-system-enabled').change(function()
918 {
919 var $this = $(this), val = $this.val();
920 var $viaCron = $('p#ws-plugin--s2member-auto-eot-system-enabled-via-cron');
921
922 if /* Display Cron instructions. */(val == 2)
923 $viaCron.show()
924 else // Hide instructions.
925 $viaCron.hide();
926 });
927 }
928 if(location.href.match(/page\=ws-plugin--s2member-paypal-buttons/))
929 {
930 $('div.ws-menu-page select[id]').filter( /* Filter all select elements with an id. */function()
931 {
932 return this.id.match(/^ws-plugin--s2member-(level[1-9][0-9]*|modification)-term$/);
933 })
934 .change(function()
935 {
936 var button = this.id.replace(/^ws-plugin--s2member-(.+?)-term$/g, '$1');
937 var trialDisabled = ($(this).val().split('-')[2].replace(/[^0-1BN]/g, '') === 'BN') ? 1 : 0;
938
939 $('p#ws-plugin--s2member-'+button+'-trial-line').css('display', (trialDisabled ? 'none' : ''));
940 $('span#ws-plugin--s2member-'+button+'-trial-then').css('display', (trialDisabled ? 'none' : ''));
941 $('span#ws-plugin--s2member-'+button+'-20p-rule').css('display', (trialDisabled ? 'none' : ''));
942
943 (trialDisabled) ? $('input#ws-plugin--s2member-'+button+'-trial-period').val(0) : null;
944 (trialDisabled) ? $('input#ws-plugin--s2member-'+button+'-trial-amount').val('0.00') : null;
945 });
946 $('div.ws-menu-page input[id]').filter( /* Filter all input elements with an id. */function()
947 {
948 return this.id.match(/^ws-plugin--s2member-(level[1-9][0-9]*|modification|ccap)-ccaps$/);
949 })
950 .keyup(function()
951 {
952 var value = this.value.replace(/^(-all|-al|-a|-)[;,]*/gi, ''), _all = (this.value.match(/^(-all|-al|-a|-)[;,]*/i)) ? '-all,' : '';
953 if /* Only if there is a problem with the actual values; because this causes interruptions. */(value.match(/[^a-z_0-9,]/))
954 this.value = _all+$.trim($.trim(value).replace(/[ \-]/g, '_').replace(/[^a-z_0-9,]/gi, '').toLowerCase());
955 });
956 ws_plugin__s2member_paypalButtonGenerate = /* Handles PayPal Button Generation. */ function(button)
957 {
958 var shortCodeTemplate = '[s2Member-PayPal-Button %%attrs%% image="default" output="button" /]', shortCodeTemplateAttrs = '', labels = {};
959
960 eval("<?php echo c_ws_plugin__s2member_utils_strings::esc_dq($labels); ?>");
961
962 var shortCode = $('input#ws-plugin--s2member-'+button+'-shortcode');
963 var code = $('textarea#ws-plugin--s2member-'+button+'-button');
964 var modLevel = $('select#ws-plugin--s2member-modification-level');
965
966 var level = (button === 'modification') ? modLevel.val().split(':', 2)[1] : button.replace(/^level/, '');
967 var label = /* Labels may NOT contain double-quotes. */ labels['level'+level].replace(/"/g, '');
968 var desc = $.trim($('input#ws-plugin--s2member-'+button+'-desc').val().replace(/"/g, ""));
969
970 var trialAmount = $('input#ws-plugin--s2member-'+button+'-trial-amount').val().replace(/[^0-9\.]/g, '');
971 var trialPeriod = $('input#ws-plugin--s2member-'+button+'-trial-period').val().replace(/[^0-9]/g, '');
972 var trialTerm = $('select#ws-plugin--s2member-'+button+'-trial-term').val().replace(/[^A-Z]/g, '');
973
974 var regAmount = $('input#ws-plugin--s2member-'+button+'-amount').val().replace(/[^0-9\.]/g, '');
975 var regPeriod = $('select#ws-plugin--s2member-'+button+'-term').val().split('-')[0].replace(/[^0-9]/g, '');
976 var regTerm = $('select#ws-plugin--s2member-'+button+'-term').val().split('-')[1].replace(/[^A-Z]/g, '');
977 var regRecur = $('select#ws-plugin--s2member-'+button+'-term').val().split('-')[2].replace(/[^0-1BN]/g, '');
978 var /* These options are NOT yet configurable. */ regRecurTimes = '', regRecurRetry = '1';
979
980 var /* NOT yet configurable. */ localeCode = '', digital = '0', noShipping = '1';
981 var pageStyle = $.trim($('input#ws-plugin--s2member-'+button+'-page-style').val().replace(/"/g, ''));
982 var currencyCode = $('select#ws-plugin--s2member-'+button+'-currency').val().replace(/[^A-Z]/g, '');
983
984 var cCaps = $.trim($.trim($('input#ws-plugin--s2member-'+button+'-ccaps').val()).replace(/^(-all|-al|-a|-)[;,]*/gi, '').replace(/[ \-]/g, '_').replace(/[^a-z_0-9,]/gi, '').toLowerCase());
985 cCaps = ($.trim($('input#ws-plugin--s2member-'+button+'-ccaps').val()).match(/^(-all|-al|-a|-)[;,]*/i)) ? ((cCaps) ? '-all,' : '-all')+cCaps.toLowerCase() : cCaps.toLowerCase();
986
987 trialPeriod = /* Lifetime (1-L-BN) and Buy Now ( BN ) access is absolutely NOT compatible w/ Trial Periods. */ (regRecur === 'BN') ? '0' : trialPeriod;
988 trialAmount = /* Validate Trial Amount. */ (!trialAmount || isNaN(trialAmount) || trialAmount < 0.01 || trialPeriod <= 0) ? '0' : trialAmount;
989
990 var levelCcapsPer = (regRecur === 'BN' && regTerm !== 'L') ? level+':'+cCaps+':'+regPeriod+' '+regTerm : level+':'+cCaps;
991 levelCcapsPer = /* Clean any trailing separators from this string. */ levelCcapsPer.replace(/\:+$/g, '');
992
993 if(trialAmount !== '0' && (isNaN(trialAmount) || trialAmount < 0.00))
994 {
995 alert('— Oops, a slight problem: —\n\nWhen provided, Trial Amount must be >= 0.00');
996 return false;
997 }
998 else if(trialAmount !== '0' && /* Maximum. */ trialAmount > 10000.00 && currencyCode.toUpperCase() === 'USD')
999 {
1000 alert('— Oops, a slight problem: —\n\nMaximum Trial Amount is: 10000.00');
1001 return false;
1002 }
1003 else if(trialTerm === 'D' && /* Some validation on the Trial Period. Max days: 90. */ trialPeriod > 90)
1004 {
1005 alert('— Oops, a slight problem: —\n\nMaximum Trial Days is: 90.\nIf you want to offer more than 90 days, please choose Weeks or Months from the drop-down.');
1006 return false;
1007 }
1008 else if(trialTerm === 'W' && /* Some validation on the Trial Period. 52 max. */ trialPeriod > 52)
1009 {
1010 alert('— Oops, a slight problem: —\n\nMaximum Trial Weeks is: 52.\nIf you want to offer more than 52 weeks, please choose Months from the drop-down.');
1011 return false;
1012 }
1013 else if(trialTerm === 'M' && /* Some validation on the Trial Period. 24 max. */ trialPeriod > 24)
1014 {
1015 alert('— Oops, a slight problem: —\n\nMaximum Trial Months is: 24.\nIf you want to offer more than 24 months, please choose Years from the drop-down.');
1016 return false;
1017 }
1018 else if(trialTerm === 'Y' && /* 5 years max. */ trialPeriod > 5)
1019 {
1020 alert('— Oops, a slight problem: —\n\nMax Trial Period Years is: 5.');
1021 return false;
1022 }
1023 else if(!regAmount || isNaN(regAmount) || regAmount < 0.01)
1024 {
1025 alert('— Oops, a slight problem: —\n\nAmount must be >= 0.01');
1026 return false;
1027 }
1028 else if(regAmount > /* $10,000.00 maximum. */ 10000.00 && currencyCode.toUpperCase() === 'USD')
1029 {
1030 alert('— Oops, a slight problem: —\n\nMaximum Amount is: 10000.00');
1031 return false;
1032 }
1033 else if /* Each Button should have a Description. */(!desc)
1034 {
1035 alert('— Oops, a slight problem: —\n\nPlease type a Description for this Button.');
1036 return false;
1037 }
1038 code.html(code.val().replace(/ \<\!--(\<input type\="hidden" name\="(amount|src|srt|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)--\>/g, " $1"));
1039 (parseInt(trialPeriod) <= 0) ? code.html(code.val().replace(/ (\<input type\="hidden" name\="(a1|p1|t1)" value\="(.*?)" \/\>)/g, " <!--$1-->")) : null;
1040 (regRecur === 'BN') ? code.html(code.val().replace(/ (\<input type\="hidden" name\="cmd" value\=")(.*?)(" \/\>)/g, " $1_xclick$3")) : null;
1041 (regRecur === 'BN') ? code.html(code.val().replace(/ (\<input type\="hidden" name\="(src|srt|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)/g, " <!--$1-->")) : null;
1042 (regRecur !== 'BN') ? code.html(code.val().replace(/ (\<input type\="hidden" name\="cmd" value\=")(.*?)(" \/\>)/g, " $1_xclick-subscriptions$3")) : null;
1043 (regRecur !== 'BN') ? code.html(code.val().replace(/ (\<input type\="hidden" name\="amount" value\="(.*?)" \/\>)/g, " <!--$1-->")) : null;
1044
1045 shortCodeTemplateAttrs += /* For Modification Buttons. */ (button === 'modification') ? 'modify="1" ' : '';
1046 shortCodeTemplateAttrs += 'level="'+esc_attr(level)+'" ccaps="'+esc_attr(cCaps)+'" desc="'+esc_attr(desc)+'" ps="'+esc_attr(pageStyle)+'" lc="'+esc_attr(localeCode)+'" cc="'+esc_attr(currencyCode)+'" dg="'+esc_attr(digital)+'" ns="'+esc_attr(noShipping)+'" custom="<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>"';
1047 shortCodeTemplateAttrs += ' ta="'+esc_attr(trialAmount)+'" tp="'+esc_attr(trialPeriod)+'" tt="'+esc_attr(trialTerm)+'" ra="'+esc_attr(regAmount)+'" rp="'+esc_attr(regPeriod)+'" rt="'+esc_attr(regTerm)+'" rr="'+esc_attr(regRecur)+'" rrt="'+esc_attr(regRecurTimes)+'" rra="'+esc_attr(regRecurRetry)+'"';
1048 shortCode.val(shortCodeTemplate.replace(/%%attrs%%/, shortCodeTemplateAttrs));
1049
1050 code.html(code.val().replace(/ name\="lc" value\="(.*?)"/, ' name="lc" value="'+esc_attr(localeCode)+'"'));
1051 code.html(code.val().replace(/ name\="no_shipping" value\="(.*?)"/, ' name="no_shipping" value="'+esc_attr(noShipping)+'"'));
1052 code.html(code.val().replace(/ name\="item_name" value\="(.*?)"/, ' name="item_name" value="'+esc_attr(desc)+'"'));
1053 code.html(code.val().replace(/ name\="item_number" value\="(.*?)"/, ' name="item_number" value="'+esc_attr(levelCcapsPer)+'"'));
1054 code.html(code.val().replace(/ name\="page_style" value\="(.*?)"/, ' name="page_style" value="'+esc_attr(pageStyle)+'"'));
1055 code.html(code.val().replace(/ name\="currency_code" value\="(.*?)"/, ' name="currency_code" value="'+esc_attr(currencyCode)+'"'));
1056 code.html(code.val().replace(/ name\="custom" value\="(.*?)"/, ' name="custom" value="<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>"'));
1057
1058 code.html(code.val().replace(/ name\="modify" value\="(.*?)"/, ' name="modify" value="'+((button === 'modification') ? '1' : '0')+'"'));
1059
1060 code.html(code.val().replace(/ name\="amount" value\="(.*?)"/, ' name="amount" value="'+esc_attr(regAmount)+'"'));
1061
1062 code.html(code.val().replace(/ name\="src" value\="(.*?)"/, ' name="src" value="'+esc_attr(regRecur)+'"'));
1063 code.html(code.val().replace(/ name\="srt" value\="(.*?)"/, ' name="srt" value="'+esc_attr(regRecurTimes)+'"'));
1064 code.html(code.val().replace(/ name\="sra" value\="(.*?)"/, ' name="sra" value="'+esc_attr(regRecurRetry)+'"'));
1065
1066 code.html(code.val().replace(/ name\="a1" value\="(.*?)"/, ' name="a1" value="'+esc_attr(trialAmount)+'"'));
1067 code.html(code.val().replace(/ name\="p1" value\="(.*?)"/, ' name="p1" value="'+esc_attr(trialPeriod)+'"'));
1068 code.html(code.val().replace(/ name\="t1" value\="(.*?)"/, ' name="t1" value="'+esc_attr(trialTerm)+'"'));
1069 code.html(code.val().replace(/ name\="a3" value\="(.*?)"/, ' name="a3" value="'+esc_attr(regAmount)+'"'));
1070 code.html(code.val().replace(/ name\="p3" value\="(.*?)"/, ' name="p3" value="'+esc_attr(regPeriod)+'"'));
1071 code.html(code.val().replace(/ name\="t3" value\="(.*?)"/, ' name="t3" value="'+esc_attr(regTerm)+'"'));
1072
1073 $('div#ws-plugin--s2member-'+button+'-button-prev').html(code.val().replace(/\<form/, '<form target="_blank"').replace(/\<\?php echo S2MEMBER_VALUE_FOR_PP_INV\(\); \?\>/g, Math.round(new Date().getTime())+'~<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr (c_ws_plugin__s2member_utils_ip::current())); ?>').replace(/\<\?php echo S2MEMBER_CURRENT_USER_VALUE_FOR_PP_(ON0|OS0|ON1|OS1); \?\>/g, ''));
1074
1075 (button === 'modification') ? alert('Your Modification Button has been generated.\nPlease copy/paste the Shortcode into your Login Welcome Page, or wherever you feel it would be most appropriate.\n\n* Remember, Modification Buttons should be displayed to existing Users/Members, and they should be logged-in, BEFORE clicking this Button.') : alert('Your Button has been generated.\nPlease copy/paste the Shortcode Format into your Membership Options Page.');
1076
1077 shortCode.each( /* Focus and select the Shortcode. */function()
1078 {
1079 this.focus(), this.select();
1080 });
1081 return false;
1082 };
1083 ws_plugin__s2member_paypalCcapButtonGenerate = /* Handles PayPal Button Generation for Independent Capabilities. */ function()
1084 {
1085 var shortCodeTemplate = '[s2Member-PayPal-Button %%attrs%% image="default" output="button" /]', shortCodeTemplateAttrs = '';
1086
1087 var shortCode = $('input#ws-plugin--s2member-ccap-shortcode');
1088 var code = $('textarea#ws-plugin--s2member-ccap-button');
1089
1090 var desc = $.trim($('input#ws-plugin--s2member-ccap-desc').val().replace(/"/g, ''));
1091
1092 var regAmount = $('input#ws-plugin--s2member-ccap-amount').val().replace(/[^0-9\.]/g, '');
1093 var regPeriod = $('select#ws-plugin--s2member-ccap-term').val().split('-')[0].replace(/[^0-9]/g, '');
1094 var regTerm = $('select#ws-plugin--s2member-ccap-term').val().split('-')[1].replace(/[^A-Z]/g, '');
1095 var regRecur = $('select#ws-plugin--s2member-ccap-term').val().split('-')[2].replace(/[^0-1BN]/g, '');
1096
1097 var /* NOT yet configurable. */ localeCode = '', digital = '0', noShipping = '1';
1098 var pageStyle = $.trim($('input#ws-plugin--s2member-ccap-page-style').val().replace(/"/g, ''));
1099 var currencyCode = $('select#ws-plugin--s2member-ccap-currency').val().replace(/[^A-Z]/g, '');
1100
1101 var cCaps = $.trim($.trim($('input#ws-plugin--s2member-ccap-ccaps').val()).replace(/^(-all|-al|-a|-)[;,]*/gi, '').replace(/[ \-]/g, '_').replace(/[^a-z_0-9,]/gi, '').toLowerCase());
1102 cCaps = ($.trim($('input#ws-plugin--s2member-ccap-ccaps').val()).match(/^(-all|-al|-a|-)[;,]*/i)) ? ((cCaps) ? '-all,' : '-all')+cCaps.toLowerCase() : cCaps.toLowerCase();
1103
1104 var levelCcapsPer = (regRecur === 'BN' && regTerm !== 'L') ? '*:'+cCaps+':'+regPeriod+' '+regTerm : '*:'+cCaps;
1105 levelCcapsPer = /* Clean any trailing separators from this string. */ levelCcapsPer.replace(/\:+$/g, '');
1106
1107 if /* Must have some Independent Custom Capabilities. */(!cCaps || cCaps === '-all')
1108 {
1109 alert('— Oops, a slight problem: —\n\nPlease provide at least one Custom Capability.');
1110 return false;
1111 }
1112 else if(!regAmount || isNaN(regAmount) || regAmount < 0.01)
1113 {
1114 alert('— Oops, a slight problem: —\n\nAmount must be >= 0.01');
1115 return false;
1116 }
1117 else if /* $10,000.00 maximum. */(regAmount > 10000.00 && currencyCode.toUpperCase() === 'USD')
1118 {
1119 alert('— Oops, a slight problem: —\n\nMaximum Amount is: 10000.00');
1120 return false;
1121 }
1122 else if /* Each Button should have a Description. */(!desc)
1123 {
1124 alert('— Oops, a slight problem: —\n\nPlease type a Description for this Button.');
1125 return false;
1126 }
1127
1128 shortCodeTemplateAttrs += 'level="*" ccaps="'+esc_attr(cCaps)+'" desc="'+esc_attr(desc)+'" ps="'+esc_attr(pageStyle)+'" lc="'+esc_attr(localeCode)+'" cc="'+esc_attr(currencyCode)+'" dg="'+esc_attr(digital)+'" ns="'+esc_attr(noShipping)+'"';
1129 shortCodeTemplateAttrs += ' custom="<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>" ra="'+esc_attr(regAmount)+'" rp="'+esc_attr(regPeriod)+'" rt="'+esc_attr(regTerm)+'" rr="'+esc_attr(regRecur)+'"';
1130 shortCode.val(shortCodeTemplate.replace(/%%attrs%%/, shortCodeTemplateAttrs));
1131
1132 code.html(code.val().replace(/ name\="lc" value\="(.*?)"/, ' name="lc" value="'+esc_attr(localeCode)+'"'));
1133 code.html(code.val().replace(/ name\="no_shipping" value\="(.*?)"/, ' name="no_shipping" value="'+esc_attr(noShipping)+'"'));
1134 code.html(code.val().replace(/ name\="item_name" value\="(.*?)"/, ' name="item_name" value="'+esc_attr(desc)+'"'));
1135 code.html(code.val().replace(/ name\="item_number" value\="(.*?)"/, ' name="item_number" value="'+esc_attr(levelCcapsPer)+'"'));
1136 code.html(code.val().replace(/ name\="page_style" value\="(.*?)"/, ' name="page_style" value="'+esc_attr(pageStyle)+'"'));
1137 code.html(code.val().replace(/ name\="currency_code" value\="(.*?)"/, ' name="currency_code" value="'+esc_attr(currencyCode)+'"'));
1138 code.html(code.val().replace(/ name\="custom" value\="(.*?)"/, ' name="custom" value="<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>"'));
1139
1140 code.html(code.val().replace(/ name\="amount" value\="(.*?)"/, ' name="amount" value="'+esc_attr(regAmount)+'"'));
1141
1142 $('div#ws-plugin--s2member-ccap-button-prev').html(code.val().replace(/\<form/, '<form target="_blank"').replace(/\<\?php echo S2MEMBER_VALUE_FOR_PP_INV\(\); \?\>/g, Math.round(new Date().getTime())+'~<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr (c_ws_plugin__s2member_utils_ip::current())); ?>').replace(/\<\?php echo S2MEMBER_CURRENT_USER_VALUE_FOR_PP_(ON0|OS0|ON1|OS1); \?\>/g, ''));
1143
1144 alert('Your Button has been generated.\nPlease copy/paste the Shortcode into your Login Welcome Page, or wherever you feel it would be most appropriate.\n\n* Remember, Independent Custom Capability Buttons should ONLY be displayed to existing Users/Members, and they MUST be logged-in, BEFORE clicking this Button.');
1145
1146 shortCode.each /* Focus and select the Shortcode. */(function()
1147 {
1148 this.focus(), this.select();
1149 });
1150 return false;
1151 };
1152 ws_plugin__s2member_paypalSpButtonGenerate = /* Handles PayPal Button Generation for Specific Post/Page Access. */ function()
1153 {
1154 var shortCodeTemplate = '[s2Member-PayPal-Button %%attrs%% image="default" output="button" /]', shortCodeTemplateAttrs = '';
1155
1156 var shortCode = $('input#ws-plugin--s2member-sp-shortcode');
1157 var code = $('textarea#ws-plugin--s2member-sp-button');
1158
1159 var leading = $('select#ws-plugin--s2member-sp-leading-id').val().replace(/[^0-9]/g, '');
1160 var additionals = $('select#ws-plugin--s2member-sp-additional-ids').val() || [];
1161 var hours = $('select#ws-plugin--s2member-sp-hours').val().replace(/[^0-9]/g, '');
1162
1163 var regAmount = $('input#ws-plugin--s2member-sp-amount').val().replace(/[^0-9\.]/g, '');
1164 var desc = $.trim($('input#ws-plugin--s2member-sp-desc').val().replace(/"/g, ''));
1165
1166 var /* NOT yet configurable. */ localeCode = '', digital = '0', noShipping = '1';
1167 var pageStyle = $.trim($('input#ws-plugin--s2member-sp-page-style').val().replace(/"/g, ''));
1168 var currencyCode = $('select#ws-plugin--s2member-sp-currency').val().replace(/[^A-Z]/g, '');
1169
1170 if /* Must have a Leading Post/Page ID to work with. Otherwise, Link generation will fail. */(!leading)
1171 {
1172 alert('— Oops, a slight problem: —\n\nPlease select a Leading Post/Page.\n\n*Tip* If there are no Posts/Pages in the menu, it\'s because you\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member → Restriction Options → Specific Post/Page Access.');
1173 return false;
1174 }
1175 else if(!regAmount || isNaN(regAmount) || regAmount < 0.01)
1176 {
1177 alert('— Oops, a slight problem: —\n\nAmount must be >= 0.01');
1178 return false;
1179 }
1180 else if /* $10,000.00 maximum. */(regAmount > 10000.00 && currencyCode.toUpperCase() === 'USD')
1181 {
1182 alert('— Oops, a slight problem: —\n\nMaximum Amount is: 10000.00');
1183 return false;
1184 }
1185 else if /* Each Button should have a Description. */(!desc)
1186 {
1187 alert('— Oops, a slight problem: —\n\nPlease type a Description for this Button.');
1188 return false;
1189 }
1190 for(var i = 0, ids = leading; i < additionals.length; i++)
1191 if(additionals[i] && additionals[i] !== leading)
1192 ids += ','+additionals[i];
1193
1194 var /* Combined sp:ids:expiration hours. */ spIdsHours = 'sp:'+ids+':'+hours;
1195
1196 shortCodeTemplateAttrs += 'sp="1" ids="'+esc_attr(ids)+'" exp="'+esc_attr(hours)+'" desc="'+esc_attr(desc)+'" ps="'+esc_attr(pageStyle)+'" lc="'+esc_attr(localeCode)+'" cc="'+esc_attr(currencyCode)+'" dg="'+esc_attr(digital)+'" ns="'+esc_attr(noShipping)+'"';
1197 shortCodeTemplateAttrs += ' custom="<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>" ra="'+esc_attr(regAmount)+'"';
1198 shortCode.val(shortCodeTemplate.replace(/%%attrs%%/, shortCodeTemplateAttrs));
1199
1200 code.html(code.val().replace(/ name\="lc" value\="(.*?)"/, ' name="lc" value="'+esc_attr(localeCode)+'"'));
1201 code.html(code.val().replace(/ name\="no_shipping" value\="(.*?)"/, ' name="no_shipping" value="'+esc_attr(noShipping)+'"'));
1202 code.html(code.val().replace(/ name\="item_name" value\="(.*?)"/, ' name="item_name" value="'+esc_attr(desc)+'"'));
1203 code.html(code.val().replace(/ name\="item_number" value\="(.*?)"/, ' name="item_number" value="'+esc_attr(spIdsHours)+'"'));
1204 code.html(code.val().replace(/ name\="page_style" value\="(.*?)"/, ' name="page_style" value="'+esc_attr(pageStyle)+'"'));
1205 code.html(code.val().replace(/ name\="currency_code" value\="(.*?)"/, ' name="currency_code" value="'+esc_attr(currencyCode)+'"'));
1206 code.html(code.val().replace(/ name\="custom" value\="(.*?)"/, ' name="custom" value="<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>"'));
1207
1208 code.html(code.val().replace(/ name\="amount" value\="(.*?)"/, ' name="amount" value="'+esc_attr(regAmount)+'"'));
1209
1210 $('div#ws-plugin--s2member-sp-button-prev').html(code.val().replace(/\<form/, '<form target="_blank"').replace(/\<\?php echo S2MEMBER_VALUE_FOR_PP_INV\(\); \?\>/g, Math.round(new Date().getTime())+'~<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (esc_attr (c_ws_plugin__s2member_utils_ip::current())); ?>').replace(/\<\?php echo S2MEMBER_CURRENT_USER_VALUE_FOR_PP_(ON0|OS0|ON1|OS1); \?\>/g, ''));
1211
1212 alert('Your Button has been generated.\nPlease copy/paste the Shortcode into your WordPress Editor.');
1213
1214 shortCode.each( /* Focus and select the Shortcode. */function()
1215 {
1216 this.focus(), this.select();
1217 });
1218 return false;
1219 };
1220 ws_plugin__s2member_paypalRegLinkGenerate = /* Handles PayPal Link Generation. */ function()
1221 {
1222 var level = $('select#ws-plugin--s2member-reg-link-level').val().replace(/[^0-9]/g, '');
1223 var subscrID = $.trim($('input#ws-plugin--s2member-reg-link-subscr-id').val());
1224 var custom = $.trim($('input#ws-plugin--s2member-reg-link-custom').val());
1225 var cCaps = $.trim($.trim($('input#ws-plugin--s2member-reg-link-ccaps').val()).replace(/[ \-]/g, '_').replace(/[^a-z_0-9,]/gi, '').toLowerCase());
1226 var fixedTerm = $.trim($('input#ws-plugin--s2member-reg-link-fixed-term').val().replace(/[^A-Z 0-9]/gi, '').toUpperCase());
1227 var $link = $('p#ws-plugin--s2member-reg-link'), $loading = $('img#ws-plugin--s2member-reg-link-loading');
1228
1229 var levelCcapsPer = (fixedTerm && !fixedTerm.match(/L$/)) ? level+':'+cCaps+':'+fixedTerm : level+':'+cCaps;
1230 levelCcapsPer = /* Clean any trailing separators from this string. */ levelCcapsPer.replace(/\:+$/g, '');
1231
1232 if /* We must have a Paid Subscr. ID value. */(!subscrID)
1233 {
1234 alert('— Oops, a slight problem: —\n\nPaid Subscr. ID is a required value.');
1235 return false;
1236 }
1237 else if(!custom || custom.indexOf('<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq ($_SERVER["HTTP_HOST"]); ?>') !== 0)
1238 {
1239 alert('— Oops, a slight problem: —\n\nThe Custom Value MUST start with your domain name.');
1240 return false;
1241 }
1242 else if /* Check format. */(fixedTerm && !fixedTerm.match(/^[1-9]+ (D|W|M|Y|L)$/))
1243 {
1244 alert('— Oops, a slight problem: —\n\nThe Fixed Term Length is not formatted properly.');
1245 return false;
1246 }
1247 $link.hide(), $loading.show(), $.post(ajaxurl, {action: 'ws_plugin__s2member_reg_access_link_via_ajax', ws_plugin__s2member_reg_access_link_via_ajax: '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (wp_create_nonce ("ws-plugin--s2member-reg-access-link-via-ajax")); ?>', s2member_reg_access_link_subscr_gateway: 'paypal', s2member_reg_access_link_subscr_id: subscrID, s2member_reg_access_link_custom: custom, s2member_reg_access_link_item_number: levelCcapsPer}, function(response)
1248 {
1249 $link.show().html('<a href="'+esc_attr(response)+'" target="_blank" rel="external">'+esc_html(response)+'</a>'), $loading.hide();
1250 });
1251 return false;
1252 };
1253 ws_plugin__s2member_paypalSpLinkGenerate = /* Handles PayPal Link Generation. */ function()
1254 {
1255 var leading = $('select#ws-plugin--s2member-sp-link-leading-id').val().replace(/[^0-9]/g, '');
1256 var additionals = $('select#ws-plugin--s2member-sp-link-additional-ids').val() || [];
1257 var hours = $('select#ws-plugin--s2member-sp-link-hours').val().replace(/[^0-9]/g, '');
1258 var $link = $('p#ws-plugin--s2member-sp-link'), $loading = $('img#ws-plugin--s2member-sp-link-loading');
1259
1260 if /* Must have a Leading Post/Page ID to work with. Otherwise, Link generation will fail. */(!leading)
1261 {
1262 alert('— Oops, a slight problem: —\n\nPlease select a Leading Post/Page.\n\n*Tip* If there are no Posts/Pages in the menu, it\'s because you\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member → Restriction Options → Specific Post/Page Access.');
1263 return false;
1264 }
1265 for(var i = 0, ids = leading; i < additionals.length; i++)
1266 if(additionals[i] && additionals[i] !== leading)
1267 ids += ','+additionals[i];
1268
1269 $link.hide(), $loading.show(), $.post(ajaxurl, {action: 'ws_plugin__s2member_sp_access_link_via_ajax', ws_plugin__s2member_sp_access_link_via_ajax: '<?php echo c_ws_plugin__s2member_utils_strings::esc_js_sq (wp_create_nonce ("ws-plugin--s2member-sp-access-link-via-ajax")); ?>', s2member_sp_access_link_ids: ids, s2member_sp_access_link_hours: hours}, function(response)
1270 {
1271 $link.show().html('<a href="'+esc_attr(response)+'" target="_blank" rel="external">'+esc_html(response)+'</a>'), $loading.hide();
1272 });
1273 return false;
1274 };
1275 }
1276 if(location.href.match(/page\=ws-plugin--s2member-els-ops/))
1277 {
1278 $('select#ws-plugin--s2member-custom-reg-opt-in').change(function()
1279 {
1280 var $this = $(this), val = $this.val();
1281 var $rows = $('tr.ws-plugin--s2member-custom-reg-opt-in-label-row');
1282 var $prevImg = $('img.ws-plugin--s2member-custom-reg-opt-in-label-prev-img');
1283
1284 if /* Checkbox disabled. */(val <= 0)
1285 $rows.css('display', 'none'), $prevImg.attr('src', $prevImg.attr('src').replace(/\/checked\.png$/, '/unchecked.png'));
1286
1287 else if /* Enabled, checked by default. */(val == 1)
1288 $rows.css('display', ''), $prevImg.attr('src', $prevImg.attr('src').replace(/\/unchecked\.png$/, '/checked.png'));
1289
1290 else if /* Enabled, unchecked by default. */(val == 2)
1291 $rows.css('display', ''), $prevImg.attr('src', $prevImg.attr('src').replace(/\/checked\.png$/, '/unchecked.png'));
1292 });
1293 $('div.ws-plugin--s2member-opt-out-section input[type="checkbox"][name="ws_plugin__s2member_custom_reg_auto_opt_outs\[\]"]').change(function()
1294 {
1295 var /* Record value associated with change event. Also initialize checkedIndexes array. */ thisChange = $(this).val(), checkedIndexes = [];
1296
1297 $('div.ws-plugin--s2member-opt-out-section input[type="checkbox"][name="ws_plugin__s2member_custom_reg_auto_opt_outs\[\]"]').each(function()
1298 {
1299 var $this = $(this), val = $this.val(), checkboxes = 'input[type="checkbox"]';
1300
1301 if /* All sub-items get checked/disabled too. */(val === 'removal-deletion' && this.checked)
1302 $this.nextAll(checkboxes).slice(0, 2).attr({'checked': 'checked', 'disabled': 'disabled'});
1303
1304 else if(val === 'removal-deletion' && !this.checked)
1305 {
1306 $this.nextAll(checkboxes).slice(0, 2).removeAttr('disabled');
1307 (thisChange === 'removal-deletion') ? $this.nextAll(checkboxes).slice(0, 2).removeAttr('checked') : null;
1308 }
1309 else if /* All sub-items get checked/disabled too. */(val === 'modification' && this.checked)
1310 $this.nextAll(checkboxes).slice(0, 3).attr({'checked': 'checked', 'disabled': 'disabled'});
1311
1312 else if(val === 'modification' && !this.checked)
1313 {
1314 (thisChange === 'modification') ? $this.nextAll(checkboxes).slice(0, 3).removeAttr('checked') : null;
1315 $this.nextAll(checkboxes).slice(0, 3).removeAttr('disabled');
1316 }
1317 })
1318 .each( /* Now, which ones are checked? */function(index)
1319 {
1320 (this.checked) ? checkedIndexes.push(index) : null;
1321 });
1322 $('select#ws-plugin--s2member-custom-reg-auto-opt-out-transitions').removeAttr('disabled');
1323 if($.inArray(3, checkedIndexes) === -1 && $.inArray(4, checkedIndexes) === -1 && $.inArray(5, checkedIndexes) === -1 && $.inArray(6, checkedIndexes) === -1)
1324 $('select#ws-plugin--s2member-custom-reg-auto-opt-out-transitions').attr('disabled', 'disabled');
1325
1326 }).last().trigger('change');
1327 }
1328 });
1329