Many modern sites make use of two or three-state buttons to provide an added degree of interactivity when navigating across pages or submitting a form. It’s possible to create two and three state buttons using straight CSS or images. This article focuses on using a type of image file referred to as a sprite sheet in combination with CSS link styles to create ASP.NET HyperLink and LinkButton controls. Using the techniques in this article you can create buttons that look like the following and interact with them using standard ASP.NET controls:

Click here to see the ASP.NET Example Page

What is a Sprite Sheet?

The term sprite sheet refers to an image file composed of multiple images, usually with a transparent background and of type PNG or GIF. Sprite sheets were first used in games to load many images into memory simultaneously to allow for fast switching. Recently sprite sheets have come into usage on web pages due to the CSS background-image, background-position, and background-repeat properties. Using the background properties, we can load multiple images into 1 file and then use the background-position combined with CSS width and height attributes to index to a specific “sub-image” within the sprite sheet.

Why Use Sprite Sheets?

Using sprite sheets to style image buttons means you can get fast switching between states as the user mouses over and/or clicks the button without having to load the image from the server (possibly causing a flicker) or having to resort to the now-outdated technique of pre-loading images with JavaScript.

Step 1: Create the Sprite Sheet

Naturally the first step is to have some type of image to work with. You can either make the sprite sheet yourself, ask a designer to make one, or purchase pre-made images from GraphicRiver.net or similar image sites.

A common pattern used to create button sprite sheets is to build one PNG per button with each of the 3 states stacked on top of each other. If you are using PhotoShop and the images were designed in this way, then you can slice each button out into a transparent PNG. For this example I’ve created “Previous” and “Next” buttons using an image set I purchased from GraphicRiver.net. Each column in the table below shows the PNG file for the Previous button, and each column highlights a different “sub-image” to demonstrate how the 3 states for Normal, Hover, and Active are stacked on top of each other in the PNG sprite sheet.

The Normal, or “up” state sub-image in column 1 starts at position 0,0 and is 51 pixels high and 186 pixels wide. The Hover, or “mouse-over” state sub-image in column 2 starts at position 0,-66 and is also 51 pixels high and 186 pixels wide. The Active, or “clicked” state sub-image in column 3 starts at position 0, –132 and is 51 pixels high and 186 pixels wide.

Normalimage Hoverimage Activeimage

Step 2: Create the Styles

Once you have the sprite sheet setup with the 3 images stacked we can define the CSS styles for the images. Since the only thing that varies is where each image starts, we can put most of the styles in the link element and then we only have to define the unique starting position for the hover and active states. Finally we can define a style for each unique image file that points to the sprite sheet and defines its unique width:

.spriteButton a {
    background-position: 0 0;
    background-repeat: no-repeat;    
    height: 51px; 
    display: inline-block;
    outline: none;
}

.spriteButton a:hover {     
    background-position: -0px -66px;
    background-repeat: no-repeat;    
}

.spriteButton a:active { 
    background-position: -0px -132px;
    background-repeat: no-repeat;     
}

.next a {     
    background-image: url('/images/next.png'); 
    width: 145px; 
}

.previous a {     
    background-image: url('/images/previous.png'); 
    width: 186px; 
}

 

Step 3: Write the ASP.NET Code

Having defined the styles, we can now use them as the class assignment for a span tag that surrounds link elements. The code below is for the ASP.NET example page which shows normal href links and ASP.NET HyperLink and LinkButton controls. Using a span instead of assigning the CSS class to the link or image works better with the CSS background properties and across browsers. If you want some padding above and below your image you could also use a div instead of a span.

ASPX

<form id="form1" runat="server">
    <h1>Simple Links</h1>
    <p>
            <span class="spriteButton previous"><a href=""></a></span>    
            <span class="spriteButton next"><a href=""></a></span>    
    </p>    
    
    <h1>ASP.NET HyperLink and LinkButton Controls</h1>
    <p>
        <span class="spriteButton previous">
            <asp:HyperLink NavigateUrl="" runat="server" />
        </span>                    
        <span class="spriteButton next">
            <asp:LinkButton OnClick="NextButtonClick" runat="server" />        
        </span>
    </p>
</form>

Code-Behind

    protected void NextButtonClick(object sender, EventArgs e)
    {
        // do something
    }

 

