본문 바로가기
프로그래밍/AJAX

[HTML+JS] WYSIWYG 에디터 참고자료

by 베리베리 2008. 7. 10.
출처: http://cafe.naver.com/q69/74197

요즘 혼자 만드는 사이트에 WYSIWYG html 에디터를 붙이는 중이다.

Cross Browser 에디터를 목표로 하다보니 이래저래 삽질이... ㅠㅠ.


지금은 간신히 IE, FF 만이라도 제대로 구현되도록 해놓은 상태고, 앞으로 다른 브라우저도 테스트 해봐야 겠다.


요즘 블로고스피어에서 웹표준에 대해 말이 많은 모양이다.

실제 코딩을 해보니까 하는 말인데 개발자 입장에서는 이 브라우저 저 브라우저 모두 제대로 돌아가기만 한다면, 웹표준은 고사하고 온갖 꼼수에 '사파'스러운 코딩까지, 악마에게 영혼이라도 팔고 싶은 심정이다. ㅠㅠ


오늘은 내가 주로 겪은 삽질부분에 대해서 우선 적어놓고, Cross Browser 에디터에 대한 자세한 노하우는 나중에 여유가 있을 때 기록하겠다.

*



WYSIWYG 에디터란 현재 이블로그의 글쓰기 상태처럼, 글자크기 색깔 모양, 정렬 및 이미지 링크등을 html 태그를 몰라도 다룰 수 있게 지원하는 에디터를 말한다.

일반적으로 이러한 글쓰기 입력창은 iframe-x 이며, 이 iframe-x를 designMode "On" 상태로 설정함으로써 다양한 기능의 에디팅이 가능해진다.


그런데 실제코딩에서는 IE 나 FF 등 브라우저에 따라서 조금씩 차이가 나서 사람을 환장하게 하는데 주의할 점은 다음과 같다.  




1. IE 나 FF 모두 가능한 designMode on 설정 방법은 다음과 같다.

 var cw = document.getElementById("에디터iframe-x 아이디").contentWindow;

 cw.document.designMode = "on";


여러방법이 있지만 위 방법이 IE 나 FF 의 cross browsing 은 잘된다.



2. 파이어폭스에서도 designMode에 대해 지원한다. 그런데 FF 에서 이것은 반드시 페이지가 로딩될 때 설정되어야 한다.

 즉 다음과 같은 loadEdit 함수는

function loadEdit() {
   
         에디터의document.designMode = "on";

}


<body onload="loadEdit()" ...> 이렇게 해줘야 한다.

코드의 어느 구석탱이에서 <script-x>loadEdit()</script-x> 이런식으로 해서는 먹히지 않는다.



3. 계층적으로 dom 객체를 나눠고, 각 브라우저의 객체를 계층에 따라 일관되게 분류해놓고 동일한 변수명을 써야 안 헤깔린다. (놀랍게도 두 브라우저는 거의 모든 계층에서 다른 방식으로 obj를 추출해야한다. 환장할~~)


A: iframe-x 계층: 에디터 창이 되는 최상위 객체

B: contentWindow 계층: focus() 함수를 호출한다. (-> 이 계층부터 변수명을 정해둔다.)

C: document 계층 : 

    1) 이 객체 단계에서 designMode 설정해야한다.

    2) execCommand 도

D: selection 계층

E: range 계층


코딩 예는 다음과 같다

//A

this.frm = document.getElementById(this.eid);
//B

 this.cw = this.frm.contentWindow;

//C
 this.document = this.cw.document;

//D

if (isMIE())

  this.document.selection;
else
  return this.cw.getSelection();


 //E (여기서 확실한 것은 IE와 FF 입니다.)

       if (isMIE()) {
            return selc.createRange(); //IE
        } else {
            this.cw.focus();
            if (typeof selc != "undefined") {
                try {
                    return selc.getRangeAt(0); //FF
                } catch(e) {
                    return this.document.createRange(); //else
                }
            } else {
                return this.document.createRange(); //else
            }
        }



4. 위 각 계층의 obj 들을 하나의 객체로 만들어 묶어두는게 편하다. 객체지향적 코딩이 편하다.



5. 별도의 설정창이 필요한 경우에는 어떻게 selection을 유지해가는가가 중요하다.

글자색깔, 배경색깔, url 링크 등은 일반적으로 팝업창이나 레이어, prompt 창등을 띄워서 사용자로부터 입력을 받는다. 이때 사용자의 마우스가 입력창을 클릭하는 순간, 경우에 따라 에디터 창의 selection이 해제되어 버리는 경우가 있다.


 FF 는 레이어로 설정창을 만들어도 가능하다. IE는 레이어 설정창에 클릭되는 순간 에디터의 selection은 해제된다. 반면 프롬프트창의 버튼들, 레이어의 버튼을 클릭해도 selection은 해제되지 않는다.


