자동 완성 플러그인 결과를 사용자 정의 형식으로 지정할 수 있습니까?


답변:


233

실시간 제안으로 자동 완성

예, 원숭이 패치 자동 완성 기능을 사용할 수 있습니다.

jQuery UI v1.8rc3에 포함 된 자동 완성 위젯에서 제안 팝업은 자동 완성 위젯의 _renderMenu 함수에 생성됩니다. 이 기능은 다음과 같이 정의됩니다.

_renderMenu: function( ul, items ) {
    var self = this;
    $.each( items, function( index, item ) {
        self._renderItem( ul, item );
    });
},

_renderItem 함수는 다음과 같이 정의됩니다.

_renderItem: function( ul, item) {
    return $( "<li></li>" )
        .data( "item.autocomplete", item )
        .append( "<a>" + item.label + "</a>" )
        .appendTo( ul );
},

따라서 _renderItem fn을 원하는 효과를 생성하는 자신 만의 창작물로 바꾸어야합니다. 라이브러리에서 내부 함수를 재정의하는이 기술은 원숭이 패치 라고 합니다. 내가 한 방법은 다음과 같습니다.

  function monkeyPatchAutocomplete() {

      // don't really need this, but in case I did, I could store it and chain
      var oldFn = $.ui.autocomplete.prototype._renderItem;

      $.ui.autocomplete.prototype._renderItem = function( ul, item) {
          var re = new RegExp("^" + this.term) ;
          var t = item.label.replace(re,"<span style='font-weight:bold;color:Blue;'>" + 
                  this.term + 
                  "</span>");
          return $( "<li></li>" )
              .data( "item.autocomplete", item )
              .append( "<a>" + t + "</a>" )
              .appendTo( ul );
      };
  }

에서 해당 함수를 한 번 호출하십시오 $(document).ready(...).

이제 이것은 해킹입니다.

  • 목록에 렌더링되는 모든 항목에 대해 정규 표현식 obj가 생성됩니다. 해당 정규 표현식 obj는 모든 항목에 재사용되어야합니다.

  • 완성 된 부분의 형식에 사용되는 CSS 클래스는 없습니다. 인라인 스타일입니다.
    이는 동일한 페이지에 여러 개의 자동 완성 기능이있는 경우 모두 동일한 처리 방법을 갖음을 의미합니다. CSS 스타일로 해결할 수 있습니다.

...하지만 주요 기술을 설명하며 기본 요구 사항에 적합합니다.

대체 텍스트

업데이트 된 작업 예 : http://output.jsbin.com/qixaxinuhe


일치하는 문자열의 대소 문자를 유지하려면 입력 된 문자의 대소 문자를 사용하는 대신이 행을 사용하십시오.

var t = item.label.replace(re,"<span style='font-weight:bold;color:Blue;'>" + 
          "$&" + 
          "</span>");

즉, 위의 원래 코드부터 시작하여로 교체 this.term하면 "$&"됩니다.


편집
위 는 페이지의 모든 자동 완성 위젯을 변경 합니다. 하나만 변경하려면 다음 질문을 참조하십시오
. 페이지에서 자동 완성 인스턴스를 하나만 패치하는 방법은 무엇입니까?


감사합니다. 이에 대한 jsbin 링크가 있습니까?
— dev.e.loper

1
체인을 연결하는 경우 컨텍스트를 재설정하는 것이 중요합니다. oldFn.apply (this, [ul, item]);
— emanaton

대단히 감사합니다! 이것이 jQuery UI의 일부가되면 멋질 것입니다.
— David Ryder

4
한 가지 말은 일치하는 문자열의 일부만 (시작 부분이 아닌) 결과를 굵게 표시하려면 RegExp 줄을 다음과 같이 수정하십시오. var re = new RegExp (this.term);
— David Ryder

1
JQueryUI 자동 완성은 기본적으로 대소 문자를 구분하지 않는 검색을 수행하는 것으로 보이므로 RegExp 객체에 "i"플래그를 추가하는 것이 좋습니다. @DavidRyder가 언급했듯이 정규식에서 "^"을 사용할 이유가 없습니다. 좋아요 : 좋은 var re = new RegExp(this.term, "i"); 소식!
— Sam

