diff -r 48c4eec2b7e6 -r 8c2e4d02f4ef wp/wp-admin/js/updates.js --- a/wp/wp-admin/js/updates.js Fri Sep 05 18:40:08 2025 +0200 +++ b/wp/wp-admin/js/updates.js Fri Sep 05 18:52:52 2025 +0200 @@ -142,6 +142,15 @@ wp.updates.searchTerm = ''; /** + * Minimum number of characters before an ajax search is fired. + * + * @since 6.7.0 + * + * @type {number} + */ + wp.updates.searchMinCharacters = 2; + + /** * Whether filesystem credentials need to be requested from the user. * * @since 4.2.0 @@ -2324,7 +2333,7 @@ * 'update' or 'install'. */ wp.updates.isValidResponse = function( response, action ) { - var error = __( 'Something went wrong.' ), + var error = __( 'An error occurred during the update process. Please try again.' ), errorMessage; // Make sure the response is a valid data object and not a Promise object. @@ -2823,14 +2832,7 @@ // Bail if there were no items selected. if ( ! itemsSelected.length ) { - event.preventDefault(); - $( 'html, body' ).animate( { scrollTop: 0 } ); - - return wp.updates.addAdminNotice( { - id: 'no-items-selected', - className: 'notice-error is-dismissible', - message: __( 'Please select at least one item to perform this action on.' ) - } ); + bulkAction = false; } // Determine the type of request we're dealing with. @@ -2977,6 +2979,15 @@ $pluginInstallSearch.attr( 'aria-describedby', 'live-search-desc' ); } + // Track the previous search string length. + var previousSearchStringLength = 0; + wp.updates.shouldSearch = function( searchStringLength ) { + var shouldSearch = searchStringLength >= wp.updates.searchMinCharacters || + previousSearchStringLength > wp.updates.searchMinCharacters; + previousSearchStringLength = searchStringLength; + return shouldSearch; + }; + /** * Handles changes to the plugin search box on the new-plugin page, * searching the repository dynamically. @@ -2984,7 +2995,8 @@ * @since 4.6.0 */ $pluginInstallSearch.on( 'keyup input', _.debounce( function( event, eventtype ) { - var $searchTab = $( '.plugin-install-search' ), data, searchLocation; + var $searchTab = $( '.plugin-install-search' ), data, searchLocation, + searchStringLength = $pluginInstallSearch.val().length; data = { _ajax_nonce: wp.updates.ajaxNonce, @@ -2995,6 +3007,14 @@ }; searchLocation = location.href.split( '?' )[ 0 ] + '?' + $.param( _.omit( data, [ '_ajax_nonce', 'pagenow' ] ) ); + // Set the autocomplete attribute, turning off autocomplete 1 character before ajax search kicks in. + if ( wp.updates.shouldSearch( searchStringLength ) ) { + $pluginInstallSearch.attr( 'autocomplete', 'off' ); + } else { + $pluginInstallSearch.attr( 'autocomplete', 'on' ); + return; + } + // Clear on escape. if ( 'keyup' === event.type && 27 === event.which ) { event.target.value = ''; @@ -3054,6 +3074,7 @@ if ( $pluginSearch.length ) { $pluginSearch.attr( 'aria-describedby', 'live-search-desc' ); + } /** @@ -3069,7 +3090,16 @@ pagenow: pagenow, plugin_status: 'all' }, - queryArgs; + queryArgs, + searchStringLength = $pluginSearch.val().length; + + // Set the autocomplete attribute, turning off autocomplete 1 character before ajax search kicks in. + if ( wp.updates.shouldSearch( searchStringLength ) ) { + $pluginSearch.attr( 'autocomplete', 'off' ); + } else { + $pluginSearch.attr( 'autocomplete', 'on' ); + return; + } // Clear on escape. if ( 'keyup' === event.type && 27 === event.which ) {