발생일: 2012.02.09

문제:
이번에 모바일 프로젝트를 하나 맡게 됐다.

기획서를 검토하고 구조를 잡던 중에,
예전에 어떤 가이드에서 iOS에서는 스크립트 사이즈가 몇 kb 이상이면 캐시가 되지 않는다고 했던 게 기억났다.

꽤 오래 전이었던 걸로 기억하는데,..
아직도 유효한가?


해결책:
스티브 사우더스가 모바일 캐시 파일 사이즈에 대해 아주 잘 설명해놓은 포스트가 있다.
http://www.stevesouders.com/blog/2010/07/12/mobile-cache-file-sizes/ 

요약해보면,
한 세션 당, (여기서 세션은 한 페이지에서 다른 페이지로 이동하는 것을 의미한다)
스크립트 한 개의 파일 당 iOS는 4MB까지, 안드로이드는 2MB까지 캐시가 된다. 

물론 버전에 따라 약간씩 다르긴 하다.


또한, 폰을 잠궜다가 다시 들어갔을 때에도 캐시는 유효하다.
전원을 껐다 켰을 경우, iOS는 캐시가 모두 삭제된다.  

성능 팀에서 테스트 한 자료에 의하면,
스크립트 사이즈가 작을 경우(256kb 이하, iOS4.3) 전원을 껐다 켜도 캐시가 된다고 한다. 
스티브 사우더스의 실험 결과와는 차이가 있는 부분이다.


HTML 페이지의 경우, iOS3 이하에서는 25.6kb 이하가 될 때에만 캐시된다고 한다.
아마 내가 기억하고 있던 예전 사이즈가 HTML 사이즈였던 모양이다.
4.3 버전의 경우, 약간 늘어서 128kb 까지 캐시가 된다고 한다.


시간이 좀 된 자료지만, YUI 블로그의 포스트를 참고해봐도 좋겠다.
http://www.yuiblog.com/blog/2010/07/12/mobile-browser-cache-limits-revisited/ 
 

저작자 표시 비영리 변경 금지
Posted by ohgyun
발생일: 2012.01.19

문제:
며칠 전 크로미엄 버전을 18.0.1010.1 dev-m 버전으로 업데이트 한 이후로,
잘 작동하던 몇몇 익스텐션이 제대로 작동하지 않는다.

어느 부분에서 오류가 나나 찾아봤더니,
익스텐션에서 document.documentElement 를 찾지 못한다.

뭐가 문젤까?


해결책:
크롬 dev 버전이 18.0.1010.1로 업데이트 되면서 발생한 버그로 추정된다.

검색해보니 같은 문제로 2012.01.11에 버그 리포팅 된 것이 있다.
https://groups.google.com/a/chromium.org/group/chromium-bugs/browse_thread/thread/0e668df511f0b381 

재현을 위해서는,
1. 익스텐션에서 아래와 같이 content script의 실행 시점을 document_start로 설정하고,
  content_scripts: [
    {
      ... (생략) ...
      run_at: "document_start"
    }
  ]


2. 스크립트 내에서 document.documentElement 를 접근하면 undefined가 뜨는 것을 확인할 수 있다.


아직 버그가 해결되지 않은 상태라 일단은,
임시 해결을 위해 스크립트 실행 시점을 기본값인 document_idle 로 변경하면 된다.



저작자 표시 비영리 변경 금지
Posted by ohgyun
발생일: 2012.01.10

문제:
아이폰이나 아이패드와 같은 터치 디바이스에서는 PC와 다르게 hover(마우스 롤오버) 효과가 적용되지 않는다.
'마우스' 개념이 없기 때문이다. 
실제로 모바일 웹 페이지를 작성하는 경우, 마크업 단계부터 hover 효과를 고려하지 않는다.

하지만 기존 서비스를 모바일에서도 그대로 제공해야 하는 경우라면, 서비스에 적용된 여러 가지 hover 효과 때문에 사용자가 불편을 겪을 수 있다.
예를 들어, 마우스를 오버했을 때 가이드가 표시되는 버튼을 구현했다면,
터치 디바이스에서는 한 번 클릭 시 마우스 오버 효과가 발생하고, 다시 클릭했을 때 클릭 이벤트가 발생한다.
PC에서는 한 번 클릭으로 실행 가능했던 버튼이 터치 디바이스에서는 두 번을 클릭해야 한다.

