jQuery

jquery 시작 2009. 6. 30. 16:31


1. 왜 jQuery 인가 ?

페이지에 동적인 기능을 추가하기 위해서는 element , element group 을 선택하여, 선택된 element 를 페이지에서 감추거나 보여주고, 해당 element 에 CSS 클래스를 추가하거나 애니메이션 효과를 주어야 하는 데, 이런 경우 수십줄의 자바스크립트 코드를 직접 작성해야 합니다. 그러나 jQuery 를 이용하면 수십줄의 코드를 한두줄의 코드로 줄일 수 있습니다.

아래의 같이 행간의 색상이 대비되는 얼룩무늬 형태의 테이블을 만들 경우 기존 자바스크립트를 이용하면 열줄이상을 작성하셔야 합니다.
jQuery 라이브러리를 사용시에는 아래와 같이 한줄로 작성이 가능합니다. (여기에 jQuery 의 강력함이 있는 것 같습니다.)

$("table tr:nth-child(even)").addClass("striped");  



  •  FULL SOURCE

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
    <html>
      <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>얼룩 무늬</title>
        <script type="text/javascript" src="../scripts/jquery-1.2.1.js">
        </script>
        <script type="text/javascript">
          $(function() {
            $("table tr:nth-child(even)").addClass("striped");
          });
        </script>
        <style>
          body,td {
            font-size: 10pt;
          }
          table {
            background-color: black;
            border: 1px black solid;
            border-collapse: collapse;
          }
          th {
            border: 1px outset silver;
            background-color: maroon;
            color: white;
          }
          tr {
            background-color: white;
            margin: 1px;
          }
          tr.striped {
            background-color: coral;
          }
          td {
            padding: 1px 8px;
          }
        </style>
      </head>

  <body>
    <table>
      <tr>
        <th>생산연도</th>
        <th>제조사</th>
        <th>모델</th>
      </tr>
      <tr>
        <td>1965</td>
        <td>Ford</td>
        <td>Mustang</td>
      </tr>
      <tr>
        <td>1970</td>
        <td>Toyota</td>
        <td>Corolla</td>
      </tr>
      <tr>
        <td>1979</td>
        <td>AMC</td>
        <td>Jeep CJ-5</td>
      </tr>
      <tr>
        <td>1983</td>
        <td>Ford</td>
        <td>EXP</td>
      </tr>
      <tr>
        <td>1985</td>
        <td>Dodge</td>
        <td>Daytona</td>
      </tr>
      <tr>
        <td>1990</td>
        <td>Chrysler</td>
        <td>Jeep Wrangler Sahara</td>
      </tr>
      <tr>
        <td>1995</td>
        <td>Ford</td>
        <td>Ranger</td>
      </tr>
      <tr>
        <td>1997</td>
        <td>Chrysler</td>
        <td>Jeep Wrangler Sahara</td>
      </tr>
      <tr>
        <td>2000</td>
        <td>Chrysler</td>
        <td>Jeep Wrangler Sahara</td>
      </tr>
      <tr>
        <td>2005</td>
        <td>Chrysler</td>
        <td>Jeep Wrangler Unlimited</td>
      </tr>
      <tr>
        <td>2007</td>
        <td>Dodge</td>
        <td>Caliber R/T</td>
      </tr>
    </table>
  </body>
</html>

2. unobtrusive 자바스크립트

HTML 문서에서 스타일정보를 분리하는 것과 마찬가지로 문서에서 동작을 분리해서 사용하는 방법을 말합니다.
jQuery 의 창시자는 개발자들이 쉽게 동작을 분리할 수 있도록 라이브러리를 설계했습니다. (존경심이 나오네요 ^^)
사실 unobtrusive 자바스크립트에서는 HTML 페이지의 <body> 태그에 포함된 자바스크립트 표현식이나 구문은 잘못된 것으로 본다고 합니다.

아래는 기존의 방식에서 동작을 분리하는 방법에 대한 간단한 예제입니다.

기존방식 :
<button type="button" onclick="document.getElementById('xyz').style.color='red';">클릭하시오.</button>

jQuery 를 사용해서 변경 :
<button type="button" id="testButton">클릭하시오.</button>

<script type="text/javascript">
     window.onload = function() {
          document.getElementById('testButton').onclick = makeItRed;
     };

     function makeItRed()  {
         document.getElementById('xyz').style.color = 'red';
     }
</script>

unobtrusive 자바스크립트를 구현할 경우 위의 경우와 같이 코드의 양이 많이지는 불편함이 있습니다. 
하지만 jQuery 를 이용할 경우 적은 코드의 양으로도 동일한 효과를 얻을 수 있습니다.

Posted by 바람이불면
,

스크립트 라이브러리의 시대 그리고 jQuery

필자의 잡담~

이번엔 빠르게 마무리 해보리라 맘 먹고 써보는 jQuery 강좌입니다.
무엇보다 제 자신에게 자극이 되는 강좌이기를 바라고 있어요.

jQuery는 최근 각광을 받고 있는 경량의 오픈 소스 자바스크립트 라이브러리의 이름입니다. 물론, 최근에 한번씩은 들어보셨죠? 지난 1월에 있었던 태오 사이트 신년 세미나(비정기)에서도 정석모 시삽이 이에 대한 이야기를 발표해서 저는 능가하는 인기를 끌었던 바로 그 소재이기도 합니다.

기존에 Ajax를 해 보신 분은 익히(?) 들어보셨을 것이라 예상되는 이 라이브러리는 prototype이나 ExtJs, Dojo 등과 유사한 스크립트 라이브러리 혹은 스크립트 프레임워크라고 보시면 됩니다. 이는 리치 웹, Ajax의 진화와 함께 요즘의 트렌드에 맞춰 개량된 신예 라이브러리인데요. 업계 선두이자 전설인 prototype 라이브러리를 제치고 세계적으로 가장 많이 사용되는 라이브러리로 자리를 잡고 있습니다. 2008년 후반에 이미 사용률이 60%에 가까웠죠. http://www.rubyrailways.com/rails-rumble-observations-part-i-jquery-on-the-heels-of-prototype/가 보시면 그 내용을 확인하실 수 있습니다. 더 최근의 자료는 제 검색 능력이 후덜덜이라 찾을 수가 없었습니다만, 이미 70%를 넘어섰다는 이야기도 얼마 전에 들었습니다.

사실, prototype도 여전히 괜찮은 라이브러리이긴 합니다만, 최근의 추세는 jQuery쪽 손을 들어주고 있는 편입니다. 이에 관해서는 다음 글을 한번 읽어보시기 바랍니다. http://www.quarkruby.com/2007/11/6/why-i-moved-from-prototype-to-jquery. 물론, 이러한 스크립트 라이브러리 혹은 프레임워크는 지극히 개발자의 개인 취향이나 팀 취향에 따라 호감도가 다르기에 이견이 있을 수 있습니다만, 요즘의 추세가 확실히 jQuery인 것은 분명해 보입니다. 수 많은 사이트에서 [소스 보기]를 해보면 jQuery 코드를 쉽게 볼 수 있기 때문이지요. 그리고, 실제로 이를 써 보면 그 매력에 반하게 되기도 하고요. 아참. 방금 위의 링크는 영어 원문인데요. “Why I moved from Prototype to jQuery”라는 제목으로 구글 검색을 해보면, 이 글을 번역해 놓은 블로그 글도 보실 수 있습니다.

게다가, 2008년 9월에는 Microsoft가 공식적으로 JQuery의 유용성을 인정하고, 차기 Visual Studio에서는 jQuery를 MIT 라이선스(http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt)인 상태로 포함시킬 것임을 발표하기도 했습니다. 게다가, jQuery에 대한 인텔리센스도 제공할 것이며 ASP.NET AJAX에서도 긴밀하게 사용될 것임을 발표하여 jQuery에 더욱 큰 힘을 실어주기도 했죠.

그래서인지, 최근의 외국 웹 사이트를 보면 대부분의 스크립트들이 jQuery로 구현되어 있는 것을 심심찮게 볼 수 있습니다. 이 말은 결국 앞으로 웹 개발을 하는 개발자들은 jQuery에 대한 지식을 미리 갖출 경우, 더욱 경쟁력 있는 개발자로 설 수 있을 것임을 의미하기도 합니다. jQuery를 다룰 줄 안다면 경쟁력이 있다는 이야기는 제 개인적인 생각이 아니라 실제로 외국 구직 사이트에 올라온 통계를 토대로 드린 말씀입니다. 다음 그림을 살펴보시기 바랍니다. 출처는 http://www.indeed.com/jobtrends?q=jquery%2C+dojo%2C+yui 입니다.

네. 뭐 일단 떡밥은 충분히 던져진 것 같다는 생각이 듭니다(최근의 온라인 유머 스타일을 따라한 것이니 ‘떡밥’이라는 단어에 오해하시고 기분 나빠하지 않으셨으면 합니다).

jQuery의 위상 및 사용율이 크게 올라감에 따라, 차기 웹 애플리케이션의 개발 구도도 아마 ASP.NET MVC + jQuery의 조합 형태가 되지 않을까 하는 생각을 해 봅니다. 물론, WebForm 기반의 개발이 아예 사라질 것은 아니기에, 그러한 경우에는 ASP.NET이 기본적인 UI 골격을 렌더링하는 역할을 담당하면서 jQuery와 WCF(혹은 웹 서비스)로 연동되는 아키텍처도 고려해 볼만 합니다. 이는 기존 개발 스타일을 유지하면서 점진적으로 MVC로 옮겨갈 수 있다는 장점이 있겠죠(사실, Ajax가 일반화되고, jQuery가 득세하면서 ASP.NET 서버 컨트롤의 필요성은 갈수록 줄어들고 있는 것이 사실이니까요).


Case 1. jQuery + ASP.NET MVC


Case 2. jQuery + ASP.NET WebForm(UI 렌더링) + WCF(혹은 웹 서비스)

서론이 길었는데요. 그래서 하고 싶은 말은 이러한 jQuery에 대해서 작게나마 강좌를 진행해볼까 한다는 것입니다. 아주 상세한 내용은 IT의 경기를 살리기 위해서라도 “책을 사서” 보실 것을 권장하고요. 제 강좌는 jQuery의 유용함과 초급 사용법 정도에 초점을 두고 2~3회 정도로 진행을 해볼까 합니다. 아직 이전 강좌인 예외처리 기법에 대한 강좌도 마무리를 못한 상태라서요 ^^;

그럼 다음 강좌부터 본격적으로 시작해 봅니다.


authored by Taeyo

Posted by 바람이불면
,

jQuery : 폼 필터 및 조작 메서드(each 등)

필자의 잡담~

강좌가 좀 늦어졌네요.
실은 재미삼아 시작한 게시판 만들기에 뜻밖에 심취하는 바람에 그랬어요.
http://taeyo.net/jQueryBoard ^^;

강좌가 좀 늦어졌네요. 그냥 데모 수준으로 가볍게 만들어 보려 한 게시판에 의외로 몰입하게 되는 바람에 한 10일 정도 jQueryBoard를 만들게 되어서 그리 되었습니다. http://taeyo.net/jQueryBoard 가 그것인데요. 아직 손을 봐야 할 것들이 남아있긴 합니다만, 그런대로 기본 기능들은 다 갖춘 것 같습니다. 습작이니 너무 예리한 눈으로 보진 마시고요. 그냥 이렇게 jQuery를 적용할 수도 있다는 수준으로 봐주시면 감사하겠습니다. 그러면, 이제 강좌로 들어가 볼까요?

이번 강좌는 셀렉터의 마지막 강좌로 폼과 관련된 셀렉터에 대해서 알아볼까 합니다. 사실상, 웹 페이지에서 서버로 데이터를 전송하려면 입력 UI로 다양한 폼 컨트롤들을 사용할 수 밖에 없는데요. 이는 Ajax 기반의 웹 페이지라 해도 다를 것이 없습니다. 해서, 폼 관련 요소들은 다양한 HTML 요소들 중 상당히 중요한 요소라 할 수 있고, 그렇기에, 이와 직접적으로 연관된 폼 필터들도 마찬가지로 매우 중요하다고 우겨볼 수 있을 것 같습니다. 하하. 하지만, 정말로 그럴까요?

이미 이전 강좌를 통해서 필터의 역할이나 사용방법은 알고 계실 테니까요. 폼 필터들에는 어떤 것들이 있는지 일단 정리한 것을 먼저 보고 이야기를 계속해 나가보겠습니다.

:input 모든 input, textarea, select, button요소들과 일치됩니다
:text text 타입의 모든 input 요소들과 일치됩니다.
:password password타입의 모든 input 요소들과 일치됩니다.
:radio radio 타입의 모든 input 요소들과 일치됩니다.
:checkbox checkbox 타입의 모든 input 요소들과 일치됩니다.
:submit submit 타입의 모든 input 요소들과 일치됩니다.
:image image 타입의 모든 input 요소들과 일치됩니다.
:reset reset 타입의 모든 input 요소들과 일치됩니다.
:button 모든 button 요소들 및 button 타입의 input 요소들과 일치됩니다.
:file file 타입의 모든 input 요소들과 일치됩니다.
:hidden hidden 상태인 모든 요소들과 일치됩니다.

이미 필터에 익숙한 여러분이기에 보면서 이해가 되실텐데요. 보이는 것처럼 모든 입력 컨트롤을 선택하고 싶다면 $(":input") 라고 작성하면 되고, 체크박스만 선택하고 싶다면 $(":checkbox")라고 jQuery를 작성하면 됩니다. 히든 필드는 $(":hidden") 이라고 작성해서 선택할 수 있고요. 호오~ 깔끔하네요.

하지만, 생각 외로 이 폼 필터들을 자주 사용할 일은 없는 편인데요(물론, 사용하기 나름이겠지만 저의 경우는 그다지 사용할 일이 많지 않았습니다). 이는 일반적으로 $("input#UserID")이나 $("input.required") 와 같이 특정 목적을 위한 입력 컨트롤들을 콕 찝어서 접근하는 방식을 더 선호하기 때문이 아닐까 합니다. 사실, 모든 입력 컨트롤을 선택한다거나, 모든 라디오 버튼을 선택한다거나 할 일은 그리 많지 않죠.

반면, 체크박스 중 체크된 것들을 모두 알아온다던가, 셀렉트 컨트롤들 중에서 선택된 것들을 알아낸다던가 하는 작업은 상대적으로 자주 요구되는 일 중에 하나입니다. 예를 들어, 사용자가 체크한 값들이나 선택한 값들을 화면에 출력해주는 일을 생각해 볼 수 있습니다. 다음의 코드를 한번 볼까요?

var sports $("input:checkbox");
for 
(var 0i < sports.lengthi++) {
  
if (sports[i].checked == true) {
    
//두 썸띵!
  
}
}

이는 체크박스 필터를 사용해서, 우선 현재 페이지에 있는 모든 체크박스들을 얻어온 뒤, 전체 요소들만큼 for 루프문을 반복하면서 해당 체크박스가 checked 상태인지를 검사하고, 만일, 체크가 된 상태라면 "두 썸띵"을 하는 코드입니다. ^^;

