티스토리 뷰

라이브러리 개조 : LightBox2 - 2화

이제 LB2를 까서 보자.

다운받은 디렉토리 구조 내, dist/js/lightbox.js를 자신이 가장 잘 사용하는 에디터나 IDE로 로드하고, 찬찬히 살펴 보자. 역시 2번째 라벨에 걸맞게 주석들이 깔끔하게 잘 정리되어 있고, 구조 또한 배울게 많게 잘 만들어져 있다. 아마 자바스크립트를 어느정도 경험이 있는 분들은 분명히 그렇게 느낄 것이다.

이 중 아까전 크롬내 콘솔창에서 lightbox를 치면 나오던 오브젝트들을 기억하는가? 그 오브젝트가 일단 어디에서 선언되어 export 되었는지 확인해보자. 잘 보면, Lightbox.prototype.build 부분에서 export가 수행되는 것을 추측할 수 있다. 아래는 Lightbox.prototype.build의 상위 부분이다.

var self = this;
$('<div id="lightboxOverlay" class="lightboxOverlay"></div><div id="lightbox" class="lightbox"><div class="lb-outerContainer"><div class="lb-container"><img class="lb-image" src="https://t1.daumcdn.net/cfile/tistory/2361A64256E6C37F05" /><div class="lb-nav"><a class="lb-prev" href="" ></a><a class="lb-next" href="" ></a></div><div class="lb-loader"><a class="lb-cancel"></a></div></div></div><div class="lb-dataContainer"><div class="lb-data"><div class="lb-details"><span class="lb-caption"></span><span class="lb-number"></span></div><div class="lb-closeContainer"><a class="lb-close"></a></div></div></div></div>').appendTo($('body'));

// Cache jQuery objects
this.$lightbox       = $('#lightbox');
this.$overlay        = $('#lightboxOverlay');
this.$outerContainer = this.$lightbox.find('.lb-outerContainer');
this.$container      = this.$lightbox.find('.lb-container');

// Store css values for future lookup
this.containerTopPadding = parseInt(this.$container.css('padding-top'), 10);
this.containerRightPadding = parseInt(this.$container.css('padding-right'), 10);
this.containerBottomPadding = parseInt(this.$container.css('padding-bottom'), 10);
this.containerLeftPadding = parseInt(this.$container.css('padding-left'), 10);

self 변수 정의 부 밑에 보면 이 라이브러리가 <body>에서 어떤 모습으로 추가되는지 간략하게 볼 수 있고, 차후 이것을 변경하면 UI구조를 커스터마이징 가능하다는 것을 유추할 수 있다. 또한, 아래의 $로 시작되는 오브젝트들이 아까 눈여겨 봤던 것들이다. 즉, 이곳에 함수를 자체적으로 만들어 선언한다면, 다른 위치에서 lightbox.[함수] 형태로 실행할 수 있다는 것이다.

그렇다면, <a> 태그를 선택하여 이미지가 상세로 출력되는데, 어떤 부분에서 처리를 할 것인가?
바로 윗부분 코드 중 하나인 Lightbox.prototype.enable에서 click이벤트에 대한 정의를 하는 것을 알 수 있다.

Lightbox.prototype.enable = function() {
    var self = this;
    $('body').on('click', 'a[rel^=lightbox], area[rel^=lightbox], a[data-lightbox]
    , area[data-lightbox]', function(event) {
        self.start($(event.currentTarget));
        return false;
    });
};

click 이벤트를 받아 self.start라는 함수를 실행하는데, 이 함수가 실제 실행되어 이미지 팝업을 실행하는 주체라 볼 수 있다. 라이브러리 내부의 Lightbox.prototype.start로 정의되어 있는 위치로 가서, 함수 내부 소스를 한번 살펴 보자. 간략하게 플로우를 설명하자면, 아래의 도표를 확인하자.

Lightbox.prototype.start
초기화
DOM내 동일한 data-lightbox 이름을 가진 태그들을 가져옴
앨범에 등록
선택한 요소가 앨범내 어떤 위치인지 확인
화면 사이즈 확인 및 출력할 팝업 사이즈 정의
선택한 요소부터 이미지 팝업 시작

위와 같은 플로우로 Lightbox.prototype.start가 실행될 것이며, 직접 데이터를 입력하기 위해서는 albumimageNumber이 가장 중요한 오브젝트라는 것을 알 수 있다.
바로 Lightbox.prototype.start를 기반으로 우리가 원하는 방향으로 수정하는 것이 오늘의 목적이라고 생각하면 되겠다.

