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


답변:


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.