Simple Slide Show: Cycle2 + jQuery + Asp.Net + SQL CE

by doug 20. January 2013 18:42

This is a typical case of not seeing any solutions for a simple slide show that fit my needs.  So I took some bits and pieces, wired them together to create my own solution.  If it worked for me, it might work for you too, so I’m sharing my recipe.

I wanted a slide show for my website that

·          would be easy to wire up each time I had a new set of images

·          didn’t take up much page real estate

·          Looked and worked with a certain amount of elegance

·         Cross browser of course

So I started with Mike Alsup’s jQuery solution called Cycle2.  Check it out over at http://jquery.malsup.com/cycle2/   Cycle2 is a jQuery plugin that is really flexible and super easy to implement.  It “Cycles” images through a set container. Yet you can make it do virtually anything you want. Mike has created a wonderful library and you really should visit his site.

 Here’s the configuration that I choose as my starting point:

The images have a nice flowing transition, the caption overlay looks really nice and since it will accommodate any image size, I can easily resize it to fit in my site.  An excellent start. 

Looking at the code needed to use this, it’s very straight forward:

In the  <head> section you have:

·         a link to jQuery hosted by Google

·          a link to the Cycle2 jQuery plug in

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

<script src="jquery.cycle2.min.js"></script>

 

Also in the <head> section you have a bit of CSS:

<style type="text/css">

.cycle-overlay {

    font-family:Georgia;

    position: absolute; bottom: 0; width: 582px; z-index: 600;

    background: black; color: white; padding: 15px; opacity: .5;

}

 

.mainContainer{

     width:612px;

     border: 1px solid black;

     padding: 5px;

     background-color: #EAEAEA;

     margin-top: 10px;

    }

 

</style>

These two classes take care of the caption overlay as well as the main container that will hold all the images.

Moving on to the <body> section you have:

·         The slide show main container

·         The container for the slides (notice the special Cycle2 properties)

·         Each slide is wrapped in a <span> tag that also contains the caption overlay

 

 <div id="div_SlideShowMainContainer" class="mainContainer">

 

   <div id="div_SlideContainer" class="cycle-slideshow"

            data-cycle-fx="scrollHorz"

            data-cycle-timeout="0"

            data-cycle-prev="#prev"

            data-cycle-next="#next"

            data-cycle-slides=">span"

                            >

                          

        <span>

           <img alt="" src="slides/WP_000122.jpg" width="612" height="448" />

           <div class="cycle-overlay">I'm stalking you.</div>

         </span>

         <span>

           <img alt="" src="slides/WP_000155.jpg" width="612" height="448"/>

           <div class="cycle-overlay">I'm upside down.</div>

         </span>

        <span>

           <img alt="" src="slides/WP_000072.jpg" width="612" height="448"/>

           <div class="cycle-overlay">My paper binky.</div>

          </span>

 

         <!--

          <span>

           You can even add other content here, like video (youtube or html5 video tag), text or anything else you'd like

           </span>

  -->

   </div>

</div>

Then finally the Prev and Next buttons  together in a single container:

  <div style="margin-top: 5px;">

    <a href="#" id="prev"><img alt="" src="prev.png" style="border:0;" /></a>

    <a href="#" id="next"><img alt="" src="next.png"  style="border:0;" /></a>

 </div>

 

I love the simplicity of this slide show.  But there is one negative.  If you have many slides – you’d be writing a bunch of markup.  Yeah, you can cut and paste, then go back and  do some cleanup.  My idea was to add some ASP.Net to automate some of this.   Are you with me .Net brethren? Smile

Here’s what I did for the page hosting the slide show:

·         Replace each slide container with an ASP.Net Repeater server object

·         Added the necessary attributes and database calls

·         Created a SQL Data Source that pulls slides based on slide show name

Then added a new Upload page to:

·         Upload 5 slides at a time

·         Slides are uploaded to the server

·         Data is kept in a SQL CE 4.0 database

Download the project here.

The code for the slide show now looks like:

<div id="div_SlideShowMainContainer" style="width:612px; border: 1px solid black; padding: 5px; background-color: #EAEAEA; margin-top: 10px;">

 

 <div class="cycle-slideshow"

    data-cycle-fx="scrollHorz"

    data-cycle-timeout="0"

    data-cycle-prev="#prev"

    data-cycle-next="#next"

    data-cycle-slides=">span"

    >

     

