메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

IT/모바일

고급 자바스크립트 활용 II

한빛미디어

|

2007-09-17

|

by HANBIT

14,786

제공: 한빛 네트워크
저자: Howard Feldman
역자: 이대엽
원문: Advanced JavaScript II

바로 전 기사에서는 두 가지 형태의 자바스크립트 위젯과 떠다니는 텍스트, 팝업 메뉴를 완전한 소스를 보여주면서 소개하였다. 이 기사에서는 또 다른 유용한 자바스크립트 위젯을 계속해서 소개해볼 텐데, 실제로 위젯이 어떻게 동작하는 지에 대해 집중적으로 살펴봄으로써 여러분이 그것들을 필요한 대로 손쉽게 수정할 수 있게 할 것이다. 이 기사에서 사용된 자바스크립트는 수정할 필요 없이 현재 사용되고 있는 주요 브라우저에서 모두 동작해야 한다. 별 어려움 없이 말이다…

div 태그를 이용한 이미지 토글

종종 여러분은 이미지 같은 무언가를 웹 페이지에 잔뜩 집어넣고 싶을 때가 있을 수도 있는데, 그것들을 모두 집어넣기엔 웹 페이지의 공간을 너무 많이 차지한다. 그러면 이미지 하나만 집어넣고 사용자가 스위치를 이용해서 다른 이미지로 교체하도록 하면 어떨까? 아마 이렇게 작동할 것이다:

div_toggle.html

이렇게 하는 것은 실제로 매우 간단하다. 한 가지 알아둘 것은 매번 이미지를 전환할 때마다 브라우저는 서버와 교신하지 않는다는 것이다. 하지만 이미지는 즉시 전환된다. 트릭이 무엇이냐고? 바로 이미지를 모두 HTML에 집어넣긴 하지만 한번에 하나씩만 보여주는 것이다! 이는 div 태그와 스타일을 이용해서 손쉽게 완성할 수 있다. 이 기법을 이용하면 인상적인 효과를 꽤 많이 만들어 낼 수 있으며, 이어지는 예제에서 볼 수 있을 것이다. 하지만 처음에는 지금 보여지고 있는 예제가 실제로 어떻게 작동하는 지에 대해서만 생각해 보기로 하자. 단 하나의 자바스크립트 함수만 사용하였다:
function ShowImage(page, tag)
{
    var i = 1;
    var el;
    while (el = document.getElementById(tag + i)) {
        if (i == page)
            el.style.display = "block";
        else
            el.style.display = "none";
        i++;
    }
}
실제 이미지들은 HTML상에 나타나야 할 위치에 놓여져 있는데, 각 이미지들은 다음과 같이 해당 div 태그에 들어있다:
위 테이블 구조는 단순히 레이아웃에 맞춰져 있는데, 기사의 논의 목적상 그런 것은 무시할 수 있다. 중요한 부분은 테이블의 첫 번째 셀 안에 들어있는 세 개의 div 태그들이다. 다른 div 태그들은 display가 none으로 설정되어 있는데 반해 첫 번째 div 태그는 display가 block으로 설정되어 있다. 비록 이전에 이미지를 서버로부터 전달받아 로컬에 저장하여 웹 페이지의 나머지 부분에 있더라도 display가 none으로 설정되어 있는 것들은 뷰에서 감춰져 브라우저 창에 그려지지 않는다. 따라서 처음에는 pic1.jpg만 보여지고 다른 두 개의 이미지는 볼 수 없다.

그런 다음 선택상자(selector box)에 onchange 이벤트가 발생할 때 자바스크립트 함수를 호출하도록 만들어 놓는다. 이렇게 하면 사용자가 선택상자에서 새로운 것을 선택 할 때 이벤트가 발생한다. 자바스크립트에는 두 개의 인자를 전달하는데, 각각 선택상자의 노드 자체에 대한 레퍼런스와 이미지를 담고 있는 div 태그의 id이다(id는 image1, image2, image3으로 모두 image로 시작한다는 것을 염두에 둔다).

