0

I'm building an AIR desktop application. At one point the application loads a popup window (an MXML component based on s:Window), which contains an mx:HTML component which loads a local (in the application directory) html file, blank.html. The relevant elements in blank.html are:

<script src="jw/jwplayer.js"/> <!--JW Player's JS-based Embedder-->
...
<div id="jwtarget" /> <!-- the target that the embedder will use -->

Since the parameters I want to use are determined at runtime, I use the domWindow property to invoke the method which loads the player. Here's an example that works:

private function injectPlayer():void {
  var playerVars:Object = {};
  playerVars.flashplayer = "jw/player.swf";
  playerVars.file = "http://www.archive.org/download/meet_john_doe_ipod/meet_john_doe_512kb.mp4";
  playerVars.height = 360;
  playerVars.width = 640;

  try { // attempt to invoke the js function
    htmlComponent.domWindow.jwplayer("jwtarget").setup(playerVars);
  } catch(e:Error) {}

}

which is called when the page finishes loading by:

<mx:HTML id="htmlComponent" location="assets/blank.html" complete="injectPlayer()" />

That all works fine.

Now to the question. I need to be able to pass a more complex playerVars Object to the function, but I don't seem to be getting the syntax correct. Here's the simplest example I've been attempting:

private function injectPlayer():void {
  var playerVars:Object = {};
  //playerVars.flashplayer = "jw/player.swf";
  playerVars.file = "http://www.archive.org/download/meet_john_doe_ipod/meet_john_doe_512kb.mp4";
  playerVars.height = 360;
  playerVars.width = 640;
  playerVars.modes = [{"type":"flash","src":"jw/player.swf"}];

  try { // attempt to invoke the js function
    htmlComponent.domWindow.jwplayer("jwtarget").setup(playerVars);
  } catch(e:Error) {}

}

This code should create the exact same thing as the above code, but it fails to execute. I assume I need to change the syntax in some way to allow the array of Objects (modes) to be passed properly as a parameter to the js function.

I've tried various things, like passing the modes as a String, or putting the whole thing through JSON.stringify() first, but to no avail. Anyone know the correct way for constructing a complex object for a parameter?

Other details, if you haven't inferred them by now: Flex 4.5.1 is the SDK I'm building with, including the AIR 3.0 extensions (which means targeting FP11).

Update:

Another configuration I tried, which does work:

playerVars.modes = {"type":"flash", "src":"jw/player.swf"};

However, this still doesn't solve the problem that I should be able to pass an Array of Objects in the modes property. But at least this way loads the video player.

More Update:

So, I found this little section of code from jwplayer.js where I suspected the player loading was failing:

if (typeof parsedConfig.modes == "string") {
  _modes = _playerDefaults();
  _modes[0].src = parsedConfig.modes;
} else if (parsedConfig.modes instanceof Array) {  // I suspect this was eval'd as false
  _modes = parsedConfig.modes;
} else if (typeof parsedConfig.modes == "object" && parsedConfig.modes.type) {
  _modes = [parsedConfig.modes];
}

And to test my suspicion I added the following function to my blank.html:

<script type="text/javascript">
  var instanceOfArrayTest = function(arr) {
    return arr instanceof Array;
  }
</script>

And in my ActionScript code tried the following:

trace([1,2,3] is Array); // true
trace(htmlComponent.domWindow.instanceOfArrayTest([1,2,3])); // false!!!!

So, it seems that the problem is that ActionScript is not passing AS3 Array objects as JS Array objects!

15
  • playerVars.modes = [{"type":"flash"}]; Is this supposed to be an array with the first element an object? Commented Oct 17, 2011 at 22:26
  • @The_asMan - Yes. Normally one would include other possible modes, also as objects, eg. [{"type":"flash", "src":"player.swf"},{"type":"html5"},{"type":"download"}], which defines an order series of possible fallbacks. Hopefully, the fact that I forgot the '"src": "player.swf"' when initially posted the question didn't throw you off. I amended it as soon as I noticed. Commented Oct 18, 2011 at 1:22
  • Just seems odd to me that the parameter would be an array of objects but the objects only have one attribute. This all could be done on one object or an associative array. I am willing to bet its not set up correctly Commented Oct 18, 2011 at 15:18
  • @The_asMan - If you have a look at the JW Embedder Modes documentation on LongtailVideo, the API will make more sense. For example, one can also specify alternative files to be played per type object. Stuff like that comes in handy when, say, you want to offer HTML5 video that is valid for Chrome/IE (h264) and Firefox (ogg). The example in my question was supposed to be just enough to cause the video player not to load (when it should be ;), and certainly not much of a real world example. Commented Oct 18, 2011 at 16:51
  • Did you try playerVars.modes = [{"type":"flash","src":"player.swf"}]; if the player is in the same directory as jwplayer.js when jwplayer.js runs the function it will be relative to that file. Commented Oct 18, 2011 at 17:47

2 Answers 2

2

Try doing this instead:

playerVars.modes = [{type:"flash",src:"jw/player.swf"}];
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the suggestion @J_A_X. This didn't resolve the problem, but from my tests it is just as valid as the initial form that I put it in. That is, both this syntax and the one I used appear to have been parsed correctly in the object that the JS function returns. I'm beginning to think that perhaps the root of the problem might be different. :(
1

Unlike the call() method of the ExternalInterface class, the mx:HTML does not automatically convert AS3 classes to corresponding JS classes when they are passed as parameters to a JS function. Instead, the HTML Control maintains an environment where methods and properties native to the AS3 classes are preserved and made accessible to JS directly.

If a JS function requires a JS Array object, one must create the JS Array explicitly using the JavaScript Window object to access the JS Array constructor. The HTML Control provides access to this with it's domWindow property. Otherwise, there is no way to "cast" an AS3 Array to a JS Array.

Here's a basic example:

var JSArray:Function = htmlComponent.domWindow.Array;
htmlComponent.domWindow.instanceOfArrayTest( JSArray(1,2,3) ); // true

And for the more complex example using the config parameter for JW Player:

playerVars.modes = JSArray({"type":"flash","src":"jw/player.swf"},{"type":"html5"});

which creates a JS Array of two Objects.

For more info on the JavaScript environment in the HTML Control, check out the JavaScript in AIR section of Adobe's Developing AIR Applications with Flex.

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.