References & Tools

Hopefully this article will inspire you to take on creating sprite sheets the next time you need to use image buttons in a project. Really the hardest part is creating the image, after that the CSS is straightforward once you’ve gained an understanding of the CSS background attributes. There’s a lot more that can be done with sprite sheets then just simple buttons. Check out the tools and references listed below to learn more.

CSS Sprites Generator

The Mystery of CSS Sprites: Techniques, Tools And Tutorials [Smashing Magazine]

Sprite Sheet Builder 1.0

Pure CSS Image Rollovers

CSS Sprites: What They Are, Why They’re Cool, and How To Use Them

Bookmark and Share  Comments [5] | Permalink | ASP.NET | WebDesign
 

Have you ever started out developing a class library for web parts or utility classes only to realize you later need to add a User Control or Page to the project? This can happen when working with SharePoint solutions as a popular way to develop and package solutions is as a class library project (DLL).

However, you can also package SharePoint solution DLLs by building a Web Application project file, which produces a single DLL which can then be deployed to the GAC or web application as part of a solution package (veterans of ASP.NET 1.x you will recognize web application projects as the way “it used to work” when developing web applications prior to ASP.NET 2.0). You just have to remember that it’s not a true web application project when deployed to SharePoint, because SharePoint “owns” the web application and if you add a Global.asax or Web.config to the project and then deploy as a solution, it won’t have any effect since SharePoint sees your code as a DLL (refer to this post for details of how to create an event handler in lieu of a Global.asax function). However, developing as a web application project in Visual Studio means you can work on User Controls and Pages which are then deployed in the solution as CONTROLTEMPLATES and LAYOUTS.

So if you have found yourself in the situation where you started out with a class library project and need to convert to a web application project, it’s an easy change to make. This change works even if your project has nothing to do with SharePoint.

Open the .csproj file in a text editor, and find the definition for ProjectGuid – it’s probably on or around line 7 (ignore the GUID below, that’s going to be specific to your .csproj file)

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>8.0.50727</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{9A693F59-9C63-4424-A98D-D69A801C7614}</ProjectGuid>    

Paste this line after the <ProjectGuid> line:

<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>

Leave all other properties unchanged. Your file should now look something like this:

<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>8.0.50727</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{9A693F59-9C63-4424-A98D-D69A801C7614}</ProjectGuid>    
    <ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>        
    <OutputType>Library</OutputType>

Save the .csproj file and open in Visual Studio 2008. You should now be able to add Pages and User Controls to your project yet still compile to a single DLL suitable for deployment as part of a SharePoint solution.

Bookmark and Share  Comments [2] | Permalink | ASP.NET | SharePoint
 

This post describes how to build an object tag for Windows Media Player that will work on multiple browsers. Recently while writing some code for Windows Media Player, I took a walk down Google lane and came across an article on A List Apart by Elizabeth Castro describing how to code video player Object tags without resorting to the non-standards compliant embed tag. Starting with the code in the article and then tweaking some parameters to generate 1 set of output for Internet Explorer and 1 set for “everyone else”, I was able to generate an object tag that worked in the following browsers: Internet Explorer 7, Firefox 3.0.10, Opera 9.64, Safari 4.0, Google Chrome 2.0 and Flock 2.5 (all running on Windows XP, sorry – I am too poor to buy a Mac). This MSDN article describing how Windows Media Player PARAM tags work in Firefox and Internet Explorer was also helpful, and would be useful reference if you use this code as the basis for more complex coding.

Click here to see the Live Example

Here’s the code, it’s just a page and code-behind based on the conditional display of Panels to render the Object tag depending on the browser type (i.e. if it’s Internet Explorer or not).

WindowsMediaPlayerExample.aspx

<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="WindowsMediaPlayerExample.aspx.cs" 
    Inherits="WindowsMediaPlayerExample" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Mike Knowles - Windows Media Player Multiple Browser Example</title>    
<style type="text/css">        
    body {
        background-color:#EFEFEF;
        color:#01010F;
        font-family:Verdana, "lucida grande", sans-serif;
        font-size:1em;
        padding-left:54px;
        line-height:1.4em;
    }        
</style>
</head>
<body>
<form id="form1" runat="server">
<div style="width:540px; padding-top:18px;">
<p>This example demonstrates how to build a Windows Media 
Player object tag that plays on multiple browsers.</p>
<p>For more detail, refer to the <a href="">blog post on this topic</a>.</p>

