34개의 클래스들이 많아 보이지만

라이브러리, 에디터, 플러그인 클래스의

3개의 그룹으로 나누어 정리할 수 있고,

먼저 라이브러리에 대하여 정리한다.


라이브러리에서 가장 먼저 확인되는 클래스는 bkExtend이다.

JS는 클래스를 함수로 이용하여 사용하기 때문에 혼동할 수 있는데

bkExtend는 클래스라기 보다는

개체의 속성(변수와 함수)을 복사하는 함수에 가깝다.

bkClass.extend = function(C) {
   var A = function() {
       if (arguments[0] !== bkClass) {
           return this.construct.apply(this, arguments)
       }
   };
   var B = new this(bkClass);
   bkExtend(B, C);
   A.prototype = B;
   A.extend = this.extend;
   return A
};  

bkClass는 bkExtend와 prototype으로

클래스 상속 메서드(extend)를 구현한 것이다.

다른 언어에서 클래스 상속이란

부모의 속성을 자식이 물려 받는 것이고,로

JS는 클래스 속성을 복사(또는 클래스 둘을 합친다)하는 개념으로 사용한다.

JS는 상속의 개념이 없기 때문에

복사 개념(extend)을 이용하여 흉내 낸 것으로 볼 수 있다.

JQuery의 extend와 비슷하다.

프로토타입(prototype)에 대한 내용은 http://www.nextree.co.kr/p7323/ 참조


bkClass의 두 가지 기능 중 하나가 이상에서 언급한 상속(extend)이고

나머지 하나는 생성자(construct) 이다.

JS는 클래스가 없기 때문에 생성자도 없다.

하지만 클래스가 생성될 때 여러가지 처리를 해야 할 필요가 있다 (생성자).

따라서, NicEdit는 extend 메서드를 호출할 때를

생성자가 실행되는 시점으로 보고 construct 함수를 호출한다.

다음 코드에서 보듯이 빈 construct 함수를 생성하고

extend 에서 호출한다.

function bkClass() {}
bkClass.prototype.construct = function() {};

bkClass.extend = function(C) {
   var A = function() {
       if (arguments[0] !== bkClass) {
           return this.construct.apply(this, arguments)
       }
   };
   var B = new this(bkClass);
   bkExtend(B, C);
   A.prototype = B;
   A.extend = this.extend;
   return A
}; 

이 내용을 복사해서 가진 클래스(자식, 예: nicEditor)에서는

construct에 필요한 내용(코드)를 추가하여,

생성자처럼 사용하는 것이다.