함수는 보여줄 이미지를 의미하는 최근에 선택된 값을 가지고 실행된다. parseInt를 이용하여 선택된 값이 문자열이 아니라 숫자로 저장되도록 하였다. 다음으로는 첫 번째 div 태그에 대한 핸들을 가져오는데, 위 경우 image1이라는 id를 가진 것을 가져오게 된다. 만약 현재 이미지가 보여질 이미지이면 display 스타일을 block으로 지정하고 나머지 것들은 none으로 지정한다. 그리고 나서 더 이상 태그를 찾을 수 없을 때까지 다음 태그들을 처리한다.

그러므로 드롭 다운 박스에 새로운 항목들이 선택될 때마다 해당 div 블록이 보여지며 다른 것들은 모두 감춰진다. 이미지들은 모두 웹 페이지상의 동일한 물리적 공간을 공유하고 있는데, 왜냐하면 HTML내에서 서로서로 바로 옆에 위치해 있기 때문이다. 하지만 물론 꼭 이렇게 해야 하는 것은 아니므로 이미지들을 페이지의 서로 다른 영역에 뿌려놓고 원한다면 선택하는 것에 따라 다양한 위치에 그림을 나타나게 할 수도 있었다. 이와 비슷하게 이미지에도 어떠한 제약사항이 가해지는 것도 아니라서, 죄다 div 태그 사이에 집어넣고 마우스 클릭 한번으로 감추고 보이게 할 수도 있다. 이는 여러분이 일반적으로 집어넣는 것 보다 훨씬 더 많은 정보를 웹 페이지에 집어넣을 수 있도록 해주며 사용자는 아무런 스크롤도 할 필요가 없다.

탭 : div 좀 더 갖고 놀기

div 태그를 이용하는 다른 독창적인 예제를 통해 계속 진행해 보자. 종종 정보가 담겨있는 여러 개의 "탭(tab)"이 포함된 웹 페이지를 만들어 보고 싶을 때가 있다. 마치 요즘 사용되는 대부분의 웹 브라우저에서 제공하는 탭 브라우징 기능이 작동하는 것 마냥 탭을 클릭하면 탭에 들어있는 정보를 보여주고 다른 부분들은 감춰진다. 하지만 일반적으로 이처럼 HTML상의 탭을 클릭하면 페이지를 다시 불러오기 때문에 확실히 인터페이스의 자연스러움이 흐트러지게 된다. 정보가 즉각적으로 나타날 때 좀 더 멋있게 할 수는 없을까? 이전 예제에서 배웠던 매우 사소한 트릭을 이용하면 그렇게 할 수 있다. 한번 해보자:

tab_source.html

놀랄 것도 없이 이 예제는 이전 예제에서 사용했던 것과 정확히 동일한 자바스크립트 함수를 사용하고 있고 있는데, 전혀 다른 효과를 보여주고 있다. 나머지 부분은 몇 가지 단순한 CSS 규칙만으로 이루어진다. 이제 이 예제의 HTML을 살펴보기로 하자.
  • Summary
  • Details
  • Known Issues

Introducing the new, improved multi-widget. It slices, it dices, it even does your taxes! Order yours today! Call now: 555-WIDG

마치 이전 예제에서 각각의 이미지 하나당 하나의 div를 가졌던 것처럼3개의 div 섹션(각 탭 당 하나씩)을 가지고 있음을 알아둔다. 그리고 이번에도 첫 번째 블록에만 display:block으로 지정하고 나머지 것들은 display:none으로 지정하여 처음에는 오직 첫 번째 블록만 보이도록 한다. 이러한 각 섹션들은 세 개의 탭을 그림으로써 시작하는데, 선택된 블록만 다른 것과 블록과 다른 색상을 띤다. 그렇게 하여 실제로는 각 탭을 선택할 때마다 세 개의 탭을 모두 몇 번이고 다시 그리게 되는 셈이다. 탭에 들어가는 내용은 임의의 HTML이 될 수 있다. 기억해둘 것은 내용은 오직 한번만 보여지고, 실제 탭의 HTML만 수회에 걸쳐 반복되기 때문에 "낭비되는(wasted)" 공간을 최소화할 수 있는 것이다.

