티스토리 뷰

hacking/web

dojo by example(4) - 유틸리티 함수

Ho Eyo He Hum! iolo 2008.07.29 00:43
할 수 있는데 까지 해보자.

DOM 노드 위치/좌표 관련 함수들
CSS만으로 모든 레이아웃을 정확하게 계산하기란 쉽지 않다. 디자이너의 현란한 디자인이 IE의 더블마진 버그와 만나는 순간... 때문에 레이아웃 잡는게 여간 골치아픈게 아니다. 그래서 이런게 필요하다:
  • dojo.marginBox(domNode) : 지정한 DOM 노드의 margin box를 얻는다.
  • dojo.marginBox(domNode, {l:가로좌표, t:세로좌표, w:너비, h:높이}) : 지정한 DOM 노드의 위치/크기를 margin box로 설정한다. 위치는 부모 노드의 위치에 대한 상대좌표다(즉, CSS의 position:absolute 다). margin/padding/border는 바뀌지 않지만, content box의 크기는 바뀐다. 기본 단위는 픽셀(px)이다. 각 속성은 생략할 수 있다.
  • dojo.contentBox(domNode) : 지정한 DOM 노드의 content box를 얻는다.
  • dojo.contentBox(domNode, {l:가로좌표, t:세로좌표, w:너비, h:높이}) : 지정한 DOM 노드의 content box의 위치/크기를 설정한다. 위치는 부모 노드의 위치에 대한 상대좌표다(즉, CSS의 position:absolute 다) margin/padding/border는 바뀌지 않지만, margin box의 크기는 바뀐다. 기본 단위는 픽셀(px)이다. 각 속성은 생략할 수 있다.
사용자 삽입 이미지
위의 그림은 CSS의 박스모델을 설명하는 것인데, dojo의 contentBox는 위의 그림에서 맨 안쪽의 content를 둘러싼 사각형을, marginBox는 맨 바깥쪽의 margin까지 포함한 사각형을 의미한다. 이 결과는 IE이건 아니건, Quirks Mode이건 아니건 동일하다.
웬만하면 CSS로 처리하는 것이 바람직하지만, iframe이나 textarea같은 꼴통들에겐 dojo.contentBox/marginBox()가 도움이된다. 간단한 예를 들어보면(저번에 예제를 하나도 안만들어서 이번엔 좀 길게 만들어 봤다):
<html>
<head>
<script type="text/javascript" src="http://o.aolcdn.com/dojo/1.1.1/dojo/dojo.xd.js"></script>
<style type="text/css">
body { margin:0; padding:0; height:100%; overflow:hidden; }
#wrapper { width:100%; height:100%; }
#header { height:20px; background:#9cf; }
#content { width:100%; position:absolute; top:20px; bottom:0; background:#ccc; }
#frame { width:100%; height:100%; overflow:auto; }
</style>
<script type="text/javascript">
if (dojo.isIE) {
  var onResize = function() {
    var box1 = dojo.contentBox('wrapper');
    box1.t = 20;
    box1.h -= 20;
    dojo.marginBox('content', box1);
  };
  dojo.connect(dojo.global, 'resize', onResize);
  dojo.addOnLoad(onResize);
}
</script>
</head>
<body>
<div id="wrapper">
  <div id="header">Hello,World!</div>
  <div id="content"><iframe id="frame" src="http://dojotoolkit.org/" frameborder="no"></iframe></div>
</div>
</body>
</html>

이 예제의 목적은 스크롤바 없이 화면에 꽉 채운 페이지를 만드는 것이다. IE에선 부모 노드의 크기가 %로 지정되면 right/bottom 속성이 동작하지 않기때문에 곤란하다. IE의 CSS expression을 써도 되겠지만, 개인적으로는 이 방법을 선호한다. CSS만으로 어떻게 할 수 있을 것 같긴한데... 내공 부족 -.-;;;(표준 CSS만으로 할 수 있는 좋은 방법이 있으면 알려주시면 콩다방 커피 한잔 대접합니다~). 예제를 위한 예제이다 보니 아직 설명한 것들이 잔뜩 있는데 핵심은 중간 쯤에 있는 자바스크립트 코드다. 중간에 있는 if (dojo.isIE) { ... } 스크립트(주황색 배경)를 지우고 IE에서 실행시켜보시라. 나중에 dijit layout widget을 사용하면 이것보다 훨씬 복잡한 작업을 한 방에 해치울 수 있다!

DOM 편의 함수
앞에서 알아본 dojo.attr()/dojo.style()dojo.*Class() 외에도 잡다한 편의함수들이 많다. 이 함수들의 완전한 목록은 dojo API Reference에서 찾아보시고~ 여기서는 맛보기로 생각나는 것 몇 개만 알아보자:
  • dojo.place(domNode, refDomNode, position) : domNode를 refDomNode를 기준으로 위치/순서를 변경한다. position은 인덱스(숫자) 또는 before/after/first/last 중의 하나다. position 인자에 따라 appendChild/insertBefore() 등의 DOM API를 적절히 호출한다. 처음엔 복잡해 보이겠지만, 익숙해지고 나면 DOM API가 얼마나 구린지(?), 그리고 dojo.place()가 얼마나 자연스러운지 알게 될 것이다.
  • dojo.isDescendant(domNode, ancestorDomNode) : domNode가 ancestorDomNode의 하위 노드인지 확인한다.
  • dojo._destroyElement(domNode) : 지정한 노드를 해제한다. IE에서는 이벤트 핸들러가 걸린 노드와 관련한 메모리가 새는 버그가 있어서 domNode.parentNode.removeChild(domNode) 또는 domNode.parentNode.innerHTML = '' 또는 domNode.ownerDocument.detachNode(domNode) 로는 충분하지 않다. domNode.parentNode.innerHTML'_'로 시작하는 private함수지만 public으로 해도 무방할 정도로 유용하다.
  • dojo.setSelectable(domNode, selectable) : domNode와 모든 자식노드들을 선택불가능하게(마우스로 긁을 수 없게) 만든다. 이걸 활용하면 블로그 본문 긁지 못하게 하는 것을 쉽게 할 수 있겠지만... 이런 짓 하지말자. 어차피 긁을려면 다 긁는다. 다만, 메뉴나 툴바 같은 녀석들을 이 함수를 사용해 긁지 못하게 하면 잡다한 오동작을 원천봉쇄할 수 있다.
  • dojo._getOpacity(domNode) : domNode의 투명도를 얻어온다. 0이면 완전 투명, 1이면 완전 불투명이다. 이 함수 없이 할려면 IE이냐 아니냐에 따라서 삽질을 좀 해야 한다.
  • dojo._setOpacity(domNode, opacity) : domNode의 투명도를 설정한다.
이 함수들을 직접 쓸 기회는 많지 않겠지만 알아두면 유용할 때가 금방 온다.

(중간에 dojo API Reference가 있다고 얘기했다. 아는 사람은 다 알겠지만... 이걸 지금까지 얘기안한 이유가 있다. 이거 보고 괜히 dojo를 오해하지 말기 바란다. 이렇게 느려터지게 만드는 것도 쉬운 일이 아니다. 굳이 API가 필요하다면 이것 보다는 dojo toolbox를 쓰길 권한다.)

사용자 삽입 이미지
유틸리티 함수는 일단 마무리~
다음에는 재미있는(?) 애니메이션/효과 관련 함수들을 간단히 알아보고,
이어서 이벤트 시스템, 클래스 시스템, 그리고 dijit... 갈 길이 멀구나...

댓글
댓글쓰기 폼