<asp:Repeater ID="rptr_slides" runat="server" DataSourceID="sds_GetSlidesBySlideShowName">

  <ItemTemplate>

     <span>   

 <asp:Image ID="img_slide" runat="server" Width="612" Height="448" ImageUrl='<%# "~/slides/" + Eval("img_FileName") %>' />

     <div class="cycle-overlay">

         <%# Eval("img_SlideNumber") + ". " + Eval("img_SlideDescription") %>

     </div>

       </span>

    </ItemTemplate>

  </asp:Repeater>

 

    </div>

</div>

 

 <div class="center" style="margin-top: 5px;">

    <a href="#" id="prev"><img alt="" src="prev.png" style="border:0;" /></a>

    <a href="#" id="next"><img alt="" src="next.png"  style="border:0;" /></a>

 </div>

 

Here is the Data source:

<asp:SqlDataSource ID="sds_GetSlidesBySlideShowName" runat="server"

        ConnectionString="<%$ ConnectionStrings:DataConnection %>"

        ProviderName="<%$ ConnectionStrings:DataConnection.ProviderName %>"

         SelectCommand="SELECT [img_FileName], [img_SlideShowName], [img_SlideNumber], [img_SlideDescription] FROM [imgs] WHERE ([img_SlideShowName] = @img_SlideShowName) ORDER BY [img_SlideNumber]">

        <SelectParameters>

            <asp:Parameter DefaultValue="MrsMarbles" Name="img_SlideShowName" Type="String" />

        </SelectParameters>

      </asp:SqlDataSource>

 

<SQL SIDEBAR>

If you’re new to SQL CE – it’s a SQL DB contained in a flat file with a .sdf (SQL Data File) extension.  If you’ve ever done web development against an Access Db, it’s the same environment – except the .sdf file is genuine SQL  -  to a point:

·         No exotic data types – just the basics

·         No programmability  - like stored procedures – but you get to use all the T-Sql you already love

·         Not exactly effortless to set up – but once it’s done,  you have a FREE SQL database to use in your web project! No hosting fee or SQL license fee J

Setup Notes: I was NOT able to get SQL CE setup using Visual Studio 2012 Express.  I followed all the top ASP.Net bloggers and tried all the suggestions – it just wouldn’t happen. However when using Visual Studio 2012 Express it was much easier.

If you download the my solution, it will have SQL CE already set up.  If you’re starting from scratch, you’d need to “Add New Item” then choose SQL CE:

AddNew_SqlServerCeDB

Then BEFORE you upload to your server you must “Add Deployable Dependencies”

Website_AddDeployableDepandencies

..which will add this to your Bin folder:

binFolder

</SQL SIDEBAR>

Back to the upload page – it has the following markup:

    <form id="form1" runat="server">

    <div>

          

     <div id="div_SlideShowName_MainContainer">

       <div id="div_AddToExsisting">

           <fieldset id="fs_AddToExisting"><legend>Add images to exsiting slide show</legend>

        Select slide show name:&nbsp;

 <asp:DropDownList ID="ddl_SlideShowName" runat="server" DataSourceID="sds_GetSlideShowTitles" DataTextField="img_SlideShowName" DataValueField="img_SlideShowName" />

           </fieldset>

       </div>

      <div id="div_NewSlideShow">

        <fieldset id="fs_NewSlideShow"><legend>Create new slide show</legend>

              Enter name: &nbsp;  <asp:TextBox ID="txtSlideShowName" runat="server" Width="300px" /><br /><br />

        </fieldset>  

       </div>

      </div>

   <div id="div_spacer1" style="clear:left; height: 25px;" ></div>

 

 <fieldset class="slideUpload">

     <asp:FileUpload ID="fileUpload1" runat="server" CssClass="fileUploadStyles" /><br />

       Slide caption:<asp:TextBox ID="txtSlideDescription1" runat="server" CssClass="txtSlideCaptionStyles"  />

         </fieldset>

 

          <fieldset  class="slideUpload">

            <asp:FileUpload ID="fileUpload2" runat="server" CssClass="fileUploadStyles"/><br />

             Slide caption:<asp:TextBox ID="txtSlideDescription2" runat="server" CssClass="txtSlideCaptionStyles"/>

            <br />

         </fieldset>

 

          <fieldset  class="slideUpload">

            <asp:FileUpload ID="fileUpload3" runat="server" CssClass="fileUploadStyles" /><br />

             Slide caption:<asp:TextBox ID="txtSlideDescription3" runat="server" CssClass="txtSlideCaptionStyles"/>

          </fieldset>

 

          <fieldset  class="slideUpload" >

             <asp:FileUpload ID="fileUpload4" runat="server"  CssClass="fileUploadStyles" /><br />

             Slide caption:<asp:TextBox ID="txtSlideDescription4" runat="server" CssClass="txtSlideCaptionStyles" />

          </fieldset>

 

          <fieldset  class="slideUpload">

            <asp:FileUpload ID="fileUpload5" runat="server" CssClass="fileUploadStyles" /><br />

            Slide caption:<asp:TextBox ID="txtSlideDescription5" runat="server" CssClass="txtSlideCaptionStyles" />

         </fieldset>

 

         &nbsp;<asp:LinkButton  ID="lbtn_UploadNow" runat="server" Text="Upload Now" onclick="lbtn_UploadNow_Click"/>&nbsp;

         <asp:Label ID="lbl_uploadMessage" runat="server" />

    </div>

 

    </form>