<asp:Panel ID="InternetExplorerPanel" Visible="false" runat="server">
<object classid="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6" 
    type="application/x-ms-wmp" width="500" height="330">
  <param name="url" 
    value="http://silverlight.services.live.com/60107/HD%20Future%20Markers/video.wmv" />      
  <param name="autoStart" value="true" />
  <p>You must install 
  <a href="http://www.microsoft.com/windows/windowsmedia/player/download/" 
    target="_blank">Windows Media Player</a> to view this content.</p>
</object>        
</asp:Panel>
<asp:Panel ID="DefaultPanel" Visible="false" runat="server">
<object type="application/x-ms-wmp" width="500" height="330"
    data="http://silverlight.services.live.com/60107/HD%20Future%20Markers/video.wmv">
  <param name="src" 
    value="http://silverlight.services.live.com/60107/HD%20Future%20Markers/video.wmv" />    
  <param name="autoStart" value="true" /> 
  <p>You must install <a href="http://www.microsoft.com/windows/windowsmedia/player/download/"
    target="_blank">Windows Media Player</a> to view this content.</p>
</object>
</asp:Panel>    
</div>
</form>
</body>
</html>

WindowsMediaPlayerExample.aspx.cs

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class WindowsMediaPlayerExample : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (Request.UserAgent.Contains("MSIE"))
        {
            this.InternetExplorerPanel.Visible = true;
            this.DefaultPanel.Visible = false;
        }
        else
        {
            this.DefaultPanel.Visible = true;
            this.InternetExplorerPanel.Visible = false;
        }
    }
}
Bookmark and Share  Comments [4] | Permalink | ASP.NET
 

jQuery 1.3 was released earlier this year with many new features, most notably improved CSS selectors and event handling. Microsoft and the jQuery team are working together on the development and support of the jQuery framework and integrating it into the ASP.NET and Visual Studio development environments. This post describes how you can set things up to make jQuery 1.3 an integral part of your ASP.NET 3.5 and Visual Studio 2008 development stack.

Install Microsoft Visual Studio 2008 Downloads

  1. Install Visual Studio 2008 Service Pack 1
  2. Install hotfix: KB958502 – JScript Editor support for “-vsdoc.js” Intellisense doc. files

Download Latest jQuery 1.3 Files

Since jQuery is a 100% script-based framework, there’s no installation work required per-se except to download the required script files and configure your ASP.NET application to make use of them.

Head on over to the jQuery download page and scroll down to the section where the release downloads are listed. You will notice for each release that there are 3 downloads listed below the link to view the release notes:

image

Each of these downloads is just a JavaScript file that has a specific purpose as explained in the following diagram:

image 

Click to download each script (Minified, Uncompressed, and Visual Studio) and save them to your applications scripts folder (or whatever folder name you prefer to use for JavaScript files).

Note: After I downloaded the script files I had issues getting the files to load from the web server. It turns out the file permissions were being set by the browser download to be very strict. I had to right-click each file and to into it’s file properties and then select “Inherit from parent” to get things working. I don’t know if this is something specific to my machine configuration, so this is just a troubleshooting tip in case you have issues getting the JavaScript files to load later on.

ASP.NET 3.5 and Visual Studio 2008 Integration

When loading a JavaScript file, Visual Studio will automatically look for a file with the same name and –vsdoc appended at the end of the filename prior to the extension. For example if Visual Studio sees the file jquery-1.3.2.js it will automatically try to load jquery-1.3.2-vsdoc.js to provide Intellisense for the original JavaScript file. You only need to have the –vsdoc file available for Visual Studio, it’s not something to load to a production server although there would be no harm done if you did load it to production – it would not be referenced or loaded by the browser as this is a file loading convention that only Visual Studio implements.

Before we get into the code, we want to copy the Visual Studio Intellisense file and rename the new copy so that it will be loaded to provide Intellisense for the minified jQuery file. That way we only have to setup our code to use the minified version and we won’t have to change any file references when moving from development to test and production environments. Find the Visual Studio 2008 Intellisense File or Visual Studio file you downloaded earlier (refer back to download page diagram above is this is not clear). Copy-paste this file to a new file, and name the new file to have the same name as the minified version with –vsdoc appended to the end just prior to the file extension. For example if the minified file name was jquery-1.3.2.min.js, then the name of the copied version of the Intellisense file will be jquery-1.3.2.min-vsdoc.js. When you are done, your scripts folder should look something like this:

