소프트웨어/JavaScript • Dhtml

AJAX 에서 OOP 흉내내기 || Javvascript OOP

falconer 2007. 6. 15. 13:29
먼저 Ajax 을 5일 동안 공부한 초보자가 작성 한 것이라 있를지 모르는
많은 문제점에 대하여 양해와 질타을 바랍니다.

아래의 내용은 prototype.js 을 바탕으로 통신 부분만 사용한 것 이므로
문제가 없는 구조라고 생각 되시면, 가공해서 얼마든지 사용 가능하다고
생각합니다.

테스트한 브라우져는 FF, IE 이며, UTF8 환경에서 작업한것입니다.

Ajax 을 본격적으로 공부하면서 전체틀을 만들기 위해 많은 자료을 접했지만
전체적으로 Interface 을 꾸미는것을 이용하기엔 너무나 많은 파일들을
사용하기에 필요한 페이지의 일부분만 내용을 바꿀수 있는 방법을
매번 페이지 생성시마다 생성하지 않고, 상속으로 재 사용 가능한 방법을
만들어 보았습니다.

즉, 문자나 기본 정보, 문자열 짜르기등을 재 사용 가능한 방법에 중점을
두었습니다.



위의 그림에서 보면 inheritFrom 함수가 상속을 지원하는 함수로 핵심 부분입니다.

inheritFrom = function(/* Object */ aThis, /* Object */ aParent) {
var excp;
for (var property in aParent) {
try{
aThis[property] = aParent[property];
}
catch(excp){}
}
}

상속 방식은 inheritFrom( this, parent );     으로
this 은 자기자신이며, parent 은 상속받기을 원하는 부모 객체입니다.


이제 [ Bengi ] -> [ BengiDocument ] -> [ BengiUtil ] 으로 상속을 취해 줍니다.

[ Bengi ] -------------------------------------------------------------

Bengi = function(name,doc) {    
this.detect = navigator.userAgent.toLowerCase();
this.Dom = (document.getElementById) ? true : false;
this.BrowserName = navigator.appCodeName;
    
this.BrowserType = this.BrowserType();
this.BrowserVersion = this.BrowserVersion();     
...........
}

Bengi.prototype.BrowserType = function() {
// 브라우져 종류
}

Bengi.prototype.BrowserVersion = function() {
// 브라우져 버젼
}

[ BengiDocument ] -------------------------------------------------------

BengiDocument = function(name,doc) {
// 상속
inheritFrom( this, new Bengi( '', doc ) );        
}

BengiDocument.prototype.setTitle = function(value) {
// 브라우져 타이틀에 타이틀 적용
}

[ BengiUtil ] -------------------------------------------------------------

BengiUtil = function() {    
// 상속
inheritFrom( this, new BengiDocument() );    
}

BengiUtil.prototype.printMsg = function(showid,msg)     {
// 화면출력
}

BengiUtil.prototype.toConsole = function(showid,msg){
// 화면출력
}


통신 부분 및 화면 출력 부분은 따로 상속을 받았습니다.

1) 통신부분 : [ BengiUtil] -> [ BengiAjax ]

다시 표현하면
[ Bengi ] -> [ BengiDocument ] -> [ BengiUtil] -> [ BengiAjax ]

[ BengiAjax ] -----------------------------------------------------

BengiAjax = function( url, params, callback, ~~~~ ) {
// 상속
inheritFrom( this, new BengiUtil() );    
     this.xmlHttp = null;
        
new Ajax.Request( url, {
..........
..........
onSuccess: function(xmlHttp, xjson) {
        if (BengiDataShow[callback] instanceof Function) {
     BengiDataShow[callback].call( BengiDataShow, xmlHttp, xjson );
     } else {
         alert( '[ERROR]\n' +callback+'은 정의되지 않은 메소드입니다.');
     }
},
..........
..........
});

}

2) 화면 출력 부분 : [ BengiUtil] -> [ BengiDataShow ]

다시 표현하면
[ Bengi ] -> [ BengiDocument ] -> [ BengiUtil] -> [ BengiDataShow ]

[ BengiDataShow ] -----------------------------------------------

BengiDataShow = function() {    
// 상속
    inheritFrom( this, new BengiUtil() );
    this.xmlHttp = null;
    this.xjson = null;
}

3) 화면 인터페이스



var BengiDataShow = {        
    bgdatashow : function(xmlHttp, xjson) {                    
        setTitle('OK!!!!!!!!!============');    

        $('bgshow1').innerHTML = xmlHttp.responseText;            
        $('bgshow2').innerHTML = BrowserType;                
        
        printMsg('bgshow3', BrowserType );                                    
    }    
}
....

<div id="bgshow1">----</div>
<div id="bgshow2">----</div>
<div id="bgshow3">----</div>

<input type="button" id="okClick" value="실행결과 출력" onclick="BengiAjax('welcome.txt','pars=1','bgdatashow');" />

4) 서버단의 welcome.txt

AJAX STUDY 을 해보자

라는 글자의 텍스트만 있습니다.


[ 프로그램 Flow ]

