summaryrefslogtreecommitdiff
path: root/www/crm/wp-admin/js/tags-box.js
diff options
context:
space:
mode:
Diffstat (limited to 'www/crm/wp-admin/js/tags-box.js')
-rw-r--r--www/crm/wp-admin/js/tags-box.js430
1 files changed, 430 insertions, 0 deletions
diff --git a/www/crm/wp-admin/js/tags-box.js b/www/crm/wp-admin/js/tags-box.js
new file mode 100644
index 00000000..c4676f26
--- /dev/null
+++ b/www/crm/wp-admin/js/tags-box.js
@@ -0,0 +1,430 @@
+/**
+ * @output wp-admin/js/tags-box.js
+ */
+
+/* jshint curly: false, eqeqeq: false */
+/* global ajaxurl, tagBox, array_unique_noempty */
+
+( function( $ ) {
+ var tagDelimiter = ( window.tagsSuggestL10n && window.tagsSuggestL10n.tagDelimiter ) || ',';
+
+ /**
+ * Filters unique items and returns a new array.
+ *
+ * Filters all items from an array into a new array containing only the unique
+ * items. This also excludes whitespace or empty values.
+ *
+ * @since 2.8.0
+ *
+ * @global
+ *
+ * @param {Array} array The array to filter through.
+ *
+ * @return {Array} A new array containing only the unique items.
+ */
+ window.array_unique_noempty = function( array ) {
+ var out = [];
+
+ // Trim the values and ensure they are unique.
+ $.each( array, function( key, val ) {
+ val = $.trim( val );
+
+ if ( val && $.inArray( val, out ) === -1 ) {
+ out.push( val );
+ }
+ } );
+
+ return out;
+ };
+
+ /**
+ * The TagBox object.
+ *
+ * Contains functions to create and manage tags that can be associated with a
+ * post.
+ *
+ * @since 2.9.0
+ *
+ * @global
+ */
+ window.tagBox = {
+ /**
+ * Cleans up tags by removing redundant characters.
+ *
+ * @since 2.9.0
+ * @memberOf tagBox
+ *
+ * @param {string} tags Comma separated tags that need to be cleaned up.
+ *
+ * @return {string} The cleaned up tags.
+ */
+ clean : function( tags ) {
+ if ( ',' !== tagDelimiter ) {
+ tags = tags.replace( new RegExp( tagDelimiter, 'g' ), ',' );
+ }
+
+ tags = tags.replace(/\s*,\s*/g, ',').replace(/,+/g, ',').replace(/[,\s]+$/, '').replace(/^[,\s]+/, '');
+
+ if ( ',' !== tagDelimiter ) {
+ tags = tags.replace( /,/g, tagDelimiter );
+ }
+
+ return tags;
+ },
+
+ /**
+ * Parses tags and makes them editable.
+ *
+ * @since 2.9.0
+ * @memberOf tagBox
+ *
+ * @param {Object} el The tag element to retrieve the ID from.
+ *
+ * @return {boolean} Always returns false.
+ */
+ parseTags : function(el) {
+ var id = el.id,
+ num = id.split('-check-num-')[1],
+ taxbox = $(el).closest('.tagsdiv'),
+ thetags = taxbox.find('.the-tags'),
+ current_tags = thetags.val().split( tagDelimiter ),
+ new_tags = [];
+
+ delete current_tags[num];
+
+ // Sanitize the current tags and push them as if they're new tags.
+ $.each( current_tags, function( key, val ) {
+ val = $.trim( val );
+ if ( val ) {
+ new_tags.push( val );
+ }
+ });
+
+ thetags.val( this.clean( new_tags.join( tagDelimiter ) ) );
+
+ this.quickClicks( taxbox );
+ return false;
+ },
+
+ /**
+ * Creates clickable links, buttons and fields for adding or editing tags.
+ *
+ * @since 2.9.0
+ * @memberOf tagBox
+ *
+ * @param {Object} el The container HTML element.
+ *
+ * @return {void}
+ */
+ quickClicks : function( el ) {
+ var thetags = $('.the-tags', el),
+ tagchecklist = $('.tagchecklist', el),
+ id = $(el).attr('id'),
+ current_tags, disabled;
+
+ if ( ! thetags.length )
+ return;
+
+ disabled = thetags.prop('disabled');
+
+ current_tags = thetags.val().split( tagDelimiter );
+ tagchecklist.empty();
+
+ /**
+ * Creates a delete button if tag editing is enabled, before adding it to the tag list.
+ *
+ * @since 2.5.0
+ * @memberOf tagBox
+ *
+ * @param {string} key The index of the current tag.
+ * @param {string} val The value of the current tag.
+ *
+ * @return {void}
+ */
+ $.each( current_tags, function( key, val ) {
+ var listItem, xbutton;
+
+ val = $.trim( val );
+
+ if ( ! val )
+ return;
+
+ // Create a new list item, and ensure the text is properly escaped.
+ listItem = $( '<li />' ).text( val );
+
+ // If tags editing isn't disabled, create the X button.
+ if ( ! disabled ) {
+ /*
+ * Build the X buttons, hide the X icon with aria-hidden and
+ * use visually hidden text for screen readers.
+ */
+ xbutton = $( '<button type="button" id="' + id + '-check-num-' + key + '" class="ntdelbutton">' +
+ '<span class="remove-tag-icon" aria-hidden="true"></span>' +
+ '<span class="screen-reader-text">' + window.tagsSuggestL10n.removeTerm + ' ' + listItem.html() + '</span>' +
+ '</button>' );
+
+ /**
+ * Handles the click and keypress event of the tag remove button.
+ *
+ * Makes sure the focus ends up in the tag input field when using
+ * the keyboard to delete the tag.
+ *
+ * @since 4.2.0
+ *
+ * @param {Event} e The click or keypress event to handle.
+ *
+ * @return {void}
+ */
+ xbutton.on( 'click keypress', function( e ) {
+ // On click or when using the Enter/Spacebar keys.
+ if ( 'click' === e.type || 13 === e.keyCode || 32 === e.keyCode ) {
+ /*
+ * When using the keyboard, move focus back to the
+ * add new tag field. Note: when releasing the pressed
+ * key this will fire the `keyup` event on the input.
+ */
+ if ( 13 === e.keyCode || 32 === e.keyCode ) {
+ $( this ).closest( '.tagsdiv' ).find( 'input.newtag' ).focus();
+ }
+
+ tagBox.userAction = 'remove';
+ tagBox.parseTags( this );
+ }
+ });
+
+ listItem.prepend( '&nbsp;' ).prepend( xbutton );
+ }
+
+ // Append the list item to the tag list.
+ tagchecklist.append( listItem );
+ });
+
+ // The buttons list is built now, give feedback to screen reader users.
+ tagBox.screenReadersMessage();
+ },
+
+ /**
+ * Adds a new tag.
+ *
+ * Also ensures that the quick links are properly generated.
+ *
+ * @since 2.9.0
+ * @memberOf tagBox
+ *
+ * @param {Object} el The container HTML element.
+ * @param {Object|boolean} a When this is an HTML element the text of that
+ * element will be used for the new tag.
+ * @param {number|boolean} f If this value is not passed then the tag input
+ * field is focused.
+ *
+ * @return {boolean} Always returns false.
+ */
+ flushTags : function( el, a, f ) {
+ var tagsval, newtags, text,
+ tags = $( '.the-tags', el ),
+ newtag = $( 'input.newtag', el );
+
+ a = a || false;
+
+ text = a ? $(a).text() : newtag.val();
+
+ /*
+ * Return if there's no new tag or if the input field is empty.
+ * Note: when using the keyboard to add tags, focus is moved back to
+ * the input field and the `keyup` event attached on this field will
+ * fire when releasing the pressed key. Checking also for the field
+ * emptiness avoids to set the tags and call quickClicks() again.
+ */
+ if ( 'undefined' == typeof( text ) || '' === text ) {
+ return false;
+ }
+
+ tagsval = tags.val();
+ newtags = tagsval ? tagsval + tagDelimiter + text : text;
+
+ newtags = this.clean( newtags );
+ newtags = array_unique_noempty( newtags.split( tagDelimiter ) ).join( tagDelimiter );
+ tags.val( newtags );
+ this.quickClicks( el );
+
+ if ( ! a )
+ newtag.val('');
+ if ( 'undefined' == typeof( f ) )
+ newtag.focus();
+
+ return false;
+ },
+
+ /**
+ * Retrieves the available tags and creates a tagcloud.
+ *
+ * Retrieves the available tags from the database and creates an interactive
+ * tagcloud. Clicking a tag will add it.
+ *
+ * @since 2.9.0
+ * @memberOf tagBox
+ *
+ * @param {string} id The ID to extract the taxonomy from.
+ *
+ * @return {void}
+ */
+ get : function( id ) {
+ var tax = id.substr( id.indexOf('-') + 1 );
+
+ /**
+ * Puts a received tag cloud into a DOM element.
+ *
+ * The tag cloud HTML is generated on the server.
+ *
+ * @since 2.9.0
+ *
+ * @param {number|string} r The response message from the AJAX call.
+ * @param {string} stat The status of the AJAX request.
+ *
+ * @return {void}
+ */
+ $.post( ajaxurl, { 'action': 'get-tagcloud', 'tax': tax }, function( r, stat ) {
+ if ( 0 === r || 'success' != stat ) {
+ return;
+ }
+
+ r = $( '<div id="tagcloud-' + tax + '" class="the-tagcloud">' + r + '</div>' );
+
+ /**
+ * Adds a new tag when a tag in the tagcloud is clicked.
+ *
+ * @since 2.9.0
+ *
+ * @return {boolean} Returns false to prevent the default action.
+ */
+ $( 'a', r ).click( function() {
+ tagBox.userAction = 'add';
+ tagBox.flushTags( $( '#' + tax ), this );
+ return false;
+ });
+
+ $( '#' + id ).after( r );
+ });
+ },
+
+ /**
+ * Track the user's last action.
+ *
+ * @since 4.7.0
+ */
+ userAction: '',
+
+ /**
+ * Dispatches an audible message to screen readers.
+ *
+ * This will inform the user when a tag has been added or removed.
+ *
+ * @since 4.7.0
+ *
+ * @return {void}
+ */
+ screenReadersMessage: function() {
+ var message;
+
+ switch ( this.userAction ) {
+ case 'remove':
+ message = window.tagsSuggestL10n.termRemoved;
+ break;
+
+ case 'add':
+ message = window.tagsSuggestL10n.termAdded;
+ break;
+
+ default:
+ return;
+ }
+
+ window.wp.a11y.speak( message, 'assertive' );
+ },
+
+ /**
+ * Initializes the tags box by setting up the links, buttons. Sets up event
+ * handling.
+ *
+ * This includes handling of pressing the enter key in the input field and the
+ * retrieval of tag suggestions.
+ *
+ * @since 2.9.0
+ * @memberOf tagBox
+ *
+ * @return {void}
+ */
+ init : function() {
+ var ajaxtag = $('div.ajaxtag');
+
+ $('.tagsdiv').each( function() {
+ tagBox.quickClicks( this );
+ });
+
+ $( '.tagadd', ajaxtag ).click( function() {
+ tagBox.userAction = 'add';
+ tagBox.flushTags( $( this ).closest( '.tagsdiv' ) );
+ });
+
+ /**
+ * Handles pressing enter on the new tag input field.
+ *
+ * Prevents submitting the post edit form. Uses `keypress` to take
+ * into account Input Method Editor (IME) converters.
+ *
+ * @since 2.9.0
+ *
+ * @param {Event} event The keypress event that occurred.
+ *
+ * @return {void}
+ */
+ $( 'input.newtag', ajaxtag ).keypress( function( event ) {
+ if ( 13 == event.which ) {
+ tagBox.userAction = 'add';
+ tagBox.flushTags( $( this ).closest( '.tagsdiv' ) );
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }).each( function( i, element ) {
+ $( element ).wpTagsSuggest();
+ });
+
+ /**
+ * Before a post is saved the value currently in the new tag input field will be
+ * added as a tag.
+ *
+ * @since 2.9.0
+ *
+ * @return {void}
+ */
+ $('#post').submit(function(){
+ $('div.tagsdiv').each( function() {
+ tagBox.flushTags(this, false, 1);
+ });
+ });
+
+ /**
+ * Handles clicking on the tag cloud link.
+ *
+ * Makes sure the ARIA attributes are set correctly.
+ *
+ * @since 2.9.0
+ *
+ * @return {void}
+ */
+ $('.tagcloud-link').click(function(){
+ // On the first click, fetch the tag cloud and insert it in the DOM.
+ tagBox.get( $( this ).attr( 'id' ) );
+ // Update button state, remove previous click event and attach a new one to toggle the cloud.
+ $( this )
+ .attr( 'aria-expanded', 'true' )
+ .unbind()
+ .click( function() {
+ $( this )
+ .attr( 'aria-expanded', 'false' === $( this ).attr( 'aria-expanded' ) ? 'true' : 'false' )
+ .siblings( '.the-tagcloud' ).toggle();
+ });
+ });
+ }
+ };
+}( jQuery ));