image

Now it’s time to create or open a site in Visual Studio 2008 and setup a Master Page to include the jQuery file and verify Intellisense is working. Here’s the Master Page code to get you started:

<%@ Master Language="C#" AutoEventWireup="true" 
    CodeFile="MasterPage.master.cs" Inherits="MasterPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>

    <script src="scripts/jquery-1.3.2.min.js" type="text/javascript"></script>

    <script type="text/javascript" language="javascript">
        $(document).ready(function() {
                
        })        
    </script>
    
    <asp:ContentPlaceHolder id="head" runat="server" />        
</head>
<body>
    <form id="form1" runat="server">    
        <asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server" />        
    </form>
</body>
</html>

To test that Intellisense is working correctly, turn on line numbers in Visual Studio and position the cursor on line 13 and start typing $( and you should see Intellisense as shown below:

image

Continue typing $(“div”). and you should see a list of methods pop-up as shown below. Continue typing cli and the click method should be selected:

image

Setup Master Page and Content Page jQuery Code in the HTML Page Head

As shown above, we can setup jQuery script commands in the head of the Master Page which will then load on all content pages. Notice also that the Master Page code above contains a ContentPlaceholder named ”head” – this ContentPlaceholder is created by default when a new Master Page is created in Visual Studio 2008 (see related post on this topic as it relates to meta tags).

By adding any jQuery script that belongs in the HTML head to the content page implementation of the “head” ContentPlaceholder, we can group all Master and Content page jQuery sequentially in the page output without having to resort to code-behind or other workarounds to add JavaScript to the Master Page head section. This effectively gives us a CSS-cascade like sequencing of jQuery code and events which can be especially useful when working with the jQuery document.ready function.

To tie everything together and show some examples of jQuery in action, here’s an example of a Master Page and Content Page that implement a few jQuery events when the page is loaded and elements are clicked. This example, which is not going to win any awards, is running on my site if you want to try it out. You can also download the example zip (including the jQuery 1.3.2 script files) in case it might be of some help to you in getting things working the first time.

MasterPage.master:

<%@ Master Language="C#" AutoEventWireup="true" 
    CodeFile="MasterPage.master.cs" Inherits="MasterPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <link rel="stylesheet" type="text/css" href="style.css" runat="server" />    
    <script src="scripts/jquery-1.3.2.min.js" type="text/javascript"></script>

    <script type="text/javascript" language="javascript">
        $(document).ready(function() {
                
            $("div").css("background-color", "green");

            $("div").click(function() {
                $(this).css("background-color", "red");
            });

            $("a").click(function(event) {
                alert("Thanks for visiting!");
            });
        })        
    </script>
    
    <asp:ContentPlaceHolder id="head" runat="server" />        
</head>
<body>
    <form id="form1" runat="server">    
    <p>
    <a href="http://jquery.com/" target="_blank">jQuery</a>
    </p>    
    <div style="background-color:blue">
        <asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server" />        
    </div>        
    </form>
</body>
</html>

Default.aspx:

<%@ Page Title="jqTest Page" Language="C#" MasterPageFile="MasterPage.master" 
    AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
    <script type="text/javascript" language="javascript">        
        $(document).ready(function() {
            $("div.test").click(function() {
                $(this).css("background-color", "white");
            });
        })        
    </script>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" 
    Runat="Server">
    
    test test test
    <div class="test">some test content</div>
    <span class="test">some span text</span>
</asp:Content>
Bookmark and Share  Comments [5] | Permalink | ASP.NET | jQuery
 

When building ASP.NET Master Pages there are some simple approaches that will improve your search engine rankings, result displays, and integration with Google form-based tools such as Custom Search and AdSense.

Basic Search Engine Optimization Techniques

Search Engine Optimization (SEO) is the practice of constructing the content and meta tags on an html page to improve your page rankings so that your site shows up in search engine results with a descriptive title and summary that will improve your chances of a click-through. To learn more about SEO, read the Google Search Engine Optimization Starter Guide.

In programming terms, the basics of SEO are simple to understand although not easily implemented unless planned for early in the site’s lifecycle. The first item of importance is to have useful content on each page and to use words in your copy that will resonate with web users looking for the product or information you have to offer. Just as important is to specify a unique title on each page as readers of search engine result pages typically just scan titles looking for the match closest to their search terms. The description and keywords are also important in determining a page's relevance and search engine ranking.

When defining an ASPX page that uses a Master Page, you can define the title in the Page tag that goes at the top of each ASPX file. The Master Page will then display the title dynamically - provided you have the runat="server" tag on the head section opening tag in the Master Page.

Visual Studio 2008 provides an improvement over previous versions in how you can set head section tagged content specific to each page. When a Master Page is created in 2008, it automatically adds an appropriately-placed ContentPlaceHolder called head which you can override in your content page to set meta tags such as the description and keywords.

For example, consider this Master Page snippet created by Visual Studio 2008:

<%@ Master Language="C#" AutoEventWireup="true" 
    CodeFile="MasterPage.master.cs" Inherits="MasterPage" %> 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<asp:ContentPlaceHolder id="head" runat="server">
</asp:ContentPlaceHolder>
</head> 

You can then override the title, description, and keywords in the content page as shown below:

<%@ Page Title="Page Title" Language="C#" 
    MasterPageFile="~/MasterPage.master" AutoEventWireup="true" 
    CodeFile="Default.aspx.cs" Inherits="Default" %> 

<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
<meta name="keywords" content="page keyword listing" />
<meta name="description" content="page description" />
</asp:Content> 

Here's the view-source of how it renders to the browser:

<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>
Page Title
</title>
<meta name="keywords" content="page keyword listing" />
<meta name="description" content="page description" />
</head>

Integrating Google AdSense and Custom Site Search Forms

Lately I've been working on integrating Google AdSense and Custom Search Engine into ASP.NET pages that use a common Master Page. Like many web widgets you can run within a web page that display content from another site, the code provided by Google for AdSense and Custom Search Engine each contain a form tag. This can be problematic since by default when you create a new Master Page in Visual Studio it places the form tag in the Master Page around the main ContentPlaceHolder intended for the page content. An HTML page can contain N forms, but there can be no nested forms, which means you cannot add your Google form tags to the page content as they would be scoped within the main master page form tag.

Sometimes you can place the widget in the Master Page in which case you just copy-paste the widget code into the Master Page outside the scope of the ASP.NET form tag. However - what if you want to place the widget code in the content page? Since the form is defined in the Master Page, it looks upon first inspection like this might not be possible.

Fortunately there is a simple solution - you don't have to define the Form tag in the Master Page! Just because it's placed there by default doesn't mean that is your only option. It's perfectly valid to define the form tag in each content page instead. This is what I do so that I can place Google AdSense and Custom Search at specific points inside my ASPX pages and still take advantage of ASP.NET forms.

For example, in the code below the Master Page defines the main place holder, but with no surrounding form tag:

<div id="main">    
    <asp:contentplaceholder id="ContentPlaceHolder1" 
        runat="server" />
</div>

The content page then defines the form tag for Google Custom Search followed by the ASP.NET form tag:

<form action="CustomSearchResults.aspx" id="cse-search-box">
  <div>
    <input type="hidden" name="cx" value="GUID" />
    <input type="hidden" name="cof" value="FORID:10" />
    <input type="hidden" name="ie" value="UTF-8" />
    <input type="text" name="q" size="31" />
    <input type="submit" name="sa" value="Search" />
  </div>
</form>

<form runat="server">
ASP.NET form goes here
</form>
Bookmark and Share  Comments [2] | Permalink | ASP.NET
Subscribe
Top 5 Posts
Add Google Analytics to a SharePoint Publishing Site
Integrating jQuery 1.3, ASP.NET 3.5 Visual Studio 2008
Add Custom Table Formats to SharePoint Content Editor
Configuring log4net for SharePoint Windows Authentication
Convert Visual Studio 2008 Class Library Project to Web Application Project
Tags
ASP.NET (5) dasBlog (5) GoogleAnalytics (2) jQuery (1) log4net (2) SharePoint (18) WebDesign (3)
 
 
 
Spreadfirefox Affiliate Button
 
Download Notepad++