IE 의 경우는 팝업창을 띄워서 입력을 받는 것이 가장 쉬운 방법이나 UI 상 좋지 않다. 따라서 IE에서 레이어로 설정창을 만들 때는 range 객체의 select() 함수로 selection을 묶어두는 게 중요하다.


6. 이때의 range 객체는 레이어를 띄우기 직전에 추출해야한다. 즉, 다음과 같다.


설정창이 필요한 아이콘클릭시 --> range 객체 추출해서 전역변수나 4.번에서 언급한 객체의 변수로 담아둔다. --> 레이어를 띄운다. --> 레이어 내부에서 onclick 호출시 --> 먼저 담아둔 range 객체에서 range.select();  


7. IE 에서 designMode on 상태에서 엔터키를 주면 <p> 태그가 먹히는데, IE 는 이 태그 때문에 줄간이 너무 벌어져서 조절해야 한다. 입력시점, 보는 시점 모두 고려해야 한다.



지난번에 이어서 오늘은 줄바꿈 처리에 관련해서 간략히 적어볼게요. 방금 막 삽질하다가 돌아왔습니다.


7. iframe-x 에디터 내에서 줄바꿈 문제

1) 문제

rich editor는 designMode 기능으로 가능하고 에디터는 보통 iframe-x 으로 구현된다.

이때 문제가 되는 것은 다음과 같다.

  a. IE 브라우저에서 줄간 간격이 너무 넓게 나와 보기 싫다.

  b. IE, FF 모두 줄바꿈 없이 글을 쓰면  iframe-x 이 옆으로 늘어나서 디자인이 깨진다.


2)해결책

이에 대한 해결책은 다음과 같다. 페이지 로딩하는 시점에 iframe-x 을 다음과 같이 초기화한다.

  this.document.open();
  this.document.write("<style>P {margin-top:3px;margin-bottom:3px;margin-left:3;margin-right:3;white-space: -moz-pre-wrap;word-break:break-all;}</style><P>&nbsp;</P>");
  this.document.close();


  여기서 하늘색 바탕색 부분은 a 에 대한 해결책이 된다.

  반면 b 문제는 아주 복잡하다.  일단 노란색 바탕색 부분같이 해주면, word-break:break-all; 는 IE 브라우저, white-space: -moz-pre-wrap; 는 FF 줄바꿈 문제를 어느정도 해결할 수 있다.


3) ie 줄바꿈

 그런데 IE 브라우저에서, 에디터에 첫 포커스를 주고 같은 단어 예를 들어 pppppppppp... 를 계속 누르면 에티터가 옆으로 밀린다. 포커스를 준다음 엔터를 치거나 한 후에 같은 단어를 누를 때는 괜찮다. 이처럼 첫 포커스에서 같은 단어를 반복할 때의 줄바꿈 문제는 붉은색 바탕의 더미 태그를 주는 것으로 해결할 수 있다.


4) ff 줄바꿈

FF 브라우저는 더 심각한 문제가 있다. FF 브라우저에서 다음과 같이 같은 단어를 반복하면 자동 줄바꿈이 된다. adb adb adb adb adb .... 그러나  pppppppppp... 로 하면 밀린다. 문제는 FF에서 띄워쓰기가 안된 한단어는 밀린다는 것이다. IE는 줄바꿈 된다. (아직 해결못한 부분입니다)


8. 디비에서 불러와 table td 에 뿌릴 때의 줄바꿈 문제 

IE 에서는 위의 에디터를 입력하면 문단마다 <P></P> 가 달리고, FF 에서는 <br> 태그로 문단을 구분한다. 따라서 FF 에서 작성된 글은 문제 없으나, ie 에서 작성된 글이 ie 나 ff 에서 보여질 경우 역시 줄바꿈처리를 해주야 한다.


이것 역시 다음과 같은 css를 지정함으로써 해결할 수 있다. 마찬가지로 white-space: -moz-pre-wrap 는 FF, word-break:break-all; 는 IE 의 줄바꿈, margin-top:3px; 등은 줄간격 문제를 해결한다. table 내 td 에 이러한 css 를 주면 원하는 결과가 안 나온다.
 

P {    
    white-space: -moz-pre-wrap;
    white-space: -pre-wrap;
    white-space: -o-pre-wrap; //opera
    margin-top:3px;
    margin-bottom:3px;
    margin-left:3;
    margin-right:3;
    word-break:break-all;
}  

댓글