레이블이 JS(Library)인 게시물을 표시합니다. 모든 게시물 표시
레이블이 JS(Library)인 게시물을 표시합니다. 모든 게시물 표시

2008년 7월 21일 월요일

jQuery와 다른 라이브러리를 함께 사용하기

  시작하는 글 

jQuery는 다른 라이브러리와 함께 사용할 수 있도록 만들어졌는데요. jQuery라이브러리와 플러그인들은 jQuery(namespace) 안에 포함되도록 제한되어 있습니다. jQuery의 일반적인 규칙으로 "global"한 객체들은 모두 jQuery(namespace) 안에 정의되어지기 때문에 Prototype이나 MooTools 또는 YUI와 충돌에 관해서 걱정할 필요가 없습니다.

그러나, 단 하나의 예외가 있는데요. jQuery 라이브러리에서 jQuery(namespace)의 shortcut으로 사용되는 $입니다.

  $ 함수 재정의하기 

그러나, 이러한 $에 대해 충돌이 발생하더라도 jQuery.noConflict()를 호출함으로서 해결할 수 있습니다. (jQuery.noConflict()를 호출하기 위해서는 jQuery 라이브러리가 선언된 뒤여야만 합니다.)

<html>
  <head>
    <script src="prototype.js"></script>
    <script src="jquery.js"></script>
    <script>
      jQuery.noConflict();
    
      // Use jQuery via jQuery(...), $가 아닌 jQuery를 사용
      jQuery(document).ready(function(){
         jQuery("div").hide();
      });
    
      // Use Prototype with $(...), etc.
      $('someid').hide();
    </script>
  </head>
  <body></body>
 </html>

jQuery.noConfict()를 호출하게되면 _$(jquery.js 파일이 로딩될 때 기존에 선언되었던 $의 내용을 _$에 저장)의 내용들을 복원하게 됩니다. $를 호출하게 되면 위에서 선언하였던 prototype의 $가 호출이 되지만 jQuery는 페이지의 다른 곳에서 계속 사용할 수 있게 됩니다.

이 외에도 다른 해결책도 있습니다. 다른 라이브러리와 충돌이 나지 않는 shortcut을 선언하는 것입니다.

<html>
  <head>
    <script src="prototype.js"></script>
    <script src="jquery.js"></script>
    <script>
      var $j = jQuery.noConflict();
   
       // Use jQuery via $j(...), $가 아닌 $j를 사용
      $j(document).ready(function(){
         $j("div").hide();
      });
    
       // Use Prototype with $(...), etc.
      $('someid').hide();
    </script>
  </head>
  <body></body>
 </html>

jQuery.noConflict()에서 리턴되는 값은 jQuery입니다. 여기에 $j가 jQuery를 참조하도록 하는 코드구요. 당연히 $j 외에도 여러 다른 기호들을 alias로 사용할 수 있습니다.

  jQuery 코드

jQuery 시작 부분을 보게 되면 jQuery에서 사용되는 jQuery와 $ namespace에 대해서 따로 저장을 하게 되구요.

// Map over jQuery in case of overwrite
var _jQuery = window.jQuery,
// Map over the $ in case of overwrite
    _$ = window.$;

noConflict 함수가 호출되는 경우 이를 복원하는 형태를 취하고 있습니다.

