внешний интерфейс и проблема swfobject.js - PullRequest
2 голосов
/ 16 декабря 2011

Несколько месяцев назад для проекта на работе я разработал видеоплеер, используя flash, внешний интерфейс и swfobject.js. Я использовал внешний интерфейс для облегчения связи между JavaScript и ActionScript. Это прекрасно работает. В настоящее время я работаю над расширением этого, которое требует от меня экстраполировать логику из того, что я уже написал. Я использую один и тот же SWF-файл в обоих приложениях, но в расширении я не могу заставить объект Flash распознавать мои вызовы. Так как я использую тот же объект SWF, я знаю, что моя проблема в JavaScript, я просто не знаю, где. Я использую библиотеку JQuery. Без лишних слов вот мой код.

В нижней части моего файла JS у меня есть следующее:

$(function(){
     //the video player shouldn't be built until the user presses the div with 'video-btn' class
    $('.video-btn').click(function(){
         var videoplayer = new VideoPlayer();
         videoplayer.addVideoPlayer();
         //external interface function
         videoplayer.player.loadVideo();
    });
});

Вот определение для VideoPlayer.addVideoPlayer() и соответствующие вспомогательные функции:

//inside of VideoPlayer object definition
this.addVideoPlayer = function(){
     var that = this;
     $('body').append('<div id="no-flash"></div>');

     //uses swfobject.js to replace the div i just appended with the flash object
     //This works fine.  the flash object replaces the div as intended
     that.embedFlashObject();
     //that.player is (supposed to be) a reference to flash object
     that.player = that.getFlashObject();
};

this.embedFlashObject = function(){
     var that = this;

     //set up all the variables to pass to swfobject.embedSWF

     //this method removes my div and replaces it with an object element that contains the swf file
     //the object tag gets an id which is specified.  Let's assume it's 'vp'
     swfobject.embedSWF(swfFile, 'no-flash', width, hieght, '9.0.0', ... );
};

this.getFlashObject = function(){
     var that = this;

     //this method returns the flash object to make external interface calls on
     //this the method prescribed by swfobject api  
     var videoObj = swfobject.getObjectById('vp');
     if(typeOf videoObj == 'undefined')
     {
          //check if useragent string is IE
          var isIE = navigator.userAgent.match(/MSIE/i);
          videoObj = isIE ? window['vp'] : document['vp'];
     }
     return videoObj;
};

В моем блоке $(function(){..}); при выполнении команды 'videoplayer.player.loadMedia();' я получаю сообщение об ошибке

.loadMedia не является функцией.

В предыдущей версии этого проекта (в которой я использую тот же SWF-файл) я не получаю эту ошибку.

Я не думаю, что пропускаю какие-либо серьезные логические ошибки, и я знаю, что трудно сказать однозначно «это ваша проблема ...», глядя на сокращенный и вычеркнутый код. Вместо определенного ответа я приму предложения относительно того, как решить эту проблему. Я играл aorund в консоли браузера и обнаружил, что атрибут «player» моего объекта VideoPlayer имеет значение null. Когда я выполнял тот же консольный запрос к рабочей версии этого проекта, он выплевывает тег объекта. Я не могу напрямую установить тег объекта, потому что он порвет с соглашениями, использованными в предыдущей версии, которые мне нужно поддерживать.

HELP !!!!!!!!!!!!!!!

Ответы [ 5 ]

3 голосов
/ 21 декабря 2011

Итак, я понял, в чём была моя проблема.Несмотря на все мои усилия, чтобы быть сильным в описании проблемы, я пропустил один ключевой факт, который, вероятно, помог бы решить мою проблему.Я разрабатывал свое приложение локально, прежде чем перейти на реальный сервер разработки.При использовании флэш-приложения в локальном контексте связь из Интернета по умолчанию отключена.Если вы воспользуетесь Google «Настройки безопасности Adobe», одна из главных ссылок приведет вас на страницу настроек Adobe Security, где вы сможете выбрать папки на локальном компьютере, для которых вы хотите разрешить эту внешнюю связь.Мой SWF-файл попытался бы на раннем этапе установить соединение с нашими серверами, чтобы инициализировать внешние обратные вызовы, если он не может этого сделать, он просто ждет, и поэтому ни одна из моих функций не стала объявленной функцией.У меня действительно была эта проблема, когда я работал над первоначальной итерацией этого проекта, но не думал об этом до вчерашнего дня.

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

3 голосов
/ 19 декабря 2011

Функция обратного вызова SWFObject

Пожалуйста, ознакомьтесь с документацией SWFObject.https://code.google.com/p/swfobject/wiki/api

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

1 голос
/ 18 декабря 2011

Есть несколько возможных причин. Одним из наиболее распространенных является время - если вы попытаетесь получить доступ к ExternalInterface до того, как SWF будет готов, вы столкнетесь с ошибкой.

Порядок событий:

  1. SWFObject записывает <object> на страницу
  2. Плагин Flash Player инициализирует
  3. SWF загружен
  4. ExternalInterface инициализируется

