PluginProbe
Authorizer / 2.9.10
Authorizer v2.9.10
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.10, at js/authorizer.js

1,363 lines 59.0 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 localIcon = shouldCreateLocalAccount ? '&nbsp;<a title="' + authL10n.local_wordpress_user + '" class="auth-local-user"><span class="glyphicon glyphicon-user"></span></a>' : '';
929 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>' : '';
930 $( ' \
931 <li id="new_user_' + nextId + '" class="new-user" style="display: none;"> \
932 <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" /> \
933 <select name="auth_settings[access_users_' + list + '][' + nextId + '][role]" class="auth-role" onchange="' + authJsPrefix + 'ChangeRole( this );"> \
934 </select> \
935 <input type="text" name="auth_settings[access_users_' + list + '][' + nextId + '][date_added]" value="' + getShortDate() + '" readonly="true" class="auth-date-added" /> \
936 ' + banButton + ' \
937 <a class="button" id="ignore_user_' + nextId + '" onclick="' + authJsPrefix + 'IgnoreUser( this, \'' + list + '\' );" title="' + authL10n.remove_user + '"><span class="glyphicon glyphicon-remove"></span></a> \
938 ' + localIcon + ' \
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_widget_enabled = $( '#auth_settings_advanced_widget_enabled' ).is( ':checked' ) ? '1' : '';
1106 var advanced_users_per_page = $( '#auth_settings_advanced_users_per_page' ).val();
1107 var advanced_users_sort_by = $( '#auth_settings_advanced_users_sort_by' ).val();
1108 var advanced_users_sort_order = $( '#auth_settings_advanced_users_sort_order' ).val();
1109
1110 $.post( ajaxurl, {
1111 action: 'save_auth_multisite_settings',
1112 nonce: nonce_save_auth_settings,
1113 multisite_override: multisite_override,
1114 access_who_can_login: access_who_can_login,
1115 access_who_can_view: access_who_can_view,
1116 access_users_approved: access_users_approved,
1117 access_default_role: access_default_role,
1118 google: google,
1119 google_clientid: google_clientid,
1120 google_clientsecret: google_clientsecret,
1121 google_hosteddomain: google_hosteddomain,
1122 cas: cas,
1123 cas_custom_label: cas_custom_label,
1124 cas_host: cas_host,
1125 cas_port: cas_port,
1126 cas_path: cas_path,
1127 cas_version: cas_version,
1128 cas_attr_email: cas_attr_email,
1129 cas_attr_first_name: cas_attr_first_name,
1130 cas_attr_last_name: cas_attr_last_name,
1131 cas_attr_update_on_login: cas_attr_update_on_login,
1132 cas_auto_login: cas_auto_login,
1133 cas_link_on_username: cas_link_on_username,
1134 ldap: ldap,
1135 ldap_host: ldap_host,
1136 ldap_port: ldap_port,
1137 ldap_search_base: ldap_search_base,
1138 ldap_uid: ldap_uid,
1139 ldap_attr_email: ldap_attr_email,
1140 ldap_user: ldap_user,
1141 ldap_password: ldap_password,
1142 ldap_tls: ldap_tls,
1143 ldap_lostpassword_url: ldap_lostpassword_url,
1144 ldap_attr_first_name: ldap_attr_first_name,
1145 ldap_attr_last_name: ldap_attr_last_name,
1146 ldap_attr_update_on_login: ldap_attr_update_on_login,
1147 advanced_lockouts: advanced_lockouts,
1148 advanced_hide_wp_login: advanced_hide_wp_login,
1149 advanced_users_per_page: advanced_users_per_page,
1150 advanced_users_sort_by: advanced_users_sort_by,
1151 advanced_users_sort_order: advanced_users_sort_order,
1152 advanced_widget_enabled: advanced_widget_enabled,
1153 }, function( response ) {
1154 var succeeded = response === 'success';
1155 var spinnerText = succeeded ? authL10n.saved + '.' : '<span class="attention">' + authL10n.failed + '.</span>';
1156 var spinnerWait = succeeded ? 500 : 2000;
1157 $( 'form .spinner:not(:has(.spinner-text))' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
1158 $( this ).remove();
1159 });
1160 $( caller ).removeAttr( 'disabled' );
1161
1162 // Disable wait cursor.
1163 $( 'html' ).removeClass( 'busy' );
1164 }).fail( function() {
1165 // Fail fires if the server doesn't respond
1166 var succeeded = false;
1167 var spinnerText = succeeded ? authL10n.saved + '.' : '<span class="attention">' + authL10n.failed + '.</span>';
1168 var spinnerWait = succeeded ? 500 : 2000;
1169 $( 'form .spinner:not(:has(.spinner-text))' ).append( '<span class="spinner-text">' + spinnerText + '</span>' ).delay( spinnerWait ).hide( animationSpeed, function() {
1170 $( this ).remove();
1171 });
1172 $( caller ).removeAttr( 'disabled' );
1173
1174 // Disable wait cursor.
1175 $( 'html' ).removeClass( 'busy' );
1176 });
1177 };
1178 /* eslint-enable camelcase */
1179
1180 // Fade in/out Authorizer logo in bottom right on Settings.
1181 $(document).on( 'scroll', function () {
1182 fadeLogo();
1183 });
1184
1185 function fadeLogo() {
1186 if ( getScrollPercent() < 90 ) {
1187 $( '#wpwrap' ).removeClass( 'not-faded' );
1188 } else {
1189 $( '#wpwrap' ).addClass( 'not-faded' );
1190 }
1191 }
1192
1193 function getScrollPercent() {
1194 var h = document.documentElement,
1195 b = document.body,
1196 st = 'scrollTop',
1197 sh = 'scrollHeight';
1198 return ( h[st] || b[st] ) / ( ( h[sh] || b[sh] ) - h.clientHeight ) * 100;
1199 }
1200
1201 /* ========================================================================
1202 * Portions below from Bootstrap.
1203 * ========================================================================
1204 * Bootstrap: dropdown.js v3.1.1
1205 * http://getbootstrap.com/javascript/#dropdowns
1206 * ========================================================================
1207 * Copyright 2011-2014 Twitter, Inc.
1208 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1209 * ======================================================================== */
1210
1211 // DROPDOWN CLASS DEFINITION
1212 // =========================
1213 var backdrop = '.dropdown-backdrop';
1214 var toggle = '[data-toggle=dropdown]';
1215 var Dropdown = function( element ) { // eslint-disable-line func-style
1216 $( element ).on( 'click.bs.dropdown', this.toggle );
1217 };
1218
1219 Dropdown.prototype.toggle = function( event ) {
1220 var $this = $( this );
1221
1222 if ( $this.is( '.disabled, :disabled' ) ) {
1223 return;
1224 }
1225
1226 var $parent = getParent( $this );
1227 var isActive = $parent.hasClass( 'open' );
1228
1229 clearMenus();
1230
1231 if ( ! isActive ) {
1232 if ( 'ontouchstart' in document.documentElement && ! $parent.closest( '.navbar-nav' ).length ) {
1233 // if mobile we use a backdrop because click events don't delegate
1234 $( '<div class="dropdown-backdrop"/>' ).insertAfter( $( this ) ).on( 'click', clearMenus );
1235 }
1236
1237 var relatedTarget = { relatedTarget: this };
1238 $parent.trigger( event = $.Event( 'show.bs.dropdown', relatedTarget ) );
1239
1240 if ( event.isDefaultPrevented() ) {
1241 return;
1242 }
1243
1244 $parent
1245 .toggleClass( 'open' )
1246 .trigger( 'shown.bs.dropdown', relatedTarget);
1247
1248 $this.focus();
1249 }
1250
1251 return false;
1252 };
1253
1254 Dropdown.prototype.keydown = function( event ) {
1255 if ( ! /(38|40|27)/.test( event.keyCode ) ) {
1256 return;
1257 }
1258
1259 var $this = $( this );
1260
1261 event.preventDefault();
1262 event.stopPropagation();
1263
1264 if ( $this.is( '.disabled, :disabled' ) ) {
1265 return;
1266 }
1267
1268 var $parent = getParent( $this );
1269 var isActive = $parent.hasClass( 'open' );
1270
1271 if ( ! isActive || ( isActive && event.keyCode === 27 ) ) {
1272 if ( event.which === 27 ) {
1273 $parent.find( toggle ).focus();
1274 }
1275 return $this.click();
1276 }
1277
1278 var desc = ' li:not(.divider):visible a';
1279 var $items = $parent.find( '[role=menu]' + desc + ', [role=listbox]' + desc);
1280
1281 if ( ! $items.length ) {
1282 return;
1283 }
1284
1285 var index = $items.index($items.filter( ':focus' ));
1286
1287 if ( event.keyCode === 38 && index > 0 ) {
1288 index--; // up
1289 }
1290 if ( event.keyCode === 40 && index < $items.length - 1 ) {
1291 index++; // down
1292 }
1293 if ( ! ~index ) {
1294 index = 0;
1295 }
1296
1297 $items.eq(index).focus();
1298 };
1299
1300 function clearMenus( event ) {
1301 $(backdrop).remove();
1302 $(toggle).each( function() {
1303 var $parent = getParent($( this ));
1304 var relatedTarget = { relatedTarget: this };
1305 if ( ! $parent.hasClass( 'open' ) ) {
1306 return;
1307 }
1308 $parent.trigger( event = $.Event( 'hide.bs.dropdown', relatedTarget ) );
1309 if ( event.isDefaultPrevented() ) {
1310 return;
1311 }
1312 $parent.removeClass( 'open' ).trigger( 'hidden.bs.dropdown', relatedTarget);
1313 });
1314 }
1315
1316 function getParent( $this ) {
1317 var selector = $this.attr( 'data-target' );
1318
1319 if ( ! selector ) {
1320 selector = $this.attr( 'href' );
1321 selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '' ); // strip for ie7
1322 }
1323
1324 var $parent = selector && $(selector);
1325
1326 return $parent && $parent.length ? $parent : $this.parent();
1327 }
1328
1329 // DROPDOWN PLUGIN DEFINITION
1330 // ==========================
1331 var old = $.fn.dropdown;
1332 $.fn.dropdown = function( option ) {
1333 return this.each( function() {
1334 var $this = $( this );
1335 var data = $this.data( 'bs.dropdown' );
1336
1337 if ( ! data ) {
1338 $this.data( 'bs.dropdown', ( data = new Dropdown( this ) ) );
1339 }
1340 if ( 'string' === typeof option ) {
1341 data[option].call( $this );
1342 }
1343 });
1344 };
1345 $.fn.dropdown.Constructor = Dropdown;
1346
1347 // DROPDOWN NO CONFLICT
1348 // ====================
1349 $.fn.dropdown.noConflict = function() {
1350 $.fn.dropdown = old;
1351 return this;
1352 };
1353
1354 // APPLY TO STANDARD DROPDOWN ELEMENTS
1355 // ===================================
1356 $(document)
1357 .on( 'click.bs.dropdown.data-api', clearMenus)
1358 .on( 'click.bs.dropdown.data-api', '.dropdown form', function( event ) { event.stopPropagation(); })
1359 .on( 'click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
1360 .on( 'keydown.bs.dropdown.data-api', toggle + ', [role=menu], [role=listbox]', Dropdown.prototype.keydown);
1361
1362 } )( jQuery );
1363