앞서서 설명을 드렸었는지 기억이 가물해서 언급하자면 var sports = $("input:checkbox"); 와 같은 셀렉터 혹은 셀렉터 필터에 의해 반환하는 개체는 Html 요소들의 배열입니다. 즉, sports 라는 변수는 Html 요소들의 배열이지, jQuery 개체의 배열이 아니라는 것이죠.

상기 코드는 현재 페이지에 존재하는 모든 체크박스들을 일일히 확인해가면서 선택된 것을 찾아내는 코드입니다만, jQuery의 필터 중에는 이와 같은 작업을 보다 쉽게 해주는 필터들도 있습니다. 바로 다음과 같은 것들이죠.

:enabled 현재 enable 상태인 모든 요소와 일치됩니다.
:disabled 현재 disable 상태인 모든 요소와 일치됩니다.
:checked 체크된 모든 요소들과 일치됩니다.
:selected 선택된 모든 요소들과 일치됩니다.

예를 들면, :checked 와 같은 필터는 폼에서 체크된 모든 요소들을 선택하게 됩니다. 즉, 이 필터를 사용하면 모든 체크박스를 일일히 확인할 필요없이, 체크가 된 체크박스들만을 얻어올 수 있다는 것이죠. 해서, 이 필터를 사용하면 이전의 체크박스 확인 코드가 다음과 같이 좀 더 간단해 질 수 있습니다.

var sports $("input:checked");
var 
result "";
for 
(var 0i < sports.lengthi++) {
  
//두 썸띵!
}

전과 비교했을 때, if (sports[i].checked == true){ .. } 와 같은 코드를 사용할 필요가 없게 된 것이죠. 이미 필터를 통해서 체크된 요소들만 가져와진 상태니까요 ^^.

자. 그럼 간단한 예제를 통해서 확인을 해볼까요?

<html>
<head>
    
<title></title>
<script src="js/jquery-1.3.2.min.js" type="text/javascript"></script>
    
<script type="text/javascript">
        $(
document).ready(function() {

            $(
"#DoIt").click(function() {
                
var sports $("input:checked");
                var 
result "";
                for 
(var 0i < sports.lengthi++) {
                        result +
$(sports[i]).next().text() + ",";
                
}
                $(
"#result").text(result);
            
});
});
    </
script>
</head>
<body>
    
<p>
        스포츠 :
<input id="c1" type="checkbox" /><label for="c1">농구</label>
        
<input id="c2" type="checkbox" /><label for="c2">배구</label>
        
<input id="c3" type="checkbox" /><label for="c3">축구</label>
        
<input id="c4" type="checkbox" /><label for="c4">야구</label>
    
</p>
<p>
        
<input id="DoIt" type="button" value="선택" />
</
p>
    
<p>
        당신이 선택하신 스포츠는 
<span id="result"></span> 입니다.
    
</p>
</body>
</html>

우선, HTML 코드들부터 살펴보도록 하세요. 화면에는 4개의 체크박스가 존재하고 있고, 1개의 버튼과 1개의 출력용 span 구역이 정의되어 있습니다. 그리고, 구현하려는 기능은 사용자가 몇몇 체크박스에 체크를 하고, "선택" 버튼을 클릭하면, span 영역에 그 선택된 값들을 출력하려는 것입니다. 매우 간단한 예제이긴 하죠?

하지만, 스크립트 구역의 소스는 생각보다 설명을 드릴 것이 조금 많네요. 하지만, 재미있는 내용이니 기쁘게 설명해 보도록 할게요. 우선 이벤트에 관한 것부터 설명 드리겠습니다. 사실, 이벤트에 관한 부분은 추후에 설명드릴 예정인 부분이지만, 예제에서 등장을 했으니 조금쯤은 설명을 드리고 가야 할 듯 합니다.

우선, $(document).ready()라는 이벤트 메서드를 보세요. 이것! 기억하시죠? 그렇습니다. 이는 jQuery가 제공하는 페이지 로드 이벤트 함수(마치, window.load와 유사한)라고 제가 2번째 강좌에서 간략하게 설명을 드렸었습니다. 그리고, 그 메서드 인자로는 함수를 작성한다고 말씀을 드렸었죠. 즉, 다음과 같이 말입니다.

$(document).ready(pageLoad);
function 
pageLoad()
{
   
//.. 페이지 로드시에 할 일
}

하지만, 일반적으로는 저렇게 굳이 함수를 분리해서 작성할 이유가 없어서, pageLoad라는 함수를 별도로 작성하지 않고, 그냥 다음과 같이 익명 함수로 작성하는 편입니다.

$(document).ready(
   
function()
   {
      
//.. 페이지 로드시에 할 일
   
}
)
;

그리고, 대부분은 가독성을 위해서 다음과 같이 붙여서 쓰곤 하는 편이죠.

$(document).ready(function(){
    
//.. 페이지 로드시에 할 일
});

이렇게 말이죠. 해서, 예제에서의 코드도 이러한 코드 내부에 작성된 것을 보실 수 있습니다. 혹시라도, 이전에 이 코드가 왜 이렇게 작성된 것인지 잘 이해가 안되셨던 분들은 이제는 좀 감을 잡으셨을 것이라 생각합니다(그리고, 이와 같은 류의 코드가 jQuery에서는 대단히 자주 등장합니다. 진짜로 100초 안에 다시 등장할 겁니다).

그 이후 등장하는 소스를 계속해서 보시면, 페이지가 준비가 되는대로(즉, ready() 함수 안에서) 다음과 같은 코드를 사용해서 버튼에 click 이벤트를 걸어주는 것을 볼 수 있습니다.

$("#DoIt").click( someFunction );

이는 #DoIt이라는 개체에게 동적으로 클릭 이벤트를 걸어주는 jQuery 코드입니다. 사실, 이는 document.getElementById("DoIt").click = someFunction; 이라는 자바스크립트 함수와 같은 것이라 볼 수 있죠. 하지만, 코드가 간결하고, 메서드 체인을 통해서 여러 작업을 이어서 지정할 수 있다는 장점이 있습니다. 예를 들면, 다음과 같이 말입니다.

$("#DoIt").click( someFunction ).mouseover( otherFunction ).css("color""red");

즉, 이와 같은 식으로 작성해서, 클릭 이벤트와 마우스 오버 이벤트를 걸어줌과 동시에 color 스타일 값도 red로 변경하는 작업을 한번에 할 수 있다는 것이죠.

사실, 오리지날 jQuery에서의 이벤트 설정 작업은 상기와 같은 코드를 사용하는 것이 아니라 다음과 같이 bind 라는 메서드를 통해서 설정해야 합니다.

$("#DoIt").bind("click"someFunction );

하지만, jQuery는 자주 사용하는 몇몇 이벤트(몇몇이라고 하기엔 꽤 많지만)에 대해서는 click과 같이 단축 메서드를 작성해 놓았기에, bind 대신 click과 같이 직관적인 메서드를 사용해서도 이벤트 핸들러를 걸 수가 있는 것입니다. 이러한 부분에 대한 구체적인 이야기는 추후에 다시 하도록 하고요(엉? 근데, 거의 다 이야기했는데..). 다시 예제에 집중하도록 하죠.

해서, 소스를 보시면, DoIt이라는 아이디를 갖는 버튼에게 click 이벤트를 지정하고 있는데요. click() 이라는 메서드도 인자로는 함수(클릭 시에 해야할 작업을 작성하는 함수)를 지정할 수 있게 되어 있습니다. 해서, ready() 메서드에서 했던 것처럼 이도 별도의 함수로 작성하기 보다는 그냥 익명함수로 작성하곤 합니다. 다음과 같이 말이죠(제가 100초 안에 다시 등장할 거라고 말했죠!).

$("#DoIt2").click(function() {
  
//.. 클릭 시 해야할 작업
});

click 메서드의 인자로 지정된 익명함수 내에서는 원래의 개체에 대한 컨텍스트가 유지되기 때문에, 함수 내에서 this라는 키워드를 사용할 수 있으며, 이 this는 Doit이라는 html 요소를 의미합니다. 만일, jQuery 개체로 다시 감싸고 싶다면, 함수 내부에서 $(this)와 같이 작성하시면 되지요.

자. 그럼 이제 클릭 이벤트 핸들러 안에다 어떤 코드를 작성했는지 한번 살펴보도록 하겠습니다. 단, 그 전에 이제부터 작성하는 코드들은 "버튼이 클릭되는 경우"에만 수행된다는 것을 기억하세요. 전체적인 코드 작성이 $(document).ready() 메서드 안에서 작성되고 있기에, 마치 모든 코드가 페이지 로드 시에 동작할 것이라고 오해하실 수 있어서 강조드리는데요. 페이지가 로드될 경우 수행되는 것은 이러한 함수가 click 이벤트에 연결되는 것까지이고요. 실제 click 메서드 안에 작성된 익명 함수(아래의 코드)는 사용자가 실제로 버튼을 클릭하는 경우에만 호출되고, 수행됩니다.

var sports $("input:checked");
var 
result "";
for 
(var 0i < sports.lengthi++) {
   result +
$(sports[i]).next().text() + ",";
}
$(
"#result").text(result);

자. 이 코드는 앞서 설명한 :checked 필터를 사용하여 체크가 된 체크박스들을 얻어오고 있고요. 그를 sports라는 변수에 담고 있습니다. 결국, sports라는 변수는 셀렉터에 의해 필터링된 html 요소들의 배열이라고 볼 수 있죠. 그들을 루프를 돌면서, 각 체크박스의 다음에 있는 html 요소로 접근한 뒤(next() 메서드), 그 요소의 텍스트값을 얻어와서 문자열로 구성하고 있습니다.

여기서 우리가 추가로 배우게 되는 2개의 jQuery 메서드가 있는데요. 하나는 next() 이고, 다른 하나는 text() 입니다.

next()란 메서드는 현재의 개체 요소와 형제 수준인 요소 중 바로 다음에 나오는 개체를 얻어오는 메서드입니다. 이름에서 느껴지듯이 딱 그런 역할을 하는 메서드이죠. 예제를 기준으로 설명드리면, 현재 예제는 각각의 체크박스 바로 옆에 <label> 개체들이 놓여있는 것을 보실 수 있을 겁니다. 고로, $(sports[i]).next() 라는 표현은 현재의 체크박스 바로 옆에 있는 label 개체를 찾아가게 되는 것이죠. 단, 루프 안에서 sports[i].next() 라고 코드를 작성한 것이 아니라, $(sports[i]).next()라고 작성한 것에 주목하셔야 하는데요. sports라는 배열에 들어있는 개체들은 jQuery 개체가 아닌 html 요소일 수 있기 때문입니다. 해서, 이를 $()를 사용하여 확실하게 jQuery 개체로 포장해야만 합니다. jQuery 개체가 아니면 next() 메서드를 사용할 수 없으니까요.

text() 메서드는 해당 개체가 가지고 있는 컨텐트를 텍스트로 반환하는 메서드입니다. 이와 유사한 메서드로는 html()이 있는데요. 이는 개체가 포함하고 있는 html 컨텐트를 반환하는 메서드입니다. 이 메서드들은 인자를 사용하지 않으면 값을 가져오는 역할을 하지만, 인자로 값을 지정하면 그 값으로 원래의 값을 바꾸는 역할을 합니다. text() 메서드의 재미있는 점은 개체의 컨텐트가 html 요소들을 포함하고 있다고 해도, 다 무시하고 텍스트만을 반환한다는 점입니다. 즉, <span><b>taeyo</b></span> 와 같은 span 개체가 있을 때, 이 span 개체에 대해서 text()를 수행하면, 반환값은 내부 html을 제외한 "taeyo"가 되고요. html() 메서드를 사용하면 <b>taeyo</b>를 반환한다는 것이죠.

그리하여, 예제에서의 result += $(sports[i]).next().text() + ","; 라는 구문은 현재 루프 안에서, 체크박스 개체의 바로 옆에 있는 개체(label)의 텍스트를 읽어와서 그 텍스트에 ","라는 문자를 더한 다음, 이를 result 라는 변수에 덧붙이는 역할을 하게 됩니다. 즉, 사용자가 체크한 체크박스의 명칭을 차곡차곡 문자열에 더하는 것이죠.

그 후, 예제는 그렇게 만들어진 문자열 result를 span 요소에 출력하는 것을 볼 수 있습니다. 텍스트 설정을 위해서 text() 메서드를 사용하고 있는 것도 잊지말고 째려봐 주세요. 해서, 결과 화면은 다음과 같죠.

이야기를 진행하다 보니, 원래의 폼 관련 셀렉터에 대한 설명보다는 jQuery 개체가 제공하는 트래버싱(traversing, 탐색) 메서드나 조작(Manipulation) 메서드에 대해 설명을 하게 되었네요. 하긴, 이 이야기가 다음 강좌의 주제이니 지금 이야기하는 것이 부드럽긴 하지만요(그리고, 사실 폼 관련 셀렉터에 대해서는 이번 강좌 초반에 표로 설명한 정도면 충분하다고 봅니다요).

그렇다면, 이야기를 꺼낸 김에 루프를 좀 더 편하게 작성할 수 있는 jQuery의 기본 제공 메서드인 each() 메서드에 대해서도 설명을 좀 드리고 넘어갈까 합니다.

each() 메서드는 jQuery 개체가 제공하는 메서드로서, 모든 일치된 개체들에 대해서 순차적으로 특정 함수를 수행할 수 있게 해주는 메서드입니다. 문법은 다음과 같아요.

jQuery(selector).each( function );

each() 메서드 안에 인자로 사용하는 것은 역시나 또 함수입니다(jQuery는 거의 인자로 함수를 사용합니다). 그리고, 역시나 주로 익명 함수를 사용하게 되죠. 해서, 일반적으로 다음과 같은 구문을 가지게 됩니다.

jQuery(selector).each( function(i) {
    //.. 루프 안에서 할 일을 작성
});

익명 함수의 i 라는 인자는 0부터 시작하는 인덱스 값이 넘어옵니다. 마치 for 문에서의 i와 동일하다고 보시면 됩니다만, 필요치 않다면, 인자를 지정하지 않으셔도 됩니다.

each() 메서드는 상당히 자주 사용하게 되는 메서드입니다. 제가 샘플로 만들어 놓은 jQueryBoard에서도 이는 예외가 아닙니다. 이는 셀렉터에 의해 추출된 개체들에 대해서 각각 지정한 함수를 수행하게 합니다. 해서, 루프를 사용할 때와 마찬가지로 각 요소에 대해 어떤 작업을 하고 싶다면 바로 그 함수 안에다가 수행할 내용을 작성하면 됩니다. 이는 for 루프문을 대체할 수 있을 뿐만 아니라, 상당히 효과적이어서 한번 사용하기 시작하면 다시는 for 문을 거들떠 보지도 않게 만드는 마력이 있더군요. 그러면, 이번 예제의 for 루프문을 each() 메서드를 사용해서 바꾸어 볼까요?

var result "";
$("input:checked").each(function(i) {
   result +
$(this).next().text() + ",";
});
$("#result").text(result);

만일, 2개의 체크박스가 체크되었다면, each() 안의 함수는 그 2개의 체크박스에 대해 각각 호출될 것이고, 구문 내 this는 각각의 호출 시에 그에 해당하는 체크박스가 될 것입니다.