jQuery.extend({
    noConflict: function( deep ) {
        window.$ = _$;

        if ( deep )
            window.jQuery = _jQuery;

        return jQuery;
    },

  참고자료


2008년 7월 1일 화요일

Canvas 태그에 그린 내용을 저장하고 싶을 때...

Canvas에 그려진 이미지를 이미지로 저장할 일이 있었는데요. Ajaxian에서 본 기억이 어렴풋이 떠올라서 검색을 해봤습니다. Canvas2Image: Save out your canvas data to images의 기사가 Canvas 태그를 이미지로 저장하는 라이브러리를 소개하는 기사입니다.

사용법은 간단합니다.  
먼저, html 페이지에서 canvas 태그를 이미지로 저장하기 위한 js파일들을 canvas2image.jsbase64.js를 script태그를 사용하여 읽어들입니다. (base64.js는 bmp를 저장할 때만 사용됩니다.) 그리고, 스크립트 코드에서 다음과 같이 Canvas의 내용을 저장하면 됩니다.
// Canvas element를 얻어온 다음에
var oCanvas = document.getElementById("thecanvas");

// 원하는 파일 타입인 PNG, JPEG, BMP로 저장합니다.
Canvas2Image.saveAsPNG(oCanvas);
Canvas2Image.saveAsJPEG(oCanvas);
Canvas2Image.saveAsBMP(oCanvas);
canvas2image.js에서 이미지를 저장하는 방법은 크게 두 가지로 나눌 수 있습니다.
  1. 내장된 변환코드로 변환: Canvas2Image에 선언되어 있는 createBMP()를 사용하여 변환
  2. toDataURL()을 사용: png와 jpeg는 Canvas태그의 HTMLCanvasElement.toDataURL()를 사용하여 이미지를 생성
toDataURL()의 인자로는 Mime 타입인 image/png, image/jpeg, image/svg+xml 등을 인자로 넘겨줄 수 있습니다.

Canvas2Image.savaeAsXXXX()를 실행할 때 3,4번째 인자로 크기를 조절할 width, height를 줄 수 있는데 크기 조절이 안되는 경우가 있더군요. 제가 잘 못했는지도 모르겠습니다만 ^^;; canvas 태그의 width/height에 직접 값을 넣어줬습니다. Firefox 3.0에서 style로 width/height를 줘도 canvas의 디폴트 값인 300,150 크기의 이미지가 넘어오더군요.

출처: Saving canvas data to image file via Ajaxian

2008년 6월 29일 일요일

Objective-J

사용자 삽입 이미지

요즘들어 자바스크립트와 관련하여 자주 들리는 이슈 중 하나가 Objective-J입니다.
Carsonified의 Ryan씨가 이와 관련하여 "Why Objective-J, Cappucino and SproutCore are completely changing the web app industry"에 내용을 정리하였습니다. 먼저, Objective-J에 관해서 정리하면,
  1. DOM을 생성하기 위한 HTML, CSS, JavaScript 계층 위에 Objective-J라는 계층을 둔다.
  2. Objective-J를 사용하면 데스크탑 애플리케이션 개발 스타일로 웹 애플리케이션을 개발할 수 있다.
  3. 개발자들은 HTML, CSS에 직접 접근하여 화면을 조정하지 않고 Objective-J를 통하여 화면을 어떻게 그릴지 어떻게 보여야 할 지를 정의한다.
이러한 특징들은, 클라이언트-서버 모델 개발을 벗어나서 브라우져 안에서 직접 동작할 수 있는 애플리케이션을 만들 수 있게 합니다.

그 외에 Apple의 Mobile Me에서 사용되는 SproutCore를 다루고 있습니다. -Capuccino는 280Slides.com에서 만들어진 Cocoa를 포팅한 프레임웍입니다.- 위의 특징들은 "Why Objective-J..."에서 새로운 흐름이라고 얘기하고 있으며 이들이 오픈 소스이기 때문에 Silverlight, Air와 다르다고 얘기를 하고 있습니다.

=> JavaScript 위에 새로운 계층을 얹는 다는 것은 재미있는 발상이기는 합니다만, 280Slides의 Presentation을 실행해보면 알겠지만 느리다는 단점이 있습니다. 아직은 지켜봐야겠지만, 새로운 하나의 흐름으로 지켜봐야할 것 같습니다.

출처:

2008년 3월 19일 수요일

prototype.js, HTMLElement에 method를 추가하기

Firefox에서 prototype.js를 사용하게 되면 prototype의 Element.Methods와 Element.Methods.Simultated 정의되어 있는 method와 property가 HTMLElement.property에 추가되게 됩니다.
  if (F.ElementExtensions) {
    // copy(source, destination)
    copy(Element.Methods, HTMLElement.prototype);
    copy(Element.Methods.Simulated, HTMLElement.prototype, true);
  }
이렇게 추가되게 되면, 다음의 효과를 얻습니다. HTMLElement를 생성할 때, Element.Methods에 정의되어 있는 메소드를 그대로 상속받게 되는거죠. 예를 들면 element를 생성만 했슴에도 Element.Methods에 정의되어 있는 getDimension()에 접근이 가능하게 되는거죠.
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
     "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <script type="text/javascript" src="prototype_v1511.js"></script>
    <title>Insert title here</title>
</head>
<body
  onload="var divElm = document.createElement('div');
    alert(divElm.getDimensions);">
</body>
</html>
그러나, IE에서는 HTMLElement 인터페이스(정확히는 HTMLElement 인터페이스를 구현한 Object)에 어떠한 메소드나 프로퍼티 추가를 허락하지 않습니다. 그렇기 때문에 IE에서 위의 코드를 실행하게 되면 동작을 하지 않습니다.
사용자 삽입 이미지

그렇기 때문에, IE에서는 element를 생성할 때, $()로 한 번 감싸주거나 Element.extend를 한 번 더 호출해서 prototype.js의 Element 기능을 추가합니다.

출처: How Prototype extends the DOM

P.S >
다른 분과 IE에서 HTMLElement.prototype 에 접근이 안된다는 얘기를 했더니 그럴리가 없다는 얘기를 하시면서 new로 생성이 안되어서 그렇다는 의견을 얘기한 적이 있었습니다. 그 당시에 실험을 해보고 글로는 안 썼었는데 정리하는 차원에서 추가합니다.

IE에서 몇 가지 실험을 해보면,
alert(HTMLElement);
// HTMLElement 가 정의되어 있지 않다고 에러가 발생합니다. (Element 동일)
즉, HTMLElement에 접근할 수 조차 없게 되겠죠. 그러나, new로 생성하지 못하기 때문에 new가 원인이 된다는 확인해보지 못했었는데요. 곰곰히 생각하다보니 IE에서 img 태그의 경우 new Image()로 생성할 수 있다는 게 생각이 나더군요. 그러나, 역시 Image의 경우에도 prototype에 접근할 수 없었습니다.
alert(Image);  // Object가 뜹니다.
alert(Image.prototype);  // undefined가 나오네요.
결론은 IE에서는 HTMLElement나 Tag에 직접접근할 수 없다고 보는게 맞다고 생각이 됩니다.

2008년 2월 23일 토요일

script.aculo.us의 effects.js 정리

제가 요즘 다니고 있는 YUI 스터디에서 '멋진인생'님께서 script.aculo.us의 effects.js를 발표하셨는데요.
제가 잘 몰랐던 부분을 마음껏 물어볼 수 있어서 좋왔던 것 같습니다. 후후후 ^^;;

※ 본 포스트는 script.aculo.us의 effects.js와 관련된 세미나를 들으면서 들었던 생각과 내용을 보충하는 내용입니다. Effet를 생성하거나 ScopedQueue를 생성하거나 옵션을 주는 부분은 다루지 않습니다.
사용자 삽입 이미지

  1. effects.js란?
  • 인자로 받는 element들을 대상으로
  • 시작시간(startOn)부터 종료시간(finishOn)까지
  • 투명하게하거나, 접히거나, 서서히 사라지고 나타나는 등의 효과(데모 페이지)
를 주는 것을 의미합니다.
사용자 삽입 이미지

  2. effects의 코드 상의 구성
effects.js의 구성은 세 가지 단계로 나눌 수 있습니다. (effects.js 코드는 Effect 스코프를 가지고 있습니다.)
  • Effect.Base를 상속받은 Effect 클래스
  • Effect클래스를 시간 상(time line)에서 어디에 배치되고 동작할 지를 관리하는 Effect.ScopedQueue
  • Effect.ScopedQueue를 전부 관리하는 Effect.Queues
다이어그램으로 본다면 다음의 그림으로 볼 수 있겠네요.
사용자 삽입 이미지

※ 다이어그램은 의미전달 용도로 쓰였기 때문에 UML 규약과 틀릴 수 있습니다.

  3. effects 개념상의 구성
effects의 개념을 보기 위해서는 가장 먼저 할일이 ScopedQueue를 들여보는 일입니다. ScopedQueue를 간단히 말하자면 영사기와 같다고 보시면 됩니다. 15ms이라는 단위를 갖는 시간 축을 갖고 15ms이 지날 때마자 자신의 effects(영화 필름의 프레임으로 생각하셔도 될 것 같습니다.)들에게 시간을 알려줍니다.

사용자 삽입 이미지

ScopedQueue에 더해진 Effect들은 넘겨 받은 시간을 확인하여 자신이 나타날 시간인지 아닌지를 확인한 후 자신들이 변화된 (스타일이 변경되거나 html이 변경된) 모습을 화면(페이지)상에 출력하게 됩니다.

ScopedQueue의 코드 상의 흐름을 잠시 살펴보겠습니다.
  1. 먼저 add()가 호출되면 현재 시간의 timestamp를 얻어옵니다.
    add: function(effect) {
       var timestamp = new Date().getTime();

  2. 더해진 effect가 다른 effect보다 앞에 나와야할 지 또는 뒤에 나와야할 지에 대한 position 값이 주어지면 해당하는 position만큼 effect들이 무대(페이지)에 나오는 시간과 들어갈 시간을 조절해 줍니다.

    var position = Object.isString(effect.options.queue) ?
       effect.options.queue : effect.options.queue.position;

    switch(position) {
         case 'front':
           // move unstarted effects after this effect 
           this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
             e.startOn  += effect.finishOn;
             e.finishOn += effect.finishOn;
           });
           break;
         case 'with-last':
           timestamp = this.effects.pluck('startOn').max() || timestamp;
           break;
         case 'end':
            // start effect after last queued effect has finished
            timestamp = this.effects.pluck('finishOn').max() || timestamp;
           break;
       }

    그림으로 본다면 다음과 같이 될 것 같습니다. 앞의 그림을 ScopedQueue의 현재 상태라고 가정하구요. 여기에 초록색 Effect를 추가하겠습니다. 시작시간(startOn)은 15ms, 종료 시간은 65ms으로 설정을하고 파란색 Effect의 앞(front)로 삽입을하면 다음의 결과가 나오게 됩니다.
    사용자 삽입 이미지
    초록색 Effect가 앞에 나오고 다른 Effect들의 시작시간은 65ms만큼 앞에 더해지게 되는거죠.

  3. 더해지는 Effect에 시작시간(startOn)과 종료시간(finishOn)에 현재 시간의 timestamp를 더해서 시작가능한 시간이 되도록 맞춰줍니다.
        effect.startOn  += timestamp;
        effect.finishOn += timestamp;

  4. Effect의 limit를 체크한 후, limit를 넘지 않는 경우 ScopedQueue에 추가를 합니다.
        if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
          this.effects.push(effect);

  5. this.interval가 있는지 확인한 후 없는 경우 setInterval을 호출해서 interval을 생성합니다. (달리말하면, timeline을 생성한다고 봐도 되겠죠.)
        if (!this.interval)
          this.interval = setInterval(this.loop.bind(this), 15);
      },

    this.interval이 설정이 되면, 15ms마다 loop를 호출하게 됩니다.

  6. loop에서는 호출 될 때마다, 현재 시간을 얻은 후 ScopedQueue에 쌓여 있는 effect들에게 시간을 알려줍니다. (Effect.Base에서 상속받는 loop()를 호출해주게 됩니다.)
      loop: function() {
       
    var timestamp = new Date().getTime();
        for(var i=0, len=this.effects.length;i<len;i++)
          this.effects[i] && this.effects[i].loop(timePos);
      }

  7. 호출된 Effect의 loop에서는 현재 시간이 자신이 나타나야되는 시간이 지났는지와 종료되어야 하는 시간인지를 체크한 후 (startOn과 finishOn 사이의 시간인지를 확인한 후에) 자기 자신을 화면에 그리게 됩니다.

      // Effect.Base의 loop 메소드입니다.
      loop: function(timePos) {
        if (timePos >= this.startOn) {
         
    if (timePos >= this.finishOn) {
           
    this.render(1.0); // 종료 시점의 pos 값은 1입니다.
           
    this.cancel();
           
    this.event('beforeFinish');
           
    if (this.finish) this.finish();
           
    this.event('afterFinish');
            return
          }
          // startOn과 finishOn 사이의 시간인 경우
          var pos   = (timePos - this.startOn) / this.totalTime,
              frame = (pos * this.totalFrames).round();
         
    if (frame > this.currentFrame) {
            // 현재의 frame과 timeline상의 시간의 frame이 맞지 않은 경우 새로 그려줍니다.
            this.render(pos);
            this.currentFrame = frame;
          }
        }
      },
