JQuery Autocomplete. Как выделить совпадения?

543
20 ноября 2017, 21:33

Встала задача сделать поисковик по dropdown. Решил реализовать на jquery. Взял готовый пример с официального сайта.

Единственное, что меня не устроило - это то, что совпадения в тексте не выделяются жирным шрифтом. Я изменил код так, чтобы совпадения брались в теги <strong>...</strong>.

Подробнее о проблематике: Мне нужно жирным выделять буквы и цифры, которые совпадают с критерием поиска. Например, я ввожу asi или avascr и в dropdown menu текст должен иметь такой вид: BASIC или JavaScript соответственно.

Однако, теги не заменяются на стили. Может кто знает, как это исправить?

$( function() { 
    $.widget( "custom.combobox", { 
      _create: function() { 
        this.wrapper = $( "<span>" ) 
          .addClass( "custom-combobox" ) 
          .insertAfter( this.element ); 
  
        this.element.hide(); 
        this._createAutocomplete(); 
        this._createShowAllButton(); 
      }, 
  
      _createAutocomplete: function() { 
        var selected = this.element.children( ":selected" ), 
          value = selected.val() ? selected.text() : ""; 
  
        this.input = $( "<input>" ) 
          .appendTo( this.wrapper ) 
          .val( value ) 
          .attr( "title", "" ) 
          .addClass( "custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left" ) 
          .autocomplete({ 
            delay: 0, 
            minLength: 0, 
            source: $.proxy( this, "_source" ) 
          }) 
          .tooltip({ 
            classes: { 
              "ui-tooltip": "ui-state-highlight" 
            } 
          }); 
  
        this._on( this.input, { 
          autocompleteselect: function( event, ui ) { 
            ui.item.option.selected = true; 
            this._trigger( "select", event, { 
              item: ui.item.option 
            }); 
          }, 
  
          autocompletechange: "_removeIfInvalid" 
        }); 
      }, 
  
      _createShowAllButton: function() { 
        var input = this.input, 
          wasOpen = false; 
  
        $( "<a>" ) 
          .attr( "tabIndex", -1 ) 
          .attr( "title", "Show All Items" ) 
          .tooltip() 
          .appendTo( this.wrapper ) 
          .button({ 
            icons: { 
              primary: "ui-icon-triangle-1-s" 
            }, 
            text: false 
          }) 
          .removeClass( "ui-corner-all" ) 
          .addClass( "custom-combobox-toggle ui-corner-right" ) 
          .on( "mousedown", function() { 
            wasOpen = input.autocomplete( "widget" ).is( ":visible" ); 
          }) 
          .on( "click", function() { 
            input.trigger( "focus" ); 
  
            // Close if already visible 
            if ( wasOpen ) { 
              return; 
            } 
  
            // Pass empty string as value to search for, displaying all results 
            input.autocomplete( "search", "" ); 
          }); 
      }, 
  
      _source: function( request, response ) { 
        var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "gi"); 
        response( this.element.children( "option" ).map(function() { 
            var text = $(this).text().replace(matcher, function(str) { 
                return '<strong>' + str + '</strong>' 
            }); 
          if ( this.value && ( !request.term || matcher.test(text) ) ) 
            return { 
              label: text, 
              value: text, 
              option: this 
            }; 
        }) ); 
      }, 
  
      _removeIfInvalid: function( event, ui ) { 
  
        // Selected an item, nothing to do 
        if ( ui.item ) { 
          return; 
        } 
  
        // Search for a match (case-insensitive) 
        var value = this.input.val(), 
          valueLowerCase = value.toLowerCase(), 
          valid = false; 
        this.element.children( "option" ).each(function() { 
          if ( $( this ).text().toLowerCase() === valueLowerCase ) { 
            this.selected = valid = true; 
            return false; 
          } 
        }); 
  
        // Found a match, nothing to do 
        if ( valid ) { 
          return; 
        } 
  
        // Remove invalid value 
        this.input 
          .val( "" ) 
          .attr( "title", value + " didn't match any item" ) 
          .tooltip( "open" ); 
        this.element.val( "" ); 
        this._delay(function() { 
          this.input.tooltip( "close" ).attr( "title", "" ); 
        }, 2500 ); 
        this.input.autocomplete( "instance" ).term = ""; 
      }, 
  
      _destroy: function() { 
        this.wrapper.remove(); 
        this.element.show(); 
      } 
    }); 
  
    $( "#combobox" ).combobox(); 
    $( "#toggle" ).on( "click", function() { 
      $( "#combobox" ).toggle(); 
    }); 
  } );
