PluginProbe
Authorizer / 2.8.5
Authorizer v2.8.5
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.8.5, at js/authorizer.js

1,331 lines 57.6 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: '45%',
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,
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="first-page tablenav-pages-navspan" aria-hidden="true">&laquo;</span>' );
107 } else if ( $first.is( 'span' ) && currentPage > 1 ) {
108 $first.replaceWith( '<a class="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="prev-page tablenav-pages-navspan" aria-hidden="true">&lsaquo;</span>' );
115 } else if ( currentPage > 1 ) {
116 $prev.replaceWith( '<a class="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="next-page tablenav-pages-navspan" aria-hidden="true">&rsaquo;</span>' );
123 } else if ( currentPage < totalPages ) {
124 $next.replaceWith( '<a class="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="last-page tablenav-pages-navspan" aria-hidden="true">&raquo;</span>' );
131 } else if ( $last.is( 'span' ) && currentPage < totalPages ) {
132 $last.replaceWith( '<a class="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 style="color: red;">' + 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" style="color: red;">' + authL10n.duplicate + '.</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 style="color: red;">' + 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 - 20,
258 width: '100%',
259 height: settings.height(),
260 'padding-left': 20,
261 });
262 overlay.show();
263 }
264 }
265
266 // Helper function to remove duplicate entries from an array of strings.
267 function removeDuplicatesFromArrayOfStrings( arrayOfStrings ) {
268 var seen = {};
269 return arrayOfStrings.filter( function( item ) {
270 return seen.hasOwnProperty( item ) ? false : ( seen[item] = true );
271 });
272 }
273
274 // Helper function to hide/show wordpress option
275 function animateOption( action, option ) {
276 if ( action === 'show' ) {
277 $( 'div.animated_wrapper', option ).slideDown( animationSpeed );
278 $( 'th', option ).animate({ padding: '20px 10px 20px 0' }, { duration: animationSpeed });
279 $( 'td', option ).animate({ padding: '15px 10px' }, { duration: animationSpeed });
280 } else if ( action === 'hide' ) {
281 $( 'div.animated_wrapper', option ).slideUp( animationSpeed );
282 $( 'td, th', option ).animate({ padding: '0px' }, { duration: animationSpeed });
283 } else if ( action === 'hide_immediately' ) {
284 $( 'div.animated_wrapper', option ).hide();
285 $( 'td, th', option ).css({ padding: '0px' });
286 }
287 }
288
289 // Helper function to grab a querystring param value by name
290 function getParameterByName( needle, haystack ) {
291 needle = needle.replace( /[\[]/, '\\\[').replace(/[\]]/, '\\\]' ); // eslint-disable-line no-useless-escape
292 var regex = new RegExp( '[\\?&]' + needle + '=([^&#]*)' );
293 var results = regex.exec( haystack );
294 if ( results === null ) {
295 return '';
296 } else {
297 return decodeURIComponent( results[1].replace( /\+/g, ' ' ) );
298 }
299 }
300
301 // Helper function to return a short date (e.g., Jul 2013) for today's date
302 function getShortDate( date ) {
303 date = typeof date !== 'undefined' ? date : new Date();
304 var month = '';
305 switch ( date.getMonth() ) {
306 case 0: month = 'Jan'; break;
307 case 1: month = 'Feb'; break;
308 case 2: month = 'Mar'; break;
309 case 3: month = 'Apr'; break;
310 case 4: month = 'May'; break;
311 case 5: month = 'Jun'; break;
312 case 6: month = 'Jul'; break;
313 case 7: month = 'Aug'; break;
314 case 8: month = 'Sep'; break;
315 case 9: month = 'Oct'; break;
316 case 10: month = 'Nov'; break;
317 case 11: month = 'Dec'; break;
318 }
319 return month + ' ' + date.getFullYear();
320 }
321
322 // Helper function to grab a querystring value
323 function getQuerystringValuesByKey( key ) {
324 var re = new RegExp( '(?:\\?|&)' + key + '=(.*?)(?=&|$)', 'gi' );
325 var matchingValues = [];
326 var match;
327 while ( ( match = re.exec( document.location.search ) ) !== null ) {
328 matchingValues.push( match[1] );
329 }
330 return matchingValues;
331 }
332
333 // Helper function to check if an email address is valid.
334 function validEmail( email ) {
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 );
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_ldap_host = $( '#auth_settings_ldap_host' ).closest( 'tr' );
400 var auth_settings_external_ldap_port = $( '#auth_settings_ldap_port' ).closest( 'tr' );
401 var auth_settings_external_ldap_search_base = $( '#auth_settings_ldap_search_base' ).closest( 'tr' );
402 var auth_settings_external_ldap_uid = $( '#auth_settings_ldap_uid' ).closest( 'tr' );
403 var auth_settings_external_ldap_attr_email = $( '#auth_settings_ldap_attr_email' ).closest( 'tr' );
404 var auth_settings_external_ldap_user = $( '#auth_settings_ldap_user' ).closest( 'tr' );
405 var auth_settings_external_ldap_password = $( '#auth_settings_ldap_password' ).closest( 'tr' );
406 var auth_settings_external_ldap_tls = $( '#auth_settings_ldap_tls' ).closest( 'tr' );
407 var auth_settings_external_ldap_lostpassword_url = $( '#auth_settings_ldap_lostpassword_url' ).closest( 'tr' );
408 var auth_settings_external_ldap_attr_first_name = $( '#auth_settings_ldap_attr_first_name' ).closest( 'tr' );
409 var auth_settings_external_ldap_attr_last_name = $( '#auth_settings_ldap_attr_last_name' ).closest( 'tr' );
410 var auth_settings_external_ldap_attr_update_on_login = $( '#auth_settings_ldap_attr_update_on_login' ).closest( 'tr' );
411 /* eslint-enable */
412
413 // Wrap the th and td in the rows above so we can animate their heights (can't animate tr heights with jquery)
414 $( 'th, td', auth_settings_access_role_receive_pending_emails ).wrapInner( '<div class="animated_wrapper" />' );
415 $( 'th, td', auth_settings_access_pending_redirect_to_message ).wrapInner( '<div class="animated_wrapper" />' );
416 $( 'th, td', auth_settings_access_blocked_redirect_to_message ).wrapInner( '<div class="animated_wrapper" />' );
417 $( 'th, td', auth_settings_access_should_email_approved_users ).wrapInner( '<div class="animated_wrapper" />' );
418 $( 'th, td', auth_settings_access_email_approved_users_subject ).wrapInner( '<div class="animated_wrapper" />' );
419 $( 'th, td', auth_settings_access_email_approved_users_body ).wrapInner( '<div class="animated_wrapper" />' );
420 $( 'th, td', auth_settings_access_public_pages ).wrapInner( '<div class="animated_wrapper" />' );
421 $( 'th, td', auth_settings_access_redirect_to_login ).wrapInner( '<div class="animated_wrapper" />' );
422 $( 'th, td', auth_settings_access_public_warning ).wrapInner( '<div class="animated_wrapper" />' );
423 $( 'th, td', auth_settings_access_redirect_to_message ).wrapInner( '<div class="animated_wrapper" />' );
424 $( 'th, td', auth_settings_external_google_clientid ).wrapInner( '<div class="animated_wrapper" />' );
425 $( 'th, td', auth_settings_external_google_clientsecret ).wrapInner( '<div class="animated_wrapper" />' );
426 $( 'th, td', auth_settings_external_google_hosteddomain ).wrapInner( '<div class="animated_wrapper" />' );
427 $( 'th, td', auth_settings_external_cas_custom_label ).wrapInner( '<div class="animated_wrapper" />' );
428 $( 'th, td', auth_settings_external_cas_host ).wrapInner( '<div class="animated_wrapper" />' );
429 $( 'th, td', auth_settings_external_cas_port ).wrapInner( '<div class="animated_wrapper" />' );
430 $( 'th, td', auth_settings_external_cas_path ).wrapInner( '<div class="animated_wrapper" />' );
431 $( 'th, td', auth_settings_external_cas_version ).wrapInner( '<div class="animated_wrapper" />' );
432 $( 'th, td', auth_settings_external_cas_attr_email ).wrapInner( '<div class="animated_wrapper" />' );
433 $( 'th, td', auth_settings_external_cas_attr_first_name ).wrapInner( '<div class="animated_wrapper" />' );
434 $( 'th, td', auth_settings_external_cas_attr_last_name ).wrapInner( '<div class="animated_wrapper" />' );
435 $( 'th, td', auth_settings_external_cas_attr_update_on_login ).wrapInner( '<div class="animated_wrapper" />' );
436 $( 'th, td', auth_settings_external_cas_auto_login ).wrapInner( '<div class="animated_wrapper" />' );
437 $( 'th, td', auth_settings_external_ldap_host ).wrapInner( '<div class="animated_wrapper" />' );
438 $( 'th, td', auth_settings_external_ldap_port ).wrapInner( '<div class="animated_wrapper" />' );
439 $( 'th, td', auth_settings_external_ldap_search_base ).wrapInner( '<div class="animated_wrapper" />' );
440 $( 'th, td', auth_settings_external_ldap_uid ).wrapInner( '<div class="animated_wrapper" />' );
441 $( 'th, td', auth_settings_external_ldap_attr_email ).wrapInner( '<div class="animated_wrapper" />' );
442 $( 'th, td', auth_settings_external_ldap_user ).wrapInner( '<div class="animated_wrapper" />' );
443 $( 'th, td', auth_settings_external_ldap_password ).wrapInner( '<div class="animated_wrapper" />' );
444 $( 'th, td', auth_settings_external_ldap_tls ).wrapInner( '<div class="animated_wrapper" />' );
445 $( 'th, td', auth_settings_external_ldap_lostpassword_url ).wrapInner( '<div class="animated_wrapper" />' );
446 $( 'th, td', auth_settings_external_ldap_attr_first_name ).wrapInner( '<div class="animated_wrapper" />' );
447 $( 'th, td', auth_settings_external_ldap_attr_last_name ).wrapInner( '<div class="animated_wrapper" />' );
448 $( 'th, td', auth_settings_external_ldap_attr_update_on_login ).wrapInner( '<div class="animated_wrapper" />' );
449
450 // If we're viewing the dashboard widget, reset a couple of the relevant
451 // option variables (since they aren't nested in table rows).
452 if ( $( '#auth_dashboard_widget' ).length ) {
453 // Remove the helper link, since there are no tabs on the dashboard widget
454 $( '#dashboard_link_approved_users' ).contents().unwrap();
455 }
456
457 // Hide settings unless "Only approved users" is checked
458 if ( ! $( '#radio_auth_settings_access_who_can_login_approved_users' ).is( ':checked' ) ) {
459 animateOption( 'hide_immediately', auth_settings_access_role_receive_pending_emails );
460 animateOption( 'hide_immediately', auth_settings_access_pending_redirect_to_message );
461 animateOption( 'hide_immediately', auth_settings_access_blocked_redirect_to_message );
462 animateOption( 'hide_immediately', auth_settings_access_should_email_approved_users );
463 }
464
465 // Hide Welcome email body/subject options if "Send welcome email" is off.
466 if ( ! $( '#auth_settings_access_should_email_approved_users' ).is( ':checked' ) ) {
467 animateOption( 'hide_immediately', auth_settings_access_email_approved_users_subject );
468 animateOption( 'hide_immediately', auth_settings_access_email_approved_users_body );
469 }
470
471 // On load: Show/hide public access options if everyone can see site
472 if ( ! $( '#radio_auth_settings_access_who_can_view_logged_in_users' ).is( ':checked' ) ) {
473 animateOption( 'hide_immediately', auth_settings_access_public_pages );
474 animateOption( 'hide_immediately', auth_settings_access_redirect_to_login );
475 animateOption( 'hide_immediately', auth_settings_access_public_warning );
476 animateOption( 'hide_immediately', auth_settings_access_redirect_to_message );
477 }
478
479 // Hide Google options if unchecked
480 if ( ! $( '#auth_settings_google' ).is( ':checked' ) ) {
481 animateOption( 'hide_immediately', auth_settings_external_google_clientid );
482 animateOption( 'hide_immediately', auth_settings_external_google_clientsecret );
483 animateOption( 'hide_immediately', auth_settings_external_google_hosteddomain );
484 }
485
486 // Hide CAS options if unchecked
487 if ( ! $( '#auth_settings_cas' ).is( ':checked' ) ) {
488 animateOption( 'hide_immediately', auth_settings_external_cas_custom_label );
489 animateOption( 'hide_immediately', auth_settings_external_cas_host );
490 animateOption( 'hide_immediately', auth_settings_external_cas_port );
491 animateOption( 'hide_immediately', auth_settings_external_cas_path );
492 animateOption( 'hide_immediately', auth_settings_external_cas_version );
493 animateOption( 'hide_immediately', auth_settings_external_cas_attr_email );
494 animateOption( 'hide_immediately', auth_settings_external_cas_attr_first_name );
495 animateOption( 'hide_immediately', auth_settings_external_cas_attr_last_name );
496 animateOption( 'hide_immediately', auth_settings_external_cas_attr_update_on_login );
497 animateOption( 'hide_immediately', auth_settings_external_cas_auto_login );
498 }
499
500 // Hide LDAP options if unchecked
501 if ( ! $( '#auth_settings_ldap' ).is( ':checked' ) ) {
502 animateOption( 'hide_immediately', auth_settings_external_ldap_host );
503 animateOption( 'hide_immediately', auth_settings_external_ldap_port );
504 animateOption( 'hide_immediately', auth_settings_external_ldap_search_base );
505 animateOption( 'hide_immediately', auth_settings_external_ldap_uid );
506 animateOption( 'hide_immediately', auth_settings_external_ldap_attr_email );
507 animateOption( 'hide_immediately', auth_settings_external_ldap_user );
508 animateOption( 'hide_immediately', auth_settings_external_ldap_password );
509 animateOption( 'hide_immediately', auth_settings_external_ldap_tls );
510 animateOption( 'hide_immediately', auth_settings_external_ldap_lostpassword_url );
511 animateOption( 'hide_immediately', auth_settings_external_ldap_attr_first_name );
512 animateOption( 'hide_immediately', auth_settings_external_ldap_attr_last_name );
513 animateOption( 'hide_immediately', auth_settings_external_ldap_attr_update_on_login );
514 }
515
516 // Event handler: Hide "Handle unauthorized visitors" option if access is granted to "Everyone"
517 $( 'input[name="auth_settings[access_who_can_login]"]' ).change( function() {
518 // Hide settings unless "Only approved users" is checked
519 var action = $( '#radio_auth_settings_access_who_can_login_approved_users' ).is( ':checked' ) ? 'show' : 'hide';
520 animateOption( action, auth_settings_access_role_receive_pending_emails );
521 animateOption( action, auth_settings_access_pending_redirect_to_message );
522 animateOption( action, auth_settings_access_blocked_redirect_to_message );
523 animateOption( action, auth_settings_access_should_email_approved_users );
524 action = action === 'show' && $( '#auth_settings_access_should_email_approved_users' ).is( ':checked' ) ? 'show' : 'hide_immediately';
525 animateOption( action, auth_settings_access_email_approved_users_subject );
526 animateOption( action, auth_settings_access_email_approved_users_body );
527 });
528
529 // Event handler: Hide Welcome email body/subject options if "Send welcome email" is off.
530 $( 'input[name="auth_settings[access_should_email_approved_users]"]' ).change( function() {
531 var action = $( this ).is( ':checked' ) ? 'show' : 'hide';
532 animateOption( action, auth_settings_access_email_approved_users_subject );
533 animateOption( action, auth_settings_access_email_approved_users_body );
534 });
535
536 // Event handler: Hide "Handle unauthorized visitors" option if access is granted to "Everyone"
537 $( 'input[name="auth_settings[access_who_can_view]"]' ).change( function() {
538 var action = $( '#radio_auth_settings_access_who_can_view_everyone' ).is( ':checked' ) ? 'hide' : 'show';
539 animateOption( action, auth_settings_access_redirect_to_login );
540 animateOption( action, auth_settings_access_redirect_to_message );
541 animateOption( action, auth_settings_access_public_pages );
542 animateOption( action, auth_settings_access_public_warning );
543 });
544
545 // Event handler: Show/hide Google options based on checkbox
546 $( 'input[name="auth_settings[google]"]' ).change( function() {
547 var action = $( this ).is( ':checked' ) ? 'show' : 'hide';
548 animateOption( action, auth_settings_external_google_clientid );
549 animateOption( action, auth_settings_external_google_clientsecret );
550 animateOption( action, auth_settings_external_google_hosteddomain );
551 });
552
553 // Event handler: Show/hide CAS options based on checkbox
554 $( 'input[name="auth_settings[cas]"]' ).change( function() {
555 var action = $( this ).is( ':checked' ) ? 'show' : 'hide';
556 animateOption( action, auth_settings_external_cas_custom_label );
557 animateOption( action, auth_settings_external_cas_host );
558 animateOption( action, auth_settings_external_cas_port );
559 animateOption( action, auth_settings_external_cas_path );
560 animateOption( action, auth_settings_external_cas_version );
561 animateOption( action, auth_settings_external_cas_attr_email );
562 animateOption( action, auth_settings_external_cas_attr_first_name );
563 animateOption( action, auth_settings_external_cas_attr_last_name );
564 animateOption( action, auth_settings_external_cas_attr_update_on_login );
565 animateOption( action, auth_settings_external_cas_auto_login );
566 });
567
568 // Event handler: Show/hide LDAP options based on checkbox
569 $( 'input[name="auth_settings[ldap]"]' ).change( function() {
570 var action = $( this ).is( ':checked' ) ? 'show' : 'hide';
571 animateOption( action, auth_settings_external_ldap_host );
572 animateOption( action, auth_settings_external_ldap_port );
573 animateOption( action, auth_settings_external_ldap_search_base );
574 animateOption( action, auth_settings_external_ldap_uid );
575 animateOption( action, auth_settings_external_ldap_attr_email );
576 animateOption( action, auth_settings_external_ldap_user );
577 animateOption( action, auth_settings_external_ldap_password );
578 animateOption( action, auth_settings_external_ldap_tls );
579 animateOption( action, auth_settings_external_ldap_lostpassword_url );
580 animateOption( action, auth_settings_external_ldap_attr_first_name );
581 animateOption( action, auth_settings_external_ldap_attr_last_name );
582 animateOption( action, auth_settings_external_ldap_attr_update_on_login );
583 });
584
585 // Show save button if usermeta field is modified.
586 $( 'form input.auth-usermeta' ).on( 'keyup', function( event ) {
587 // Don't do anything if tab or arrow keys were pressed.
588 if ( event.which === 9 || event.which === 37 || event.which === 38 || event.which === 39 || event.which === 40 ) {
589 return;
590 }
591 $( this ).siblings( '.button' ).css( 'display', 'inline-block' );
592 });
593
594 // List management function: pressing enter in the new approved or new
595 // blocked user (email or role field) adds the user to the list.
596 $( '#new_approved_user_email, #new_approved_user_role, #new_blocked_user_email' ).on( 'keyup', function( event ) {
597 // For textareas, make Enter add the user; for inputs, make enter add the user.
598 if ( $( this ).is( 'textarea' ) ) {
599 // Enter key adds a newline; Enter key with Ctrl, Alt, Shift, or Meta adds the user.
600 if ( event.which === 13 && ( event.ctrlKey || event.altKey || event.metaKey ) ) {
601 $( this ).parent().find( 'a.button-add-user' ).trigger( 'click' );
602 event.preventDefault();
603 }
604 } else if ( event.which === 13 ) { // Enter key on input[type="text"]
605 $( this ).parent().find( 'a.button-add-user' ).trigger( 'click' );
606 event.preventDefault();
607 }
608 });
609
610 // Don't submit form (i.e., save options) when hitting enter in any user list field.
611 $( 'input.auth-email, select.auth-role, input.auth-date-added, input.auth-usermeta' ).on( 'keydown', function( event ) {
612 if ( event.which === 13 ) { // Enter key
613 event.preventDefault();
614 return false;
615 }
616 });
617
618 // Enable the user-friendly multiselect form element on the options page.
619 $( '#auth_settings_access_public_pages' ).multiSelect({
620 selectableOptgroup: true,
621 selectableHeader: '<div class="custom-header">' + authL10n.private_pages + '</div>',
622 selectionHeader: '<div class="custom-header">' + authL10n.public_pages + '</div>',
623 });
624
625 // Switch to the first tab (or the tab indicated in sessionStorage, or the querystring).
626 var tab = '';
627 if ( getQuerystringValuesByKey( 'tab' ).length > 0 ) {
628 tab = getQuerystringValuesByKey( 'tab' )[0];
629 } else if ( sessionStorage.getItem( 'tab' ) ) {
630 tab = sessionStorage.getItem( 'tab' );
631 }
632 if ( $.inArray( tab, [ 'access_lists', 'access_login', 'access_public', 'external', 'advanced' ] ) < 0 ) {
633 tab = 'access_lists';
634 }
635 window.chooseTab( tab, animationSpeed );
636
637 // Hide/show multisite settings based on override checkbox.
638 $( 'input[name="auth_settings[multisite_override]"]' ).change( function() {
639 hideMultisiteSettingsIfDisabled();
640 });
641 hideMultisiteSettingsIfDisabled();
642
643 // Wire up pager events on Approved User list (first/last/next/previous
644 // buttons, go to page text input, and search.
645 $( '#current-page-selector, #user-search-input' ).on( 'keydown', function( event ) {
646 if ( event.which === 13 ) { // Enter key
647 var searchTerm = $( '#user-search-input' ).val();
648 var currentPage = parseInt( $( this ).val(), 10 ) || 1;
649 var totalPages = parseInt( $( '.total-pages' ).first().text().replace( /[^0-9]/g, '' ), 10 ) || 1;
650
651 // Make sure current page is between 1 and max pages.
652 if ( currentPage < 1 ) {
653 currentPage = 1;
654 } else if ( currentPage > totalPages ) {
655 currentPage = totalPages;
656 }
657
658 // Update user list with users on next page.
659 refreshApprovedUserList( currentPage, searchTerm );
660
661 // Prevent default behavior.
662 event.preventDefault();
663 return false;
664 }
665 });
666
667 $( '.tablenav' ).on( 'click', '.pagination-links a, #search-submit', function( event ) {
668 var searchTerm = $( '#user-search-input' ).val();
669 var currentPage = parseInt( getParameterByName( 'paged', $( this ).attr( 'href' ) ), 10 ) || 1;
670 var totalPages = parseInt( $( '.total-pages' ).first().text().replace( /[^0-9]/g, '' ), 10 ) || 1;
671 if ( currentPage > totalPages ) {
672 currentPage = totalPages;
673 }
674
675 // Update user list with users on next page.
676 refreshApprovedUserList( currentPage, searchTerm );
677
678 // Remove focus from clicked element.
679 $( this ).blur();
680
681 // Prevent default behavior.
682 event.preventDefault();
683 return false;
684 });
685
686 // Enable growable textarea for new user field.
687 $( 'textarea#new_approved_user_email' ).autogrow();
688
689 // Enable growable textarea for config fields.
690 $( 'textarea#auth_settings_ldap_search_base' ).autogrow();
691 $( 'textarea#auth_settings_google_hosteddomain' ).autogrow();
692
693 });
694
695
696 /**
697 * Globals.
698 */
699
700
701 // Switch between option tabs.
702 window.chooseTab = function( listName, delay ) {
703 // default delay is 0
704 delay = 'undefined' !== typeof delay ? delay : 0;
705
706 // default to the access list tab
707 listName = 'undefined' !== typeof listName ? listName : 'access_lists';
708
709 // Hide all tab content, then show selected tab content
710 $( 'div.section_info, div.section_info + table' ).hide();
711 $( '#section_info_' + listName + ', #section_info_' + listName + ' + table' ).show();
712
713 // Set active tab
714 $( '.nav-tab-wrapper a' ).removeClass( 'nav-tab-active' );
715 $( 'a.nav-tab-' + listName ).addClass( 'nav-tab-active' );
716
717 // Hide site options if they are overridden by a multisite setting.
718 setTimeout( window.hideMultisiteOverriddenOptions, delay );
719
720 // Hide Save Changes button if we're on the access lists page (changing
721 // access lists saves automatically via AJAX).
722 $( 'body:not(.network-admin) #submit' ).toggle( 'access_lists' !== listName );
723
724 // Save user's active tab to sessionStorage (so we can restore it on reload).
725 // Note: session storage persists until the browser tab is closed.
726 sessionStorage.setItem( 'tab', listName );
727 };
728
729 // Hide (with overlay) site options if overridden by a multisite option.
730 window.hideMultisiteOverriddenOptions = function() {
731 $( '.auth_multisite_override_overlay' ).each( function() {
732 // Option to hide is stored in the overlay's id with 'overlay-hide-' prefix.
733 var optionContainerToHide = $( this ).closest( 'tr' );
734 if ( optionContainerToHide.length > 0 ) {
735 $( this ).css({
736 'background-color': '#f1f1f1',
737 'z-index': 1,
738 opacity: 0.8,
739 position: 'absolute',
740 top: optionContainerToHide.position().top,
741 left: optionContainerToHide.position().left,
742 width: '100%',
743 height: optionContainerToHide.height(),
744 });
745 $( this ).show();
746 }
747 });
748 };
749
750 // Update user's usermeta field.
751 // @calls php wp_ajax_update_auth_usermeta.
752 window.authUpdateUsermeta = function( caller ) {
753 var $caller = $( caller ),
754 $usermeta = $caller.parent().children( '.auth-usermeta' ),
755 email = $caller.siblings( '.auth-email' ).val(),
756 usermeta = $usermeta.val(),
757 nonce = $( '#nonce_save_auth_settings' ).val();
758
759 // Remove reference to caller if it's the usermeta field itself (not a button triggering the save).
760 if ( $caller.hasClass( 'auth-usermeta' ) ) {
761 $caller = $();
762 }
763
764 // Disable inputs, show spinner.
765 $caller.attr( 'disabled', 'disabled' );
766 $usermeta.attr( 'disabled', 'disabled' );
767 var $row = $usermeta.closest( 'li' );
768 var $spinner = $( '<span class="spinner is-active"></span>' ).css({
769 position: 'absolute',
770 top: $row.position().top,
771 left: $row.position().left + $row.width(),
772 });
773 $usermeta.after( $spinner );
774 $( 'html' ).addClass( 'busy' );
775
776 // Call ajax save function.
777 $.post( ajaxurl, {
778 action: 'update_auth_usermeta',
779 email: email,
780 usermeta: usermeta,
781 nonce: nonce,
782 }, function( response ) {
783 var succeeded = response === 'success';
784 var spinnerText = succeeded ? authL10n.saved + '.' : '<span style="color: red;">' + authL10n.failed + '.</span>';
785 var spinnerWait = succeeded ? 500 : 2000;
786
787 // Enable inputs, remove spinner.
788 $caller.removeAttr( 'disabled' );
789 $usermeta.removeAttr( 'disabled' );
790 $caller.css( 'display', 'none' );
791 $( 'form .spinner:not(:has(.spinner-text))' ).animate( { width: '60px' }, 'fast' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
792 $( this ).remove();
793 });
794 $( 'html' ).removeClass( 'busy' );
795
796 }).fail( function() {
797 var succeeded = false;
798 var spinnerText = succeeded ? authL10n.saved + '.' : '<span style="color: red;">' + authL10n.failed + '.</span>';
799 var spinnerWait = succeeded ? 500 : 2000;
800
801 // Enable inputs, remove spinner.
802 $caller.removeAttr( 'disabled' );
803 $usermeta.removeAttr( 'disabled' );
804 $caller.css( 'display', 'none' );
805 $( 'form .spinner:not(:has(.spinner-text))' ).animate( { width: '60px' }, 'fast' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
806 $( this ).remove();
807 });
808 $( 'html' ).removeClass( 'busy' );
809
810 });
811 };
812
813 // Update user's role.
814 window.authChangeRole = function( caller, isMultisite ) {
815 // Set default for multisite flag (run different save routine if multisite)
816 isMultisite = typeof isMultisite !== 'undefined' ? isMultisite : false;
817
818 var email = $( caller ).parent().find( '.auth-email' );
819 var role = $( caller ).parent().find( '.auth-role' );
820 var dateAdded = $( caller ).parent().find( '.auth-date-added' );
821
822 var user = {
823 email: email.val(),
824 role: role.val(),
825 date_added: dateAdded.val(), // eslint-disable-line camelcase
826 edit_action: 'change_role', // eslint-disable-line camelcase
827 multisite_user: isMultisite, // eslint-disable-line camelcase
828 };
829
830 // Update the options in the database with this change.
831 updateAuthUser( caller, 'access_users_approved', user );
832
833 return true;
834 };
835
836 // Update user's role (multisite options page).
837 window.authMultisiteChangeRole = function( caller ) {
838 var isMultisite = true;
839 window.authChangeRole( caller, isMultisite );
840 };
841
842 // Add user to list (list = blocked or approved).
843 window.authAddUser = function( caller, list, shouldCreateLocalAccount, isMultisite ) {
844 // Skip email address validation if adding from pending list (not user-editable).
845 var skipValidation = $( caller ).parent().parent().attr( 'id' ) === 'list_auth_settings_access_users_pending';
846
847 // Skip email address validation if we're banning an existing user (since they're already in a list).
848 skipValidation = skipValidation || $( caller ).attr( 'id' ).indexOf( 'block_user' ) > -1;
849
850 // Set default for multisite flag (run different save routine if multisite)
851 isMultisite = 'undefined' !== typeof isMultisite ? isMultisite : false;
852
853 // Default to the approved list.
854 list = 'undefined' !== typeof list ? list : 'approved';
855
856 // Default to not creating a local account.
857 shouldCreateLocalAccount = 'undefined' !== typeof shouldCreateLocalAccount ? shouldCreateLocalAccount : false;
858
859 var email = $( caller ).parent().find( '.auth-email' );
860 var role = $( caller ).parent().find( '.auth-role' );
861 var dateAdded = $( caller ).parent().find( '.auth-date-added' );
862
863 // Helper variable for disabling buttons while processing. This will be
864 // set differently if our clicked button is nested in a div (below).
865 var buttons = caller;
866
867 // Button (caller) might be nested in a div, so we need to walk up one more level
868 if ( 0 === email.length || 0 === role.length ) {
869 email = $( caller ).parent().parent().find( '.auth-email' );
870 role = $( caller ).parent().parent().find( '.auth-role' );
871 dateAdded = $( caller ).parent().parent().find( '.auth-date-added' );
872 buttons = $( caller ).parent().children();
873 }
874
875 // Support a single email address, or multiple (separated by newlines, commas, semicolons, or spaces).
876 var emails = $.trim( email.val() ).replace( /mailto:/g, '' ).split( /[\s,;]+/ );
877
878 // Remove any invalid email addresses.
879 if ( ! skipValidation ) {
880 // Check if the email(s) being added is well-formed.
881 emails = emails.filter( function( emailToValidate ) {
882 return validEmail( emailToValidate );
883 });
884 // Remove any duplicates in the list of emails to add.
885 emails = removeDuplicatesFromArrayOfStrings( emails );
886 }
887
888 // Shake and quit if no valid email addresses exist.
889 if ( 1 > emails.length ) {
890 $( '#new_' + list + '_user_email' ).parent().effect( 'shake', shakeSpeed );
891 return false;
892 }
893
894 $( buttons ).attr( 'disabled', 'disabled' );
895
896 var users = [];
897 for ( var i = 0; i < emails.length; i++ ) {
898 var user = {
899 email: emails[i],
900 role: role.val(),
901 date_added: dateAdded.val(), // eslint-disable-line camelcase
902 edit_action: 'add', // eslint-disable-line camelcase
903 local_user: shouldCreateLocalAccount, // eslint-disable-line camelcase
904 multisite_user: isMultisite, // eslint-disable-line camelcase
905 };
906 users.push( user );
907
908 // Get next highest user ID.
909 var nextId = 1 + Math.max.apply(
910 null,
911 // eslint-disable-next-line no-unused-vars
912 $( '#list_auth_settings_access_users_' + list + ' li .auth-email' ).map( function( el ) { // jshint ignore:line
913 return parseInt( this.id.replace( 'auth_multisite_settings_access_users_' + list + '_', '' ).replace( 'auth_settings_access_users_' + list + '_', '' ), 10 );
914 })
915 );
916
917 // Add the new item.
918 var authJsPrefix = isMultisite ? 'authMultisite' : 'auth';
919 var localIcon = shouldCreateLocalAccount ? '&nbsp;<a title="' + authL10n.local_wordpress_user + '" class="auth-local-user"><span class="glyphicon glyphicon-user"></span></a>' : '';
920 var banButton = list === 'approved' && ! isMultisite ? '<a class="button" 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>' : '';
921 $( ' \
922 <li id="new_user_' + nextId + '" class="new-user" style="display: none;"> \
923 <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" /> \
924 <select name="auth_settings[access_users_' + list + '][' + nextId + '][role]" class="auth-role" onchange="' + authJsPrefix + 'ChangeRole( this );"> \
925 </select> \
926 <input type="text" name="auth_settings[access_users_' + list + '][' + nextId + '][date_added]" value="' + getShortDate() + '" readonly="true" class="auth-date-added" /> \
927 ' + banButton + ' \
928 <a class="button" id="ignore_user_' + nextId + '" onclick="' + authJsPrefix + 'IgnoreUser( this, \'' + list + '\' );" title="' + authL10n.remove_user + '"><span class="glyphicon glyphicon-remove"></span></a> \
929 ' + localIcon + ' \
930 <span class="spinner is-active"></span> \
931 </li> \
932 ' ).appendTo( '#list_auth_settings_access_users_' + list ).slideDown( 250 );
933
934 // Populate the role dropdown in the new element. Because clone() doesn't
935 // save selected state on select elements, set that too.
936 $( 'option', role ).clone().appendTo( '#new_user_' + nextId + ' .auth-role' );
937 $( '#new_user_' + nextId + ' .auth-role' ).val( role.val() );
938 }
939
940 // Remove the 'empty list' item if it exists.
941 $( '#list_auth_settings_access_users_' + list + ' li.auth-empty' ).remove();
942
943 // Update the options in the database with this change.
944 updateAuthUser( buttons, 'access_users_' + list, users );
945
946 // Reset the new user textboxes
947 if ( email.hasClass( 'new' ) ) {
948 email.val( '' ).keydown();
949 }
950
951 // Re-enable the action buttons now that we're done saving.
952 $( buttons ).removeAttr( 'disabled' );
953 return true;
954 };
955
956 // Add user to list (multisite options page).
957 window.authMultisiteAddUser = function( caller, list, shouldCreateLocalAccount ) {
958 var isMultisite = true;
959
960 // Default to the approved list.
961 list = typeof list !== 'undefined' ? list : 'approved';
962
963 // Default to not creating a local account.
964 shouldCreateLocalAccount = typeof shouldCreateLocalAccount !== 'undefined' ? shouldCreateLocalAccount : false;
965
966 // There currently is no multisite blocked list, so do nothing.
967 if ( list === 'blocked' ) {
968 return;
969 }
970
971 window.authAddUser( caller, list, shouldCreateLocalAccount, isMultisite );
972 };
973
974 // Remove user from list.
975 window.authIgnoreUser = function( caller, listName, isMultisite ) {
976 // Set default for multisite flag (run different save routine if multisite)
977 isMultisite = typeof isMultisite !== 'undefined' ? isMultisite : false;
978
979 // Set default list if not provided.
980 listName = typeof listName !== 'undefined' ? listName : 'approved';
981
982 var email = $( caller ).parent().find( '.auth-email' );
983
984 var user = {
985 email: email.val(),
986 role: '',
987 date_added: '', // eslint-disable-line camelcase
988 edit_action: 'remove', // eslint-disable-line camelcase
989 multisite_user: isMultisite, // eslint-disable-line camelcase
990 };
991
992 // Show an 'empty list' message if we're deleting the last item
993 var list = $( caller ).closest( 'ul' );
994 if ( $( 'li', list ).length <= 1 ) {
995 $( list ).append( '<li class="auth-empty"><em>' + authL10n.no_users_in + ' ' + listName + '</em></li>' );
996 }
997
998 $( caller ).parent().slideUp( 250, function() {
999 // Remove the list item.
1000 $( this ).remove();
1001
1002 // Update the options in the database with this change.
1003 updateAuthUser( caller, 'access_users_' + listName, user );
1004 });
1005 };
1006
1007 // Remove user from list (multisite options page).
1008 window.authMultisiteIgnoreUser = function( caller, listName ) {
1009 var isMultisite = true;
1010
1011 // Set default list if not provided.
1012 listName = typeof listName !== 'undefined' ? listName : '';
1013
1014 window.authIgnoreUser( caller, listName, isMultisite );
1015 };
1016
1017 // Save Authorizer Settings (multisite).
1018 // @calls php wp_ajax_save_auth_multisite_settings.
1019 /* eslint-disable camelcase */
1020 window.saveAuthMultisiteSettings = function( caller ) {
1021 // Enable wait cursor.
1022 $( 'html' ).addClass( 'busy' );
1023
1024 // Disable button (prevent duplicate clicks).
1025 $( caller ).attr( 'disabled', 'disabled' );
1026
1027 // Enable spinner by element that triggered this event (caller).
1028 var $spinner = $( '<span class="spinner is-active"></span>' ).css({
1029 position: 'absolute',
1030 top: $( caller ).position().top,
1031 left: $( caller ).position().left + $( caller ).width() + 20,
1032 });
1033 $( caller ).after( $spinner );
1034
1035 // Get form elements to save
1036 var nonce_save_auth_settings = $( '#nonce_save_auth_settings' ).val();
1037
1038 var multisite_override = $( '#auth_settings_multisite_override' ).is( ':checked' ) ? '1' : '';
1039
1040 var access_who_can_login = $( 'form input[name="auth_settings[access_who_can_login]"]:checked' ).val();
1041
1042 var access_who_can_view = $( 'form input[name="auth_settings[access_who_can_view]"]:checked' ).val();
1043
1044 var access_users_approved = {};
1045 $( '#list_auth_settings_access_users_approved li' ).each( function( index ) {
1046 var user = {};
1047 user.email = $( '.auth-email', this ).val();
1048 user.role = $( '.auth-role', this ).val();
1049 user.date_added = $( '.auth-date-added', this ).val();
1050 user.local_user = $( '.auth-local-user', this ).length !== 0;
1051 access_users_approved[index] = user;
1052 });
1053
1054 var access_default_role = $( '#auth_settings_access_default_role' ).val();
1055
1056 var google = $( '#auth_settings_google' ).is( ':checked' ) ? '1' : '';
1057 var google_clientid = $( '#auth_settings_google_clientid' ).val();
1058 var google_clientsecret = $( '#auth_settings_google_clientsecret' ).val();
1059 var google_hosteddomain = $( '#auth_settings_google_hosteddomain' ).val();
1060
1061 var cas = $( '#auth_settings_cas' ).is( ':checked' ) ? '1' : '';
1062 var cas_custom_label = $( '#auth_settings_cas_custom_label' ).val();
1063 var cas_host = $( '#auth_settings_cas_host' ).val();
1064 var cas_port = $( '#auth_settings_cas_port' ).val();
1065 var cas_path = $( '#auth_settings_cas_path' ).val();
1066 var cas_version = $( '#auth_settings_cas_version' ).val();
1067 var cas_attr_email = $( '#auth_settings_cas_attr_email' ).val();
1068 var cas_attr_first_name = $( '#auth_settings_cas_attr_first_name' ).val();
1069 var cas_attr_last_name = $( '#auth_settings_cas_attr_last_name' ).val();
1070 var cas_attr_update_on_login = $( '#auth_settings_cas_attr_update_on_login' ).is( ':checked' ) ? '1' : '';
1071 var cas_auto_login = $( '#auth_settings_cas_auto_login' ).is( ':checked' ) ? '1' : '';
1072
1073 var ldap = $( '#auth_settings_ldap' ).is( ':checked' ) ? '1' : '';
1074 var ldap_host = $( '#auth_settings_ldap_host' ).val();
1075 var ldap_port = $( '#auth_settings_ldap_port' ).val();
1076 var ldap_search_base = $( '#auth_settings_ldap_search_base' ).val();
1077 var ldap_uid = $( '#auth_settings_ldap_uid' ).val();
1078 var ldap_attr_email = $( '#auth_settings_ldap_attr_email' ).val();
1079 var ldap_user = $( '#auth_settings_ldap_user' ).val();
1080 var ldap_password = $( '#auth_settings_ldap_password' ).val();
1081 var ldap_tls = $( '#auth_settings_ldap_tls' ).is( ':checked' ) ? '1' : '';
1082 var ldap_lostpassword_url = $( '#auth_settings_ldap_lostpassword_url' ).val();
1083 var ldap_attr_first_name = $( '#auth_settings_ldap_attr_first_name' ).val();
1084 var ldap_attr_last_name = $( '#auth_settings_ldap_attr_last_name' ).val();
1085 var ldap_attr_update_on_login = $( '#auth_settings_ldap_attr_update_on_login' ).is( ':checked' ) ? '1' : '';
1086
1087 var advanced_lockouts = {
1088 attempts_1: $( '#auth_settings_advanced_lockouts_attempts_1' ).val(),
1089 duration_1: $( '#auth_settings_advanced_lockouts_duration_1' ).val(),
1090 attempts_2: $( '#auth_settings_advanced_lockouts_attempts_2' ).val(),
1091 duration_2: $( '#auth_settings_advanced_lockouts_duration_2' ).val(),
1092 reset_duration: $( '#auth_settings_advanced_lockouts_reset_duration' ).val(),
1093 };
1094 var advanced_hide_wp_login = $( '#auth_settings_advanced_hide_wp_login' ).is( ':checked' ) ? '1' : '';
1095 var advanced_widget_enabled = $( '#auth_settings_advanced_widget_enabled' ).is( ':checked' ) ? '1' : '';
1096 var advanced_users_per_page = $( '#auth_settings_advanced_users_per_page' ).val();
1097 var advanced_users_sort_by = $( '#auth_settings_advanced_users_sort_by' ).val();
1098 var advanced_users_sort_order = $( '#auth_settings_advanced_users_sort_order' ).val();
1099
1100 $.post( ajaxurl, {
1101 action: 'save_auth_multisite_settings',
1102 nonce: nonce_save_auth_settings,
1103 multisite_override: multisite_override,
1104 access_who_can_login: access_who_can_login,
1105 access_who_can_view: access_who_can_view,
1106 access_users_approved: access_users_approved,
1107 access_default_role: access_default_role,
1108 google: google,
1109 google_clientid: google_clientid,
1110 google_clientsecret: google_clientsecret,
1111 google_hosteddomain: google_hosteddomain,
1112 cas: cas,
1113 cas_custom_label: cas_custom_label,
1114 cas_host: cas_host,
1115 cas_port: cas_port,
1116 cas_path: cas_path,
1117 cas_version: cas_version,
1118 cas_attr_email: cas_attr_email,
1119 cas_attr_first_name: cas_attr_first_name,
1120 cas_attr_last_name: cas_attr_last_name,
1121 cas_attr_update_on_login: cas_attr_update_on_login,
1122 cas_auto_login: cas_auto_login,
1123 ldap: ldap,
1124 ldap_host: ldap_host,
1125 ldap_port: ldap_port,
1126 ldap_search_base: ldap_search_base,
1127 ldap_uid: ldap_uid,
1128 ldap_attr_email: ldap_attr_email,
1129 ldap_user: ldap_user,
1130 ldap_password: ldap_password,
1131 ldap_tls: ldap_tls,
1132 ldap_lostpassword_url: ldap_lostpassword_url,
1133 ldap_attr_first_name: ldap_attr_first_name,
1134 ldap_attr_last_name: ldap_attr_last_name,
1135 ldap_attr_update_on_login: ldap_attr_update_on_login,
1136 advanced_lockouts: advanced_lockouts,
1137 advanced_hide_wp_login: advanced_hide_wp_login,
1138 advanced_users_per_page: advanced_users_per_page,
1139 advanced_users_sort_by: advanced_users_sort_by,
1140 advanced_users_sort_order: advanced_users_sort_order,
1141 advanced_widget_enabled: advanced_widget_enabled,
1142 }, function( response ) {
1143 var succeeded = response === 'success';
1144 var spinnerText = succeeded ? authL10n.saved + '.' : '<span style="color: red;">' + authL10n.failed + '.</span>';
1145 var spinnerWait = succeeded ? 500 : 2000;
1146 $( 'form .spinner:not(:has(.spinner-text))' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
1147 $( this ).remove();
1148 });
1149 $( caller ).removeAttr( 'disabled' );
1150
1151 // Disable wait cursor.
1152 $( 'html' ).removeClass( 'busy' );
1153 }).fail( function() {
1154 // Fail fires if the server doesn't respond
1155 var succeeded = false;
1156 var spinnerText = succeeded ? authL10n.saved + '.' : '<span style="color: red;">' + authL10n.failed + '.</span>';
1157 var spinnerWait = succeeded ? 500 : 2000;
1158 $( 'form .spinner:not(:has(.spinner-text))' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
1159 $( this ).remove();
1160 });
1161 $( caller ).removeAttr( 'disabled' );
1162
1163 // Disable wait cursor.
1164 $( 'html' ).removeClass( 'busy' );
1165 });
1166 };
1167 /* eslint-enable camelcase */
1168
1169 /* ========================================================================
1170 * Portions below from Bootstrap.
1171 * ========================================================================
1172 * Bootstrap: dropdown.js v3.1.1
1173 * http://getbootstrap.com/javascript/#dropdowns
1174 * ========================================================================
1175 * Copyright 2011-2014 Twitter, Inc.
1176 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1177 * ======================================================================== */
1178
1179 // DROPDOWN CLASS DEFINITION
1180 // =========================
1181 var backdrop = '.dropdown-backdrop';
1182 var toggle = '[data-toggle=dropdown]';
1183 var Dropdown = function( element ) { // eslint-disable-line func-style
1184 $( element ).on( 'click.bs.dropdown', this.toggle );
1185 };
1186
1187 Dropdown.prototype.toggle = function( event ) {
1188 var $this = $( this );
1189
1190 if ( $this.is( '.disabled, :disabled' ) ) {
1191 return;
1192 }
1193
1194 var $parent = getParent( $this );
1195 var isActive = $parent.hasClass( 'open' );
1196
1197 clearMenus();
1198
1199 if ( ! isActive ) {
1200 if ( 'ontouchstart' in document.documentElement && ! $parent.closest( '.navbar-nav' ).length ) {
1201 // if mobile we use a backdrop because click events don't delegate
1202 $( '<div class="dropdown-backdrop"/>' ).insertAfter( $( this ) ).on( 'click', clearMenus );
1203 }
1204
1205 var relatedTarget = { relatedTarget: this };
1206 $parent.trigger( event = $.Event( 'show.bs.dropdown', relatedTarget ) );
1207
1208 if ( event.isDefaultPrevented() ) {
1209 return;
1210 }
1211
1212 $parent
1213 .toggleClass( 'open' )
1214 .trigger( 'shown.bs.dropdown', relatedTarget);
1215
1216 $this.focus();
1217 }
1218
1219 return false;
1220 };
1221
1222 Dropdown.prototype.keydown = function( event ) {
1223 if ( ! /(38|40|27)/.test( event.keyCode ) ) {
1224 return;
1225 }
1226
1227 var $this = $( this );
1228
1229 event.preventDefault();
1230 event.stopPropagation();
1231
1232 if ( $this.is( '.disabled, :disabled' ) ) {
1233 return;
1234 }
1235
1236 var $parent = getParent( $this );
1237 var isActive = $parent.hasClass( 'open' );
1238
1239 if ( ! isActive || ( isActive && event.keyCode === 27 ) ) {
1240 if ( event.which === 27 ) {
1241 $parent.find( toggle ).focus();
1242 }
1243 return $this.click();
1244 }
1245
1246 var desc = ' li:not(.divider):visible a';
1247 var $items = $parent.find( '[role=menu]' + desc + ', [role=listbox]' + desc);
1248
1249 if ( ! $items.length ) {
1250 return;
1251 }
1252
1253 var index = $items.index($items.filter( ':focus' ));
1254
1255 if ( event.keyCode === 38 && index > 0 ) {
1256 index--; // up
1257 }
1258 if ( event.keyCode === 40 && index < $items.length - 1 ) {
1259 index++; // down
1260 }
1261 if ( ! ~index ) {
1262 index = 0;
1263 }
1264
1265 $items.eq(index).focus();
1266 };
1267
1268 function clearMenus( event ) {
1269 $(backdrop).remove();
1270 $(toggle).each( function() {
1271 var $parent = getParent($( this ));
1272 var relatedTarget = { relatedTarget: this };
1273 if ( ! $parent.hasClass( 'open' ) ) {
1274 return;
1275 }
1276 $parent.trigger( event = $.Event( 'hide.bs.dropdown', relatedTarget ) );
1277 if ( event.isDefaultPrevented() ) {
1278 return;
1279 }
1280 $parent.removeClass( 'open' ).trigger( 'hidden.bs.dropdown', relatedTarget);
1281 });
1282 }
1283
1284 function getParent( $this ) {
1285 var selector = $this.attr( 'data-target' );
1286
1287 if ( ! selector ) {
1288 selector = $this.attr( 'href' );
1289 selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '' ); // strip for ie7
1290 }
1291
1292 var $parent = selector && $(selector);
1293
1294 return $parent && $parent.length ? $parent : $this.parent();
1295 }
1296
1297 // DROPDOWN PLUGIN DEFINITION
1298 // ==========================
1299 var old = $.fn.dropdown;
1300 $.fn.dropdown = function( option ) {
1301 return this.each( function() {
1302 var $this = $( this );
1303 var data = $this.data( 'bs.dropdown' );
1304
1305 if ( ! data ) {
1306 $this.data( 'bs.dropdown', ( data = new Dropdown( this ) ) );
1307 }
1308 if ( 'string' === typeof option ) {
1309 data[option].call( $this );
1310 }
1311 });
1312 };
1313 $.fn.dropdown.Constructor = Dropdown;
1314
1315 // DROPDOWN NO CONFLICT
1316 // ====================
1317 $.fn.dropdown.noConflict = function() {
1318 $.fn.dropdown = old;
1319 return this;
1320 };
1321
1322 // APPLY TO STANDARD DROPDOWN ELEMENTS
1323 // ===================================
1324 $(document)
1325 .on( 'click.bs.dropdown.data-api', clearMenus)
1326 .on( 'click.bs.dropdown.data-api', '.dropdown form', function( event ) { event.stopPropagation(); })
1327 .on( 'click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
1328 .on( 'keydown.bs.dropdown.data-api', toggle + ', [role=menu], [role=listbox]', Dropdown.prototype.keydown);
1329
1330 } )( jQuery );
1331