Flash and Flash Video EPiServer Dynamic Content

Posted on November 17, 2009 by Frederik Vig in EPiServer

I’ve extended Allan Thræn’s Insert Flash elements in the Editor as Dynamic Content, to now use swfobject for a more standards-friendly way of embedding Flash. I’ve also added support for videos, by using Flowplayer, which is a popular Flash Video Player.

Flowplayer

Click here to view it

Edit mode

Solution

Update 18.11.2009

I’ve updated the code to now also use fallback content for users that do not have Flash or JavaScript installed/enabled. When using the fallback content with regular Flash files (.swf), whenever someone who doesn’t have Flash or JavaScript installed/enabled it will display.

For Flowplayer it behaves a bit differently, the fallback content will be displayed when the page loads, when someone clicks it, the video will start. So with no fallback content, the video plays automatically when the page loads. With fallback content (could be an image for instance), the user has to click the image (in this case), to start the video. Here’s an example.

The code is almost identical to Allan’s, the only thing I’ve changed is the Render method and I’ve added an extra text field for the id (must be unique for the page).

Since the fallback content contains HTML code I had to update the code for getting and setting the State. Previously I just used Allan’s code, which used | to separate the different values. But now I had to use XML and Serialization. It was a little tricky at first, but thankfully I came across Anders’ post Dynamic content and State attribute.

using System;
using System.Globalization;
using System.Xml.Linq;
using EPiServer;
using EPiServer.Core;
using EPiServer.DynamicContent;
using EPiServer.Editor;
using EPiServer.SpecializedProperties;
 
namespace FlashDynamicContent
{
    public class FlashDynamicContent : IDynamicContent
    {
        protected PropertyDocumentUrl flash;
        protected PropertyNumber width;
        protected PropertyNumber height;
        protected PropertyXhtmlString fallbackContent;
 
        /// <summary>
        /// Setup properties
        /// </summary>
        public FlashDynamicContent()
        {
            flash = new PropertyDocumentUrl { Name = "Flash file " };
            width = new PropertyNumber(300) { Name = "Width" };
            height = new PropertyNumber(300) { Name = "Height" };
 
            fallbackContent = new PropertyXhtmlString
                                  {
                                      Name = "Fallback content",
                                      EditorToolOptions = EditorToolOption.All ^ EditorToolOption.Font ^ EditorToolOption.DynamicContent
                                  };
        }
 
        public System.Web.UI.Control GetControl(PageBase hostPage)
        {
            throw new NotImplementedException();
        }
 
        public PropertyDataCollection Properties
        {
            get
            {
                return new PropertyDataCollection { flash, width, height, fallbackContent };
            }
        }
 
        public string Render(PageBase hostPage)
        {
            if (flash.ToString().EndsWith(".swf", true, CultureInfo.InvariantCulture))
            {
                if (!hostPage.ClientScript.IsClientScriptIncludeRegistered("swfobject"))
                {
                    hostPage.ClientScript.RegisterClientScriptInclude("swfobject", "http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js");
                }
 
                hostPage.ClientScript.RegisterStartupScript(GetType(), "swfobject" + this.GetHashCode(), string.Format("swfobject.embedSWF(\"{0}\", \"flash{3}\", \"{1}\", \"{2}\", \"9.0.0\", false);", flash, width, height, this.GetHashCode()), true);
 
                return string.Format("<div id=\"flash{0}\">{1}</div>", this.GetHashCode(), fallbackContent);
            }
 
            if (!hostPage.ClientScript.IsClientScriptIncludeRegistered("flowplayer"))
            {
                hostPage.ClientScript.RegisterClientScriptInclude("flowplayer", "/Flowplayer/flowplayer-3.1.4.min.js");
            }
 
            hostPage.ClientScript.RegisterStartupScript(GetType(), "flowplayer" + this.GetHashCode(), string.Format("flowplayer(\"flash{0}\", \"/Flowplayer/flowplayer-3.1.5.swf\", \"{1}\");", this.GetHashCode(), flash), true);
 
            return string.Format("<div style=\"width:{0}px;height:{1}px\" id=\"flash{2}\">{3}</div>", width, height, this.GetHashCode(), fallbackContent);
        }
 
        public bool RendersWithControl
        {
            get { return false; }
        }
 
        public string State
        {
            get
            {
                return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(new XElement("flashcontent",
                    new XElement("flash", flash),
                    new XElement("width", width),
                    new XElement("height", height),
                    new XElement("fallbackcontent", new XCData(fallbackContent.ToString()))).ToString(SaveOptions.DisableFormatting)));
            }
            set
            {
                if (value == null)
                {
                    return;
                }
 
                byte[] toDecodeByte = Convert.FromBase64String(value);
 
                var encoder = new System.Text.UTF8Encoding();
                System.Text.Decoder utf8Decode = encoder.GetDecoder();
 
                int charCount = utf8Decode.GetCharCount(toDecodeByte, 0, toDecodeByte.Length);
 
                var decodedChar = new char[charCount];
                utf8Decode.GetChars(toDecodeByte, 0, toDecodeByte.Length, decodedChar, 0);
 
                var flashContent = XElement.Parse(new string(decodedChar));
                flash.ParseToSelf((string)flashContent.Element("flash"));
                width.ParseToSelf((string)flashContent.Element("width"));
                height.ParseToSelf((string)flashContent.Element("height"));
                fallbackContent.ParseToSelf((string)flashContent.Element("fallbackcontent"));
            }
        }
    }
}

In the Render method I check if the file ends with .swf, depending on that I either add the code for swfobject, or for flowplayer.

Update 19.11.2009

Thanks to Martins comment, I’ve removed the id field and replaced it with the HashCode and a prefix of flash (HTML id have to start with a letter in the roman alphabet). One less thing for the editor to worry about :).

Installation

  1. Download the code
  2. Unzip, and copy the FlashDynamicContent.dll into your sites bin folder, and the Flowplayer folder into your sites root folder
  3. Register it in your web.config file
    <dynamicContent>
    	<controls>
            ...
    		<add description="Insert Flash or Flash Video" name="FlashDynamicContent" type="FlashDynamicContent.FlashDynamicContent, FlashDynamicContent"/>
    	</controls>
    </dynamicContent>

Related Posts: