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