각 항목에 onclick 이벤트가 발생하면 showImage 자바스크립트 함수가 호출된다는 것을 알아둔다. 첫 번째 예제에서 살펴본 것과 같이 showImage 함수는 인자로 전달된 하나만 제외하고 나머지 모든 div 섹션들을 숨긴다. 이와 같이 여기에서는 이 함수를 여러분이 클릭한 탭만을 보여주고 다른 나머지 것들은 감추는데 사용한다. 탭을 적절하게 그리는 데에는 실질적으로 CSS나 스타일을 사용하며 CSS에는 tab과 tab_selected라는 이름의 두 클래스를 정의하였다. 전자는 특별한데가 없는 전체 탭에 적용되는 것이고, 후자는 현재 선택된 탭에만 적용되는 것이다. CSS의 내용은 다음과 같다:
ul.tab {
    margin: 0;
    padding: 3px 0;
    border-bottom: 1px solid #778;
    font-weight: bold;
}

ul.tab li {
    display: inline;
    padding: 3px 0.5em;
    margin-left: 3px;
    border-top: 1px solid #778;
    border-left: 1px solid #778;
    border-right: 1px solid #778;
    border-bottom: none;
    background: top repeat-x #89aac7;
    white-space: nowrap;
    color: white;
    cursor:pointer;
}

ul.tab li.tab_selected {
    background: #fff;
    border-bottom: 1px solid #fff;
    color: black;
}
첫 번째 섹션은 ul 태그와 전체 탭 바에 적용된다. 첫 번째 섹션은 margin과 padding을 지정하여 무조건 왼쪽위로 지정하고 border가 탭 바의 바닥에 그려지게 한다. 적당히 줄을 맞추기 위해 padding이 필요하며, 탭 바의 텍스트는 모두 진하게 표시하였다.

다음 섹션은 탭 바에 들어있는 모든 li 태그에 적용된다. 아마 display:inline이 가장 중요한 속성일텐데, 목록을 수직이 아닌 수평으로 만들어 주기 때문이다. 다시 한번 padding과 margin을 이용하여 탭을 일렬로 세우고 탭 사이사이의 여백을 맞춘다. border 속성은 상단과 탭 좌우를 그린다(바닥은 ul 태그로 그려짐을 떠올려본다). 마지막으로 배경 및 전경색상을 지정하고 텍스트 줄바꿈은 비활성화 하였다.

마지막 섹션은 현재 선택된 탭에만 적용되는데, 두 번째 섹션에 정의되어 있는 모든 설정을 재정의한다. 바뀐 것은 탭의 배경색상과 전경색상이며 ul 태그의 검정색 바닥 경계선을 흰색 바닥 경계선으로 그려줄 뿐만 아니라 선택된 탭을 눈에 띄도록 해준다. 이는 선택된 탭이 다른 탭 앞으로 튀어 나온 것처럼 착각하게 만든다.

이 예제에서 모든 탭의 내용은 모두 페이지 안으로 불러들여져 저장되므로 탭을 클릭하면 거의 즉각적으로 새로운 정보가 만들어지며 페이지를 다시 불러오지 않기 때문에 주의가 분산되지도 않는다. 매우 간단한 자바스크립트 함수와 CSS를 조금 사용하여 실로 매우 인상적인 효과를 거둘 수 있었다.

훨씬 고급스러운 div 트릭

앞에서 배웠던 트릭을 이용하는 유용한 애플리케이션의 마지막 예제로서 많은 양의 내용이나 목록을 요약하여 사용자가 관심있는 목록만을 열어볼 수 있도록 하는데 사용할 수 있는 다음의 예제를 만들어 보기로 하자:

advanced_div.html

아래는 위 예제의 소스이다:
Click to Expand Choice of four widget colors
이제 이 예제가 어떻게 작동하는지 꽤 명확하게 알 수 있어야 한다. 이번에도 위에서는 두 개의 div 블록을 포함하고 있는데, 하나는 접혀 있는 내용에 펼침 버튼이 있는 것이고, 다른 하나는 완전히 펼쳐진 내용에 닫기 버튼이 있는 것이다. 처음에는 닫힌 버전(display:block)만을 보여주고 이미지의 onclick 콜백을 이용하여 div 블록이 바뀌는 것을 감지한다. 블록에는 colors1과 colors2라는 id가 주어지는데, 그렇게 하여 앞서 작성했던 ShowImage 자바스크립트 함수로 손쉽게 전환할 수 있다.

드래그 앤 드롭과 맞바꾸기(swap)