65

이것은 또한 작동합니다 :

       $.ui.autocomplete.prototype._renderItem = function (ul, item) {
            item.label = item.label.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + $.ui.autocomplete.escapeRegex(this.term) + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
            return $("<li></li>")
                    .data("item.autocomplete", item)
                    .append("<a>" + item.label + "</a>")
                    .appendTo(ul);
        };

@ Jörn Zaefferer와 @Cheeso의 답변 조합.


나는 전체 단어와 일치하기 때문에이 것을 더 좋아했습니다.
— atp

3
이것은 잘 작동합니다. 주의해야 할 것은 item.label이 바뀌는 것입니다. 나는 텍스트 상자에 "<strong ..."을 받고 있었다. 대체 결과를 다른 변수에 할당하면 해당 변수가 지워집니다. 데이터에 텍스트 상자에 입력되는 값 속성이 포함되어 있으면이 문제가 발생하지 않습니다.
— Kijana Woodard

여러 값을 지원하는 자동 완성 기능이 있으면 작동하지 않습니다. 어떤 제안?
— leora

자동 완성 결과에서 텍스트를 강조 표시하는 가장 간단한 방법입니다. 위의 leora와 Kijana가 지적한대로 버그를 찾으십시오
— adamst85

전화하기 전 어디에서나 @RNKushwaha$().autocomplete()
— Brian Leishman

8

매우 도움이되었습니다. 감사합니다. +1.

다음은 "문자열은 용어로 시작해야합니다"를 기준으로 한 간단한 버전입니다.

function hackAutocomplete(){

    $.extend($.ui.autocomplete, {
        filter: function(array, term){
            var matcher = new RegExp("^" + term, "i");

            return $.grep(array, function(value){
                return matcher.test(value.label || value.value || value);
            });
        }
    });
}

hackAutocomplete();

1
감사합니다 Orolo, 여러 위치에서 자동 완성을 사용하고 입력 한 문자로 시작하는 결과 만 표시하도록 변경할 수있는 중앙 위치를 원했습니다.이 문자는 내가 정확히 필요한 것입니다!
— dreamerkumar

감사. 이것이 가장 좋은 해결책입니다. 대소 문자를 구분하지 않습니다.
— Aniket Kulkarni

7

다음은 기능적인 전체 예입니다.

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Autocomplete - jQuery</title>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.2/themes/smoothness/jquery-ui.css">
</head>
<body>
<form id="form1" name="form1" method="post" action="">
  <label for="search"></label>
  <input type="text" name="search" id="search" />
</form>

<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.2/jquery-ui.js"></script>
<script>
$(function(){

$.ui.autocomplete.prototype._renderItem = function (ul, item) {
    item.label = item.label.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + $.ui.autocomplete.escapeRegex(this.term) + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
    return $("<li></li>")
            .data("item.autocomplete", item)
            .append("<a>" + item.label + "</a>")
            .appendTo(ul);
};


var availableTags = [
    "JavaScript",
    "ActionScript",
    "C++",
    "Delphi",
    "Cobol",
    "Java",
    "Ruby",
    "Python",
    "Perl",
    "Groove",
    "Lisp",
    "Pascal",
    "Assembly",
    "Cliper",
];

$('#search').autocomplete({
    source: availableTags,
    minLength: 3
});


});
</script>
</body>
</html>

도움이 되었기를 바랍니다


6

jQueryUI 1.9.0은 _renderItem의 작동 방식을 변경합니다.

아래 코드는 이러한 변경 사항을 고려하고 Jörn Zaefferer의 jQuery Autocomplete 플러그인을 사용하여 하이라이트 일치를 수행 한 방법을 보여줍니다. 전체 검색어에서 모든 개별 용어를 강조 표시합니다.

Knockout 및 jqAuto 사용으로 이동 한 후 결과를 스타일링하는 훨씬 쉬운 방법을 찾았습니다.