어떻습니까? 기존의 for 문으로 작성한 것보다 훨씬 간단하고 명료합니다. 그리고, 결과는 기존과 아주 확실히 동일하죠. 게다가, each() 메서드를 사용하게 되면, 여전히 jQuery의 장점 중 하나인 메서드 체인도 사용이 가능합니다. 예를 들어, 다음 구문을 보시죠.

$("#DoIt").click(function() {
   
var result "";
   
$("input:checked")
      .each(
function(i) {
         result +
$(this).next().text() + ",";
       
})
      .css(
"background""yellow");

   $(
"#result").text(result);
});

each() 메서드에 이어서 css() 메서드를 체인으로 연결해서 작성하고 있습니다. 이렇게 작성하면, 체크된 모든 체크박스에 대해서 each() 메서드를 사용한 기존 작업을 수행할 뿐 아니라, 배경색을 노란색으로 지정하는 것까지 수행하게 됩니다. 해서, 이렇게 바꿔 작성된 예제는 다음과 같은 결과를 보이게 됩니다.

호~ 쓸만하죠?

어찌하다보니, 이번 강좌에는 다음 번에 다루어야 할 내용까지 들어가 버리게 된 결과가 되었지만, 그래도 독자들은 단순히 셀렉터만을 다루는 것보다는 재미있지 않았을까 생각해 봅니다. 어찌됐건, 이로서 셀렉터에 대한 내용은 거의 모두 다룬 것 같네요.

다음 강좌부터는 UI를 조작하는 메서드들 즉, Manipulation 관련 메서드들을 다룰 예정에 있습니다. 그리고, 그를 통해서 여러분은 동적으로 UI를 보다 쉽게 조정할 수 있게 될 것이라 생각합니다.

그럼 다음 강좌에서 뵈어연~~~ jQueryBoard도 많은 테스트와 조언을 부탁드립니다.


authored by Taeyo

Posted by 바람이불면
,
jQuery : 탐색(Traversing) 메서드

필자의 잡담~

갈수록 인기를 얻어가는 태오의 jQuery 강좌.
7월에는 세미나로도 만나보실 수 있지 않을까 합니다. ㅎㅎ

이번 강좌는 트래버스(Traverse)와 관련된 강좌입니다. 트래버스라는 단어의 의미는 어떤 것을 횡단하거나, 탐색하거나, 검토하거나, 여기 저기 왔다갔다 하는 등의 의미를 갖는 단어입니다. 즉, jQuery의 트래버스 관련 메서드들은 개체들의 집합에서 다시금 특정 개체를 찾거나, 필터하거나, 추가하는 등의 작업을 위해 지원되는 API 메서드들의 그룹이라고 보시면 됩니다. 사실, 개체를 찾거나 필터하는 작업은 대부분 셀렉터를 통해서 이루어지지만, 1차적으로 셀렉터를 통해서 필터링을 하고 난 다음에, 그 결과 집합 내에서 추가적으로 필터링하거나, 추가 탐색하거나, 다른 결과 집합과 합치거나 하는 등의 작업을 하기 위해서는 이러한 메서드가 유용하게 사용됩니다.

트래버스와 관련된 많은 메서드들이 존재합니다만, 이들 전부에 대해서 이야기하는 것은 다소 어려울 것 같고요. 이전 강좌들과 마찬가지로 자주 사용하는 메서드들 중심적으로 설명을 드려볼까 합니다. 전체 트래버스 메서드는 http://docs.jquery.com/Traversing에서 살펴보실 수 있으니 완전한 목록은 정식 문서를 참고하시길 바라며언셔~~ 시작해 보겠습니다.

우선, 추가 필터링 관련 메서드들부터 알아보도록 하겠습니다. 다시 말씀드리지만, 이들은 모두 셀렉터를 통해서 1차적으로 일치되는 집합을 얻어낸 후, 그 집합에 대해서 사용할 수 있는 메서드들입니다.

eq(index) 일치된 요소들 중에서 인덱스와 일치하는 단일 요소를 가져옵니다.
filter(expr) 지정된 표현식과 매치되지 않는 모든 요소들을 제거합니다. 즉, 매치되는 요소들만을 가져옵니다.
filter(func) 지정된 함수와 매치되지 않는 모든 요소들을 제거합니다.
is(expr) 현재 개체와 표현식에 해당한다면 true, 표현식에 여러 개의 조건이 있다면 그 중 한 개만 맞아도 true가 됨
map(callback) jQuery 개체 안에 있는 요소들의 집합을 다른 집합으로 변경해서 옮긴다.
not(expr) 지정된 표현식과 매치되는 모든 요소들을 제거합니다. 즉, 매치되지 않는 요소들만을 가져옵니다.

이 중 특히나, filter 메서드와 is, not 메서드는 활용빈도가 높습니다. 셀렉터에 의해서 1차적으로 걸러낸 데이터를 가지고 작업을 하다가 2차적으로 추가 필터링을 한다거나, 특정 요소가 어떤 조건에 부합하는지를 검사한다거나 하는 작업은 꽤나 자주 하게되는 일이니까요.

메서드의 인자인 expr은 expression을 의미하는 것으로 여기에는 주로 셀렉터를 사용합니다.

그러면, 각각의 항목에 대해서 조금씩만 더 설명을 하고, 예제로 들어가 보도록 하겠습니다.

eq(index)라는 메서드는 사실 :eq(index) 라는 셀렉터 필터와 거의 동일합니다. 하나는 메서드이고 하나는 셀렉터 구문이라는 차이만 있는 것이죠. 다음 예제 코드를 한번 보세요.

$("div:eq(1)").addClass("blue");
$("div").eq(1).addClass("blue");

첫 번째 구문은 이미 익숙한 셀렉터이죠? 다들 아시겠지만, 현재 문서에 있는 div 중 2번째로 등장하는 div를 얻어내는 셀렉터입니다. 그리고, 그 요소에 대해 blue 라는 css 클래스를 적용하고 있습니다.

이는 eq() 메서드를 사용하는 두 번째 구문처럼 작성할 수도 있습니다.일단 모든 div들을 셀렉트한 다음, 그 중 2번째 개체를 얻어내기 위해서 eq(1)이라는 메서드를 사용하는 것이죠. 사실, 이 둘은 결과적으로 동일합니다. 그렇다면, 어떤 방법을 쓰던지는 우리의 맘일까요? 그럼요~ 여러분의 마음입니다. 다만!!!

eq() 메서드를 사용한 경우에는 end()라는 엄청난 초능력자 메서드의 도움을 받아 이전 상태로 돌아갈 수 있다는 장점이 있습니다(eq() 메서드 뿐만 아니라 대부분의 조작 메서드는 end() 메서드를 사용할 수 있습니다).

원래 end() 메서드는 이번 강좌 후반에 설명을 드릴 예정이었던 메서드이긴 합니다만, 말이 나온 김에, 그리고 여기가 보다 적절한 자리인 것 같기에 앞당겨 설명을 드려봅니다.

end() 메서드 :
현재 일치된 개체 집합을 변경하여, 방금 일어난 "파괴적인 작업" 직전의 상태로 되돌린다.

마치 1분 전의 과거로 돌아갈 수 있는 초능력자를 보는 듯한 표정을 지으시면 됩니다. 이 녀석은 그런 능력을 가지고 있으니까요. 대부분의 조작 메서드, 트래버스 메서드에 end()라는 메서드를 적용할 수 있습니다. 이는 자기가 되돌릴 과거 상태가 존재한다면, 현재의 개체집합을 그 상태로 되돌리고, 되돌릴 과거없는 상태라면 단순히 빈 값을 반환합니다.

앞의 예제에 이를 사용해 보기 위해서, 다음과 같은 조건에 맞는 셀렉터를 한번 작성해 보도록 해요.

"모든 짝수 번째 div를 구한 다음, 그 중 첫 번째 div는 orange라는 배경색을 적용하고, 두 번째 div는 blue 배경색을 적용하라"

end() 메서드를 모르는 상황이었다면 여러분은 이를 다음과 같이 작성할 듯 합니다.

$("div:odd").eq(0).css("background""orange");
$("div:odd").eq(1).css("background""blue");

우선, $("div:odd")를 통해서 짝수번째 div들을 구한 다음, eq() 메서드를 사용해서 그 중 첫 번째와 두 번째 요소에 각각 접근하는 것이죠. 코드가 두 줄이라는 것은 그렇다치더라도, 각각에 대해서 동일한 검색을 두번이나 반복하는 부분은 썩 마음에 들지 않습니다.

해서, 이 코드를 다음과 같이 할 수 있으면 좋을 것 같다는 생각이 들지 않나요?

$("div:odd")
            .eq(
0).css("background""orange")
            .eq(
1).css("background""blue");

그러면 참 좋겠습니다만, 안타깝게도 이는 올바로 동작하지 않습니다. 왜냐하면, 이미 $("div:odd").eq(0)으로 인해서 매치되는 집합이 전체 div:odd가 아니라 단일 요소로 줄어든 상황에서는 eq(1)을 해봐야 아무런 대상도 찾을 수 없기 때문이죠. 그렇다면, 최종 요소에 대해 작업을 하고 방금 이전의 상태로 돌아가서 다시 검색할 수 있다면 얼마나 좋을까 하는 생각이 들지 않나요? 들었죠? (그렇다면, 내려 놓으세요~ 아. 몹쓸 개그였습니다)

바로 여기서 end()가 엄청난 능력을 발휘하게 됩니다. 상기 코드는 다음과 같이 작성할 수 있습니다.

$("div:odd")
            .eq(
0).css("background""orange")
            
.end()     // $("div:odd")와 동일
            
.eq(1).css("background""blue");

여기서 end()는 eq(0)을 하기 직전의 상태로 되돌리는 역할을 합니다. 고로, end()를 사용하면 단 한줄의 메서드 체인으로 원하는 작업을 마무리 할 수 있게 되는 것입니다. 멋지죠?

end()는 jQuery에서 대단히 심도있게 사용되므로, 잘 기억을 해두시기 바랍니다. 하긴, 기억을 하고 싶지 않아도 저절로 하실 수 밖에 없게 될 듯 해 보이네요. 하하

그럼, 이제 필터 메서드에 대해서 알아보도록 하죠.

filter(expr)은 결과적으로는 일반 셀렉터를 통한 검색하는 것과 동일하다고 보시면 됩니다. 다만, 셀렉터는 문서상에 존재하는 개체들을 대상으로 검색한다면, 이는 메모리상에 존재하는 개체 집합을 대상으로 필터링을 한다는 부분에서 차이가 있습니다. 즉, 셀렉터에 의한 1차적 검색 집합에 대해서 다시 추가적으로 필터링(걸러냄)을 하고 싶은 경우에 사용하는 API 메서드라는 것이죠. 인자로는 필터링을 위한 표현식을 제공할 수 있고요. 그 표현식과 매치되지 않는 모든 요소들을 개체 집합(메모리)에서 제거하여 필터링된 결과를 얻습니다.

반면, 유사한 API로 Filter(func)도 있는데요. 이는 인자로 표현식이 아닌 함수를 사용하지요. 즉, 필터링(걸러냄)을 함수를 통해서 보다 세밀하게 제어하고 싶은 경우에 사용합니다. 필터링 조건이 일반적인 표현식으로 설명하기 어려운 경우에 별도의 함수로 작성을 해서 그 안에서 어떻게 필터를 수행할 것인지를 지정하는 것이죠.

가장 간단하게 예를 들면, 다음 2개의 표현은 결과적으로는 동일하다고 볼 수 있습니다.