var nicEditor = bkClass.extend({
   construct: function(C) {
       this.options = new nicEditorConfig();
       bkExtend(this.options, C);
       this.nicInstances = new Array();
       this.loadedPlugins = new Array();
       var A = nicEditors.nicPlugins;
       for (var B = 0; B < A.length; B++) {
           this.loadedPlugins.push(new A[B].p(this, A[B].o))
       }
       nicEditors.editors.push(this);
       bkLib.addEvent(document.body, "mousedown", this.selectCheck.closureListener(this))
   }, 

bkClass.extend가 실행되면

해당 클래스의 생성자가(construct) 실행되고,

해당 클래스(함수)내에 있는 변수와 함수가 복사 되게 된다.

클래스 상속(복사)과 같은 일이 발생한다.

따라서, bkClass가 가장 상위의 클래스 같은 역할을 하게 된다.

이 글에서는 상속 받는다는 표현(bkClass.extend)을 사용할 것이다.


BkClass에서 상속받은 (var bkElement = bkClass.extend(...) )

bkElement는 NicEdit에서

동적으로 생성하는 클래스(버튼, 판넬 등 HTML 태그)들을 감싸는 클래스이다.

예로, 버튼(button)에 CSS를 적용할 경우 addStyle이라는 함수를 만들고

그냥 addStyle를 호출할 경우 addStyle(해당버튼, 스타일값)으로 지정해야 한다.

이렇게 사용하는 것을 구조화 프로그래밍이라고 한다.

그렇지 않고

해당버튼.addStyle(스타일값)

이렇게 클래스의 메서드로 사용하면

객체지향 프로그래밍 방식으로 개발한다고 할 수 있다.

bkElement는 많이 사용하는 함수들을 메서드로 가지고 있어

해당 HTML 태그에서 자유롭게 사용할 수 있게 한다.


addStyle함수는 JQuery에서는 $(해당버튼).css(스타일값)로 사용한다 (addStyle도 있음).

JQuery의 $와 비슷한 기능은 $BK( + bkElement)함수이다. 


bkElement의 주요 메서드는

이벤트 추가(addEvent), CSS 클래스 추가(addClass) / 삭제(removeClass),

CSS 속성 지정(setStyle), HTML 속성 지정(setAttributes) 등으로

모두 HTML 태그 지정에 유용한 것들로 구성되어 있다.


구체적으로 살펴보면,

bkElement의 addEvent는 실제로는 bkLib의 addEvent를 호출한다.

bkLib의 addEvent를 클래스 내에서 편리하게 사용하기 위해

bkElement의 메서드로 구성한 것이다.

즉, bkElement를 상속한 클래스는 this.addEvent()로 호출하고

그렇지 않은 클래스나 함수에서는

bkLib.addEvent()를 호출하여 사용하면 된다.

어떤 방식이 좋다고 말하기 어렵고,

객체 지향과 구조화 프로그램의 차이라고 정리할 뿐이다.


bkElemen의 사용 예를 확인해 보면 다음과 같다.


var A = new bkElement("DIV").setStyle({width: (parseInt(B.getStyle("width")) || B.clientWidth) + "px"}).appendBefore(B); 


bkElement 파라메터로 DIV가 주어지는데

bkElement는 bkClass에서 상속 받았기 때문에

생성자(construct)가 실행된다.

bkElement의 생성자에서는 주어진 파라메터를

document의 createElement를 이용하여 생성한다.

var bkElement = bkClass.extend({
    construct: function(B, A) {
        if (typeof(B) == "string") {
            B = (A || document).createElement(B)
        }
        B = $BK(B);
        return B
    },

즉, 위 코드는 HTML DIV 태그를 생성하고,

bkElement로 포장해서(WRAP- $BK) 반환한다.

bkElement에서 제공되는 메서드로 스타일(setStyle)을 지정하고

B 클래스 다음 위치(appendBefore)에 배치하게 된다.

(JQuery-insertBefore와 매우 유사하게 사용한다. )

위 코드를 일반 JS 코드로 구현하면 다음과 같다.

(실제로는 조금 더 복잡하게 처리 해야 한다.)

           
            var A = document.createElement("DIV");
           
            A.style.width = (parseInt(B.style.width) || B.clientWidth) + "px";
           
            B.parentNode.insertBefore(A, B); 



bkLib는 많이 사용되는 함수의 묶음 클래스로 볼 수 있다.

자바의 Static 클래스처럼 bkLib.메서드()로 호출해서 사용한다.

배열화 하거나(toArray), 배열에서 값을 찾기(inArray),

이벤트 추가(addEvent) / 삭제(cancelEvent) 등의 기능을 가지고 있다.


bkEvent 클래스는

이벤트를 추가하고(addEvent), 실행하는(fireEvent) 클래스 이다.

실제 JS의 이벤트와는 차이가 있다.

앞서의 이벤트들은 모두 HTML 태그들에

이벤트를 적용해서 발생하는 것이고,

bkEvent의 addEvent는

프로그램(NicEdit)이 지정된 이벤트들을 가지고 있다가

실행하라고 하면 그때 서야 프로그램 상에서 호출되는 이벤트이다.

즉, bkElement와 bkLib에서 지정된 이벤트 함수는

사용자의 행동에 의해 시스템(웹 브라우저)에서 호출되고,

bkEvent에서 지정된 함수는

함수 리스트(eventList)에 보관하고 있다가

프로그램 상에서 호출된다.

예로,

에디터에는 굵게, 이탤릭체 등 다양한 편집 버튼이 있다.

이 버튼들을 클릭하는 것은 bkElement의 addEvent를 이용하여 함수를 지정하고,

사용자가 마우스로 선택하면 해당 함수가 실행이 된다.

하지만, 사용자가 에디터에서 작업하다 다른 곳을 클릭한 경우

에디터는 버튼을 누를 수 없게 만들어야 한다 (Disable).

에디터에는 많은 버튼들이 있는데

이 모든 버튼 클래스에 Disable 이벤트를 만들고 등록했다가 (addEvent)

사용자가 에디터에서 작업하다 다른 곳을 클릭한 경우 이 이벤트들을

호출하여(fireEvent) 버튼을 사용할 수 없게 만들어 준다.

이 방식을 쓰지 않으면

모든 컨트롤의 함수를 직접 호출해야 하는 불편함이 있다.


$BK는 함수로 보는 것이 적당한데

파라메터가 문자열이면 해당 문자열을 ID로 HTML 태그를 찾아서 반환하고 (getElementById)

아니면 HTML 태그 클래스로 보고 bkElement로 포장하여 반환한다.

bkElement로 포장한다는 말은

HTML 태그이지만 bkElement의 메서드들을 사용할 수 있다는 것이다.


마지막으로 두 개의 내부 함수(closure)를 사용한 예가 있는 데,

내부 함수에 대한 개념은 찾아보기 바라며

prototype으로 함수에 두 개의 기능을 추가 하였다.

closure, closureListener이다.

이름이 내부 함수(closure)이지 기능이 내부 함수이지는 않다.

내부 함수 기법을 사용해서 이름을 그렇게 붙인 것 같고,

실제 용도는 전혀 다르다.

둘 다 이벤트 호출시 this를 특정 클래스로 나타내기 위해 사용하는 것이다.

즉, 버튼을 클릭(click)하면 해당 이벤트 내에서 this는 버튼이다.

버튼을 bkElement로 생성한 경우

this는 버튼이 아닌 버튼을 생성한 bkElement가 되어야 한다.

둘의 차이점은 closure는 파라메터 없이 호출되는 경우이고,

closureListener는 파라메터를 필요로 하는 경우에 사용한다.

예로, JS에서는 mousedown이벤트에서 event개체가 파라메터로 넘어온다.

function mousedown(event) {

처리 ~

}

이 event개체를 파라메터로 받아서 사용할 경우 closureListener,

없이 사용할 때는 closure로 사용하면 된다.

파라메터로 지정할 필요 없이

window.event로 사용해도 되지만, 이 개체는 Firefox에서 지원되지 않는다.


사용예

      bkLib.addEvent(document.body, "mousedown", this.selectCheck.closureListener(this))

      bkLib.addEvent(F, "submit", this.saveContent.closure(this)) 


selectCheck와 saveContent는 함수로 이밴트 핸들러이고

Function.prototype로 함수 원형을 수정하였기 때문에

이상과 같이 사용자 함수 뒤에 추가하여 지정하는 식으로 사용한다.


정리하면,

NicEdit를 구성하는 기본 라이브러리(클래스)는

클래스의 첫 부모(시조) bkClass(Object),

NicEdit용 HTML 태그 컨트롤을 위한 부모 bkElement,

NicEdit용 HTML 태그 컨트등에 이벤트를 보내기 위한 bkEvent,

잡다하게 사용하는 라이브러리 bkLib,

마지막으로 이벤트의 발생자를 바꾸는 closure가 있다.

구현 방법이나 사용법이 JQuery와 같거나 유사하다는 것을 알 수 있는데,

NicEdit의 라이브러리들은 복사해서

자체 제품 개발시 사용한다면 큰 도움이 될 것이다











+ Recent posts