…which renders like this:

UploadPage 

And the upload .cs file:

public partial class admin_Upload : System.Web.UI.Page

{      

   private SqlCeDataReader ceReader;

   private SqlCeConnection ceConn;

   private SqlCeCommand ceComm;

   private string connString = ConfigurationManager.ConnectionStrings["DataConnection"].ConnectionString;

   

   

    protected void Page_Load(object sender, EventArgs e)

    {

 

    }

    protected void lbtn_UploadNow_Click(object sender, EventArgs e)

    {

 

 

if (!fileUpload1.HasFile && !fileUpload2.HasFile && !fileUpload3.HasFile && !fileUpload4.HasFile && !fileUpload5.HasFile)

        {

            lbl_uploadMessage.Text = "No slides to upload.";

            lbl_uploadMessage.ForeColor = System.Drawing.Color.Red;

            return;

        }

 

 

        string slideShowName = txtSlideShowName.Text.Trim();

 

        if (fileUpload1.HasFile)

        {

           string fileName = fileUpload1.PostedFile.FileName;

           string slideDescription = txtSlideDescription1.Text.Trim();

           int slideNumber = getSlideNumber(slideShowName);

           uploadSlideData(fileName, slideShowName, slideDescription, slideNumber);

           fileUpload1.SaveAs(MapPath("../slides/" + fileName));

        }

 

 

        if (fileUpload2.HasFile)

        {

            string fileName = fileUpload2.PostedFile.FileName;

            string slideDescription = txtSlideDescription2.Text.Trim();

            int slideNumber = getSlideNumber(slideShowName);

            uploadSlideData(fileName, slideShowName, slideDescription, slideNumber);

            fileUpload2.SaveAs(MapPath("../slides/" + fileName));

        }

 

        if (fileUpload3.HasFile)

        {

            string fileName = fileUpload3.PostedFile.FileName;

            string slideDescription = txtSlideDescription3.Text.Trim();

            int slideNumber = getSlideNumber(slideShowName);

            uploadSlideData(fileName, slideShowName, slideDescription, slideNumber);

            fileUpload3.SaveAs(MapPath("../slides/" + fileName));

        }

 

        if (fileUpload4.HasFile)

        {

            string fileName = fileUpload4.PostedFile.FileName;

            string slideDescription = txtSlideDescription4.Text.Trim();

            int slideNumber = getSlideNumber(slideShowName);

            uploadSlideData(fileName, slideShowName, slideDescription, slideNumber);

            fileUpload4.SaveAs(MapPath("../slides/" + fileName));

 

        }

        if (fileUpload5.HasFile)

        {

            string fileName = fileUpload5.PostedFile.FileName;

            string slideDescription = txtSlideDescription5.Text.Trim();

            int slideNumber = getSlideNumber(slideShowName);

            uploadSlideData(fileName, slideShowName, slideDescription, slideNumber);

            fileUpload5.SaveAs(MapPath("../slides/" + fileName));

        }

 

        lbl_uploadMessage.Text = "Upload complete!";

        lbl_uploadMessage.ForeColor = System.Drawing.Color.Green;

 

        txtSlideDescription1.Text = string.Empty;

        txtSlideDescription2.Text = string.Empty;

        txtSlideDescription3.Text = string.Empty;

        txtSlideDescription4.Text = string.Empty;

        txtSlideDescription5.Text = string.Empty;

 

    }

       

  