새로이 만들어질 함수의 이름은 외부에서 접근할 경우 imgeViewer로, 내부에서는 startByImgeList라 잠정적으로 정하고 진행토록하겠다. 먼저 외부에서 접근할 수 있게 Lightbox.prototype.build 부분에서 아래와 같은 코드를 추가하자.

this.imgeViewer = function(imgeList, index){
    self.startByImgeList(imgeList, index);
}

위 코드 내부에서 쓰는 selfthis나 지금은 같겠지만, Lightbox.prototype.build 다른 코드 부분을 잘 읽어 보시고 self와 this를 나눠서 사용한 이유를 아신다면 당신은 자바스크립트의 이해가 높을 것이다. 저렇게 사용하는 이유는 이벤트 내부의 암시적 함수 선언된 부분의 함수 내부는 this를 event로 인식하기 때문에, self로 따로 위에서 정의하여 준비하는 것이다.

외부에서 접근할 함수 명은 imgeViewer라 정의했고, JSON Array type로 실제 출력할 데이터 정보와 이 데이터들 중 가장 먼저 출력할 위치를 index로 받는 것으로 하였다. 그리고, 라이브러리 내부에 startByImgeList 함수를 만들어 이를 호출하도록 할 것이다.

이전에 분석했던 Lightbox.prototype.start의 밑에, 아래의 코드를 추가하자.

Lightbox.prototype.startByImgeList = function(imgeList, index) {
    var self    = this;
    var $window = $(window);

    $window.on('resize', $.proxy(this.sizeOverlay, this));

    $('select, object, embed').css({
      visibility: 'hidden'
    });

    this.sizeOverlay();

    this.album = [];
    var imageNumber = 0;

    function addToAlbum(imge) {
      self.album.push({
        link: imge.imgePath,
        title: imge.imgeNm
      });
    }

    for (var i = 0; i < imgeList.length; i = ++i) {
        addToAlbum(imgeList[i]);
        if (i == index) {
          imageNumber = i;
        }
    }

    // Position Lightbox
    var top  = $window.scrollTop() + this.options.positionFromTop;
    var left = $window.scrollLeft();
    this.$lightbox.css({
      top: top + 'px',
      left: left + 'px'
    }).fadeIn(this.options.fadeDuration);

    this.changeImage(imageNumber);
}

추가한 소스를 천천히 잘 읽어보자, 가장 눈여겨 봐야할 곳은 album을 생성하는 부분인 addToAlbum 함수 선언부이다. 이부분은 JSON ARRAY이로 만들어진 데이터를 하나씩 가져와 album에 넣기 위한 부분이며, JSON 배열 내 각 Object의 키값이 imgePath, imgeNm을 가져와 각각 출력할 이미지 위치, 출력할 이미지의 제목을 넣는다.

즉, JSON ARRAY 구성 시, 이를 염두하고 구성해야 하는 것이다.
이제 수정된 라이브러리를 더미 페이지를 만들어 적용해 보고, 크롬 콘솔창에 아래와 같은 스크립트를 실행해 보자.

가장 먼저 중요한 것은 <script src="js/lightbox.js"></script>html page에 넣어 스크립트를 적용할 시, jquery와 동일한 위치에 있는 해더에 값을 넣게 된다면, 지연적용으로 인해 lightbox 기능이 전혀 수행되지 않는다. 이 경우, <body> 태그 밑에 넣어야 한다.(이왕 이면, </html>위에 넣는 것이 좋다.) 아니면, jquery와 한몸으로 이뤄진 js를 수정하여 써도 무방할 듯 보인다.

var imgList = [
    {imgePath:'http://www.san-x.jp/characters/image/main/m-rila.jpg',imgeNm:'리락쿠마 좋아'},
    {imgePath:'http://images4.fanpop.com/image/photos/21600000/Rilakkuma-wallpaper-kawaii-21685723-1024-768.gif',imgeNm:'리락쿠마 완전 좋아'},
    {imgePath:'http://static.tumblr.com/2rdw8gm/bhpm630aa/rilakkuma-wallpaper.gif',imgeNm:'리락쿠마 많이 좋아'}
];

lightbox.imgeViewer(imgList, 1);

외부의 링크를 그대로 활용하여 만들어본 예제이다. 위의 스크립트가 바로 실행되지 않는다면, 페이지 내에 <script src="js/lightbox.js"></script>위치를 꼭 확인해 보도록 하자.


댓글
댓글쓰기 폼