이제 div 태그에 대해 멀미날 정도로 조사해 보았으므로 이번에는 조금 다른 것에 관해 알아보기로 하자. 이 예제에서는 마우스로 텍스트(혹은 이미지)를 드래그 앤 드롭할 수 있는 메소드를 보여줄 것이다. 이러한 메소드는 자바스크립트 게임이나 좀 더 중요한 목적, 예를 들면 여러분이 한 페이지에 들어있는 이미지의 순서를 바꾸거나 할 때 사용할 수 있다. 다음 예제에서는 서로 위에 포개져 있는 세 개의 이름을 드래그 앤 드롭하여 이름의 위치를 바꿔보도록 하겠다. 여러분이 John과 Jane은 문제없이 위치를 바꿀 수 있겠지만, Bill은 다른 것과 서로 위치를 바꿀 수 없을 것이다. 왜냐하면 Bill은 항상 말썽만을 일으키는 녀석이기 때문이다.

draggable.html

이 예제는 지금껏 보여주었던 것보다는 더 많은 양의 코드를 필요로 하긴 하지만 상당히 직관적이기도 하다. 다른 예제와는 달리 이번 예제는 전역 마우스 이벤트를 이용한다. 구체적으로 말하자면 이 예제는 트리거되는 세 개의 콜백 함수(마우스가 눌렸을 때, 마우스가 이동할 때, 마우스 버튼을 놓았을 때)에 의존한다. 이러한 종류의 전역 이벤트를 사용하는 것의 단점은 만약 여러분이 한꺼번에 여러 가지를 이어서 할 경우 상당히 곤란한 경우를 겪을 수도 있다는 것이다. 그러므로 여러분은 이러한 전역 이벤트를 사용하는 것을 최소화해야 하며 페이지당 기껏해야 하나 혹은 두 개만을 갖도록 해야 한다. 특히 이러한 예제의 경우 전역 이벤트는 상당히 필수적이다. 한 문단씩 살펴보기로 하자.
// 콜백을 지정
document.onmousedown = mousedown;
document.onmousemove = movemouse;
document.onmouseup   = mouseup;
var lastobj; // 마지막으로 마우스를 올려놓았던 드래그 가능한 객체
var isdrag; // 객체를 드래그 하고 있을 경우 True
다음 코드에서는 세 개의 콜백 함수들을 초기화한다. mousedown과 mousemove는 각각 사용자가 마우스 버튼을 클릭할 때와 이동할 때 호출될 것이며, mouseup은 왼쪽 마우스 버튼을 놓았을 때 트리거될 것이다. 또한 여기에서는 두 개의 전역 변수가 필요한데, 첫 번째 것은 가장 최근에 마우스를 올려놓았던 객체를 추적하기 위한 것이며, 두 번째는 현재 객체를 드래그하고 있을 경우 true를 값으로 가지는 플래그 변수이다.
// 다음 코드는 여러분이 텍스트를 클릭했을 때 
// 드래그할 수 있는 텍스트를 강조하지 않도록 한다.
// 테이블은 drag_drop이라는 id를 가진 모든 드래그 
// 가능한 텍스트를 포함한다.

window.onload = function()
{
    var e = document.getElementById("drag_drop");
    if (e) {
        if (moz)
            e.onmousedown = function () { return false; } // mozilla
        else
            e.onselectstart = function () { return false; } // ie
    }
}
페이지가 로딩되자마자 위 함수가 실행되는데, 드래그할 수 있는 객체에 대해 클릭할 경우 보통 우리가 텍스트를 클릭했을 때 일어나는 일처럼 텍스트를 강조하지 않도록 한다. 이는 일반적으로 텍스트를 강조하도록 요청되는 함수를 빈 함수로 재정의하여 강조하지 않도록 만들 수 있다.
// 객체의 id에 근거하여 두 객체간에 맞바꾸기가 허용되는지를 확인한다.
// 각각의 드래그할 수 있는 항목들의 짝에 대해 맞바꾸기를 허용하거나 금지하도록 하는
// 조건을 여러분이 원하는 대로 변경한다.
function allowswap(a,b)
{
    if (a.id == "dragdropa" && b.id == "dragdropb" || a.id == "dragdropb" && b.id 
    == "dragdropa")
        return true;
    return false;
}