function monkeyPatchAutocomplete() {
   $.ui.autocomplete.prototype._renderItem = function (ul, item) {

      // Escape any regex syntax inside this.term
      var cleanTerm = this.term.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');

      // Build pipe separated string of terms to highlight
      var keywords = $.trim(cleanTerm).replace('  ', ' ').split(' ').join('|');

      // Get the new label text to use with matched terms wrapped
      // in a span tag with a class to do the highlighting
      var re = new RegExp("(" + keywords + ")", "gi");
      var output = item.label.replace(re,  
         '<span class="ui-menu-item-highlight">$1</span>');

      return $("<li>")
         .append($("<a>").html(output))
         .appendTo(ul);
   };
};

$(function () {
   monkeyPatchAutocomplete();
});

'('와 같은 문자를 검색 할 때 정규식과의 충돌을 방지하여 어쨌든 오류 ( "Uncaught SyntaxError : Invalid regular expression : / (sam | at | () / : Unterminated group") ")가 발생합니까?
— Idan

멋진 답변! 그것이 어디에 나타나는지에 관계없이 용어를 강조하는 것을 좋아합니다. 매우 시원합니다. 게시물을 업데이트 해 주셔서 감사합니다. 내가 가진 질문 중 하나는 사용하는 .ui-menu-item-highlight 클래스에 관한 것입니다. 이것은 jquery-ui 또는 소비자가 정의 할 것으로 예상됩니까? 클래스 이름을 내 자신의 수단으로 스위트로 변경하고 단순히 글꼴 두께를 굵게 표시했습니다. .jqAutocompleteMatch { font-weight: bold; }
— 샘

@IdanShechter 좋은 의견. this.term처리하기 전에 정규식 을 이스케이프 처리하는 일부 논리를 사용해야합니다. 이 작업을 수행하는 방법에 대한 많은 답변 중 하나로 Javascript 정규식에 사용되는 이스케이프 문자열을 참조하십시오 .
— Sam

3

더 쉬운 방법으로 다음을 시도하십시오.

$('ul: li: a[class=ui-corner-all]').each (function (){      
 //grab each text value 
 var text1 = $(this).text();     
 //grab user input from the search box
 var val = $('#s').val()
     //convert 
 re = new RegExp(val, "ig") 
 //match with the converted value
 matchNew = text1.match(re);
 //Find the reg expression, replace it with blue coloring/
 text = text1.replace(matchNew, ("<span style='font-weight:bold;color:green;'>")  + matchNew +    ("</span>"));

    $(this).html(text)
});
  }

3

다음은 Ted de Koning 솔루션의 해시입니다. 다음을 포함합니다 :

  • 대소 문자를 구분하지 않는 검색
  • 검색된 문자열의 많은 항목 찾기
$.ui.autocomplete.prototype._renderItem = function (ul, item) {

    var sNeedle     = item.label;
    var iTermLength = this.term.length; 
    var tStrPos     = new Array();      //Positions of this.term in string
    var iPointer    = 0;
    var sOutput     = '';

    //Change style here
    var sPrefix     = '<strong style="color:#3399FF">';
    var sSuffix     = '</strong>';

    //Find all occurences positions
    tTemp = item.label.toLowerCase().split(this.term.toLowerCase());
    var CharCount = 0;
    tTemp[-1] = '';
    for(i=0;i<tTemp.length;i++){
        CharCount += tTemp[i-1].length;
        tStrPos[i] = CharCount + (i * iTermLength) + tTemp[i].length
    }

    //Apply style
    i=0;
    if(tStrPos.length > 0){
        while(iPointer < sNeedle.length){
            if(i<=tStrPos.length){
                //Needle
                if(iPointer == tStrPos[i]){
                    sOutput += sPrefix + sNeedle.substring(iPointer, iPointer + iTermLength) + sSuffix;
                    iPointer += iTermLength;
                    i++;
                }
                else{
                    sOutput += sNeedle.substring(iPointer, tStrPos[i]);
                    iPointer = tStrPos[i];
                }
            }
        }
    }


    return $("<li></li>")
        .data("item.autocomplete", item)
        .append("<a>" + sOutput + "</a>")
        .appendTo(ul);
};

1
나는 당신이 바퀴를 다시 발명하고 있다고 생각합니다! 이 코드보다 더 빠르고 쉽고 컴팩트 한 정규식을 사용하지 않는 이유는 무엇입니까?
— George Mavritsakis

