@qooxdoo/framework
Version:
The JS Framework for Coders
355 lines (297 loc) • 10.7 kB
JavaScript
/* ************************************************************************
qooxdoo - the new era of web development
http://qooxdoo.org
Copyright:
2004-2008 1&1 Internet AG, Germany, http://www.1und1.de
License:
MIT: https://opensource.org/licenses/MIT
See the LICENSE file in the project's top-level directory for details.
Authors:
* Sebastian Werner (wpbasti)
* Christian Hagendorn (chris_schmidt)
======================================================================
This class contains code based on the following work:
* SWFFix
http://code.google.com/p/swffix/
Version 0.3 (r17)
Copyright:
(c) 2007 SWFFix developers
License:
MIT: http://www.opensource.org/licenses/mit-license.php
Authors:
* Geoff Stearns
* Michael Williams
* Bobby van der Sluis
************************************************************************ */
/**
* Flash(TM) embed via script
*
* Include:
*
* * Simple movie embedding (returning a cross-browser working DOM node)
* * Support for custom parameters and attributes
* * Support for Flash(TM) variables
*
* Does not include the following features from SWFFix:
*
* * Active content workarounds for already inserted movies (via markup)
* * Express install support
* * Transformation of standard conformance markup to cross browser support
* * Support for alternative content (alt text)
*/
qx.Class.define("qx.bom.Flash",
{
/*
*****************************************************************************
STATICS
*****************************************************************************
*/
statics :
{
/**
* Saves the references to the flash objects to delete the flash objects
* before the browser is closed. Note: it is only used in IE.
*/
_flashObjects: {},
/*
---------------------------------------------------------------------------
CREATION
---------------------------------------------------------------------------
*/
/**
* Creates an DOM element
*
* The dimension of the movie should define through CSS styles {@link qx.bom.element.Style}
*
* It is possible to add these parameters as supported by Flash movies:
* http://helpx.adobe.com/flash/kb/flash-object-embed-tag-attributes.html
*
* @param element {Element} Parent DOM element node to add flash movie
* @param attributes {Map} attributes for the object tag like id or mayscript
* @param variables {Map?null} Flash variable data (these are available in the movie later)
* @param params {Map?null} Flash parameter data (these are used to configure the movie itself)
* @param win {Window?null} Window to create the element for
* @return {Element} The created Flash element
*/
create : function(element, attributes, variables, params, win)
{
if (!win) {
win = window;
}
//Check parameters and check if element for flash is in DOM, before call creates swf.
if (qx.core.Environment.get("qx.debug"))
{
qx.core.Assert.assertElement(element, "Invalid parameter 'element'.");
qx.core.Assert.assertMap(attributes, "Invalid parameter 'attributes'.");
qx.core.Assert.assertString(attributes.movie, "Invalid attribute 'movie'.");
qx.core.Assert.assertString(attributes.id, "Invalid attribute 'id'.");
if (!qx.dom.Element.isInDom(element, win)) {
qx.log.Logger.warn(this, "The parent DOM element isn't in DOM! The External Interface doesn't work in IE!");
}
}
if (!attributes.width) {
attributes.width = "100%";
}
if (!attributes.height) {
attributes.height = "100%";
}
// Work on param copy
params = params ? qx.lang.Object.clone(params) : {};
if (!params["movie"]) {
params["movie"] = attributes.movie;
}
attributes["data"] = attributes.movie;
delete attributes.movie;
// Copy over variables (into params)
if (variables)
{
for (var name in variables)
{
if (typeof params.flashvars != "undefined") {
params.flashvars += "&" + name + "=" + variables[name];
} else {
params.flashvars = name + "=" + variables[name];
}
}
}
// Finally create the SWF
var flash = this.__createSwf(element, attributes, params, win);
this._flashObjects[attributes.id] = flash;
return flash;
},
/**
* Destroys the flash object from DOM, but not the parent DOM element.
*
* Note: Removing the flash object like this:
* <pre>
* var div = qx.dom.Element.create("div");
* document.body.appendChild(div);
*
* var flashObject = qx.bom.Flash.create(div, { movie : "Flash.swf", id : "id" });
* div.removeChild(div.firstChild);
* </pre>
* involve memory leaks in Internet Explorer.
*
* @param element {Element} Either the DOM element that contains
* the flash object or the flash object itself.
* @param win {Window?} Window that the element, which is to be destroyed,
belongs to.
* @signature function(element, win)
*/
destroy : function(element, win) {
if (qx.core.Environment.get("engine.name") == "mshtml" &&
qx.core.Environment.get("browser.documentmode") < 11)
{
element = this.__getFlashObject(element);
if (element.readyState == 4) {
this.__destroyObjectInIE(element);
}
else
{
if (!win) {
win = window;
}
qx.bom.Event.addNativeListener(win, "load", function() {
qx.bom.Flash.__destroyObjectInIE(element);
});
}
} else {
element = this.__getFlashObject(element);
if (element.parentNode) {
element.parentNode.removeChild(element);
}
delete this._flashObjects[element.id];
}
},
/**
* Return the flash object element from DOM node.
*
* @param element {Element} The element to look.
* @return {Element} Flash object element
*/
__getFlashObject : function(element)
{
if (!element) {
throw new Error("DOM element is null or undefined!");
}
if (element.tagName.toLowerCase() !== "object") {
element = element.firstChild;
}
if (!element || element.tagName.toLowerCase() !== "object") {
throw new Error("DOM element has or is not a flash object!");
}
return element;
},
/**
* Destroy the flash object and remove from DOM, to fix memory leaks.
*
* @signature function(element)
* @param element {Element} Flash object element to destroy.
*/
__destroyObjectInIE : qx.core.Environment.select("engine.name",
{
"mshtml" : qx.event.GlobalError.observeMethod(function(element)
{
for (var i in element)
{
if (typeof element[i] == "function") {
element[i] = null;
}
}
if (element.parentNode) {
element.parentNode.removeChild(element);
}
delete this._flashObjects[element.id];
}),
"default" : null
}),
/**
* Internal helper to prevent leaks in IE
*
* @signature function()
*/
__fixOutOfMemoryError : qx.event.GlobalError.observeMethod(function()
{
// IE Memory Leak Fix
for (var key in qx.bom.Flash._flashObjects) {
qx.bom.Flash.destroy(qx.bom.Flash._flashObjects[key]);
}
window.__flash_unloadHandler = function() {};
window.__flash_savedUnloadHandler = function() {};
// Remove listener again
qx.bom.Event.removeNativeListener(window, "beforeunload", qx.bom.Flash.__fixOutOfMemoryError);
}),
/**
* Creates a DOM element with a flash movie.
*
* @param element {Element} DOM element node where the Flash element node will be added.
* @param attributes {Map} Flash attribute data.
* @param params {Map} Flash parameter data.
* @param win {Window} Window to create the element for.
* @signature function(element, attributes, params, win)
*/
__createSwf : function(element, attributes, params, win) {
if (qx.core.Environment.get("engine.name") == "mshtml" &&
qx.core.Environment.get("browser.documentmode") < 11)
{
// Move data from params to attributes
params.movie = attributes.data;
delete attributes.data;
// Cleanup classid
delete attributes.classid;
// Prepare parameters
var paramsStr = "";
for (var name in params) {
paramsStr += '<param name="' + name + '" value="' + params[name] + '" />';
}
// Create element, but set attribute "id" first and not later.
if (attributes.id)
{
element.innerHTML = '<object id="' + attributes.id +
'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000">' +
paramsStr + '</object>';
delete attributes.id;
} else {
element.innerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000">' + paramsStr + '</object>';
}
// Apply attributes
for (var name in attributes) {
// IE doesn't like dollar signs in attribute names.
if (name.substring(0, 1) == "$") {
element.firstChild[name] = attributes[name];
} else {
element.firstChild.setAttribute(name, attributes[name]);
}
}
return element.firstChild;
}
// Cleanup
delete attributes.classid;
delete params.movie;
var swf = qx.dom.Element.create("object", attributes, win);
swf.setAttribute("type", "application/x-shockwave-flash");
// Add parameters
var param;
for (var name in params)
{
param = qx.dom.Element.create("param", {}, win);
param.setAttribute("name", name);
param.setAttribute("value", params[name]);
swf.appendChild(param);
}
element.appendChild(swf);
return swf;
}
},
/*
*****************************************************************************
DEFER
*****************************************************************************
*/
defer : function(statics)
{
if (qx.core.Environment.get("engine.name") == "mshtml") {
qx.bom.Event.addNativeListener(window, "beforeunload", statics.__fixOutOfMemoryError);
}
}
});