2 * Default settings for jQuery UI Autocomplete for use with non-hierarchical taxonomies.
5 if ( typeof window.tagsSuggestL10n === 'undefined' || typeof window.uiAutocompleteL10n === 'undefined' ) {
10 var separator = window.tagsSuggestL10n.tagDelimiter || ',';
12 function split( val ) {
13 return val.split( new RegExp( separator + '\\s*' ) );
16 function getLast( term ) {
17 return split( term ).pop();
21 * Add UI Autocomplete to an input or textarea element with presets for use
22 * with non-hierarchical taxonomies.
24 * Example: `$( element ).wpTagsSuggest( options )`.
26 * The taxonomy can be passed in a `data-wp-taxonomy` attribute on the element or
27 * can be in `options.taxonomy`.
31 * @param {object} options Options that are passed to UI Autocomplete. Can be used to override the default settings.
32 * @returns {object} jQuery instance.
34 $.fn.wpTagsSuggest = function( options ) {
37 var $element = $( this );
39 options = options || {};
41 var taxonomy = options.taxonomy || $element.attr( 'data-wp-taxonomy' ) || 'post_tag';
43 delete( options.taxonomy );
46 source: function( request, response ) {
49 if ( last === request.term ) {
54 term = getLast( request.term );
56 $.get( window.ajaxurl, {
57 action: 'ajax-tag-search',
60 } ).always( function() {
61 $element.removeClass( 'ui-autocomplete-loading' ); // UI fails to remove this sometimes?
62 } ).done( function( data ) {
67 data = data.split( '\n' );
69 for ( tagName in data ) {
87 focus: function( event, ui ) {
88 $element.attr( 'aria-activedescendant', 'wp-tags-autocomplete-' + ui.item.id );
90 // Don't empty the input field when using the arrow keys to
91 // highlight items. See api.jqueryui.com/autocomplete/#event-focus
92 event.preventDefault();
94 select: function( event, ui ) {
95 var tags = split( $element.val() );
96 // Remove the last user input.
98 // Append the new tag and an empty element to get one more separator at the end.
99 tags.push( ui.item.name, '' );
101 $element.val( tags.join( separator + ' ' ) );
103 if ( $.ui.keyCode.TAB === event.keyCode ) {
104 // Audible confirmation message when a tag has been selected.
105 window.wp.a11y.speak( window.tagsSuggestL10n.termSelected, 'assertive' );
106 event.preventDefault();
107 } else if ( $.ui.keyCode.ENTER === event.keyCode ) {
108 // Do not close Quick Edit / Bulk Edit
109 event.preventDefault();
110 event.stopPropagation();
116 $element.attr( 'aria-expanded', 'true' );
119 $element.attr( 'aria-expanded', 'false' );
126 noResults: window.uiAutocompleteL10n.noResults,
127 results: function( number ) {
129 return window.uiAutocompleteL10n.manyResults.replace( '%d', number );
132 return window.uiAutocompleteL10n.oneResult;
137 $element.on( 'keydown', function() {
138 $element.removeAttr( 'aria-activedescendant' );
140 .autocomplete( options )
141 .autocomplete( 'instance' )._renderItem = function( ul, item ) {
142 return $( '<li role="option" id="wp-tags-autocomplete-' + item.id + '">' )
149 'aria-autocomplete': 'list',
150 'aria-expanded': 'false',
151 'aria-owns': $element.autocomplete( 'widget' ).attr( 'id' )
153 .on( 'focus', function() {
154 var inputValue = split( $element.val() ).pop();
156 // Don't trigger a search if the field is empty.
157 // Also, avoids screen readers announce `No search results`.
159 $element.autocomplete( 'search' );
162 // Returns a jQuery object containing the menu element.
163 .autocomplete( 'widget' )
164 .addClass( 'wp-tags-autocomplete' )
165 .attr( 'role', 'listbox' )
166 .removeAttr( 'tabindex' ) // Remove the `tabindex=0` attribute added by jQuery UI.
168 // Looks like Safari and VoiceOver need an `aria-selected` attribute. See ticket #33301.
169 // The `menufocus` and `menublur` events are the same events used to add and remove
170 // the `ui-state-focus` CSS class on the menu items. See jQuery UI Menu Widget.
171 .on( 'menufocus', function( event, ui ) {
172 ui.item.attr( 'aria-selected', 'true' );
174 .on( 'menublur', function() {
175 // The `menublur` event returns an object where the item is `null`
176 // so we need to find the active item with other means.
177 $( this ).find( '[aria-selected="true"]' ).removeAttr( 'aria-selected' );