Skip to content

Commit f20b265

Browse files
committed
Menus: Improve usability and accessibility of menu quick search.
Change the admin menu quick search to limit to searching post titles. Add filter `wp_ajax_menu_quick_search_args` to support customizing post columns in query. Clear quick search results when search query is cleared. Send announcements about search status via `wp.a11y.speak()`. Props diebombe, afercia, audrasjb, nickjbedford, kevinlearynet, mukesh27, joedolson. Fixes #48655. git-svn-id: https://develop.svn.wordpress.org/trunk@60991 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 6dd1ac6 commit f20b265

File tree

3 files changed

+93
-21
lines changed

3 files changed

+93
-21
lines changed

src/js/_enqueues/lib/nav-menu.js

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,14 +1406,25 @@
14061406

14071407
updateQuickSearchResults : function(input) {
14081408
var panel, params,
1409-
minSearchLength = 2,
1410-
q = input.val();
1409+
minSearchLength = 1,
1410+
q = input.val(),
1411+
pageSearchChecklist = $( '#page-search-checklist' );
14111412

14121413
/*
1413-
* Minimum characters for a search. Also avoid a new Ajax search when
1414-
* the pressed key (e.g. arrows) doesn't change the searched term.
1414+
* Avoid a new Ajax search when the pressed key (e.g. arrows)
1415+
* doesn't change the searched term.
14151416
*/
1416-
if ( q.length < minSearchLength || api.lastSearch == q ) {
1417+
if ( api.lastSearch == q ) {
1418+
return;
1419+
}
1420+
1421+
/*
1422+
* Reset results when search is less than or equal to
1423+
* minimum characters for searched term.
1424+
*/
1425+
if ( q.length <= minSearchLength ) {
1426+
pageSearchChecklist.empty();
1427+
wp.a11y.speak( wp.i18n.__( 'Search results cleared' ) );
14171428
return;
14181429
}
14191430

@@ -1770,12 +1781,14 @@
17701781
$item;
17711782

17721783
if( ! $items.length ) {
1784+
let noResults = wp.i18n.__( 'No results found.' );
17731785
const li = $( '<li>' );
1774-
const p = $( '<p>', { text: wp.i18n.__( 'No results found.' ) } );
1786+
const p = $( '<p>', { text: noResults } );
17751787
li.append( p );
17761788
$('.categorychecklist', panel).empty().append( li );
17771789
$( '.spinner', panel ).removeClass( 'is-active' );
17781790
wrapper.addClass( 'has-no-menu-item' );
1791+
wp.a11y.speak( noResults, 'assertive' );
17791792
return;
17801793
}
17811794

@@ -1802,6 +1815,7 @@
18021815
});
18031816

18041817
$('.categorychecklist', panel).html( $items );
1818+
wp.a11y.speak( wp.i18n.sprintf( wp.i18n.__( '%d Search Results Found' ), $items.length ), 'assertive' );
18051819
$( '.spinner', panel ).removeClass( 'is-active' );
18061820
wrapper.removeClass( 'has-no-menu-item' );
18071821

