DOM 순회 메서드

지금까지 살펴본 jQuery 선택자는 DOM 트리를 참조해 아래로 내려가면서 순회하고 그 결과를 필터링해 요소 집합을 얻을 수 있게 해준다. 요소를 순회하는 방법이 아래로 내려가는 방향만 있다면 선택은 상당히 제한적일 것이다(솔직히, 일반적은 DOM 스크립트와 비교해보면 선택자 표현식 그 자체만으로도 충분히 강력하다고 할 수 있다). 하지만 때에 따라서는 부모나 조상 요소를 얻어야할 때가 있다. jQuery의 DOM 순회 메서드는 이럴 때 사용한다. 이러한 순회 메서드를 잘 사용하면 위로 혹은 아래로 그리고 모든 DOM 트리 전체를 쉽게 검색할 수 있다.



예시

Selected Shakespeare Plays

  • Comedies
    • As You Like It
    • All's Well That Ends Well
    • A Midsummer Night's Dream
    • Twelfth Night
  • Tragedies
    • Hamlet
    • Macbeth
    • Romeo and Juliet
  • Histories


Shakespeare's Plays

As You Like It Comedy
All's Well that Ends Well Comedy 1601
Hamlet Tragedy 1604
Macbeth Tragedy 1606
Romeo and Juliet Tragedy 1595
Henry IV, Part I History 1596
Henry V History 1599

Shakespeare's Sonnets

The Fair Youth 1–126
The Dark Lady 127–152
The Rival Poet 78–86


메서드 가운데 일부는 선택자 표현식과 거의 같은 표현을 사용한다. 예를 들면 alt 클래스를 추가할 때 사용했던 $('tr:even').addClass('alt');은 다음 코드처럼 .filter() 메서드로 대체할 수 있다.

							$("tr").filter(':even').addClass('alt');		
						

하지만 요소를 얻는 이 두 가지 방법은 대부분 상호 보완관계에 있다. 또한 .filter() 메서드는 함수를 인자로 지정할 수 있으므로 매우 강력하다. 이 기능을 사용하면 요소가 특정한 집합에 속하는지 아닌지 확인할 수 있는 복잡한 테스트를 만들 수 있다. 예를 들어 모든 외부 링크에 클래스를 추가한다고 했을 때 jQuery에는 모든 외부 링크에 클래스를 추가할 수 있는 선택자가 없다. filter 기능이 없다면 명시적으로 반복문을 돌려가며 일일이 검사를 해야 할 것이다. 다행이 다음 코드와 같이 filter 기능을 사용하면서 묵시적인 순환을 사용하는 간결한 코드를 작성할 수 있다.

							$("a", "#selected-plays").filter(function () {
								return this.hostname && this.hostname != location.hostname;
							}).addClass('external');
						

두 번째 줄에서는 다음 조건으로 a 요소를 필터링하고 있다.

  1. 1. href 속성값이 도메인 이름(this.hostname)을 포함해야 한다. 이 검사로 mailto 링크를 제외할 수 있다.
  2. 2. 링크된 도메일 이름(this.hostname)이 현재 페이지의 도메인 이름(location.hostname)과 같지 않아야(!=) 한다.

좀 더 자세히 말해, filter() 메서드는 일치하는 요소의 집합을 순회하면서 각 인자로 넘어온 함수를 실행하고 그 반환 값을 검사한다. 함수의 반환 값이 거짓(false)이면 요소는 일치된 집합에서 제거되고 참(true)이면 요소를 유지한다.



특정 셀에 스타일 입히기

앞서 우리는 Henry라는 텍스트를 포함하는 모든 셀에 highlight 클래스를 추가했었다. Henry라는 텍스트를 포함하는 셀의 바로 다음 셀에 스타일을 적용하려면 다음과 같이 이미 작성한 선텍자에 next() 메서드만 추가로 불러주면 된다.

							$(document).ready(function(){
								var tb = $(".div_sample_table table");
								$("td:contains(Henry)", tb).next().addClass('highlight');
							});
						

위 코드를 적용한 결과는 상기의 테이블과 같다.

.next() 메서드는 오로지 바로 뒤의 형제 요소만 반환한다. Henry를 포함하는 셀 다음에 오는 모든 셀을 선택하려면 nextAll() 메서드를 사용하면 된다.

							$(document).ready(function(){
								var tb = $(".div_sample_table table");
								$("td:contains(Henry)", tb).nextAll().addClass('highlight');
							});
						

위의 테이블에서 볼 수 있듯이 Henry는 첫 번째 셀에 있으므로 첫 번째 셀을 제외한 해당 행의 나머지 셀이 모두 강조된다.

여러분이 예상한 대로 .prev() 와 .prevAll() 는 .next()와 .nextAll()의 반대이다. 덧붙여 .siblings()는 다음에 오거나 이전에 있거나 상관 없이 같은 DOM 레벨에 있는 모든 요소를 골라낸다.

다음에 오는 셀들과 함께 원래 셀(Henry를 포함하는 셀)을 포함하려면 .andSelf() 메서드를 사용한다.

							$(document).ready(function(){
								var tb = $(".div_sample_table table");
								$("td:contains(Henry)", tb).nextAll().andSelf().addClass('highlight');
							});
						

.andSelf를 추가하면 이제 해당 행의 모든 셀이 highlight 클래스의 영향을 받는다. 다시 table을 확인해 보자.

정확히 말하자면 다중 선택자와 조회 메서드를 조합해서 위와 같은 요소를 선택하는 방법은 여러 가지다. 다음 예제는 Henry를 포함한 셀이 최소한 하나 이상 존재하는 행의 모든 셀을 선택하는 또 다른 방법이다.

							$(document).ready(function(){
								var tb = $(".div_sample_table table");
								$("td:contains(Henry)", tb).parent().children().addClass('highlight');
							});
						

여기서는 형제 요소를 모두 순회하는 대신 .parent() 메서드로 DOM 레벨상의 한 단계 위의 tr로 이동하고 .children() 메서드로 그 행의 모든 셀을 선택하고 있다.