※ 관련링크 : script.aculo.us의 위키 페이지
※※ 발표하느라 고생이 많으셨던 '멋진인생'님과 제가 잘 몰랐던 부분을 가르켜주신 신기루님 감사해요~

2008년 2월 3일 일요일

YUI - compressor

사용자 삽입 이미지
YUI Compressor는 Yahoo의 UI Library 중 하나로 javascript와 css 파일 크기를 최소화 시킴으로서 js,css 파일의 다운로드 속도를 개선하게 해주는 라이브러리입니다. YUI Compressor에서 줄 수 있는 옵션들은 다음과 같습니다.
  • js/css 모두에 사용할 수 있는 글로벌 옵션들
    • -h, --help : 도움말을 출력합니다.
    • --line-break <column>: 압축을 하는 경우 한 줄로 파일이 생성되게 되는데, 다음과 같은 이유로 특정  컬럼뒤에 line break를 삽입해 줍니다.
      1. 이렇게 압축된 파일은 읽기에도 불편할 뿐더러
      2. 디버깅하기 어려운 문제를 가지고 있습니다.
      3. 특정 소스 컨트롤 툴에서 문제가 될 수 있습니다.
    • --type <js|css>: YUI Compressor에서는 압축하는 파일의 확장자를 기반으로 js|css를 선택해서 압축하고 있습니다. 그러나, 입력 파일이 명시되지 않을 때나 확장자가 js 또는 css가 아닌 경우 사용되어야 합니다.
    • --charset <charset>: 입력 파일을 읽을 때 사용되난 charset입니다. 해당 옵션이 선언되지 않은 경우에 사용되는 플랫폼의 기본 charset을 사용하며, 출력 charset에도 동일한 charset이 사용됩니다.
    • -o <file>: 출력 파일을 지정합니다. 옵션이 선언되지 않은 경우 YUI Comressor의 기본 출력 폴더로 압축파일을 내보내게 됩니다.
    • -v, --verbose: 압축 시 발생하는 정보성 또는 경고 메시지를 출력하게 합니다.
  • js에서만 사용가능한 옵션들
    • --nomunge: 공백 제거만을 사용하며 로컬의 변수들의 이름을 변경하여 크기를 줄이는 obfuscation을 사용하지 않습니다.
    • --preserve-semi: 불필요한 세미콜론들을 삭제하지 않고 유지시킵니다. 예를 들면 } 바로 앞에 위치한 ;을 삭제하지 않고 유지시킵니다.
    • --disable-optimizations: built-in micro optimization을 사용하지 않습니다.
※ 2.3.1에 오면서 --warn 옵션과 --preserve-strings 옵션이 없어졌네요.

사용법
Usage: java -jar yuicompressor-x.y.z.jar [options] [input file]
[options]에는 위의 옵션들 중 필요한 사항들을 입력하시면 되고, [input file]에는 압축할 파일을 입력하시면 됩니다. 출력 파일은 [input file] 뒤에 입력해 주시면 되구요. yuicompressor-x.y.z의 x.y.z는 빌드 넘버입니다. 다운 받은 jar파일의 버전에 맞게 바꿔 주시면 됩니다.

사용 예
C:\java -jar -jar yuicompressor-2.3.1.jar --charset utf-8 --line-break 100 -v --preserve-semi C:\sample.js -o C:\dst\sample.js
- 저의 경우 2.3.1을 다운 받고, utf-8 설정과 100 컬럼당 라인 브레이크 추가 경고문 출력, 세미콜론을 보호하는 옵션을 주었습니다.

관련자료:
  • YUI Compressor - BSD License를 사용하고 있습니다. Java 1.4 이상의 버전을 필요로 합니다.


2008년 1월 10일 목요일

웹사이트의 타이틀을 쉽게 복사하기

Jon Aquino 씨의 묵혀둔 RSS를 뒤져보다 Copy Title bookmarklet이란 포스트를 보개 되었습니다.
Copy Title bookmarklet은 자신이 보고 있는 사이트의 타이틀을 쉽게 복사할 수 있게하는 북마크릿인데요.
  1. Q/A 팀에서 버그를 보고하는 경우 해당하는 페이지의 타이틀을 복사해서 붙여넣으려면 직접 입력하는 방법 밖에 없습니다.
  2. 북마크릿에 자바스크립트 코드를 넣어서 북마크릿을 실행하는 경우
  3. 해당하는 페이지의 타이틀(document.title)을 읽어와서
  4. body태그의 가장 첫 번째 element로 input안에 타이틀을 넣어서 삽입합니다. 즉, 웹페이지의 가장 상단에 타이틀이 선택된 채로 나오게 되겠죠.
  5. input.select()를 호출하기 때문에 당연히 해당 타이틀이 선택된 상태이므로 북마크릿을 클릭한 후 Ctrl+C만 누르면 쉽게 타이틀을 복사할 수 있습니다.
