Loading Previously Saved Values
The
control retrieves the previously saved resource gallery path and
displays it in the textbox. As what we have saved to the content
repository is XML, we will use the helper function GetResourceGalleryPath() (defined later) to extract it.
protected override void LoadPlaceholderContentForAuthoring(
PlaceholderControlEventArgs e)
{
EnsureChildControls();
string xml = ((XmlPlaceholder)this.BoundPlaceholder).XmlAsString;
m_resourceGalleryPath = GetResourceGalleryPath(xml);
txtResourceGalleryPath.Text = m_resourceGalleryPath;
}
The GetResourceGalleryPath() helper function accepts the entire XML string that has been saved in the underling XmlPlaceholder as an input parameter. It loads it into an XmlDocument object and retrieves the path of the resource gallery from the <Path> child element.
private string GetResourceGalleryPath(string xml)
{
string rgPath = "";
try
{
XmlDocument xd = new XmlDocument();
xd.LoadXml(xml);
rgPath = xd.DocumentElement.SelectSingleNode("Path").InnerText;
}
catch
{}
return rgPath;
}
Rotating Images Randomly
In presentation view, a file is randomly picked
from the resource gallery. As the resource gallery accepts files of all
types, we won’t know if the selected file is an image, a Flash file, an
Office document or a PDF. Therefore the control that we load in the
presentation container has to be generic, like the ASP.NET PlaceHolder control from the System.Web.UI.WebControls namespace (don’t confuse this with the MCMS placeholder controls!). We will use the CreatePresentationChildControls() method to add the PlaceHolder control to the presentation container.
PlaceHolder ph;
protected override void CreatePresentationChildControls(
BaseModeContainer presentationContainer)
{
ph = new PlaceHolder();
presentationContainer.Controls.Add(ph);
}
When loading content, the placeholder control first ensures that all child controls, in this case the single PlaceHolder
control we added earlier, have been created at run time before
proceeding. Once it has done so, it retrieves the path of the resource
gallery from the underlying XmlPlaceholder. To extract the information from the XML, we will use the GetResourceGalleryPath() method defined earlier.
protected override void LoadPlaceholderContentForPresentation(
PlaceholderControlEventArgs e)
{
EnsureChildControls();
// Get the current CmsHttpContext
CmsHttpContext cmsContext = CmsHttpContext.Current;
// Get an instance of the selected resource gallery
string xml = ((XmlPlaceholder)this.BoundPlaceholder).XmlAsString;
m_resourceGalleryPath = GetResourceGalleryPath(xml);
ResourceGallery rg = cmsContext.Searches.GetByPath(m_resourceGalleryPath)
as ResourceGallery;
}
Once we have an instance of the resource gallery, a random number is generated. Again, we will write a helper function, RandomNumberGenerator(), to pick a number from zero to one less than the number of resources in the gallery:
private int RandomNumberGenerator(int max)
{
// generate a random number
int seed;
int index = 0;
seed = (int)System.DateTime.Now.Ticks % System.Int32.MaxValue;
System.Random rand = new System.Random(seed);
index = rand.Next(0,max);
return index;
}
Next, we get the resource that corresponds to the randomly chosen index. Modify the LoadPlaceholderContentForPresentation() method as shown below:
protected override void LoadPlaceholderContentForPresentation(
PlaceholderControlEventArgs e)
{
. . . code continues . . .
if (rg != null)
{
// Randomly select a resource from the gallery
int indexOfResource = RandomNumberGenerator(rg.Resources.Count);
Resource r = rg.Resources[indexOfResource];
}
}
To determine the file’s type, we check its MIME
type (Multipurpose Internet Mail Extensions type). MIME types are used
by the browser to determine how content should be displayed. For
example, a file with the MIME type applications/x-shockwave-flash will be played within a Flash player instead of being displayed as an image or text. The exact value returned by the Resource.MimeType property depends on the server’s registry.
Why don’t we check the file extension instead? Don’t all images have a file extension like GIF, JPEG, or even BMP?
We could check the file extension. However,
doing so would mean having a collection of all possible file extensions.
For example, to decide whether the file is actually an image, we would
have to check if the file extension is *.bmp, *.gif, *.jpg, *.jpeg—the list goes on. While it’s a workable way of getting the job done, it is by no means exhaustive. What if someone uploads a *.png file? Our list will have to be updated with the latest file extension.
Checking the MIME type is a more efficient way of
detecting the file type. Regardless of its extension, all images will
have the word “image” as the main content type. The sub-type (for example, gif, jpeg, or png for images) follows after a forward slash.
Main Content Type | Sub Type | Mime Type |
---|
Image | GIF | image/gif |
Image | JPEG | image/jpeg |
Image | PNG | image/png |
Applications | x-shockwave-flash | applications/x-shockwave-flash |
Once we have determined if the resource is an
image, a Flash file, or something else altogether, we decide how to
display it. For images, the answer is pretty straightforward; we create
an Image control and set its ImageUrl property to point to the image.
protected override void LoadPlaceholderContentForPresentation(
PlaceholderControlEventArgs e)
{
. . . code continues . . .
if (rg != null)
{
// Randomly select a resource from the gallery
int indexOfResource = RandomNumberGenerator(rg.Resources.Count);
Resource r = rg.Resources[indexOfResource];
if (r.MimeType.StartsWith("image"))
{
// If it is an image, display it
Image img = new Image();
img.ImageUrl = r.Url;
ph.Controls.Add(img);
}
}
}
Flash files are played using a Flash plug-in.
Visitors should already have the plug-in installed, otherwise the
browser will prompt them to install it from download.macromedia.com. In Internet Explorer, the Flash plug-in is really an ActiveX control, which we can invoke using the HTML <object> tag as shown overleaf. The <EMBED></EMBED>
element is included overleaf to support non-Microsoft browsers that
don’t use ActiveX technology. Because it is surrounded by the <OBJECT></OBJECT> tag, it will be ignored by Internet Explorer.
The highlighted code below indicate places where we have to replace MyMovie.swf with the actual URL of the resource:
<OBJECT classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#
version=7,0,0,0" id="MyMovie">
<PARAM NAME=movie VALUE="MyMovie.swf">
<PARAM NAME=quality VALUE=high>
<PARAM NAME=bgcolor VALUE=#FFFFFF>
<EMBED src="MyMovie.swf" quality=high bgcolor=#FFFFFF
NAME="MyMovie" TYPE=\"application/x-shockwave-flash"
PLUGINSPAGE="http://www.macromedia.com/go/getflashplayer">
</EMBED></OBJECT>
A Literal control is used to display the entire HTML string. Add the highlighted portion as shown to the LoadPlaceholderContentForPresentation() method:
protected override void LoadPlaceholderContentForPresentation(
PlaceholderControlEventArgs e)
{
. . . code continues . . .
if (r.MimeType.StartsWith("image"))
{
// If it is an image, display it
Image img = new Image();
img.ImageUrl = r.Url;
ph.Controls.Add(img);
}
else if (r.MimeType.EndsWith("x-shockwave-flash"))
{
// If it is a shockwave flash file, display it
Literal swf = new Literal();
string html = "<OBJECT classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-"
+ "444553540000\" "
+ "codebase=\"http://download.macromedia.com/pub"
+ "/shockwave/cabs/flash/swflash.cab#version=7,0,0,0\""
+ "id=\"" + r.Name + "\">"
+ "<PARAM NAME=movie VALUE=\"" + r.Url + "\">"
+ "<PARAM NAME=quality VALUE=high>"
+ "<PARAM NAME=bgcolor VALUE=#FFFFFF>"
+ "<EMBED src=\"" + r.Url + "\" quality=high "
+ "bgcolor=#FFFFFF NAME=\"" + r.Name + "\" "
+ "TYPE=\"application/x-shockwave-flash\" "
+ "PLUGINSPAGE=\"http://www.macromedia.com/go/"
+ "getflashplayer\"></EMBED></OBJECT>";
swf.Text = html;
ph.Controls.Add(swf);
}
}
For all other file types, we will simply display their thumbnails within an Image
control. You could choose not to display them at all and get the
random-file generator to pick only images and Flash files. Or perhaps
you may have some other creative way of tackling such files. For
example, you could read the contents of a text file to make a
quote-of-the-day control. If you do, just add the logic to deal with
them here.
protected override void LoadPlaceholderContentForPresentation(
PlaceholderControlEventArgs e)
{
. . . code continues . . .
if (r.MimeType.StartsWith("image"))
{
. . . code continues . . .
}
else if (r.MimeType.EndsWith("x-shockwave-flash"))
{
. . . code continues . . .
}
else
{
// For all other types, show the thumbnail
Image img = new Image();
img.ImageUrl = r.UrlThumbnail;
ph.Controls.Add(img);
}
The control is complete. Save and build the solution.
The selected
resource gallery contains many file types. But I only wish to display
images in the control. Is there a quick way to filter the unwanted files
without deleting them from the gallery?
You could use the ResourceCollection.FilterByMimeType() or ResourceCollection.FilterByExtension()
methods of the PAPI to retrieve resources of specific MIME types or
extensions. For example, the following code selects only images from the
gallery.
// Get an instance of the resource gallery
ResourceGallery rg = cmsContext.Searches.GetByPath(m_resourceGalleryPath)
as ResourceGallery;
// Select only images from the resource
ResourceCollection rc = rg.FilterByMimeType("image", true);
Using the Image Rotator Placeholder Control
To use the image rotator placeholder control, add it to a template file and bind it to an XmlPlaceholderDefinition.
Within a posting, supply the control with the path of a resource
gallery that contains some resources. Load the posting in presentation
view and watch the images rotate on each load.
With a few modifications, the control can be enhanced to accommodate advertisements:
Store the URL of the site that the visitor will be redirected to in the resource’s description field.
Wrap the images, Flash movies, and icons of attachments within an anchor tag. Set the href attribute to point to the target website.