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