2013-01-14 3 views
3

Backbone.js/Underscore.js을 사용하여 입력란에 입력 할 때 필터하는 HTML 테이블을 렌더링합니다. 이 경우 기본 전화 번호부입니다.
표 내용은 JSON 파일로 채워진 모음에서 가져옵니다. JSON 파일의 기본적인 예는 다음과 같습니다 : Backbone.js - 여러 키워드가 포함 된 배열을 기반으로 컬렉션 필터링

[{ 
    "Name":"Sales and Services", 
    "Department":"Small Business", 
    "Extension":"45446", 
}, 
{ 
    "Name":"Technical Support", 
    "Department":"Small Business", 
    "Extension":"18800", 
}, 
{ 
    "Name":"Research and Development", 
    "Department":"Mid Market", 
    "Extension":"75752", 
}] 

내가 소문자 다음은이 기능에 컬렉션과 함께 값 패스 텍스트 상자의 값을 변환, 나는 다음 새 컬렉션에 반환 된 값을 할당 이를 사용하여 페이지를 다시 렌더링하십시오.

filterTable = function(collection, filterValue) { 
    var filteredCollection; 
    if (filterValue === "") { 
     return collection.toJSON(); 
    } 
    return filteredCollection = collection.filter(function(data) { 
     return _.some(_.values(data.toJSON()), function(value) { 
      value = (!isNaN(value) ? value.toString() : value.toLowerCase()); 
      return value.indexOf(filterValue) >= 0; 
     }); 
    }); 
}; 

문제는 문자가 리터럴이라는 것입니다. 필자의 예에서 "Sales and Services"부서를 찾으려면 정확하게 입력해야합니다. 아니면 "Sales"또는 "Services"라고 입력해야합니다. 나는 "sal serv"를 타이핑 할 수 없었고, 여전히 내가 할 수 있기를 원하는 것을 발견 할 수 없었다.

저는 이미 단어 배열 (이제는 사용중인 코드로 업데이트 됨)로 텍스트를 나눌 때 꽤 안정적으로 보이는 몇 가지 자바 스크립트를 작성했습니다.

"분할"배열의 각 단어를 반복하여 각 단어가 키/값 중 하나에 있는지 확인하고 싶습니다. 모든 단어가 존재하는 한 진리 반복자를 전달하고 컬렉션에 추가되어 테이블에 렌더링됩니다.

예를 들어 "sal serv"라고 입력하면 첫 번째 항목 이름에 두 문자열이 모두 포함되어 반환됩니다.
그러나 "sales business"를 입력하면 두 값이 모두 해당 항목에 표시 되더라도 같은 두 단어가 이름 섹션에 없기 때문에 반환되지 않습니다.

백본/언더 코어에 이것을 쓰는 방법을 모르거나이 방법이 최선의 방법 일지라도. 설명서를보고 어떤 기능이 가장 쉬운 지 확신하지 못했습니다.

나는 이것이 의미가 있기를 바랍니다. 나는 조금 새로운 Javascript에 익숙하다. 그리고 나는 깊은 끝으로 뛰어 들었다. 그러나 학습은 재미있는 부분이다 ;-)
필자는 필요한 경우 더 많은 코드 또는 JSFiddle을 제공 할 수있다.

답변

1

밑줄을 사용하면 anyall을 사용하는 것이 상대적으로 쉽습니다. 여기의 요지는 다음과 같습니다

var toWords = function(text) { 
    //Do any fancy cleanup and split to words 
    //I'm just doing a simple split by spaces. 
    return text.toLowerCase().split(/\s+/); 
    }; 

    var partialMatch = function(original, fragment) { 
    //get the words of each input string 
    var origWords = toWords(original + ""), //force to string 
     fragWords = toWords(fragment); 

    //if all words in the fragment match any of the original words, 
    //returns true, otherwise false 
    return _.all(fragWords, function(frag) { 
     return _.any(origWords, function(orig) { 
     return orig && orig.indexOf(frag) >= 0; 
     }); 
    }); 
    }; 

    //here's your original filterTable function slightly simplified 
    var filterTable = function(collection, filterValue) { 
     if (filterValue === "") { 
      return collection.toJSON(); 
     } 
     return collection.filter(function(data) { 
      return _.some(_.values(data.toJSON()), function(value) { 
       return partialMatch(value, filterValue); 
      }); 
     }); 
    }; 

참고 : 처음 컬렉션의 모든 항목에 걸쳐 반복 포함로이 방법은 계산이 매우 비효율적이며, 각 항목의 모든 필드, 점에서 모든 단어 항목 값 또한 루프 내부에 선언 된 몇 가지 중첩 된 함수가 있으므로 메모리 풋 프린트가 최적이 아닙니다. 작은 데이터 세트를 가지고 있다면 괜찮을 것입니다. 그러나 필요하다면 할 수있는 많은 최적화가 있습니다. 나중에 시간이 있으면 나중에 다시 돌아와 이것을 편집 할 수도 있습니다.

/코드 샘플 테스트하지 않음

+0

고마워요! 그게 나에게 아주 좋은 출발점이되었다. 내 어리 석음을 용서하지만, .any 및 .all 함수에 대한 설명서를 볼 수는 없지만, 이제는 .every 및. – Equalsk

+0

@ Equalsk, 예, 모든 사람들과 동일합니다. 두 이름 모두 작동하지만 어떤 이유로 나는 기본 이름에 대한 별명을 선호합니다. – jevakallio

+0

이것은 곧바로 작동했습니다! @fencliff에게 감사합니다. 컬렉션에는 최대 15 개의 값이있는 2000 개의 레코드 만있을 것입니다. 코드를 최적화해야한다고 생각합니까? 아직 테스트가 완료된 JSON 데이터가 없으므로 수행 방법을 알 수 없습니다. 이제는 그 개념을 이해할 수있게되었습니다. – Equalsk

관련 문제