[AS3] swf가 임베드된 html 경로 알아내기

Programming/ActionScript 3.0 2008. 12. 25. 02:01
swf가 임베드 되어 있는 html의 도메인 경로를 알아내기 위해서는 아래와 같이 ExternalInterface를 이용하여 자바 스크립트 문법에 도움을 받아 location 경로를 리턴 받을 수 있다.

var locationUrl:String = ExternalInterface.call("document.location.href.toString");

그러나 이렇게 했을 경우 하나의 문제가 있다.

만약 임베드된 object의 id값을 설정하지 않거나 설정하더라도 동영상 플레이어처럼 여러 개의 swf를 하나의 페이지에 임베드 할 경우에는 오브젝트의 id값이 같기 때문에 ExternalInterface를 이용하여 자바스크립트 함수를 호출할 수 없는 상황이 발생한다. ExternalInterface를 사용할 경우 아래와 같은 경우에는 자바스크립트를 호출할 수 없다.

HTML 페이지의 Flash Player 인스턴스에 제공된 이름(object 태그의 id 속성)에 JavaScript에서 연산자로 정의된 하이픈(-)이나 다른 문자가 포함되어 있으면(예: +, *, /, \, . 등) Internet Explorer에서 컨테이너 웹 페이지를 보면서 ActionScript에서 ExternalInterface를 호출할 수 없습니다.
뿐 만 아니라 Flash Player 인스턴스를 정의하는 HTML 태그(object 및 embed 태그)가 HTML form 태그에 중첩되어 있는 경우에도 ActionScript에서 ExternalInterface가 호출되지 않습니다.

따라서 하나의 html 페이지에 여러 개의 같은 swf를 임베드 할 경우에는 각각의 object 아이디를 다르게 설정해 주어야 한다. 그러나 상황에 따라서 중첩되는 object태그들의 id를 서로 다르게 부여하기 위해서는 여러 가지 난제가 있을 수 있다. 그렇다면 object 의 id 값을 같게 하더라도 자바스크립트 함수를 호출할 수 있는 방법이 없을까? 위와 같은 상황이라면 IE가 파이어폭스처럼 object id가 같은 상황이라도 ExternalInterface가 자바스크립트 함수를 호출해 줄 수 있을 때까지 기다리거나 ExternalInterface가 위와 같이 호출할 수 없는 상황이 발생하지 않기를 바랄 수밖에 없다. 그렇다고 해결할 수 없는 문제로 남기기에는 플래시가 서운할 것이다. object id가 같아도 ExternalInterface가 자바스크립트 함수를 호출할 수 있도록 만들어 보자.

방법은 ActionScript에서 요긴하게 사용할 수 있는 SharedObject 객체이다. SharedObject객체는 기본적으로 도메인당 최대 100KB의 데이터로 공유 객체를 만들 수 있다. SharedObject의 data속성에는 String, Array, Number, Boolean, ByteArray, XML와 같은 공유 객체를 담을 수 있다.

위에서 언급한 상황처럼 같은 swf가 여러 개 임베드 되어 있고 object id가 같을 경우 IE에서는 첫번째 임베드 되어 있는 swf에서는 정상적으로 ExternalInterface를 통하여 자바스크립트를 호출해 준다. 그러나 아래에 임베드된 swf에서는 자바스크립트를 호출하지 못한다. 따라서 첫번째 임베드된 코드에서 제대로 리턴 받은 경로를 SharedObject를 이용하여 flush(쓰기)를 하고, 반면 ExternalInterface를 통해서 리턴 받은 값이 “null”일 경우에는 SharedObject를 통해서 저장된 기존의 domain 경로를 불러와서 사용하는 것이다.

아래는 그러한 방법으로 처리한 코드 예이다.

private function getLocationUrl():String
{
    var domain:String = String( ExternalInterface.call(" function(){ return document.location.href.toString();}"));
    var so:SharedObject = SharedObject.getLocal("location");
   
    if (domain != "null"){
        so.data.domain = domain;
        so.flush();
    }else{
        domain = so.data.domain
    }
   
    return domain;
}

위 방법은 그럴듯 하다. 그런데 문제가 있다. 브라우저가 자바스크립트를 호출해 주는 object를 먼저 참조하지 않는다는 것. 따라서 위 방법으로 했을 경우 페이지를 한 차례 재로드해 줘야 제대로 적용이 된다.

결국 object id 값을 서로 다르게 설정하는 것으로 가야만 했다는... 삽질의 길은 멀고도 험하구나...

    

설정

트랙백

댓글

  • 쿠나 2008.12.25 12:32 ADDR 수정/삭제 답글

    글 잘 읽었습니다. SharedObject를 이렇게 이용할 수 있네요
    더불어 도메인을 javascript를 이용하지 않고 Actionscript를 이용해서 구하는 방법도 잘 보고 갑니다 :D

    • jasu 2008.12.27 11:12 신고 수정/삭제

      동영상 플레이어와같은 형태의 퍼가기 기능의경우는 퍼가는 소스에 자바스크립트 함수를 포함할 수 없기 때문에 플래시 내에서 이런 형태로 호출하기도 합니다.

  • 경훈 2008.12.29 00:01 ADDR 수정/삭제 답글

    allowScriptAccess 가 never 로 되어있을 경우도 알려주세욧!! ^ ^~
    저 월,화 휴가에요, 31일에 보겠네요, 열흘만에 보는듯 쿠쿠~
    저 없다고 심심해하지 마세요~ 쿠쿠

    • jasu 2009.01.01 02:11 신고 수정/삭제

      쿠쿠 never일 경우 자바스크립트를 호출하는데 문제가 있겠지~ 설마 없다고 심심해 할까 ^^

