1 /* jshint curly: false, eqeqeq: false */
4 var tagBox, array_unique_noempty;
7 var tagDelimiter = ( window.tagsSuggestL10n && window.tagsSuggestL10n.tagDelimiter ) || ',';
9 // Return an array with any duplicate, whitespace or empty values removed
10 array_unique_noempty = function( array ) {
13 $.each( array, function( key, val ) {
16 if ( val && $.inArray( val, out ) === -1 ) {
25 clean : function( tags ) {
26 if ( ',' !== tagDelimiter ) {
27 tags = tags.replace( new RegExp( tagDelimiter, 'g' ), ',' );
30 tags = tags.replace(/\s*,\s*/g, ',').replace(/,+/g, ',').replace(/[,\s]+$/, '').replace(/^[,\s]+/, '');
32 if ( ',' !== tagDelimiter ) {
33 tags = tags.replace( /,/g, tagDelimiter );
39 parseTags : function(el) {
41 num = id.split('-check-num-')[1],
42 taxbox = $(el).closest('.tagsdiv'),
43 thetags = taxbox.find('.the-tags'),
44 current_tags = thetags.val().split( tagDelimiter ),
47 delete current_tags[num];
49 $.each( current_tags, function( key, val ) {
56 thetags.val( this.clean( new_tags.join( tagDelimiter ) ) );
58 this.quickClicks( taxbox );
62 quickClicks : function( el ) {
63 var thetags = $('.the-tags', el),
64 tagchecklist = $('.tagchecklist', el),
65 id = $(el).attr('id'),
66 current_tags, disabled;
68 if ( ! thetags.length )
71 disabled = thetags.prop('disabled');
73 current_tags = thetags.val().split( tagDelimiter );
76 $.each( current_tags, function( key, val ) {
84 // Create a new span, and ensure the text is properly escaped.
85 span = $('<span />').text( val );
87 // If tags editing isn't disabled, create the X button.
90 * Build the X buttons, hide the X icon with aria-hidden and
91 * use visually hidden text for screen readers.
93 xbutton = $( '<button type="button" id="' + id + '-check-num-' + key + '" class="ntdelbutton">' +
94 '<span class="remove-tag-icon" aria-hidden="true"></span>' +
95 '<span class="screen-reader-text">' + window.tagsSuggestL10n.removeTerm + ' ' + val + '</span>' +
98 xbutton.on( 'click keypress', function( e ) {
99 // On click or when using the Enter/Spacebar keys.
100 if ( 'click' === e.type || 13 === e.keyCode || 32 === e.keyCode ) {
102 * When using the keyboard, move focus back to the
103 * add new tag field. Note: when releasing the pressed
104 * key this will fire the `keyup` event on the input.
106 if ( 13 === e.keyCode || 32 === e.keyCode ) {
107 $( this ).closest( '.tagsdiv' ).find( 'input.newtag' ).focus();
110 tagBox.userAction = 'remove';
111 tagBox.parseTags( this );
115 span.prepend( ' ' ).prepend( xbutton );
118 // Append the span to the tag list.
119 tagchecklist.append( span );
121 // The buttons list is built now, give feedback to screen reader users.
122 tagBox.screenReadersMessage();
125 flushTags : function( el, a, f ) {
126 var tagsval, newtags, text,
127 tags = $( '.the-tags', el ),
128 newtag = $( 'input.newtag', el );
132 text = a ? $(a).text() : newtag.val();
135 * Return if there's no new tag or if the input field is empty.
136 * Note: when using the keyboard to add tags, focus is moved back to
137 * the input field and the `keyup` event attached on this field will
138 * fire when releasing the pressed key. Checking also for the field
139 * emptiness avoids to set the tags and call quickClicks() again.
141 if ( 'undefined' == typeof( text ) || '' === text ) {
145 tagsval = tags.val();
146 newtags = tagsval ? tagsval + tagDelimiter + text : text;
148 newtags = this.clean( newtags );
149 newtags = array_unique_noempty( newtags.split( tagDelimiter ) ).join( tagDelimiter );
151 this.quickClicks( el );
155 if ( 'undefined' == typeof( f ) )
161 get : function( id ) {
162 var tax = id.substr( id.indexOf('-') + 1 );
164 $.post( ajaxurl, { 'action': 'get-tagcloud', 'tax': tax }, function( r, stat ) {
165 if ( 0 === r || 'success' != stat ) {
169 r = $( '<p id="tagcloud-' + tax + '" class="the-tagcloud">' + r + '</p>' );
171 $( 'a', r ).click( function() {
172 tagBox.userAction = 'add';
173 tagBox.flushTags( $( '#' + tax ), this );
177 $( '#' + id ).after( r );
182 * Track the user's last action.
189 * Dispatch an audible message to screen readers.
193 screenReadersMessage: function() {
196 switch ( this.userAction ) {
198 message = window.tagsSuggestL10n.termRemoved;
202 message = window.tagsSuggestL10n.termAdded;
209 window.wp.a11y.speak( message, 'assertive' );
213 var ajaxtag = $('div.ajaxtag');
215 $('.tagsdiv').each( function() {
216 tagBox.quickClicks( this );
219 $( '.tagadd', ajaxtag ).click( function() {
220 tagBox.userAction = 'add';
221 tagBox.flushTags( $( this ).closest( '.tagsdiv' ) );
224 $( 'input.newtag', ajaxtag ).keyup( function( event ) {
225 if ( 13 == event.which ) {
226 tagBox.userAction = 'add';
227 tagBox.flushTags( $( this ).closest( '.tagsdiv' ) );
228 event.preventDefault();
229 event.stopPropagation();
231 }).keypress( function( event ) {
232 if ( 13 == event.which ) {
233 event.preventDefault();
234 event.stopPropagation();
236 }).each( function( i, element ) {
237 $( element ).wpTagsSuggest();
240 // save tags on post save/publish
241 $('#post').submit(function(){
242 $('div.tagsdiv').each( function() {
243 tagBox.flushTags(this, false, 1);
247 // Fetch and toggle the Tag cloud.
248 $('.tagcloud-link').click(function(){
249 // On the first click, fetch the tag cloud and insert it in the DOM.
250 tagBox.get( $( this ).attr( 'id' ) );
251 // Update button state, remove previous click event and attach a new one to toggle the cloud.
253 .attr( 'aria-expanded', 'true' )
257 .attr( 'aria-expanded', 'false' === $( this ).attr( 'aria-expanded' ) ? 'true' : 'false' )
258 .siblings( '.the-tagcloud' ).toggle();