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를 가졌던 것처럼3개의 div 섹션(각 탭 당 하나씩)을 가지고 있음을 알아둔다. 그리고 이번에도 첫 번째 블록에만 display:block으로 지정하고 나머지 것들은 display:none으로 지정하여 처음에는 오직 첫 번째 블록만 보이도록 한다. 이러한 각 섹션들은 세 개의 탭을 그림으로써 시작하는데, 선택된 블록만 다른 것과 블록과 다른 색상을 띤다. 그렇게 하여 실제로는 각 탭을 선택할 때마다 세 개의 탭을 모두 몇 번이고 다시 그리게 되는 셈이다. 탭에 들어가는 내용은 임의의 HTML이 될 수 있다. 기억해둘 것은 내용은 오직 한번만 보여지고, 실제 탭의 HTML만 수회에 걸쳐 반복되기 때문에 "낭비되는(wasted)" 공간을 최소화할 수 있는 것이다.
- 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
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이 필요하며, 탭 바의 텍스트는 모두 진하게 표시하였다.
이제 이 예제가 어떻게 작동하는지 꽤 명확하게 알 수 있어야 한다. 이번에도 위에서는 두 개의 div 블록을 포함하고 있는데, 하나는 접혀 있는 내용에 펼침 버튼이 있는 것이고, 다른 하나는 완전히 펼쳐진 내용에 닫기 버튼이 있는 것이다. 처음에는 닫힌 버전(display:block)만을 보여주고 이미지의 onclick 콜백을 이용하여 div 블록이 바뀌는 것을 감지한다. 블록에는 colors1과 colors2라는 id가 주어지는데, 그렇게 하여 앞서 작성했던 ShowImage 자바스크립트 함수로 손쉽게 전환할 수 있다.
Choice of four widget colors
// 콜백을 지정 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 태그의 핸들을 가져오게 된다. 그러나 부모 노드를 확인하여 실제로 그 노드가 드래그 할 수 있는 항목의 자식인지를 확인하여 실제로는 드래그 할 수 있는지 여부를 알아낼 수 있다.
// 마우스가 이동할 때의 콜백. 이 함수는 여러분이 맞바꿀 수 있거나 맞바꿀 수 없는 객체위에서 // 마우스를 움직일 때 커서를 변경할 것이다. 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)" 모양으로 바꾼다(컴퓨터마다 모양이 다양하긴 하지만 표준 대기 커서이다). 객체를 서로 맞바꿀 수 있거나 드래그 할 수 있는 객체 위에 마우스를 올려놓지 않았다면 커서를 그대로 두고, 이전에 모양을 바꾸었다면 다시 모양을 복원한다.
// 마우스 버튼을 놓았을 때의 콜백이며 맞바꾸기가 일어나야 하는지를 확인하며 // 맞바꾸기가 일어나지 말아야할 경우 드래그되는 개체를 원래 시작위치로 되돌려 보낸다. 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 플래그 변수를 초기화한다.
John |
Jane |
Bill |
이전 글 : 왜 네트워크 디바이스 노드는 없을까?
다음 글 : 커널에서 CPU 정보 처리하기
최신 콘텐츠