tinymce의 plugin을 또 하나 만들고 있다. 이전에 codeblock plugin을 만들땐 layer를 직접 만들었는데 이번엔 tinymce의 모듈을 써서 만들어보고 싶었다. 그래서 WindowManager.open의 파라미터를 확인해봤다.
내가 헛것을 보는건 아니겠지라는 생각이 들만큼 단촐한 설명이다. 'width/height/url etc' 이라고? 잠시, 아니 한참을 멍하니 있다가 소스코드를 보기로 했다. WindowManager니까 Window의 생성자 파라미터겠지 라고 생각했는데 그게 맞았다. 근데 단순히 넘겨주는 건 아니고 조금 조작을 한다. 그러니까 Window의 생성자와 다른 값을 파라미터로 받는다. 그럼 문서에 그걸 써줘야하는거 아냐? 부글부글.
조금 짜증이 났지만 아쉬운건 나니 내가 노력해서 이걸 알아내는 수밖에 없다. 문서로는 정확한 정보를 얻을 수 없으니 이때부터 소스코드만 보기 시작했다. 그렇게 나는 tinymce core 코드 전체를 보게 되었다. ㅠㅠ
WindowManager
WindowManager의 Window는 말이 Window지 Dialog다. 사용방법은 아주 단순하다. alert()은 확인 버튼만 있는 dialog, confirm()은 확인/취소 버튼이 있는 dialog, open()은 내용을 맘대로 바꿀 수 있는 dialog를 연다. 나의 관심사는 open()에 전달하는 parameter인데 여기가 정말 복잡하다. 소스코드를 봤지만 언뜻 이해가 안됐다.
open()
의 첫번째 파라미터 args는 Window 생성자에 그대로 전달이 된다. 다음의 파라미터들은 Window 생성자 파라미터에는 없는 것들이다.
- body: items로 변환이 되지만 items의 type은 bodyType이라는 별도의 파라미터를 사용한다.
- bodyType: items의 type
- commands: items의 callback
정리해놓고 보니 별로 많이 다른 것은 없는데 동작이 다른게 문제다. 핵심적인 items
가 body
라는 것과 중복이 되고 게다가 bodyType
이라는 별도의 파라미터가 type
을 담당하고 body
를 감싸는 container
는 flexlayout
다. 이 layout은 25px
정도의 margin
같은 것을 만든다. (실제 margin
은 아니지만 그 정도 공간을 만든다) 아마도 body
, bodyType
, commands
정도만 사용하는 심플한 사용법을 만들고 싶었던 것 같은데... 그럼 설명을 해야할 거 아닌가! 이런 설명은 문서 어디에도 없다.
어쨌든 이제 뭘 봐야하는지는 알았으니 제대로 살펴보기로 했다. Window를 보다보니 FloatPanel을 상속받고 있고 FloatPanel은 Panel을, Panel은 Container.... 정리해보면 다음의 순으로 상속을 받는다.
Window -> FloatPanel -> Panel -> Container -> Control -> Class
제대로 알고 싶었기 때문에 Class부터 보기로 했다.
Class
Class는 tinymce에서 만든 javascript class 형식이다. extends
함수를 통해 상속하고 Mixins를 통해서 함수를 주입, Statics를 통해 static함수를 만들 수 있다. tinymce Class들은 모두 이 Class를 extends
해서 만들어졌다.
var Sample = Class.extends({
Mixins: [],
Statics: []
});
생성되면 init
함수와 Mixins의 init
함수를 실행한다.
Control
Control은 tinymce에서 눈에 보이는 항목들의 기본 class다.
- settings: 생성 파라미터다. 파라미터가 비어있으면 defaults 값을 가진다.
- state: visible, active, disabled, value, rendered, text, title등의 값을 가진다.
- data: 값을 넣어둔다.
- classes:
ClassList
를 사용해서 dom element의 class값을 관리한다. - border, margin, padding:
BoxUtils
를 사용해서 top, bottom, left, right값을 관리한다. - on(), off(), fire(): 이벤트를 각각 설정, 해제, 발생한다.
- innerHtml(): dom.innerHtml 값을 가져오거나 할당한다.
- visible(), active() ... : state의 값과 동일한 함수가 만들어지고 이를 통해 state의 값을 관리할 수 있다.
Container
Container는 여러 Control을 가진 Control이다.
- state: Control.state에 fixed가 추가되었다.
- _items: Control 배열인데
_
로 시작하는 것은 private인 것 같다. - _layout:
Layout
이다. settings.layout에 layout이름을 지정하면 Layout을 상속한 여러 Layout중 동일한 이름을 가진 Layout이 만들어진다. - renderHtml(): html + layout.renderHtml() 값을 반환하는데 div몇개로 감싸진다. layout.renderHtml()를 통해 items의 renderHtml()가 실행된다.
Layout에는 Absolute, Fit, Flex, Flow, Grid, Stack 이 있고 이 중 하나의 이름을 쓰면 된다. Layout에 대한 설명은 생략. (문서는 여전히 부실하다)
Panel
Panel은 FitLayout, panel class를 기본값으로 가진 Container다.
- html: 함수라면 실행결과를 변수라면 값을 사용한다. settings에 이 값을 설정하면 items, layout은 무시되고 이 값을 그대로 render한다.
FloatPanel
FloatPanel은 Mixins에 Movable, Resisable을 가진 Panel이다. 이름과 Mixins들의 이름에서 보이듯 이동이 되고 사이즈변경이 되면 떠있는 Panel이다.
Window
Window는 defaults로 layout: flex, role: dialog, state: fixed를 가진 FloatPanel이다.
- buttons: footer에 표시될 Button 리스트
집중하려고 노력했지만 하위 클래스로 점점 내려갈수록 대충 정리하게된다. ;; 어쨌든 이렇게 정리하고 보니 Window를 만드는데 가장 중요한 부분은 Container, Layout 이었다. 이 두가지를 잘 알고 있으면 만드는데 도움이 많이 될 것 같다. 그러나 결국 custom Control을 만들어야 할 때가 올 것이 분명해보인다. 과연 나는 custom Control을 만들게 될까? 아니라면 Panel에서 시작된 html
을 사용해서 직접 모든 dom을 조작하게 될 것 같다. 맘속엔 이미 방향이 정해졌지만 모르지 만들다보면 또 달라질지...