진행하고 있는 서비스에서도 비슷한 문제가 발생했고,
터치 인터페이스에서는 hover 효과 없이 한 번 클릭으로 실행될 수 있게 수정이 필요했다.

간단하게 생각해보면, 각 케이스에서 마우스 오버 이벤트를 모두 제거하면 될 것 같은데,
각 모듈마다 분기문을 추가해 이벤트를 제거할 생각을 하니 이만큼 비효율적인 것도 없다.

뭔가 엘레강스한 처리 방법이 없을까~~~


해결책:

왜 두 번 클릭해야 하나?
먼저, hover 효과가 적용된 엘리먼트에서 두 번 클릭이 필요한 이유에 대해 자세히 알아보자.

모바일 사파리에서 터치를 시도하면 아래와 같은 이벤트가 순서대로 발생한다.

  touchstart - touchend - mouseover - mousemove - mousedown - mouseup - click

마우스가 존재하진 않지만, 내부적으로는 터치 이벤트 뿐만 아니라 마우스 이벤트도 발생하는 것을 볼 수 있다.
중요한 건, mouseover 시점에서 화면이 변경될 경우, 이벤트가 멈춘다는 것이다.
(이벤트 발생 프로세스의 자세한 내용은 Safari Developer Library의 Handling Events 챕터를 참고.)

위 문서에는 '화면이 변경(if the contents of page changes)'되는 것에 대한 명확한 정의는 없다.
테스트 해본 결과, '화면이 변경'된다는 것은 정확하게는 '레이아웃이 변경(reflow)'되는 것에 가까운 것 같다.
백그라운드가 변경된다거나, 레이아웃에 영향을 끼치지 않는 정도의 margin/padding이 변경되는 경우(repaint)에는 이벤트가 종료되지 않는다.

따라서, 두 번 클릭해야 실행되는 문제를 해결하기 위해서는,
터치 인터페이스에서는 mouseover 이벤트가 발생했을 때 화면 변경이 되지 않도록 해야 한다.


Case by case로?
처음엔 각 케이스 별로, 호버 효과를 위해 추가하는 스타일이나 클래스명을 공백으로 바꿀 생각을 했다.
몇몇 모듈을 테스트 했을 때 문제 없이 적용되었다.
하지만 모듈이 수백 개인 걸... 이건 아니다.


마우스 이벤트를 터치 인터페이스로 바꾸면 어떨까?
마우스 이벤트와 상응하는 이벤트를 터치 이벤트와 매칭시켜주면 어떨까?

  mouseover ---> touchstart
  mousemove ---> touchmove
  mousedown ---> touchend
  mouseup ---> ?  
  mouseout ---> ?


터치 이벤트와 정확하게 매칭되지도 않을 뿐더러, 몇몇 모듈에 테스트해본 결과 기대했던 대로 동작하지도 않았다.
이 방법은 패스~


터치 디바이스일 경우엔, mouse 이벤트를 모두 무시하면 어떨까?
현재 서비스에서는 모든 이벤트를 특정 라이브러리를 통해서 바인딩하고 있다.
이벤트를 바인딩하는 해당 메서드를 오버라이드해서,
터치 디바이스에서 "mouse"를 포함한 이벤트를 바인딩하려는 경우 모두 무시하면 어떨까?

오. 요고 먹힌다.
대부분의 문제가 해결됐다.
다만, click이 아닌 mousedown을 사용하는 몇몇 컴포넌트(drag/drop 같은)는 전혀 작동하질 않는다.

일단은 해결책 중의 하나가 될 수 있겠지만, 의도하지 않은 부분까지도 전혀 작동되지 않는 건 문제가 있다.
화이트 리스트 방식의 적용이 필요하다.


CSS로 hover 효과를 내는 건 어떻게?
마우스 이벤트로 hover를 주는 건은 마우스 이벤트를 제거하는 걸로 해결이 된다 치더라도,
CSS로 hover 효과를 주는 경우엔 제어가 되지 않는다. (CSS와 mouseover 구분하기)

마크업 담당자에 미디어 쿼리(media query)로 터치 디바이스일 경우엔 :hover 를 없애는 건 어떻겠냐고 문의해봤으나, 미디어 쿼리로는 브라우저 구분은 안된다고 한다.

스크립트를 사용해서 CSS 파일을 분기하면 처리할 수 있겠으나,..
이건 배보다 배꼽이 크다는 판단이다.

보통은 클릭 이벤트를 강제로 발생하도록 하는 방법으로 처리할 수 있다고 한다.