작지만, 효율을 높일 수 있는 재미있는 아이템이 아닌가 싶습니다.

소스코드 (한 줄로 되어있는 코드를 풀었습니다.)
javascript:
var input = document.createElement('input');
input.type = 'text';
input.value = document.title;

input.style.width = '500px';
document.body.insertBefore(input, document.body.firstChild);
input.focus();
input.select();
출처: Copy Title bookmarklet

2007년 8월 27일 월요일

js 라이브러리 요약

이미지 로더(업로더가 아님)
  • YUI-Image Loader - 화면에 이미지가 출력될 시간을 조절하는 라이브러리(초기 로딩시간을 지연시켜 Performance에 대한 효과를 얻을 수 있다.)
슬라이더
Context Menu - 마우스 오른쪽 버튼을 눌렀을 때 나오는 팝업 메뉴
JavaScript to HTML
SVG
  • InputDraw - 결과물을 SVG로 저장할 수 있게 해준다. 입력은 Flash로 받는다.
  • reflex.js - 이미지가 반사된 효과(Cover flow effect)를 내게 해주는 라이브러리입니다. (ff1.5+, opera9+, ie6+ 를 지원합니다.) 반사된 효과를 주고 싶은 이미지 태그에 class="reflex"를 설정하면 onload 타임에 반사효과를 보여줍니다.
    사용자 삽입 이미지

Editor
  • Rich Text Editor - YUI 2.3에 포함되어 있다. Safari 2.0을 지원한다. Selection을 에뮬레이션을 한다. 가볍다.
  • Code Press - 입력 시 Syntax Highlighting을 처리한다. 입력하는 텍스트를 파싱하여서 선택한 문법에 따라서, 입력한 텍스트에 태그를 먹이거나 css를 설정한다. 생각보다는 무겁지 않다. 독립적 애플리케이션으로 붙인다면 재미있을 듯..
압축
  • YUI Compressor - 압축률이 DOJO보다 높고 JSMin보다 안전하다. evil 메소드에 대해서는 처리하지 않는다.
Clipping
  • pzImageCombine - 같은 디렉토리에 있는 여러 이미지를 하나의 이미지로 합쳐서 보여주는 라이브러리
Popup
  • Popup Politicians - 팝업을 띄워서 개인의 프로파일을 소개해주는 라이브러리
    사용자 삽입 이미지
  • YUI lightbox: Drag&Drop, Image preloading, Max/Minimize dialog
달력
  • DatePicker - prototype.js, script.aculo.us기반의 날짜 선택 컴포넌트
    사용자 삽입 이미지

CSS Crossfader
파일업로더
  • SWFUpload: 파일타입지정, 다중파일업로드, 파일크기를 비롯한 파일정보를 업로드전에 리턴, 버튼은 html+css
생략표시

※ 자바스크립트 라이브러리 요약입니다.
※※ 도움이 되셨다면 오른쪽 메뉴 아래에 보이는 광고를 클릭해주세요 쿠쿠쿠 ^^

2007년 7월 22일 일요일

HTTP overhead 줄이기

1. 문제점
  • 페이지에 많은 이미지나 비디오 파일이 포함되어 있습니다.
  • 해당하는 이미지나 비디오 파일은 동일한 파일이 아니기 때문에 HTTP연결을 생성하고 초기화하는데 비용이 들어갑니다.
  • 예) 아바타를 사용하는 Q&A 페이지에서 50개의 아바타를 로딩하는 경우
  • 이미지가 다 로딩되지 않은 경우 페이지가 아직 사용하지 못하는 것처럼 인식될 수 있습니다. (onload시간에 js동작을 하게 하였다면 로딩전까지 js가 실행되지 않겠죠)
2. 해결책
이미지의 src를 기본값이 되는 "디폴트 이미지#http://원주소"로 변경하여서 처음 페이지 로딩 시에 디폴트 이미지를 로딩하게 합니다.
<img src="default.gif#http://avatarurl" ... >
페이지 로딩이 끝난 다음(onload가 호출되는 시점)에 #뒤의 이미지 원주소를 로딩하게 합니다.

3. 소스코드

/*
        delayHTTPoverhead
        written by
                Christian Heilmann
        with help
                from Drew McLellan, David Dorward and Lawrence Carvalho
        http://www.wait-till-i.com/index.php?p=465
        License: http://creativecommons.org/licenses/by/3.0/
*/

delayHTTPoverhead
= function(){
       
var parentID = '';
       
var avtClass = '';
       
       
// 페이지의 default이미지를 원래 이미지로 교체해줍니다.
       
function replaceImage(){
               
var img = (parentID!=='')?
                        document
.getElementById(parentID).getElementsByTagName('img'):
                        document
.getElementsByTagName('img');
               
               
var rep=/.*#/;
               
for(var i=0;img[i];i++){
                       
var src=img[i].src;
                       
                       
if(src.indexOf('#')!=-1 && img[i].className.indexOf(avtClass)!==-1){
                                img
[i].src = src.replace(rep,'');
                       
};
               
};
       
}
       
       
// onload에 replaceImage를 추가시켜줍니다.
       
var _onload=wind_onloadw.onload;
       
if(typeof window.onload!='function'){
                window
.onload=replaceImage;
       
}else{
                window
.onload = function(){
                       
if(_onload){
                                _onload
();
                       
};
                        replaceImage
();
               
};
       
};
}();

4. 출처




2007년 5월 17일 목요일

Flash Tooltips

Ajaxian에 Flash Tooltip이 소개되었습니다.

Peeter Goodman 씨가 만든 라이브러리로 img 또는 a 태그를 사용하면 툴팁을 만들 수 있는데, 굳이 따로 만든 이유는 다양한 텍스트 포멧을 줄 수 없기 때문이라고 합니다. 첫 인상은 깔끔한 느낌이네요. 다이얼로그가 작아서인지 느린 것 같지는 않습니다.(이전 글의 다이얼로그를 보면 늦기는 합니다. 일부러 늦게 한것인지는 모르겠습니다. 코드까지는 보지를 않아서 -_-;;)
사용자 삽입 이미지
기타 특징들
  • 라이센스: GPL
  • jQuery가 필요합니다.
  • tooltip.config파일을 사용해서 세부 설정을 할 수 있습니다.
출처 : Flash Tooltips Using jQuery via Ajaxian.com

2007년 5월 3일 목요일

[Script.aculo.us] dragdrop.js

  dragdrop.js
script.aculo.us에서 Drag&Drop 기능을 제공해주는 라이브러리입니다.

  Droppables
드래그 대상이 되는 Draggable객체들을 Drop할 수 있는 element들을 관리하는 클래스입니다.
사용자 삽입 이미지

  Attribute