[ 1단계 ]

위의 okClick 을 마우스로 선택하면 BengiAjax function 을 Call 하게 되어,
( 객체로 따로 만들어도 되지만, 이해하기 쉅게 최소한 간단하게 만들어 보았습니다. )
서버단의 welcome.txt 을 부릅니다. 인자는 여기에선 사용하지 않습니다.
3번째 파라메타 bgdatashow 는 결과을 받아 실행 할 함수 이름 입니다.

[ 2단계 ]

위의 1) 통신부분 : [ BengiUtil] -> [ BengiAjax ] 부분에서 onSuccess 단계로 오게 되면

if (BengiDataShow[callback] instanceof Function) {
BengiDataShow[callback].call( BengiDataShow, xmlHttp, xjson );
} else {
alert( '[ERROR]\n' +callback+'은 정의되지 않은 메소드입니다.');
}

위의 코드가 bgdatashow 을 불러주는 역활을 합니다.
( 이부분에 대해선 행복한 고니님 의 도움으로 해결 하였습니다. 감사합니다...^^ )

[ 3단계 ]

3) 화면 인터페이스에서 bgdatashow 을 부르게 되며 이제 상속을 받은 기능을 사용합니다.

// BengiDocument 의 setTitle 함수을 불러 타이틀을 변경하여 줍니다.
setTitle('OK!!!!!!!!!============');    

// prototype 을 이용하여 <div id="bgshow1">----</div> 에 결과값을 표현 합니다.
$('bgshow1').innerHTML = xmlHttp.responseText;            

// Bengi 의 BrowserType Attribute 에 값을 화면에 표현합니다
$('bgshow2').innerHTML = BrowserType;    

// 바로 위의 BrowserType 을 BengiUtil 의 printMsg function 을 이용하여 화면에 표현합니다
printMsg('bgshow3', BrowserType );                    
[ 결과화면 ]



----------------------------------------------------------------------
// 전체 소스 - default.js
----------------------------------------------------------------------

inheritFrom = function(/* Object */ aThis, /* Object */ aParent) {
var excp;
for (var property in aParent) {
try{
aThis[property] = aParent[property];
}
catch(excp){}
}
}

Bengi = function(name,doc) {    
this.detect = navigator.userAgent.toLowerCase();
    this.Dom = (document.getElementById) ? true : false;
    this.BrowserName =     navigator.appCodeName;
    
this.BrowserType = this.BrowserType();
this.BrowserVersion = this.BrowserVersion();
}

Bengi.prototype.BrowsercheckIt = function(string) {
    place = this.detect.indexOf(string) + 1;
    return place;
}

Bengi.prototype.BrowserType = function() {
    if ( this.BrowsercheckIt('konqueror')) Browser = "kq";
    else if (this.BrowsercheckIt('safari')) Browser = "Safari";
    else if (this.BrowsercheckIt('omniweb')) Browser = "OmniWeb";
    else if (this.BrowsercheckIt('opera')) Browser = "Opera";
    else if (this.BrowsercheckIt('webtv')) Browser = "WebTV";
    else if (this.BrowsercheckIt('icab')) Browser = "iCab";
    else if (this.BrowsercheckIt('msie')) Browser = "ie";
    else if (!this.BrowsercheckIt('compatible')) Browser = "ns"
    else Browser = "An unknown browser";
    return Browser;
}

Bengi.prototype.BrowserVersion = function() {
    if( this.BrowserType == "ie" ) {
        if ( ( this.detect.indexOf("msie")>-1 ) && this.Dom ) BrowserVersion = "5.0";
        else if ( document.all && !this.Dom) BrowserVersion = "4.0";
    }    
    else if( this.BrowserType == "ns" ) {
        if ( ( this.detect.indexOf("gecko")>-1 ) && this.Dom ) BrowserVersion = "5.0";
        else if ( document.layers && !this.Dom) BrowserVersion = "4.0";
    }
    else {
        BrowserVersion = 'unknown';
    }
    return BrowserVersion;
}

BengiDocument = function(name,doc) {
    inheritFrom( this, new Bengi( '', doc ) );        
}

BengiDocument.prototype.setTitle = function(value) {
    document.title = value;
}

BengiUtil = function() {    
    inheritFrom( this, new BengiDocument() );    
}

BengiUtil.prototype.printMsg = function(showid,msg)     {
console = document.getElementById(showid);
    console.innerHTML = msg; //msg.replace("/\n/g",'');    
}

BengiUtil.prototype.toConsole = function(showid,msg){
console = document.getElementById(showid);
if ( console != null ){
     console.width = '100%';
     console.align = 'center';
     console.innerHTML = msg;
}
}

BengiAjax = function( url, params, callback, showid, revtype, HttpMethod, debugmode, imgsrc, async, sload, user, password ) {
inheritFrom( this, new BengiUtil() );    
this.xmlHttp = null;
        
if(!url) url = "/error.php";    
if(!showid) showid = "bgshow";
if(!revtype) revtype = "TEXT";
f(!HttpMethod) HttpMethod = "POST";
        
new Ajax.Request( url, {
method : HttpMethod,
parameters : params,

onSuccess: function(xmlHttp, xjson) {
    if (BengiDataShow[callback] instanceof Function) {
     BengiDataShow[callback].call( BengiDataShow, xmlHttp, xjson );
    } else {
     alert( '[ERROR]\n' +callback+'은 정의되지 않은 메소드입니다.');
    }
}
});
}
        
