Gererally, Silverlight needs a <object> tag and a default error-handling function to be embedded in web page.  I always want to conver this job with jQuery plugin, so I tried to extract these HTML and scripting details from the Silverlight test page automatically genereated by Visual Studio, and convert them as a “jQuery Silverlight 3 plugin”.

With this plugin, I can use $(“…”).insertSilverlight(source, options) to embed my Silverlight application into any HTML container element, like this:

    <script type="text/javascript" src="jquery-1.3.2.js"></script>
    <script type="text/javascript" src="jquery.silverlight3.js"></script>
    <script type="text/javascript">
        $(function () {
            $("#Span1").insertSilverlight(
                "bin/debug/AddressTextBox.xap",
                {
                    height: 30, width: 600,
                    onLoad: function (s, e) { alert('Test1'); }
                }
            );
            $("#Div1").insertSilverlight(
                "bin/debug/AddressTextBox.xap",
                {
                    height: 250, width: 400,
                    onLoad: "namedOnLoadFunc"
                }
            ).css("border", "solid red 2px");
        });
        function namedOnLoadFunc(s, e) {
            alert("Test2");
        }
    </script>

The plugin accept Silverlight object parameter as option, with the same parameter naming in object tag, like onError, onLoad, background, minRuntimeVersion, autoUpgrade, enableHtmlAccess, windowless, initParams, splashScreenSource, onSourceDownloadProgressChanged, onSourceDownloadComplete, onResize. 

In fact, because I use for (var p in options) trick to get any parameter paased in, any Silverlight object parameter is acceptable.  Another interesting part is that you can use either anonymous function or named function name string as event parameter (ex: onLoad, onResize), like onLoad: function(s, e) { … }, or onLoad: “myOnLoadFunctionName”.

Here is the plugin code, any feedback is welcome.

//jQuery Plugin for Silverlight 3 Embedding
//Ver 0.9 by Jeffrey Lee, http://blog.darkthread.net
(function ($) {
    if (!window.onSilverlightError) {
        window.onSilverlightError = function (sender, args) {
            var appSource =
                        (sender != null && sender != 0) ?
                        appSource = sender.getHost().Source : "";
 
            var errorType = args.ErrorType;
            var iErrorCode = args.ErrorCode;
 
            if (errorType == "ImageError" || errorType == "MediaError") {
                return;
            }
            var errMsg = [];
            errMsg.push("Unhandled Error in Silverlight Application " + appSource);
            errMsg.push("Code: " + iErrorCode + "    ");
            errMsg.push("Category: " + errorType + "       ");
            errMsg.push("Message: " + args.ErrorMessage + "     ");
 
            if (errorType == "ParserError") {
                errMsg.push("File: " + args.xamlFile + "     ");
                errMsg.push("Line: " + args.lineNumber + "     ");
                errMsg.push("Position: " + args.charPosition + "     ");
            }
            else if (errorType == "RuntimeError") {
                if (args.lineNumber != 0) {
                    errMsg.push("Line: " + args.lineNumber + "     ");
                    errMsg.push("Position: " + args.charPosition + "     ");
                }
                errMsg.push("MethodName: " + args.methodName + "     ");
            }
            throw new Error(errMsg.join("\n"));
        }
    }
 
    //seed for unique function name
    if (!window.dtsl_FuncUid)
        window.dtsl_FuncUid = 1000;
 
    $.fn.insertSilverlight = function (source, options) {
        var defaults = {
            onError: "onSilverlightError",
            background: "white",
            minRuntimeVersion: "3.0.40818.0",
            autoUpgrade: "true",
            enableHtmlAccess: "true",
            initParams: null,
            splashScreenSource: null,
            onSourceDownloadProgressChanged: null,
            onSourceDownloadComplete: null,
            onLoad: null,
            onResize: null,
            windowless: false,
            width: "100%",
            height: "100%"
        };
        var settings = $.extend(defaults, options);
        return this.each(function () {
            var a = [];
            a.push('<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="' + settings.width + '" height="' + settings.height + '">');
            a.push('<param name="source" value="' + source + '"/>');
            a.push('<param name="onError" value="onSilverlightError" />');
            for (var p in settings) {
                if (p == "width" || p == "height") continue;
                var v = settings[p];
                if (v !== null) {
                    //event callback
                    if (p.indexOf("on") == 0 && $.isFunction(v)) {
                        var funcId = "ftsl_Func" + (window.dtsl_FuncUid++);
                        window[funcId] = v;
                        v = funcId;
                    }
                    a.push('<param name="' + p + '" value="' + v + '" />');
                }
            }
            a.push('<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=' + settings.minRuntimeVersion + '" style="text-decoration:none">');
            a.push('<img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style:none"/>');
            a.push('</a>');
            a.push('</object>');
            a.push('<iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe>');
            $(this).prepend(a.join('\n'));
        });
    }
})(jQuery);

【中文摘要】

之前測試Silverlight Application都是用Visual Studio自動產生的測試網頁,但我一直想用jQuery Plugin做掉這件事,這樣子可以大幅簡化在網頁中嵌入Silverlight... 今天終於花了點時間寫了一個jQuery.insertSilverlight(source, options)實現夢想!

option的部分很彈性,除了height及width外,其餘傳入的任何參數都會變成<param name=”name” value=”value” />(我用了for (var p in options)的技巧),所以只要Silverlight <object>標籤支援的參數都可傳入。而事件的部分,我也加了支援匿名函數的功能,例如: onLoad: function(s, e) { … },這樣應該更合jQuery的調調吧!

程式與範例都附上了,歡迎指教!


Comments

# by Leo

好正點的程式!!!! 黑暗大果然不同凡響 (膜拜~~)

# by 小黑

「傻強」說過,「神」曾經也是「人」,之所以晉升為人,是因為他做了人做不到的事。(跪拜)

Post a comment