// 객체가 드래그할 수 있는 것이면 true를 반환 - 필요에 맞게 변경하도록 한다.
function isdraggable(obj)
{
    if (obj.id.substr(0,8) == "dragdrop")
        return true;
    return false;
}
두 개의 유틸리티 함수도 필요한데, 주어진 두 객체에 대하여 allowswap함수는 두 객체가 서로 맞바꿀 수 있을 경우 true를 반환하며, 그렇지 않을 경우 false를 반환한다. 확실히 여기에 들어있는 조금 복잡한 로직을 이용하여 여러분은 꽤 재미있는 일을 할 수 있다. isdraggable함수는 주어진 객체가 드래그 가능할 경우true를 반환한다. 이 예제의 취지상 객체가 드래그할 수 있는지를 단순히 객체의 id가 dragdrop으로 시작하는지 근거하여 판단하고 있는데, 물론 여러분은 그렇지 하지 않을 수도 있으며, 여러분이 원하는 대로 변경할 수도 있다. 가령 특정 class로 드래그할 수 있음을 나타낼 수도 있는데, 이 예제의 취지상 위에서 했던 것만으로도 충분하다.
// 마우스 버튼이 놓였을 경우의 콜백. 이 함수는 항목이 드래그 할 수 있는지를 확인하고,
// 드래그 할 수 있으면 프로세스를 초기화한다.
function mousedown(e) 
{
    var obj = moz ? e.target : event.srcElement;
    // DOM 트리를 추적하여 클릭한 항목이 드래그 할 수 있는지를 확인한다.
    // 이렇게 하면 예를 들면 TD를 감싸고 있는 TR이 드래그 할 수 있는 객체일 경우에도
    // 여러분이 클릭할 수 있다.
    while (obj.tagName != "HTML" && obj.tagName != "BODY" && !isdraggable(obj)) {
        obj = moz ? obj.parentNode : obj.parentElement;
    }
    if (isdraggable(obj)) {
    // 만약 드래그 할 수 있으면 전역 플래그 변수를 설정하여 이 객체를 추적하도록 하고,
    // 또한 객체의 포인터를 전역 변수에 저장한다(dragobj).
        isdrag = true;
        dragobj = obj;

        // origx, origy는 드래그되는 객체의 원래 시작 위치임.
        origx = dragobj.style.left;
        origy = dragobj.style.top;

        // x,y는 window내의 절대 좌표
        x = moz ? e.clientX : event.clientX;
        y = moz ? e.clientY : event.clientY;

        // offsetX, offsetY는 여러분이 클릭한 객체가 정확히 어디에 있는지에 의존한다.
        // 따라서 여러분이 객체의 중앙을 클릭할 경우, 객체는 그 위치에서
        // 마우스에 "덧붙여지는데(attached)", 예를 들면 좌상단 모서리에 덧붙여지지는 않는다.
        offsetX = moz ? e.layerX + 2: event.x + 2;
        offsetY = moz ? e.layerY + 2: event.y + 2;
    }
}
마우스 버튼이 눌렸을 때 호출되는 mousedown 함수가 코드의 첫 번째 주요 부분이다. 무언가가 클릭되면 그것이 드래그 할 수 있는지를 확인한다. 만약 드래그 할 수 없다면 그것의 부모 노드 등이 드래그 할 수 있는지를 확인한다. 이렇게 하는 이유는 여러분이 무언가를 클릭했을 때 브라우저가 일반적으로 DOM 트리에서 가장 낮고 깊이가 깊은 항목의 핸들을 반환할 것이기 때문이다. 그렇기 때문에 예를 들어p 태그를 감싸고 있는 span 태그가 드래그 할 수 있는 것으로 표시되어 있을 경우, 그러한 태그 사이의 텍스트를 클릭했을 때 여러분은 드래그 할 수 있는 것으로 표시되어 있지는 않은 p 태그의 핸들을 가져오게 된다. 그러나 부모 노드를 확인하여 실제로 그 노드가 드래그 할 수 있는 항목의 자식인지를 확인하여 실제로는 드래그 할 수 있는지 여부를 알아낼 수 있다.