Если вы попытаетесь вызвать метод ExternalInterface сразу после использования SWFObject, шаги со 2 по 4 могут еще не завершиться, что приведет к ошибке JS (метод не найден).

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

Кроме того, я заметил некоторые элементы в вашем коде, которые можно упростить или отредактировать, вот несколько советов:

  1. У вас есть опечатка внутри embedFlashObject: hieght должно быть height
  2. getFlashObject использует swfobject.getObjectById; в этом нет необходимости, swfobject.getObjectById требуется, только если вы используете статическую технику публикации SWFObject. Если вы используете динамическую публикацию, вы можете просто использовать функцию document.getElementById или jQuery $.
  3. getFlashObject имеет проверку для IE. Вы также можете использовать свойство SWFObject ua для получения информации: swfobject.ua.ie вместо navigator.userAgent.match(/MSIE/i)
  4. swfobject.createSWF может возвращать ссылку на недавно созданный <object>, поэтому вы можете упростить свой код.

    //inside of VideoPlayer object definition
    this.addVideoPlayer = function(){
    
        var that = this;
    
        if (swfobject.hasFlashPlayerVersion("9")){
    
            $('body').append('<div id="no-flash"></div>');
    
            //For legibility
            var swfdata = {
                data: swfFile,
                width: width,
                height: height
            };
    
            var params = { bgcolor: color };
    
            var id = 'no-flash';
    
            that.player = swfobject.createSWF(swfdata, params, id);
    
        }
    
    };
    

    Что может быть сжато до

    //inside of VideoPlayer object definition
    this.addVideoPlayer = function(){
        var that = this;
        if (swfobject.hasFlashPlayerVersion("9")){
            $('body').append('<div id="no-flash"></div>');
            that.player = swfobject.createSWF({data: swfFile, width: width, height: height}, {bgcolor: color}, 'no-flash');
        }
    };
    

    Это исключит необходимость использования методов embedFlashObject и getFlashObject.

0 голосов
/ 12 марта 2014

В FF вам нужно поместить свой код в элемент embed для правильного выполнения ExternalInterface, и на самом деле я думаю, что этот код не поддерживается в swfobject.js. Чтобы работать, вам также нужно установить classid, как в этом полном примере (http://code.google.com/p/flash-videoio/source/browse/trunk/examples/ichatnow/index.html)

<!doctype html>
<html style="width:100%; height: 100%;">
  <head>
  <title>I Chat Now</title>
  <style>
    body { margin: 0px; overflow:hidden; }
  </style>
  <script>
    function onCreationComplete(event) {
      console.log('onCreationComplete');
    }
  </script>
</head>
<body scroll="no" style="width:100%; height: 100%;">  
  <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
    id="video1" width="100%" height="100%"
    codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab">
    <param name="movie" value="VideoIO.swf" />
    <param name="quality" value="high" />
    <param name="bgcolor" value="#000000" />
    <param name="allowFullScreen" value="true" />
    <param name="allowScriptAccess" value="always" />
    <param name="flashVars" value="controls=true" />
    <embed src="VideoIO.swf" quality="high" bgcolor="#000000"
        width="100%" height="100%" name="video1" align="middle"
        play="true" loop="false" quality="high" 
        allowFullScreen="true" 
        allowScriptAccess="always" 
        flashVars="controls=true" 
        type="application/x-shockwave-flash" 
        pluginspage="http://www.adobe.com/go/getflashplayer"> 
    </embed> 
  </object>
</body>
</html>
0 голосов
/ 16 декабря 2011

Я чувствую твою боль. Я долго боролся с этим ...

Когда вы получаете сообщение "is not function", в основном происходит следующее: а) ваш javascript не может найти ваш экземпляр фильма. или же b) ваш скрипт действий неправильно отображает метод loadMedia ().

Всегда полезно иметь методы check () в вашем js и as. Они используются, чтобы гарантировать, что каждый элемент полностью загружен и готов к манипулированию / использованию. Есть несколько сообщений по этому поводу.

Вы заметили разницу между IE и Firefox? Один работает, а другой нет?

В следующем блоке:

var videoObj = swfobject.getObjectById('vp');
  if(typeOf videoObj == 'undefined')
  {
       //check if useragent string is IE
       var isIE = navigator.userAgent.match(/MSIE/i);
       videoObj = isIE ? window['vp'] : document['vp'];
  }
  return videoObj;

... вы, похоже, используете метод swfObject для получения фильма, но затем вы проверяете браузер и - СНОВА - просматриваете DOM для фильма. Вы пытались закомментировать следующий блок:

if(typeOf videoObj == 'undefined')
      {
           //check if useragent string is IE
           var isIE = navigator.userAgent.match(/MSIE/i);
           videoObj = isIE ? window['vp'] : document['vp'];
      }   

... и просто вернуть возвращенное значение swfobject?

Насколько я понимаю, swfObject будет обрабатывать обнаружение браузера для вас.

Кроме того, убедитесь, что swfobject фактически предоставляет html-объекту идентификатор ('vp').

...