0byt3m1n1
Path:
/
var
/
www
/
clients
/
client38
/
web37
/
web
/
wp-content
/
plugins
/
us-core
/
usof
/
js
/
[
Home
]
File: field_autocomplete.js
/** * USOF FIeld: Autocomplete */ ! function( $, undefined ) { var _window = window, _document = document; if ( _window.$usof === undefined ) { return; } $usof.field[ 'autocomplete' ] = { /** * Initializes the object. */ init: function() { // Variables this.disableScrollLoad = false; // Prefix for get params this._prefix = 'params:'; // Delay for search requests this._typingDelay = 0.5; // Event KeyCodes this.keyCodes = { ENTER: 13, BACKSPACE: 8 }; // Default settings structure var defaultSettings = { ajax_query_args: { action: 'unknown', _nonce: '' }, multiple: false, sortable: false, params_separator: ',' }; // Elements this.$container = $( '.usof-autocomplete', this.$row ); this.$toggle = $( '.usof-autocomplete-toggle', this.$container ); this.$options = $( '.usof-autocomplete-options', this.$container ); this.$search = $( 'input[type="text"]', this.$options ); this.$list = $( '.usof-autocomplete-list', this.$container ); this.$message = $( '.usof-autocomplete-message', this.$container ); this.$value = $( '> .usof-autocomplete-value', this.$container ); // Load settings this._settings = $.extend( defaultSettings, this.$container[0].onclick() || {} ); //this.$container.removeAttr( 'onclick' ); // List of all parameters this.items = {}; $( '[data-value]', this.$list ).each( function( _, item ) { var $item = $( item ); this.items[ $item.data( 'value' ) ] = $item; }.bind( this ) ); // Events if ( !this._settings.multiple ) { this.$options .on( 'click', '.usof-autocomplete-selected', function() { var isShow = this.$toggle.hasClass( 'show' ); this._events.toggleList.call( this, { type: isShow ? 'blur' : 'focus' } ); if ( ! isShow ) { if ( !! this.pid ) { clearTimeout( this.pid ); } this.pid = setTimeout( function() { this.$search.focus(); clearTimeout( this.pid ); }.bind( this ), 0 ); } }.bind( this ) ); } else { // For multiple this.$options .on( 'click', '.usof-autocomplete-selected-remove', this._events.remove.bind( this ) ); } this.$list.off() .on( 'mousedown', '[data-value]', this._events.selected.bind( this ) ) .on( 'scroll', this._events.scroll.bind( this ) ); this.$search.off() .on( 'keyup', this._events.keyup.bind( this ) ) .on( 'input', this._events.searchDelay.bind( this ) ) .on( 'focus blur', this._events.toggleList.bind( this ) ); this._initValues.call( this ); this.$container .toggleClass( 'multiple', this._settings.multiple ); if ( this._settings.multiple && this._settings.sortable ) { // Init Drag and Drop plugin this.dragdrop = new $usof.dragDrop( this.$options, { itemSelector: '> .usof-autocomplete-selected' } ); // Watch events this.dragdrop .on( 'dragend', this._events.dragdrop.dragend.bind( this ) ); } }, /** * State loaded */ loaded: false, /** * Handlers */ _events: { // Drag and Drop Handlers dragdrop: { /** * Set the value in the desired order. * * @param object target $usof.dragDrop * @param {Event} e */ dragend: function( target, e ) { var value = [], items = $( '> .usof-autocomplete-selected', target.$container ).toArray() || [], field = $( target.$container ).closest( '.type_autocomplete' ).data( 'usofField' ); for ( var k in items ) { if ( items[ k ].hasAttribute( 'data-key' ) ) { value.push( items[ k ].getAttribute( 'data-key' ) ); } } value = value.length ? value.join( field._settings.params_separator ) : ''; if ( field instanceof $usof.field ) { field.setValue( value ); } } }, /** * Remove selected. * * @param {Event} e */ remove: function( e ) { e.preventDefault(); var $target = $( e.currentTarget ), $selected = $target.closest( '.usof-autocomplete-selected' ), key = $selected.data( 'key' ); this._removeValue.call( this, key ); $( '[data-value="' + key + '"]', this.$list ).removeClass( 'selected' ); $selected.remove(); }, /** * Delayed search to avoid premature queries. * * @param {Event} e */ searchDelay: function( e ) { if ( ! e.currentTarget.value ) { return; } if ( !! this._typingTimer ) { clearTimeout( this._typingTimer ); } this._typingTimer = setTimeout( function() { this._events.search.call( this, e ); clearTimeout( this._typingTimer ); }.bind( this ), 1000 * this._typingDelay ); }, /** * Filtering results when entering characters in the search field. * * @param {Event} e */ search: function( e ) { var $input = $( e.currentTarget ), value = ( $.trim( $input.val() ).toLowerCase() ).replace( /\=|\"|\s/, '' ), $items = $( '[data-value]', this.$list ), $groups = $( '[data-group]', this.$list ), /** * Filters parameters by search text. * * @param {jQuery} $items */ filter = function( $items ) { $items .addClass( 'hidden' ) .filter( '[data-text^="'+ value +'"], [data-text*="'+ value +'"]' ) .removeClass( 'hidden' ); $groups.each(function() { var $group = $( this ); $group.toggleClass( 'hidden', !$group.find('[data-value]:not(.hidden)').length ); }); }; // Check value if ( !value || value.length < 1 ) { $items.removeClass( 'hidden' ); return; } // Filter by search text filter.call( this, $items ); // Enable scrolling data loading this.disableScrollLoad = false; // Search preload this._ajax.call( this, function( items ) { // Filter by search text filter.call( this, this.$list.find( '> *' ) ); // Messages no results found if ( value && !$( '[data-value]:not(.hidden)', this.$list ).length ) { this._showMessage.call( this, this._settings.no_results_found ); } else { this._clearMessage.call( this ); this.$toggle.addClass( 'show' ); } }.bind( this ) ); }, /** * Selected option. * * @param {Event} e */ selected: function( e ) { var $target = $( e.currentTarget ), selectedValue = $target.data( 'value' ) || ''; if ( $target.hasClass( 'selected' ) && this._settings.multiple ) { // Remove item this._removeValue.call( this, selectedValue ); $( '[data-key="' + selectedValue + '"]', this.$options ).remove(); $target.removeClass( 'selected' ); } else if ( this._addValue.call( this, selectedValue ) ) { if ( ! this._settings.multiple ) { $( '.usof-autocomplete-selected', this.$options ).remove(); $( '[data-value]', this.$list ).removeClass( 'selected' ); } this.$toggle.removeClass( 'show' ); $target.addClass( 'selected' ); // Added item this.$search .val( '' ) .before( this._getSelectedTemplate.call( this, selectedValue ) ); } }, /** * When scrolling a sheet, load the parameters. * * @param {Event} e */ scroll: function( e ) { var $target = $( e.currentTarget ); if ( !this.disableScrollLoad && !this.loaded && ( $target.scrollTop() + $target.height() ) >= e.currentTarget.scrollHeight -1 ) { this._ajax.call( this, function( items ) { if ( $.isEmptyObject( items ) ) { this.disableScrollLoad = true; } }.bind( this ) ); } }, /** * Input event handler for Search. * * @param {Event} e */ keyup: function( e ) { if ( e.keyCode === this.keyCodes.ENTER ) { // If you press enter and there are matching elements, then selected option. var search = $.trim( this.$search.val() ), $selected = $( '[data-text="'+ search +'"]:visible:first', this.$list ); if ( !$selected.length ) { $selected = $( '[data-value]:visible:first', this.$list ); } if ( $selected.length ) { $selected.trigger( 'click' ); } } if( e.keyCode === this.keyCodes.BACKSPACE ) { if ( !$.trim( this.$search.val() ) ) { this._clearMessage.call( this ); this.$list.find('.hidden').removeClass('hidden'); this.$toggle.addClass( 'show' ); } } }, /** * Show/Hide list. * * @param {Event} e */ toggleList: function( e ) { var isFocus = ( e.type === 'focus' ), pid = setTimeout( function() { this.$toggle.toggleClass( 'show', isFocus ); clearTimeout( pid ); }.bind( this ), ( isFocus ? 0 : 200 /* The delay for the blur event is necessary for the selection script to work out */ ) ); // If there is no search text, then all parameters are show. if ( !$.trim( this.$search.val() ) ) { $( '[data-value].hidden', this.$list ) .removeClass( 'hidden' ); } } }, /** * Load and search option. * * @param function callback */ _ajax: function( callback ) { if ( this.loaded ) { return; } var query_args = this._settings.ajax_query_args; // If the handler is not installed, then cancel the request. if ( ( ! query_args.hasOwnProperty( 'action' ) || query_args.action === 'unknown' ) && $.isFunction( callback ) ) { return callback.call( this, {} ); } // Request data var data = $.extend( query_args || {}, { offset: $( '[data-value]:visible', this.$list ).length, search: $.trim( this.$search.val() ), }); // Checking the last offset, it cannot be repeated repeating say that all data is loaded if ( this._offset && this._offset === data.offset ) { return; } this.loaded = true; this.$container.addClass( 'loaded' ); this._clearMessage.call( this ); this._offset = data.offset; // If the value is then add 1 to take into account the zero element of the array if ( data.offset ) { data.offset += 1; } /** * Add option to sheet. * * @param {node} $el * @param {string} name * @param {string} value */ var insertItem = function( $el, name, value ) { if ( !this.items.hasOwnProperty( value ) ) { var text = ( name || '' ).replace( /\s/, '' ).toLowerCase(), $item = $( '<div data-value="'+ usof_strip_tags( value ) +'" data-text="'+ usof_strip_tags( text ) +'" tabindex="3">'+ name +'</div>' ); $el.append( $item ); this.items[ value ] = $item; } }; // Get data $.get( ajaxurl, data, function( res ) { this.loaded = false; this.$container.removeClass( 'loaded' ); this._clearMessage.call( this ); if ( !res.success ) { this._showMessage.call( this, res.data.message ); return; } // Add to the list of new parameters $.each( res.data.items, function( value, name ) { if ( $.isPlainObject( name ) ) { $.each( name, function( _value, _name ) { var $groupList = this.$list.find( '[data-group="'+ value +'"]:first' ); if ( !$groupList.length ) { $groupList = $( '<div class="usof-autocomplete-list-group" data-group="'+ value +'"></div>' ); this.$list.append( $groupList ); } insertItem.call( this, $groupList, _name, _value ); }.bind( this ) ); } else { insertItem.call( this, this.$list, name, value ); } }.bind( this ) ); // Run callback function if ( $.isFunction( callback ) ) { callback.call( this, res.data.items ); } // We’ll run an event for watches the data update. this.trigger( 'data.loaded', res.data.items ); }.bind( this ), 'json' ); }, /** * Initializes the values. */ _initValues: function() { // Parameters which are not in the list and need to be loaded var loadParams = [], initValues = ( this.$value.val() || '' ).split( this._settings.params_separator ) || []; // Remove selecteds $( '.usof-autocomplete-selected', this.$options ).remove(); // Selection of parameters during initialization initValues.map( function( key ) { if ( !key ) { return; } var $item = $( '[data-value="' + key + '"]:first', this.$list ) .addClass( 'selected' ); if ( $item.length ) { this.$search .before( this._getSelectedTemplate.call( this, key ) ); } else { loadParams.push( key ); } }.bind( this ) ); // Loading and selection of parameters which are not in the list but must be displayed if ( loadParams.length ) { this.$search.val( this._prefix + loadParams.join( this._settings.params_separator ) ); this._ajax.call( this, function( items ) { // Reset previously selected parameters to guarantee the desired order. $( '[data-key]', this.$options ).remove(); $( '.selected', this.$list ).removeClass( 'selected' ); // Selecting parameters by an array of identifiers, this guarantees the desired order $( initValues ).each( function( _, key ) { if ( this.items.hasOwnProperty( key ) && this.items[ key ] instanceof $ ) { this.items[ key ] .addClass( 'selected' ); this.$search .before( this._getSelectedTemplate.call( this, key ) ); } }.bind( this ) ); }.bind( this ) ); this.$search.val( '' ); } }, /** * Show the message. * * @param string text The message text */ _showMessage: function( text ) { this.$list.addClass( 'hidden' ); this.$message .text( text ) .removeClass( 'hidden' ); }, /** * Clear this message. */ _clearMessage: function() { this.$list.removeClass( 'hidden' ); this.$message .addClass( 'hidden' ) .text(''); }, /** * Adding a parameter to the result * @param string key The key * @return boolean */ _addValue: function( key ) { var isNotEnabled = false, values = [], value = key; if ( this._settings.multiple ) { values = ( this.$value.val() || '' ).split( this._settings.params_separator ); for ( var k in values ) { if ( values[ k ] === key ) { isNotEnabled = true; break; } } if ( !isNotEnabled ) { values.push( key ); value = ( values || [] ).join( this._settings.params_separator ).replace(/^\,/, ''); } } if ( !isNotEnabled ) { this.$value.val( value ); this.trigger( 'change', [ value ] ); return true; } return false; }, /** * Removing a parameter from the result. * * @param string key The key */ _removeValue: function( key ) { var values = ( this.$value.val() || '' ).toLowerCase().split( this._settings.params_separator ), index = values.indexOf( '' + key ); if ( index !== - 1 ) { delete values[ index ]; // Reset indexes values = values.filter( function( item ) { return item !== undefined; } ); this.$value.val( values.join( this._settings.params_separator ) ); } this.trigger( 'change', [ this.getValue() ] ); }, /** * Get the selected template. * @param string key The key * @return string */ _getSelectedTemplate: function( key ) { var $selected = $( '[data-value="' + key + '"]:first', this.$list ); if ( !$selected.length ) { return ''; } return '<span class="usof-autocomplete-selected" data-key="' + key + '">\ ' + $selected.html() + ' <a href="javascript:void(0)" title="Remove" class="usof-autocomplete-selected-remove fas fa-trash-alt"></a>\ </span>'; }, /** * Get value * @return string */ getValue: function() { return ( this.$value instanceof $ ) ? this.$value.val() : ''; }, /** * Set values. * * @param string value The value * @param boolean quiet */ setValue: function( value, quiet ) { this.$value.val( value ); this._initValues.call( this ); if ( !quiet ) { this.trigger( 'change', [value] ); } } }; }( jQuery );