무언가 드래그 할 수 있는 것을 클릭했다고 가정하면 전역 플래그 변수를 true로 설정하고 그 객체를 dragobj에 저장한다. 또한 몇 가지 좌표도 저장하는데, 이러한 좌표에는 dragobj의 원래 위치, 클릭한 마우스의 상대 위치 및 클릭한 절대 위치가 포함된다.
// 마우스가 이동할 때의 콜백. 이 함수는 여러분이 맞바꿀 수 있거나 맞바꿀 수 없는 객체위에서
// 마우스를 움직일 때 커서를 변경할 것이다.
function movemouse(e)
{
    // 현재 객체를 드래그하고 있는지를 확인
    if (isdrag) {
        // 만약 현재 객체를 드래그하고 있다면 드래그되는 객체의 위치를 마우스가 처음 클릭한 이후로
        // 상대적으로 마우스가 움직인만큼 지정한다.
        dragobj.style.left = moz ? origx + e.clientX - x 
              + offsetX + "px" : origx + event.clientX - x + offsetX;
        dragobj.style.top  = moz ? origy + e.clientY - y + offsetY 
              + "px" : origy + event.clientY - y + offsetY;
        var obj = moz ? e.target : event.srcElement;
    
        // 지금 맞바꿀 수 없는 엘리먼트상에 있을 경우 커서 스타일을 
        // 맞바꿈이 금지되어 있음을 보여주는 것으로 변경한다.
        if (obj != dragobj && isdraggable(obj) && !allowswap(dragobj,obj)) {
            obj.style.cursor = "wait";
            // 객체에 대한 핸들을 전역변수에 저장하여 커서를 나중에 초기화할 수 있도록 한다.
            lastobj = obj;
        }
        else if (lastobj)  // 드래그할 수 없는 객체의 이동이 끝나는대로 커서를 초기화한다.
            lastobj.style.cursor = "pointer";
        return false;
    }
    else {
        // 간혹 드롭 아이콘으로 갇힐 수 있는데, 그러므로 드래그하고 있지는 않지만 드래그할 수 있는
        // 항목을 전달할 때 안전하게 하기 위해 커서를 복원한다.
        var obj = moz ? e.target : event.srcElement;
        if (isdraggable(obj))
            obj.style.cursor = "pointer";
    }
}
마우스가 이동할 때마다 먼저 무언가가 드래그되고 있는지를 확인한다. 무언가가 드래그되고 있다면 그 객체가 어디로 드래그 되어야 하는지를 계산하여(아무튼 객체가 스스로 알아서 마우스를 따라다니는 것은 아니다!) 그에 맞게 객체를 이동시킨다. 또한 다른 드래그 할 수 있는 객체 위에 마우스를 올려놓았는지도 확인한다. 그럴 경우 allowswap 함수를 호출하여 맞바꾸기를 할 수 있는지를 결정한다. 맞바꾸기를 할 수 없다면 커서는 "대기(wait)" 모양으로 바꾼다(컴퓨터마다 모양이 다양하긴 하지만 표준 대기 커서이다). 객체를 서로 맞바꿀 수 있거나 드래그 할 수 있는 객체 위에 마우스를 올려놓지 않았다면 커서를 그대로 두고, 이전에 모양을 바꾸었다면 다시 모양을 복원한다.

한 가지 추가적으로 알아두어야 할 것은 드래그할 수 있는 객체 위에 마우스를 올려 놓더라도 현재 아무것도 드래그하고 있지 않으면 그대로 커서를 원래대로 복원한다는 것이다. 왜냐하면 사용자가 마우스를 얼마나 빨리 이동하고 버튼을 놓는 등의 동작을 하느냐에 따라 간혹 커서가 "대기" 상태에 갇힐 수 있기 때문이다. 그렇기 때문에 위에서 언급한 커서를 복원하는 로직은 failproof하지는 않다.
// 마우스 버튼을 놓았을 때의 콜백이며 맞바꾸기가 일어나야 하는지를 확인하며
// 맞바꾸기가 일어나지 말아야할 경우 드래그되는 개체를 원래 시작위치로 되돌려 보낸다.