    protected void uploadSlideData(string fileName, string slideShowName, string slideDescription, int slideNumber)

    {

            ceConn = new SqlCeConnection(connString);   

            ceComm = new SqlCeCommand("INSERT INTO imgs (img_FileName, img_SlideShowName, img_SlideNumber, img_SlideDescription)VALUES(@img_FileName, @img_SlideShowName, @img_SlideNumber, @img_SlideDescription)", ceConn);

            ceComm.Parameters.AddWithValue("@img_FileName", fileName);

            ceComm.Parameters.AddWithValue("@img_SlideShowName", slideShowName);

            ceComm.Parameters.AddWithValue("@img_SlideNumber", slideNumber);

            ceComm.Parameters.AddWithValue("@img_SlideDescription", slideDescription);

 

            ceConn.Open();

            ceComm.ExecuteNonQuery();

            ceConn.Close();

    }

 

    protected int getSlideNumber(string slideShowName)

    {

        int slideNumber = 0;

       

        ceConn = new SqlCeConnection(connString);

 

        //get latest slide number then increment by 1

        ceComm = new SqlCeCommand("SELECT MAX(img_SlideNumber) AS latestSlide FROM imgs WHERE img_SlideShowName=@img_SlideShowName", ceConn);

        ceComm.Parameters.AddWithValue("@img_SlideShowName", slideShowName);

        ceConn.Open();

        ceReader = ceComm.ExecuteReader();

 

        if (ceReader.Read())

        {

            if (ceReader["latestSlide"] != DBNull.Value)

            {

                slideNumber = Convert.ToInt32(ceReader["latestSlide"]);

                slideNumber++;

            }

            else

            {

                slideNumber = 1;

            }

        }

        ceConn.Close();

        ceReader.Close();

 

        return slideNumber;

    }

 

 

}

So after all this – you now have a slide show page and an upload mechanism. Nothing ground-breaking here, but if you’re new to back end web development – this is a nice project to try.  And  - sure it could be better.  But it’s a start. Like how about protecting the Upload page with a login. Or how about a page to manage the slides in a particular slide show – like re-ordering or re-writing captions. Or how about auto-resizing images on upload to pre-defined dimensions that fit your layout.

 

Hey -download the solution and let me know what you’ve added to make it your own. And don’t forget to support the Cycle2 jQuery project.

UPDATED: Deploying SQL CE 4.0 in a Hosted Environment

by Doug 26. August 2011 12:54

 

sqlserverlogo

        COMPACT EDITION

 

As promised, Mark Wisecarver has finished his webcast regarding SQL CE 4.0. Check it out over here: http://www.dasptv.com/avc-view.aspx?videoid=39

 

Mark provides a very nice overview of this latest version, including some excellent blogs and other online resources that can will help you decide if it’s the right version of SQL for your project (remember kids, it’s not a replacement for SQL Server), and has a tutorial on creating a new app with Visual Studio using CE 4.0.

 

If you’re among those who have DiscountASP.Net as your web hosting provider, don’t forget to come back here, since I’ve outlined the steps to deploy your ASP.Net web app using SQL CE to DiscountASP.Net web hosting:

http://www.mooremediaone.com/blog/post/2011/07/11/Deploying-SQL-CE-40-in-a-Hosted-Environment.aspx

Doug's Latest Tweets

Doug Who?

Hey, Doug here.  Thanks for visiting "A Doug's Life". 

 

I enjoy packaging my thoughts, pictures, video clips and other fragments into what hopefully makes up some interesting stuff to share.  

 

I've checked the list that gives you a better idea about me!

 

Love Web Technology
Sunday is for Pro Football
Hike or bike on trail most mornings
Halloween Rocks!
Chase the latest electronic gadgets
Married
(Happily Married)
Drama
Simplicity

 

My wife and I live in the shadow of Mt Lukens on the edge of the Angeles National Forest:

 

Tujunga, CA

More Stuff