$("div:odd"
$(
"div").filter(":odd")

다만, 앞의 예제와 마찬가지로 filter 메서드를 사용한 경우는 end() 메서드의 도움을 얻어 이전 상태로 되돌릴 수가 있다는 장점이 있죠.

예를 들면, 다음과 같이 말입니다. 다음 코드는 앞선 예제에서 $("div:odd")를 $("div").filter(":odd")로 변경해 본 것입니다.

$("div").filter(":odd")
    .eq(
0).css("background""orange")
    .end()     
// filter(":odd")
    
.eq(1).css("background""blue")
    .end()     
// filter(":odd")
    
.css("color""red");   //이 코드는 odd인 div들의 폰트색상을 red로 적용한다.

이는 셀렉터를 사용하여 전체 div를 1차적 선택한 다음에 filter() 메서드를 사용하여 그 중 짝수번째 인 것들만 다시 필터링을 하고요. 그 짝수번째 div들 중에서 첫 번째 녀석(eq(0))은 오렌지 배경색으로 설정하고, 다시 짝수번째 div들 중 두번째 녀석(eq(1))은 파란 배경색으로 설정하고, 마지막으로 모든 짝수번째 div에 대해서 빨간 폰트를 지정하고 있습니다.

end() 메서드는 한번만 가능한 것이 아니라 메서드 체인 내에서 계속적으로 사용하여 방금 전 상태로 계속 올라갈 수 있습니다. 대단하죠?

또한, filter(expr) 메서드와 반대되는 메서드로 not(expr) 메서드도 있습니다. Filter(expr) 메서드가 현재의 집합에서 expr 표현식과 매치되는 것만을 가져온다면, not(expr) 메서드는 현재의 집합에서 expr 표현식과 매치되지 않는 것들만을 가져옵니다. 그렇기에, 다음 두 표현식은 동일한 개체 집합을 갖게 된다고 볼 수 있습니다.

$("div").filter(":odd")
$(
"div").not(":even")

하하. 재미있네요. 저만 재미있나요?

또한, 중요한 메서드로 is(expr)도 있습니다. 이는 그 이름이 의미하듯이, 개체를 비교하여 true/false를 알려주는 메서드인데요. 예를 들어, 다음의 코드를 한번 살펴보시죠.

var $myDiv $("div").eq(5);
if 
($myDiv.is("div")) 
{
  $myDiv.css(
"border""4px solid yellow");
}

이 코드는 우선 div 중 6번째 요소를 가져와서 $myDiv라는 변수로 참조하고 있습니다. 일단, 요 부분에서도 드릴 말씀이 하나 있는데요. 일반적으로 jQuery에서는 jQuery 개체를 일시적으로 참조하는 변수명에는 $로 시작하는 변수명을 쓰도록 은근히 권유하고 있습니다. 그래야 일반 변수들과 jQuery 개체변수가 쉽게 구분되기 때문이지요. 물론, 꼭 그래야 하는 것은 아니지만 가독성이 좋아지니 가급적 그렇게 하시길 권해봅니다.

어쨌든, 위의 소스는 $myDiv 변수에 6번째 div를 참조한 뒤, is(expr) 메서드를 사용해서 그 개체가 "div" 개체인지를 비교하여, 만일 "div"가 맞다면, 그 div에 대해서는 노란색의 두꺼운 테두리를 갖도록 지정하고 있지요.

expr인자에는 일반적으로 "div"처럼 단일 구문을 작성하곤 하지만, ","를 구분자로 사용하여 여러 개의 표현식을 나열할 수도 있습니다. 다음과 같이 말이죠.

$myDiv.is(".orange, .blue, .lightblue")

이는 $myDiv가 orange나 blue, lightblue css 클래스 중 하나라도 가지고 있으면 true가 됩니다. ^^

그리고, 그리 자주 사용되는 메서드는 아닙니다만 map(callback)라는 것이 있지요. 사실, 이는 생각보다 사용빈도가 적어서 아주 자세하게 설명하지는 않겠지만(자세한 설명은 공식 사이트에서 샘플 코드를 살펴보시면 쉽게 이해가 될 겁니다), jQuery 개체 안에 있는 요소들의 집합을 다른 집합으로 변경해서 옮긴다는 것은 기억해 두시기 바랍니다. 예를 들어, div 안에 각각 a부터 z 까지 소문자 알파벳이 기록 되어 있는 상황에서 다음과 같은 코드를 사용한다면

var arr $("div").map(function() {
   
return $(this).text().toUpperCase();
});

arr 이라는 변수에는 A부터 Z 까지 대문자로 구성된 배열이 채워진다는 것이죠. 셀렉터로 선택된 개체들의 집합에서 원하는 데이터를 별도의 다른 집합으로 옮길 수 있다는 것이 이 메서드의 특징입니다. ^^

자. 그럼 지금까지 설명한 것이 모두 포함된 예제를 한번 같이 해볼까요? 다음은 Traverse.htm 페이지의 소스입니다.

<html xmlns="http://www.w3.org/1999/xhtml" >
  
<head runat="server">
    
<title></title>
    
<script src="jquery-1.3.2.min.js" type="text/javascript"></script>
      
<script>
          $(
document).ready(function() {

              $(
"div").eq(0).addClass("lightblue");

              
$("div").filter(":odd")
                .eq(
0).css("background""orange")
                .end()
                .eq(
1).css("background""blue")
                .end()
                .css(
"color""red");

              var 
$myDiv $("div").eq(5);
              if 
($myDiv.is("div")) $myDiv.css("border""4px solid yellow");
              if 
($myDiv.is(".orange, .blue, .lightblue")) $myDiv.text("칼라");

              var 
arr $("div").map(function() {
                  
return $(this).text().toUpperCase();
              
});
          
});
    </
script>
    
<style>
      div 
{ width:60px; height:60px; margin:10px; float:left; 
           border
:2px solid blue  ; }
      
.blue { bac  kground:blue; }
      
.lightblue { background:lightblue; }
      
.orange { background:orange; }
    </
style>
  
</head>
<body>
  
<div>a</div>
  
<div>b</div>
  
<div>c</div>
  
<div>d</div>
  
<div>e</div>
  
<div class="orange">f</div>
  
<div>g</div>
</body>
</html>

그리고, 다음은 이 페이지의 결과 화면이고요. 이미 앞서서 설명드린 코드들이 들어있는 것이기에 별도의 소스 설명은 필요없을 듯 합니다 ^^

이 부분을 꽤나 길게 설명드린 것은 그만큼 자주 사용하기 때문이니까요. 꼭 각 구문의 역할을 확실히 이해하시기를 부탁드립니다.

그러면, 이번에는 트래버스 관련 메서드들 중 찾기와 관계된 API들을 살펴볼까요?(앞서 말한 바와 같이 이 목록은 전체 목록이 아닙니다. 자주 사용하는 일부만을 담고 있으니 전체 목록은 공식 문서인 http://docs.jquery.com/Traversing에서 확인하세요)

find(expr) 지정된 표현식과 일치하는 요소를 검색한다.
add(expr) 현재 요소에 expr와 일치하는 요소를 추가한다. 즉, 일치되는 요소가 추가 확장되는 의미이다.
next(expr) 현재 요소 바로 다음에 나오는 형제 요소를 선택한다. expr 을 지정하면 그로 필터링을 수행한다
nextAll(expr) 현재 요소 바로 다음에 나오는 모든 형제 요소들을 선택한다. expr 을 지정하면 그로 필터링을 수행한다
parent(expr) 현재 요소의 부모를 선택한다. expr 을 지정하면 그로 필터링을 수행한다
parents(expr) 현재 요소의 고유한 부모 요소들을 선택한다. expr 을 지정하면 그로 필터링을 수행한다
prev(expr) 현재 요소보다 앞서 나오는 형제 요소를 선택한다. expr 을 지정하면 그로 필터링을 수행한다
prevAll(expr) 현재 요소보다 앞서 나오는 모든 형제 요소들을 선택한다. expr 을 지정하면 그로 필터링을 수행한다
siblings(expr) 현재 요소의 모든 형제 요소들(자신은 제외)을 선택한다. expr 을 지정하면 그로 필터링을 수행한다

메서드 명칭이 직관적이어서 각각의 API의 역할이 쉽게 이해가 될 듯 합니다.

가장 재미있는 메서드는 그 이름 때문에 오해하기 쉬운 add(expr)인데요. 이는 셀렉터에 의해 1차적으로 검색된 결과 집합에 추가적인 검색 집합을 합치는(add) 역할을 합니다. 말로 하니 설명이 좀 모호한데요. 다음 코드를 한번 보시죠.

$("div").add("p").css("background""yellow");

add란 이름 때문에 얼핏 보면, 마치 div 요소 안에다가 p 요소를 생성하여 추가하는 것으로 느껴질 수 있는데요. 사실은 검색 결과가 합쳐지는 것입니다. 즉, $("div").add("p") 라는 것은 $("div, p")와 같다고 볼 수 있다는 것이죠. 해서, 다음과 같은 구문은

$("div")
        .css(
"border""1px solid red")
        .add(
"p")
        .css(
"background""yellow");

모든 div에게는 붉은색 테두리를 주고, div에 더하여 모든 p 요소들에게 노란 배경색을 주는 표현이 됩니다. 즉, 모든 div와 p는 노란 배경색을 갖지만, 붉은 테두리는 div만 갖게 되는 것이죠. ㅎㅎ

그 다음으로 이야기할 만한 것은 find(expr) 인데요. 이는 현재 검색된 요소의 자식을 대상으로 추가적인 검색을 수행합니다. 가끔 어떤 분들은 filter()와 find()를 헛갈려 하시더군요. 둘의 차이는 사실 아주 간단합니다. filter()는 검색된 결과 집합에서 그 개체들에 대해서 다시금 필터링을 하는 것이고요. find()는 검색된 결과 집합에서 찾는 것이 아니라, 결과 집합 내의 각 요소의 "자식"에게서 찾는 겁니다. 그래도 어렵다면, 다음의 차이를 구분하실 수 있으면 되는데요.

$("div:odd").filter("p")
$(
"div:odd").find("p")

위의 코드 중 첫번째 구문인 filter 구문의 결과는 "없음" 입니다. 왜냐구요? 셀렉터에 의해서 짝수번째 div 들만 검색한 다음, 그 div들 중에서 p라는 태그를 갖는 놈들을 가져올라고 하니 있을리가 없죠. 모두 div 태그들만 있는 집합에서 뜬금없는 p 태그로의 필터링은 뭔가요? 당황스럽죠? ㅎㅎ. 해서, filter() 메서드에서 인자로 요소명을 주는 경우는 사실 거의 없죠.

반면, find()에 의한 결과는 아주 잘 나올 것입니다(물론, div 요소의 하위로 p요소가 있다고 가정했을 경우에 말이죠). Div들 중에 p 태그를 갖는 놈이 있다면, 그 p 요소들으 find() 명령에 의해서 수루룩 일치대상이 될 것입니다.

알고나니 쉽죠? 항상 모든 일이 그런 것 같습니다. 알기 전에는 대단한 것처럼 보이지만, 막상 알고나면 별 것 아니죠. 하지만, 알고 모름의 작은 차이가 가끔은 차등 대접의 원인이 되기도 합니다요. 그래서, 어릴때 부모님이 공부해라 공부해라 하시는 것인가 봅니다.

그 외의 메서드인 next(), prev(), nextAll() 이런 것들은 굳이 설명을 드릴 필요가 없을 것 같아요. 이름에서도 느껴질 뿐더러, 다른 언어에서도 이런 류의 메서드는 항상 있어왔고, 그 역할도 항상 똑같기 때문이죠 ^^

자. 방금 배운 것들을 그런대로 섞어본 종합 예제 하나 더 나갑니다.

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
  
<title></title>
  
<script src="jquery-1.3.2.min.js" type="text/javascript"></script>
  
<script type="text/javascript">
    $(
document).ready(function() {

      $(
"div:eq(1)")
        .siblings().css(
"border""1px solid blue")
        .end()
        .next().text(
"third")
        .end()
        .nextAll().css(
"background""yellow");
                
      
$("div").find("p").css("color""blue")
        .add(
"span").css("border""1px solid red");
         
    
});
  </
script>
  
<style>
    
* { font-size:12px; font-family:돋움; }
    div 
{ width:60px; height:60px; margin:10px; float:left; 
          border
:1px solid silver; padding: 5px }
  </
style>
</head>
<body>
  
<div><p>p a</p> </div>
  
<div><p>p b</p></div>
  
<div><p>p c</p></div>
  
<div><br /><span>span d</span></div>
  
<div><br /><span>span e</span></div>
</body>
</html>

예제는 siblings()와 next(), nextAll() 그리고 find()와 add()까지 골고루 섞어서 사용하는 대단히 적절하다 못해 아니꼽기까지 한 출중한 예제가 아닐 수 없습니다.

$("div:eq(1)")
  .siblings().css(
"border""1px solid blue")
  .end()    
// $("div:eq(1)")
  
.next().text("third")
  .end()    
// $("div:eq(1)")
  
.nextAll().css("background""yellow");

라는 구문은 문서 상에 존재하는 div 중 두번째 div를 1차적으로 가져온 다음, 그와 친구들인 모든 요소들(siblings())에게 파란색 테두리를 적용하고요. end()를 사용해서 다시 두번째 div로 돌아온 다음, 자신의 바로 뒤에 나오는 요소(next())의 텍스트를 third로 바꾸고 있습니다. 그리고, 또 end()를 사용해서 두번째 div로 되돌아 온다음, 자신의 뒤로 나오는 모든 형제 요소들에게 노란색 배경색을 지정하고 있습니다.

가급적 end() 메서드 뒤에는 // 주석을 사용하여, end()로 인한 대상 집합이 현재 무엇인지를 적어두시는 좋습니다. 그러면, 보다 코드가 직관적이 될테니까요 ^^

그러면, 브라우저로 이를 실행한 결과는 어떨까요? ㅎㅎ

예상한대로의 결과가 나왔나요? 그러길 바랍니다. ^^

트래버스 강좌는 이걸로 마무리가 일단락 되었습니다. 이로써, 대부분의 jQuery의 일반적인 API 메서드들은 대부분 언급을 한 것 같긴 한데요. css 관련 메서드나 어트리뷰트 관련 메서드는 사실 언급을 제대로 하지 않았다는 것을 이제야 깨달았습니다. ㅎㅎ

해서, 다음 강좌는 그에 대한 강좌로 준비할까 생각하는데요. 한편으로는 굳이 그것을 제가 설명드릴 필요가 없어보이기도 해서, 그 부분은 자습에 맡기고 저는 이벤트나 이펙트 쪽의 설명으로 넘어갈까 고민하고 있기도 합니다.

어느쪽으로 방향을 잡을지는 여러분의 리플을 통해서 결정해 보는 것도 좋겠네요.
그러면, 오늘도 좋은 하루 되세요~~

Ps : 아참. 7월에는 jQuery의 기초편 총정리의 의미로 3시간짜리 무료 세미나를 진행할까 고민하고 있기도 합니다. MS에 세미나실을 빌릴 수 있는지 확인을 해봐야겠네요.


authored by Taeyo

Posted by 바람이불면
,
jQuery : 조작(Manipulation) 메서드

필자의 잡담~

뭐냐! 설마 이 강좌를 책으로 제작하자는 제의라도 들어온 것이냐? 너무 강좌가 안 올라와서 그런 줄 알았다. 역시 그런 불순한 의도로 강좌를 쓴 것이구나! 하시는 분들이 혹시 계시지는 않겠죠? 다만, 그냥 바빴을 뿐입니다.ㅎㅎ (책을 쓸 의향도 없어요!)

게다가, 첫 강좌에서도 말씀드렸지만, 이 jQuery 강좌는 2-3회 정도로 정리해서 초반 길잡이만 하려 했던 것인데요. 어쩌다보니, 현재 너무 장황해진 거 같아서 살짝 부담도 되고 있긴 합니다. 어쩌면 기쁜 부담이죠~

그래도, 주욱 해온대로 원하는 내용을 원하는 시간에 쓰고자 합니다. 그래야 읽을만한 글이 될거라 생각하니까요. 강좌 처음에도 말씀드렸다시피, 더 많은 내용이 필요하신 분은 책! 마음의 양식을 잊지 마세요

이번 강좌에서는 이전에 언급한대로 jQuery의 조작(Manipulation) 관련 메서드들에 대해서 다루어 볼까 합니다. 사실, 이미 기초를 뗀 여러분들에게 조작관련 메서드, 탐색관련 메서드를 굳이 구분지어서 설명할 필요는 없다는 느낌도 들긴 하지만 그래도 깔끔한 정리를 위해서 말이죠 ^^;

조작 관련 메서드라 함은 요소에 값을 지정한다거나, 특정 요소의 값을 읽어온다거나 하는 작업을 포함해서, 동적으로 요소 자체를 생성, 삭제, 복사, 제거하는 기능들을 의미합니다. 전체 목록은 jQuery 공식 페이지인 http://docs.jquery.com/Manipulation 에서 확인하실 수 있고요. 저는 그러한 메서드들 중에서 자주 사용될만한 것들 위주로 설명을 할까 합니다.

우선, 현재 jQuery에서 제공하는 조작과 관련한 메서드들은 크게 7개의 카테고리로 나누어져 있는데요. 그들은 각각 요소의 내용을 조작하는 메서드, 요소를 추가하거나 삭제하는 메서드, 요소를 래핑하거나 바꿔치기 하는 메서드, 요소를 제거하거나 복사하는 메서드들로 구분되어 있습니다. jQuery의 버전이 올라가면 이러한 카테고리는 더 추가되거나 정리될 수도 있습니다만, 현재의 버전은 이러한 카테고리를 가지고 있기에, 강좌도 그에 따라 설명하겠습니다(다만, 전체 카테고리를 다 설명드리지는 못할 듯 하고요. 제가 상대적으로 자주썼던 5개의 카테고리만을 설명할 예정입니다).

jQuery의 조작 메서드 중 하나의 카테고리인 요소의 내용을 다루는 메소드로는 다음과 같은 것들이 있습니다.

내용 변경 메서드
html() 일치된 요소의 html 내용을 가져옵니다. 이는 요소의 innerHTML 값과 동일합니다. 만일, 일치된 요소가 여러 개라면 그 중 첫 번째 요소의 HTML을 가져옵니다.
html(val) 일치된 요소의 html 본문을 val 값으로 설정합니다. 만일, 일치된 요소가 여러 개라면 모든 요소에 이러한 작업을 수행합니다
text() 일치된 모든 요소의 텍스트를 합쳐서 가져옵니다.
text(val) 모든 일치된 요소의 텍스트를 val 값으로 설정합니다.

사실, 이 메서드들은 이전 강좌에서도 만나보았던 것인데요. 그 때 제가 다음과 같이 설명을 드렸을 겁니다.

'text() 메서드는 해당 개체가 가지고 있는 컨텐트를 텍스트로 반환하는 메서드입니다. 이와 유사한 메서드로는 html()이 있는데요. 이는 개체가 포함하고 있는 html 컨텐트를 반환하는 메서드입니다. 이 메서드들은 인자를 사용하지 않으면 값을 가져오는 역할을 하지만, 인자로 값을 지정하면 그 값으로 원래의 값을 바꾸는 역할을 합니다.

text() 메서드의 재미있는 점은 개체의 컨텐트가 html 요소들을 포함하고 있다고 해도, 다 무시하고 텍스트만을 반환한다는 점입니다. 즉, <span><b>taeyo</b></span> 와 같은 span 개체가 있을 때, 이 span 개체에 대해서 text()를 수행하면, 반환값은 내부 html을 제외한 "taeyo"가 되고요. html() 메서드를 사용하면 <b>taeyo</b>를 반환한다는 것이죠.'

사실, 위의 설명이면 이 메서드들을 이해하는데 충분할 것이라 생각하지만, 기왕 말을 꺼낸 김에, 약간의 설명을 덧붙일 것이 있습니다. 이는 jQuery로 검색된 대상 요소가 여러 개일 경우, text() 메서드와 html() 메서드의 동작이 약간 다르다는 것인데요. 일치된 요소가 여러 개인 경우, text() 메서드는 일치된 모든 대상의 텍스트를 결합해서 반환하는 반면, html() 메서드는 일치된 요소들 중 첫 번째 요소의 html 만을 반환한다는 것이 그 차이이지요. 크게 중요한 사항은 아니지만, 이 차이를 모르면 jQuery를 사용하다가 간혹 결과가 이상하게 나온다고 불만을 가질 수 있으므로 기억 해 두시기 바랍니다.

이어지는 메서드들은 특정 요소나 개체 집합을 다른 요소의 "내부"에다가 앞, 뒤로 덧붙이는 기능을 제공하는 메서드들입니다.

추가(요소 내부에) 관련 메서드
append(content) 일치된 요소의 내부에 content를 덧붙입니다.
appendTo(selector) 일치된 요소를 selector에 의해 일치된 모든 요소들 내부에 덧붙입니다. 만일, 일치된 요소가 본문에 존재하는 개체(예, $("#some")과 같은)라면 그를 제거한 후 복사(즉, 이동)합니다. 설명이 어려우면 밑의 예제를 참고하세요.
prepend(content) append(content)와 동일하며, 다만, 내부 앞쪽에 붙여 넣습니다.
prependTo(selector) appendTo(selector)와 동일하며, 다만, 내부 앞쪽에 붙여 넣습니다.

append(content) 메서드는 이름이 의미하는 바가 명확하기에, 쉽게 이해할 수 있을 것입니다. 인자로 지정된 content를 jQuery 개체 내부에 덧붙이는 것이니까요. 예를 들어, 다음과 같은 표현이 있다고 가정해 봐요.

$("b.link").append("(클릭)");

이는 link라는 css 클래스를 갖는 B 태그 내부에 "(클릭)" 이라는 문자열을 추가하는 예입니다. B 태그 내부 뒤쪽에 덧붙이는 것이기에 "(클릭)"이라는 단어도 당연히 굵게 표현될 것입니다. 즉, 다음과 같은 최종 html이 형성된다는 것이죠.

<b class="link">굵은 글자임 (클릭)</b>

참 쉽죠? 하지만, 혹시 순간적으로 이렇게 간단한 메서드가 왜 필요할까라는 생각을 하지는 않으셨나요? 아니라고요? 글쎄요. 순간! 하신 것 같은데.. -_-+. 하셨던 안 하셨던은 사실 중요하지 않습니다. 이미 개그로 꺼낸 말이 지루해져 버렸으니까요(엉엉). 어쨌든, 이 메서드는 상당히 유용하게 사용되곤 합니다. 예를 들어, 저처럼 강좌를 Html로 길게 쓴 다음, 주석을 표현하고자 할 경우에 말이죠. 주석 표시를 HTML로 표현하는 경우에는 <sup>라는 태그를 사용하곤 하는데요. 그것을 수동으로 일일이 태그를 달자면 상당히 노가다스럽습니다. 주석 태그를 수십개 달아뒀는데, 순서라도 바뀌는 날에는 생각만해도 피곤해 집니다. 하지만, 주석을 표현해야 할 단어들에 대해서 .annotation이라는 스타일 클래스를 지정해 두었다면(대부분 스타일을 지정하죠), 다음과 같은 jQuery 구문을 통해서 주석표시를 일괄적으로 해결할 수 있습니다.

$(".annotation").each(function(i) {
  
var idx i + 1;
  
$(this).append("<sup>" + idx + "</sup>");
});

이는 .annotation라는 css 클래스가 지정된 html 요소들에 대해서 <sup>1</sup>, <sup>2</sup>와 같은 주석 표현 태그를 동적으로 덧붙여주는 코드입니다. 일일이 단어의 뒷 부분에 <sup>1</sup>와 같은 태그를 수동으로 추가할 필요없이, jQuery를 이용해서 동적으로 그러한 표현을 추가할 수 있는 아주 유용한 예라고 볼 수 있습니다. 이제 jQuery님 좀 짱으로 보이시지 않나요? 다음 그림은 그렇게 처리한 예를 보여줍니다.

append(content) 메서드가 간단하면서도 유용하기에, 그와 유사한 appendTo(selector) 메서드도 관심을 가져 볼만 합니다. 그런데, 이 메서드는 사용법이 상대적으로 살짝 복잡하게 느껴질 수 있습니다. append와는 덧붙이기의 대상이 반대이며, 더불어, 셀렉터에 의해 일치된 대상 모두에게 덧붙여지기 때문이지요. 다음 예를 한번 볼까요?

$("#linkText").appendTo("a.link");

이는 #linkText 라는 아이디를 갖는 요소를 얻어서, 그를 link라는 css 클래스를 갖는 "모든" 하이퍼링크 뒤에 덧붙이게 됩니다. 그러면서, 원래의 #linkText 요소는 사라집니다. 원본 개체는 복사되면서 제거되는 것이죠. 더불어, 다음과 같은 구문도 가능합니다.

$("<font>(클릭)</font>").appendTo("b");

이는 <font>(클릭)</font>라는 태그 문자열을 동적으로 생성한 뒤, 그를 모든 B 태그의 뒤에 덧붙이는 역할을 합니다. 어때요? appendTo 메서드가 어떤 역할을 하는지 이해가 되시죠?

말이 나온 김에, 우리는 $()라는 핵심 표현에 대해 살펴보고 넘어가야 할 필요성이 있습니다. 가장 기본적이면서 가장 마법스러운 $()라는 특이한 표현이 제공하는 다양한 기능을 말이죠.

여러분은 $() 표현이 jQuery()라는 구문의 단축표현이자, 셀렉터를 수행하기 위한 구문이라고 알고 있을 것입니다만, 실은 그 외에도 3가지의 기능을 더 가지고 있습니다.

자세한 내용은 http://docs.jquery.com/Core 를 보면 잘 나와있습니다만, 간략하게 설명을 드리면 각 기능은 이렇습니다.

1. 인자로 셀렉터를 지정한 경우에는 일치되는 모든 요소를 찾는다.
2. 인자로 html 태그를 지정한 경우에는 동적으로 그 요소를 생성한다.
3. 인자로 특정 DOM 요소를 지정하면, 그 요소의 jQuery 래퍼를 생성한다.
4. 인자로 function을 지정하면, 그는 $(document).ready() 메서드와 동일하다.

간단하죠?

해서, $("<font>(클릭)</font>") 라는 표현은 동적으로 font 요소를 생성하게 되는 것이고요. $("#linkText")라는 표현은 #linkText라는 셀렉터에 일치하는 요소들을 검색하게 되는 것이죠.

append와 appendTo 메서드를 이해하셨으면, prepend와 prependTo 메서드도 쉽게 이해하실 수 있을 것입니다. 영어사전에서 이 단어들을 검색하지는 마세요. 이런 단어는 공식적으로는 존재하지 않으니까요. 단지, pre-append 라는 의미라고 생각하시면 됩니다. 즉, prepend는 append와 동일하지만, 요소를 뒤에 덧붙이는 것이 아니라 앞에 덧붙인다는 차이가 있습니다. prependTo도 마찬가지고요. 하하. 설명 안해줘도 그럴 것인줄 이미 알았다고 말씀하실 줄 저도 알았습니다.

세번째 메서드 그룹은 위의 추가(내부) 관련 메서드와 유사하긴 하지만, 요소 내부에 추가를 하는 것이 아니라, 요소 외부에 추가하는 메서드 그룹입니다.

추가(요소 외부에) 관련 메서드
after(content) 일치된 요소 뒤에 content를 삽입합니다. 요소 내부가 아닌 외부에 삽입된다는 것을 제외하면 append와 동일합니다.
before(content) 일치된 요소 앞에 content를 삽입합니다. 요소 내부가 아닌 외부에 삽입된다는 것을 제외하면 prepend와 동일합니다.
insertAfter(selector) 일치된 요소를 selector에 의해 일치된 모든 요소들 뒤쪽에 삽입합니다. 요소 내부가 아닌 외부에 삽입된다는 것을 제외하면 appendTo와 동일합니다.
insertBefore(selector) insertBefore(selector)와 유사하나, 요소 앞쪽에 삽입합니다. 요소 내부가 아닌 외부에 삽입된다는 것을 제외하면 prependTo와 동일합니다.

after 메서드는 앞서 설명한 append 메서드와 눈에 보이는 결과는 유사합니다. 다만, 태그 내부에 덧붙이는 것이 아니라, 태그 바깥쪽에 덧붙인다는 차이가 있지요. 예를 들어, 다음 구문을 보도록 해요.

$("a").after("<font>(클릭)</font>");

이는 모든 하이퍼링크 바로 뒤에 "<font>(클릭)</font>" 이라는 태그 문자열을 덧붙이는 구문입니다. 해서, 결과로 다음과 같은 태그가 구성되는 것이죠.

<a href="http://taeyo.net">태오 사이트</a><font>(클릭)</font>

만일, after 메서드 대신 append 구문을 다음과 같이 사용했다면,

$("a").append("<font>(클릭)</font>");

이는 다음과 같은 결과 태그를 구성했을 것입니다.

<a href="http://taeyo.net">태오 사이트<font>(클릭)</font></a> 

차이가 느껴지시죠?

같은 방식으로 before 메서드도 prepend 메서드와 유사합니다. 태그 내부에 삽입 되느냐 외부에 삽입되느냐만 차이가 있는 것이죠. 마찬가지로, insertAfter()는 appendTo() 메서드와 동일하게 동작하며, insertBefore()는 prependTo()와 동일하게 동작합니다. 다만, 자식 요소로서 태그 내부에 삽입되느냐, 형제 요소로서 외부에 삽입되느냐의 차이만 있다는 것이죠. 참 쉽죠?

스피디하게, 이어지는 소개할 메서드 그룹은 삭제용 메서드와 복사용 메서드들입니다.

삭제 메서드
empty() 모든 일치된 요소들의 자식 노드들을 제거합니다.
remove() 모든 일치된 요소들을 DOM에서 제거합니다.
복사 메서드
clone() 일치된 요소를 복사하고, 그를 선택합니다.
clone(bool) 이벤트 처리기를 포함하여 DOM 요소를 복사하고 그를 선택합니다.

별도의 설명이 필요없을 정도로 직관적이면서도, 매우 자주 사용하게 되는 메서드들입니다. 다만, 복사 관련 메서드(clone)는 약간의 부연 설명을 드릴 필요가 있는데요. 인자로서 true를 지정하게 되면, 단순히 요소만을 복사하는 것이 아니라, 그 요소에 달려있는 이벤트 처리기(예, click, mouseover)등도 복사가 된다는 것입니다. 인자가 없는 기본 clone() 메서드로 복사하게 되면, 요소 자체만 복사될 뿐, 해당 요소에 달려있는 이벤트 처리기들은 복사가 되지 않습니다. 해서, 이벤트 처리기까지 복사하고 싶다면 반드시 clone(true) 메서드를 사용해서 대상을 복사해야 한다는 점에 주의하세요.

자. 그럼, 이번 강좌에서 설명한 메서드들을 전반적으로 확인해보는 종합 예제를 같이 해 볼까요? 다음과 같은 htm 페이지를 하나 작성해 보도록 해요.

Manip.htm

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
  
<title></title>
  
<script src="jquery-1.3.2.min.js" type="text/javascript"></script>
  
<script type="text/javascript">
    $(
document).ready(
      
function() {
        $(
".annotation").each(function(i) {
            
var idx i + 1;
            
$(this).after("<sup>" + idx + "</sup>");
        
});

        
$("button").click(function() {
            
alert($(this).val());
            
$(this).remove();
        
});

        var 
$prev $("#prevBtn").clone();
        var 
$next $("#nextBtn").clone(true);

        
$("div#bottomDiv").prepend($prev);
        
$("div#bottomDiv").append($next);
    
});
  </
script>
  
<style type="text/css">
    
* { font-size:12px; font-family:돋움; }
    
.annotation { background: pink; }
  </
style>
</head>
<body>
  
<button id="prevBtn">이전 페이지로</button>
  
<button id="nextBtn">다음 페이지로</button>
  
<h3>jQuery란?</h3>
  
<div>
    
<b>jQuery</b>는 가볍고 빠르며, 간결한 <font class="annotation">오픈소스</font> 스크립트 라이브러리입니다. 이를 이용하면 Rich 웹 UI를 개발하는 데 도움이 되는 다양한 기능들 즉, HTML 문서  <font class="annotation">트래버스</font>, 이벤트 처리, 애니메이션, <font class="annotation">Ajax</font> 상호 작용 등을 지원하여 빠르고 견고하게 리치 웹 애플리케이션 개발을 할 수 있도록 지원합니다.
  
</div>
  
<br />
  <
div id="bottomDiv"></div>
</body>
</html>

jQuery 코드는 주석 표현을 화면에 삽입하는 것으로 시작하고 있습니다. append() 메서드를 설명할 때 예시했던 소스를 사용해서 말이죠. Annotation 이라는 css 클래스를 갖는 요소들을 루프 돌면서 <sup> 태그를 사용하여 주석을 표현하고 있는데요. 앞선 강좌 설명에서는 append 메서드를 사용했던 것에 반해, 이번 예제에서는 after 메서드를 사용해서 주석 표현을 하고 있습니다. 그 편이 좀 더 깔끔해 보여서요.

이어지는 코드는 <button> 요소들에 대해서 click 이벤트 처리기를 달고 있습니다. 그리고, click 처리기에서는 현재 버튼의 텍스트를 메시지박스로 나타낸 뒤, 그 버튼을 DOM에서 제거하도록 remove() 메서드를 사용하고 있습니다.

그리고, 마지막 코드 구역은 이전 페이지 버튼과 다음 페이지 버튼을 복사해서(clone), 하단의 div 영역에 append 하는 것을 볼 수 있습니다. 다만, 이전 페이지 버튼은 clone() 메서드로 복사를 했고, 다음 페이지 버튼은 clone(true) 메서드로 복사를 했기에, 전자는 클릭 이벤트 처리기가 무시되며, 후자는 click 이벤트 처리기까지 포함된 상태로 복사가 된 것을 확인할 수 있을 것입니다. 즉, 복사된 이전 페이지 버튼은 클릭해도 아무런 반응이 없지만, 다음 페이지 버튼은 메시지박스가 뜬다는 것이죠.

이를 테스트한 결과 화면은 다음과 같습니다.

어때요? 참 쉽죠?

jQuery는 참으로 사용하기 쉽고, 직관적인 API들로 구성되어 있다는 것을 느낄 수가 있습니다. 그리고, 개개의 메서드는 간단하지만 그것들을 혼합해서 사용하면 상당히 막강한 기능을 구현할 수 있도록 설계 되어 있죠.

다음 강좌는 트래버스에 관한 강좌를 생각하고 있습니다. 그리고, 그것이 마무리되면 바로 Ajax에 관한 기능들을 설명하는 것으로 일단은 jQuery 강좌를 마무리할 예정에 있어요. 긴 여정이 될지는 모르겠지만 꾸준히 관심을 주시는 분들이 있어서 힘을 더 내보겠습니다.

읽어주셔서 감사합니다.

Ps : 응원이 더 많으면 플러그인 제작까지도… 쿨럭


authored by Taeyo

Posted by 바람이불면
,

jQuery 셀렉터 : 필터 사용하기

필자의 잡담~

제가 jQuery 강좌에서 특히나 셀렉터 부분을 집중적으로 이렇듯 자세하게 설명하는 이유는 현재 출판된 서적이나 아티클들에서 이러한 부분을 조목조목 정리한 문서를 찾아보기가 쉽지 않아서 입니다(물론, 제가 잘 찾지 못했을 수도 있습니다).

더불어, 셀렉터(selector)가 jQuery의 화려한 기능들을 다루기에 앞서 반드시 알아두어야 하는 궁극의 기본기이기에 그렇기도 합니다.
jQuery 셀렉터 : 기본 필터

기본적인 셀렉터에 더하여, jQuery는 다양한 셀렉터 필터들도 제공을 합니다. 바로 앞에서 다루었던 어트리뷰트 셀렉터의 경우도 필터의 한 예입니다만, 어트리뷰트 셀렉터는 지금부터 다룰 필터들과는 표현식이 약간 달라서 기본 셀렉터와 함께 다루었습니다.

필터는 말 그대로 걸러내는 역할을 합니다. jQuery는 위치를 기반으로 필터링 하거나, 하위 자식들을 필터링할 수 있게 한다거나, 컨텐트를 기반으로 필터링하는 등 다양한 방식으로 원하는 요소들을 필터링하여 선택할 수 있게 합니다. 그리고, 대부분의 필터는 : 을 시작문자로 사용하는 단어들입니다. 이러한 필터는 일반적으로 기본 셀렉터에 덧붙여 사용하곤 하지만, 단독으로 사용할 수도 있습니다. 그러면, 우선 가장 일반적인 필터들부터 차례대로 살펴보도록 할까요?

< 기본 필터 >

:first 선택된 개체들 중 첫 번째 요소와 일치합니다.
:last 선택된 개체들 중 마지막 요소와 일치합니다
:not(selector) 괄호에 주어진 셀렉터와 일치되는 모든 요소를 제외합니다.
:even 짝수 요소들과 일치합니다(0부터 시작)
:odd 홀수 요소들과 일치합니다(0부터 시작)
:eq(index) 인덱스에 해당하는 단일 요소와 일치합니다
:gt(index) 주어진 인덱스보다 높은 인덱스를 갖는 모든 요소와 일치합니다
:lt(index) 주어진 인덱스보다 낮은 인덱스를 갖는 모든 요소와 일치합니다
:header 모든 헤더 요소들(h1, h2, h3 등)과 일치합니다
:animated 현재 애니메이션이 동작중인 모든 요소와 일치합니다

각각의 필터는 셀렉터로서 독립적으로 사용될 수도 있고, 다른 셀렉터와 함께 사용할 수도 있습니다. 더불어, 여러 필터를 이어서 사용할 수도 있죠. 예를 들어 다음과 같이 말이죠.

tr:odd
tr:gt(4)
tr:last
:header:eq(1)

각각의 셀렉터가 의미하는 바는 쉽게 이해하실 수 있을 것입니다.

첫 번째 셀렉터인 tr:odd는 현재 문서에 존재하는 모든 tr 중 홀 수번째 열들만을 선택하는 것이며, 두 번째 셀렉터인 tr:gt(4)는 문서에 존재하는 모든 tr 중 그 인덱스가 4 이상인 모든 열들을 선택하는 것이고요. 세 번째 셀렉터인 tr:last는 모든 tr 중 가장 마지막 tr을 선택하는 셀렉터입니다. 그리고, 마지막 셀렉터는 문서에 존재하는 헤더들 중에서 인덱스가 1번째인 헤더를 선택하는 셀렉터이지요.

주의할 점은 여기서의 인덱스는 0부터 시작이라는 것입니다. 고로, 첫번째로 나오는 tr은 인덱스 0을 가지므로, 홀수 열이 아니라 짝수열이라는 것을 기억하셔야 합니다.

해서, 다시 정리하자면,

tr:odd 문서에 나오는 모든 tr 중 홀수번째 tr만을 선택합니다. 그런데, 인덱스는 0부터 시작하므로, 사실, 제일 처음 나오는 tr은 짝수 열로 인식된다는 부분에 주의하세요.
tr:gt(4) 문서에 나오는 tr 중 5번째(인덱스 4) 후에 나오는 모든 tr 즉, 6번째 tr 부터 모든 tr을 선택합니다.
tr:last 문서에 나오는 모든 tr 중 가장 마지막에 존재하는 tr만을 선택합니다.
:header:eq(1) 현재 문서에 나오는 모든 헤더(h1, h2, h3 등) 중에서 인덱스 위치가 1인 헤더 즉, 눈에 보이기에 두 번째로 나오는 헤더를 선택합니다.

필터 앞에 아무것도 지정되지 않으면, 암시적으로 *이 지정된 것으로 인식됩니다. 즉, 이는 *:header:eq(1)와 동일한 표현으로 인식된다는 것이며, 페이지에 존재하는 모든 요소 중에서 헤더를 찾게 됩니다.

라는 것입니다. 하하. 설명이 쉬우니 머리에 쏙쏙 들어오죠? 더욱 이해하기 쉽도록 예제를 통해서 확인을 해보도록 합시다.

Filter01.htm

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    
<title></title>
    
<script src="jquery-1.3.2.min.js" type="text/javascript"></script>
    
<script type="text/javascript">
        $(
document).ready(
            
function() {
                $(
"tr:odd").css("background""#efefef");
                
$("tr:gt(4)").css("background""silver");
                
$("tr:last").css("background""yellow");
                
                
$(":header:eq(0)").css("font-weight""bold").css("color""blue");
            
});
    </
script>
    
<style type="text/css">
        
* { font-size:12px; font-family돋움 }
        
.nameTable { background: white; border-collapse:collapse }
    </
style>
</head>
<body>
    
<h3>수학 시험 점수</h3>
    
<table class="nameTable" border="1" cellpadding="10">
        
<tr><td width="100">name</td><td width="100">value</td></tr>
        
<tr><td>Taeyo</td><td>80</td></tr>
        
<tr><td>Dragon</td><td>98</td></tr>
        
<tr><td>Eric</td><td>85</td></tr>
        
<tr><td>Queeny</td><td>96</td></tr>
        
<tr><td>Youngsun</td><td>88</td></tr>
        
<tr><td>kobukii</td><td>90</td></tr>
        
<tr><td>Mr.Net</td><td>92</td></tr>
    
</table>
</body>
</html>

보시디시피, 문서에는 총 8개의 tr이 존재하고 있고요. 각각의 셀렉터는 그러한 tr을 대상으로 해서 스타일을 매기고 있습니다. css() 라는 메서드는 이전 강좌에서도 다룬 적이 있지만, 대상 개체에 css 스타일을 적용하는 메서드인거 기억하시죠?

예제는 모든 홀수번째 tr(tr:odd)에게는 #efefef 배경색(아주 연한 회색)을 적용하고 있고요. 인덱스 번호 4 이후의 모든 tr들(즉, 6번째 tr 부터)에 대해서는 silver 배경색을 적용하고 있습니다. 그리고, 가장 마지막 tr(tr:last)에 대해서는 yellow 배경색을 주고 있고요. 더불어, 문서상에서 첫 번째로 나오는 헤더(:header:eq(0))에는 굵고 파란색의 폰트를 설정하고 있습니다.

해서, 결과 화면은 다음과 같이 나타나게 되는 것이죠.

매우 간단한 예제였지만, 이 예제는 마지막 셀렉터에 스타일을 주는 부분에서 재미있는 것이 하나 있는데요.

$(":header:eq(0)").css("font-weight""bold").css("color""blue");

라는 구문을 보시면, 셀렉터 대상에 대해서 css()라는 메서드를 연달아 사용하는 것을 볼 수 있죠? 이를 메서드 체인이라고 하는데요. jQuery가 제공하는 모든 메서드는 그 반환값(return value)이 효과가 반영된 jQuery 개체이기 때문에 이런 식으로 메서드를 이어서 사용할 수가 있습니다. 다시 말해서, 저 표현은

var jQ = $(":header:eq(0)")
jQ = jQ.css("font-weight", "bold");
jQ = jQ.css("color", "blue");

와 동일하다 할 수 있다는 것이죠. 하지만, 이러한 방식은 직관적이기는 하지만 소스가 길어지는 단점이 있기에, 일반적으로는 메서드 체인으로 작성하곤 합니다.

물론, 메서드 체인으로 작성할 경우에, 체인이 너무 길어지게 되면 오히려 소스가 더 복잡해 보일 수 있기에 부담스러워 하시는 분들도 있는데요. 자바스크립트는 줄바꿈을 인식하지 않기 때문에 다음과 같이 줄을 바꿔가면서 메서드 체인을 작성할 수 있습니다. 그리고, 대부분의 jQuery 개발자들도 다음과 같은 메서드 체인 방식을 즐겨 사용한답니다.

$(":header:eq(0)")
    .css("font-weight", "bold")
    .css("font-size", "12px")
    .css("color", "blue");

어때요? 보기 편하죠? 지금은 가벼운 예제들이기에 이러한 메서드 체인은 자주 볼일이 없지만, 이후의 강좌에서는 다양한 기능을 다루면서 메서드 체인이 마구 늘어나게 될 것입니다.

위의 메서드 체인에서는 css() 메서드를 3번 연속 사용하고 있는데요. 이는 단지 메서드 체인의 예를 든 것임을 기억하세요. 실제로 저렇게 여러 스타일을 매기고자 하는 경우에는, css 메서드를 반복해서 사용하지 않고요. 스타일시트 파일에 필요한 css 클래스를 하나 만들어 두고, jQuery의 addClass() 메서드를 사용하여 스타일을 한번에 지정하곤 합니다. 이에 대해서는 뒤에서 다룰 예정입니다.

참 재미있군요.

물론, "별로 재미없는데요"라고 말하시는 분이 있을 수도 있습니다만, 이 기능은 실제 jQuery가 제공하는 막강한 기능의 10%도 안되는 것이라서 아직까지는 감동이 적을 수도 있습니다. 셀렉터를 다루는 것은 jQuery의 멋진 기능을 다루기 위한 기본기라는 것을 기억하셔야 합니다. 지금은 드리볼을 배우는 단계입니다. 아직은 슛을 쏘기에는 이르다는 것이죠.

jQuery 셀렉터 : 컨텐트 필터와 자식 필터

이상 기본 필터에 대해서 알아봤는데요. 이 외에도 몇 개 안되지만 컨텐트 필터와 자식 필터라는 것이 또한 존재합니다. 이 또한 자주 쓰일만한 것이기에 마저 알아보도록 하죠.

먼저 컨텐트 필터입니다. 현재 버전에서는 꼴랑 다음과 같이 4개의 필터가 존재합니다.

< 컨텐트 필터 >

:contains(text) 지정한 텍스트를 포함하는 요소들과 일치됩니다
:empty 자식을 가지지 않는 모든 요소와 일치됩니다. 더불어, 내부 텍스트를 가지지 않는 요소들도 이에 해당됩니다.
:has(selector) 지정된 셀렉터에 해당하는 요소를 갖는 모든 요소들과 일치됩니다.
:parent 부모인 모든 요소들과 일치됩니다. 자식 요소를 갖는 요소 뿐만 아니라 텍스트를 갖는 요소들이 이에 해당됩니다.

별거 아닌 것처럼 보이는 이 필터들, 막상 알고나면, 각각의 필터들이 상당히 유용합니다.

개인적으로는 :empty 필터가 상당히 유용했는데요. 예를 들면, 그리드 출력을 하는 경우에, 값이 누락되어 있는 셀들(td)을 찾아서 그 셀들만 배경색을 회색으로 처리한다거나 할 때는 완전 딱입니다. 물론, contains() 필터와 :has() 필터도 유용하긴 마찬가지 입니다.

다음과 같은 셀렉터를 한번 살펴볼까요?

b:contains('j')
div:has('ul')
table.nameTable td:empty
.nameTable td:contains('F')
table.nameTable tr:eq(0)

첫 번째 셀렉터는 "j"라는 단어를 포함하는 모든 b 요소들을 선택합니다.
두 번째 셀렉터는 모든 div 요소들 중에 ul 요소를 가지고 있는 div 만을 선택합니다.
세 번째 셀렉터는 nameTable이라는 css 클래스가 지정된 table들 중에서 자식 요소인 td 내부에 텍스트 값이 없는(또는 자식요소가 없는) 모든 td를 선택합니다.
네 번째 셀렉터는 nameTable이라는 css 클래스가 지정된 요소들 중에서 그 내부의 td가 텍스트로 "F"란 단어를 포함하고 있는 모든 td를 선택합니다.

마지막 셀렉터는 이미 이전에 다루었던 것이라 굳이 설명할 필요가 없어보이긴 하지만 복습의 차원에서 설명하자면, nameTable이라는 css 클래스가 지정된 table 내의 tr 중에서 첫번째 tr을 선택합니다.

그다지 어렵지 않게 구분이 가능하시죠?

그리고, 기왕 이야기를 하는 김에요. 사실은 이전 강좌에서 이야기할까 하다가 접었던 짧은 이야기를 하나 보태볼까 하는데요. 복습의 차원에서 한번 읽어봐 주시겠어요?

만일, 문서 내에 table 요소가 한 개만 존재하고, 그 table에 nameTable 이라는 css 클래스가 적용이 되었다면, 다음의 셀렉터는 모두 같은 것을 선택한다는 것!

$("table.nameTable tr")
$(".nameTable tr")
$("table tr")
$("tr")

네. 당연한 이야기입니다. 그렇죠? 그래요. 기본 셀렉터의 다양한 형태를 복습의 차원에서 한번 같이 살펴본 것 뿐입니다. 굳이 이러한 이야기를 꺼낸 것은 셀렉터를 처음 접할 경우에는 셀렉터를 어떻게 작성하는 것이 좋은지에 대해 자꾸 걱정하는 분들이 있어서요. 셀렉터는 문서 내에서 원하는 요소를 명확히 찾아낼 수 있는 직관적인 구문이면 뭐든지 오케이입니다. 특별히 어떤 구문이 더 좋다라는 식의 정해진 룰은 없습니다. 물론, 자꾸 사용하시다보면 자신만의 패턴이 생기긴 할 겁니다~(저의 경우는 가급적 구문을 상세하게 작성하는 것을 권합니다)

그러면, 이제 예제를 통해서 컨텐트 필터들의 사용 예를 한번 살펴볼까요?

Filter02.htm

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    
<title></title>
    
<script src="jquery-1.3.2.min.js" type="text/javascript"></script>
    
<script type="text/javascript">
        $(
document).ready(
            
function() {
                $(
"b:contains('j')").css("background""yellow");
                
$("div:has('ul')").css("border""solid 1px green");

                
$("table.nameTable td:empty").css("background""#dddddd");
                
$(".nameTable td:contains('F')").parent().css("background""pink");
                
$("table.nameTable tr:eq(0)").css("background""lightblue");
            
});
    </
script>
    
<style type="text/css">
        
* { font-size:12px; font-family돋움 }
        
.nameTable { background: white; border-collapse:collapse }
    </
style>
</head>
<body>
    
<h3>jQuery란?</h3>
    
<div>
        
<b>jQuery</b>는 가볍고 빠르며, 간결한 오픈소스 스크립트 라이브러리입니다. 
        이를 이용하면 Rich 웹 UI를 개발하는 데 도움이 되는 다양한 기능들 즉,
        
<b>HTML 문서 트래버스</b><b>이벤트 처리</b><b>애니메이션</b><b>Ajax 상호작용
        </b>등을 지원하여 빠르고 견고하게 리치 웹 애플리케이션 개발을 할 수 있도록 지원합니다.
    
</div>
    
<br />
    <
div>
        이러한
<b>jQuery</b>의 기능적인 특징은 다음과 같습니다
    
</div>
    
<br />
    <
div>
        
<ul>
            
<li>막강한 CSS 셀렉터</li>
            
<li>크로스 브라우저 지원</li>
            
<li>메서드 체인</li>
            
<li>Ajax 지원</li>
            
<li>풍부한 플러그 인 지원</li>
        
</ul>
    
</div>
    
<br />
    <
table class="nameTable" border="1" cellpadding="3">
        
<tr><td width="100">이름</td><td width="100">성별</td><td width="100">기타 정보</td></tr>
        
<tr><td>Taeyo</td><td>M</td><td>...</td></tr>
        
<tr><td>Dragon</td><td>M</td><td>...</td></tr>
        
<tr><td>Eric</td><td>M</td><td>...</td></tr>
        
<tr><td>Queeny</td><td>F</td><td>...</td></tr>
        
<tr><td>Youngsun</td><td></td><td>...</td></tr>
        
<tr><td>Hera</td><td>M</td><td>...</td></tr>
        
<tr><td>Secret</td><td>F</td><td>...</td></tr>
    
</table>
</body>
</html>

셀렉터들이 어떤 요소를 선택하고, 어떻게 동작할지는 소스를 보시면 이해가 되실 것입니다. 예제에서 사용한 셀렉터는 이미 예제에 앞서 설명을 드린 셀렉터 그대로이니까요. 다만, 4번째 구문인 다음 구문에서는 parent()라는 처음 보는 메서드가 하나 사용된 것을 보실 수 있을 겁니다.

$(".nameTable td:contains('F')").parent().css("background", "pink");

parent()라는 메서드는 말 그대로 현재 셀렉터에 의해 선택된 개체 집합의 바로 위 부모 개체를 반환하는 메서드입니다. 고로, 이 구문은 .nameTable 이라는 css 클래스를 갖는 개체의 td들 중에서 "F"라는 텍스트를 포함하는 모든 td를 찾아낸 다음(여기까지가 셀렉터), 그의 부모인 tr 개체를 얻어내서( parent 메서드), 그의 배경색을 핑크빛으로 물들이는 것입니다.

그리고, 결과 화면은 이미 여러분이 셀렉터를 해독하여 예상하고 있던 것과 마찬가지로 다음과 같이 나타나게 될 것입니다.

예상대로, b 요소 중 "j"라는 단어가 포함된 것들은 노란 배경색으로 출력되고 있으며, div 요소들 중에서 ul이라는 자식 요소를 가진 개체는 녹색 테두리로 나타나고 있습니다. 또한, 테이블에서 내용이 없는 td는 연한 회색으로 채워져 있으며, td 안의 텍스트가 "F"라는 글자를 포함하고 있으면 그의 부모인 tr이 핑크색으로 출력되는 것을 볼 수 있습니다. 마지막으로, 가장 첫 번째 tr은 연한 파란색으로 출력되고 있고요.

컨텐트 필터는 이처럼 요소의 컨텐트와 관련하여 필터링을 하는데 사용할 수 있는 기능입니다.

컨텐트 필터 외에 또 다른 필터로 자식 필터라는 것도 있습니다. 자식 필터는 말 그대로 현재 요소의 자식들에 대한 필터를 할 수 있는 기능을 제공하는데요. 현재 버전의 jQuery(1.3.2)에서는 다음과 같이 4개의 자식 필터가 제공됩니다.

< 자식 필터 >

:nth-child(index/even/odd) 자식 중 index로 지정된 위치의 요소들과 일치되거나, even, odd에 해당하는 자식들과 일치됩니다. 단, 여기서의 index는 1부터 시작합니다.
:first-child 첫 번째 자식인 모든 요소와 일치됩니다.
:last-child 마지막 자식인 모든 요소와 일치됩니다.
:only-child 자신이 부모 요소의 유일한 자식인 모든 요소와 일치됩니다

처음 이 필터를 접할 경우에는 이전에 다루었던 기본 필터 중 :first, :last와 유사한 필터가 아닐까 하고 생각할 수 있는데요. 사실 이들은 기존의 필터와 상당한 차이가 있습니다.

:first, :last 필터가 단일 요소를 선택하는 반면, 자식 필터들은 단일 요소가 아닌 해당 요소들의 집합을 선택한다는 것이 차이입니다. 예를 들어, 다음 두 셀렉터의 차이를 한번 생각해 볼까요?

td:first
td:first-child

얼핏 보기에는 같은 요소를 선택할 것처럼 보이는 이 둘은 확실한 차이를 보입니다. 즉,

td:first는 현재 테이블 안에서 첫 번째로 나오는 td 하나 만을 선택하는 반면, td:first-child는 현재 테이블 안에서 나오는 첫 번째 수준의 td들을 모두 선택한다는 것이죠. 말로 이해가 잘 안 가시면 다음 그림을 한번 보도록 하세요.

차이가 느껴지시죠?

:nth-child라는 필터도 동작 방식은 동일합니다만, 인덱스를 지정할 수 있거나, even 이나 odd와 같은 값을 지정하여, 짝수나 홀수 번째 그룹이 선택되도록 할 수 있습니다. 심지어는 Xn+Y와 같은 수식을 사용해서 특정 규칙에 따라 선택할 수도 있습니다. 예를 들어, td:nth-child(3n)과 같이 작성하게 되면, 이는 3의 배수에 해당하는 위치의 td 그룹이 선택될 것이며, td:nth-child(2n+1)과 같이 작성하게 되면, 2의 배수에 1을 더한 값에 해당하는 위치의 td 그룹이 선택될 것입니다. 수식에서의 n은 0부터 계산되기에, 3n은 0,3,6,9 .. 에 해당하는 그룹이 되며, 2n+1은 1,3,5,7… 에 해당하는 인덱스 그룹이 선택될 것입니다.

다만, 여기서의 인덱스는 0부터 시작하는 것이 아니라 1부터라는 것에 유념하셔야 합니다. 요 부분이 살짝 짜증(?) 나는 부분이긴 한데요. 앞서 다룬 기본 필터(:even, :odd, :eq(index), :gt(index) 등)에서는 인덱스가 0부터 시작했으나, 자식 필터인 :nth-child에서의 인덱스는 1부터 적용된다는 것이죠.

즉, :first-child와 동일한 것은 :nth-child(1)이지, :nth-child(0)이 아니라는 것입니다. 자식 필터에서 :nth-child(0)은 그 어떤 것과도 일치되지 않습니다. 꼭 기억하세요. 자식 필터를 사용하는 경우에는 인덱스가 1부터 시작한다는 것을요.

이로써, 기본 셀렉터에서 사용할 수 있는 필터들을 어느 정도 정리한 것 같네요. 물론, 아직 visible 관련 필터(2개)가 남아있긴 한데요. 이 부분은 다음 강좌의 시작부에서 가볍게 정리하기로 하겠습니다.

다음 강좌의 본격적인 내용은 사실 셀렉터의 하이라이트라고 할 수 있는 폼 셀렉터에 대한 이야기입니다. 입력 UI를 구현하려면 피해갈 수 없는 폼 요소들을 셀렉터를 이용해서 쉽게 선택할 수 있는 것이 바로 폼 셀렉터인데요. 그러한 셀렉터들을 살펴봄으로써 jQuery의 기본인 셀렉터에 대한 이야기를 완전하게 마무리하도록 하겠습니다.

사실, 이러한 분류는 실제 jQuery 온라인 문서에 나온 분류를 기반으로 말씀을 드리고 있습니다. 해서, 제가 설명드린 셀렉터들에 대해서 개별적으로 조금 더 자세한 설명을 보고 싶다 하시면, http://docs.jquery.com/Selectors 페이지에 가셔서 각각의 셀렉터를 클릭하여 자세한 설명과 함께 라이브 데모 및 소스까지 즐기실 수 있습니다. 꽤 많은 셀렉터가 있지만, 태오와 함께 깔끔한 강좌로 같이 정리해 나가니 생각보다 많게 느껴지시지 않죠? 어쩌면 jQuery의 공식문서보다 저의 강좌가 더 명쾌하게 느껴지실 지도 모르겠습니다(네. 왠지 태오 갑자기 재수가 좀 없군요…).

그러면, 다음 강좌에서 또 뵙겠습니다. 잘 읽으신 분은 /환호 /토닥 한번씩 날려주세요.


authored by Taeyo

Posted by 바람이불면
,

jQuery, 기본 셀렉터

필자의 잡담~

본격적인 jQuery의 기초 설명에 들어갑니다~
그 시작은 셀렉터 입니다~
jQuery란?

jQuery는 가볍고 빠르며, 간결한 오픈소스 스크립트 라이브러리입니다. 이를 이용하면 Rich 웹 UI를 개발하는 데 도움이 되는 다양한 기능들 즉, HTML 문서 트래버스, 이벤트 처리, 애니메이션, Ajax 상호 작용 등을 지원하여 빠르고 견고하게 리치 웹 애플리케이션 개발을 할 수 있도록 지원합니다.

이러한 jQuery의 기능적인 특징을 핵심 키워드만 뽑아서 정리하자면,

  • 막강한 CSS 셀렉터
  • 크로스 브라우저 지원
  • 메서드 체인
  • Ajax 지원
  • 풍부한 플러그 인 지원

정도로 설명할 수 있지 않을까 싶네요. 물론, 이 외에도 많은 것들이 제공되지만 말이죠.

개발 준비사항

처음 jQuery를 공부하고자 맘을 먹고, jQuery 웹 사이트에 가면 이런 생각이 들지도 모르겠습니다.

"에~ 그러니깐, 어디서부터 뭘 어떻게 봐야 하는 거지?"

그렇습니다. 어린 시절부터 완전정복, 맨투맨 류의 참고서적에 길들여져 있는 우리들은 항상 신기술을 접할 때 어떻게 시작해야 할지를 막막해하곤 하죠. 이는 비단 저도 예외가 아닙니다. 하지만, 언제나 신기술이 나왔을 때 가장 좋은 설명서는 해당 웹 사이트에 공개되어 있는 튜토리얼이라는 것은 변함이 없는 사실이지요(물론, 저의 경우는 인터넷 서점에서 관련 서적을 구입한 뒤, 1독이상을 하고 난 뒤에 튜토리얼을 보는 편입니다만, 이는 지극히 개인적인 성향에 따라 다른 부분입니다). 여러분도 성향에 따라 튜토리얼을 보셔도 되고, 제 강좌를 보셔도 되고, 서적을 구매해서 보셔도 됩니다(제 강좌에는 너무 의존하지 마세요 ㅎ).

공부하는 방식은 각자의 선택에 따라 다르지만, jQuery 라이브러리는 모두가 반드시 다운로드 하여 준비해야 하는 사항입니다. 해서, 우선 jQuery를 다운로드 받도록 하죠. http://jquery.com/ 에 가면 메인 화면에서 바로 다운로드가 가능하며, 현재 강좌 작성 기준으로 jQuery의 최신 버전은 1.3.2 를 얻으실 수 있습니다. 그리고, 구하신 파일은 여러분이 작업하는 어떠한 웹 애플리케이션에든지 복사해서 쓰시면 됩니다.

그럼 이제 jQuery의 셀렉터를 이야기하는 것으로 본격적으로 시작해볼까요?

jQuery 셀렉터 : 기본

jQuery의 가장 강력한 부분은 HTML DOM을 마음대로 트래버스 즉, 순회 탐색할 수 있다는 것인데요. 놀랍게도, CSS 셀렉터를 사용하여 원하는 개체를 탐색할 수 있습니다. CSS 셀렉터(Selector)는 대부분의 웹 개발자라면 이미 아실 것이라 생각합니다. 다음과 같이 css 파일에서 사용했던 표현식이 바로 CSS 셀렉터이니까요.

div p {
    font-color
:red;
}

#loginID {
    font-weight
:bold;
    background
:yellow;
}

.Columns {
    padding
:10px;
    background
:white;
}

div p라는 셀렉터는 현재 문서 상에서 div 요소의 자식으로 존재하는 모든 p 요소들에 적용되며, #loginID는 loginID라는 id 값을 가진 요소에, .Columns는 class 어트리뷰트 값으로 Columns를 갖는 모든 요소에 적용되는 것이죠.

이러한 셀렉터를 그대로 jQuery에서 사용할 수 있다는 것은 놀랍습니다. jQuery에서는 원하는 DOM 요소의 그룹을 찾기 위해서 $(selector) 혹은 jQuery(selector)과 같은 표현식을 사용하기에, 위의 3가지 셀렉터를 다음과 같이 사용할 수 있습니다.

$("div p") 혹은 jQuery("div p")
$("#loginID") 혹은 jQuery("#loginID")
$(".Columns") 혹은 jQuery(".Columns")

그리고, 각각의 표현식은 각 DOM 요소의 확장 개체인 jQuery 개체 집합을 반환합니다. DOM 요소를 직접 반환해주는 것이 아니라 그의 래퍼(Wrapper)인 jQuery 개체로 반환해 주기 때문에 직접 DOM 요소를 제어할 때보다 훨씬 편하고 쉽게 개체를 제어할 수 있다는 장점이 있습니다. 예를 들어, $("div p").hide() 와 같은 명령을 사용하면, 현재 문서 상에서 div 요소의 자식으로 존재하는 모든 p 태그집합들은 눈에서 보이지 않게 됩니다. hide()라는 명령은 jQuery 개체가 지원하는 명령이며, 추후 알아보게 될 것인데요. jQuery 셀렉터에 의해 반환되는 개체가 일반 DOM 개체라면 이러한 명령을 사용할 수 없겠지만, jQuery 개체 집합으로 반환되기에 그러한 명령을 사용할 수 있게 되는 것입니다. (아직, hide() 명령의 역할에 대해서는 설명하지 않았지만, 이름만 봐도 기능을 추측할 수는 있겠죠?)

모든 요소를 선택하기 위해서는 $("*")와 같은 표현을 사용할 수 있습니다.

또한, jQuery는 이러한 기본적인 CSS 셀렉터 외에 고급 CSS 셀렉터도 지원합니다. 예를 들면, 계층 셀렉터, 일반 필터 셀렉터, 어트리뷰트 필터 셀렉터 등이 바로 그것인데요. 다음은 계층 셀렉터의 예입니다.

p > a : p 요소 바로 아래 자식인 a 요소(하이퍼링크)와 일치된다.
div + p : div 요소의 바로 다음에 나오는 형제 p 요소와 일치된다.
div ~ p : div 요소의 다음에 나오는 모든 형제 p 요소와 일치된다.

$("p a")와 $("p > a")의 차이점은 전자가 p요소 하위에 존재하는 모든 a 요소를 선택한다면, 후자는 p 요소 바로 아래의 자식으로 놓여있는 a 요소만을 선택한다는 것이 차이입니다.

즉, 다음과 같은 html이 존재한다면,

<p>
    
<span>
        
<a href="1.aspx">1.aspx</a>
    
</span>
    
<br />
    <
a href="2.aspx">2.aspx</a>
</p>

$("p a")는 1.aspx 링크와 2.aspx 링크 모두를 선택하지만, $("p > a")는 2.aspx 링크만을 선택한다는 것이죠.

div + p 및 div ~ p 와 같은 경우는 자식이 아니라 형제 요소와 연관이 있습니다. 즉, 다음과 같은 html 있다고 가정할 경우에 말입니다.

<div>앨범 목록입니다</div>
<p>노라조</p>
<span>수퍼맨</span>
<p>이적</p>
<span>다행이다</span>
<p>현진영</p>
<span>Break me down</span> 

$("div + p")는 div 바로 다음에 나오는 형제 수준의 p 요소, 즉, "노라조"를 선택하게 되는 반면, $("div ~ p")는 div 요소 다음에 나오는 형제 요소들 중 모든 p 요소, 즉, "노라조", "이적", "현진영"과 일치된다는 것이죠.

더불어, a[title]이나 a[href^="mailto:"]와 같이 어트리뷰트를 기반으로 하는 필터링도 가능한데요. 특정 어트리뷰트가 존재하거나, 그 어트리뷰트 값이 특정 값으로 시작 혹은 끝나거나, 특정 값을 포함하거나 하는 부분까지 비교해서 선택할 수 있습니다. 다음은 이러한 어트리뷰트 필러의 예입니다.

a[title] : title 어트리뷰트를 갖는 하이퍼 링크와 일치된다.
a[href^="mailto:"] : href 값이 mailto로 시작하는 하이퍼 링크와 일치된다.
a[href$=".pdf"] : pdf 파일에 링크가 걸린 모든 하이퍼링크와 일치된다.
a[href*="taeyo.net"] : taeyo.net이라는 값이 포함되어 있는 모든 하이퍼 링크와 일치된다.
input[type="text"] : text 형식의 입력 컨트롤과 일치된다.

이러한 선택이 가능한 것은 시작부분(^) 혹은 끝부분($)을 가리키는 정규 표현식을 jQuery가 지원하기 때문입니다.

그러면, 우선 지금까지 알아본 셀렉터들, 가장 기본이 되는 이러한 셀렉터들을 한번 정리해보고 넘어가도록 하겠습니다.

jQuery가 지원하는 CSS 셀렉터들

셀렉터 설명
* 모든 요소와 일치
E1 E1(태그명)인 모든 요소와 일치
E1.class E1(태그명) 요소의 클래스가 class와 동일한 요소와 일치
E1.#id E1(태그명) 요소의 id 어트리뷰트 값이 id와 동일한 요소와 일치
E1 E2 E1 요소의 자식인 모든 E2(태그명) 요소와 일치
E1 > E2 E1 요소 바로 아래 자식인 E2 요소와 일치
E1 + E2 E1 요소의 바로 다음에 나오는 형제요소 E2와 일치
E1 ~ E2 E1 요소의 다음에 나오는 모든 형제 E2와 일치
E1[attr] attr 어트리뷰트를 갖는 E1 요소와 일치
E1[attr=val] attr 어트리뷰트의 값이 val을 갖는 E1 요소와 일치
E1[attr^=val] attr 어트리뷰트의 값이 val 값으로 시작하는 E1 요소와 일치
E1[attr$=val] attr 어트리뷰트의 값이 val 값으로 끝나는 E1 요소와 일치
E1[attr*=val] attr 어트리뷰트의 값이 val 값을 포함하는 E1 요소와 일치

그리고, 이러한 셀렉터를 사용하는 가벼운 예제를 한번 같이 해 보도록 하겠습니다. 가상 디렉토리를 하나 만드시고, 다음과 같은 htm 파일을 하나 작성하도록 하세요. 물론, 동일 폴더에는 아까 다운로드 받은 jQuery 자바스크립트 파일(저의 경우, jquery-1.3.2.min.js)이 있어야 하겠죠?

Default.htm

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    
<title></title>
    
<script src="jquery-1.3.2.min.js" type="text/javascript"></script>
    
<script>
        $(
document).ready(
            
function(){
                $(
"#song").css("border""solid 1px silver");
                
$("a[href^='mailto:']").css("background""lightblue");
                
$("input[type='button']").css("background""yellow");

                
$("div ~ b").css("background""#efefef");
                
$("div > b").css("border""1px");
            
});
    </
script>
    
<style type="text/css">
        
* { font-size:12px; font-family:돋움 }
    </
style>
</head>
<body>
    
<div>
        
<span><a href="http://taeyo.net">taeyo.net</a></span>
        
<br />
        <
a href="mailto:taeyo@A.net">태오의 메일주소</a>
        
<p>
            
<input type="button" value클릭~ />
            <
input type="checkbox" />
            <
input type="radio" />
        </
p>
        
        
<div id="song">요즘 노래방에서 부르는 노래 목록입니다</div><br />
        <
b>노라조</b>
        
<span>수퍼맨</span><br />
        <
b>이적</b>
        
<span>다행이다</span><br />
        <
b>현진영</b>
        
<span>Break me down</span>        
    
</div>
</body>
</html>

예제는 간단합니다. jQuery 셀렉터를 사용해서 몇몇 DOM 요소의 스타일을 변경하는 것이 전부이니까요. 그렇다고, 설명을 안하면 뭔가 서운하니깐, 이야기를 한번 해 보죠.

일단, $(document).ready();라는 함수에 대해서는 설명을 드릴 필요가 있을 듯 합니다. 이는 jQuery가 제공하는 이벤트 메서드 중 하나인데요. 문서의 DOM 요소들을 조작 가능한 시점이 되면 자동으로 호출이 되는 이벤트 메서드라고 보시면 됩니다. 굳이 비교하자면, window.onload 이벤트와 유사한 것이라고 보면 되겠네요. 메서드의 인자로는 델리게이트 함수명을 기입하거나, 익명 함수를 작성하면 됩니다. jQuery를 사용하는 경우에는 일반적으로 별도의 델리게이트 함수를 작성하지 않고, 익명함수를 그대로 작성하곤 합니다. 해서, 소스에서도 그렇게 처리한 것을 보실 수 있습니다. 이 방식은 처음에는 뭔가 복잡해 보일 수 있습니다만, 차츰 매우 익숙해지게 되실 것입니다. 사실, $(document).ready()와 windows.onload 이벤트와는 확실한 차이점이 있습니다만, 일단은 비슷하다고만 기억을 하시고요. 나중에 관련 이야기가 본격적으로 펼쳐질 때, 다시 설명드리도록 하겠습니다.

그리고, 익명 함수 내에서는 다양한 jQuery 셀렉터들을 보실 수 있습니다. 일단, 셀렉터로 원하는 DOM 요소를 찾고, css() 라고 하는 jQuery의 메서드를 사용해서 스타일을 매기는 것을 볼 수 있습니다. 기본적으로 DOM 요소는 css() 라는 메서드는 가지고 있지 않지만, jQuery 셀렉터가 반환하는 개체는 jQuery 확장 개체이기에, 이러한 메서드를 사용해서 쉽게 스타일을 매길 수가 있습니다. 각각의 셀렉터가 어떤 DOM 요소와 일치하는 지는 설명을 드리지 않아도 되겠죠? 여러분이 이미 다 아실 수 있을테니까요. 다음은 이번 예제의 실행 결과입니다.

참 쉽죠?

다음 강좌에서는 이렇듯 막강한 셀렉터에 대해서 조금 더 알아볼 예정입니다. 즉, jQuery 셀렉터 필터라는 것에 대해서 살펴볼까 해요. 원래는 같이 하나의 강좌로 올리려 했는데 생각보다 길어져서 기본 셀렉터만 먼저 올리게 되었습니다 ^^; 셀렉터 필터까지 알고 나시면, 여러분은 찾고자 하는 DOM 요소를 정말 편하고 쉽게 얻어내실 수 있다고 장담합니다.

스크립트 라이브러리를 왜 써야 하는가?

물론, 안 써도 됩니다. 매번 스크립트 기능이 필요할 때마다 손수 다 작성해도 뭐라 그럴 사람은 없으니까요. 하지만, 팀 개발을 하는 경우나 유사한 프로젝트를 반복해서 하는 경우에는 여러분 스스로가 가벼운 수준일지라도 자신만의 라이브러리(일반적으로 유틸리티 function들을 모아놓은 js 파일들) 만들어 놓고 있을 것입니다. 그러면서, 뭔가 풍족하고도 믿고 사용할만한 라이브러리는 없을까 둘러보곤 하죠.

일반적으로 우리가 웹 프로젝트에서 공개된 혹은 상용의 스크립트 라이브러리를 사용하려는 데에는 다음과 같은 이유가 있기 때문입니다.

  • 모든 브라우저에서 올바로 동작하는 자바스크립트를 작성하기는 힘들다.
  • 유사한 기능을 위해서 반복적으로 스크립트 코드를 작성하곤 한다.
  • 수 많은 자바스크립트로 인해 사이트의 유지보수가 힘들다.

더 많은 이유가 있겠지만, 결론적으로 말하자면 스크립트 라이브러리를 사용할 경우, 공수(비용과 시간)를 줄일 수 있고, 개발 및 관리하기가 편해지며, 균일한 코드 퀄리티를 유지할 수 있고, 그에 따라 스트레스도 줄어들기 때문이라고 할 수 있을 것입니다. 사실 이것이 서버 측이던 클라이언트 측이던 프레임워크를 도입하는 대표적인 이유이기도 하죠.




authored by Taeyo

Posted by 바람이불면
,

jQuery 사용하기

jquery 시작 2009. 6. 30. 00:58

jQuery: The Basics

<!DOCTYPE html>
<html lang="en">
<head>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
   <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script>
   <script type="text/javascript">
     $(document).ready(function(){
       $("a").click(function(event){
         alert("As you can see, the link no longer took you to jquery.com");
         event.preventDefault();
       });
     });
    
   </script>
</head>
<body>
   <a href="http://jquery.com/">jQuery</a>
</body>
</html>

 

  • script 파일은 <head> 태그 사이에 위치 시킵니다.
  • $(document).ready(function(){   // Your code here }); 는 자바스크립트 window.onload의 문제를 우회하기 위해서 이용합니다.
    • window.onload = function() { alert("welcome"); } 는 웹페이지의 구조(DOM)가 로드된 직후에 호출되지 않고, 페이지 내의 모든 컨텐츠(이미지, 광고배너, 스크립트파일등)가 로드되어야만 호출이 되는 문제를 가지고 있음.
  • event.preventDefault() 는 이벤트의 기본적인 행동을 방해합니다. 위의 샘플의 경우 페이지 이동을 하지 않습니다.
  • 위의 예의 경우는 링크 클릭시 alert 창만 띄우고 페이지가 이동하지 않습니다.  
Posted by 바람이불면
,

jQuery 다운로드

jquery 시작 2009. 6. 29. 12:01

jQuery 다운로드

 

jQuery 다운로드

여러 브라우저에서 안정적으로 이용하려면 jQuery 추천버젼을 사용을 권장합니다.

jQuery 는 두개의 버젼으로 이루어져 있습니다.

  • minified versions
    • 압축이 되어 있지 않아 packed versions 보다는 사이즈가 크지만, 압축을 푸는 과정이 없어 빠르게 실행이 가능한 버젼입니다.
  • packed versions
    • packed versions 은 minified versions 과는 다르게 압축이 되어 있어, 클라이언트에서 실행시에 압축해제 과정이 있어 minified versions 보다는 실행이 느립니다.

Current Release

문서

API Reference, html 파일형식으로 zip압축되어 있습니다.

Past Releases


Nightly Builds

서브버젼 저장소에 접근권한이 없는 사람, 저장소로 부터 파일을 카피하여 본인이 직접빌드를 원하지 않은 사람들이 작업하여 서브버젼에 올려놓은 소스코드는 야간에 빌드과정을 거쳐서 만들어 집니다. 

The nightly files 은 여기 (http://code.jquery.com/nightlies/) 에서 이용할 수 있습니다. 해당 디렉토리안에 아래와 같은 파일이 있습니다 :

 

Subversion (SVN)

  • jQuery 는 SVN 이라는 최근기술을 가지고 온라인상에서 유지관리가 되고 있습니다.  만약에 jQuery 의 더욱더 최근 버젼을 받고싶으면, nightly builds 을 이용하십시요.
  • 아래와 같은 양식으로 연결하시면 jQuery의 다른버젼을 이용할 수 있습니다 :
  • jQuery UI 코드는 아래의 SVN으로 분리되어 있습니다 :
svn co http://jquery-ui.googlecode.com/svn/tags
 

Build 요구사항

jQuery 아래의 컴포넌트가 설치되어 있어야 빌드가 가능합니다 :

  • A build system (either make or ant works):
    • make: Available on most Unix-based system (Unix, BSD, OSX, Cygwin)
    • ant: Available on any platform with JDK and ANT installed
  • java: A copy of Java, version 1.4.0 or later

Build 과정

make or ant 를 이용해서 빌드를 합니다.처음에 jQuery 디렉토리를 이동하면 6개의 디렉토리가 있습니다.  (jquery, plugins, qunit, themes, tools, ui).

make 를 이용해서 JQuery  만들기:

  • make 를 이용해서 jQuery 만들기 :  make
    • jquery.js, jquery.pack.js, and jquery.lite.js 가 대상 디렉토리에 만들어 집니다.
    • cat.xml and index.xml 가 docs 디렉토리에 만들어 집니다.
    • test 디렉토리안에 tests 가 구축됩니다.
  • To just build docs: make docs
  • To just build packed jQuery: make pack
  • To just build tests: make test

ant 를 이용해서 jQuery 만들기:

  • To create jQuery: ant
    • jquery.js, jquery.pack.js, and jquery.lite.js 가 대상 디렉토리에 만들어 집니다.
    • cat.xml and index.xml 가 docs 디렉토리에 만들어 집니다.
    • test 디렉토리안에 tests 가 구축됩니다.
  • To just build docs: ant docs
  • To just build packed jQuery: ant pack
  • To just build tests: ant test
 
Posted by 바람이불면
,