BengiDataShow = function() {    
    inheritFrom( this, new BengiUtil() );
    this.xmlHttp = null;
    this.xjson = null;
}

----------------------------------------------------------------------
// 전체 소스 - default.php
----------------------------------------------------------------------

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>OOP</title>

<style>
body{
margin: 10px;
padding: 0;
font-size: 12px;
}    
</style>

<script language="javascript" type="text/javascript" src="./prototype.js"></script>
<script language="javascript" type="text/javascript" src="./default.js"></script>
<script language="javascript" type="text/javascript">
var BengiDataShow = {        
    bgdatashow : function(xmlHttp, xjson) {                    
        setTitle('OK!!!!!!!!!============');    

        $('bgshow1').innerHTML = xmlHttp.responseText;            
        $('bgshow2').innerHTML = BrowserType;                
        
        printMsg('bgshow3', BrowserType );                                    
    }    
}
</script>
</head>
<body>
<div id="firstDivision">
<div id="buttonArea">
<input type="button" id="okClick" value="실행결과 출력" onclick="BengiAjax('welcome.txt','pars=1','bgdatashow');" />
</div>
<br />
<div id="showArea">
<div id="bgshow1">----</div>
<div id="bgshow2">----</div>
<div id="bgshow3">----</div>        
</div>
</div>
</body>
</html>

----------------------------------------------------------------------
// 전체 소스 - welcome.txt
----------------------------------------------------------------------

AJAX STUDY 을 해보자


----------------------------------------------------------------------

질문에 답해 주신 행복한 고니님에게 감사 드리며,
질문에 관심을 가져 주신 공대 여자님에게도 감사 드립니다.

출처 : http://www.phpschool.com/gnuboard4/bbs/board.php?bo_table=tipntech&wr_id=54489&page=1


 추가내용 Javascript OOP Style

당연 널리 알려진것과 다른것은 없습니다...
Interface 까지 포한한 공개된것이 많이 있었지만 ( 작은 기능에 사용하기엔 너무 큼 ),
통신을 포함해서 핵심만 뽑아서 확장이 가능한것을 못 찾아 만들어본것입니다.

prototype 의 extend 은 객체 상속으로
객체의 속성 및 method 을 복사 받아서 확장하는것과
제가 나열한것과는 다른것입니다. ( object.create 부터 손볼것은 많이 있습니다만 )

new 을 이용한 생성도 고려 했지만, interface 울 꾸미지 않은 이상
PC 에 부하을 줄 필요없이 일부 영역에만 표현 할 때 사용하고자 만든이구요,
prototype.js 외의 연관성은 통신 부분을 제외하고, 출력 부분 몇개을 제외하곤 없습니다.

저는 더 잛은 능력이라 부끄럽습니다.

찾지을 못 했었는데 링크 감사합니다..^^
덕분에 다른것 하나 찾았네요..

http://www.webreference.com/js/tips/010213.html

[ 상속 ]

this.inheritFrom = superClass;
this.inheritFrom();

위의 2줄만 따로 변경하면 더 편할것 같습니다.

------------------------------------------

function superClass() {

  this.bye = superBye;
  this.hello = superHello;
 
  function superHello() {
    return "Hello from superClass";
  }
 
  function superBye() {
    return "Bye from superClass";
  }
}

function subClass() {
  this.inheritFrom = superClass;
  this.inheritFrom();
  this.bye = subBye;
 
  function subBye() {
    return "Bye from subClass";
  }
}

var newClass = new subClass();
alert(newClass.bye());
alert(newClass.hello());

-----------------------------------------

혹시, Bengi.prototype.xxxx 로 정의된것을 보고 prototype 많이 사용했다라고
하실것 같아 제가 파악한 2가지 방식을 아래에 나열 했습니다.

1) 따로 분리

      Bengi = function(name,doc) {    
          this.BrowserType    = this.BrowserType();
      }

      Bengi.prototype.BrowserType = function() {
          if ( this.BrowsercheckIt('konqueror')) Browser = "kq";
          ...........
          else Browser = "An unknown browser";
          return Browser;
    }

    Bengi.prototype.BrowsercheckIt = function(string) {
          place = this.detect.indexOf(string) + 1;
          return place;
      }

2) 객체 안에 전부 표현

    var Bengi = {        
        BrowserType : function(xmlHttp, xjson) {    
            ..........
        },
        BrowsercheckIt = function(string) {
            ..........
        }               
    }

링크 다시 한번 더 감사드립니다....꾸뻑


다른 Style OOP Javascript 참고 사이트

http://www.webreference.com/js/tips/010213.html
http://blog.naver.com/iheart2u/20033695668
http://www.crockford.com/javascript/