<script src="https://code.jquery.com/jquery-1.12.4.js"></script> 
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> 
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"> 
   
<div class="ui-widget"> 
  <label>Your preferred programming language: </label> 
  <select id="combobox"> 
    <option value="">Select one...</option> 
    <option value="ActionScript">ActionScript</option> 
    <option value="AppleScript">AppleScript</option> 
    <option value="Asp">Asp</option> 
    <option value="BASIC">BASIC</option> 
    <option value="C">C</option> 
    <option value="C++">C++</option> 
    <option value="Clojure">Clojure</option> 
    <option value="COBOL">COBOL</option> 
    <option value="ColdFusion">ColdFusion</option> 
    <option value="Erlang">Erlang</option> 
    <option value="Fortran">Fortran</option> 
    <option value="Groovy">Groovy</option> 
    <option value="Haskell">Haskell</option> 
    <option value="Java">Java</option> 
    <option value="JavaScript">JavaScript</option> 
    <option value="Lisp">Lisp</option> 
    <option value="Perl">Perl</option> 
    <option value="PHP">PHP</option> 
    <option value="Python">Python</option> 
    <option value="Ruby">Ruby</option> 
    <option value="Scala">Scala</option> 
    <option value="Scheme">Scheme</option> 
  </select> 
</div>

P.S. Проблема связана с тем, что strong'и при вставке преобразуются в текст, а не в теги. Так можно заметить, что внешний вид текст в исходном коде имеет следующий вид:

<div id="ui-id-123" tabindex="-1" class="ui-menu-item-wrapper">&lt;strong&gt;As&lt;/strong&gt;p</div>

вместо

<div id="ui-id-123" tabindex="-1" class="ui-menu-item-wrapper"><strong>As</strong>p</div>

Это и вызывает проблему

Answer 1

Может и подойдёт какая идея:

1) как вариант, самый короткий и может не самый красивый

.ui-menu-item{
font-weight: bold
}

$( function() { 
    $.widget( "custom.combobox", { 
      _create: function() { 
        this.wrapper = $( "<span>" ) 
          .addClass( "custom-combobox" ) 
          .insertAfter( this.element ); 
  
        this.element.hide(); 
        this._createAutocomplete(); 
        this._createShowAllButton(); 
      }, 
  
      _createAutocomplete: function() { 
        var selected = this.element.children( ":selected" ), 
          value = selected.val() ? selected.text() : ""; 
  
        this.input = $( "<input>" ) 
          .appendTo( this.wrapper ) 
          .val( value ) 
          .attr( "title", "" ) 
          .addClass( "custom-combobox-input ui-widget ui-widget-content ui-state-default ui-corner-left" ) 
          .autocomplete({ 
            delay: 0, 
            minLength: 0, 
            source: $.proxy( this, "_source" ) 
          }) 
          .tooltip({ 
            classes: { 
              "ui-tooltip": "ui-state-highlight" 
            } 
          }); 
  
        this._on( this.input, { 
          autocompleteselect: function( event, ui ) { 
            ui.item.option.selected = true; 
            this._trigger( "select", event, { 
              item: ui.item.option 
            }); 
          }, 
  
          autocompletechange: "_removeIfInvalid" 
        }); 
      }, 
  
      _createShowAllButton: function() { 
        var input = this.input, 
          wasOpen = false; 
  
        $( "<a>" ) 
          .attr( "tabIndex", -1 ) 
          .attr( "title", "Show All Items" ) 
          .tooltip() 
          .appendTo( this.wrapper ) 
          .button({ 
            icons: { 
              primary: "ui-icon-triangle-1-s" 
            }, 
            text: false 
          }) 
          .removeClass( "ui-corner-all" ) 
          .addClass( "custom-combobox-toggle ui-corner-right" ) 
          .on( "mousedown", function() { 
            wasOpen = input.autocomplete( "widget" ).is( ":visible" ); 
          }) 
          .on( "click", function() { 
            input.trigger( "focus" ); 
  
            // Close if already visible 
            if ( wasOpen ) { 
              return; 
            } 
  
            // Pass empty string as value to search for, displaying all results 
            input.autocomplete( "search", "" ); 
          }); 
      }, 
  
      _source: function( request, response ) { 
        var matcher = new RegExp($.ui.autocomplete.escapeRegex(request.term), "gi"); 
        response( this.element.children( "option" ).map(function() { 
            var text = $(this).text().replace(matcher, function(str) { 
                return str  
            }); 
          if ( this.value && ( !request.term || matcher.test(text) ) ) 
            return { 
              label: text, 
              value: text, 
              option: this 
            }; 
        }) ); 
      }, 
  
      _removeIfInvalid: function( event, ui ) { 
  
        // Selected an item, nothing to do 
        if ( ui.item ) { 
          return; 
        } 
  
        // Search for a match (case-insensitive) 
        var value = this.input.val(), 
          valueLowerCase = value.toLowerCase(), 
          valid = false; 
        this.element.children( "option" ).each(function() { 
          if ( $( this ).text().toLowerCase() === valueLowerCase ) { 
            this.selected = valid = true; 
            return false; 
          } 
        }); 
  
        // Found a match, nothing to do 
        if ( valid ) { 
          return; 
        } 
  
        // Remove invalid value 
        this.input 
          .val( "" ) 
          .attr( "title", value + " didn't match any item" ) 
          .tooltip( "open" ); 
        this.element.val( "" ); 
        this._delay(function() { 
          this.input.tooltip( "close" ).attr( "title", "" ); 
        }, 2500 ); 
        this.input.autocomplete( "instance" ).term = ""; 
      }, 
  
      _destroy: function() { 
        this.wrapper.remove(); 
        this.element.show(); 
      } 
    }); 
  
    $( "#combobox" ).combobox(); 
    $( "#toggle" ).on( "click", function() { 
      $( "#combobox" ).toggle(); 
    }); 
  } );
