﻿/**
* tools.flashembed 1.0.3 - The future of Flash embedding.
* 
* Copyright (c) 2009 Tero Piirainen
* http://flowplayer.org/tools/flash-embed.html
*
* Dual licensed under MIT and GPL 2+ licenses
* http://www.opensource.org/licenses
*
* Launch  : March 2008
* Date: 2009-06-03 07:16:50 +0000 (Wed, 03 Jun 2009)
* Revision: 1870 
*/
(function() {

    //{{{ utility functions 

    var jQ = typeof jQuery == 'function';

    // from "Pro JavaScript techniques" by John Resig
    function isDomReady() {

        if (domReady.done) { return false; }

        var d = document;
        if (d && d.getElementsByTagName && d.getElementById && d.body) {
            clearInterval(domReady.timer);
            domReady.timer = null;

            for (var i = 0; i < domReady.ready.length; i++) {
                domReady.ready[i].call();
            }

            domReady.ready = null;
            domReady.done = true;
        }
    }

    // if jQuery is present, use it's more effective domReady method
    var domReady = jQ ? jQuery : function(f) {

        if (domReady.done) {
            return f();
        }

        if (domReady.timer) {
            domReady.ready.push(f);

        } else {
            domReady.ready = [f];
            domReady.timer = setInterval(isDomReady, 13);
        }
    };


    // override extend opts function 
    function extend(to, from) {
        if (from) {
            for (key in from) {
                if (from.hasOwnProperty(key)) {
                    to[key] = from[key];
                }
            }
        }

        return to;
    }


    // JSON.asString() function
    function asString(obj) {

        switch (typeOf(obj)) {
            case 'string':
                obj = obj.replace(new RegExp('(["\\\\])', 'g'), '\\$1');

                // flash does not handle %- characters well. transforms "50%" to "50pct" (a dirty hack, I admit)
                obj = obj.replace(/^\s?(\d+)%/, "$1pct");
                return '"' + obj + '"';

            case 'array':
                return '[' + map(obj, function(el) {
                    return asString(el);
                }).join(',') + ']';

            case 'function':
                return '"function()"';

            case 'object':
                var str = [];
                for (var prop in obj) {
                    if (obj.hasOwnProperty(prop)) {
                        str.push('"' + prop + '":' + asString(obj[prop]));
                    }
                }
                return '{' + str.join(',') + '}';
        }

        // replace ' --> "  and remove spaces
        return String(obj).replace(/\s/g, " ").replace(/\'/g, "\"");
    }


    // private functions
    function typeOf(obj) {
        if (obj === null || obj === undefined) { return false; }
        var type = typeof obj;
        return (type == 'object' && obj.push) ? 'array' : type;
    }


    // version 9 bugfix: (http://blog.deconcept.com/2006/07/28/swfobject-143-released/)
    if (window.attachEvent) {
        window.attachEvent("onbeforeunload", function() {
            __flash_unloadHandler = function() { };
            __flash_savedUnloadHandler = function() { };
        });
    }

    function map(arr, func) {
        var newArr = [];
        for (var i in arr) {
            if (arr.hasOwnProperty(i)) {
                newArr[i] = func(arr[i]);
            }
        }
        return newArr;
    }

    function getHTML(p, c) {


        var e = extend({}, p);

        var ie = document.all;
        var html = '<object width="' + e.width + '" height="' + e.height + '"';

        // force id for IE or Flash API cannot be returned
        if (ie && !e.id) {
            e.id = "_" + ("" + Math.random()).substring(9);
        }

        if (e.id) {
            html += ' id="' + e.id + '"';
        }

        // prevent possible caching problems
        e.src += ((e.src.indexOf("?") != -1 ? "&" : "?") + Math.random());

        if (e.w3c || !ie) {
            html += ' data="' + e.src + '" type="application/x-shockwave-flash"';
        } else {
            html += ' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"';
        }

        html += '>';

        if (e.w3c || ie) {
            html += '<param name="movie" value="' + e.src + '" />';
        }

        // parameters
        e.width = e.height = e.id = e.w3c = e.src = null;

        for (var k in e) {
            if (e[k] !== null) {
                html += '<param name="' + k + '" value="' + e[k] + '" />';
            }
        }

        // flashvars
        var vars = "";

        if (c) {
            for (var key in c) {
                if (c[key] !== null) {
                    vars += key + '=' + (typeof c[key] == 'object' ? asString(c[key]) : c[key]) + '&';
                }
            }
            vars = vars.substring(0, vars.length - 1);
            html += '<param name="flashvars" value=\'' + vars + '\' />';
        }

        html += "</object>";

        return html;

    }

    //}}}


    function Flash(root, opts, flashvars) {

        var version = flashembed.getVersion();

        // API methods for callback
        extend(this, {

            getContainer: function() {
                return root;
            },

            getConf: function() {
                return opts;
            },

            getVersion: function() {
                return version;
            },

            getFlashvars: function() {
                return flashvars;
            },

            getApi: function() {
                return root.firstChild;
            },

            getHTML: function() {
                return getHTML(opts, flashvars);
            }

        });

        // variables	
        var required = opts.version;
        var express = opts.expressInstall;


        // everything ok -> generate OBJECT tag 
        var ok = !required || flashembed.isSupported(required);

        if (ok) {
            opts.onFail = opts.version = opts.expressInstall = null;
            root.innerHTML = getHTML(opts, flashvars);

            // fail #1. express install
        } else if (required && express && flashembed.isSupported([6, 65])) {

            extend(opts, { src: express });

            flashvars = {
                MMredirectURL: location.href,
                MMplayerType: 'PlugIn',
                MMdoctitle: document.title
            };

            root.innerHTML = getHTML(opts, flashvars);

            // fail #2. 
        } else {

            // fail #2.1 custom content inside container
            if (root.innerHTML.replace(/\s/g, '') !== '') {
                // minor bug fixed here 08.04.2008 (thanks JRodman)			

                // fail #2.2 default content
            } else {
                root.innerHTML =
				"<h2>Flash version " + required + " or greater is required</h2>" +
				"<h3>" +
					(version[0] > 0 ? "Your version is " + version : "You have no flash plugin installed") +
				"</h3>" +

				(root.tagName == 'A' ? "<p>Click here to download latest version</p>" :
					"<p>Download latest version from <a href='http://www.adobe.com/go/getflashplayer'>here</a></p>");

                if (root.tagName == 'A') {
                    root.onclick = function() {
                        location.href = 'http://www.adobe.com/go/getflashplayer';
                    };
                }
            }
        }

        // onFail
        if (!ok && opts.onFail) {
            var ret = opts.onFail.call(this);
            if (typeof ret == 'string') { root.innerHTML = ret; }
        }

        // http://flowplayer.org/forum/8/18186#post-18593
        if (document.all) {
            window[opts.id] = document.getElementById(opts.id);
        }

    }

    window.flashembed = function(root, conf, flashvars) {

        //{{{ construction

        // root must be found / loaded	
        if (typeof root == 'string') {
            var el = document.getElementById(root);
            if (el) {
                root = el;
            } else {
                domReady(function() {
                    flashembed(root, conf, flashvars);
                });
                return;
            }
        }

        // not found
        if (!root) { return; }


        // setup opts
        var opts = {

            // very common opts
            width: '100%',
            height: '100%',

            // flashembed defaults
            allowfullscreen: true,
            allowscriptaccess: 'always',
            quality: 'high',


            // flashembed specific options
            version: null,
            onFail: null,
            expressInstall: null,
            w3c: false
        };


        if (typeof conf == 'string') {
            conf = { src: conf };
        }

        extend(opts, conf);

        return new Flash(root, opts, flashvars);

        //}}}


    };


    //{{{ static methods

    extend(window.flashembed, {

        // returns arr[major, fix]
        getVersion: function() {

            var version = [0, 0];

            if (navigator.plugins && typeof navigator.plugins["Shockwave Flash"] == "object") {
                var _d = navigator.plugins["Shockwave Flash"].description;
                if (typeof _d != "undefined") {
                    _d = _d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
                    var _m = parseInt(_d.replace(/^(.*)\..*$/, "$1"), 10);
                    var _r = /r/.test(_d) ? parseInt(_d.replace(/^.*r(.*)$/, "$1"), 10) : 0;
                    version = [_m, _r];
                }

            } else if (window.ActiveXObject) {

                try { // avoid fp 6 crashes
                    var _a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");

                } catch (e) {

                    try {
                        _a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
                        version = [6, 0];
                        _a.AllowScriptAccess = "always"; // throws if fp < 6.47 

                    } catch (ee) {
                        if (version[0] == 6) { return version; }
                    }
                    try {
                        _a = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
                    } catch (eee) {

                    }

                }

                if (typeof _a == "object") {
                    _d = _a.GetVariable("$version"); // bugs in fp 6.21 / 6.23
                    if (typeof _d != "undefined") {
                        _d = _d.replace(/^\S+\s+(.*)$/, "$1").split(",");
                        version = [parseInt(_d[0], 10), parseInt(_d[2], 10)];
                    }
                }
            }

            return version;
        },

        isSupported: function(version) {
            var now = flashembed.getVersion();
            var ret = (now[0] > version[0]) || (now[0] == version[0] && now[1] >= version[1]);
            return ret;
        },

        domReady: domReady,

        // returns a String representation from JSON object 
        asString: asString,


        getHTML: getHTML

    });

    //}}}


    // setup jquery support
    if (jQ) {

        // tools version number
        jQuery.tools = jQuery.tools || { version: {} };
        jQuery.tools.version.flashembed = '1.0.3';


        jQuery.fn.flashembed = function(conf, flashvars) {

            var el = null;

            this.each(function() {
                el = flashembed(this, conf, flashvars);
            });

            return conf.api === false ? this : el;
        };

    }

})();
