앞서 NicEdit 라이브러리 설명 중 

fireEvent에 대하여 간단하게 정리하였다.

여기서는 nicEditorInstance 클래스를 중심으로

보다 상세하게 구현 방법을(사용방법) 정리한다.


정리하기 전에 다음 흐름을 확인하고 넘어간다.

이 장에서 정리한 내용을 그림으로 그린 것으로 

익숙하지 않은 사람에게는 

그림과 정리한 내용을 같이 보는 것이 더 쉬울 수 있다.


먼저, nicEditorInstance 클래스 생성 후

mousedown과 keyup 이벤트 핸들러로 selected를 지정했다. 

var nicEditorInstance = bkClass.extend({
    ~~ 생략 ~~
    init: function() {
        this.elm.setAttribute("contentEditable", "true");
        if (this.getContent() == "") {
            this.setContent("<br />")
        }
        this.instanceDoc = document.defaultView;
        this.elm.addEvent("mousedown", this.selected.closureListener(this)).addEvent(생략).addEvent("keyup", this.selected.closure(this));
        this.ne.fireEvent("add", this)
    },
    ~~ 생략 ~~
     

사용자가 편집기에서 동작을 할 때 마다

selected로 받아서 무엇인가를 처리하겠다는 것이다.

selected: function(C, A) {
    if (!A && !(A = this.selElm)) {
        A = this.selElm()
    }
    if (!C.ctrlKey) {
        var B = this.ne.selectedInstance;
        if (B != this) {
            if (B) {
                this.ne.fireEvent("blur", B, A)
            }
            this.ne.selectedInstance = this;
            this.ne.fireEvent("focus", B, A)
        }
        this.ne.fireEvent("selected", B, A);
        this.isFocused = true;
        this.elm.addClass("selected")
    }
    return false
}, 

지정된 selected 핸들러의 코드를 보면

특정 변화가 있으면 3가지 이벤트를 발생 시키라고

niceditor에게 요구 한다(fireEvent).

마우스나 키보드를 눌러서 이벤트를 발생 시킨 대상

편집기인 나(this)와 현재 선택되었던 편집기(이전 편집기 - B)가 다르면

이전 편집기(B)에게는 포커스가 나갔다고(blur) 알리고(fireEvent),

이벤트를 발생시킨 나(this)에게는 포커스가 들어왔다고(focus) 알린다(fireEvent),

이것은 사용자가 나(this)를 마우스나 키보드로 클릭했다는 당연한 것을 의미한다.


fireEvent를 niceditor(ne)의 메서드로 호출하는데

bkEvent 클래스에서 상속 받은 메서드이다.

niceditor는 bkClass, bkEvent 클래스에서 상속 받았다.

bkEvent 클래스의 fireEvent에서는

다음 코드와 같이 등록된 이벤트들(eventList)에게

지정된 이벤트를 실행하라고 알림을 준다(apply).

함수를 실행하는 것과 같은데,

this를 해당 개체로 하기 위해 apply를 사용한다.

apply에 대한 자세한 내용은 찾아보길 바란다.

var bkEvent = {
    addEvent: function(A, B) {
      ~~ 생략 ~~
    fireEvent: function() {
        var A = bkLib.toArray(arguments),
            C = A.shift();
        if (this.eventList && this.eventList[C]) {
            for (var B = 0; B < this.eventList[C].length; B++) {
                this.eventList[C][B].apply(this, A)
            }
        }
    }
}; 


niceditor에 이벤트를 등록하는 대상들은 모두 버튼들로

편집기가 포커스를 가지면 버튼을 활성화 시키고

편집기가 포커스를 잃으면 버튼을 비활성화 시키는 것이다.

따라서, bkEvent(nicEditor)의 addEvent를 호출하는것은 

nicEditorButton와 nicEditorSelect

그리고 이들로부터 상속 받은 자식들이다.

nicEditorButton 생성자에서 다음 코드를 확인할 수 있다.

파라미터 B는 눈치로 nicEditor(ne)임을 알 수 있다.

선택되면(포커스가 가면 selected) enable함수를 호출하도록,

포커스를 잃으면 disable 함수를 호출하도록 지정하였다.


 var nicEditorButton = bkClass.extend({
    construct: function(D, A, C, B) {
        this.options = C.buttons[A];
        this.name = A;
        this.ne = B;
        this.elm = D;
        ~~ 생략 ~~
        B.addEvent("selected", this.enable.closure(this)).addEvent("blur", this.disable.closure(this)).addEvent("key", this.key.closure(this));
        this.disable();
        this.init()
    },

nicEditorInstance에서 focus 이벤트가 있었는데,

버튼에서 사용하지 않는다.

버튼에서는 focus 대신에 selected를 사용한다.

focus가 아닌 selected로 사용한 이유는

(이름은 붙이기 나름이지만)

버튼 활성화 외에 현재 선택된 영역의 HTML 태그를 확인하여

해당 버튼을 누른 상태(실행 여부 표시)로

보여 주기 위한 기능(checkNodes)도 있기 때문인 것으로 추측한다.




마지막은 NicEdit의 버튼과 플러그인 클래스이다.

버튼과 플러그인 클래스들이 JS의 객체지향을 가장 잘 보여준다고 생각한다.

다음 그림을 보면서 설명을 읽기 바란다.

NicEdit의 플러그인은 

크게 확장 버튼(nicEditorAdvancedButton)과

선택 상자(nicEditorSelect) 두 가지 이다.

버튼을 누르면 편집 명령이 실행되는

일반적인 버튼은 nicEditorButton으로 생성되고,

버튼을 누르면 별도의 창이 뜨는 것은 모두 플러그인으로 구현되었다.


즉, 버튼을 누르면 해당 버튼 아래에 

세부 설정 판넬이 나타나는 nicEditorAdvancedButton 클래스가 있고,

일반 버튼과 달리 사용자가 특정 값을 리스트에서 선택하는

HTML SELECT 태그를 구현한 nicEditorSelect 클래스가 있다.

확장 버튼(nicEditorAdvancedButton)은

일반 버튼과 동일하게 생성되고 기능하지만

사용자가 클릭하면 세부 설정 판넬이 나타나는 차이를 가지기 때문에

nicEditorButton에서 상속된다.

nicEditorAdvancedButton은 설정 판넬을 보여주고 감추는 기능 위주로 구현되고

nicEditorAdvancedButton를 상속받아

설정 판넬에 나타나는 것들(그림)에 따라 각 클래스가 다시 만들어 진다.

즉, 설정 판넬에

이미지 파일을 선택하게 하면 nicImageButton,

웹사이트 주소 정보를 입력 받으면 nicLinkButton,

글자색을 선택하게 하면 nicEditorColorButton,

배경색을 선택하게 하면 nicEditorBgColorButton 클래스를 구성하였다.


HTML select 태그를 이용하지 않고 div를 이용하여 직접 개발하였다.

HTML select 태그는 설정 판넬에 리스트들이 한 라인씩 출력되고,

사용자가 선택하면 

버튼 부분에 해당 내용이 출력되면서 설정 판넬이 사라진다.

nicEditorSelect로 이 기능을 구현하고

설정 판넬의 내용에 따라 3가지 하위 클래스를 개발하였다.

폰트 이름이 나열되는 nicEditorFontFamilySelect,

폰트 크기가 나열되는 nicEditorFontSizeSelect,

폰트 포맷(스타일)이 나열되는 nicEditorFontFormatSelect 클래스를 개발하였다.

먼저, NicEdit에서 사용되는 (일반적인) 버튼의 클래스이자

다른 버튼들의 가장 상위의 부모인 nicEditorButton을 살펴 본다.

nicEditorButton은 bkClass에서 상속 받아

생성자에서 DIV를 이용하여 버튼을 만들어 낸다.

버튼의 플랫(flat) 기능을 위해 active, deactive 함수가 있다.

마우스가 버튼 위(hover)에 오면 버튼 외곽선을 그리고(active),

벗어나면 원 상태로 돌아가는 기능을 가지고 있다(deactive).

이러한 상태 변화는 updateState에서 이루어 진다.

NicEdit에 포커스가 있으면 버튼이 눌러질 수 있지만 (enable)

포커스가 다른 곳으로 이동하면 버튼을 누를 수 없게 만든다(disable).

버튼을 선택하면(mouseClick),

nicEditorConfig에서 지정된 command를 실행한다.


nicEditorPane은 판넬(div)를

보였다가 숨기는 기능이 전부 이다(toggle).

이 판넬에 컬러 박스들을 보이거나,

리스트들을 보여서 사용자가 선택하게 하는 역할을 한다.

nicEditorAdvancedButton은

nicEditorPane을 마우스로 버튼을 클릭하면 보이고, 

다시 버튼을 클릭하면 숨기는 기능이 첫번째이다 (mouseClick).

그리고, 아주 재미있는 기능이 addForm()함수에 있다.

Json 데이터를 파라메터로 받아서

nicEditorPane에 HTML form과 입력 상자 등을 자동으로 생성한다.

nicEditorAdvancedButton의

addForm() 함수 코드를 살펴보는 것은 다소 어렵기 때문에

자식 클래스에서 호출하는 사용법 위주로 살펴본다.

자식 클래스의 역할은

nicEditorPane에 각자에게 필요한 정보를 입력하도록 설정하고

입력 받은 값 데로 실행하는 것이다.

nicLinkButton은 URL 링크 정보를 필요로 한다.

따라서, URL 링크를 입력하는 입력 상자(text-href),

링크의 제목(text - title),

링크를 사용자가 클릭했을 때,

현재 창에 해당 링크 내용을 출력할 것인지,

새로운 창에 출력할 것인지 선택하게 하는 선택창(select - target)의

3개 HTML 태그가 필요하다.

폼 작성 완료를 위한 버튼(submit)도 있어야 한다.


nicLinkButton은 addPane과 submit메소드 두가지로 구성되었다.

addPane은 앞서 언급한 입력들을 위해

nicEditorPane에 설정할 내용들을 설정하는 일종의 이벤트로

부모인 nicEditorAdvancedButton에서

nicEditorPane이 보일 때 호출하고 있다.

부모에서 호출하기 때문에

자식에서는 오버라이드(override)한 것처럼 사용한다.

submit도 유사한데

부모에게서 선언하고, 구체적인 코드를 작성하지 않았다.

구체적인 코드는 자식에게서 작성하여 (override)

객체 지향 프로그래밍처럼 구현하였다.


nicLinkButton의 addPane에서 사용된 addForm 코드와

실행 화면을 비교하며 사용법을 정리한다.

var nicLinkButton = nicEditorAdvancedButton.extend({
    addPane: function() {
        this.ln = this.ne.selectedInstance.selElm().parentTag("A");
        this.addForm({
            "": {
                type: "title",
                txt: "Add/Edit Link"
            },
            href: {
                type: "text",
                txt: "URL",
                value: "http://",
                style: {
                    width: "150px"
                }
            },
            title: {
                type: "text",
                txt: "Title"
            },
            target: {
                type: "select",
                txt: "Open In",
                options: {
                    "": "Current Window",
                    _blank: "New Window"
                },
                style: {
                    width: "100px"
                }
            }
        }, this.ln)
    },

 

빈문자열, href, title, target 4가지의 Json 키가 있고

각각이 다시 Json 값을 가지고 있다.

이 4가지가 실행 화면에서 각각 한 행 인 걸 알 수 있다.

이 키는 각 입력 컨트롤의 아이디(HTML ID 속성)가 되는 것으로

빈 문자열은 입력 받는 것이 없다는 것을 의미한다.

그리고 type은 입력 컨트롤의 종류로

title은 입력 컨트롤이 아닌 단순 문자열(txt) 출력을 의미하고,

text는 입력 상자(Text 태그),

select는 선택 상자(Select 태그)

contents는 다중 입력 상자(TextArea 태그)를 생성한다.

먼저, 빈 문자열은 입력 받는 컨트롤이 없다는 걸 의미한다.

따라서 하위 속성에서 type은 단순 문자열 출력인 title이고,

추가할 링크를 입력하라(Add/Edit Link)는 제목이 주어진다.

다음의 href는 입력 상자(type:text)를 생성하고

기본값(value)을 "http://" 준 뒤 사용자의 입력을 대기한다.

submit후에 아이디가 href 인 입력 상자의 값을 가져와 사용한다.

Txt 속성은 일종의 label 역할을 한다.

하나의 행은 안내문 역할을 하는 txt와

사용자의 입력을 나타내는 type로 구성되었다.

세 번째로 title키는

제목을 입력 받는데, url의 제목을 의미한다.

마지막으로 target은 type이 select로

HTML 선택 박스(select)를 생성한다.

선택할 항목은 options하위에 json으로 지정한다.

addForm을 호출하면

마지막에 submit 버튼(질의보내기)이 무조건 생성된다.

이 버튼이 submit()와 연동되어 있다.

nicLinkButton에서 오버라이드한 submit()의 내용은

사용자가 입력한 url 값이 없으면 오류 메시지를 출력하고

값이 있으면 먼저 판넬부터 숨긴다 (제거-removePane).

그리고 사용자가 입력한 값을 파라미터로

nicCommand를 실행하여 html link (a href)를 생성하게 된다.


정리하면

nicEditorButton, nicEditorAdvancedButton, nicLinkButton으로 

이어지는 계층 구조를 이해하고

왜 계층이 생겼는지 이해해야 한다.

모든 버튼에 필요한 기능은 nicEditorButton 클래스,

이 중에 버튼을 누르면 

상세 정보를 입력할 수 있도록 하는 nicLinkButton 클래스가 있다.

NicLinkButton 이 외에도

nicEditorColorButton, nicEditorBgColorButton, nicImageButton이 있는데

이들의 공통점은 설정 판넬(nicEditorPane)이 필요하다는 것이고

차이점은 설정 판넬에서 입력 받는 값들과

실행 방식(command)은 각각 모두 다르다는 것이다.

공통적인 것은 모아서 구조화 하거나 객체지향으로 개발하게 되는데,

여기서는 부모화(추상화 - nicEditorAdvancedButton)해서 객체지향 프로그래밍을 하였다.

차이점은 각각의 클래스에서 구현하게 된다.

나머지 3개의 클래스에 대한 설명은 하지 않지만

어떤 차이를 어떻게 구현했는지 알면 도움이 많이 되니 확인해 보길 바란다.


마지막으로

nicEditorSelect 클래스를 정리한다.

nicEditorSelect의 자식들은

nicEditorAdvancedButton의 자식들과 달라서 모두 유사하다.

즉, 버튼과 선택된 내용을 보여주는 라벨이 있는 select 태그로 구성되었다.


nicEditorSelect는 nicEditorButton과

nicEditorAdvancedButton를 합친 기능을 하고 있다.

nicEditorSelect는 버튼을 누르면 설정 판넬(nicEditorPane)이 나오는 것으로 

nicEditorAdvancedButton과 유사하다.

차이점은 버튼 보다 너비가 넓고, 

넓은 공간에 사용자가 선택한 값을 출력한다는 차이가 있다.

그리고, 설정 판넬의 내용도 사용자 입력 값이 아니라

사용자가 선택할 수 있는 리스트들 

(폰트명-Arial, Comic Sans, Courier New 등, 

폰트크기-P, pre, h6, h5 등, 

폰트 형식-8pt, 10pt, 12pt, 14pt 등)이 나열되는 것으로 

HTML SELECT 태그와 동일하다.

차이점은 리스트에서 

폰트명일 경우 폰트명이 적용되어 값이 출력되고,

폰트 크기일 경우 폰트 크기가 적용되어 출력된다는 것이다 (위 그림 참조).

nicEditorSelect 하위에 3개의 자식이 있는 것은

폰트명, 폰트크기, 폰트 형식이 적용된 것을 보여 주기 위해서 이다.

따라서, 자식 클래스인 

폰트명(nicEditorFontFamilySelect), 

폰트크기(nicEditorFontFormatSelect), 

폰트형식(nicEditorFontSizeSelect)에는

리스트 항목을 나타내는 Json 데이터인 sel 변수와

항목 개수 만큼(for (itm in this.sel) )

폰트명(font face), 폰트 크기(font size), 폰트 형식(p, pre, h6…) 태그를

적용하는 코드가 있을 뿐이다.

이렇게 HTML 적용된 리스트가

nicEditorSelect 클래스 자식들이다.

var nicEditorFontSizeSelect = nicEditorSelect.extend({
    sel: {
        1: "1&nbsp;(8pt)",
    ~~ 생략 ~~
    },
    init: function() {
        this.setDisplay("Font&nbsp;Size...");
        for (itm in this.sel) {
            this.add(itm, '<font size="' + itm + '">' + this.sel[itm] + "</font>")
        }
    }
});
var nicEditorFontFamilySelect = nicEditorSelect.extend({
    sel: {
        arial: "Arial",
    ~~ 생략 ~~
    },
    init: function() {
        this.setDisplay("Font&nbsp;Family...");
        for (itm in this.sel) {
            this.add(itm, '<font face="' + itm + '">' + this.sel[itm] + "</font>")
        }
    }
});
var nicEditorFontFormatSelect = nicEditorSelect.extend({
    sel: {
        p: "Paragraph",
    ~~ 생략 ~~
    },
    init: function() {
        this.setDisplay("Font&nbsp;Format...");
        for (itm in this.sel) {
            var A = itm.toUpperCase();
            this.add("<" + A + ">", "<" + itm + ' style="padding: 0px; margin: 0px;">' + this.sel[itm] + "</" + A + ">")
        }
    }
}); 


계층 구조 중심으로 정리하면서

nicEditorButton의 메서드에 대한 정리가 부족하다.

nicEditorButton의 주요 메서드 중

버튼 활성과 관련된 것은 라이브러리에서 언급했다.

대부분 마우스가 버튼 위에 올라오면 (mousemove, hover)

평평한 버튼 주변에 선이 생기게 하는 기능,

마우스로 클릭한 기능(mousedown - activate/deactivate),

에디터가 포커스를 잃으면 버튼을 누를 수 없게 하는 기능(disable, enable) 등이 구현되어 있다.

모두 평범한 코드인데

checkNodes는 HTML DOM 구조를 조금 활용한 코드이다.

nicEditorInstance에서 언급한 Selection, Range로

현재 커서의 위치에 있는 HTML 개체를 가져와서

HTML 태그(CSS)가 무엇인지 판단하여 버튼을 활성화 시킨다.

do {
    if (this.options.tags && bkLib.inArray(this.options.tags, B.nodeName)) {
        this.activate();
        return true
    }
} while (B = B.parentNode && B.className != "nicEdit");
B = $BK(A);
while (B.nodeType == 3) {
    B = $BK(B.parentNode)
}
if (this.options.css) {
    for (itm in this.options.css) {
        if (B.getStyle(itm, this.ne.selectedInstance.instanceDoc) == this.options.css[itm]) {
            this.activate();
            return true
        }
    }

위 코드에서

앞서의 do 문에서는 nicEditorConfig에서 지정되어

각 버튼에게 주어진 tags값과 태그의 nodeName이 같은지(inArray) 비교하여

버튼을 활성화(activate) 시킨다.

현재 선택된 노드(B) 뿐 아니라 부모(parentNode) 노드까지 찾아보게(do) 구현하였다.

또는 CSS로 작성된 태그를 검출할 수 있도록

현재 선택된 노드(B)로 부터 CSS를 추출하여(getStyle) 버튼에 지정된 CSS와 비교한다.

checkNodes의 기능은 에디터에서 제법 중요한 기능이고

노드 탐색(parentNode)등의 코드는

JS 라이브러리(도구)에서 많이 사용되는 방법이라 잘 익혀두는 것이 좋다.




마지막으로

NicEdit를 수정하면서 몇 가지 개념을 정리한다.

nicEditorSelect의 자식들이

실제로 웹에서 사용되는 다음 그림을 보면 문제가 있다.

첫 번째는 설정 판넬의 크기가 작아서 항목들이 잘려서 보인다.

두 번째는 하나의 nicEditorSelect를 클릭하고,

다른 nicEditorSelect을 선택하면

앞서 선택한 nicEditorSelect의 설정 판넬이 그대로 있는 것이다.

버그를 수정하기 위해

NicEdit에서 데모 파일을 다운로드 받는다.

다운로드 페이지 하단의 압축되지 않은 파일 설정을 체크하고

(Uncompressed NicEdit for development) 다운로드 받는다.


demos 폴더에 있는 예제 중 적당한 파일을 선택하여 실행한다.

nicEdit.js만 수정하고

수정한 실행 결과를 보는 것이기 때문에

NicEdit가 실행되는 어떤 파일이든 관계가 없다.


준비가 되었으면

간단하게 이 두 가지 버그를 수정해 본다.

먼저 설정 판넬의 크기(width) 문제를 해결해 본다.

이 설정 판넬을 사용하는 것은 nicEditorSelect의 자식인

폰트명(nicEditorFontFamilySelect),

폰트 크기(nicEditorFontSizeSelect),

폰트 형식(nicEditorFontFormatSelect) 인데

모두 nicEditorSelect에서 설정 판넬(nicEditorPane)을

보이거나(open) 숨기고(close) 있다.

nicEditorSelect의 open함수를 보면

nicEditorPane의 크기(width)가 88px로 고정되어 생성되는 것을 알 수 있다.

    open: function() {
        this.pane = new nicEditorPane(this.items, this.ne, {
            width: "88px",
            padding: "0px",
            borderTop: 0,
            borderLeft: "1px solid #ccc",
            borderRight: "1px solid #ccc",
            borderBottom: "0px",
            backgroundColor: "#fff"
        });
        for (var C = 0; C < this.selOptions.length; C++) {
            var B = this.selOptions[C];
            var A = new bkElement("div").setStyle({
                overflow: "hidden",
                borderBottom: "1px solid #ccc",
                width: "88px",
                textAlign: "left",
                overflow: "hidden",
                cursor: "pointer"
            });
            var D = new bkElement("div").setStyle({
                padding: "0px 4px"
            }).setContent(B[1]).appendTo(A).noSelect();
            D.addEvent("click", this.update.closure(this, B[0])).addEvent("mouseover", this.over.closure(this, D)).addEvent("mouseout", this.out.closure(this, D)).setAttributes("id", B[0]);
            this.pane.append(A);
            if (!window.opera) {
                D.onmousedown = bkLib.cancelEvent
            }
        }
    },
    close: function() {
        if (this.pane) {
            this.pane = this.pane.remove()
        }
    }, 

this.selOptions은 설정 판넬에 출력할 항목들 (폰트명, 크기등)인데

마찬가지로 크기(width)가 88px로 고정되어 생성되는 것을 알 수 있다.

이 값을 대충 150px로 수정하고 실행한다.

그림과 같이 넓이 문제가 해결 되었다.

하지만, 크기가 너무 커서 여백이 남는 클래스도 있다.

따라서, 그림처럼 각각 자기의 크기를 갖는 것이 좋을 것이다.


해결 방법은 this.selOptions이 힌트가 되어 준다.

this.selOptions는 부모인 nicEditorSelect에서는

변수 선언이나 할당된 데이터를 볼 수 없다.

위 코드에서 사용된 것이 전부 이다.

즉, 이 변수는 자식에서 선언되고 부모에서 사용된다.

(실제로는 자식에서 sel로 선언되고 add 되면서 할당된다.)

자식 클래스인 폰트 크기(nicEditorFontSizeSelect)에서

다음 코드와 같이 panelWidth 변수에 "150px" 넣어서 생성한다.

이와 같은 방식으로 폰트명과 폰트 형식도 작성한다.

var nicEditorFontSizeSelect = nicEditorSelect.extend({
    panelWidth: "150px",
    sel: {
        1: "1&nbsp;(8pt)",
        2: "2&nbsp;(10pt)",
        3: "3&nbsp;(12pt)",
        4: "4&nbsp;(14pt)",
        5: "5&nbsp;(18pt)",
        6: "6&nbsp;(24pt)"
    },
    init: function() {
        this.setDisplay("Font&nbsp;Size...");
        for (itm in this.sel) {
            this.add(itm, '<font size="' + itm + '">' + this.sel[itm] + "</font>")
        }
    }
}); 

그리고, nicEditorSelect의 open함수에서

다음과 같이 panelWidth의 크기로 생성하도록 한다.

open: function() {
    this.pane = new nicEditorPane(this.items, this.ne, {
        width: this.panelWidth,
        padding: "0px",
        borderTop: 0,
        생략
    });
    for (var C = 0; C < this.selOptions.length; C++) {
        var B = this.selOptions[C];
        var A = new bkElement("div").setStyle({
            overflow: "hidden",
            borderBottom: "1px solid #ccc",
            width: this.panelWidth,
            생략
        }
    }
}, 

아주 간단하게

각각의 자식에 필요한 크기로 설정 판넬이 생성된다.

여기서 하나 더 생각해 보면

폰트 크기는 너비가(width) 넓지만

나머지 폰트명과 형식은 너비가 비슷해 보인다.

이 두 자식(실제로는 아주 많을 수 있다.)에서 코드를 입력하는 것이 귀찮다.

이 경우, 기본 값(default)을 주어서 해결할 수 있다.

즉, 부모에서 panelWidth 변수를 선언하고 값을 주는 것이다.

자식에서 재할당(선언) 하면 자식 값으로 사용되고(override),

그렇지 않으면 부모의 값이 사용되도록 하면 된다.


아주 간단하다.

다음 코드처럼 nicEditorSelect에 자식에게 넣었던 것을 그대로 작성하면 된다.

var nicEditorSelect = bkClass.extend({
    panelWidth: "100px",
    construct: function(D, A, C, B) {
        this.options = C.buttons[A];
 

즉, 부모(nicEditorSelect)에게서

panelWidth를 선언하고 100px을 할당한다.

자식 중에서 좀 큰 너비가 필요한

폰트 크기(nicEditorFontSizeSelect)는 150px을 할당하고,

비슷한 너비를 가진 나머지 자식은 아무 것도 하지 않는다.

즉, 부모에서 상속 받은 값을 그대로 사용하는 것이다.


두 번째 버그는 하나의 nicEditorSelect를 클릭하고,

다른 nicEditorSelect을 선택하면

앞서 선택한 nicEditorSelect의 설정 판넬이 그대로 있는 것이다.

이 것은 하나의 nicEditorSelect의 설정 판넬을 열 때(open),

이전의 nicEditorSelect의 설정 판넬을 닫아 주면 해결 된다.


var openedSelectBox = null;
var nicEditorSelect = bkClass.extend({
    panelWidth: "100px",
    construct: function(D, A, C, B) {
       ~~ 생략 ~~

    open: function() {
        if (openedSelectBox) openedSelectBox.close()
        openedSelectBox = this;
        this.pane = new nicEditorPane(this.items, this.ne, {

코드와 같이 전역 변수로 openedSelectBox를 선언하고,

nicEditorSelect의 open 함수가 실행될 때 (설정 판넬이 열릴 때)

현재 nicEditorSelect(this)를 openedSelectBox에 보관한다.

보관하기 전에 다음 코드와 같이 이전에 지정된 nicEditorSelect를

닫아주면(close)면 문제가 해결 된다.

nicEdit.js


간단하게 마지막 버그를 수정했지만

좋은 프로그램 방식은 아니다.

JS에서 전역 변수(openedSelectBox) 사용은 추천되지 않으며

객체 지향 프로그래밍으로 보기 어렵다.

JS에는 static변수가 없어서 전역 변수로 처리했지만

좋은 방법은 아니다.

조금 더 나은 방식은 openedSelectBox를 다른 클래스에 두는 것이다.

적절한 클래스는 버튼과 편집 창을 관리하는 niceditor일 것이다.

더욱이 niceditor는 nicEditorSelect가 생성될 때 파라미터로 넘어오고

nicEditorSelect내부에서 ne로 관리되기 때문이다.

따라서 niceditor에 openedSelectBox를 선언하고

addSelectList 메소드를 만들어서 추가하는 방식으로 구현하는 것이 좋다.

이 것은 연습 문제로  남겨둔다.





+ Recent posts