.ui-menu-item{ 
font-weight: bold 
}
<script src="https://code.jquery.com/jquery-1.12.4.js"></script> 
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> 
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"> 
   
<div class="ui-widget"> 
  <label>Your preferred programming language: </label> 
  <select id="combobox"> 
    <option value="">Select one...</option> 
    <option value="ActionScript">ActionScript</option> 
    <option value="AppleScript">AppleScript</option> 
    <option value="Asp">Asp</option> 
    <option value="BASIC">BASIC</option> 
    <option value="C">C</option> 
    <option value="C++">C++</option> 
    <option value="Clojure">Clojure</option> 
    <option value="COBOL">COBOL</option> 
    <option value="ColdFusion">ColdFusion</option> 
    <option value="Erlang">Erlang</option> 
    <option value="Fortran">Fortran</option> 
    <option value="Groovy">Groovy</option> 
    <option value="Haskell">Haskell</option> 
    <option value="Java">Java</option> 
    <option value="JavaScript">JavaScript</option> 
    <option value="Lisp">Lisp</option> 
    <option value="Perl">Perl</option> 
    <option value="PHP">PHP</option> 
    <option value="Python">Python</option> 
    <option value="Ruby">Ruby</option> 
    <option value="Scala">Scala</option> 
    <option value="Scheme">Scheme</option> 
  </select> 
</div>

2) можно посмотреть разные темы оформления.
У Вас base сейчас

<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">

На данный момент темы для jQuery UI 1.12 (- base - black-tie - blitzer - cupertino - dark-hive - dot-luv - eggplant - excite-bike - flick - hot-sneaks - humanity - le-frog - mint-choc - overcast - pepper-grinder - redmond - smoothness - south-street - start sunny - swanky-purse - trontastic - ui-darkness - ui-lightness - vader)

3) Сами разработчики рекомендуют использовать CSS, это протестированный и отлаженный метод Официальный сайт. Коротко основное:

  • Использовать дизайнер стилей (http://learn.jquery.com/jquery-ui/themeroller/)
  • Изменить файл CSS jquery-ui.theme.css
  • Написать собственный файл

    4) Продолжение следует

READ ALSO
Почему происходит переполнение при 2^31 xor 0

Почему происходит переполнение при 2^31 xor 0

Здравствуйте,не понимаю,почему alert( Mathpow(2, 31) ^ 0 ); дает результат -2147483648

354
Javascript код в представлении Yii2

Javascript код в представлении Yii2

Правильно ли размещать javascript-код в вьюшках где лежит PHP код или его надо размещать где то в другом месте?

323
Как вывести сумму нечетных чисел циклом от 11 до 30 do-while на PHP

Как вывести сумму нечетных чисел циклом от 11 до 30 do-while на PHP

Как вывести сумму нечетных чисел циклом от 11 до 30 do-while на PHP

377
Как поправить кодировку?

Как поправить кодировку?

Делаю проверку на палиндром, но с русскими символами, что то не такПочему кодировка кривая? Кто то подскажет ?

290