src/wp-admin/includes/nav-menu.php

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,17 +83,34 @@ function _wp_ajax_menu_quick_search( $request = array() ) {
8383
} elseif ( preg_match( '/quick-search-(posttype|taxonomy)-([a-zA-Z0-9_-]*\b)/', $type, $matches ) ) {
8484
if ( 'posttype' === $matches[1] && get_post_type_object( $matches[2] ) ) {
8585
$post_type_obj = _wp_nav_menu_meta_box_object( get_post_type_object( $matches[2] ) );
86-
$args = array_merge(
87-
$args,
88-
array(
89-
'no_found_rows' => true,
90-
'update_post_meta_cache' => false,
91-
'update_post_term_cache' => false,
92-
'posts_per_page' => 10,
93-
'post_type' => $matches[2],
94-
's' => $query,
95-
)
86+
$query_args = array(
87+
'no_found_rows' => true,
88+
'update_post_meta_cache' => false,
89+
'update_post_term_cache' => false,
90+
'posts_per_page' => 10,
91+
'post_type' => $matches[2],
92+
's' => $query,
93+
'search_columns' => array( 'post_title' ),
9694
);
95+
/**
96+
* Filter the menu quick search arguments.
97+
*
98+
* @since 6.9.0
99+
*
100+
* @param array $args {
101+
* Menu quick search arguments.
102+
*
103+
* @type boolean $no_found_rows Whether to return found rows data. Default true.
104+
* @type boolean $update_post_meta_cache Whether to update post meta cache. Default false.
105+
* @type boolean $update_post_term_cache Whether to update post term cache. Default false.
106+
* @type int $posts_per_page Number of posts to return. Default 10.
107+
* @type string $post_type Type of post to return.
108+
* @type string $s Search query.
109+
* @type array $search_columns Which post table columns to query.
110+
* }
111+
*/
112+
$query_args = apply_filters( 'wp_ajax_menu_quick_search_args', $query_args );
113+
$args = array_merge( $args, $query_args );
97114

98115
if ( isset( $post_type_obj->_default_query ) ) {
99116
$args = array_merge( $args, (array) $post_type_obj->_default_query );

tests/phpunit/tests/menu/wpAjaxMenuQuickSearch.php

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ public function test_search_returns_results_for_pages() {
1818
array(
1919
'post_type' => 'page',
2020
'post_content' => 'foo',
21+
'post_title' => 'foo title',
2122
)
2223
);
2324
self::factory()->post->create(
2425
array(
2526
'post_type' => 'page',
2627
'post_content' => 'bar',
28+
'post_title' => 'bar title',
2729
)
2830
);
2931

@@ -40,6 +42,45 @@ public function test_search_returns_results_for_pages() {
4042
$this->assertCount( 3, $results );
4143
}
4244

45+
/**
46+
* Test that search only returns results for posts with term in title.
47+
*
48+
* @ticket 48655
49+
*/
50+
public function test_search_only_returns_results_for_posts_with_term_in_title() {
51+
require_once ABSPATH . 'wp-admin/includes/nav-menu.php';
52+
53+
// This will make sure that WP_Query sets is_admin to true.
54+
set_current_screen( 'nav-menu.php' );
55+
56+
self::factory()->post->create(
57+
array(
58+
'post_type' => 'post',
59+
'post_status' => 'publish',
60+
'post_title' => 'Publish FOO',
61+
'post_content' => 'FOO',
62+
)
63+
);
64+
self::factory()->post->create(
65+
array(
66+
'post_type' => 'post',
67+
'post_status' => 'publish',
68+
'post_title' => 'Publish without search term',
69+
'post_content' => 'FOO',
70+
)
71+
);
72+
73+
$request = array(
74+
'type' => 'quick-search-posttype-post',
75+
'q' => 'FOO',
76+
);
77+
$output = get_echo( '_wp_ajax_menu_quick_search', array( $request ) );
78+
79+
$this->assertNotEmpty( $output );
80+
$results = explode( "\n", trim( $output ) );
81+
$this->assertCount( 1, $results );
82+
}
83+
4384
/**
4485
* Test that search only returns results for published posts.
4586
*
@@ -55,31 +96,31 @@ public function test_search_returns_results_for_published_posts() {
5596
array(
5697
'post_type' => 'post',
5798
'post_status' => 'publish',
58-
'post_title' => 'Publish',
99+
'post_title' => 'Publish FOO',
59100
'post_content' => 'FOO',
60101
)
61102
);
62103
self::factory()->post->create(
63104
array(
64105
'post_type' => 'post',
65106
'post_status' => 'draft',
66-
'post_title' => 'Draft',
107+
'post_title' => 'Draft FOO',
67108
'post_content' => 'FOO',
68109
)
69110
);
70111
self::factory()->post->create(
71112
array(
72113
'post_type' => 'post',
73114
'post_status' => 'pending',
74-
'post_title' => 'Pending',
115+
'post_title' => 'Pending FOO',
75116
'post_content' => 'FOO',
76117
)
77118
);
78119
self::factory()->post->create(
79120
array(
80121
'post_type' => 'post',
81122
'post_status' => 'future',
82-
'post_title' => 'Future',
123+
'post_title' => 'Future FOO',
83124
'post_content' => 'FOO',
84125
'post_date' => gmdate( 'Y-m-d H:i:s', strtotime( '+1 month' ) ),
85126
)
@@ -132,7 +173,7 @@ public function test_search_returns_post_types_with_numeric_slugs() {
132173

133174
self::factory()->post->create(
134175
array(
135-
'post_title' => 'Post Title 123',
176+
'post_title' => 'Post Title 123 FOO',
136177
'post_type' => 'wptests_123',
137178
'post_status' => 'publish',
138179
'post_content' => 'FOO',

0 commit comments

Comments
 (0)