Droppables.drops: Array - Droppable 객체(실제로는 add()의 options 전체 항목이 저장됩니다.)들을 저장하는 배열입니다.

  Method
1. Droppables.add(element, options) - Droppable 객체를 추가합니다. options로 다음 사항을 받을 수 있습니다.
options 항목들
  • accept - Droppable에서 받아들일 Draggable 객체의 클래스 스트링들을 설정합니다.
  • containment - Droppable에서 받아들일 Draggable객체의 element나 id를 설정합니다.
  • hoverclass:boolean - 받아들이기로 한 Draggable객체가 Droppable의 위에 있을 때 css를 설정하는 class를 설정합니다.
  • overlap - 'horizontal' 또는 'vertical'을 인자로 받습니다. 수직/수평 방향으로 이동할 때 동작이 발생하도록 합니다.
  • greedy:boolean - true로 설정된 경우 hover와 관련된 처리를 수행하지 않습니다.
options 항목들 중 내부사용 프로퍼티
  • tree - tree에서 사용하기 위한 코드로 보임
  • _continaers - options.containment객체들이 저장됩니다.
  • element - 실제 Droppable element가 저장됩니다.
options 항목의 callback들
  • onHover(dragElement, dropElement, position) - 받아들이기로 한 Draggable 객체가 Droppable의 위에 있에 있을 때 메소드를 onHover 인자로 받은 function을 호출합니다.
  • onDrop(dragElement, dropElement, event) - 받아들이기로 한 Drggable 객체가 Droppable의 위에서 릴리즈되었을 때 onDrop 인자로 받은 function을 호출합니다.
2. Droppables.remove(element) - Droppable 객체를 삭제합니다.

3.
Droppables.findDeepestChild(drops)
- drops 루프를 돌면서 drops에서 가장 먼저 등록한 Droppable 객체들 중에서 가장 상위에 있는 Droppable 객체를 찾는 메소드입니다. (의도는?)

4.
Droppables.isContained(element, drop)
- 인자로 받는 element의 부모노드가 drop의 containment(받아들이기로 한 element) 목록에 있는 지 여부를 리턴합니다.

5. Droppables.isAffected(point, element, drop)
- 인자로 받는 element가 인자로 받는 drop(Droppable)에 Drop이 된 것인지의 여부를 체크하는 메소드입니다.
  1. drop.element와 달라야하고,
  2. drop._containers가 있는 경우 여기에 속해야하고,
  3. drop.accept가 있는 경우 element의 className중 하나가 해당해야하고,
  4. drop.element의 안에 인자로 받는 point의 위치가 속해야 합니다.
6. Droppables.activate(drop) [Droppables.deactivate(drop)]
- active[deactive]가 된 경우, drop.hoverclass가 있다면 drop.element에 hoverclass를 설정[제거]하고 last_activate 값을 설정[null로 설정]합니다.

※ show, fire, reset 메소드의 경우 Draggable에서 호출되는 메소드입니다.
7. Droppables.show(point, element)
- element의 Drop에 해당하는 Droppable이 있으면 hover 이펙트를 발생시킵니다.
  1. 인자로 받은 element가 Drop되었는지를 체크(isAffected())하여 affected에 담습니다.
  2. affected된 Droppable 중에서 가장 상위의 element(findDeepestChild()를 사용하여)를 찾습니다.
  3. 해당하는 Droppable을 activate시킵니다.
8. Droppables.fire(event, element) - onDrop 옵션을 가지고 있는 경우 onDrop 이벤트를 실행시킵니다.
9. Droppables.reset() - 초기화(deactivate) 시킵니다.

  Draggables
Draggables객체들을 관리하는 클래스입니다.
사용자 삽입 이미지

  Attribute
Draggables.drags: Array - draggable을 저장합니다.
Draggables.observers: Array -
activeDraggable - 현재 활성화되어 있는 Draggable을 가르키는 변수입니다.

  Method
1. Draggables.register(draggable)
- draggable을 인자로 받아서 drags에 추가합니다.
- drggable이 처음 등록되는 경우 document의 mouseup/mousemove/keypress 이벤트 핸들러로 eventMoueUp/eventMouseMove/eventKeypress 메소드를 등록합니다.

2. Draggables.unregister(draggable) -
- 인자로 받는 draggable을 drags에서 삭제합니다.
- 모든 draggable이 삭제되는 경우, document의 mouseup/mousemove/keypress 이벤트에 등록된 핸들러들을 모두 삭제합니다.

3. Draggables.activate(draggable)
- Draggable에서 호출되며, (delay 옵션이 있는 경우 dealy 옵션 뒤에) activeDraggable을 설정합니다.

4. Draggables.deactivate() - activeDraggable을 삭제합니다.(null처리)

