Click here to Skip to main content
15,868,419 members
Articles / Web Development / ASP.NET

ASP.NET Slideshow Control with jQuery and XML

Rate me:
Please Sign up or sign in to vote.
4.76/5 (21 votes)
11 Nov 2009CPOL6 min read 130K   4.1K   60   24
An article on how to create an ASP.NET slideshow control using jQuery and XML.

Introduction

For the past few years, image sliders, slide-shows, and ad rotator scripts have become increasingly popular for web pages. There are thousands of these scripts on the Web, but it was difficult to find one that fit my requirements. I wanted a script that is flexible enough for me to use as an ad rotator, slide-show, or image rotator with navigation controls and that extracts the slides information from an XML file. After spending some time researching for it, I found the jQuery based slideshow with navigation controls from Dynamic Drive and the article Reading XML with jQuery. I had put together these findings and a brief tutorial "jQuery slideshow with XML". Recently, I decided to encapsulate this into ASP.NET User Controls to increase the reusability of code. Now, I can have multiple instances of this control on my page, and I can customize the width and height, options to hide or show navigation controls, XML file source, and other settings for each instance. I have put together a step by step tutorial on how I have accomplished this.

Figure 1

Sample results

Check list

Getting started

Before we begin, make sure to download a copy of the Simple Controls Gallery v1.3 from Dynamic Drive, Reading XML with JQuery, and the latest version of the jQuery JavaScript library. Here is the structure of my project. You are welcome to download this demo.

Figure 2

Project Structure

Putting everything together

SlideShow.ascx.cs

First, add a Web User Control to the project and create public properties and methods to allow interaction with the control at design-time or programmatically.

Listing 1
C#
//slide div
public string WrapperID
{
    get { return this.ClientID + "Div"; }
}

WrapperID will return the unique ID of the User Control. Every time we drop an ASP.NET User Control on to a page, it will automatically include an ID property that uniquely identifies the control. The ID value is the combination of the tag name and a number. If the tag name of the User Control is "SlideShow", WrapperID will return SlideShow1Div, SlideShow2Div …SlideShowNDiv.

Listing 2
C#
private int _width =728;
[DefaultValue(728)]
public int Width
{
    set { this._width = value; } get { return this._width; }
}
//height of the slide
private int _height = 95;
[DefaultValue(95)]
public int Height
{
    set { this._height = value; }  get { return this._height; }
}

Add the Width and Height properties to allow us to adjust the height and width of the div control.

Listing 3
C#
// autoplay true|false 
private bool _autoPlay = true;
[DefaultValue(true)]
public bool AutoPlay
{
    get { return this._autoPlay; }  set { this._autoPlay = value; }
}

// Show Navigation Control true|false
private bool _showNavigation = true;
[DefaultValue(true)]
public bool ShowNavigation
{
    get { return this._showNavigation; } set{ this._showNavigation = value; }
}

private int _delay_btw_slide = 10000;
/// delay between slide in miliseconds 
[DefaultValue(10000)]
public int Delay_btw_slide
{
    set { this._delay_btw_slide = value; }   get { return this._delay_btw_slide; }
}

private int _fadeDuration = 2000;
/// transition duration (milliseconds) 
[DefaultValue(2000)]
public int FadeDuration
{
    set { this._fadeDuration = value; }  get { return this._fadeDuration; }
}
private int _cycles_before_stopping = 99;
/// cycles befote stopping
[DefaultValue(99)]
public int Cycles_before_stopping
{
    set { this._cycles_before_stopping = value; } 
    get { return this._cycles_before_stopping; }
}

// previous button
private string _btnPrevious = "~/images/previous.gif";
[Category("Appearance"), Localizable(true)]
[Description("Previous button"), 
 DefaultValue("~/images/previous.gif"), Bindable(true)]
