/***************************************************** * * Copyright 2009 Adobe Systems Incorporated. All Rights Reserved. * ***************************************************** * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * * The Initial Developer of the Original Code is Adobe Systems Incorporated. * Portions created by Adobe Systems Incorporated are Copyright (C) 2009 Adobe Systems * Incorporated. All Rights Reserved. * *****************************************************/ package org.osmf.containers { import flash.errors.IllegalOperationError; import flash.external.ExternalInterface; import flash.utils.Dictionary; import org.osmf.elements.HTMLElement; import org.osmf.elements.ProxyElement; import org.osmf.events.ContainerChangeEvent; import org.osmf.media.MediaElement; import org.osmf.traits.*; import org.osmf.utils.OSMFStrings; /** * HTMLMediaContainer is an IMediaContainer-implementing class that uses ExternalInterface * to expose the container's child media elements to JavaScript. * * @includeExample HTMLMediaContainerExample.as -noswf * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion OSMF 1.0 */ public class HTMLMediaContainer implements IMediaContainer { // IMediaContainer // /** * @private */ public function addMediaElement(child:MediaElement):MediaElement { requireExternalInterface; if (child == null) { throw new IllegalOperationError(OSMFStrings.getString(OSMFStrings.NULL_PARAM)); } // Find out if the element at hand is an HTML element or not: var htmlElement:HTMLElement = elementAsHTMLElement(child); if (htmlElement == null) { throw new IllegalOperationError(OSMFStrings.getString(OSMFStrings.UNSUPPORTED_MEDIA_ELEMENT_TYPE)) } var result:MediaElement; var elementId:String = "element_" + elementIdCounter++; var elementScriptPath:String = containerScriptPath + "elements." + elementId + "."; elements[elementId] = htmlElement; htmlElement.scriptPath = elementScriptPath; ExternalInterface.call(containerScriptPath + "__addElement__", elementId); // Media containers are under obligation to dispatch a gateway change event when // they add a media element: child.dispatchEvent ( new ContainerChangeEvent ( ContainerChangeEvent.CONTAINER_CHANGE , false, false , child.container, this ) ); return child; } /** * @private */ public function removeMediaElement(child:MediaElement):MediaElement { requireExternalInterface; if (child == null) { throw new IllegalOperationError(OSMFStrings.getString(OSMFStrings.NULL_PARAM)); } var elementId:String = getElementId(child); if (elementId == null) { throw new IllegalOperationError("Element is not a child element"); } delete elements[elementId]; ExternalInterface.call ( containerScriptPath + "__removeElement__" , elementId ); // Media containers are under obigation to dispatch a gateway change event when // they remove a media element: child.dispatchEvent ( new ContainerChangeEvent ( ContainerChangeEvent.CONTAINER_CHANGE , false, false , child.container, null ) ); return child; } /** * @private */ public function containsMediaElement(child:MediaElement):Boolean { for each (var element:HTMLElement in elements) { if (element == child) { return true; } } return false; } // Public API // /** * Constructor. * * @param containerIdentifier The identifier that will be used for this container * in JavaScript. If no identifier is specified, a random one will be generated. * * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion OSMF 1.0 */ public function HTMLMediaContainer(containerIdentifier:String = null) { _containerIdentifier = containerIdentifier || ( "OSMF_HTMLMediaContainer_" + instanceCounter + "_" + Math.round(0xffffffff * Math.random()) ); initialize(); instanceCounter++; } // Internals // private function initialize():void { requireExternalInterface; containerScriptPath = "document.osmf.mediaContainers." + ExternalInterface.objectID + "_" + _containerIdentifier + "."; ExternalInterface.marshallExceptions = true; ExternalInterface.addCallback("osmf_getProperty", getPropertyCallback); ExternalInterface.addCallback("osmf_setProperty", setPropertyCallback); ExternalInterface.addCallback("osmf_invoke", invokeCallback); ExternalInterface.call ( registerContainer_js , ExternalInterface.objectID , _containerIdentifier ); } private var elements:Dictionary = new Dictionary(); private var elementIdCounter:int = 0; private var _containerIdentifier:String; private var containerScriptPath:String; private function get requireExternalInterface():* { if (ExternalInterface.available == false) { throw new IllegalOperationError("No ExternalInterface available"); } return undefined; } private function getElementId(element:MediaElement):String { var result:String; for (var index:String in elements) { if (elements[index] == element) { result = index; break; } } return result; } private function getPropertyCallback(elementId:String, property:String):* { var result:*; var element:HTMLElement = elements[elementId]; if (element) { result = element.getPropertyCallback(property); } return result; } private function setPropertyCallback(elementId:String, property:String, value:*):void { var element:HTMLElement = elements[elementId] as HTMLElement; if (element) { element.setPropertyCallback(property, value); } } private function invokeCallback(elementId:String, method:String, args:Array):* { var result:*; if (elementId == null) { switch (method) { // Container case "trace": if (args.length) { trace("JavaScript says:", args[0]); } break; default: throw new IllegalOperationError ( "Method '" + method + "' invoked from JavaScript is not supported on a Container." ); break; } } else { var element:MediaElement = elements[elementId]; if (element) { switch (method) { // Currently no methods... default: throw new IllegalOperationError ( "Method '" + method + "' invoked from JavaScript is not supported on a MediaElement." ); break; } } else { throw new IllegalOperationError ( "Unable to resolve the element with identifier '" + elementId + "' on invoking the '" + method + "' method from JavaScript." ); } } return result; } // Utils // private static function elementAsHTMLElement(element:MediaElement):HTMLElement { var result:HTMLElement; if (element != null) { if (element is ProxyElement) { return arguments.callee(ProxyElement(element).proxiedElement) } else { result = element as HTMLElement; } } return result; } // JavaScript API // private static const utils_js:XML = ; private static const constants_js:XML = ; // Defines the JS Container class: private static const container_js:XML = ; // Defines the JS MediaElement class: private static const mediaElement_js:XML = ; // Defines the logic that sets up the document.osmf object, adding a container: private static const registrationLogic_js:XML = ; private static const registerContainer_js:XML = new XML ( "" ); private static var instanceCounter:int; } }