블로그의 올플래시 페이지 infinite 메뉴 추가

Project/Web 2007. 4. 15. 02:26
예전 방문자 카운터 기능을 추가하면서 생각한 것이 있었다. div로 iframe을 잡고 상위 레이어를 올리면 올플래시 형태의 페이지를 만들 수 있을 거라는 생각에서 시도해 보았다.

이 구조를 넣으면서 여러가지 문제점이 생겼는데 문제점들은 아래와 같다.


1. 자바스크립트에서 플래시로 값을 넘겨주기 위해서는 플래시에서 ExternalInterface 클래스를 사용하게 된다. 이 클래스를 이용하면 html에 삽입된 javascript와 플래시간 상호 지정한 function을 호출할 수 있으며 return값도 전달 할 수 있다.
하지만 배경 화면에 해당하는 플래시에서 티스토리 스킨에 제공하고 있는 skin.html안에 삽입된 자바스크립트를 호출하는 것은 가능하나 그 자바스크립트에서 플래시로 값을 넘겨주지 못하는 문제점이 있다. 아마도 크로스 도메인 문제인 듯 싶다.

하루정도 고민 하다가 결국은 우회하기로 결정했다. 일단 하단에 있는 메뉴플래시에서 infinite 버튼을 클릭할 시에 상위에 있는 레이어를 display = block을 적용하고 플래시의 LocalConnection을 이용하여 레이어 안에 있는 플래시와 통신을 하는 방법이다.
여기도 또다시 문제점이 발생했는데 하위 플래시에서 레이어를 살리는 동시에 상위 플래시와 통신을 할 경우에는 기존에 있던 플래시가 포함된 레이어가 작동을 정지하면서 제대로 호출해주지 않는 문제가 발생했다. Display를 대신해 visibility을 이용해 보았지만 마찮가지였다.

상위 레이어가 살아났을 때 플래시에 레이어가 나타났다는 메시지를 전달함으로써 infinite의 초기 시작 모션을 적용해야 하는데 그 문제가 해결되지 않아서 발생하는 문제점이다.

익스플로러와 파이어폭스 두 브라우저에서 테스트해본 결과 두 브라우저 간의 약간의 차이가 발생했다.

그래서 LocalConnection으로 플래시간 통신을 하되 약간은 딜레이 타임을 적용하기로 하고 레이어를 살리고 초기 시작 모션들 들어가기 전에 0.5초간 로딩바를 보여주는 형태로 LocalConnection의 문제점을 해결했다. 사실 해결이라기보다는 궁여지책이다.


2. 두번째 문제는 익스플로러와 파이어폭스의 호환 문제다. document.all는 IE에서만 먹는 코딩 방식이라는 것을 알게 되었다.
보 통 IE에서 div의 style이나 레이어에 접근하기 위한 접근자 방식을 document.all.ID.style.display이런 형태로 썼는데, 이러한 코딩방식은 파이어폭스나 타 브라우저에서는 먹히지 않는 방식이다. MSDOM에서만 사용하는 것이며 W3C에서도 권하지 않는 방법이라고 한다. 우리나라의 경우는 90% 가량이 IE를 사용하고 있는 상황이기 때문에 IE를 사용하고 있다면 별 문제가 되지 않겠지만 타 브라우저를 사용하는 사용자에게는 치명적인 문제를 발생시킨다. 공든 탑이 이러한 표준 문제에서 무너질 수 있다.

W3C에서 권장하는 표준형은 document.getElementById("ID").style.display 이러한 형태로 접근하는 것이다.


3. 세번째 문제는 티스토리에 로그인한 상태에서 블로그에 접근했을 때는 오른쪽 상단에 티스토리 툴바가 보이게 된다.  테스트 과정에서 레이어의 index값을 아무리 올려도 상위에 있는 레이어보다 티스토리 툴바가 상위에 떠있는 것이다. 그래서 블로그 소스를 뒤져보니 상위에 뜨는 툴바의 index값이 무려 1000000라는 사실… 그래서 상위에 뜨는 레이어의 index 값을 1000001로 잡아서 해결했다.


4. 네번째는 문제라기 보다는 레이어를 올리는 과정에서 생겨난 부가적인 노동이다. 블로그에서 음악이 흘러나오도록 play를 시켜놓은 상태에서 infinite 페이지로 들어갔을 때는 끄고, play되고 있던 사용자라면 다시 나올 때 play를 시켜주는 것이다. 그리고 음악을 듣지 않고 있던 사용자라면 그대로 음악이 흘러나오지 않는 기능을 추가해야 했다. 그리고 블로그의 배경에서 랜덤으로 생겨나는 나비의 움직임이 infinite 페이지를 접근했을 때에 불필요하게 CPU의 낭비를 가져오고 있어서 infinite메뉴로 들어갔을 때는 나비들이 생성하지 않도록 interval을 clear시켜주고 다시 블로그로 나갔을 때는 생성하도록 설정해 놓았다.


Infinite메뉴를 추가하면서 가장 큰 문제는 자바스크립트에서 플래시로 통신하기가 어렵다는 것이 가장 큰 문제였던 것 같다. 일단 지금은 LocalConnection을 이용하여 플래시 간에 주거니 받거니 하고 있으니 나중에 알게 되면 수정해야 겠다.

Infinite 메뉴는 아직 구체적은 내용 구성과 구현 방법에 대해서는 생각해 둔 것은 없다. 일단 블로그에서 새로운 시도를 해본 것이고 캠버스에 어떤 것들을 담아갈지는 앞으로 시간 날 때 고민해 봐야 하겠다.

사용자 삽입 이미지


    

설정

트랙백

댓글

  • 2007.06.23 22:31 ADDR 수정/삭제 답글

    비밀댓글입니다