클릭 이벤트를 강제로 발생한다?
CSS로 hover가 적용된 경우라면,
mouseover 이벤트에서 이벤트를 중지하고 강제로 한 번 더 click 이벤트를 발생하도록 처리하는 방법이 있다. 
마찬가지로, 이벤트 바인딩 메서드를 오버라이드 해서 구현해봤다.

오. 요고도 먹힌다.
대부분이 문제 없이 잘 실행된다.
하지만, 역시 몇 가지 문제가 있다.

overflow: scroll 속성을 가지고 있는 엘리먼트 내에서 one-finger 스크롤 시, 예기치 않은 이벤트가 계속 발생한다. 
또한, 스크립트로 hover 효과가 적용된 경우라면, mouse 이벤트를 없애는 경우보다 비효율적이다.
터치 때마다 페이지 변경이 계속 발생하기 때문이다.

그리고 mouse 이벤트를 모두 제거했을 때와 마찬가지로 화이트 리스트 방식의 접근이 필요한다.


그렇다면?
최종적으로는, 아래와 같은 방법으로 해결할 수 있었다.

1. 특정 클래스 클래스를 가지고 있는 엘리먼트의 경우, 마우스 이벤트를 할당하지 않는다.
    - 스크립트로 hover 효과를 적용한 경우에 적합하다.
    - 이벤트를 바인딩하는 메서드를 오버라이드 한다.
    - ignore-mouse-event 클래스를 가진 경우, 마우스 이벤트를 할당하지 않는다.
    - mouseover 효과 제거가 필요한 엘리먼트에 해당 클래스를 추가한다.

2. 특정 클래스를 가지고 있는 엘리먼트의 경우, mouseover 이벤트 발생 시 이벤트를 멈추고 강제로 click 이벤트를 발생한다.
    - CSS로 hover 효과를 적용한 경우에 적합하다.
    - document에 mouseover 이벤트를 바인딩한다.
    - touch-force-click 클래스를 가지고 있는 경우, 이벤트를 멈추고 click 이벤트를 발생한다.
    - css로 hover가 적용된 엘리먼트에 해당 클래스를 추가한다.


호버 효과 제거가 필요한 엘리먼트를 찾아 클래스를 추가해야 하는 번거로움이 있긴 하지만, 스크립트 코드 내에 분기문을 추가하는 것보단 훨씬 깔끔하다는 생각이다.
이걸로 삽질 끝~ ㅎ

 

저작자 표시 비영리 변경 금지
Posted by ohgyun
발생일: 2011.12.30

문제:
엘리먼트에 hover 효과(롤오버)가 적용되어 있는 경우,
CSS hover 로 구현된 것인지,
mouseover/mouseout 이벤트로 효과를 준 것인지 쉽게 구별할 수 있는 방법이 있을까?

해결책:
마크업 담당자에게 문의하던 과정에서 알게된 방법~ ^^
별 것 아닌 것 같지만, 요고요고 유용하다.ㅎㅎ

  1. 개발자 도구의 엘리먼트 패널에서 대상 엘리먼트를 inspect 한다.
  2. 대상 엘리먼트에 마우스 오버/아웃 해본다.
  3. 클래스나 스타일의 변경이 직접적으로 보인다면 자바스크립트로 변경한 것.
      아닐 경우, CSS에서 :hover 클래스로 호버 효과를 준 것이다.




# 기타 참고.
- CSS 가상 클래스 우선순위: http://cssdesign.kr/forum/viewtopic.php?id=514
저작자 표시 비영리 변경 금지
Posted by ohgyun
발생일: 2011.12.19

문제:
종종 어떤 서비스들의 Ajax 패킷을 보다보면,
X-Requested-With 헤더에 XMLHttpRequest 값이 포함된 걸 볼 수 있다.

Ajax로 요청하는 트위터의 타임라인을 예로 들어보면,
아래와 같이 요청 헤더에 X-Requested-With 헤더가 있다.

  GET /1/statuses/home_timeline.json?...  HTTP/1.1
  Host: api.twitter.com
  Connection: keep-alive
  X-Requested-With: XMLHttpRequest
  User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.12 Safari/535.11
  ...


정확하게 이 헤더가 의미하는 건 뭐고,
어떤 용도로 사용하는 건지 알아보자.


해결책:

X-Requested-With 헤더는, 해당 요청이 Ajax라는 걸 의미한다.


