| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- /*!
- * Copyright Ben Olson (https://github.com/bseth99/jquery-ui-extensions)
- * jQuery UI ComboBox @VERSION
- *
- * Adapted from Jörn Zaefferer original implementation at
- * http://www.learningjquery.com/2010/06/a-jquery-ui-combobox-under-the-hood
- *
- * And the demo at
- * http://jqueryui.com/autocomplete/#combobox
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- */
- (function( $, undefined ) {
- $.widget( "ui.combobox", {
- version: "@VERSION",
- widgetEventPrefix: "combobox",
- uiCombo: null,
- uiInput: null,
- _wasOpen: false,
- _create: function() {
- var self = this,
- select = this.element.hide(),
- input, wrapper;
- input = this.uiInput =
- $( "<input />" )
- .insertAfter(select)
- .addClass("ui-widget ui-widget-content ui-corner-left ui-combobox-input")
- .val( select.children(':selected').text() )
- .attr('tabindex', select.attr( 'tabindex'));
- wrapper = this.uiCombo =
- input.wrap( '<span>' )
- .parent()
- .addClass( 'ui-combobox' )
- .insertAfter( select );
- input
- .autocomplete({
- delay: 0,
- minLength: 0,
- appendTo: wrapper,
- source: $.proxy( this, "_linkSelectList" )
- });
- $( "<button>" )
- .attr( "tabIndex", -1 )
- .attr( "type", "button" )
- .insertAfter( input )
- .button({
- icons: {
- primary: "ui-icon-triangle-1-s"
- },
- text: false
- })
- .removeClass( "ui-corner-all" )
- .addClass( "ui-corner-right ui-button-icon ui-combobox-button" );
- // Our items have HTML tags. The default rendering uses text()
- // to set the content of the <a> tag. We need html().
- input.data( "ui-autocomplete" )._renderItem = function( ul, item ) {
- return $( "<li>" )
- .append( $( "<a>" ).html( item.label ) )
- .appendTo( ul );
- };
- this._on( this._events );
- },
- _linkSelectList: function( request, response ) {
- var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), 'i' );
- response( this.element.children('option').map(function() {
- var text = $( this ).text();
- if ( this.value && ( !request.term || matcher.test(text) ) ) {
- var optionData = {
- label: text,
- value: text,
- option: this
- };
- if (request.term) {
- optionData.label = text.replace(
- new RegExp(
- "(?![^&;]+;)(?!<[^<>]*)(" +
- $.ui.autocomplete.escapeRegex(request.term) +
- ")(?![^<>]*>)(?![^&;]+;)", "gi"),
- "<strong>$1</strong>");
- }
- return optionData;
- }
- })
- );
- },
- _events: {
- "autocompletechange input" : function(event, ui) {
- var $el = $(event.currentTarget);
- var changedOption = ui.item ? ui.item.option : null;
- if ( !ui.item ) {
- var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $el.val() ) + "$", "i" ),
- valid = false,
- matchContains = null,
- iContains = 0,
- iSelectCtr = -1,
- iSelected = -1,
- optContains = null;
- if (this.options.autofillsinglematch) {
- matchContains = new RegExp($.ui.autocomplete.escapeRegex($el.val()), "i");
- }
- this.element.children( "option" ).each(function() {
- var t = $(this).text();
- if ( t.match( matcher ) ) {
- this.selected = valid = true;
- return false;
- }
- if (matchContains) {
- // look for items containing the value
- iSelectCtr++;
- if (t.match(matchContains)) {
- iContains++;
- optContains = $(this);
- iSelected = iSelectCtr;
- }
- }
- });
- if ( !valid ) {
- // autofill option: if there is just one match, then select the matched option
- if (iContains == 1) {
- changedOption = optContains[0];
- changedOption.selected = true;
- var t2 = optContains.text();
- $el.val(t2);
- $el.data('ui-autocomplete').term = t2;
- this.element.prop('selectedIndex', iSelected);
- console.log("Found single match with '" + t2 + "'");
- } else {
- // remove invalid value, as it didn't match anything
- $el.val( '' );
- // Internally, term must change before another search is performed
- // if the same search is performed again, the menu won't be shown
- // because the value didn't actually change via a keyboard event
- $el.data( 'ui-autocomplete' ).term = '';
- this.element.prop('selectedIndex', -1);
- }
- }
- }
- this._trigger( "change", event, {
- item: changedOption
- });
- },
- "autocompleteselect input": function( event, ui ) {
- ui.item.option.selected = true;
- this._trigger( "select", event, {
- item: ui.item.option
- });
- },
- "autocompleteopen input": function ( event, ui ) {
- this.uiCombo.children('.ui-autocomplete')
- .outerWidth(this.uiCombo.outerWidth(true));
- },
- "mousedown .ui-combobox-button" : function ( event ) {
- this._wasOpen = this.uiInput.autocomplete("widget").is(":visible");
- },
- "click .ui-combobox-button" : function( event ) {
- this.uiInput.focus();
- // close if already visible
- if (this._wasOpen)
- return;
- // pass empty string as value to search for, displaying all results
- this.uiInput.autocomplete("search", "");
- }
- },
- value: function ( newVal ) {
- var select = this.element,
- valid = false,
- selected;
- if ( !arguments.length ) {
- selected = select.children( ":selected" );
- return selected.length > 0 ? selected.val() : null;
- }
- select.prop('selectedIndex', -1);
- select.children('option').each(function() {
- if ( this.value == newVal ) {
- this.selected = valid = true;
- return false;
- }
- });
- if ( valid ) {
- this.uiInput.val(select.children(':selected').text());
- } else {
- this.uiInput.val( "" );
- this.element.prop('selectedIndex', -1);
- }
- },
- _destroy: function () {
- this.element.show();
- this.uiCombo.replaceWith( this.element );
- },
- widget: function () {
- return this.uiCombo;
- },
- _getCreateEventData: function() {
- return {
- select: this.element,
- combo: this.uiCombo,
- input: this.uiInput
- };
- }
- });
- }(jQuery));
|