/** * UI wiring for Authorizer Settings page. */ /* global window, document, setTimeout, sessionStorage, ajaxurl, authL10n, history */ ( function( $ ) { // Milliseconds for jQuery UI animations to complete. var animationSpeed = 300; // Milliseconds for shake animation (reject email address) to complete. var shakeSpeed = 600; /** * Wiring and UI for Authorizer Settings page. */ // Switch between pages in the Approved User list. // @calls php wp_ajax_refresh_approved_user_list. function refreshApprovedUserList( currentPage, searchTerm ) { var $list = $( '#list_auth_settings_access_users_approved' ); var $spinner = $( '' ).css({ position: 'relative', top: '40%', left: '-240px', }); var $overlay = $( '
' ).css({ 'background-color': '#f1f1f1', 'z-index': 1, opacity: 0.8, position: 'absolute', top: $list.position().top + parseInt( $list.css( 'margin-top' ) ), left: $list.position().left, width: $list.width(), height: $list.height(), }); $overlay.append( $spinner ); // Show overlay and wait cursor. $list.after( $overlay ); $( 'html' ).addClass( 'busy' ); $.post( ajaxurl, { action: 'refresh_approved_user_list', nonce: $( '#nonce_save_auth_settings' ).val(), is_network_admin: authL10n.is_network_admin, // eslint-disable-line camelcase paged: currentPage, search: searchTerm, }, function( response ) { if ( response.success ) { // Update user list and total user and page count. $( '#list_auth_settings_access_users_approved' ).html( response.html ); $( '.displaying-num' ).html( response.total_users_html ); $( '.total-pages' ).html( response.total_pages_html ); // Adjust our current page if the query changed the total page count. if ( currentPage > response.total_pages ) { currentPage = response.total_pages; } // Update pager elements. refreshApprovedUserPager( currentPage ); // Update querystring with new paged param value (but don't reload the page). if ( history.pushState ) { var url = window.location.href; url = updateQueryStringParameter( url, 'paged', currentPage ); url = updateQueryStringParameter( url, 'search', searchTerm ); window.history.pushState( { path: url }, '', url ); } } // Remove overlay and wait cursor. $overlay.remove(); $( 'html' ).removeClass( 'busy' ); }).fail( function() { // Remove overlay and wait cursor. $overlay.remove(); $( 'html' ).removeClass( 'busy' ); }); } // Update the pager elements when changing pages. function refreshApprovedUserPager( currentPage ) { var totalPages = parseInt( $( '.total-pages' ).first().text().replace( /[^0-9]/g, '' ), 10 ) || 1; // If total number of pages changed (because a search filter reduced it), make // sure current page is not larger than it. if ( currentPage > totalPages ) { currentPage = totalPages; } if ( currentPage < 1 ) { currentPage = 1; } if ( totalPages < 1 ) { totalPages = 1; } // Update current page text input. $( '#current-page-selector' ).val( currentPage ); // Update current page span. $( '#table-paging .current-page-text' ).text( currentPage ); // Update first page button. var $first = $( '.first-page' ); if ( $first.is( 'a' ) && currentPage <= 1 ) { $first.replaceWith( '' ); } else if ( $first.is( 'span' ) && currentPage > 1 ) { $first.replaceWith( '' + authL10n.first_page + '' ); } // Update prev page button. var $prev = $( '.prev-page' ); if ( $prev.is( 'a' ) && currentPage <= 1 ) { $prev.replaceWith( '' ); } else if ( currentPage > 1 ) { $prev.replaceWith( '' + authL10n.prev_page + '' ); } // Update next button. var $next = $( '.next-page' ); if ( $next.is( 'a' ) && currentPage >= totalPages ) { $next.replaceWith( '' ); } else if ( currentPage < totalPages ) { $next.replaceWith( '' + authL10n.next_page + '' ); } // Update last button. var $last = $( '.last-page' ); if ( $last.is( 'a' ) && currentPage >= totalPages ) { $last.replaceWith( '' ); } else if ( $last.is( 'span' ) && currentPage < totalPages ) { $last.replaceWith( '' + authL10n.next_page + '' ); } } // Make changes to one of the user lists (pending, approved, blocked) via ajax. // @calls php wp_ajax_update_auth_user. function updateAuthUser( caller, setting, usersToEdit ) { var accessUsersPending = [], accessUsersApproved = [], accessUsersBlocked = [], nonce = $( '#nonce_save_auth_settings' ).val(); // Defaults: // setting = 'access_users_pending' or 'access_users_approved' or 'access_users_blocked', // usersToEdit = [ // { // email: 'johndoe@example.com', // role: 'subscriber', // date_added: 'Jun 2014', // edit_action: 'add' or 'remove' or 'change_role', // local_user: true or false, // multisite_user: true or false, // }, { // ... // } // ] setting = typeof setting !== 'undefined' ? setting : 'none'; // If we are only editing a single user, make that user the only item in the array. usersToEdit = typeof usersToEdit !== 'undefined' ? usersToEdit : []; if ( ! Array.isArray( usersToEdit ) ) { usersToEdit = [ usersToEdit ]; } // Enable wait cursor. $( 'html' ).addClass( 'busy' ); // Disable button (prevent duplicate clicks). $( caller ).attr( 'disabled', 'disabled' ); // Enable spinner by element that triggered this event (caller). var $row = $( caller ).closest( 'li' ); if ( $row.length > 0 ) { var $spinner = $( '' ).css({ position: 'absolute', top: $row.position().top, left: $row.position().left + $row.width(), }); $row.append( $spinner ); } // Grab the value of the setting we are saving. if ( setting === 'access_users_pending' ) { accessUsersPending = usersToEdit; } else if ( setting === 'access_users_approved' ) { accessUsersApproved = usersToEdit; } else if ( setting === 'access_users_blocked' ) { accessUsersBlocked = usersToEdit; } $.post( ajaxurl, { action: 'update_auth_user', setting: setting, access_users_pending: accessUsersPending, // eslint-disable-line camelcase access_users_approved: accessUsersApproved, // eslint-disable-line camelcase access_users_blocked: accessUsersBlocked, // eslint-disable-line camelcase nonce: nonce, }, function( response ) { // Server responded, but if success isn't true it failed to save. var succeeded = response.success; var spinnerText = succeeded ? authL10n.saved + '.' : '' + authL10n.failed + '.'; var spinnerWait = succeeded ? 500 : 2000; // Remove any new user entries that were rejected by the server. if ( response.invalid_emails.length > 0 ) { for ( var i = 0; i < response.invalid_emails.length; i++ ) { var duplicateEmail = response.invalid_emails[i]; $( 'li.new-user .auth-email[value="' + duplicateEmail + '"]' ) .siblings( '.spinner' ).addClass( 'duplicate' ).append( '' + authL10n.duplicate + '.' ) .parent().fadeOut( spinnerWait, function() { $( this ).remove(); }); // jshint ignore:line } } // Show message ('Saved', 'Failed', or 'Saved, removing duplicates'). $( 'form .spinner:not(:has(.spinner-text)):not(.duplicate)' ).append( '' + spinnerText + '' ).delay( spinnerWait ).hide( animationSpeed, function() { $( this ).remove(); }); $( caller ).removeAttr( 'disabled' ); // Disable wait cursor. $( 'html' ).removeClass( 'busy' ); }).fail( function() { // Fail fires if the server doesn't respond or responds with 500 codes var succeeded = false; var spinnerText = succeeded ? authL10n.saved + '.' : '' + authL10n.failed + '.'; var spinnerWait = succeeded ? 500 : 2000; $( 'form .spinner:not(:has(.spinner-text))' ).append( '' + spinnerText + '' ).delay( spinnerWait ).hide( animationSpeed, function() { $( this ).remove(); }); $( caller ).removeAttr( 'disabled' ); // Disable wait cursor. $( 'html' ).removeClass( 'busy' ); }); } // Hide or show (with overlay) the multisite settings based on the "multisite override" setting. function hideMultisiteSettingsIfDisabled() { if ( $( '#auth_settings_multisite_override' ).length === 0 ) { return; } var settings = $( '#auth_multisite_settings' ); var overlay = $( '#auth_multisite_settings_disabled_overlay' ); if ( $( '#auth_settings_multisite_override' ).is( ':checked' ) ) { overlay.hide( animationSpeed ); } else { overlay.css({ 'background-color': '#f1f1f1', 'z-index': 1, opacity: 0.8, position: 'absolute', top: settings.position().top + 46, left: settings.position().left - 20, width: '100%', height: settings.height() + 20, 'padding-left': 20, }); overlay.show(); } } // Helper function to remove duplicate entries from an array of strings. function removeDuplicatesFromArrayOfStrings( arrayOfStrings ) { var seen = {}; return arrayOfStrings.filter( function( item ) { return seen.hasOwnProperty( item ) ? false : ( seen[item] = true ); }); } // Helper function to hide/show wordpress option function animateOption( action, option ) { if ( action === 'show' ) { $( 'div.animated_wrapper', option ).slideDown( animationSpeed ); $( 'th', option ).animate({ padding: '20px 10px 20px 0' }, { duration: animationSpeed }); $( 'td', option ).animate({ padding: '15px 10px' }, { duration: animationSpeed }); } else if ( action === 'hide' ) { $( 'div.animated_wrapper', option ).slideUp( animationSpeed ); $( 'td, th', option ).animate({ padding: '0px' }, { duration: animationSpeed }); } else if ( action === 'hide_immediately' ) { $( 'div.animated_wrapper', option ).hide(); $( 'td, th', option ).css({ padding: '0px' }); } } // Helper function to grab a querystring param value by name function getParameterByName( needle, haystack ) { needle = needle.replace( /[\[]/, '\\\[').replace(/[\]]/, '\\\]' ); // eslint-disable-line no-useless-escape var regex = new RegExp( '[\\?&]' + needle + '=([^&#]*)' ); var results = regex.exec( haystack ); if ( results === null ) { return ''; } else { return decodeURIComponent( results[1].replace( /\+/g, ' ' ) ); } } // Helper function to return a short date (e.g., Jul 2013) for today's date function getShortDate( date ) { date = typeof date !== 'undefined' ? date : new Date(); var month = ''; switch ( date.getMonth() ) { case 0: month = 'Jan'; break; case 1: month = 'Feb'; break; case 2: month = 'Mar'; break; case 3: month = 'Apr'; break; case 4: month = 'May'; break; case 5: month = 'Jun'; break; case 6: month = 'Jul'; break; case 7: month = 'Aug'; break; case 8: month = 'Sep'; break; case 9: month = 'Oct'; break; case 10: month = 'Nov'; break; case 11: month = 'Dec'; break; } return month + ' ' + date.getFullYear(); } // Helper function to grab a querystring value function getQuerystringValuesByKey( key ) { var re = new RegExp( '(?:\\?|&)' + key + '=(.*?)(?=&|$)', 'gi' ); var matchingValues = []; var match; while ( ( match = re.exec( document.location.search ) ) !== null ) { matchingValues.push( match[1] ); } return matchingValues; } // Helper function to check if an email address is valid. If allowWildcardEmail // is true, then any string starting with an @ is valid. function validEmail( email, allowWildcardEmail ) { allowWildcardEmail = typeof allowWildcardEmail !== 'undefined' ? allowWildcardEmail : false; 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,}))$/; return email.length > 0 && ( re.test( email ) || email.startsWith( '@' ) ); } // Helper function to set or update a querystring value. function updateQueryStringParameter( uri, key, value ) { // Remove the hash before operating on the URI. var i = uri.indexOf( '#' ); var hash = i === -1 ? '' : uri.substr( i ); uri = i === -1 ? uri : uri.substr( 0, i ); var re = new RegExp( '([?&])' + key + '=.*?(&|$)', 'i' ); var separator = uri.indexOf( '?' ) !== -1 ? '&' : '?'; if ( ! value ) { // Remove key-value pair if empty. uri = uri.replace( new RegExp( '([?&]?)' + key + '=[^&]*', 'i' ), '' ); if ( uri.slice( -1 ) === '?' ) { uri = uri.slice( 0, -1 ); } // Replace first occurrence of & by ? if no ? is present. if ( uri.indexOf( '?' ) === -1 ) { uri = uri.replace( /&/, '?' ); } } else if ( uri.match( re ) ) { uri = uri.replace( re, '$1' + key + '=' + value + '$2' ); } else { uri = uri + separator + key + '=' + value; } return uri + hash; } /** * Wire up actions when document has loaded. */ $( document ).ready( function() { // Grab references to form elements that we will show/hide on page load /* eslint-disable camelcase */ var auth_settings_access_role_receive_pending_emails = $( '#auth_settings_access_role_receive_pending_emails' ).closest( 'tr' ); var auth_settings_access_pending_redirect_to_message = $( '#wp-auth_settings_access_pending_redirect_to_message-wrap' ).closest( 'tr' ); var auth_settings_access_blocked_redirect_to_message = $( '#wp-auth_settings_access_blocked_redirect_to_message-wrap' ).closest( 'tr' ); var auth_settings_access_should_email_approved_users = $( '#auth_settings_access_should_email_approved_users' ).closest( 'tr' ); var auth_settings_access_email_approved_users_subject = $( '#auth_settings_access_email_approved_users_subject' ).closest( 'tr' ); var auth_settings_access_email_approved_users_body = $( '#wp-auth_settings_access_email_approved_users_body-wrap' ).closest( 'tr' ); var auth_settings_access_public_pages = $( '#auth_settings_access_public_pages' ).closest( 'tr' ); var auth_settings_access_redirect_to_login = $( '#radio_auth_settings_access_redirect_to_login' ).closest( 'tr' ); var auth_settings_access_public_warning = $( '#radio_auth_settings_access_public_warning' ).closest( 'tr' ); var auth_settings_access_redirect_to_message = $( '#wp-auth_settings_access_redirect_to_message-wrap' ).closest( 'tr' ); var auth_settings_external_google_clientid = $( '#auth_settings_google_clientid' ).closest( 'tr' ); var auth_settings_external_google_clientsecret = $( '#auth_settings_google_clientsecret' ).closest( 'tr' ); var auth_settings_external_google_hosteddomain = $( '#auth_settings_google_hosteddomain' ).closest( 'tr' ); var auth_settings_external_cas_custom_label = $( '#auth_settings_cas_custom_label' ).closest( 'tr' ); var auth_settings_external_cas_host = $( '#auth_settings_cas_host' ).closest( 'tr' ); var auth_settings_external_cas_port = $( '#auth_settings_cas_port' ).closest( 'tr' ); var auth_settings_external_cas_path = $( '#auth_settings_cas_path' ).closest( 'tr' ); var auth_settings_external_cas_version = $( '#auth_settings_cas_version' ).closest( 'tr' ); var auth_settings_external_cas_attr_email = $( '#auth_settings_cas_attr_email' ).closest( 'tr' ); var auth_settings_external_cas_attr_first_name = $( '#auth_settings_cas_attr_first_name' ).closest( 'tr' ); var auth_settings_external_cas_attr_last_name = $( '#auth_settings_cas_attr_last_name' ).closest( 'tr' ); var auth_settings_external_cas_attr_update_on_login = $( '#auth_settings_cas_attr_update_on_login' ).closest( 'tr' ); var auth_settings_external_cas_auto_login = $( '#auth_settings_cas_auto_login' ).closest( 'tr' ); var auth_settings_external_cas_link_on_username = $( '#auth_settings_cas_link_on_username' ).closest( 'tr' ); var auth_settings_external_ldap_host = $( '#auth_settings_ldap_host' ).closest( 'tr' ); var auth_settings_external_ldap_port = $( '#auth_settings_ldap_port' ).closest( 'tr' ); var auth_settings_external_ldap_search_base = $( '#auth_settings_ldap_search_base' ).closest( 'tr' ); var auth_settings_external_ldap_uid = $( '#auth_settings_ldap_uid' ).closest( 'tr' ); var auth_settings_external_ldap_attr_email = $( '#auth_settings_ldap_attr_email' ).closest( 'tr' ); var auth_settings_external_ldap_user = $( '#auth_settings_ldap_user' ).closest( 'tr' ); var auth_settings_external_ldap_password = $( '#auth_settings_ldap_password' ).closest( 'tr' ); var auth_settings_external_ldap_tls = $( '#auth_settings_ldap_tls' ).closest( 'tr' ); var auth_settings_external_ldap_lostpassword_url = $( '#auth_settings_ldap_lostpassword_url' ).closest( 'tr' ); var auth_settings_external_ldap_attr_first_name = $( '#auth_settings_ldap_attr_first_name' ).closest( 'tr' ); var auth_settings_external_ldap_attr_last_name = $( '#auth_settings_ldap_attr_last_name' ).closest( 'tr' ); var auth_settings_external_ldap_attr_update_on_login = $( '#auth_settings_ldap_attr_update_on_login' ).closest( 'tr' ); /* eslint-enable */ // Wrap the th and td in the rows above so we can animate their heights (can't animate tr heights with jquery) $( 'th, td', auth_settings_access_role_receive_pending_emails ).wrapInner( '
' ); $( 'th, td', auth_settings_access_pending_redirect_to_message ).wrapInner( '
' ); $( 'th, td', auth_settings_access_blocked_redirect_to_message ).wrapInner( '
' ); $( 'th, td', auth_settings_access_should_email_approved_users ).wrapInner( '
' ); $( 'th, td', auth_settings_access_email_approved_users_subject ).wrapInner( '
' ); $( 'th, td', auth_settings_access_email_approved_users_body ).wrapInner( '
' ); $( 'th, td', auth_settings_access_public_pages ).wrapInner( '
' ); $( 'th, td', auth_settings_access_redirect_to_login ).wrapInner( '
' ); $( 'th, td', auth_settings_access_public_warning ).wrapInner( '
' ); $( 'th, td', auth_settings_access_redirect_to_message ).wrapInner( '
' ); $( 'th, td', auth_settings_external_google_clientid ).wrapInner( '
' ); $( 'th, td', auth_settings_external_google_clientsecret ).wrapInner( '
' ); $( 'th, td', auth_settings_external_google_hosteddomain ).wrapInner( '
' ); $( 'th, td', auth_settings_external_cas_custom_label ).wrapInner( '
' ); $( 'th, td', auth_settings_external_cas_host ).wrapInner( '
' ); $( 'th, td', auth_settings_external_cas_port ).wrapInner( '
' ); $( 'th, td', auth_settings_external_cas_path ).wrapInner( '
' ); $( 'th, td', auth_settings_external_cas_version ).wrapInner( '
' ); $( 'th, td', auth_settings_external_cas_attr_email ).wrapInner( '
' ); $( 'th, td', auth_settings_external_cas_attr_first_name ).wrapInner( '
' ); $( 'th, td', auth_settings_external_cas_attr_last_name ).wrapInner( '
' ); $( 'th, td', auth_settings_external_cas_attr_update_on_login ).wrapInner( '
' ); $( 'th, td', auth_settings_external_cas_auto_login ).wrapInner( '
' ); $( 'th, td', auth_settings_external_cas_link_on_username ).wrapInner( '
' ); $( 'th, td', auth_settings_external_ldap_host ).wrapInner( '
' ); $( 'th, td', auth_settings_external_ldap_port ).wrapInner( '
' ); $( 'th, td', auth_settings_external_ldap_search_base ).wrapInner( '
' ); $( 'th, td', auth_settings_external_ldap_uid ).wrapInner( '
' ); $( 'th, td', auth_settings_external_ldap_attr_email ).wrapInner( '
' ); $( 'th, td', auth_settings_external_ldap_user ).wrapInner( '
' ); $( 'th, td', auth_settings_external_ldap_password ).wrapInner( '
' ); $( 'th, td', auth_settings_external_ldap_tls ).wrapInner( '
' ); $( 'th, td', auth_settings_external_ldap_lostpassword_url ).wrapInner( '
' ); $( 'th, td', auth_settings_external_ldap_attr_first_name ).wrapInner( '
' ); $( 'th, td', auth_settings_external_ldap_attr_last_name ).wrapInner( '
' ); $( 'th, td', auth_settings_external_ldap_attr_update_on_login ).wrapInner( '
' ); // If we're viewing the dashboard widget, reset a couple of the relevant // option variables (since they aren't nested in table rows). if ( $( '#auth_dashboard_widget' ).length ) { // Remove the helper link, since there are no tabs on the dashboard widget $( '#dashboard_link_approved_users' ).contents().unwrap(); } // Hide settings unless "Only approved users" is checked if ( ! $( '#radio_auth_settings_access_who_can_login_approved_users' ).is( ':checked' ) ) { animateOption( 'hide_immediately', auth_settings_access_role_receive_pending_emails ); animateOption( 'hide_immediately', auth_settings_access_pending_redirect_to_message ); animateOption( 'hide_immediately', auth_settings_access_blocked_redirect_to_message ); animateOption( 'hide_immediately', auth_settings_access_should_email_approved_users ); } // Hide Welcome email body/subject options if "Send welcome email" is off. if ( ! $( '#auth_settings_access_should_email_approved_users' ).is( ':checked' ) ) { animateOption( 'hide_immediately', auth_settings_access_email_approved_users_subject ); animateOption( 'hide_immediately', auth_settings_access_email_approved_users_body ); } // On load: Show/hide public access options if everyone can see site if ( ! $( '#radio_auth_settings_access_who_can_view_logged_in_users' ).is( ':checked' ) ) { animateOption( 'hide_immediately', auth_settings_access_public_pages ); animateOption( 'hide_immediately', auth_settings_access_redirect_to_login ); animateOption( 'hide_immediately', auth_settings_access_public_warning ); animateOption( 'hide_immediately', auth_settings_access_redirect_to_message ); } // Hide Google options if unchecked if ( ! $( '#auth_settings_google' ).is( ':checked' ) ) { animateOption( 'hide_immediately', auth_settings_external_google_clientid ); animateOption( 'hide_immediately', auth_settings_external_google_clientsecret ); animateOption( 'hide_immediately', auth_settings_external_google_hosteddomain ); } // Hide CAS options if unchecked if ( ! $( '#auth_settings_cas' ).is( ':checked' ) ) { animateOption( 'hide_immediately', auth_settings_external_cas_custom_label ); animateOption( 'hide_immediately', auth_settings_external_cas_host ); animateOption( 'hide_immediately', auth_settings_external_cas_port ); animateOption( 'hide_immediately', auth_settings_external_cas_path ); animateOption( 'hide_immediately', auth_settings_external_cas_version ); animateOption( 'hide_immediately', auth_settings_external_cas_attr_email ); animateOption( 'hide_immediately', auth_settings_external_cas_attr_first_name ); animateOption( 'hide_immediately', auth_settings_external_cas_attr_last_name ); animateOption( 'hide_immediately', auth_settings_external_cas_attr_update_on_login ); animateOption( 'hide_immediately', auth_settings_external_cas_auto_login ); animateOption( 'hide_immediately', auth_settings_external_cas_link_on_username ); } // Hide LDAP options if unchecked if ( ! $( '#auth_settings_ldap' ).is( ':checked' ) ) { animateOption( 'hide_immediately', auth_settings_external_ldap_host ); animateOption( 'hide_immediately', auth_settings_external_ldap_port ); animateOption( 'hide_immediately', auth_settings_external_ldap_search_base ); animateOption( 'hide_immediately', auth_settings_external_ldap_uid ); animateOption( 'hide_immediately', auth_settings_external_ldap_attr_email ); animateOption( 'hide_immediately', auth_settings_external_ldap_user ); animateOption( 'hide_immediately', auth_settings_external_ldap_password ); animateOption( 'hide_immediately', auth_settings_external_ldap_tls ); animateOption( 'hide_immediately', auth_settings_external_ldap_lostpassword_url ); animateOption( 'hide_immediately', auth_settings_external_ldap_attr_first_name ); animateOption( 'hide_immediately', auth_settings_external_ldap_attr_last_name ); animateOption( 'hide_immediately', auth_settings_external_ldap_attr_update_on_login ); } // Event handler: Hide "Handle unauthorized visitors" option if access is granted to "Everyone" $( 'input[name="auth_settings[access_who_can_login]"]' ).change( function() { // Hide settings unless "Only approved users" is checked var action = $( '#radio_auth_settings_access_who_can_login_approved_users' ).is( ':checked' ) ? 'show' : 'hide'; animateOption( action, auth_settings_access_role_receive_pending_emails ); animateOption( action, auth_settings_access_pending_redirect_to_message ); animateOption( action, auth_settings_access_blocked_redirect_to_message ); animateOption( action, auth_settings_access_should_email_approved_users ); action = action === 'show' && $( '#auth_settings_access_should_email_approved_users' ).is( ':checked' ) ? 'show' : 'hide_immediately'; animateOption( action, auth_settings_access_email_approved_users_subject ); animateOption( action, auth_settings_access_email_approved_users_body ); }); // Event handler: Hide Welcome email body/subject options if "Send welcome email" is off. $( 'input[name="auth_settings[access_should_email_approved_users]"]' ).change( function() { var action = $( this ).is( ':checked' ) ? 'show' : 'hide'; animateOption( action, auth_settings_access_email_approved_users_subject ); animateOption( action, auth_settings_access_email_approved_users_body ); }); // Event handler: Hide "Handle unauthorized visitors" option if access is granted to "Everyone" $( 'input[name="auth_settings[access_who_can_view]"]' ).change( function() { var action = $( '#radio_auth_settings_access_who_can_view_everyone' ).is( ':checked' ) ? 'hide' : 'show'; animateOption( action, auth_settings_access_redirect_to_login ); animateOption( action, auth_settings_access_redirect_to_message ); animateOption( action, auth_settings_access_public_pages ); animateOption( action, auth_settings_access_public_warning ); }); // Event handler: Show/hide Google options based on checkbox $( 'input[name="auth_settings[google]"]' ).change( function() { var action = $( this ).is( ':checked' ) ? 'show' : 'hide'; animateOption( action, auth_settings_external_google_clientid ); animateOption( action, auth_settings_external_google_clientsecret ); animateOption( action, auth_settings_external_google_hosteddomain ); }); // Event handler: Show/hide CAS options based on checkbox $( 'input[name="auth_settings[cas]"]' ).change( function() { var action = $( this ).is( ':checked' ) ? 'show' : 'hide'; animateOption( action, auth_settings_external_cas_custom_label ); animateOption( action, auth_settings_external_cas_host ); animateOption( action, auth_settings_external_cas_port ); animateOption( action, auth_settings_external_cas_path ); animateOption( action, auth_settings_external_cas_version ); animateOption( action, auth_settings_external_cas_attr_email ); animateOption( action, auth_settings_external_cas_attr_first_name ); animateOption( action, auth_settings_external_cas_attr_last_name ); animateOption( action, auth_settings_external_cas_attr_update_on_login ); animateOption( action, auth_settings_external_cas_auto_login ); animateOption( action, auth_settings_external_cas_link_on_username ); }); // Event handler: Show/hide LDAP options based on checkbox $( 'input[name="auth_settings[ldap]"]' ).change( function() { var action = $( this ).is( ':checked' ) ? 'show' : 'hide'; animateOption( action, auth_settings_external_ldap_host ); animateOption( action, auth_settings_external_ldap_port ); animateOption( action, auth_settings_external_ldap_search_base ); animateOption( action, auth_settings_external_ldap_uid ); animateOption( action, auth_settings_external_ldap_attr_email ); animateOption( action, auth_settings_external_ldap_user ); animateOption( action, auth_settings_external_ldap_password ); animateOption( action, auth_settings_external_ldap_tls ); animateOption( action, auth_settings_external_ldap_lostpassword_url ); animateOption( action, auth_settings_external_ldap_attr_first_name ); animateOption( action, auth_settings_external_ldap_attr_last_name ); animateOption( action, auth_settings_external_ldap_attr_update_on_login ); }); // Show save button if usermeta field is modified. $( 'form input.auth-usermeta' ).on( 'keyup', function( event ) { // Don't do anything if tab or arrow keys were pressed. if ( event.which === 9 || event.which === 37 || event.which === 38 || event.which === 39 || event.which === 40 ) { return; } $( this ).siblings( '.button' ).css( 'display', 'inline-block' ); }); // List management function: pressing enter in the new approved or new // blocked user (email or role field) adds the user to the list. $( '#new_approved_user_email, #new_approved_user_role, #new_blocked_user_email' ).on( 'keyup', function( event ) { // For textareas, make Enter add the user; for inputs, make enter add the user. if ( $( this ).is( 'textarea' ) ) { // Enter key adds a newline; Enter key with Ctrl, Alt, Shift, or Meta adds the user. if ( event.which === 13 && ( event.ctrlKey || event.altKey || event.metaKey ) ) { $( this ).parent().find( 'a.button-add-user' ).trigger( 'click' ); event.preventDefault(); } } else if ( event.which === 13 ) { // Enter key on input[type="text"] $( this ).parent().find( 'a.button-add-user' ).trigger( 'click' ); event.preventDefault(); } }); // Don't submit form (i.e., save options) when hitting enter in any user list field. $( 'input.auth-email, select.auth-role, input.auth-date-added, input.auth-usermeta' ).on( 'keydown', function( event ) { if ( event.which === 13 ) { // Enter key event.preventDefault(); return false; } }); // Enable the user-friendly multiselect form element on the options page. $( '#auth_settings_access_public_pages' ).multiSelect({ selectableOptgroup: true, selectableHeader: '
' + authL10n.private_pages + '
', selectionHeader: '
' + authL10n.public_pages + '
', }); // Switch to the first tab (or the tab indicated in sessionStorage, or the querystring). var tab = ''; if ( getQuerystringValuesByKey( 'tab' ).length > 0 ) { tab = getQuerystringValuesByKey( 'tab' )[0]; } else if ( sessionStorage.getItem( 'tab' ) ) { tab = sessionStorage.getItem( 'tab' ); } if ( $.inArray( tab, [ 'access_lists', 'access_login', 'access_public', 'external', 'advanced' ] ) < 0 ) { tab = 'access_lists'; } window.chooseTab( tab, animationSpeed ); // Hide/show multisite settings based on override checkbox. $( 'input[name="auth_settings[multisite_override]"]' ).change( function() { hideMultisiteSettingsIfDisabled(); }); hideMultisiteSettingsIfDisabled(); // Wire up pager events on Approved User list (first/last/next/previous // buttons, go to page text input, and search. $( '#current-page-selector, #user-search-input' ).on( 'keydown', function( event ) { if ( event.which === 13 ) { // Enter key var searchTerm = $( '#user-search-input' ).val(); var currentPage = parseInt( $( this ).val(), 10 ) || 1; var totalPages = parseInt( $( '.total-pages' ).first().text().replace( /[^0-9]/g, '' ), 10 ) || 1; // Make sure current page is between 1 and max pages. if ( currentPage < 1 ) { currentPage = 1; } else if ( currentPage > totalPages ) { currentPage = totalPages; } // Update user list with users on next page. refreshApprovedUserList( currentPage, searchTerm ); // Prevent default behavior. event.preventDefault(); return false; } }); $( '.tablenav' ).on( 'click', '.pagination-links a, #search-submit', function( event ) { var searchTerm = $( '#user-search-input' ).val(); var currentPage = parseInt( getParameterByName( 'paged', $( this ).attr( 'href' ) ), 10 ) || 1; var totalPages = parseInt( $( '.total-pages' ).first().text().replace( /[^0-9]/g, '' ), 10 ) || 1; if ( currentPage > totalPages ) { currentPage = totalPages; } // Update user list with users on next page. refreshApprovedUserList( currentPage, searchTerm ); // Remove focus from clicked element. $( this ).blur(); // Prevent default behavior. event.preventDefault(); return false; }); // Enable growable textarea for new user field. $( 'textarea#new_approved_user_email' ).autogrow(); // Enable growable textarea for config fields. $( 'textarea#auth_settings_ldap_search_base' ).autogrow(); $( 'textarea#auth_settings_google_hosteddomain' ).autogrow(); }); /** * Globals. */ // Switch between option tabs. window.chooseTab = function( listName, delay ) { // default delay is 0 delay = 'undefined' !== typeof delay ? delay : 0; // default to the access list tab listName = 'undefined' !== typeof listName ? listName : 'access_lists'; // Hide all tab content, then show selected tab content $( 'div.section_info, div.section_info + table' ).hide(); $( '#section_info_' + listName + ', #section_info_' + listName + ' + table' ).show(); // Set active tab $( '.nav-tab-wrapper a' ).removeClass( 'nav-tab-active' ); $( 'a.nav-tab-' + listName ).addClass( 'nav-tab-active' ); // Hide site options if they are overridden by a multisite setting. setTimeout( window.hideMultisiteOverriddenOptions, delay ); // Hide Save Changes button if we're on the access lists page (changing // access lists saves automatically via AJAX). $( 'body:not(.network-admin) #submit' ).toggle( 'access_lists' !== listName ); // Save user's active tab to sessionStorage (so we can restore it on reload). // Note: session storage persists until the browser tab is closed. sessionStorage.setItem( 'tab', listName ); }; // Hide (with overlay) site options if overridden by a multisite option. window.hideMultisiteOverriddenOptions = function() { $( '.auth_multisite_override_overlay' ).each( function() { // Option to hide is stored in the overlay's id with 'overlay-hide-' prefix. var optionContainerToHide = $( this ).closest( 'tr' ); if ( optionContainerToHide.length > 0 ) { $( this ).css({ 'background-color': '#f1f1f1', 'z-index': 1, opacity: 0.8, position: 'absolute', top: optionContainerToHide.position().top, left: optionContainerToHide.position().left, width: '100%', height: optionContainerToHide.height(), }); $( this ).show(); } }); }; // Update user's usermeta field. // @calls php wp_ajax_update_auth_usermeta. window.authUpdateUsermeta = function( caller ) { var $caller = $( caller ), $usermeta = $caller.parent().children( '.auth-usermeta' ), email = $caller.siblings( '.auth-email' ).val(), usermeta = $usermeta.val(), nonce = $( '#nonce_save_auth_settings' ).val(); // Remove reference to caller if it's the usermeta field itself (not a button triggering the save). if ( $caller.hasClass( 'auth-usermeta' ) ) { $caller = $(); } // Disable inputs, show spinner. $caller.attr( 'disabled', 'disabled' ); $usermeta.attr( 'disabled', 'disabled' ); var $row = $usermeta.closest( 'li' ); var $spinner = $( '' ).css({ position: 'absolute', top: $row.position().top, left: $row.position().left + $row.width(), }); $usermeta.after( $spinner ); $( 'html' ).addClass( 'busy' ); // Call ajax save function. $.post( ajaxurl, { action: 'update_auth_usermeta', email: email, usermeta: usermeta, nonce: nonce, }, function( response ) { var succeeded = response === 'success'; var spinnerText = succeeded ? authL10n.saved + '.' : '' + authL10n.failed + '.'; var spinnerWait = succeeded ? 500 : 2000; // Enable inputs, remove spinner. $caller.removeAttr( 'disabled' ); $usermeta.removeAttr( 'disabled' ); $caller.css( 'display', 'none' ); $( 'form .spinner:not(:has(.spinner-text))' ).animate( { width: '60px' }, 'fast' ).append( '' + spinnerText + '' ).delay( spinnerWait ).hide( animationSpeed, function() { $( this ).remove(); }); $( 'html' ).removeClass( 'busy' ); }).fail( function() { var succeeded = false; var spinnerText = succeeded ? authL10n.saved + '.' : '' + authL10n.failed + '.'; var spinnerWait = succeeded ? 500 : 2000; // Enable inputs, remove spinner. $caller.removeAttr( 'disabled' ); $usermeta.removeAttr( 'disabled' ); $caller.css( 'display', 'none' ); $( 'form .spinner:not(:has(.spinner-text))' ).animate( { width: '60px' }, 'fast' ).append( '' + spinnerText + '' ).delay( spinnerWait ).hide( animationSpeed, function() { $( this ).remove(); }); $( 'html' ).removeClass( 'busy' ); }); }; // Update user's role. window.authChangeRole = function( caller, isMultisite ) { // Set default for multisite flag (run different save routine if multisite) isMultisite = typeof isMultisite !== 'undefined' ? isMultisite : false; var email = $( caller ).parent().find( '.auth-email' ); var role = $( caller ).parent().find( '.auth-role' ); var dateAdded = $( caller ).parent().find( '.auth-date-added' ); var user = { email: email.val(), role: role.val(), date_added: dateAdded.val(), // eslint-disable-line camelcase edit_action: 'change_role', // eslint-disable-line camelcase multisite_user: isMultisite, // eslint-disable-line camelcase }; // Update the options in the database with this change. updateAuthUser( caller, 'access_users_approved', user ); return true; }; // Update user's role (multisite options page). window.authMultisiteChangeRole = function( caller ) { var isMultisite = true; window.authChangeRole( caller, isMultisite ); }; // Add user to list (list = blocked or approved). window.authAddUser = function( caller, list, shouldCreateLocalAccount, isMultisite ) { // Skip email address validation if adding from pending list (not user-editable). var skipValidation = $( caller ).parent().parent().attr( 'id' ) === 'list_auth_settings_access_users_pending'; // Skip email address validation if we're banning an existing user (since they're already in a list). var blockingNewUser = $( caller ).attr( 'id' ).indexOf( 'block_user_new' ) > -1; skipValidation = skipValidation || ( $( caller ).attr( 'id' ).indexOf( 'block_user' ) > -1 && ! blockingNewUser ); // Set default for multisite flag (run different save routine if multisite) isMultisite = 'undefined' !== typeof isMultisite ? isMultisite : false; // Default to the approved list. list = 'undefined' !== typeof list ? list : 'approved'; // Default to not creating a local account. shouldCreateLocalAccount = 'undefined' !== typeof shouldCreateLocalAccount ? shouldCreateLocalAccount : false; var email = $( caller ).parent().find( '.auth-email' ); var role = $( caller ).parent().find( '.auth-role' ); var dateAdded = $( caller ).parent().find( '.auth-date-added' ); // Helper variable for disabling buttons while processing. This will be // set differently if our clicked button is nested in a div (below). var buttons = caller; // Button (caller) might be nested in a div, so we need to walk up one more level if ( 0 === email.length || 0 === role.length ) { email = $( caller ).parent().parent().find( '.auth-email' ); role = $( caller ).parent().parent().find( '.auth-role' ); dateAdded = $( caller ).parent().parent().find( '.auth-date-added' ); buttons = $( caller ).parent().children(); } // Support a single email address, or multiple (separated by newlines, commas, semicolons, or spaces). var emails = $.trim( email.val() ).replace( /mailto:/g, '' ).split( /[\s,;]+/ ); // Remove any invalid email addresses. if ( ! skipValidation ) { // Check if the email(s) being added is well-formed. emails = emails.filter( function( emailToValidate ) { return validEmail( emailToValidate, blockingNewUser ); }); // Remove any duplicates in the list of emails to add. emails = removeDuplicatesFromArrayOfStrings( emails ); } // Shake and quit if no valid email addresses exist. if ( 1 > emails.length ) { $( '#new_' + list + '_user_email' ).parent().effect( 'shake', shakeSpeed ); return false; } $( buttons ).attr( 'disabled', 'disabled' ); var users = []; for ( var i = 0; i < emails.length; i++ ) { var user = { email: emails[i], role: role.val(), date_added: dateAdded.val(), // eslint-disable-line camelcase edit_action: 'add', // eslint-disable-line camelcase local_user: shouldCreateLocalAccount, // eslint-disable-line camelcase multisite_user: isMultisite, // eslint-disable-line camelcase }; users.push( user ); // Get next highest user ID. var nextId = 1 + Math.max.apply( null, // eslint-disable-next-line no-unused-vars $( '#list_auth_settings_access_users_' + list + ' li .auth-email' ).map( function( el ) { // jshint ignore:line return parseInt( this.id.replace( 'auth_multisite_settings_access_users_' + list + '_', '' ).replace( 'auth_settings_access_users_' + list + '_', '' ), 10 ); }) ); // Add the new item. var authJsPrefix = isMultisite ? 'authMultisite' : 'auth'; var localIcon = shouldCreateLocalAccount ? ' ' : ''; var banButton = list === 'approved' && ! isMultisite ? '' : ''; $( ' \ \ ' ).appendTo( '#list_auth_settings_access_users_' + list ).slideDown( 250 ); // Populate the role dropdown in the new element. Because clone() doesn't // save selected state on select elements, set that too. $( 'option', role ).clone().appendTo( '#new_user_' + nextId + ' .auth-role' ); $( '#new_user_' + nextId + ' .auth-role' ).val( role.val() ); } // Remove the 'empty list' item if it exists. $( '#list_auth_settings_access_users_' + list + ' li.auth-empty' ).remove(); // Update the options in the database with this change. updateAuthUser( buttons, 'access_users_' + list, users ); // Reset the new user textboxes if ( email.hasClass( 'new' ) ) { email.val( '' ).keydown(); } // Re-enable the action buttons now that we're done saving. $( buttons ).removeAttr( 'disabled' ); return true; }; // Add user to list (multisite options page). window.authMultisiteAddUser = function( caller, list, shouldCreateLocalAccount ) { var isMultisite = true; // Default to the approved list. list = typeof list !== 'undefined' ? list : 'approved'; // Default to not creating a local account. shouldCreateLocalAccount = typeof shouldCreateLocalAccount !== 'undefined' ? shouldCreateLocalAccount : false; // There currently is no multisite blocked list, so do nothing. if ( list === 'blocked' ) { return; } window.authAddUser( caller, list, shouldCreateLocalAccount, isMultisite ); }; // Remove user from list. window.authIgnoreUser = function( caller, listName, isMultisite ) { // Set default for multisite flag (run different save routine if multisite) isMultisite = typeof isMultisite !== 'undefined' ? isMultisite : false; // Set default list if not provided. listName = typeof listName !== 'undefined' ? listName : 'approved'; var email = $( caller ).parent().find( '.auth-email' ); var user = { email: email.val(), role: '', date_added: '', // eslint-disable-line camelcase edit_action: 'remove', // eslint-disable-line camelcase multisite_user: isMultisite, // eslint-disable-line camelcase }; // Show an 'empty list' message if we're deleting the last item var list = $( caller ).closest( 'ul' ); if ( $( 'li', list ).length <= 1 ) { $( list ).append( '
  • ' + authL10n.no_users_in + ' ' + listName + '
  • ' ); } $( caller ).parent().slideUp( 250, function() { // Remove the list item. $( this ).remove(); // Update the options in the database with this change. updateAuthUser( caller, 'access_users_' + listName, user ); }); }; // Remove user from list (multisite options page). window.authMultisiteIgnoreUser = function( caller, listName ) { var isMultisite = true; // Set default list if not provided. listName = typeof listName !== 'undefined' ? listName : ''; window.authIgnoreUser( caller, listName, isMultisite ); }; // Save Authorizer Settings (multisite). // @calls php wp_ajax_save_auth_multisite_settings. /* eslint-disable camelcase */ window.saveAuthMultisiteSettings = function( caller ) { // Enable wait cursor. $( 'html' ).addClass( 'busy' ); // Disable button (prevent duplicate clicks). $( caller ).attr( 'disabled', 'disabled' ); // Enable spinner by element that triggered this event (caller). var $spinner = $( '' ).css({ position: 'absolute', top: $( caller ).position().top, left: $( caller ).position().left + $( caller ).width() + 20, }); $( caller ).after( $spinner ); // Get form elements to save var nonce_save_auth_settings = $( '#nonce_save_auth_settings' ).val(); var multisite_override = $( '#auth_settings_multisite_override' ).is( ':checked' ) ? '1' : ''; var access_who_can_login = $( 'form input[name="auth_settings[access_who_can_login]"]:checked' ).val(); var access_who_can_view = $( 'form input[name="auth_settings[access_who_can_view]"]:checked' ).val(); var access_users_approved = {}; $( '#list_auth_settings_access_users_approved li' ).each( function( index ) { var user = {}; user.email = $( '.auth-email', this ).val(); user.role = $( '.auth-role', this ).val(); user.date_added = $( '.auth-date-added', this ).val(); user.local_user = $( '.auth-local-user', this ).length !== 0; access_users_approved[index] = user; }); var access_default_role = $( '#auth_settings_access_default_role' ).val(); var google = $( '#auth_settings_google' ).is( ':checked' ) ? '1' : ''; var google_clientid = $( '#auth_settings_google_clientid' ).val(); var google_clientsecret = $( '#auth_settings_google_clientsecret' ).val(); var google_hosteddomain = $( '#auth_settings_google_hosteddomain' ).val(); var cas = $( '#auth_settings_cas' ).is( ':checked' ) ? '1' : ''; var cas_custom_label = $( '#auth_settings_cas_custom_label' ).val(); var cas_host = $( '#auth_settings_cas_host' ).val(); var cas_port = $( '#auth_settings_cas_port' ).val(); var cas_path = $( '#auth_settings_cas_path' ).val(); var cas_version = $( '#auth_settings_cas_version' ).val(); var cas_attr_email = $( '#auth_settings_cas_attr_email' ).val(); var cas_attr_first_name = $( '#auth_settings_cas_attr_first_name' ).val(); var cas_attr_last_name = $( '#auth_settings_cas_attr_last_name' ).val(); var cas_attr_update_on_login = $( '#auth_settings_cas_attr_update_on_login' ).is( ':checked' ) ? '1' : ''; var cas_auto_login = $( '#auth_settings_cas_auto_login' ).is( ':checked' ) ? '1' : ''; var cas_link_on_username = $( '#auth_settings_cas_link_on_username' ).is( ':checked' ) ? '1' : ''; var ldap = $( '#auth_settings_ldap' ).is( ':checked' ) ? '1' : ''; var ldap_host = $( '#auth_settings_ldap_host' ).val(); var ldap_port = $( '#auth_settings_ldap_port' ).val(); var ldap_search_base = $( '#auth_settings_ldap_search_base' ).val(); var ldap_uid = $( '#auth_settings_ldap_uid' ).val(); var ldap_attr_email = $( '#auth_settings_ldap_attr_email' ).val(); var ldap_user = $( '#auth_settings_ldap_user' ).val(); var ldap_password = $( '#auth_settings_ldap_password' ).val(); var ldap_tls = $( '#auth_settings_ldap_tls' ).is( ':checked' ) ? '1' : ''; var ldap_lostpassword_url = $( '#auth_settings_ldap_lostpassword_url' ).val(); var ldap_attr_first_name = $( '#auth_settings_ldap_attr_first_name' ).val(); var ldap_attr_last_name = $( '#auth_settings_ldap_attr_last_name' ).val(); var ldap_attr_update_on_login = $( '#auth_settings_ldap_attr_update_on_login' ).is( ':checked' ) ? '1' : ''; var advanced_lockouts = { attempts_1: $( '#auth_settings_advanced_lockouts_attempts_1' ).val(), duration_1: $( '#auth_settings_advanced_lockouts_duration_1' ).val(), attempts_2: $( '#auth_settings_advanced_lockouts_attempts_2' ).val(), duration_2: $( '#auth_settings_advanced_lockouts_duration_2' ).val(), reset_duration: $( '#auth_settings_advanced_lockouts_reset_duration' ).val(), }; var advanced_hide_wp_login = $( '#auth_settings_advanced_hide_wp_login' ).is( ':checked' ) ? '1' : ''; var advanced_widget_enabled = $( '#auth_settings_advanced_widget_enabled' ).is( ':checked' ) ? '1' : ''; var advanced_users_per_page = $( '#auth_settings_advanced_users_per_page' ).val(); var advanced_users_sort_by = $( '#auth_settings_advanced_users_sort_by' ).val(); var advanced_users_sort_order = $( '#auth_settings_advanced_users_sort_order' ).val(); $.post( ajaxurl, { action: 'save_auth_multisite_settings', nonce: nonce_save_auth_settings, multisite_override: multisite_override, access_who_can_login: access_who_can_login, access_who_can_view: access_who_can_view, access_users_approved: access_users_approved, access_default_role: access_default_role, google: google, google_clientid: google_clientid, google_clientsecret: google_clientsecret, google_hosteddomain: google_hosteddomain, cas: cas, cas_custom_label: cas_custom_label, cas_host: cas_host, cas_port: cas_port, cas_path: cas_path, cas_version: cas_version, cas_attr_email: cas_attr_email, cas_attr_first_name: cas_attr_first_name, cas_attr_last_name: cas_attr_last_name, cas_attr_update_on_login: cas_attr_update_on_login, cas_auto_login: cas_auto_login, cas_link_on_username: cas_link_on_username, ldap: ldap, ldap_host: ldap_host, ldap_port: ldap_port, ldap_search_base: ldap_search_base, ldap_uid: ldap_uid, ldap_attr_email: ldap_attr_email, ldap_user: ldap_user, ldap_password: ldap_password, ldap_tls: ldap_tls, ldap_lostpassword_url: ldap_lostpassword_url, ldap_attr_first_name: ldap_attr_first_name, ldap_attr_last_name: ldap_attr_last_name, ldap_attr_update_on_login: ldap_attr_update_on_login, advanced_lockouts: advanced_lockouts, advanced_hide_wp_login: advanced_hide_wp_login, advanced_users_per_page: advanced_users_per_page, advanced_users_sort_by: advanced_users_sort_by, advanced_users_sort_order: advanced_users_sort_order, advanced_widget_enabled: advanced_widget_enabled, }, function( response ) { var succeeded = response === 'success'; var spinnerText = succeeded ? authL10n.saved + '.' : '' + authL10n.failed + '.'; var spinnerWait = succeeded ? 500 : 2000; $( 'form .spinner:not(:has(.spinner-text))' ).append( '' + spinnerText + '' ).delay( spinnerWait ).hide( animationSpeed, function() { $( this ).remove(); }); $( caller ).removeAttr( 'disabled' ); // Disable wait cursor. $( 'html' ).removeClass( 'busy' ); }).fail( function() { // Fail fires if the server doesn't respond var succeeded = false; var spinnerText = succeeded ? authL10n.saved + '.' : '' + authL10n.failed + '.'; var spinnerWait = succeeded ? 500 : 2000; $( 'form .spinner:not(:has(.spinner-text))' ).append( '' + spinnerText + '' ).delay( spinnerWait ).hide( animationSpeed, function() { $( this ).remove(); }); $( caller ).removeAttr( 'disabled' ); // Disable wait cursor. $( 'html' ).removeClass( 'busy' ); }); }; /* eslint-enable camelcase */ /* ======================================================================== * Portions below from Bootstrap. * ======================================================================== * Bootstrap: dropdown.js v3.1.1 * http://getbootstrap.com/javascript/#dropdowns * ======================================================================== * Copyright 2011-2014 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ // DROPDOWN CLASS DEFINITION // ========================= var backdrop = '.dropdown-backdrop'; var toggle = '[data-toggle=dropdown]'; var Dropdown = function( element ) { // eslint-disable-line func-style $( element ).on( 'click.bs.dropdown', this.toggle ); }; Dropdown.prototype.toggle = function( event ) { var $this = $( this ); if ( $this.is( '.disabled, :disabled' ) ) { return; } var $parent = getParent( $this ); var isActive = $parent.hasClass( 'open' ); clearMenus(); if ( ! isActive ) { if ( 'ontouchstart' in document.documentElement && ! $parent.closest( '.navbar-nav' ).length ) { // if mobile we use a backdrop because click events don't delegate $( '