2

다음은 정규 표현식이 필요하지 않고 레이블의 여러 결과와 일치하는 버전입니다.

$.ui.autocomplete.prototype._renderItem = function (ul, item) {
            var highlighted = item.label.split(this.term).join('<strong>' + this.term +  '</strong>');
            return $("<li></li>")
                .data("item.autocomplete", item)
                .append("<a>" + highlighted + "</a>")
                .appendTo(ul);
};

이것은 아마도 가장 좋은 해결책 일 수 있지만 string.split은 대소 문자를 구분하는 일치 만 가능합니다.
— Noel Abrahams

대소 문자를 구분하지 않고 단어를 일치시키는 방법이 있습니까? 검색 "alfa"가 있으면 "Alfa"가 강조 표시되지 않습니다
— Patrick


1

내 버전은 다음과 같습니다.

  • RegEx 대신 DOM 함수를 사용하여 문자열 나누기 / 스팬 태그 삽입
  • 지정된 자동 완성 만 영향을 받지만 전부는 아닙니다.
  • UI 버전 1.9.x에서 작동
function highlightText(text, $node) {
    var searchText = $.trim(text).toLowerCase(),
        currentNode = $node.get(0).firstChild,
        matchIndex,
        newTextNode,
        newSpanNode;
    while ((matchIndex = currentNode.data.toLowerCase().indexOf(searchText)) >= 0) {
        newTextNode = currentNode.splitText(matchIndex);
        currentNode = newTextNode.splitText(searchText.length);
        newSpanNode = document.createElement("span");
        newSpanNode.className = "highlight";
        currentNode.parentNode.insertBefore(newSpanNode, currentNode);
        newSpanNode.appendChild(newTextNode);
    }
}
$("#autocomplete").autocomplete({
    source: data
}).data("ui-autocomplete")._renderItem = function (ul, item) {
    var $a = $("<a></a>").text(item.label);
    highlightText(this.term, $a);
    return $("<li></li>").append($a).appendTo(ul);
};

일치하는 텍스트 예 강조


1

다음 코드를 사용할 수 있습니다.

lib :

$.widget("custom.highlightedautocomplete", $.ui.autocomplete, {
    _renderItem: function (ul, item) {
        var $li = $.ui.autocomplete.prototype._renderItem.call(this,ul,item);
        //any manipulation with li
        return $li;
    }
});

논리 :

$('selector').highlightedautocomplete({...});

원래 플러그인 프로토 타입 _renderItem을 덮어 쓰지 않고 무시할 수있는 사용자 정의 위젯을 작성 _renderItem합니다.

내 예제에서 일부 렌더링 코드에 원래 렌더링 기능을 사용했습니다.

자동 완성의 다른보기로 다른 장소에서 플러그인을 사용하고 코드를 깨지 않으려는 경우 중요합니다.


일반적으로 새로운 질문에 답하거나 6 년 된 질문에 대답하기보다는 답이없는 질문에 시간을 보내는 것이 좋습니다.
— zchrykng

0

타사 플러그인을 대신 사용하는 경우 강조 표시 옵션이 있습니다. http://docs.jquery.com/Plugins/Autocomplete/autocomplete#url_or_dataoptions

(옵션 탭 참조)


그래 나는이 플러그 알고 있어요 그러나,이 작업을 얻을 것이 좋을 것이다, 그래서 우리는 우리의 응용 프로그램에 jQueryUI를 사용하는 jQueryUI 자동 완성 플러그인 인치
— dev.e.loper

1
2010 년 6 월 23 일부터 jQuery 자동 완성 플러그인은 jQuery UI 자동 완성 플러그인을 위해 더 이상 사용되지 않습니다. 자세한 내용은 bassistance.de/jquery-plugins/jquery-plugin-autocomplete 를 참조하십시오
— shek

0

여러 값을 지원하려면 다음 기능을 추가하기 만하면됩니다.

function getLastTerm( term ) {
  return split( term ).pop();
}

var t = String(item.value).replace(new RegExp(getLastTerm(this.term), "gi"), "<span class='ui-state-highlight'>$&</span>");
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.