swf로 ajax를 대신하기
ajax기술은 여러 가지를 포함하고 있습니다. DHTML, DOMscript, javascript, XHR객체, XML파서, CSS 등을 버무려서 사용하는 기법을 현재의 ajax라 정의할 수 있습니다.
이 중 나머지는 알아서들 할 일이지만 XHR객체의 경우 여전히 까다롭고 브라우저간 호환성에 문제가 많이 생깁니다. 그래서 이를 중간층에서 막아주는 jquery 등을 사용합니다만, 반대로 이번엔 그 jquery를 사용하기 위한 여러 가지 문제가 추가적으로 발생합니다.
블로그 독자 여러분의 대부분이 as3쪽이 더 친하실거라 생각하여 ExternalInterface를 통해 다음과 같은 객체를 작성해봅시다.
package{
import com.bsidesoft.BSnet.*;
import flash.events.*
import flash.external.*;
import flash.utils.*;
[SWF(backgroundColor="#ffffff", frameRate="1", width="1", height="1")]
public class Main extends Sprite{
private var _listener:String;
private var _timers:Object = {};
private var _status:Dictionary = new Dictionary( true );
public function Main(){
ExternalInterface.addCallback( 'AAAXload', load );
ExternalInterface.addCallback( 'AAAXloop', loop );
ExternalInterface.addCallback( 'AAAXstop', stop );
}
private function stop( $key:String ):void{
if( _timers[$key] ){
_timers[$key].stop();
_timers[$key].removeEventListener( TimerEvent.TIMER, TIMER );
}
}
private function loop( $key:String, $url:String, $listener:String, $times:String, $interval:String ):void{
stop( $key );
_timers[$key] = new Timer( parseInt( $interval), parseInt( $times ) );
_timers[$key].addEventListener( TimerEvent.TIMER, TIMER );
_status[ _timers[$key] ] = {isFlushed:true, url:$url, listener:$listener};
_timers[$key].start();
}
private function TIMER( $e:TimerEvent ):void{
if( _status[ $e.target ].isFlushed ){
_status[ $e.target ].isFlushed = false;
CSloader.LOAD( CSloader.ARG.addTEXT( 'txt', _status[ $e.target ].url ).END( function( $data:Object ):void{
_status[ $e.target ].isFlushed = true;
ExternalInterface.call( _status[ $e.target ].listener, $data.txt );
} ) );
}
}
private function load( $url:String, $listener:String ):void{
_listener = $listener;
CSloader.LOAD( CSloader.ARG.END( hnLoaded ).addTEXT( 'txt', $url ) );
}
private function hnLoaded( $data:Object ):void{
ExternalInterface.call( _listener, $data.txt );
}
}
}
귀찮아서 회사 라이브러리가 있는 버전을 그냥 올렸습니다. 참고로 BSnet은 URLLoader, Sound, Loader를 전체적으로 완만하게 래핑하고 있는 데이터 로딩 클래스입니다.
이 클래스가 제공하는 서비스는 다음과 같습니다.
- 단순한 데이터 로딩을 지원하는 AAAload
- 연속으로 데이터를 로딩하여 이벤트를 발생시키는 AAAloop
- 진행 중인 loop를 정지시키는 stop
간단하게 이 클래스를 컴파일 한 뒤엔 아래와 같은 html을 작성하여 사용하게 됩니다.
<html>
<head>
<script language="JavaScript" type="text/javascript" src="main.js"></script>
<script language="JavaScript" type="text/javascript">
AAAX = {
_target:'',
load:function( $url, $listener ){
if( this._target ){
this._target.AAAXload( $url, $listener );
}else{
alert( 'setTaget을 먼저 호출하세요' );
}
},
loop:function( $key, $url, $listener, $times, $interval ){
if( this._target ){
this._target.AAAXloop( $key, $url, $listener, $times, $interval );
}else{
alert( 'setTaget을 먼저 호출하세요'+this._target );
}
},
stop:function( $key ){
if( this._target ){
this._target.AAAXstop( $key );
}else{
alert( 'setTaget을 먼저 호출하세요' );
}
},
setTarget:function( $id ){
if( document.getElementById( $id ) ){
this._target = document.getElementById( $id );
}else{
alert( $id + '는 존재하지 않는 객체입니다.' );
}
}
}
</script>
</head>
<body onload="AAAX.setTarget( 'aaax' );">
<script language="JavaScript" type="text/javascript">
AC_FL_RunContent(
'id', 'aaax','name', 'aaax',
'src', 'Main','movie', 'Main',
'width', '1','height', '1',
'wmode', 'gpu','scale', 'exactfit','loop', 'false','play', 'false','align', 'middle','quality', 'low','devicefont', 'false',
'bgcolor', '#02182e','menu', 'false','allowFullScreen', 'false','allowScriptAccess','sameDomain',
'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,0,0',
'pluginspage', 'http://www.adobe.com/go/getflashplayer','salign', ''
);
</script>
</body>
</html>
위의 html 매우 간단히 설명하면 사실 html이라기보다 AAAX자바스크립트 객체에 관한 설명인데, body의 onload에 걸려있는 setTarget을 통해 플래시 객체를 인지시킵니다.
이후 AAAX.load(), AAAX.loop() 등과 같은 형태로 사용할 수 있게 됩니다. 매우 흔한 ajax객체의 샘플인 2단계 select박스라면 아래와 같은 html코드로 설명할 수 있습니다.
<select id="category1" onchanged="hnChanged( this.value );" >
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
</select>
<div id="target"></div>
<script>
function hnChanged( $value ){
AAAX.load( 'getCat2.asp?cat1='+$value, 'hnLoaded' );
}
function hnLoaded( $data ){
document.getElementById( 'target' ).innerHTML = $data;
}
</script>
- 위의 예에서 셀렉트박스의 항목을 선택하면
- onchanged이벤트에 걸려있는 hnChanged 함수가 호출되고
- 함수 내부에 있는 AAAX.load가 호출됩니다.
- 이때 인자로 url과 로딩완료 리스너를 지정할 수 있는데 완료리스너의 경우 함수의 이름을 문자열로 보내면 됩니다.
- ‘hnLoaded’ 라고 보냈으므로 이 데이터가 로딩완료되면 자동으로 hnLoaded가 호출되며 인자로 로딩해온 데이터를 넘겨줍니다.
- 실제 자바스크립트의 hnLoaded함수에서는 받아온 데이터를 target DIV의 내용으로 써줄 뿐입니다.
- 두번째 select박스를 그리는 모든 html코드 조각은 이미 getCat2.asp가 생성해서 넘겨준 것이죠.
loop나 stop로 대동소이하게 작동합니다.