표준 헤더는 아닌 커스텀 헤더이며,
jQuery와 Prototype을 포함한 대부분의 자바스크립트 라이브러리에서 Ajax 요청을 보낼 때에 이 헤더를 설정한다. 

(여기서, 접두사 X는 표준이 아님을 의미한다. (non-standard))


실제로 jQuery 코드를 보면, 아래와 같이 헤더를 설정하고 있다.

  if ( !( s.crossDomain && !s.hasContent ) && !headers["x-requested-with"] ) {
    headers[ "x-requested-with" ] = "XMLHttpRequest";
  }

(HTTP 헤더는 대소문자를 구분하지 않는다. (case-insensitive하다))


Prototype도 마찬가지이다.

  setRequestHeaders: function() {
    var headers = {
      'X-Requested-With': 'XMLHttpRequest',
      'X-Prototype-Version': Prototype.Version,
      'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
    }; 



이 커스텀 헤더를 통해 해당 요청이 Ajax 임을 서버에 알려줄 수 있을 뿐 아니라,
JSON Hijacking을 방어하는 용도로 사용할 수도 있다.
실제로 Ruby on Rails나 Django 등 몇몇 서버에서는 이 헤더로 Ajax 요청인지를 구분하는 기능을 제공하기도 한다.


참고로, Rails에 구현되어 있는 코드는 아래와 같다.

  # Returns true if the "X-Requested-With" header contains "XMLHttpRequest"

  # (case-insensitive). All major JavaScript libraries send this header with
  # every Ajax request.
  def xml_http_request?
    @env['HTTP_X_REQUESTED_WITH'] =~ /XMLHttpRequest/i
  end
  alias :xhr? :xml_http_request?

(HTTP_X_REQUESTED_WITH 는 x-requested-with 헤더를 의미한다)


X-Requested-With 헤더는 비표준이지만,
대부분의 라이브러리가 사용하고 있기 때문에 실질적인 표준이라 해도 무방할 것 같다.


#. 참고.
List of HTTP header fields Wikipedia:  http://en.wikipedia.org/wiki/List_of_HTTP_header_fields 
Rails github:  https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/http/request.rb#L136
HTTP 1.1 Spec(RFC2616):  http://www.ietf.org/rfc/rfc2616.txt
Custom HTTP Headers: http://www.developertutorials.com/learn-ajax/custom-http-headers-2643.php 
HTTP_X_REQUESTED_WITH in Django: http://stackoverflow.com/questions/458617/x-requested-with-http-x-requested-with-weird-problem




저작자 표시 비영리 변경 금지
Posted by ohgyun
발생일: 2011.12.17

문제:
Google Closure Compiler를 살펴보다가
구글의 꼼꼼한 자바스크립트 스타일 가이드를 보고 마음에(?) 드는 부분이 있어 메모해둔다.


해결책:
먼저, Google Closure Complier는 간단하게는 자바스크립트 압축 도구라 할 수 있고,
나아가서는 자바스크립트를 미리 컴파일 해볼 수 있는 도구이다.

재미있는 건, 컴파일 시점에 주석으로 달아놓은 어노테이션을 분석해서,
코드 내에서 의도하지 않은 방향으로 쓰인 경우를 찾아 경고해준다는 거다.

컴파일러와 어노테이션이 밀접하게 관련이 있어서이겠지?
구글의 자바스크립트 스타일 가이드의 Type Expression 부분이 유난히 꼼꼼하게 설계되어 있다.
(JSDoc과는 비교가 안될 정도로 꼼꼼하다)


변수의 타입을 설정하거나 파라미터의 타입을 설정할 때,
optional 한 것을 구분하는 것은 물론, null 여부도 구분할 수 있다.

  {Object} : (필수) Object
  {Object=} : (옵션) Object 이지만 undefined도 가능하다.
  {!Object} : (필수) Object이며, null 이어서는 안된다.
  {?Object} : (필수) Object 또는 null 이어야 한다.  
 

Arry나 Object 내의 타입을 설정하는 부분도 꼼꼼하게 정의할 수 있다.

  {Array.<number>} : number로 이루어진 배열. e.g. [1, 2, 3]
  {Object.<string, Object>} : key가 string, value가 Object인 레코드 타입.


function의 경우, 파라미터와 리턴 타입은 물론 context까지 정의할 수 있다.

  {function(number): string} : number를 파라미터로 받고, string을 리턴하는 함수.
  {function(this:ui.Menu, number)} : number를 파라미터로 받고, ui.Menu를 컨텍스트로 갖는 함수.
  {function(...number)} : 다수의 number를 파라미터로 받는 함수.


익숙해지면, 가독성도 좋을 것 같고, 무엇보다 미리 컴파일해볼 수 있다는 데에 메리트가 있다.

스타일 가이드에 대한 자세한 내용은 아래 링크를 참고하자.
http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml#JavaScript_Types
http://code.google.com/intl/ko-KR/closure/compiler/docs/js-for-compiler.html#types 

 

저작자 표시 비영리 변경 금지
Posted by ohgyun
발생일: 2011.12.16

문제:
요새 가장 관심있는 부분 중의 하나는,
큰 프로젝트에 적용할 수 있는 자바스크립트 프레임워크를 만드는 거다.
(라이브러리 말고 프레임워크.)

짬짬히 시간을 내서 만들어보고 있는데, 생각처럼 쉽지가 않다.
처음엔 자바의 스프링 프레임워크에서 영감을 받아 시작했다가,
최근엔 Addy Osmani의 Large Scale Javascript Application에 대해 작성한 포스트를 보고 다시 고민에 빠졌다.

2년 전에 Nicholas Zakas가 이 주제에 대해 발표한 이후로,
최근에는 Addy Osmani가 이 분야에 대해 굉장히 전문적이고 많은 관심을 보이는 것 같다.

훌륭한 자료들이 많아 메모해둔다.


해결책:

Scalable Javascript Application Architecture by Nicholas C. Zakas

Patterns For Large-Scale Javascript Application Architecture by Addy Osamani

Building Large-Sacle jQuery Applications by Addy Osmani

Scalable Javascript Design Pattern by Addy Osmani


읽을 수록 더욱 고민이... -..-a..

저작자 표시 비영리 변경 금지
Posted by ohgyun
발생일: 2011.11.22

문제:
그제였나.
Facebook Javascript SDK 코드가 어떻게 구현되었나 읽어보다가,
랜덤 키를 생성하는 재밌는 코드를 발견해 메모해둔다.

해결책:
iframe을 갱신하거나, jsonp 요청을 보낼 때 사용할 용도로 랜덤 키를 생성하는데,
아래 코드가 그 메서드이다.

  guid: function () {
    return 'f' + (Math.random() * (1 << 30)).toString(16).replace('.', '');
  }

자세히 들여다보면,
  1. 'f' + : 'f' 문자열에 뒤의 것을 더할 건데, // f
  2. Math.random() : 0~1 사이의 랜덤한 수 생성에  //  0.13190673617646098 
  3. * (1 << 30) : 2의 30승을 곱하고, //  0.13190673617646098  *  1073741824  = 141633779.5
  4. .toString(16) : 16진수로 문자열로 표현한 후에, // Number(141633779.9).toString(16) = 87128f3.8
  5. .replace('.', '') : 문자열에서 닷(소수점)을 제거한다. // 'f' + 87128f38 = f87128f38

이 되는 것~

Number().toString()의 파라미터로는 2, 4, 8, 16, 32 가 지원되니,
나중에 활용핼 볼 때엔 32진수로 바꾸는 것도 좋을 것 같다.  

저작자 표시 비영리 변경 금지
Posted by ohgyun
발생일: 2011.11.10

문제:
얼마 전 작은 애플리케이션을 하나 만들었는데,
애플리케이션을 구성하는 모듈의 대부분을 모듈 패턴(Module Pattern)으로 구현했었다.

모듈 패턴은 아래 예제와 같이 즉시실행함수와 클로저를 이용해 유효범위를 만들어,
private/public 개념을 흉내낸 패턴이다.

  var module = (function() {
    var private = 0; // private 멤버 (클로저 변수)

    function doPrivate() {
      private++;
    }

    // Public API
    return {
      doPublic: function() {
        doPrivate();
      }
    };
  }());

(좀 더 자세한 내용은 여기를 참조)

여튼, 개인적으로는 모듈 패턴을 사용하는 것을 꽤 선호했었다.
private 한 것과 public 한 것들을 확실하게 구별할 수 있고,
특히 모듈 내에서 (반복되고 번거롭다고 느꼈었던) this 키워드를 사용하지 않아도 되기 때문이었다.

하지만 한 가지 마음에 들지 않았던 점은,
private 메서드는 외부 접근이 불가능해 유닛 테스트하기가 어렵다는 것이다.

접근이 불가능하도록 하는 의도로 패턴을 사용하는 거라 당연한 것이기도 하고,
모듈을 작게 만들어서 공개 API만 테스트해도 되겠다만,..
음... 다른 사람들은 어찌 해결했나 궁금해서 좀 검색해봤다.


해결책:
모듈 패턴의 private 메서드 테스팅에 대한 내용은 아니지만,
비슷한 개념으로 답을 얻을 수 있는 포스트가 있었다.

조나단 스눅
이란 아자씨가 2009년 4월에 모듈 패턴에 관해 포스팅을 한 게 있는데,
제목부터 막 끌린다.

    Why I don't love JavaScript's module pattern
    http://snook.ca/archives/javascript/no-love-for-module-pattern


조나단 아자씨가 모듈 패턴을 좋아하지 않는 이유를 가볍게 정리해보며 아래와 같다.

  - 디버깅이 불편하다.
        private 변수를 바로 볼 수 없으니까. 심지어 압축된 코드라고 생각해봐? 라며...

  - 확장이 쉽지 않다.
        마찬가지로 변수가 노출되어 있지 않기 때문에, 객체의 확장이 용이하지 않다.

  - AOP 적용이 어렵다.
        AOP 방식으로 구현한다 하더라도 숨겨진 속성들에 접근할 수 없기 때문에 효율적이지 않다.

  - private 한 변수는 접두사 언더바(_)를 사용하는 표기법 만으로도 충분하다.


댓글로 찬반에 대한 의견이 많은데, 그 중 니콜라스 자카스의 댓글이 모든 상황을 정리해주는 느낌이다.
자세하게 답변을 했는데 결국엔 "그 때 그 때 달라요~" 랄까.


그 외, 비슷한 주제에 대해,
'왜 private member가 필요하냐?'서부터 'javascript는 javascript 답게 써라'까지 여러 포스트가 있었는데.
역시 결론은 '상황에 맞게'인 것 같다. 테스팅도 마찬가지.


# 덧)
일전에 포스팅했던 Testing private method - Methods Should Be Public? 을 다시 읽어보니 재밌다.




저작자 표시 비영리 변경 금지
Posted by ohgyun
발생일: 2011.11.07

문제:
라이브러리 없이 각 노드의 관계를 비교하려고 하다보니 compareDocumentPosition() 이라는 메서드가 있더라.
비슷하게 contains()가 있다는 건 알고 있었는데, compareDocumentPosition()은 첨 들어본다.

자세히 알아보자.

해결책:
compareDocumentPosition() 메서드는 W3C DOM Level 3 Core 스펙에 정의되어 있다.
현재 노드와 파라미터로 전달되는 노드와의 관계를 비교해, 비트마스크 연산을 통한 정수값을 리턴한다.

node.compareDocumentPosition(otherNode) 와 같이 호출할 수 있으며,
각 노드의 관계에 따라 아래 값을 리턴한다.


비트         값       관계
000000     0        동일한 노드이다.
000001     1        서로 다른 도큐먼트에 존재하는 노드이다.
000010     2        node가 otherNode 보다 앞에 존재한다.
000100     4        node가 otherNode 보다 뒤에 존재한다.
001000     8        node가 otherNode의 부모이다. (포함한다)
010000    16        node가 otherNode의 자식이다. (포함된다)

두 노드의 관계에 따라 더해진(mask on 연산) 값을 리턴한다.


예를 들어, 아래와 같은 노드가 있다고 가정하고,
   <div id="a"><div id="b"></div></div>

아래 메서드를 호출하면,
  nodeA.compareDocumentPosition(nodeB); // 10을 리턴한다.

각 노드의 관계로 10을 리턴한다.

(nodeA는 nodeB의 부모이므로 8,
nodeA는 nodeB보다 앞에 존재하는 노드이므로 2가 더해져 10을 리턴한다.)



node.compareDocumentPosition()는 현재 IE9~, Chrome, FF, Safari, Opera에 구현되어 있다.
(http://www.quirksmode.org/dom/w3c_core.html#t120)



참고로,
compareDocumentPosition()의 값이 10을 리턴하는 경우는 node.contains() 메서드와 동일하다고 볼 수 있다.


#. 참고
  compareDocumentPosition API by MDN
  Comparing Document Position by John Resig 
  FF에서 contains() 구현하기 by quirksmode
  W3C DOM Level 3 Spec : compareDocumentPosition
저작자 표시 비영리 변경 금지
Posted by ohgyun