[Editor("System.Web.UI.Design.ImageUrlEditor, 
         System.Design, Version=2.0.0.0, Culture=neutral, 
PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]    [UrlProperty]
public string BtnPrevious
{
    get { return this._btnPrevious; } set { this._btnPrevious = value;}
}

// Next button
// Play button 
// Pause button
  • AutoPlay - true = start the slide show automatically without pressing the Play button and vice versa.
  • ShowNavigation - true = show the navigation control, or false = hide the navigation control.
  • Delay_btw_slide - get or set the delay between each image slide.
  • FadeDuration - get or set the fade duration between each slide.
  • Cycles_before_stopping - get or set the number of rotations before stopping the rotation. If we set 99, it will rotate 99 times and stop until we hit the Play button again.
  • BtnPrevious, BtnNext, BtnPlay, BtnPause - get or set the image for the Previous, Next, Play, and Pause buttons, respectively. These properties accept relative URLs or absolute URL paths to the button images. Make sure to place the images folder at the root directory of the application if you are using relative URLs.
Listing 4
//xml file
private string _xmlSource = "~/xml/sites.xml";
[UrlProperty]
[Bindable(true)]
[DefaultValue("~/xml/sites.xml")]
public string XMLSource
{
    get { return this._xmlSource; } set { this._xmlSource = value; }
}

//xPath
private string _xPath = "site";
[DefaultValue("site")]
public string xPath
{
    get { return this._xPath; }  set { this._xPath = value; }
}

Add a property to get and set the XML source path. The default path is set to ~/xml/sites.xml. This property accepts a relative URL or absolute URL path to the XML file. Make sure to place the XML folder at the root directory of the application if you are using relative URL. Then, add another property, XPATH, to navigate through elements and attributes in the XML document.

Listing 5
C#
void CreateScript()
{
    StringBuilder ssScript = new StringBuilder(string.Empty);
    string arrName = "myArray" + this.WrapperID;

    //read XML
    ssScript.Append("var " + arrName+ "= [];");
    ssScript.Append("$(document).ready(function() {");
    ssScript.Append(" $.ajax({");
    ssScript.Append("type: \"GET\",");
    ssScript.Append("url: '" + ResolveUrl(XMLSource) + "',");
    ssScript.Append("cache: true,");
    ssScript.Append("dataType: \"xml\",");
    ssScript.Append("success: function(xml) {");
    ssScript.Append("var count = 0;");
    ssScript.Append("$(xml).find('" + xPath + "').each(function() {");

    ssScript.Append(" var url = $(this).find('url').text();");
    ssScript.Append("var target = $(this).find('target').text();");
    ssScript.Append("var imageURL = $(this).find('imageURL').text();");
    ssScript.Append("var alt = $(this).find('alt').text();");

    ssScript.Append(arrName + "[parseInt(count)] = 
             new Array(imageURL, url, target, alt); ");
    ssScript.Append("count++;");
    ssScript.Append("});");

    //slide-shows
    ssScript.Append(" var mygallery"+this.WrapperID+" = new simpleGallery({");
    ssScript.Append(" wrapperid: '" + this.ClientID + 
                    "_" + this.WrapperID + "',");
    //width/height of gallery in pixels.
    //Should reflect dimensions of the images exactly
    ssScript.Append("dimensions: [" + Width.ToString() + 
                    ","+ Height.ToString()+"],"); 
    ssScript.Append("imagearray: "+arrName+","); //array of images
    ssScript.Append("navimages: ['" + ResolveUrl(BtnPrevious) + "', '" + 
                    ResolveUrl(BtnPlay) + "', '" + ResolveUrl(BtnNext) + 
                    "', '" + ResolveUrl(BtnPause) + "'],");
    ssScript.Append("showpanel: '" + ShowNavigation.ToString().ToLower() + "',");
    ssScript.Append(" autoplay: [" + AutoPlay.ToString().ToLower() + "," + 
                    Delay_btw_slide.ToString() + "," + 
                    Cycles_before_stopping.ToString() + "],"); 
    //[auto_play_boolean, delay_btw_slide_millisec, cycles_before_stopping_int]
    ssScript.Append(" persist: true,");
    //transition duration (milliseconds)
    ssScript.Append(" fadeduration:" + FadeDuration.ToString() + ",");
    //event that fires when gallery has initialized/ ready to run
    ssScript.Append(" oninit: function() {");
    ssScript.Append("  },");
    //event that fires after each slide is shown
    ssScript.Append("  onslide: function(curslide, i) {");
    //curslide: returns DOM reference to current
    // slide's DIV (ie: try alert(curslide.innerHTML)
    //i: integer reflecting current image within collection
    //   being shown (0=1st image, 1=2nd etc)
    ssScript.Append("   }");
    ssScript.Append("  })");
    ssScript.Append("  }");
    ssScript.Append("   });");
    ssScript.Append(" });");

        ClientScriptManager jScript = Page.ClientScript;
        jScript.RegisterClientScriptBlock(this.GetType(), 
                Guid.NewGuid().ToString(), ssScript.ToString(), true);
    }

Then, add a method to render the JavaScript programmatically. The main purpose of this JavaScript is to read the slide information from the XML file into an array and initialize the slide-show properties. The key items of this JavaScript are the array variable, HTML div control, and the slide-shows variable. In order to have multiple instances of slide-shows on the page, we have to ensure that the unique IDs and name are being assigned to the mentioned key items. We can utilize the WrapperID property to create unique names and IDs for each instance. Note that the ResolveUrl method is being utilized so that the browser can resolve the URL of the images and the XML file. The rest of the code is very straightforward; you can download the original code from Dynamic Drive to compare the changes.

Listing 6
C#
void CreateDiv()
{
    System.Web.UI.HtmlControls.HtmlGenericControl ssDivWrapper = 
       new System.Web.UI.HtmlControls.HtmlGenericControl("div");
    ssDivWrapper.ID = this.WrapperID;
    ssDivWrapper.Style.Add("background", "white none repeat scroll 0% 0%");
    ssDivWrapper.Style.Add(HtmlTextWriterStyle.Overflow, "hidden");
    ssDivWrapper.Style.Add(HtmlTextWriterStyle.Position, "relative");
    ssDivWrapper.Style.Add(HtmlTextWriterStyle.Visibility, "visible");
    ssDivWrapper.Style.Add(" -moz-background-clip", "border");
    ssDivWrapper.Style.Add("-moz-background-origin", "padding");
    ssDivWrapper.Style.Add("-moz-background-inline-policy", "continuous");

    this.Controls.Add(ssDivWrapper);
}

The CreateDiv method will generate the HTML div on the page dynamically.

Listing 7
C#
//load the javascript
internal void LoadJScript()
{
    ClientScriptManager script = Page.ClientScript;
    //prevent duplicate script
    if (!script.IsStartupScriptRegistered(this.GetType(), "JQuerySlideShowJS"))
    {
        script.RegisterClientScriptBlock(this.GetType(), "JQuerySlideShowJS",
           "<script src="%22%20+%20ResolveUrl%28%22%7E/" + 
           "SlideShowControl/js/jquery-1.3.2.min.js%22%29%20+" + 
           "%20%22" type="text/javascript"></script>");
    }

    if (!script.IsStartupScriptRegistered(this.GetType(), "SimpleGalleryJS"))
    {
        script.RegisterClientScriptBlock(this.GetType(), "SimpleGalleryJS",
           "<script src="%22%20+%20ResolveUrl%28%22%7E/" + 
           "SlideShowControl/js/simplegallery.js%22%29%20+%20%22" type="text/" + 
           "javascript"></script>");
    }
}

The purpose of the LoadJScript method is to load jquery-1.3.2.min.js and simplegallery.js dynamically with no duplicates. With that being said, if we drag 10 slide-show controls on to a page, it will only add the JavaScript once on to the ASP.NET page. This will help avoid unnecessarily assembling the client-side script.

simplegallery.js

I'm not going to post the whole contents of this JavaScript here, but I'll list the changes that I have made.

  1. Removed the static image button properties from the simpleGallery_navpanel interface since the image buttons will be assigned dynamically through the CreateScript method.
  2. Modified the script to read the image button properties from different interfaces.
  3. Added logic to hide and display the navigation control through the ShowNavigation property.
  4. Added alternate text to the image buttons.

Using the Code

Listing 8
XML
<uc1:SlideShow ID="SlideShow2" runat="server" />

Drag and drop the User Control on to the page. Here is the default setting of the User control:

Figure 3

Default properties

Listing 9
XML
<uc1:SlideShow ID="SlideShow5" runat="server" 
    BtnNext="~/images/nav-arrow-right.gif" 
    BtnPrevious="~/images/nav-arrow-left.gif" 
    AutoPlay="false" />

Above is an example on how to set the image buttons and the AutoPlay property.

Listing 10
XML
<uc1:SlideShow ID="SlideShow7" runat="server" XPath="site500x281"  
    Width="500" Height="281" ShowNavigation="true" 
    XMLSource="~/xml/500x281.xml"/>

The above example demonstrates how to set the width and height of the HTML div control. The control gets the images information from the 500x821.xml file and selects the site500x281 nodes. By default, the ShowNavigation attribute is set to true.

Listing 11 - More sample usage
XML
<uc1:SlideShow ID="SlideShow6" runat="server" BtnNext="~/images/nav-arrow-right.gif" 
        BtnPrevious="~/images/nav-arrow-left.gif" 
        XMLSource="~/xml/120x600.xml" XPath="site120x600" 
         Width="120" Height="600" />

<uc1:SlideShow ID="SlideShow1" XPath="site120x60" 
    Width="120" Height="60"
    ShowNavigation="false" 
    runat="server" XMLSource="~/xml/sites2.xml"  />

Conclusion

If you are not sure of the relative path to the images or XML file, I would suggest using absolute links. Please keep in mind that the links to the XML files have to be in the same domain, no cross-domain calls. Also, try not to place all the images information in one XML file for multiple slide-show controls. Imagine, if we have a XML file of 50KB in size, 10 slide-show controls on the page, and each of them consuming the same XML source. It will cost us 500KB bandwidth and degrade the loading speed. I hope someone will find this tutorial useful and share some thoughts with me on how to make it better.

Tested on IE 6.0/7.0/8.0, Google Chrome, and Firefox.

References

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
I have over 10 years of experience working with Microsoft technologies. I have earned my Microsoft Certified Technology Specialist (MCTS) certification. I'm a highly motivated self-starter with an aptitude for learning new skills quickly.

Comments and Discussions

 
GeneralMy vote of 5 Pin
katela9-Jan-13 0:59
katela9-Jan-13 0:59 
GeneralMy vote of 5 Pin
Yasser Zaid25-Sep-12 1:14
Yasser Zaid25-Sep-12 1:14 
GeneralRe: My vote of 5 Pin
Bryian Tan25-Sep-12 13:35
professionalBryian Tan25-Sep-12 13:35 
GeneralMy vote of 5 Pin
Ahmad24722-Sep-12 3:08
Ahmad24722-Sep-12 3:08 
QuestionSlideshow doesnt work on the server Pin
Ahmad24722-Sep-12 3:08
Ahmad24722-Sep-12 3:08 
AnswerRe: Slideshow doesnt work on the server Pin
Bryian Tan23-Sep-12 8:38
professionalBryian Tan23-Sep-12 8:38 
GeneralMy vote of 5 Pin
navren22-Jul-12 6:08
navren22-Jul-12 6:08 
GeneralMy vote of 5 Pin
Manoj Kumar Choubey17-Feb-12 21:43
professionalManoj Kumar Choubey17-Feb-12 21:43 
GeneralMy vote of 5 Pin
edwin62357-Feb-12 3:06
edwin62357-Feb-12 3:06 
GeneralRe: My vote of 5 Pin
Bryian Tan23-Sep-12 8:39
professionalBryian Tan23-Sep-12 8:39 
Generalmy vote 5 Pin
shaheen_mix16-Dec-11 23:48
shaheen_mix16-Dec-11 23:48 
very nice work... Big Grin | :-D
GeneralRe: my vote 5 Pin
Bryian Tan29-Aug-12 5:04
professionalBryian Tan29-Aug-12 5:04 
GeneralGreat work Bryian Pin
CreativeBug21-Apr-11 20:15
CreativeBug21-Apr-11 20:15 
GeneralRe: Great work Bryian Pin
Bryian Tan22-Apr-11 17:47
professionalBryian Tan22-Apr-11 17:47 
Generalnice Pin
musaied21-Apr-11 10:31
musaied21-Apr-11 10:31 
GeneralRe: nice Pin
Bryian Tan22-Apr-11 17:47
professionalBryian Tan22-Apr-11 17:47 
GeneralMy vote of 5 Pin
antrim29-Dec-10 6:23
antrim29-Dec-10 6:23 
GeneralRe: My vote of 5 Pin
Bryian Tan22-Apr-11 17:48
professionalBryian Tan22-Apr-11 17:48 
GeneralMy vote of 4 Pin
AshwinSR16-Nov-10 1:04
AshwinSR16-Nov-10 1:04 
GeneralRe: My vote of 4 Pin
Bryian Tan22-Apr-11 17:48
professionalBryian Tan22-Apr-11 17:48 
GeneralGood Job Pin
Z@clarco24-Nov-09 4:07
Z@clarco24-Nov-09 4:07 
GeneralRe: Good Job Pin
Bryian Tan24-Nov-09 6:45
professionalBryian Tan24-Nov-09 6:45 
GeneralNice work Pin
paulsoren21-Nov-09 12:56
paulsoren21-Nov-09 12:56 
GeneralRe: Nice work Pin
Bryian Tan23-Nov-09 19:18
professionalBryian Tan23-Nov-09 19:18 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.