function mouseup(e)
{
    if (isdrag) {  // 무언가가 드래그되고 있다면

        // 마우스 버튼이 놓여진 객체를 획득한다.
        var obj = moz ? e.target : event.srcElement;

        // 맞바꿀 수 있는 객체에 대해 마우스가 놓여졌는지를 확인한다.
        if (obj != dragobj && isdraggable(obj) && allowswap(dragobj, obj)) {

            // 맞바꾸기가 허용된 경우, 색상, 툴팁, 드래그 되는 객체의 내용을
            // 마우스가 놓여진 객체의 것들과 맞바꾼다.
            var htm = obj.innerHTML;
            obj.innerHTML = dragobj.innerHTML;
            dragobj.innerHTML = htm;

            var col = obj.style.color;
            obj.style.color = dragobj.style.color;
            dragobj.style.color = col;

            var titl = obj.title;
            obj.title = dragobj.title;
            dragobj.title = titl;

            // 현재 드래그하고 있는 객체(dragobj)의 위치를 다른 객체(obj)의 위치로 지정하고
            // obj를 dragobj가 드래그되기 전에 dragobj의 원래 위치(origx, origy)로 이동한다.
            dragobj.style.left = obj.style.left;
            dragobj.style.top = obj.style.top;
            obj.style.left = origx;
            obj.style.top = origy;
        }
        else {
            // 맞바꾸기가 일어나지 않으므로 드래그되는 객체를 원래의 시작 지점으로 돌려보낸다.
            dragobj.style.left = origx;
            dragobj.style.top = origy;
        }

        // 커서가 movemouse에서 바뀌었을 경우 커서를 포인터로 복원한다.
        if (lastobj) {
            lastobj.style.cursor = "pointer";
        }
    }
    isdrag = false;  // 현재 아무것도 드래그되는 것이 없음
}
mouseup이벤트는 객체를 드래그하는 동안 마우스가 놓여졌는지에 관해 가장 상세한 조사를 벌인다. 드래그할 수 있는 객체를 놓을 경우 allowswap 함수를 이용하여 맞바꾸기가 가능한지를 확인한다. 바꾸기가 가능하다면 두 객체의 텍스트 내용, 색상, 그리고 툴팁(title 속성)을 서로 맞바꾼다. 이 시점에서 여러분은 여러분 목적에 맞게 단순히 객체의 모든 속성들을 맞바꾸길 선호할지도 모르겠다. 그리고 나서는 드래그되고 있는 객체를 마우스를 놓은 객체가 위치한 곳까지 이동시킨 후, 이번에는 마우스를 놓은 객체를 드래그되는 객체의 원래 시작지점으로 이동시킨다. 이리하여 맞바꾸기가 완료된다. 반면 맞바꾸기가 금지되어 있으면 단순히 드래그 되는 객체를 원래의 시작지점으로 돌려 보낸다. 두 경우 모두 마우스 커서가 movemouse 상태의 "대기" 커서로 변했을 경우 마우스 커서를 복원하고 더 이상 객체를 드래그하고 있지 않다는 것을 나타내기 위해 isdrag 플래그 변수를 초기화한다.

마지막으로 객체를 인스턴스화하는 것은 매우 쉽다. 드래그 할 수 있는 객체의id가 dragdrop으로 시작한다는 것만 기억하면 된다:
John
Jane
Bill
편의상 테이블에 객체가 위치해 있을 경우 각기 다른 색상을 띠도록 하였는데, 중요한 점은 드래그할 수 있는 항목의 id가 allowswap에서도 참조되며 style 속성이 position:relative라는 사실이다. 이 공식은 자바스크립트에서 객체들의 위치를 계산하여 상대적인 위치를 추정하는데 사용되었다. 또한 감싸고 있는 테이블의 id는 drag_drop인데, window.onload 함수의 맨 위에서 참조되고 있다는 것도 알아두도록 한다.

요약

대체로 앞서의 예제들은 웹 페이지의 일부를 나누거나 선택적으로 보이게끔 하는 데 있어 다소 창의적인 방식으로 div 태그가 사용될 수 있음을 보여주고 있다. 드래그 앤 드롭 예제는 요즘 볼 수 있는 대부부의 고급스런 웹 페이지에서 볼 수 있는 상당히 강력한 개념을 정말로 간단하게 보여주는 예제의 하나일 뿐이다. 거기에 조금만 더 작업을 하면 예를 들어 완전히 커스터마이즈가 가능한 홈 페이지를 만들어 여러분이 각종 뉴스 피드나 이미지, 그리고 핵심 컨텐츠들을 드래그 하고 서로 위치를 바꿀 수 있도록 할 수도 있다. 여러분의 상상력만이 유일한 제약사항일 뿐이다!


저자 Howard Feldman은 퀘벡주의 몬트리올에 위치한 Chemical Computing Group의 연구원이다.
TAG :
댓글 입력
자료실