PluginProbe
Authorizer / 2.9.13
Authorizer v2.9.13
3.15.3 3.15.2 3.15.1 3.15.0 3.14.3 3.14.4 3.14.2 3.14.1 2.8.1 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.9.0 2.9.1 2.9.10 2.9.11 2.9.12 2.9.13 2.9.2 2.9.3 2.9.6 All 126 releases
authorizer / js / authorizer.js

authorizer.js in Authorizer 2.9.13, at js/authorizer.js

1,365 lines 59.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * UI wiring for Authorizer Settings page.
3 */
4
5 /* global window, document, setTimeout, sessionStorage, ajaxurl, authL10n, history */
6 ( function( $ ) {
7
8 // Milliseconds for jQuery UI animations to complete.
9 var animationSpeed = 300;
10 // Milliseconds for shake animation (reject email address) to complete.
11 var shakeSpeed = 600;
12
13 /**
14 * Wiring and UI for Authorizer Settings page.
15 */
16
17 // Switch between pages in the Approved User list.
18 // @calls php wp_ajax_refresh_approved_user_list.
19 function refreshApprovedUserList( currentPage, searchTerm ) {
20 var $list = $( '#list_auth_settings_access_users_approved' );
21 var $spinner = $( '<span class="spinner is-active"></span>' ).css({
22 position: 'relative',
23 top: '40%',
24 left: '-240px',
25 });
26 var $overlay = $( '<div id="list_auth_settings_access_users_approved_overlay"></div>' ).css({
27 'background-color': '#f1f1f1',
28 'z-index': 1,
29 opacity: 0.8,
30 position: 'absolute',
31 top: $list.position().top + parseInt( $list.css( 'margin-top' ) ),
32 left: $list.position().left,
33 width: $list.width(),
34 height: $list.height(),
35 });
36 $overlay.append( $spinner );
37
38 // Show overlay and wait cursor.
39 $list.after( $overlay );
40 $( 'html' ).addClass( 'busy' );
41
42 $.post( ajaxurl, {
43 action: 'refresh_approved_user_list',
44 nonce: $( '#nonce_save_auth_settings' ).val(),
45 is_network_admin: authL10n.is_network_admin, // eslint-disable-line camelcase
46 paged: currentPage,
47 search: searchTerm,
48 }, function( response ) {
49 if ( response.success ) {
50 // Update user list and total user and page count.
51 $( '#list_auth_settings_access_users_approved' ).html( response.html );
52 $( '.displaying-num' ).html( response.total_users_html );
53 $( '.total-pages' ).html( response.total_pages_html );
54
55 // Adjust our current page if the query changed the total page count.
56 if ( currentPage > response.total_pages ) {
57 currentPage = response.total_pages;
58 }
59
60 // Update pager elements.
61 refreshApprovedUserPager( currentPage );
62
63 // Update querystring with new paged param value (but don't reload the page).
64 if ( history.pushState ) {
65 var url = window.location.href;
66 url = updateQueryStringParameter( url, 'paged', currentPage );
67 url = updateQueryStringParameter( url, 'search', searchTerm );
68 window.history.pushState( { path: url }, '', url );
69 }
70 }
71 // Remove overlay and wait cursor.
72 $overlay.remove();
73 $( 'html' ).removeClass( 'busy' );
74 }).fail( function() {
75 // Remove overlay and wait cursor.
76 $overlay.remove();
77 $( 'html' ).removeClass( 'busy' );
78 });
79 }
80
81 // Update the pager elements when changing pages.
82 function refreshApprovedUserPager( currentPage ) {
83 var totalPages = parseInt( $( '.total-pages' ).first().text().replace( /[^0-9]/g, '' ), 10 ) || 1;
84
85 // If total number of pages changed (because a search filter reduced it), make
86 // sure current page is not larger than it.
87 if ( currentPage > totalPages ) {
88 currentPage = totalPages;
89 }
90 if ( currentPage < 1 ) {
91 currentPage = 1;
92 }
93 if ( totalPages < 1 ) {
94 totalPages = 1;
95 }
96
97 // Update current page text input.
98 $( '#current-page-selector' ).val( currentPage );
99
100 // Update current page span.
101 $( '#table-paging .current-page-text' ).text( currentPage );
102
103 // Update first page button.
104 var $first = $( '.first-page' );
105 if ( $first.is( 'a' ) && currentPage <= 1 ) {
106 $first.replaceWith( '<span class="button disabled first-page tablenav-pages-navspan" aria-hidden="true">&laquo;</span>' );
107 } else if ( $first.is( 'span' ) && currentPage > 1 ) {
108 $first.replaceWith( '<a class="button first-page" href="' + updateQueryStringParameter( window.location.href, 'paged', '1' ) + '"><span class="screen-reader-text">' + authL10n.first_page + '</span><span aria-hidden="true">&laquo;</span></a>' );
109 }
110
111 // Update prev page button.
112 var $prev = $( '.prev-page' );
113 if ( $prev.is( 'a' ) && currentPage <= 1 ) {
114 $prev.replaceWith( '<span class="button disabled prev-page tablenav-pages-navspan" aria-hidden="true">&lsaquo;</span>' );
115 } else if ( currentPage > 1 ) {
116 $prev.replaceWith( '<a class="button prev-page" href="' + updateQueryStringParameter( window.location.href, 'paged', currentPage - 1 ) + '"><span class="screen-reader-text">' + authL10n.prev_page + '</span><span aria-hidden="true">&lsaquo;</span></a>' );
117 }
118
119 // Update next button.
120 var $next = $( '.next-page' );
121 if ( $next.is( 'a' ) && currentPage >= totalPages ) {
122 $next.replaceWith( '<span class="button disabled next-page tablenav-pages-navspan" aria-hidden="true">&rsaquo;</span>' );
123 } else if ( currentPage < totalPages ) {
124 $next.replaceWith( '<a class="button next-page" href="' + updateQueryStringParameter( window.location.href, 'paged', currentPage + 1 ) + '"><span class="screen-reader-text">' + authL10n.next_page + '</span><span aria-hidden="true">&rsaquo;</span></a>' );
125 }
126
127 // Update last button.
128 var $last = $( '.last-page' );
129 if ( $last.is( 'a' ) && currentPage >= totalPages ) {
130 $last.replaceWith( '<span class="button disabled last-page tablenav-pages-navspan" aria-hidden="true">&raquo;</span>' );
131 } else if ( $last.is( 'span' ) && currentPage < totalPages ) {
132 $last.replaceWith( '<a class="button last-page" href="' + updateQueryStringParameter( window.location.href, 'paged', totalPages ) + '"><span class="screen-reader-text">' + authL10n.next_page + '</span><span aria-hidden="true">&raquo;</span></a>' );
133 }
134 }
135
136 // Make changes to one of the user lists (pending, approved, blocked) via ajax.
137 // @calls php wp_ajax_update_auth_user.
138 function updateAuthUser( caller, setting, usersToEdit ) {
139 var accessUsersPending = [],
140 accessUsersApproved = [],
141 accessUsersBlocked = [],
142 nonce = $( '#nonce_save_auth_settings' ).val();
143
144 // Defaults:
145 // setting = 'access_users_pending' or 'access_users_approved' or 'access_users_blocked',
146 // usersToEdit = [
147 // {
148 // email: 'johndoe@example.com',
149 // role: 'subscriber',
150 // date_added: 'Jun 2014',
151 // edit_action: 'add' or 'remove' or 'change_role',
152 // local_user: true or false,
153 // multisite_user: true or false,
154 // }, {
155 // ...
156 // }
157 // ]
158 setting = typeof setting !== 'undefined' ? setting : 'none';
159
160 // If we are only editing a single user, make that user the only item in the array.
161 usersToEdit = typeof usersToEdit !== 'undefined' ? usersToEdit : [];
162 if ( ! Array.isArray( usersToEdit ) ) {
163 usersToEdit = [ usersToEdit ];
164 }
165
166 // Enable wait cursor.
167 $( 'html' ).addClass( 'busy' );
168
169 // Disable button (prevent duplicate clicks).
170 $( caller ).attr( 'disabled', 'disabled' );
171
172 // Enable spinner by element that triggered this event (caller).
173 var $row = $( caller ).closest( 'li' );
174 if ( $row.length > 0 ) {
175 var $spinner = $( '<span class="spinner is-active"></span>' ).css({
176 position: 'absolute',
177 top: $row.position().top,
178 left: $row.position().left + $row.width(),
179 });
180 $row.append( $spinner );
181 }
182
183 // Grab the value of the setting we are saving.
184 if ( setting === 'access_users_pending' ) {
185 accessUsersPending = usersToEdit;
186 } else if ( setting === 'access_users_approved' ) {
187 accessUsersApproved = usersToEdit;
188 } else if ( setting === 'access_users_blocked' ) {
189 accessUsersBlocked = usersToEdit;
190 }
191
192 $.post( ajaxurl, {
193 action: 'update_auth_user',
194 setting: setting,
195 access_users_pending: accessUsersPending, // eslint-disable-line camelcase
196 access_users_approved: accessUsersApproved, // eslint-disable-line camelcase
197 access_users_blocked: accessUsersBlocked, // eslint-disable-line camelcase
198 nonce: nonce,
199 }, function( response ) {
200 // Server responded, but if success isn't true it failed to save.
201 var succeeded = response.success;
202 var spinnerText = succeeded ? authL10n.saved + '.' : '<span class="attention">' + authL10n.failed + '.</span>';
203 var spinnerWait = succeeded ? 500 : 2000;
204
205 // Remove any new user entries that were rejected by the server.
206 if ( response.invalid_emails.length > 0 ) {
207 for ( var i = 0; i < response.invalid_emails.length; i++ ) {
208 var duplicateEmail = response.invalid_emails[i];
209 $( 'li.new-user .auth-email[value="' + duplicateEmail + '"]' )
210 .siblings( '.spinner' ).addClass( 'duplicate' ).append( '<span class="spinner-text"><span class="attention">' + authL10n.duplicate + '.</span></span>' )
211 .parent().fadeOut( spinnerWait, function() { $( this ).remove(); }); // jshint ignore:line
212 }
213 }
214
215 // Show message ('Saved', 'Failed', or 'Saved, removing duplicates').
216 $( 'form .spinner:not(:has(.spinner-text)):not(.duplicate)' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
217 $( this ).remove();
218 });
219 $( caller ).removeAttr( 'disabled' );
220
221 // Disable wait cursor.
222 $( 'html' ).removeClass( 'busy' );
223 }).fail( function() {
224 // Fail fires if the server doesn't respond or responds with 500 codes
225 var succeeded = false;
226 var spinnerText = succeeded ? authL10n.saved + '.' : '<span class="attention">' + authL10n.failed + '.</span>';
227 var spinnerWait = succeeded ? 500 : 2000;
228 $( 'form .spinner:not(:has(.spinner-text))' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
229 $( this ).remove();
230 });
231 $( caller ).removeAttr( 'disabled' );
232
233 // Disable wait cursor.
234 $( 'html' ).removeClass( 'busy' );
235 });
236 }
237
238
239 // Hide or show (with overlay) the multisite settings based on the "multisite override" setting.
240 function hideMultisiteSettingsIfDisabled() {
241 if ( $( '#auth_settings_multisite_override' ).length === 0 ) {
242 return;
243 }
244
245 var settings = $( '#auth_multisite_settings' );
246 var overlay = $( '#auth_multisite_settings_disabled_overlay' );
247
248 if ( $( '#auth_settings_multisite_override' ).is( ':checked' ) ) {
249 overlay.hide( animationSpeed );
250 } else {
251 overlay.css({
252 'background-color': '#f1f1f1',
253 'z-index': 1,
254 opacity: 0.8,
255 position: 'absolute',
256 top: settings.position().top,
257 left: settings.position().left,
258 width: settings.width(),
259 height: settings.height() + 50,
260 });
261 overlay.show();
262 }
263 }
264
265 // Helper function to remove duplicate entries from an array of strings.
266 function removeDuplicatesFromArrayOfStrings( arrayOfStrings ) {
267 var seen = {};
268 return arrayOfStrings.filter( function( item ) {
269 return seen.hasOwnProperty( item ) ? false : ( seen[item] = true );
270 });
271 }
272
273 // Helper function to hide/show wordpress option
274 function animateOption( action, option ) {
275 if ( action === 'show' ) {
276 $( 'div.animated_wrapper', option ).slideDown( animationSpeed );
277 $( 'th, td', option ).removeClass( 'hide-animate hide-no-animate' );
278 } else if ( action === 'hide' ) {
279 $( 'div.animated_wrapper', option ).slideUp( animationSpeed );
280 $( 'td, th', option ).addClass( 'hide-animate' );
281 } else if ( action === 'hide_immediately' ) {
282 $( 'div.animated_wrapper', option ).hide();
283 $( 'td, th', option ).addClass( 'hide-no-animate' );
284 }
285 }
286
287 // Helper function to grab a querystring param value by name
288 function getParameterByName( needle, haystack ) {
289 needle = needle.replace( /[\[]/, '\\\[').replace(/[\]]/, '\\\]' ); // eslint-disable-line no-useless-escape
290 var regex = new RegExp( '[\\?&]' + needle + '=([^&#]*)' );
291 var results = regex.exec( haystack );
292 if ( results === null ) {
293 return '';
294 } else {
295 return decodeURIComponent( results[1].replace( /\+/g, ' ' ) );
296 }
297 }
298
299 // Helper function to return a short date (e.g., Jul 2013) for today's date
300 function getShortDate( date ) {
301 date = typeof date !== 'undefined' ? date : new Date();
302 var month = '';
303 switch ( date.getMonth() ) {
304 case 0: month = 'Jan'; break;
305 case 1: month = 'Feb'; break;
306 case 2: month = 'Mar'; break;
307 case 3: month = 'Apr'; break;
308 case 4: month = 'May'; break;
309 case 5: month = 'Jun'; break;
310 case 6: month = 'Jul'; break;
311 case 7: month = 'Aug'; break;
312 case 8: month = 'Sep'; break;
313 case 9: month = 'Oct'; break;
314 case 10: month = 'Nov'; break;
315 case 11: month = 'Dec'; break;
316 }
317 return month + ' ' + date.getFullYear();
318 }
319
320 // Helper function to grab a querystring value
321 function getQuerystringValuesByKey( key ) {
322 var re = new RegExp( '(?:\\?|&)' + key + '=(.*?)(?=&|$)', 'gi' );
323 var matchingValues = [];
324 var match;
325 while ( ( match = re.exec( document.location.search ) ) !== null ) {
326 matchingValues.push( match[1] );
327 }
328 return matchingValues;
329 }
330
331 // Helper function to check if an email address is valid. If allowWildcardEmail
332 // is true, then any string starting with an @ is valid.
333 function validEmail( email, allowWildcardEmail ) {
334 allowWildcardEmail = typeof allowWildcardEmail !== 'undefined' ? allowWildcardEmail : false;
335 var re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
336 return email.length > 0 && ( re.test( email ) || email.startsWith( '@' ) );
337 }
338
339 // Helper function to set or update a querystring value.
340 function updateQueryStringParameter( uri, key, value ) {
341 // Remove the hash before operating on the URI.
342 var i = uri.indexOf( '#' );
343 var hash = i === -1 ? '' : uri.substr( i );
344 uri = i === -1 ? uri : uri.substr( 0, i );
345
346 var re = new RegExp( '([?&])' + key + '=.*?(&|$)', 'i' );
347 var separator = uri.indexOf( '?' ) !== -1 ? '&' : '?';
348
349 if ( ! value ) {
350 // Remove key-value pair if empty.
351 uri = uri.replace( new RegExp( '([?&]?)' + key + '=[^&]*', 'i' ), '' );
352 if ( uri.slice( -1 ) === '?' ) {
353 uri = uri.slice( 0, -1 );
354 }
355 // Replace first occurrence of & by ? if no ? is present.
356 if ( uri.indexOf( '?' ) === -1 ) {
357 uri = uri.replace( /&/, '?' );
358 }
359 } else if ( uri.match( re ) ) {
360 uri = uri.replace( re, '$1' + key + '=' + value + '$2' );
361 } else {
362 uri = uri + separator + key + '=' + value;
363 }
364 return uri + hash;
365 }
366
367
368 /**
369 * Wire up actions when document has loaded.
370 */
371
372
373 $( document ).ready( function() {
374 // Grab references to form elements that we will show/hide on page load
375 /* eslint-disable camelcase */
376 var auth_settings_access_role_receive_pending_emails = $( '#auth_settings_access_role_receive_pending_emails' ).closest( 'tr' );
377 var auth_settings_access_pending_redirect_to_message = $( '#wp-auth_settings_access_pending_redirect_to_message-wrap' ).closest( 'tr' );
378 var auth_settings_access_blocked_redirect_to_message = $( '#wp-auth_settings_access_blocked_redirect_to_message-wrap' ).closest( 'tr' );
379 var auth_settings_access_should_email_approved_users = $( '#auth_settings_access_should_email_approved_users' ).closest( 'tr' );
380 var auth_settings_access_email_approved_users_subject = $( '#auth_settings_access_email_approved_users_subject' ).closest( 'tr' );
381 var auth_settings_access_email_approved_users_body = $( '#wp-auth_settings_access_email_approved_users_body-wrap' ).closest( 'tr' );
382 var auth_settings_access_public_pages = $( '#auth_settings_access_public_pages' ).closest( 'tr' );
383 var auth_settings_access_redirect_to_login = $( '#radio_auth_settings_access_redirect_to_login' ).closest( 'tr' );
384 var auth_settings_access_public_warning = $( '#radio_auth_settings_access_public_warning' ).closest( 'tr' );
385 var auth_settings_access_redirect_to_message = $( '#wp-auth_settings_access_redirect_to_message-wrap' ).closest( 'tr' );
386 var auth_settings_external_google_clientid = $( '#auth_settings_google_clientid' ).closest( 'tr' );
387 var auth_settings_external_google_clientsecret = $( '#auth_settings_google_clientsecret' ).closest( 'tr' );
388 var auth_settings_external_google_hosteddomain = $( '#auth_settings_google_hosteddomain' ).closest( 'tr' );
389 var auth_settings_external_cas_custom_label = $( '#auth_settings_cas_custom_label' ).closest( 'tr' );
390 var auth_settings_external_cas_host = $( '#auth_settings_cas_host' ).closest( 'tr' );
391 var auth_settings_external_cas_port = $( '#auth_settings_cas_port' ).closest( 'tr' );
392 var auth_settings_external_cas_path = $( '#auth_settings_cas_path' ).closest( 'tr' );
393 var auth_settings_external_cas_version = $( '#auth_settings_cas_version' ).closest( 'tr' );
394 var auth_settings_external_cas_attr_email = $( '#auth_settings_cas_attr_email' ).closest( 'tr' );
395 var auth_settings_external_cas_attr_first_name = $( '#auth_settings_cas_attr_first_name' ).closest( 'tr' );
396 var auth_settings_external_cas_attr_last_name = $( '#auth_settings_cas_attr_last_name' ).closest( 'tr' );
397 var auth_settings_external_cas_attr_update_on_login = $( '#auth_settings_cas_attr_update_on_login' ).closest( 'tr' );
398 var auth_settings_external_cas_auto_login = $( '#auth_settings_cas_auto_login' ).closest( 'tr' );
399 var auth_settings_external_cas_link_on_username = $( '#auth_settings_cas_link_on_username' ).closest( 'tr' );
400 var auth_settings_external_ldap_host = $( '#auth_settings_ldap_host' ).closest( 'tr' );
401 var auth_settings_external_ldap_port = $( '#auth_settings_ldap_port' ).closest( 'tr' );
402 var auth_settings_external_ldap_search_base = $( '#auth_settings_ldap_search_base' ).closest( 'tr' );
403 var auth_settings_external_ldap_uid = $( '#auth_settings_ldap_uid' ).closest( 'tr' );
404 var auth_settings_external_ldap_attr_email = $( '#auth_settings_ldap_attr_email' ).closest( 'tr' );
405 var auth_settings_external_ldap_user = $( '#auth_settings_ldap_user' ).closest( 'tr' );
406 var auth_settings_external_ldap_password = $( '#auth_settings_ldap_password' ).closest( 'tr' );
407 var auth_settings_external_ldap_tls = $( '#auth_settings_ldap_tls' ).closest( 'tr' );
408 var auth_settings_external_ldap_lostpassword_url = $( '#auth_settings_ldap_lostpassword_url' ).closest( 'tr' );
409 var auth_settings_external_ldap_attr_first_name = $( '#auth_settings_ldap_attr_first_name' ).closest( 'tr' );
410 var auth_settings_external_ldap_attr_last_name = $( '#auth_settings_ldap_attr_last_name' ).closest( 'tr' );
411 var auth_settings_external_ldap_attr_update_on_login = $( '#auth_settings_ldap_attr_update_on_login' ).closest( 'tr' );
412 /* eslint-enable */
413
414 // Wrap the th and td in the rows above so we can animate their heights (can't animate tr heights with jquery)
415 $( 'th, td', auth_settings_access_role_receive_pending_emails ).wrapInner( '<div class="animated_wrapper" />' );
416 $( 'th, td', auth_settings_access_pending_redirect_to_message ).wrapInner( '<div class="animated_wrapper" />' );
417 $( 'th, td', auth_settings_access_blocked_redirect_to_message ).wrapInner( '<div class="animated_wrapper" />' );
418 $( 'th, td', auth_settings_access_should_email_approved_users ).wrapInner( '<div class="animated_wrapper" />' );
419 $( 'th, td', auth_settings_access_email_approved_users_subject ).wrapInner( '<div class="animated_wrapper" />' );
420 $( 'th, td', auth_settings_access_email_approved_users_body ).wrapInner( '<div class="animated_wrapper" />' );
421 $( 'th, td', auth_settings_access_public_pages ).wrapInner( '<div class="animated_wrapper" />' );
422 $( 'th, td', auth_settings_access_redirect_to_login ).wrapInner( '<div class="animated_wrapper" />' );
423 $( 'th, td', auth_settings_access_public_warning ).wrapInner( '<div class="animated_wrapper" />' );
424 $( 'th, td', auth_settings_access_redirect_to_message ).wrapInner( '<div class="animated_wrapper" />' );
425 $( 'th, td', auth_settings_external_google_clientid ).wrapInner( '<div class="animated_wrapper" />' );
426 $( 'th, td', auth_settings_external_google_clientsecret ).wrapInner( '<div class="animated_wrapper" />' );
427 $( 'th, td', auth_settings_external_google_hosteddomain ).wrapInner( '<div class="animated_wrapper" />' );
428 $( 'th, td', auth_settings_external_cas_custom_label ).wrapInner( '<div class="animated_wrapper" />' );
429 $( 'th, td', auth_settings_external_cas_host ).wrapInner( '<div class="animated_wrapper" />' );
430 $( 'th, td', auth_settings_external_cas_port ).wrapInner( '<div class="animated_wrapper" />' );
431 $( 'th, td', auth_settings_external_cas_path ).wrapInner( '<div class="animated_wrapper" />' );
432 $( 'th, td', auth_settings_external_cas_version ).wrapInner( '<div class="animated_wrapper" />' );
433 $( 'th, td', auth_settings_external_cas_attr_email ).wrapInner( '<div class="animated_wrapper" />' );
434 $( 'th, td', auth_settings_external_cas_attr_first_name ).wrapInner( '<div class="animated_wrapper" />' );
435 $( 'th, td', auth_settings_external_cas_attr_last_name ).wrapInner( '<div class="animated_wrapper" />' );
436 $( 'th, td', auth_settings_external_cas_attr_update_on_login ).wrapInner( '<div class="animated_wrapper" />' );
437 $( 'th, td', auth_settings_external_cas_auto_login ).wrapInner( '<div class="animated_wrapper" />' );
438 $( 'th, td', auth_settings_external_cas_link_on_username ).wrapInner( '<div class="animated_wrapper" />' );
439 $( 'th, td', auth_settings_external_ldap_host ).wrapInner( '<div class="animated_wrapper" />' );
440 $( 'th, td', auth_settings_external_ldap_port ).wrapInner( '<div class="animated_wrapper" />' );
441 $( 'th, td', auth_settings_external_ldap_search_base ).wrapInner( '<div class="animated_wrapper" />' );
442 $( 'th, td', auth_settings_external_ldap_uid ).wrapInner( '<div class="animated_wrapper" />' );
443 $( 'th, td', auth_settings_external_ldap_attr_email ).wrapInner( '<div class="animated_wrapper" />' );
444 $( 'th, td', auth_settings_external_ldap_user ).wrapInner( '<div class="animated_wrapper" />' );
445 $( 'th, td', auth_settings_external_ldap_password ).wrapInner( '<div class="animated_wrapper" />' );
446 $( 'th, td', auth_settings_external_ldap_tls ).wrapInner( '<div class="animated_wrapper" />' );
447 $( 'th, td', auth_settings_external_ldap_lostpassword_url ).wrapInner( '<div class="animated_wrapper" />' );
448 $( 'th, td', auth_settings_external_ldap_attr_first_name ).wrapInner( '<div class="animated_wrapper" />' );
449 $( 'th, td', auth_settings_external_ldap_attr_last_name ).wrapInner( '<div class="animated_wrapper" />' );
450 $( 'th, td', auth_settings_external_ldap_attr_update_on_login ).wrapInner( '<div class="animated_wrapper" />' );
451
452 // If we're viewing the dashboard widget, reset a couple of the relevant
453 // option variables (since they aren't nested in table rows).
454 if ( $( '#auth_dashboard_widget' ).length ) {
455 // Remove the helper link, since there are no tabs on the dashboard widget
456 $( '#dashboard_link_approved_users' ).contents().unwrap();
457 }
458
459 // Hide settings unless "Only approved users" is checked
460 if ( ! $( '#radio_auth_settings_access_who_can_login_approved_users' ).is( ':checked' ) ) {
461 animateOption( 'hide_immediately', auth_settings_access_role_receive_pending_emails );
462 animateOption( 'hide_immediately', auth_settings_access_pending_redirect_to_message );
463 animateOption( 'hide_immediately', auth_settings_access_blocked_redirect_to_message );
464 animateOption( 'hide_immediately', auth_settings_access_should_email_approved_users );
465 }
466
467 // Hide Welcome email body/subject options if "Send welcome email" is off.
468 if ( ! $( '#auth_settings_access_should_email_approved_users' ).is( ':checked' ) ) {
469 animateOption( 'hide_immediately', auth_settings_access_email_approved_users_subject );
470 animateOption( 'hide_immediately', auth_settings_access_email_approved_users_body );
471 }
472
473 // On load: Show/hide public access options if everyone can see site
474 if ( ! $( '#radio_auth_settings_access_who_can_view_logged_in_users' ).is( ':checked' ) ) {
475 animateOption( 'hide_immediately', auth_settings_access_public_pages );
476 animateOption( 'hide_immediately', auth_settings_access_redirect_to_login );
477 animateOption( 'hide_immediately', auth_settings_access_public_warning );
478 animateOption( 'hide_immediately', auth_settings_access_redirect_to_message );
479 }
480
481 // Hide Google options if unchecked
482 if ( ! $( '#auth_settings_google' ).is( ':checked' ) ) {
483 animateOption( 'hide_immediately', auth_settings_external_google_clientid );
484 animateOption( 'hide_immediately', auth_settings_external_google_clientsecret );
485 animateOption( 'hide_immediately', auth_settings_external_google_hosteddomain );
486 }
487
488 // Hide CAS options if unchecked
489 if ( ! $( '#auth_settings_cas' ).is( ':checked' ) ) {
490 animateOption( 'hide_immediately', auth_settings_external_cas_custom_label );
491 animateOption( 'hide_immediately', auth_settings_external_cas_host );
492 animateOption( 'hide_immediately', auth_settings_external_cas_port );
493 animateOption( 'hide_immediately', auth_settings_external_cas_path );
494 animateOption( 'hide_immediately', auth_settings_external_cas_version );
495 animateOption( 'hide_immediately', auth_settings_external_cas_attr_email );
496 animateOption( 'hide_immediately', auth_settings_external_cas_attr_first_name );
497 animateOption( 'hide_immediately', auth_settings_external_cas_attr_last_name );
498 animateOption( 'hide_immediately', auth_settings_external_cas_attr_update_on_login );
499 animateOption( 'hide_immediately', auth_settings_external_cas_auto_login );
500 animateOption( 'hide_immediately', auth_settings_external_cas_link_on_username );
501 }
502
503 // Hide LDAP options if unchecked
504 if ( ! $( '#auth_settings_ldap' ).is( ':checked' ) ) {
505 animateOption( 'hide_immediately', auth_settings_external_ldap_host );
506 animateOption( 'hide_immediately', auth_settings_external_ldap_port );
507 animateOption( 'hide_immediately', auth_settings_external_ldap_search_base );
508 animateOption( 'hide_immediately', auth_settings_external_ldap_uid );
509 animateOption( 'hide_immediately', auth_settings_external_ldap_attr_email );
510 animateOption( 'hide_immediately', auth_settings_external_ldap_user );
511 animateOption( 'hide_immediately', auth_settings_external_ldap_password );
512 animateOption( 'hide_immediately', auth_settings_external_ldap_tls );
513 animateOption( 'hide_immediately', auth_settings_external_ldap_lostpassword_url );
514 animateOption( 'hide_immediately', auth_settings_external_ldap_attr_first_name );
515 animateOption( 'hide_immediately', auth_settings_external_ldap_attr_last_name );
516 animateOption( 'hide_immediately', auth_settings_external_ldap_attr_update_on_login );
517 }
518
519 // Event handler: Hide "Handle unauthorized visitors" option if access is granted to "Everyone"
520 $( 'input[name="auth_settings[access_who_can_login]"]' ).change( function() {
521 // Hide settings unless "Only approved users" is checked
522 var action = $( '#radio_auth_settings_access_who_can_login_approved_users' ).is( ':checked' ) ? 'show' : 'hide';
523 animateOption( action, auth_settings_access_role_receive_pending_emails );
524 animateOption( action, auth_settings_access_pending_redirect_to_message );
525 animateOption( action, auth_settings_access_blocked_redirect_to_message );
526 animateOption( action, auth_settings_access_should_email_approved_users );
527 action = action === 'show' && $( '#auth_settings_access_should_email_approved_users' ).is( ':checked' ) ? 'show' : 'hide_immediately';
528 animateOption( action, auth_settings_access_email_approved_users_subject );
529 animateOption( action, auth_settings_access_email_approved_users_body );
530 });
531
532 // Event handler: Hide Welcome email body/subject options if "Send welcome email" is off.
533 $( 'input[name="auth_settings[access_should_email_approved_users]"]' ).change( function() {
534 var action = $( this ).is( ':checked' ) ? 'show' : 'hide';
535 animateOption( action, auth_settings_access_email_approved_users_subject );
536 animateOption( action, auth_settings_access_email_approved_users_body );
537 });
538
539 // Event handler: Hide "Handle unauthorized visitors" option if access is granted to "Everyone"
540 $( 'input[name="auth_settings[access_who_can_view]"]' ).change( function() {
541 var action = $( '#radio_auth_settings_access_who_can_view_everyone' ).is( ':checked' ) ? 'hide' : 'show';
542 animateOption( action, auth_settings_access_redirect_to_login );
543 animateOption( action, auth_settings_access_redirect_to_message );
544 animateOption( action, auth_settings_access_public_pages );
545 animateOption( action, auth_settings_access_public_warning );
546 });
547
548 // Event handler: Show/hide Google options based on checkbox
549 $( 'input[name="auth_settings[google]"]' ).change( function() {
550 var action = $( this ).is( ':checked' ) ? 'show' : 'hide';
551 animateOption( action, auth_settings_external_google_clientid );
552 animateOption( action, auth_settings_external_google_clientsecret );
553 animateOption( action, auth_settings_external_google_hosteddomain );
554 });
555
556 // Event handler: Show/hide CAS options based on checkbox
557 $( 'input[name="auth_settings[cas]"]' ).change( function() {
558 var action = $( this ).is( ':checked' ) ? 'show' : 'hide';
559 animateOption( action, auth_settings_external_cas_custom_label );
560 animateOption( action, auth_settings_external_cas_host );
561 animateOption( action, auth_settings_external_cas_port );
562 animateOption( action, auth_settings_external_cas_path );
563 animateOption( action, auth_settings_external_cas_version );
564 animateOption( action, auth_settings_external_cas_attr_email );
565 animateOption( action, auth_settings_external_cas_attr_first_name );
566 animateOption( action, auth_settings_external_cas_attr_last_name );
567 animateOption( action, auth_settings_external_cas_attr_update_on_login );
568 animateOption( action, auth_settings_external_cas_auto_login );
569 animateOption( action, auth_settings_external_cas_link_on_username );
570 });
571
572 // Event handler: Show/hide LDAP options based on checkbox
573 $( 'input[name="auth_settings[ldap]"]' ).change( function() {
574 var action = $( this ).is( ':checked' ) ? 'show' : 'hide';
575 animateOption( action, auth_settings_external_ldap_host );
576 animateOption( action, auth_settings_external_ldap_port );
577 animateOption( action, auth_settings_external_ldap_search_base );
578 animateOption( action, auth_settings_external_ldap_uid );
579 animateOption( action, auth_settings_external_ldap_attr_email );
580 animateOption( action, auth_settings_external_ldap_user );
581 animateOption( action, auth_settings_external_ldap_password );
582 animateOption( action, auth_settings_external_ldap_tls );
583 animateOption( action, auth_settings_external_ldap_lostpassword_url );
584 animateOption( action, auth_settings_external_ldap_attr_first_name );
585 animateOption( action, auth_settings_external_ldap_attr_last_name );
586 animateOption( action, auth_settings_external_ldap_attr_update_on_login );
587 });
588
589 // Show save button if usermeta field is modified.
590 $( 'form input.auth-usermeta' ).on( 'keyup', function( event ) {
591 // Don't do anything if tab or arrow keys were pressed.
592 if ( event.which === 9 || event.which === 37 || event.which === 38 || event.which === 39 || event.which === 40 ) {
593 return;
594 }
595 $( this ).siblings( '.button' ).css( 'display', 'inline-block' );
596 });
597
598 // List management function: pressing enter in the new approved or new
599 // blocked user (email or role field) adds the user to the list.
600 $( '#new_approved_user_email, #new_approved_user_role, #new_blocked_user_email' ).on( 'keyup', function( event ) {
601 // For textareas, make Enter add the user; for inputs, make enter add the user.
602 if ( $( this ).is( 'textarea' ) ) {
603 // Enter key adds a newline; Enter key with Ctrl, Alt, Shift, or Meta adds the user.
604 if ( event.which === 13 && ( event.ctrlKey || event.altKey || event.metaKey ) ) {
605 $( this ).parent().find( 'a.button-add-user' ).trigger( 'click' );
606 event.preventDefault();
607 }
608 } else if ( event.which === 13 ) { // Enter key on input[type="text"]
609 $( this ).parent().find( 'a.button-add-user' ).trigger( 'click' );
610 event.preventDefault();
611 }
612 });
613
614 // Don't submit form (i.e., save options) when hitting enter in any user list field.
615 $( 'input.auth-email, select.auth-role, input.auth-date-added, input.auth-usermeta' ).on( 'keydown', function( event ) {
616 if ( event.which === 13 ) { // Enter key
617 event.preventDefault();
618 return false;
619 }
620 });
621
622 // Enable the user-friendly multiselect form element on the options page.
623 $( '#auth_settings_access_public_pages' ).multiSelect({
624 selectableOptgroup: true,
625 selectableHeader: '<div class="custom-header">' + authL10n.private_pages + '</div>',
626 selectionHeader: '<div class="custom-header">' + authL10n.public_pages + '</div>',
627 });
628
629 // Switch to the first tab (or the tab indicated in sessionStorage, or the querystring).
630 var tab = '';
631 if ( getQuerystringValuesByKey( 'tab' ).length > 0 ) {
632 tab = getQuerystringValuesByKey( 'tab' )[0];
633 } else if ( sessionStorage.getItem( 'tab' ) ) {
634 tab = sessionStorage.getItem( 'tab' );
635 }
636 if ( $.inArray( tab, [ 'access_lists', 'access_login', 'access_public', 'external', 'advanced' ] ) < 0 ) {
637 tab = 'access_lists';
638 }
639 window.chooseTab( tab, animationSpeed );
640
641 // Hide/show multisite settings based on override checkbox.
642 $( 'input[name="auth_settings[multisite_override]"]' ).change( function() {
643 hideMultisiteSettingsIfDisabled();
644 });
645 hideMultisiteSettingsIfDisabled();
646
647 // Wire up pager events on Approved User list (first/last/next/previous
648 // buttons, go to page text input, and search.
649 $( '#current-page-selector, #user-search-input' ).on( 'keydown', function( event ) {
650 if ( event.which === 13 ) { // Enter key
651 var searchTerm = $( '#user-search-input' ).val();
652 var currentPage = parseInt( $( this ).val(), 10 ) || 1;
653 var totalPages = parseInt( $( '.total-pages' ).first().text().replace( /[^0-9]/g, '' ), 10 ) || 1;
654
655 // Make sure current page is between 1 and max pages.
656 if ( currentPage < 1 ) {
657 currentPage = 1;
658 } else if ( currentPage > totalPages ) {
659 currentPage = totalPages;
660 }
661
662 // Update user list with users on next page.
663 refreshApprovedUserList( currentPage, searchTerm );
664
665 // Prevent default behavior.
666 event.preventDefault();
667 return false;
668 }
669 });
670
671 $( '.tablenav' ).on( 'click', '.pagination-links a, #search-submit', function( event ) {
672 var searchTerm = $( '#user-search-input' ).val();
673 var currentPage = parseInt( getParameterByName( 'paged', $( this ).attr( 'href' ) ), 10 ) || 1;
674 var totalPages = parseInt( $( '.total-pages' ).first().text().replace( /[^0-9]/g, '' ), 10 ) || 1;
675 if ( currentPage > totalPages ) {
676 currentPage = totalPages;
677 }
678
679 // Update user list with users on next page.
680 refreshApprovedUserList( currentPage, searchTerm );
681
682 // Remove focus from clicked element.
683 $( this ).blur();
684
685 // Prevent default behavior.
686 event.preventDefault();
687 return false;
688 });
689
690 // Enable growable textarea for new user field.
691 $( 'textarea#new_approved_user_email' ).autogrow();
692
693 // Enable growable textarea for config fields.
694 $( 'textarea#auth_settings_ldap_host' ).autogrow();
695 $( 'textarea#auth_settings_ldap_search_base' ).autogrow();
696 $( 'textarea#auth_settings_google_hosteddomain' ).autogrow();
697
698 });
699
700
701 /**
702 * Globals.
703 */
704
705
706 // Switch between option tabs.
707 window.chooseTab = function( listName, delay ) {
708 // default delay is 0
709 delay = 'undefined' !== typeof delay ? delay : 0;
710
711 // default to the access list tab
712 listName = 'undefined' !== typeof listName ? listName : 'access_lists';
713
714 // Hide all tab content, then show selected tab content
715 $( 'div.section_info, div.section_info + table' ).hide();
716 $( '#section_info_' + listName + ', #section_info_' + listName + ' + table' ).show();
717
718 // Set active tab
719 $( '.nav-tab-wrapper a' ).removeClass( 'nav-tab-active' );
720 $( 'a.nav-tab-' + listName ).addClass( 'nav-tab-active' );
721
722 // Hide site options if they are overridden by a multisite setting.
723 setTimeout( window.hideMultisiteOverriddenOptions, delay );
724
725 // Hide Save Changes button if we're on the access lists page (changing
726 // access lists saves automatically via AJAX).
727 $( 'body:not(.network-admin) #submit' ).toggle( 'access_lists' !== listName );
728
729 // Save user's active tab to sessionStorage (so we can restore it on reload).
730 // Note: session storage persists until the browser tab is closed.
731 sessionStorage.setItem( 'tab', listName );
732
733 // Check whether to fade logo.
734 fadeLogo();
735 };
736
737 // Hide (with overlay) site options if overridden by a multisite option.
738 window.hideMultisiteOverriddenOptions = function() {
739 $( '.auth_multisite_override_overlay' ).each( function() {
740 // Option to hide is stored in the overlay's id with 'overlay-hide-' prefix.
741 var optionContainerToHide = $( this ).closest( 'tr' );
742 if ( optionContainerToHide.length > 0 ) {
743 $( this ).css({
744 'background-color': '#f1f1f1',
745 'z-index': 1,
746 opacity: 0.8,
747 position: 'absolute',
748 top: optionContainerToHide.position().top,
749 left: optionContainerToHide.position().left,
750 width: '100%',
751 height: optionContainerToHide.height(),
752 });
753 $( this ).show();
754 }
755 });
756 };
757
758 // Update user's usermeta field.
759 // @calls php wp_ajax_update_auth_usermeta.
760 window.authUpdateUsermeta = function( caller ) {
761 var $caller = $( caller ),
762 $usermeta = $caller.parent().children( '.auth-usermeta' ),
763 email = $caller.siblings( '.auth-email' ).val(),
764 usermeta = $usermeta.val(),
765 nonce = $( '#nonce_save_auth_settings' ).val();
766
767 // Remove reference to caller if it's the usermeta field itself (not a button triggering the save).
768 if ( $caller.hasClass( 'auth-usermeta' ) ) {
769 $caller = $();
770 }
771
772 // Disable inputs, show spinner.
773 $caller.attr( 'disabled', 'disabled' );
774 $usermeta.attr( 'disabled', 'disabled' );
775 var $row = $usermeta.closest( 'li' );
776 var $spinner = $( '<span class="spinner is-active"></span>' ).css({
777 position: 'absolute',
778 top: $row.position().top,
779 left: $row.position().left + $row.width(),
780 });
781 $usermeta.after( $spinner );
782 $( 'html' ).addClass( 'busy' );
783
784 // Call ajax save function.
785 $.post( ajaxurl, {
786 action: 'update_auth_usermeta',
787 email: email,
788 usermeta: usermeta,
789 nonce: nonce,
790 }, function( response ) {
791 var succeeded = response === 'success';
792 var spinnerText = succeeded ? authL10n.saved + '.' : '<span class="attention">' + authL10n.failed + '.</span>';
793 var spinnerWait = succeeded ? 500 : 2000;
794
795 // Enable inputs, remove spinner.
796 $caller.removeAttr( 'disabled' );
797 $usermeta.removeAttr( 'disabled' );
798 $caller.css( 'display', 'none' );
799 $( 'form .spinner:not(:has(.spinner-text))' ).animate( { width: '60px' }, 'fast' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
800 $( this ).remove();
801 });
802 $( 'html' ).removeClass( 'busy' );
803
804 }).fail( function() {
805 var succeeded = false;
806 var spinnerText = succeeded ? authL10n.saved + '.' : '<span class="attention">' + authL10n.failed + '.</span>';
807 var spinnerWait = succeeded ? 500 : 2000;
808
809 // Enable inputs, remove spinner.
810 $caller.removeAttr( 'disabled' );
811 $usermeta.removeAttr( 'disabled' );
812 $caller.css( 'display', 'none' );
813 $( 'form .spinner:not(:has(.spinner-text))' ).animate( { width: '60px' }, 'fast' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
814 $( this ).remove();
815 });
816 $( 'html' ).removeClass( 'busy' );
817
818 });
819 };
820
821 // Update user's role.
822 window.authChangeRole = function( caller, isMultisite ) {
823 // Set default for multisite flag (run different save routine if multisite)
824 isMultisite = typeof isMultisite !== 'undefined' ? isMultisite : false;
825
826 var email = $( caller ).parent().find( '.auth-email' );
827 var role = $( caller ).parent().find( '.auth-role' );
828 var dateAdded = $( caller ).parent().find( '.auth-date-added' );
829
830 var user = {
831 email: email.val(),
832 role: role.val(),
833 date_added: dateAdded.val(), // eslint-disable-line camelcase
834 edit_action: 'change_role', // eslint-disable-line camelcase
835 multisite_user: isMultisite, // eslint-disable-line camelcase
836 };
837
838 // Update the options in the database with this change.
839 updateAuthUser( caller, 'access_users_approved', user );
840
841 return true;
842 };
843
844 // Update user's role (multisite options page).
845 window.authMultisiteChangeRole = function( caller ) {
846 var isMultisite = true;
847 window.authChangeRole( caller, isMultisite );
848 };
849
850 // Add user to list (list = blocked or approved).
851 window.authAddUser = function( caller, list, shouldCreateLocalAccount, isMultisite ) {
852 // Skip email address validation if adding from pending list (not user-editable).
853 var skipValidation = $( caller ).parent().parent().attr( 'id' ) === 'list_auth_settings_access_users_pending';
854
855 // Skip email address validation if we're banning an existing user (since they're already in a list).
856 var blockingNewUser = $( caller ).attr( 'id' ).indexOf( 'block_user_new' ) > -1;
857 skipValidation = skipValidation || ( $( caller ).attr( 'id' ).indexOf( 'block_user' ) > -1 && ! blockingNewUser );
858
859 // Set default for multisite flag (run different save routine if multisite)
860 isMultisite = 'undefined' !== typeof isMultisite ? isMultisite : false;
861
862 // Default to the approved list.
863 list = 'undefined' !== typeof list ? list : 'approved';
864
865 // Default to not creating a local account.
866 shouldCreateLocalAccount = 'undefined' !== typeof shouldCreateLocalAccount ? shouldCreateLocalAccount : false;
867
868 var email = $( caller ).parent().find( '.auth-email' );
869 var role = $( caller ).parent().find( '.auth-role' );
870 var dateAdded = $( caller ).parent().find( '.auth-date-added' );
871
872 // Helper variable for disabling buttons while processing. This will be
873 // set differently if our clicked button is nested in a div (below).
874 var buttons = caller;
875
876 // Button (caller) might be nested in a div, so we need to walk up one more level
877 if ( 0 === email.length || 0 === role.length ) {
878 email = $( caller ).parent().parent().find( '.auth-email' );
879 role = $( caller ).parent().parent().find( '.auth-role' );
880 dateAdded = $( caller ).parent().parent().find( '.auth-date-added' );
881 buttons = $( caller ).parent().children();
882 }
883
884 // Support a single email address, or multiple (separated by newlines, commas, semicolons, or spaces).
885 var emails = $.trim( email.val() ).replace( /mailto:/g, '' ).split( /[\s,;]+/ );
886
887 // Remove any invalid email addresses.
888 if ( ! skipValidation ) {
889 // Check if the email(s) being added is well-formed.
890 emails = emails.filter( function( emailToValidate ) {
891 return validEmail( emailToValidate, blockingNewUser );
892 });
893 // Remove any duplicates in the list of emails to add.
894 emails = removeDuplicatesFromArrayOfStrings( emails );
895 }
896
897 // Shake and quit if no valid email addresses exist.
898 if ( 1 > emails.length ) {
899 $( '#new_' + list + '_user_email' ).parent().effect( 'shake', shakeSpeed );
900 return false;
901 }
902
903 $( buttons ).attr( 'disabled', 'disabled' );
904
905 var users = [];
906 for ( var i = 0; i < emails.length; i++ ) {
907 var user = {
908 email: emails[i],
909 role: role.val(),
910 date_added: dateAdded.val(), // eslint-disable-line camelcase
911 edit_action: 'add', // eslint-disable-line camelcase
912 local_user: shouldCreateLocalAccount, // eslint-disable-line camelcase
913 multisite_user: isMultisite, // eslint-disable-line camelcase
914 };
915 users.push( user );
916
917 // Get next highest user ID.
918 var nextId = 1 + Math.max.apply(
919 null,
920 // eslint-disable-next-line no-unused-vars
921 $( '#list_auth_settings_access_users_' + list + ' li .auth-email' ).map( function( el ) { // jshint ignore:line
922 return parseInt( this.id.replace( 'auth_multisite_settings_access_users_' + list + '_', '' ).replace( 'auth_settings_access_users_' + list + '_', '' ), 10 );
923 })
924 );
925
926 // Add the new item.
927 var authJsPrefix = isMultisite ? 'authMultisite' : 'auth';
928 var banButton = ! isMultisite ? '<a class="button' + ( list === 'approved' ? '' : ' invisible' ) + '" id="block_user_' + nextId + '" onclick="' + authJsPrefix + 'AddUser( this, \'blocked\', false ); ' + authJsPrefix + 'IgnoreUser( this, \'approved\' );" title="' + authL10n.block_ban_user + '"><span class="glyphicon glyphicon-ban-circle"></span></a>' : '';
929 var ignoreButton = '<a class="button" id="ignore_user_' + nextId + '" onclick="' + authJsPrefix + 'IgnoreUser( this, \'' + list + '\' );" title="' + authL10n.remove_user + '"><span class="glyphicon glyphicon-remove"></span></a>';
930 var localIcon = '&nbsp;<a title="' + authL10n.local_wordpress_user + '" class="auth-local-user' + ( shouldCreateLocalAccount ? '' : ' invisible' ) + '"><span class="glyphicon glyphicon-user"></span></a>';
931 var multisiteIcon = '&nbsp;<a title="WordPress Multisite user" class="auth-multisite-user'+ ( isMultisite ? '' : ' invisible' ) + '"><span class="glyphicon glyphicon-globe"></span></a>';
932 $( ' \
933 <li id="new_user_' + nextId + '" class="new-user" style="display: none;"> \
934 <input type="text" id="auth_settings_access_users_' + list + '_' + nextId + '" name="auth_settings[access_users_' + list + '][' + nextId + '][email]" value="' + user.email + '" readonly="true" class="auth-email" /> \
935 <select name="auth_settings[access_users_' + list + '][' + nextId + '][role]" class="auth-role" onchange="' + authJsPrefix + 'ChangeRole( this );"> \
936 </select> \
937 <input type="text" name="auth_settings[access_users_' + list + '][' + nextId + '][date_added]" value="' + getShortDate() + '" readonly="true" class="auth-date-added" /> \
938 ' + banButton + ignoreButton + localIcon + multisiteIcon + ' \
939 <span class="spinner is-active"></span> \
940 </li> \
941 ' ).appendTo( '#list_auth_settings_access_users_' + list ).slideDown( 250 );
942
943 // Populate the role dropdown in the new element. Because clone() doesn't
944 // save selected state on select elements, set that too.
945 $( 'option', role ).clone().appendTo( '#new_user_' + nextId + ' .auth-role' );
946 $( '#new_user_' + nextId + ' .auth-role' ).val( role.val() );
947 }
948
949 // Remove the 'empty list' item if it exists.
950 $( '#list_auth_settings_access_users_' + list + ' li.auth-empty' ).remove();
951
952 // Update the options in the database with this change.
953 updateAuthUser( buttons, 'access_users_' + list, users );
954
955 // Reset the new user textboxes
956 if ( email.hasClass( 'new' ) ) {
957 email.val( '' ).keydown();
958 }
959
960 // Re-enable the action buttons now that we're done saving.
961 $( buttons ).removeAttr( 'disabled' );
962 return true;
963 };
964
965 // Add user to list (multisite options page).
966 window.authMultisiteAddUser = function( caller, list, shouldCreateLocalAccount ) {
967 var isMultisite = true;
968
969 // Default to the approved list.
970 list = typeof list !== 'undefined' ? list : 'approved';
971
972 // Default to not creating a local account.
973 shouldCreateLocalAccount = typeof shouldCreateLocalAccount !== 'undefined' ? shouldCreateLocalAccount : false;
974
975 // There currently is no multisite blocked list, so do nothing.
976 if ( list === 'blocked' ) {
977 return;
978 }
979
980 window.authAddUser( caller, list, shouldCreateLocalAccount, isMultisite );
981 };
982
983 // Remove user from list.
984 window.authIgnoreUser = function( caller, listName, isMultisite ) {
985 // Set default for multisite flag (run different save routine if multisite)
986 isMultisite = typeof isMultisite !== 'undefined' ? isMultisite : false;
987
988 // Set default list if not provided.
989 listName = typeof listName !== 'undefined' ? listName : 'approved';
990
991 var email = $( caller ).parent().find( '.auth-email' );
992
993 var user = {
994 email: email.val(),
995 role: '',
996 date_added: '', // eslint-disable-line camelcase
997 edit_action: 'remove', // eslint-disable-line camelcase
998 multisite_user: isMultisite, // eslint-disable-line camelcase
999 };
1000
1001 // Show an 'empty list' message if we're deleting the last item
1002 var list = $( caller ).closest( 'ul' );
1003 if ( $( 'li', list ).length <= 1 ) {
1004 $( list ).append( '<li class="auth-empty"><em>' + authL10n.no_users_in + ' ' + listName + '</em></li>' );
1005 }
1006
1007 $( caller ).parent().slideUp( 250, function() {
1008 // Remove the list item.
1009 $( this ).remove();
1010
1011 // Update the options in the database with this change.
1012 updateAuthUser( caller, 'access_users_' + listName, user );
1013 });
1014 };
1015
1016 // Remove user from list (multisite options page).
1017 window.authMultisiteIgnoreUser = function( caller, listName ) {
1018 var isMultisite = true;
1019
1020 // Set default list if not provided.
1021 listName = typeof listName !== 'undefined' ? listName : '';
1022
1023 window.authIgnoreUser( caller, listName, isMultisite );
1024 };
1025
1026 // Save Authorizer Settings (multisite).
1027 // @calls php wp_ajax_save_auth_multisite_settings.
1028 /* eslint-disable camelcase */
1029 window.saveAuthMultisiteSettings = function( caller ) {
1030 // Enable wait cursor.
1031 $( 'html' ).addClass( 'busy' );
1032
1033 // Disable button (prevent duplicate clicks).
1034 $( caller ).attr( 'disabled', 'disabled' );
1035
1036 // Enable spinner by element that triggered this event (caller).
1037 var $spinner = $( '<span class="spinner is-active"></span>' ).css({
1038 position: 'absolute',
1039 top: $( caller ).position().top,
1040 left: $( caller ).position().left + $( caller ).width() + 20,
1041 });
1042 $( caller ).after( $spinner );
1043
1044 // Get form elements to save
1045 var nonce_save_auth_settings = $( '#nonce_save_auth_settings' ).val();
1046
1047 var multisite_override = $( '#auth_settings_multisite_override' ).is( ':checked' ) ? '1' : '';
1048
1049 var access_who_can_login = $( 'form input[name="auth_settings[access_who_can_login]"]:checked' ).val();
1050
1051 var access_who_can_view = $( 'form input[name="auth_settings[access_who_can_view]"]:checked' ).val();
1052
1053 var access_users_approved = {};
1054 $( '#list_auth_settings_access_users_approved li' ).each( function( index ) {
1055 var user = {};
1056 user.email = $( '.auth-email', this ).val();
1057 user.role = $( '.auth-role', this ).val();
1058 user.date_added = $( '.auth-date-added', this ).val();
1059 user.local_user = $( '.auth-local-user', this ).length !== 0;
1060 access_users_approved[index] = user;
1061 });
1062
1063 var access_default_role = $( '#auth_settings_access_default_role' ).val();
1064
1065 var google = $( '#auth_settings_google' ).is( ':checked' ) ? '1' : '';
1066 var google_clientid = $( '#auth_settings_google_clientid' ).val();
1067 var google_clientsecret = $( '#auth_settings_google_clientsecret' ).val();
1068 var google_hosteddomain = $( '#auth_settings_google_hosteddomain' ).val();
1069
1070 var cas = $( '#auth_settings_cas' ).is( ':checked' ) ? '1' : '';
1071 var cas_custom_label = $( '#auth_settings_cas_custom_label' ).val();
1072 var cas_host = $( '#auth_settings_cas_host' ).val();
1073 var cas_port = $( '#auth_settings_cas_port' ).val();
1074 var cas_path = $( '#auth_settings_cas_path' ).val();
1075 var cas_version = $( '#auth_settings_cas_version' ).val();
1076 var cas_attr_email = $( '#auth_settings_cas_attr_email' ).val();
1077 var cas_attr_first_name = $( '#auth_settings_cas_attr_first_name' ).val();
1078 var cas_attr_last_name = $( '#auth_settings_cas_attr_last_name' ).val();
1079 var cas_attr_update_on_login = $( '#auth_settings_cas_attr_update_on_login' ).is( ':checked' ) ? '1' : '';
1080 var cas_auto_login = $( '#auth_settings_cas_auto_login' ).is( ':checked' ) ? '1' : '';
1081 var cas_link_on_username = $( '#auth_settings_cas_link_on_username' ).is( ':checked' ) ? '1' : '';
1082
1083 var ldap = $( '#auth_settings_ldap' ).is( ':checked' ) ? '1' : '';
1084 var ldap_host = $( '#auth_settings_ldap_host' ).val();
1085 var ldap_port = $( '#auth_settings_ldap_port' ).val();
1086 var ldap_search_base = $( '#auth_settings_ldap_search_base' ).val();
1087 var ldap_uid = $( '#auth_settings_ldap_uid' ).val();
1088 var ldap_attr_email = $( '#auth_settings_ldap_attr_email' ).val();
1089 var ldap_user = $( '#auth_settings_ldap_user' ).val();
1090 var ldap_password = $( '#auth_settings_ldap_password' ).val();
1091 var ldap_tls = $( '#auth_settings_ldap_tls' ).is( ':checked' ) ? '1' : '';
1092 var ldap_lostpassword_url = $( '#auth_settings_ldap_lostpassword_url' ).val();
1093 var ldap_attr_first_name = $( '#auth_settings_ldap_attr_first_name' ).val();
1094 var ldap_attr_last_name = $( '#auth_settings_ldap_attr_last_name' ).val();
1095 var ldap_attr_update_on_login = $( '#auth_settings_ldap_attr_update_on_login' ).is( ':checked' ) ? '1' : '';
1096
1097 var advanced_lockouts = {
1098 attempts_1: $( '#auth_settings_advanced_lockouts_attempts_1' ).val(),
1099 duration_1: $( '#auth_settings_advanced_lockouts_duration_1' ).val(),
1100 attempts_2: $( '#auth_settings_advanced_lockouts_attempts_2' ).val(),
1101 duration_2: $( '#auth_settings_advanced_lockouts_duration_2' ).val(),
1102 reset_duration: $( '#auth_settings_advanced_lockouts_reset_duration' ).val(),
1103 };
1104 var advanced_hide_wp_login = $( '#auth_settings_advanced_hide_wp_login' ).is( ':checked' ) ? '1' : '';
1105 var advanced_disable_wp_login = $( '#auth_settings_advanced_disable_wp_login' ).is( ':checked' ) ? '1' : '';
1106 var advanced_widget_enabled = $( '#auth_settings_advanced_widget_enabled' ).is( ':checked' ) ? '1' : '';
1107 var advanced_users_per_page = $( '#auth_settings_advanced_users_per_page' ).val();
1108 var advanced_users_sort_by = $( '#auth_settings_advanced_users_sort_by' ).val();
1109 var advanced_users_sort_order = $( '#auth_settings_advanced_users_sort_order' ).val();
1110
1111 $.post( ajaxurl, {
1112 action: 'save_auth_multisite_settings',
1113 nonce: nonce_save_auth_settings,
1114 multisite_override: multisite_override,
1115 access_who_can_login: access_who_can_login,
1116 access_who_can_view: access_who_can_view,
1117 access_users_approved: access_users_approved,
1118 access_default_role: access_default_role,
1119 google: google,
1120 google_clientid: google_clientid,
1121 google_clientsecret: google_clientsecret,
1122 google_hosteddomain: google_hosteddomain,
1123 cas: cas,
1124 cas_custom_label: cas_custom_label,
1125 cas_host: cas_host,
1126 cas_port: cas_port,
1127 cas_path: cas_path,
1128 cas_version: cas_version,
1129 cas_attr_email: cas_attr_email,
1130 cas_attr_first_name: cas_attr_first_name,
1131 cas_attr_last_name: cas_attr_last_name,
1132 cas_attr_update_on_login: cas_attr_update_on_login,
1133 cas_auto_login: cas_auto_login,
1134 cas_link_on_username: cas_link_on_username,
1135 ldap: ldap,
1136 ldap_host: ldap_host,
1137 ldap_port: ldap_port,
1138 ldap_search_base: ldap_search_base,
1139 ldap_uid: ldap_uid,
1140 ldap_attr_email: ldap_attr_email,
1141 ldap_user: ldap_user,
1142 ldap_password: ldap_password,
1143 ldap_tls: ldap_tls,
1144 ldap_lostpassword_url: ldap_lostpassword_url,
1145 ldap_attr_first_name: ldap_attr_first_name,
1146 ldap_attr_last_name: ldap_attr_last_name,
1147 ldap_attr_update_on_login: ldap_attr_update_on_login,
1148 advanced_lockouts: advanced_lockouts,
1149 advanced_hide_wp_login: advanced_hide_wp_login,
1150 advanced_disable_wp_login: advanced_disable_wp_login,
1151 advanced_users_per_page: advanced_users_per_page,
1152 advanced_users_sort_by: advanced_users_sort_by,
1153 advanced_users_sort_order: advanced_users_sort_order,
1154 advanced_widget_enabled: advanced_widget_enabled,
1155 }, function( response ) {
1156 var succeeded = response === 'success';
1157 var spinnerText = succeeded ? authL10n.saved + '.' : '<span class="attention">' + authL10n.failed + '.</span>';
1158 var spinnerWait = succeeded ? 500 : 2000;
1159 $( 'form .spinner:not(:has(.spinner-text))' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
1160 $( this ).remove();
1161 });
1162 $( caller ).removeAttr( 'disabled' );
1163
1164 // Disable wait cursor.
1165 $( 'html' ).removeClass( 'busy' );
1166 }).fail( function() {
1167 // Fail fires if the server doesn't respond
1168 var succeeded = false;
1169 var spinnerText = succeeded ? authL10n.saved + '.' : '<span class="attention">' + authL10n.failed + '.</span>';
1170 var spinnerWait = succeeded ? 500 : 2000;
1171 $( 'form .spinner:not(:has(.spinner-text))' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
1172 $( this ).remove();
1173 });
1174 $( caller ).removeAttr( 'disabled' );
1175
1176 // Disable wait cursor.
1177 $( 'html' ).removeClass( 'busy' );
1178 });
1179 };
1180 /* eslint-enable camelcase */
1181
1182 // Fade in/out Authorizer logo in bottom right on Settings.
1183 $(document).on( 'scroll', function () {
1184 fadeLogo();
1185 });
1186
1187 function fadeLogo() {
1188 if ( getScrollPercent() < 90 ) {
1189 $( '#wpwrap' ).removeClass( 'not-faded' );
1190 } else {
1191 $( '#wpwrap' ).addClass( 'not-faded' );
1192 }
1193 }
1194
1195 function getScrollPercent() {
1196 var h = document.documentElement,
1197 b = document.body,
1198 st = 'scrollTop',
1199 sh = 'scrollHeight';
1200 return ( h[st] || b[st] ) / ( ( h[sh] || b[sh] ) - h.clientHeight ) * 100;
1201 }
1202
1203 /* ========================================================================
1204 * Portions below from Bootstrap.
1205 * ========================================================================
1206 * Bootstrap: dropdown.js v3.1.1
1207 * http://getbootstrap.com/javascript/#dropdowns
1208 * ========================================================================
1209 * Copyright 2011-2014 Twitter, Inc.
1210 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1211 * ======================================================================== */
1212
1213 // DROPDOWN CLASS DEFINITION
1214 // =========================
1215 var backdrop = '.dropdown-backdrop';
1216 var toggle = '[data-toggle=dropdown]';
1217 var Dropdown = function( element ) { // eslint-disable-line func-style
1218 $( element ).on( 'click.bs.dropdown', this.toggle );
1219 };
1220
1221 Dropdown.prototype.toggle = function( event ) {
1222 var $this = $( this );
1223
1224 if ( $this.is( '.disabled, :disabled' ) ) {
1225 return;
1226 }
1227
1228 var $parent = getParent( $this );
1229 var isActive = $parent.hasClass( 'open' );
1230
1231 clearMenus();
1232
1233 if ( ! isActive ) {
1234 if ( 'ontouchstart' in document.documentElement && ! $parent.closest( '.navbar-nav' ).length ) {
1235 // if mobile we use a backdrop because click events don't delegate
1236 $( '<div class="dropdown-backdrop"/>' ).insertAfter( $( this ) ).on( 'click', clearMenus );
1237 }
1238
1239 var relatedTarget = { relatedTarget: this };
1240 $parent.trigger( event = $.Event( 'show.bs.dropdown', relatedTarget ) );
1241
1242 if ( event.isDefaultPrevented() ) {
1243 return;
1244 }
1245
1246 $parent
1247 .toggleClass( 'open' )
1248 .trigger( 'shown.bs.dropdown', relatedTarget);
1249
1250 $this.focus();
1251 }
1252
1253 return false;
1254 };
1255
1256 Dropdown.prototype.keydown = function( event ) {
1257 if ( ! /(38|40|27)/.test( event.keyCode ) ) {
1258 return;
1259 }
1260
1261 var $this = $( this );
1262
1263 event.preventDefault();
1264 event.stopPropagation();
1265
1266 if ( $this.is( '.disabled, :disabled' ) ) {
1267 return;
1268 }
1269
1270 var $parent = getParent( $this );
1271 var isActive = $parent.hasClass( 'open' );
1272
1273 if ( ! isActive || ( isActive && event.keyCode === 27 ) ) {
1274 if ( event.which === 27 ) {
1275 $parent.find( toggle ).focus();
1276 }
1277 return $this.click();
1278 }
1279
1280 var desc = ' li:not(.divider):visible a';
1281 var $items = $parent.find( '[role=menu]' + desc + ', [role=listbox]' + desc);
1282
1283 if ( ! $items.length ) {
1284 return;
1285 }
1286
1287 var index = $items.index($items.filter( ':focus' ));
1288
1289 if ( event.keyCode === 38 && index > 0 ) {
1290 index--; // up
1291 }
1292 if ( event.keyCode === 40 && index < $items.length - 1 ) {
1293 index++; // down
1294 }
1295 if ( ! ~index ) {
1296 index = 0;
1297 }
1298
1299 $items.eq(index).focus();
1300 };
1301
1302 function clearMenus( event ) {
1303 $(backdrop).remove();
1304 $(toggle).each( function() {
1305 var $parent = getParent($( this ));
1306 var relatedTarget = { relatedTarget: this };
1307 if ( ! $parent.hasClass( 'open' ) ) {
1308 return;
1309 }
1310 $parent.trigger( event = $.Event( 'hide.bs.dropdown', relatedTarget ) );
1311 if ( event.isDefaultPrevented() ) {
1312 return;
1313 }
1314 $parent.removeClass( 'open' ).trigger( 'hidden.bs.dropdown', relatedTarget);
1315 });
1316 }
1317
1318 function getParent( $this ) {
1319 var selector = $this.attr( 'data-target' );
1320
1321 if ( ! selector ) {
1322 selector = $this.attr( 'href' );
1323 selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '' ); // strip for ie7
1324 }
1325
1326 var $parent = selector && $(selector);
1327
1328 return $parent && $parent.length ? $parent : $this.parent();
1329 }
1330
1331 // DROPDOWN PLUGIN DEFINITION
1332 // ==========================
1333 var old = $.fn.dropdown;
1334 $.fn.dropdown = function( option ) {
1335 return this.each( function() {
1336 var $this = $( this );
1337 var data = $this.data( 'bs.dropdown' );
1338
1339 if ( ! data ) {
1340 $this.data( 'bs.dropdown', ( data = new Dropdown( this ) ) );
1341 }
1342 if ( 'string' === typeof option ) {
1343 data[option].call( $this );
1344 }
1345 });
1346 };
1347 $.fn.dropdown.Constructor = Dropdown;
1348
1349 // DROPDOWN NO CONFLICT
1350 // ====================
1351 $.fn.dropdown.noConflict = function() {
1352 $.fn.dropdown = old;
1353 return this;
1354 };
1355
1356 // APPLY TO STANDARD DROPDOWN ELEMENTS
1357 // ===================================
1358 $(document)
1359 .on( 'click.bs.dropdown.data-api', clearMenus)
1360 .on( 'click.bs.dropdown.data-api', '.dropdown form', function( event ) { event.stopPropagation(); })
1361 .on( 'click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
1362 .on( 'keydown.bs.dropdown.data-api', toggle + ', [role=menu], [role=listbox]', Dropdown.prototype.keydown);
1363
1364 } )( jQuery );
1365