2

Several months ago for a project at work i developed a video player using flash, external interface and swfobject.js. I used external interface to facilitate communication between javascript and actionscript. This works great. Currently I am working on an extension to this that requires me to extrapolate logic from what i already written. I am using the same swf file in both applications, but in the extension i can't get the flash object to recognize my calls. Since i am using the same swf object i know that my problem is in the javascript, i just don't know where. I am using the JQuery Library. Without further adieu here's my code.

At the bottom of my js file i have the following:

$(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();
    });
});

Here's the definition for VideoPlayer.addVideoPlayer() and it's relevant helper functions:

//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;
};

In my $(function(){..}); block, when the command 'videoplayer.player.loadMedia();' I get an error that reads

.loadMedia is not a function.

In the previous version of this project (in which i use the exact same swf file) i do not get this error.

I don't think i am missing any severe logical errors, and i know its difficult to say definitively 'this is your issue,....' when looking at abbreviated and scrubbed code. In lieu of a definite answer i'll take suggestions as to how to debug this issue. I've been playing aorund in the browser console and i've found that the 'player' attribute of my VideoPlayer object is null. When i ran the same console query against the working version of this project it spits back the object tag. I can't directly set the object tag, because it will break with the conventions used in the previous version which i need to maintain.

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

5 Answers 5

3

SWFObject Callback function

Please go through the documentation of SWFObject. https://code.google.com/p/swfobject/wiki/api

All the functions for creating or embedding SWF has a callback parameter. You can pass a callback function as parameter which will be invoked when SWF is ready. Invoke your ExternalInterface actionscript function in this callback function.

Example:

swfobject.embedSWF("/Flash/Player.swf", "flash", "100%", "100%", swfVersionStr, xiSwfUrlStr, flashvars, params, attributes, function (e) {
    document.getElementById("flash").loadMedia();
});
Sign up to request clarification or add additional context in comments.

2 Comments

I hadn't noticed that before in the documentation. It's an interesting and useful feature, but it doesn't not solve my problem. now i get an error that reads document.getElementById("flash").loadMedia is not a function, however i placed an alert in the callback function and that fired just fine. SwfObject is definitely putting the object element on the page.
Hope you have set "AllowScriptAccess" parameter. Could you please share the actionscript statement which adds the ExternalInterface callbak ?
3

So i figured out what my problem was. Despite my best efforts to be robust in description of the problem, i left out one key fact that would probably have helped to solve my issue. I was developing my application locally before moving to an actual development server. When using a flash application in a local context, communications from the internet are disabled by default. If you google 'adobe security settings', one of the top links will take you to an adobe security settings page where you can cchose folders on your local machine that you want to allow this external communication. My swf file would tries early on to make a connection to our servers befor initializing the external call backs, if it can't do that it just waits, and thus none of my functions were becoming declared functions. I actually had this problem when working through my initial iteration of this project, but didn't think of it until yesterday.

Thank you for everyone who supplied solutions. Having done this twice i can vouch for the fact that everything that has been suggested here is something that might hold a person up while trying to program and external interface flash application.

1 Comment

You should provide the link to 'adobe security settings' URL, so others don't have to search for it. Search results change over the years
1

There are a number of possible causes. One of the most common is timing -- if you try to access ExternalInterface before the SWF is ready, you will encounter an error.

Order of events:

  1. SWFObject writes the <object> to the page
  2. Flash Player plugin initializes
  3. SWF is loaded
  4. ExternalInterface is initialized

If you try to invoke the ExternalInterface method immediately after using SWFObject, steps 2 through 4 might not have completed yet, which would throw a JS error (method not found).

In these cases, you might want to experiment with a timer to see if it changes your outcome. Here's an example you can use.

Also, I noticed some items in your code that could be simplified or edited, here are some suggestions:

  1. You have a typo inside embedFlashObject: hieght should be height
  2. getFlashObject uses swfobject.getObjectById; this is not necessary, swfobject.getObjectById is only required if you're using SWFObject's static publishing technique. If you're using dynamic publishing, you can just use document.getElementById or jQuery's $ function.
  3. getFlashObject has a check for IE. You can use SWFObject's ua property to get the info, too: swfobject.ua.ie in place of navigator.userAgent.match(/MSIE/i)
  4. swfobject.createSWF can return a reference to the newly created <object>, so you might be able to simplify your code.

    //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);
    
        }
    
    };
    

    Which could be condensed to

    //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');
        }
    };
    

    This would eliminate the need for your embedFlashObject and getFlashObject methods.

Comments

0

I feel your pain. I fought with this for a long time myself...

When you get the "is not a function" message, basically what's happening is that either: a) your javascript can't find your movie instance. or b) your actionscript is not properly exposing the loadMedia() method.

It's always a good idea to have check() methods in your js and your as. They are used to ensure each element has fully loaded and is ready for manipulation/use. There are a number of posts regarding this.

Have you noticed a difference between IE and Firefox? Does one work, but the other not?

In the following block:

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;

...you seem to be using swfObject's method to retrieve the movie, but then you are checking the browser and - AGAIN - looking in the DOM for the movie. Have you tried commenting out the following block:

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

...and just return the swfobject returned value?

As I understand it, swfObject will handle the browser detection for you.

Also, check that swfobject is actually giving the html object an id ('vp').

Comments

0

In FF you need to put your code inside an embed element for the correct execution of ExternalInterface and actually I think this code is not supported in swfobject.js. In order to work you need also to set a classid like this full example (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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.