Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Observer JS <---> AS (http://www.flasher.ru/forum/showthread.php?t=111174)

ALiEN_ 17.04.2008 17:08

Observer JS <---> AS
 
В проектах часто необходимо использовать связки JS с FLASH... Раньше использовался getURL, fscommand, сейчас ExternalInterface, но способ использования обычно ограничивался на вызовове разных функций.
Эта система работала хорошо, но приходилось заранее продумывать систему общения, задавать имена функций.
Если немного подумать, можно схитрить и использовать всего две функции, одну входящую для JS и одну входящую для Flash, тогда отдавая в функцию два параметра, первый из которых "евент" и второй системный параметр, можно все упростить. Внутри функций можно написать простой парсер на switch и строить схему по входящим евентам.
Эта схема не плоха и действует безукоризненно, пока колличество евентов не переваливает за сотню.

Во флеше, очень удобна встроенна система евентов, но как было бы удобно если бы эта же система евентов распространилась и на JS.

Например, JS говорит - flashMovie.addJSListener ( "click", myJSFunction ); и флешка добавляет слушателя, а при генерации события "click", любые подписанные на событие слушатели в JS получат уведомление.

Теперь собственно вопросы:
- А как делаете это взаимодействие Вы?
- Есть ли какие-то готовые решения?

akerka 18.04.2008 12:38

Сделать то можно все что угодно. Вопрос размеров конечного JS файла. Проще использовать конкретные вызовы чем разрабатывать механизм прозрачного обмена сообщениями, производительный и небольшой по объему.

ALiEN_ 21.04.2008 15:18

Вобщем вот набросок, рабочий. Если кому надо, юзайте.

Код:

package
{
       
        import flash.display.Sprite;
        import flash.events.*;
        import flash.external.*;
       
        public class JSListener extends Sprite
        {
               
                private var externalHandlers = [];
               
                static private var self;
               
                static public function instance ():JSListener
                {
                       
                        if ( !self ) self = new JSListener ();
                       
                        return self;
                       
                }
               
                public function JSListener ():void
                {
                       
                        ExternalInterface.addCallback ( "addJSListener", addJSListener );
                       
                }
                               
                public function addJSListener ( eventName:String, functionName:Function ):void
                {
                       
                        externalHandlers = {};
                       
                        if ( !( eventName in externalHandlers ) ) externalHandlers [ eventName ] = [];
                       
                        externalHandlers [ eventName ].push ( functionName );
                       
                }
               
                public function JSEvent ( ev, param1 = null, param2 = null ):void
                {
                       
                        var event:Array = ( ( externalHandlers [ ev.name ] || [] ) as Array ).concat ( ( externalHandlers [ '__all__' ] || [] ) as Array );
                       
                        var o:Object = joinObjects ( param1, param2 );
                       
                        for ( var i:uint = 0, len = event.length; i < len; i++ ) ExternalInterface.call ( event [ i ], o );
                         
                }
               
                private function joinObjects ( a:Object, b:Object ):Object
                {
                       
                        var c:Object = {};
                       
                        for ( var i in a ) c [ i ] = a [ i ];
                       
                        for ( i in b ) c [ i ] = b [ i ];
                       
                        return c;
                       
                }
                               
        }
       
}

В классе так же предусмотрен евент "__all__", это если JSхочет слушать все события.


Использовать можно например так:

Код:

var jsEvent = JSListener.instance ().JSEvent;

jsEvent( { type:"my_event" } );

Т.е. добавляем ссылку на синглтон в область видимости класса. И генерим события.

Единственное что смущает, это то что приходится создавать синглтон и проводить инициализацию. Может можно сделать более красивое решение?

ALiEN_ 25.04.2008 17:51

Доработал класс. Некоторые возможности:

- прозрачная генерация и получение событий (JS <-> AS, AS <-> AS, JS <-> JS);

http://qwehkwerjhbgkwe.livejournal.com/51060.html

Psycho Tiger 26.04.2008 13:08

Большое спасибо за класс.
ЗЫ, я думаю тему есть смысл переместить в ФАК.

ALiEN_ 26.04.2008 14:21

Надо чтобы гуру форума заценили для начала ) Класс ведь реально весьма полезный и многим пригодится.
На всякий случай добавлю сюда код, т.к. в жж он побился.

Вот некоторые возможности:

- прозрачная генерация и получение событий ( JS <-> AS, AS <-> AS, JS <-> JS );
- возможность использовать флешку чисто, как обсервер для JS;
- возможность рассылать события бродкастом, т.е. нам все равно где находится подписчик какая у него глубина вложенности и т.д.;
- не имеет значения, где находится подписчик во флеш или в JS и не важно кто сгенерит событие.
- есть событие __all__, при подписке к которому подписчик будет слышать вообще все евенты.

Код:

package
{

       
        import flash.external.*;
       
       
       
        public class EManager extends Object
        {
               
               
                private var externalHandlers = [];
               
                static private var _inst:EManager;
               
               
               
                static public function get inst ()
                {
                       
                        if ( !_inst ) _inst = new EManager ();
                       
                        return _inst;
                       
                }
               
               
               
                public function EEventDispatcher ():void
                {
                       
                        ExternalInterface.addCallback ( "subscribe", subscribe );
                       
                        ExternalInterface.addCallback ( "unsubscribe", unsubscribe );
                       
                        ExternalInterface.addCallback ( "notify", notify );
                       
                }
               
               
               
                public function subscribe ( event:String, handler ):void
                {
                       
                        if ( !( event in externalHandlers ) ) externalHandlers [ event ] = [];
                       
                        externalHandlers [ event ].push ( handler );
                       
                }
               
               
               
                public function unsubscribe ( event:String, handler ):void
                {
                       
                        var handlers:Array = externalHandlers [ event ];
                       
                        if ( handlers )
                                for ( var i:uint = 0, len = handlers.length; i < len; i++ )
                                        if ( handlers [ i ] == handler )
                                        {       
                                       
                                                handlers.splice ( i, 1 );
                                               
                                                break;
                                               
                                        }
                       
                }
                       

               
                public function notify ( event:String, params:Object = null ):void
                {
                       
                        var handlers:Array = ( ( externalHandlers [ event ] || [] ) as Array ).concat ( ( externalHandlers [ '__all__' ] || [] ) as Array );
                                               
                                               
                        for ( var i:uint = 0, len = handlers.length; i < len; i++ )
                        {

                                if ( handlers [ i ] instanceof Function )
                                        handlers [ i ] ( params );
                                else
                                        ExternalInterface.call ( handlers [ i ], params );
                                                               
                        }
                         
                }
               
                               
        }
       
}

Пример использования:
Например подпишемся на евент прямо во флеше, и получим его:
Код:

EManager.inst.subscribe ( "myEvent", myFunc );

EManager.inst.notify ( "myEvent", { param1:"a", param2:"b" } );

function myFunc ( e )
{
       
        trace ( e.param1 + " " + e.param2 );
       
} // a b

подписка от JS происходит точно так же =)

BlooDHounD 26.04.2008 18:02

ничё прозрачного я в этом не вижу.

ALiEN_ 27.04.2008 15:01

а что именно смущает?

BlooDHounD 27.04.2008 20:05

собственно вся конструкция и смущает.

ALiEN_ 27.04.2008 22:16

во всяком случае, я еще альтернатив не видел.


Часовой пояс GMT +4, время: 06:38.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.