※ 2에서 등록하였던 mouseup/mousemove/keypress 이벤트에 따라서, (activeDraggable이 있는 경우)activeDraggable에 해당하는 이벤트를 전달하는 역할을 합니다.
5. Draggables.updateDrag(event)
6. Draggables.endDrag(event)
7. Draggables.keyPress(event

※ 8, 9, 10, 11은 Draggables.observers와 관련된 메소드들로 Draggable에서 onStart/End/Drag 이벤트가 발생됬을 때, 해당하는 이벤트를 듣기 위한 구조입니다.
8.
Draggables.addObserver(observer)
9. Draggables.removeObserver(element)
10. Draggables.notify(eventName, draggable, event)
- notify는 Draggable에서 호출되는 메소드로 onStart/onEnd/onDrag 이벤트가 발생한경우 observer에서 해당하는 이벤트를 관차하는 observer가 있는 경우 observer의 callback을 호출한 후 draggable의 등록된 callback을 호출합니다.
11. Draggables._cacheObserverCallbacks()

  Draggable
Drag되는 (Draggable)객체 입니다.
사용자 삽입 이미지
Creation
new Draggable('id_of_element', [options]);
options항목은 다음과 같습니다.
  • handle - v1.0에서는 draggable할 element의 레퍼런스와 id를 인자로 받습니다. v1.5에서는 css 클래스 스트링으로 사용됩니다.
  • revert :boolean - true인 경우, 시작점으로 돌아갑니다. function이 들오올 수 있습니다.(since v1.5) 디폴트 값은 false입니다.
  • snap - true인 경우, snapping(달려들어 무는)이 발생합니다. 디폴트 값은 false입니다.
  • zindex - draggable할 item의 zindex를 정의합니다.
  • constraint - 'horizontal' 또는 'vertical'이 설정되는 경우, 수평/수직으로만 이동하도록 설정됩니다.
  • ghosting :boolean - Drag~Drop이 진행되는 동안 자신의 위치에 clone object를 남겨둡니다.
  • starteffect - Drag가 시작될 때, 적용할 이펙트를 정의합니다. 디폴트로 투명 이펙트(Opacity)를 실행합니다.
  • reverteffect - Drag를 하다 되돌아가는 경우(Droppable영역이 아닌 지역에서 릴리즈했을 때)에 적용할 이펙트를 정의합니다. 디폴트 값으로는 시작점 포인트로 직선 이동하는 이펙트(Move)를 실행합니다.
  • endeffect - Drag가 종료될 때, 적용할 이펙트를 정의합니다. 디폴트로 투명 이펙트(Opacity)를 실행합니다.
options에 설정되는 callback function입니다.
  • change - Drag로 인하여 Draggable의 위치가 변경된 경우 발생합니다.
  Attribute
Draggable.drags: Array - draggable을 저장합니다.
Draggable.observers: Array - observer할 object들을 저장합니다.
activeDraggable - 현재 활성화되어 있는 Draggable을 가르키는 변수입니다.
dragging: boolean - dragging이 진행 중인지를 저장하는 변수입니다.

  Method
1. destroy()
2. currentDelta() - Draggable element의 left/top 위치를 리턴합니다.
3. initDrag(event)
- Draggable에 mousedown 이벤트가 발생한 경우 호출됩니다.
- draggable에 포함되는치, form element인지를 체크한 후, 현재의 마우스 위치와 실제 화면상의 위치 값을 저장한 후 Draggables.activate를 호출합니다.

4.
startDrag(event)
- Draggable.updateDrag에서 호출됩니다.
  1. dragging 값을 true로 설정합니다.
  2. zindex, ghosting, scroll과 관련된 option이 있는 경우 해당 option과 관련된 작업을 수행합니다.
  3. Draggables에 onStart이벤트가 발생했음을 알립니다.
  4. options에 starteffect가 있는 경우 starteffect를 수행합니다.
5. updateDrag(event, pointer)
- Draggables.updateDrag에서 document의 mousemove 이벤트에 등록된 updateDrag에 의해서 호출됩니다.
  1. this.dragging이 설정되어 있지 않은 경우 startDrag를 호출합니다.
  2. Droppables.show를 호출하여 현재 해당하는 Droppable이 있는 경우에 대한 처리를 수행합니다.
  3. Draggable을 이동시킵니다.
  4. options.scroll과 관련된 항목을 처리합니다.
6. finishDrag(event, success)
- mouseup 또는 esc키가 눌린 경우 호출됩니다.
  1. this.dragging을 false로 설정합니다.
  2. mouseup인 경우, Droppables.fire를 호출하여 Drop 이벤트에 대한 처리를 수행하게 합니다.
  3. Draggables.notify를 호출해서 onEnd이벤트가 발생했음을 알립니다.
  4. revert인 경우, startDrag시 저장하였던 시작점으로 복귀시킵니다.
  5. drag가 완료되었으므로 zindex를 복원시킵니다.
  6. endeffect설정이 되어있으면 이를 호출해줍니다.
  7. Draggables.deactivate를 호출하여서 활성중인 Draggable이 없음을 설정합니다.
7. keyProcess(event) - esc키가 눌린 경우, finishDrag를 호출합니다.
8. endDrag(event) - mouseup이벤트가 발생한 경우, stopScrolling()과 finishDrag를 호출합니다.
9. draw(point)  - mouse 이동에 따른 draggable의 이동 처리를 수행합니다. (repaint코드라고 보시면 될 듯)
10. stopScrolling()
11. startScrolling(speed)
12. scroll()
13. _getWindowScroll(w)

※ scrolling의 경우 제가 정확하게 파악하지 못해서 생략했습니다. ^^;;


관련링크
  Script.aculo.us - Draggable, Draggables, Droppables

2007년 4월 11일 수요일

IE에서 Prototype.js라이브를 사용하여 Ajax로 통신할 때 느리다면..

prototype.js라이브러리를 사용하여 Ajax로 데이터를 전송하는데 IE에서 시간이 너무 걸리는 문제가 발생하였습니다. Firefox에서는 2초를 걸리던게, IE에서는 무려 89초가 걸리더군요.
사용자 삽입 이미지

위대한 alert()를 사용하여 시간을 측정해보았는데, 다음의 코드에서 걸리더군요.
if (typeof this.options.parameters == 'string')
    this.options.parameters = this.options.parameters.toQueryParams();
추적을해보고 이리저리 시험을 해본 결과 Ajax.Request를 사용할 때 parameter로 준 값이 문제가 되었습니다.
parameter의 값을 string타입으로 encodeURIComponent를 사용하여 encoding하고 넘겨준 경우
  1. this.options.parameters.toQueryParams()를 거치면서 decoding 후,
  2. Hash로 바꾸게 됩니다.
동일한 코드를 Firefox 및 IE에서 타지만, IE에서만 유독 decoding시에 많은 시간이 소모되더군요.
해당부분의 경우 Hash로 넘겨주게 되면(encoding안 한 상태에서) 88초 정도의 시간을 줄일 수 있었습니다.

P.S. 이문제를 해결하기 위해서 시간을 출력하는 코드를 찾아봤는데 Date 클래스의 parse()가 유용하더군요.
Date.parse(new Date().toString());
출력되는 값은 milliseconds단위로 출력되게 됩니다.

P.S.2 이자리를 빌어, 도움을 주신 J모 과장님과 L모 대리님께 감사를, 저 때문에 고생하신 개발팀원 여러분께 사과를 (__) ....

P.S.3 Ajax의 parameters로는 URL-encoded string Hash-compatible object를 사용할 수 있습니다.

2007년 3월 23일 금요일

Google의 Prettify 프로젝트

Google에서 재미난 오픈소스 프로젝트가 나왔습니다.
Google-Code-Prettify라는 프로젝트인데요. JavaScript를 이용해서 브라우져단에서 C 스타일의 코드를 예쁘게 출력해주는(Syntax highlighting) 프로젝트입니다.

프로젝트 명: Google-Code-Prettify
라이센스 : APL(Apache Project License) 2.0입니다.
지원하는 언어 : C, Java, Python, Bash, SQL, HTML, XML, CSS, Javascript, and Makefiles
사용하는 방법:
  1. 먼저, 프로젝트 페이지에서 prettify.js와 prettify.css 소스 파일을 다운로드 받습니다.
  2. 다운로드받은 소스를 사용할 페이지에 선언해주구요.
  3. 출력할 코드를 code, pre, xmp 태그안에 넣습니다.
  4. 1에서 선언한 태그의 class를 prettyprint로 설정합니다. 예를 들자면 <pre class="prettyprint"></pre>와 같은 형태로요.
  5. onload 이벤트에 prettyPrint()를 호출해주면 하이라이팅된 소스를 보실 수가 있습니다.
다음은 xmp를 사용해서 html소스를 출력하는 샘플 코드입니다.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test Page</title>
<script type="text/javascript"src="prettify.js"></script>
<link type="text/css" rel="stylesheet" href="prettify.css" media="screen"></link>
</head>
<body onload="prettyPrint();">
    <xmp class="prettyprint">
        <html>
        <head></head>
        <body>
            <div id="sample"></div>
        </body>
        </html>
    </xmp>
</body>
</html>

그리고, 다음은 해당코드를 prettify.js를 사용해서 출력해본 화면입니다.
사용자 삽입 이미지
스타일의 경우 prettify.css를 수정하면 되므로 원하는 스타일대로 설정도 가능합니다.

장점 : 다양한 언어를 지원하는 오픈소스 프로젝트입니다. 클라이언트에서 Syntax highlighting을 처리할 수 있기 때문에 서버단의 변경없이 쉽게 추가가 가능합니다.

단점 : 클라이언트 단에서 char단위의 파싱이 발생하기 때문에 많은 양의 소스를 파싱할 수 없으며, (소스 내부에서 250ms 단위로 체크해서 반응이 없을경우 종료시킵니다.) 비용이 많이든다는 문제점이 있습니다.

출처:

2007년 1월 9일 화요일

Prototype.js사용 시 Array에서 에러가 나는 경우..

Prototype.js를 사용하는 경우 가끔씩, Array처리하는 코드에서 에러가 발생하곤 하였습니다. 이 때 debugging을 해보면 Array의 마지막에 Array를 구동하는 function의 코드가 나오는게 원인이었습니다.

발생하는 부분이 for(index in loop)의 'for in' style의 루프에서만 발생하여서 'for in' 루프를 사용하지 않았었는데요. Ajaxian에 관련한 기사가 있었네요.

Problem
JavaScript에서 다음과 같은방법 Associative Array를 사용하는 경우에 Array.length값은 갱신이 되지 않습니다. 따라서, for in 스타일의 루프를 사용하게 되면 값을 length가 0이므로 오동작하게 됩니다.
var hardcoreBands = new Array();
hardcoreBands["mathyGoodnes"] = "Dillinger Escape Plan";
hardcoreBands["legendary"] = "Converge";
hardcoreBands["fashionistas"] = "Every Time I Die";

alert(hardcoreBands.length);
for in 스타일의 루프를 사용하지 않고, for(var i=0; i < array.length; i++) 스타일의 루프도 동작을 하지 않습니다.
User inserted image
Solution
Associative Array를 생성해서 사용하는 경우에 String을 key로 사용하지 않고 index를 사용합니다. 또는, Prototype.js의 Hash클래스를 사용하는 것이 나을 것 같습니다.

출처 : Javascript Associative Arrays considered harmful

2007년 1월 4일 목요일

Dojo Offline Toolkit이 제공된다고 합니다.

User inserted image


Ajaxian에 Dojo Offline Toolkit Kicks Off라는 기사가 올라왔습니다.
Dojo Offline Toolkit이란 사용자가 오프라인 상에서도 작업할 수 있는 기능을 제공합니다.
  1. 사용자가 B사이트에 들어갔을 때, 'Work Offline'이라는 버튼을 봅니다. (오~ 뭘까? 하며 클릭을 해야하죠~)
  2. 클릭 시, 창이 하나 뜨면서 '이 Web Application'은 오프라인에서도 사용가능해!'라는 강렬한 메시지를 전달합니다. (미소를 지으며, 그래 나도 오프라인에서 사용할 수 있으면 좋겠어라며 사용자는 다시 또 클릭을 합니다.)
  3. 사용자의 OS에 따라서 100k~300k 정도 되는 프로그램을 다운로드 받아 설치를 합니다. (인스톨러가 따로 제공이 됩니다.)
  4. 설치된 뒤에는 Web applicatoin의 URL을 북마크 해놓거나 링크를 드래그해서 바탕화면에 깔게합니다.
  5. 온라인 상에서 사용자가 사용하더라도 로컬에 저장이 저장하고 싶은게 있다면 로컬에 저장이 가능합니다. 오프라인인 경우에도 Web Application 링크를 클릭하거나 북마크를 클릭하거나 URL을 입력하고 들어감으로 Web Application을 실행시킬 수 있습니다.
  6. 실행을 시키면, 마법과 같이(Ajaxian에 그렇게 되어 있군요 ㅎㅎ) 온라인상에서의 Web Application이 화면에 나타납니다. 오프라인임에도 불구하고 !!
  7. 사용자의 로컬에 저장되어 있는 데이타는 언제라도 읽어들일 수 있고 다시 수정하여 로컬에 저장할 수 있습니다.
  8. 또한, 온라인에 다시 연결될 경우 Dojo Offline은 이를 알아채고 로컬에 있는 데이타들을 웹서버에 보낼 수 있게 해줍니다.
로컬에서의 저장은 Dojo Storage를 사용하게 되는데, 사용자의 허락하에 부라우져에서 몇 백KB에서 MB까지 저장이 가능합니다. Dojo Offline Toolkit은 IE, Firefox, Safari에서 동작이 가능할 것이며(will work라 되어 있네요), Windows, Linux/x86, Mac OS X/Universal Binary에서 구동될 수 있다.(여기도 will run)


상당히 재미있으나 강렬한 기능일 것 같습니다만, Dojo를 사용해야한다는 점이...걸리네요.(언제 또 다 공부할지 ㅠㅠ)

출처 :

2006년 12월 29일 금요일

압축과 통합을 통한 js, css 다운로드 최적화

Ajaxian에 Maximizing Performance with Compression and Combination이라는 기사가 있더군요. [Ajaxian의 밀린 기사 읽는 중이랍니다. ^^;;] 이전에 Vox.com 분석할 때 Vox.com의 js 및 css를 자동으로 통합해서 배포하는것 같다는 얘기를 한 적이 있습니다. 이와 비슷한 방법이기는 하나 Ajaxian의 Maximizig Performance...도 js와 css를 자동으로 통합해서 배포하는 방법에 대해서 설명하고 있습니다.

큰틀은 다음과 같습니다.
  • js 및 css 파일들을 request에 따라 하나의 통합된 파일로 생성합니다. (Combination)
  • 이 통합 파일을 gzip으로 압축하여 배포합니다.
  • 그리고 압축파일을 디스크에 캐싱해 둡니다.
.htaccess파일을 수정하여 css나 js파일이 여럿 나오는 경우 이를 combine.php로 redirect시켜서 처리하도록 하고 있군요. 솔루션 자체도 오픈되어 있습니다.

RewriteEngine On
RewriteBase /
RewriteRule ^css/(.*\.css) /combine.php?type=css&files=$1
RewriteRule ^javascript/(.*\.js) /combine.php?type=javascript&files=$1

솔루션을 공개해주신 rakaz님께 감사를~~ ^^

출처 :


2006년 12월 9일 토요일

Flash를 이용한 Clipboard

Jeffothy's Keyings에 소개되어 있는 글입니다.

사용자들이 Ctrl+C, Ctrl+V를 사용하여 웹의 컨텐츠를 복사해서 붙여넣고 싶어하는 기능은 웹 애플리케이션 개발에 기본적인 사항 중에 하나입니다. IE 및 Firefox의 경우에도 모두 지원합니다만, Firefox의 경우에는 configration file을 사용하여 Clipboard를 사용할 사이트에 clipboard 사용을 허락하는 과정을 한번 더 거쳐야 합니다.

당연히, 사용자들이 싫어할 수 밖에 없겠죠. 이를 해결하기 위해서 나온 방법이 웹에서 90% 이상 설치되어 있는 Flash의 Clipboard기능을 이용하는 것입니다. 사용자가 특정한 컨텐트를 선택한 다음 Ctrl+C를 눌렀을 때 선택한 내용을 읽어서 Flash의 System.setClipboard()에 설정하기만 하면, System의 Clipboard에는 컨텐트의 내용이 들어가게 되겠죠.

Jeffothy's KeyingsClipboard Copy에 나와 있는 코드는 다음과 같습니다.
User inserted image

swf의 코드는 따로 나와있지 않습니다. [제가 볼 줄 모른것일 수도 있습니다. ^^;;]
* swf파일과 해당 소스는 GPL로 공개되어 있습니다.
** 본문 글에는 Opera 8.5에서는 지원이 되지 않았다고 나와있네요.


출처 및 관련된 내용:

2006년 12월 6일 수요일

graft()

DOM을 사용하여 html을 생성해내는 코드를 작성할 때 부딪치는 가장 큰 문제가 상당히 많은 양의 코딩이 필요하다는 점입니다. 코드가 많아질 수록 당연히 Bug가 생길 가능성도 증가하게 되겠죠. 이를 해결하기 위해서 나온 방법이 html구조를 쉽게 표현하는 구조와 이를 파싱하여 DOM으로 자동 생성해주는 코드를 만드는 방법입니다.
User inserted image

생성할 html 코드


Graft function이 이러한 해결책을 위해서 나온 function인데요.
동작원리는 간단합니다. Array로 구성된 Html구조를 파싱하면서 recursive하게 DOM객체를 생성하거나 attribute를 설정해주는 코드입니다.
User inserted image

Grant로 파싱할 대상인 html array

사용방법은 간단합니다. []로 태그를 감싸는데요. Array의 처음은 태그의 이름이 두번째는 태그에 들어갈 text나 속성(Hash Object인 {})이 들어갑니다. 동일한 html을 생성하는 DOM 생성 코드와 비교하면 상당히 많은 줄의 차이를 갖습니다.
User inserted image

DOM 생성 코드


대략 25줄대 2~3줄 정도의 차이니까, 코딩양으로 본다면 엄청난 양을 줄일 수 있는 장점이 있습니다.
Grant의 실제 코드를 보면 다음과 같습니다.

User inserted image
User inserted image



graft의 경우에는 release된 version이 없습니다. function만 올려진 상태구요. 댓글 달린 것과 경험상 봤을 때 setAttribute를 사용하여 Class설정하는 코드는 IE에서 동작하지 않을겁니다. className으로 설정하도록 수정이 필요하구요.

검증이 100% 안된코드로 보시고 작업하셔야 될 걸로 생각되네요..
그래도, 이런게 어딥니까 ^^

출처 :
P.S. 1:
graft란 단어는 '접목하다', '이식하다'라는 의미를 가진 단어입니다. (사전 찾아봤습니다. ^^;;)

P.S. 2:
Ajaxian에 최근에 올라왔던 DOMTool(html을 코드를 읽어들인 다음 동일한 html을 생성해내는 DOM 생성 코드를 만들어내는 툴입니다.)에 대한 기사를 읽다가 Graft가 생각나서 정리해봤습니다.

P.S. 3:
Graft()는 Sean Burke씨와 그의 책, Higher Order JavaScript에 나와있는 코드를 기반으로 하여 만들어졌습니다. [얼핏 기억으로는 Perl로 만들었다는 글을 본 것 같기도 합니다. 미확인 정보 --;;]

2006년 11월 14일 화요일

Mr.Proto님의 Carousel 라이브러리(Scrolling-Object)

User inserted image
한 눈에 봐도 강렬한 뽀스가 느껴지는 Mr.Proto님(본명은 Sébastien Gruhier)은 13년간의 C++과 Java로  OO계를 주름 잡으셨다가 최근에 Ruby on Rails로 전향하셨다고 합니다. 흰눈썹에서 품어져 나오는 이미지는 그의 나이를 궁금케 하는군요. ^^

Bookmark manager, Transparent message, Prototype window, Prototype carousel 라이브러리가 Mr.Proto님의 홈페이지에서 제공되고 있습니다. 이번에 살펴볼 라이브러리는 Prototype carousel로서 스크롤링 라이브러리입니다.

Consulting, Training, Development Ruby on Rails/AJAX/JavaScript가 직업이라고 되어 있는데 현재는 free라고 되어있네요. 코드를 보시면 알겠지만 이 분의 코드는 상당히 깔끔하게 객체화도 잘되어있고, 읽기도 편합니다.

먼저, 코드의 Outline을 살펴보면 다음과 같습니다.

User inserted image

위의 property 중에 대부분의 코드는 option항목을 저장하기 위해서 사용됩니다.
스크롤링이 되는 대상들은 페이지 로딩 시에 로딩이되고 각각이 li태그로 감싸져서 반영이 됩니다. 이들 li태그들은 가로방향으로 생성이 됩니다. 다음은 li태그임을 보여주기 위해서 모든 css를 제거한 화면입니다.

User inserted image

css를 모두 제거한 화면


이 화면에 carousel.css를 적용하게 되면 다음과 같이 가로바 형태의 모습이 나오게 됩니다. 여기에서 다시 appliecation.css를 적용하여서 스크롤링하기 위한 Object만 나오게 합니다.

이 때 사용하는 방법이 li들이 저장되어 있는 ul객체를 div로 감싸고 이 div의 크기를 줄인다음 overflow:hidden으로 처리함으로써 나머지 영역을 클리핑하게 됩니다.
User inserted image

carousel.css만 적용한 상태로 div에 overflow:hidden이 적용되어있으나 width는 정하지 않은 상태입니다.


User inserted image
이 상태에서 스크롤 버튼을 누를 때 li의 위치만 변경시켜주면 스크롤이 되게 됩니다. 내부에서는 Clipping되어 안보이기는 하나 li태그들의 위치가 좌우로 움직이게 됩니다. 이 때 사용자는 Clipping 영역만 보기 때문에 스크롤이 되었다고 느끼게 되는거죠.

new Effect.MoveBy(this.carouselList,
      0, delta * this.elementSize, this.options.animParameters);

위의 코드는 script.aculo.us이 코드로 this.carouselList element를 x좌표 0, y좌표 delta * this.elementSize만큼 옮겨줍니다. this.options.animParameters는 script.aculo.us에서 사용되는 설정값들을 저장하는 array들입니다.

개념 자체는 상당히 simple합니다만, 실제 적용하기 위해서는 좌표 계산등에 대해서 상당히 신경써야 되는 부분이 있습니다.  Mr. Proto님께 감사의 마음을 갖고(센스와 디자인 감각도 상당함을 느끼세요) 라이브러리를 사용하셔야 합니다. ^^

  • 이 라이브러리는 Bill Scott's Carousel Component(YUI 라이브러리 사용)의 Prototype/script.aculo.us버전입니다.
  • 버전은 0.26입니다.
  • 라이센스는 MIT 라이센스입니다.
  • IE6, Firefox(Mac, PC), Opera, Camino, Safari에서 테스트되었습니다.
출처 : http://www.xilinus.com/