balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

tags-suggest.js (5648B)


      1 /**
      2  * Default settings for jQuery UI Autocomplete for use with non-hierarchical taxonomies.
      3  *
      4  * @output wp-admin/js/tags-suggest.js
      5  */
      6 ( function( $ ) {
      7 	if ( typeof window.uiAutocompleteL10n === 'undefined' ) {
      8 		return;
      9 	}
     10 
     11 	var tempID = 0;
     12 	var separator = wp.i18n._x( ',', 'tag delimiter' ) || ',';
     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 				} ).always( function() {
     68 					$element.removeClass( 'ui-autocomplete-loading' ); // UI fails to remove this sometimes?
     69 				} ).done( function( data ) {
     70 					var tagName;
     71 					var tags = [];
     72 
     73 					if ( data ) {
     74 						data = data.split( '\n' );
     75 
     76 						for ( tagName in data ) {
     77 							var id = ++tempID;
     78 
     79 							tags.push({
     80 								id: id,
     81 								name: data[tagName]
     82 							});
     83 						}
     84 
     85 						cache = tags;
     86 						response( tags );
     87 					} else {
     88 						response( tags );
     89 					}
     90 				} );
     91 
     92 				last = request.term;
     93 			},
     94 			focus: function( event, ui ) {
     95 				$element.attr( 'aria-activedescendant', 'wp-tags-autocomplete-' + ui.item.id );
     96 
     97 				// Don't empty the input field when using the arrow keys
     98 				// to highlight items. See api.jqueryui.com/autocomplete/#event-focus
     99 				event.preventDefault();
    100 			},
    101 			select: function( event, ui ) {
    102 				var tags = split( $element.val() );
    103 				// Remove the last user input.
    104 				tags.pop();
    105 				// Append the new tag and an empty element to get one more separator at the end.
    106 				tags.push( ui.item.name, '' );
    107 
    108 				$element.val( tags.join( separator + ' ' ) );
    109 
    110 				if ( $.ui.keyCode.TAB === event.keyCode ) {
    111 					// Audible confirmation message when a tag has been selected.
    112 					window.wp.a11y.speak( wp.i18n.__( 'Term selected.' ), 'assertive' );
    113 					event.preventDefault();
    114 				} else if ( $.ui.keyCode.ENTER === event.keyCode ) {
    115 					// If we're in the edit post Tags meta box, add the tag.
    116 					if ( window.tagBox ) {
    117 						window.tagBox.userAction = 'add';
    118 						window.tagBox.flushTags( $( this ).closest( '.tagsdiv' ) );
    119 					}
    120 
    121 					// Do not close Quick Edit / Bulk Edit.
    122 					event.preventDefault();
    123 					event.stopPropagation();
    124 				}
    125 
    126 				return false;
    127 			},
    128 			open: function() {
    129 				$element.attr( 'aria-expanded', 'true' );
    130 			},
    131 			close: function() {
    132 				$element.attr( 'aria-expanded', 'false' );
    133 			},
    134 			minLength: 2,
    135 			position: {
    136 				my: 'left top+2',
    137 				at: 'left bottom',
    138 				collision: 'none'
    139 			},
    140 			messages: {
    141 				noResults: window.uiAutocompleteL10n.noResults,
    142 				results: function( number ) {
    143 					if ( number > 1 ) {
    144 						return window.uiAutocompleteL10n.manyResults.replace( '%d', number );
    145 					}
    146 
    147 					return window.uiAutocompleteL10n.oneResult;
    148 				}
    149 			}
    150 		}, options );
    151 
    152 		$element.on( 'keydown', function() {
    153 			$element.removeAttr( 'aria-activedescendant' );
    154 		} );
    155 
    156 		$element.autocomplete( options );
    157 
    158 		// Ensure the autocomplete instance exists.
    159 		if ( ! $element.autocomplete( 'instance' ) ) {
    160 			return this;
    161 		}
    162 
    163 		$element.autocomplete( 'instance' )._renderItem = function( ul, item ) {
    164 			return $( '<li role="option" id="wp-tags-autocomplete-' + item.id + '">' )
    165 				.text( item.name )
    166 				.appendTo( ul );
    167 		};
    168 
    169 		$element.attr( {
    170 			'role': 'combobox',
    171 			'aria-autocomplete': 'list',
    172 			'aria-expanded': 'false',
    173 			'aria-owns': $element.autocomplete( 'widget' ).attr( 'id' )
    174 		} )
    175 		.on( 'focus', function() {
    176 			var inputValue = split( $element.val() ).pop();
    177 
    178 			// Don't trigger a search if the field is empty.
    179 			// Also, avoids screen readers announce `No search results`.
    180 			if ( inputValue ) {
    181 				$element.autocomplete( 'search' );
    182 			}
    183 		} );
    184 
    185 		// Returns a jQuery object containing the menu element.
    186 		$element.autocomplete( 'widget' )
    187 			.addClass( 'wp-tags-autocomplete' )
    188 			.attr( 'role', 'listbox' )
    189 			.removeAttr( 'tabindex' ) // Remove the `tabindex=0` attribute added by jQuery UI.
    190 
    191 			/*
    192 			 * Looks like Safari and VoiceOver need an `aria-selected` attribute. See ticket #33301.
    193 			 * The `menufocus` and `menublur` events are the same events used to add and remove
    194 			 * the `ui-state-focus` CSS class on the menu items. See jQuery UI Menu Widget.
    195 			 */
    196 			.on( 'menufocus', function( event, ui ) {
    197 				ui.item.attr( 'aria-selected', 'true' );
    198 			})
    199 			.on( 'menublur', function() {
    200 				// The `menublur` event returns an object where the item is `null`,
    201 				// so we need to find the active item with other means.
    202 				$( this ).find( '[aria-selected="true"]' ).removeAttr( 'aria-selected' );
    203 			});
    204 
    205 		return this;
    206 	};
    207 
    208 }( jQuery ) );