블로그 이미지
초딩입맛제주아재
하고 싶은 것만 하며 살고 싶다

calendar

      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
2007. 5. 29. 23:21 Programing/HTML/JavaScript/CSS
가계부를 업데이트 하면서 적용해봤는데 나름 만족할만한 정도다.



테이블 셀 작업 샘플보기

[editableText.js]
/*
작성자: 물결(asrada2001.mireene.com)
작성일: 2007-05-29
*/

function createEditor(callback){
   var editor = new Editor();
   editor.callback = callback;

   try{
       document.addEventListener('click',clickEventHandler,false);
   }catch(e){
       document.attachEvent('onclick',clickEventHandler);
   }

   return editor;
}
function clickEventHandler(e){
   var evt = e || window.event;
   var target;

   if(evt.target){
       target = evt.target;
   }else{
       target = evt.srcElement;
   }

   if(target.className.search('editable') > -1){
       editor.editing(target);
   }
}

function Editor(){
   this.autosave = false;
   this.source = null;
   this.callback = null;
   this.container = null;
   this.frm = document.createElement('INPUT');
   this.frm.className = 'editor';
   this.frm.model = this;

   this.frm.onkeydown = function(e){
       var evt = e || window.event;

       if(evt.keyCode == 13){
           try{
               evt.preventDefault();
           }catch(ex){
               evt.returnValue = false;
           }

           this.model.complete();
       }
   }

   this.frm.onblur = function(e){
       if(this.model.autosave == true){
            this.model.complete();
        }else{
            this.model.cancel();
        }
   }
}

Editor.prototype.editing = function(obj){
   try{
       this.container = obj;

       if(obj.hasChildNodes() == false){
           obj.appendChild(document.createTextNode(''));
       }

       this.source = obj.firstChild;
       this.frm.value = this.source.nodeValue;
       this.frm.style.width = '100%';

       if(this.container.style.textAlign != undefined && this.container.style.textAlign != ''){
            this.frm.style.textAlign = this.container.style.textAlign;
        }else if(this.container.align != undefined && this.container.align != ''){
            this.frm.style.textAlign = this.container.align;
        }else{
            this.frm.style.textAlign = 'left';
       }

       this.container.replaceChild(this.frm,this.source);
       this.frm.focus();
       this.frm.value += '';
   }catch(e){
   }
}

Editor.prototype.cancel = function(){
   this.finish();
}

Editor.prototype.complete = function(){
   this.save();
   this.finish();

   if(this.callback instanceof Function){
       this.callback(this.container);
   }else{
   }
}

Editor.prototype.finish = function(){
   this.container.replaceChild(this.source,this.frm);
}

Editor.prototype.save = function(){
   this.source = document.createTextNode(this.frm.value);
}


모듈을 페이지에 로드시키고 에디터 객체를 생성하면 준비는 끝.
<script type="text/javascript" src="editableText.js"></script>
<script type="text/javascript">
var editor = createEditor(callback);

function callback(obj){
}
</script>


사용자가 문서의 텍스트 부분을 클릭하면 텍스트 노드를 담고있는 container 객체의 className 속성에 'editable' 가 있는지 확인한 후 에디터 객체(INPUT)에 텍스트를 전달하고 텍스트노드와 에디터를 바꿔치기한다.

에디터는 싱글턴(singleton)으로 하나의 에디터가 문서 전역에서 동작한다.

autosave 속성이 true로 설정되면 에디터에서 수정후 포커스가 다른 곳으로 이동하면 자동으로 수정한 내용이 원본 텍스트 노드에 그대로 적용이 되고 반대로 false면 원 상태로 되돌린다.
autosave를 적용하지 않으면 사용자는 데이터 수정 후 엔터키를 눌러야 수정한 내용이 반영된다.

callback 함수를 지정하면 save() 메서드를 실행 후 callback 함수를 호출한다.
xmlHttpRequest 객체를 사용할 경우 동적으로 DB의 내용을 수정 할 수 있다.

원래는 source를 <span>태그에만 할당 하려했으나 셀작업에 쓰는게 더 좋을 것 같아서 'edtiable'을 className으로 갖는 모든 객체로 수정하였다.
하지만 변경 후 맘에 안드는 것이, 원글 너비(offsetWidth)의 반영이다.
<span>,<div>등 block 객체에 edtiable 을 적용하면 원글의 사이즈에 맞게 에디터의 사이즈를 조절할 수 있는 반면 테이블의 셀(TD)에 적용 할 경우 테이블 셀 크기에 맞춰버리니 맞춤 사이즈는 포기할 수 밖에 없다....
방법을 아시는 분은 코멘트를 부탁...^^;


*주의*
Editor는 멀티라인 편집을 지원하지 않는다.
<span>,<td>,<div>,<p> 의 엘리먼트에서 오직 가장 처음에 위치한 텍스트 노드를 편집 할 수 있다.
멀티라인 편집을 위해 Editor 객체에 에디터를 input과 textarea 두개로 구분하여 childNodes.lenth로 멀티라인
여부를 판별한 후 해당 엘리먼트에 맞는 에디터를 쓰게끔 리펙토링을 시도하였으나,
editing() 메서드와 finish() 메서드에서 replaceChild를 쓸 수 없고,
텍스트 노드 사이의 태그를 검출해야 하며, 멀티라인의 경우 줄바꿈 처리를 하는 등 코드가 복잡해지는 관계로 단문 인라인 엘리먼트에 이 스크립트를 사용할 것을 당부하는 것으로 대신한다.

posted by 초딩입맛제주아재

댓글을 달아 주세요

  1. 막막한코딩 2007.06.29 15:44  Addr Edit/Del Reply

    잘보고 갑니다.

  2. 제오니 2007.07.10 18:30  Addr Edit/Del Reply

    잘보고 갑니다..

  3. joon 2007.11.23 14:33  Addr Edit/Del Reply

    phpschool에서 링크타고 와서 잘 보고 갑니다. 동적DB 저장부분도 간단한 강의같은식으로 하나 만들어 주시면 저같은 초보들의 앞길을 환히 밝혀줄거라 생각합니다.^^ 그리고 select박스를 이용한 코드도 공개하실 의향은 없으신지요?

  4. 최명숙 2008.03.07 09:53  Addr Edit/Del Reply

    아직 실력이 안되서 잘 안되네요.
    부탁이 있는데
    [xmlHttpRequest 객체를 사용할 경우 동적으로 DB의 내용을 수정 할 수 있다.] 이부분 소스좀 보여 줄수 없나요?
    부탁드립니다.
    즐거운 하루 되세요

    • BlogIcon 초딩입맛제주아재 2008.03.08 02:57 신고  Addr Edit/Del

      브라우저에 내장된 xmlHttpRequest 객체를 이용하면 페이지 이동없이 서버와 통신을 할 수 있습니다. 즉, DB에 기록할 데이터를 xmlHttpRequest 객체에 실어 서버로 보내고 서버에서는 이를 받아 DB에 저장 하는 것이죠. 요즘 흔히 말하는 Ajax의 기본 기술이라고 보시면 되겠습니다. 소스는 제 블로그 우측에 [Link Site] 클릭해 보시면 물결의 가계부와 물결의 메모보드 링크가 있습니다. 해당 링크 타고 들어가보시면 소스보기로 각 소스 확인 하실 수 있습니다. 메모보드는 전체 소스 다운로드도 하실 수 있구요^^

  5. chamin 2008.03.14 11:03  Addr Edit/Del Reply

    잘 보고 갑니다. 감사...^^