Click here to Skip to main content
15,884,836 members
Articles / Web Development / CSS

AJAX Slider Control and GridView Rolodex

Rate me:
Please Sign up or sign in to vote.
4.86/5 (32 votes)
5 May 2009CPOL5 min read 81.1K   1K   90   20
Create a Rolodex type control for viewing contacts using the SliderExtender control and the GridView.
overview1_pic.png

Introduction

Taking a page from most mobile devices (ehem, iPhone), a sliding rolodex approach to accessing people in a list is a very handy and quick way to navigate. This project uses a combination of the SliderExtender, GridView, some CSS tricks, and UpdatePanels.

Background 

I wanted my web page to be as handy as my phone. 

Step 1: The Basic Slider Extender Setup

First, let's do some easy stuff. Put a slider on your AJAX enabled ASPX page and a text box. This is not very interesting. Notice however that I have set the Maximum to 26 and Minimum to 0 for the SliderExtender. If you were to run this page, you would see a vertical slider and that is it.

ASP.NET
<asp:TextBox runat="server" ID="SliderBox" />
  <cc1:SliderExtender runat="server" ID="SliderBoxExtender" 
     Maximum="26" Minimum="0" TargetControlID="SliderBox" /> 

Here is what it should look like:

slider_1.png

Step 2: Vertical Formatting

By default, the sliders go left to right. Of course, that would work just fine, but I wanted the slider to be vertical. So, using a bit of styling, I came up with this layout. Depending on other attributes in your style sheet, the height and length of your control may need to be adjusted. Frankly, I just adjusted the Length attribute of my slider until it matched the height of my letter column. Notice that the font-size attribute for my paragraph tags is in px. This is very important. Styling fonts with px ensures that a user cannot resize them (thus messing up the careful height styling of our slider control!).  I have a bunch of other styling rules here that will come into play later.

ASP.NET
<style>        
        body{font-family: "trebuchet ms", sans-serif;
            font-size: 10pt;
            background-color: #fff;
            color: #555;
	        line-height: 1.7em;}
	    p {paddding-top:0px;}
        table {border:none; border-collapse:collapse;margin-bottom: 1.5em;}
        table td{vertical-align:top;position:relative;}
        td p {padding:4px;margin:-1px 0px;font-size:8px;width:12px;line-height:10px;
              border: solid 1px #d1d1d1;cursor:hand;}
        td p.letterSelected{font-weight:bold; width:14px;
                            background-color:#c1c1c1;font-size:10px;color:#fff;
                            padding:4px 4px 4px 6px; border:solid 1px #d1d1d1;}
        .letterbox{
        position:absolute;top:100px; left:100px; height:60px; width:100px; z-index:5;
        border: solid 1px gray;background:#fff; filter:alpha(opacity=70); opacity:.7; 
        text-align:center; font-size:48px;padding-top:30px; 
        font-weight:bold;display:none;
        }
        
        .rowA{background:#c1c1c1;}
        .rowB{background:#f1f1f1;}
</style>

<table>
    <td>
        <asp:TextBox runat="server" ID="SliderBox" />
        <cc1:SliderExtender runat="server" 
            ID="SliderBoxExtender" Maximum="26" Length="425"
            Minimum="0" TargetControlID="SliderBox" Orientation="vertical" />    
    </td>
    <td>
        <p id="row_0">All</p>
        <p id="row_1">A</p>
        <p id="row_2">B</p>
        <p id="row_3">C</p>
        <p id="row_4">D</p>
        <p id="row_5">E</p>
        <p id="row_6">F</p>
        <p id="row_7">G</p>
        <p id="row_8">H</p>
        <p id="row_9">I</p>
        <p id="row_10">J</p>
        <p id="row_11">K</p>
        <p id="row_12">L</p>
        <p id="row_13">M</p>
        <p id="row_14">N</p>
        <p id="row_15">O</p>
        <p id="row_16">P</p>
        <p id="row_17">Q</p>
        <p id="row_18">R</p>
        <p id="row_19">S</p>
        <p id="row_20">T</p>
        <p id="row_21">U</p>
        <p id="row_22">V</p>
        <p id="row_23">W</p>
        <p id="row_24">X</p>
        <p id="row_25">Y</p>
        <p id="row_26">Z</p>
    </td>
</table>

Here is what it looks like:

slider_3.png

Step 3: Changing Numbers to Letters

Unfortunately, slider extenders can only slide through numeric ranges. Of course, we want users to slide over letters. So, the problem is: how do we convert numbers to letters? I suppose there are a lot of ways to do this. In my example, I've used paragraph containers with numbered IDs. I then use JavaScript to determine which is selected and the innerHTML attribute to pull out the matching letter. Sound confusing? It's not really.

First, we need to intercept all the Slider Extender actions. This means attaching our own functions to the control's events. This is surprisingly easy. Without going into each function just yet, here is how you attach a function to an Ajax control's events.  

JavaScript
//! set the Java functions to each of the slider events
function pageLoad(sender, e) {
var slider = $find('<%=SliderBoxExtender.ClientID %>');
slider.add_slideStart(sliderStart);
slider.add_slideEnd(sliderEnd);
slider.add_valueChanged(valChanged);
}

I've used the SliderBoxExtender.ClientID syntax to get the ControlID as generated by .NET during render.   

Now we can start coding what happens during each of these events. This is where the magic of displaying the selected letter and highlighting the selected <p> tag will occur.

  • sliderStart: Function that fires when the user first mouses down on the slider handle. We need to turn on the Letter Box (single letter box that will hover over our GridView).
    JavaScript
    function sliderStart()
    {
        var fd = document.getElementById('LetterBox');
        fd.style.display='inline';
    }
  • sliderEnd / submitForm: Functions that fire when the user releases the mouse button. We need to hide the Letter Box and submit our form. However, we want the GridView in an UpdatePanel, so instead of submitting the form, we will be clicking a hidden button that is wired to our UpdatePanel as an Asynch trigger (see submitForm() function).  I've separated the logic for submitting the form because as you will, I wanted to be able to click on a letter as well as slide to them and achieve the same result - a posted back update of the grid.

    JavaScript
    function sliderEnd()
    {
         var fd = document.getElementById('LetterBox');
         fd.style.display='none';
         submitForm();
    }
    
    function submitForm()
    {
         var hidBtn = document.getElementById('<%=hiddenButton.ClientID %>');
         hidBtn.click();        
    }   
  • valChanged:  The real workhorse that does all the fancy bits. This function changes the text in the Letter Box and changes the formatting of the <p> tag of the "active" letter.

    JavaScript
    function valChanged()
    {
         //get the box that will display the letter chosen
         var fd = document.getElementById('LetterBox');
    
         //get the box containing the value chosen by the Extender
         var valBox = document.getElementById('<%=SliderBox.ClientID %>');
    
         //get the value of the extender
         var val = valBox.value;
    
         //set up a loop variable
         var i = 0
    
         //create a row variable
         var grow
    
         //loop through numbers 0 through 26
         for(i=0;i<27;i++)
         {
             //set our local row variable to the ID of one of our paragraph tags
             grow = document.getElementById('row_' + i);
    
             //if our paragraph ID matches the selected number
             if(i==val)
                 //set the paragraph style to selected
                 {grow.className = 'letterSelected';
    
                 //change the text of our Letter Box to the innerHTML 
    	    //of our paragraph tag
                  fd.innerHTML = grow.innerHTML;
                 }
             //otherwise, set the style of our paragraph tag to nothing
             else{grow.className = '';}
         }
    }

This is a good time to stop and see where we are.  If we comment out the submitForm() portion of the JavaScript in the sliderEnd function, everything should be working as expected.

slider_4.gif

Step 4: Adding the UpdatePanel, GridView, and Data

I really like using ObjectDataSources so in this example I use one. It won't mean much to you. However, this ODS uses a stored proc that does a search of my People list using SQL syntax like this:

SQL
CREATE PROCEDURE dbo.usp_GetEmployeeList_FirstLetter 
	(@FirstLetter nvarchar(2))
AS
	SET NOCOUNT ON
		SELECT
			(E.LastName + ', ' + E.FirstName) as FullName,
			E.EmployeeID
		FROM
			TrainingWeb_Employee as E 
		WHERE
			E.LastName like @FirstLetter + '%'
			and E.[State] = 'Active'
		ORDER BY E.LastName, E.FirstName
	RETURN

So, on the *.aspx page, add the UpdatePanel, ObjectDataSource, SelectParameter of the ObjectDataSource, and GridView. Wire up the Gridview to the datasource.  Notice that I've also included a hidden button (at the bottom of the code below) that will be used to trigger the asynch postback. This is the button that is "clicked" from the submitForm() JavaScript function.

ASP.NET
<asp:UpdatePanel runat="server" ID="PersonGridUpdatePanel" UpdateMode="conditional">
    <Triggers>
        <asp:AsyncPostBackTrigger ControlID="hiddenButton" EventName="Click" />
    </Triggers>
    
    <ContentTemplate>
        <asp:ObjectDataSource runat="server" ID="PersonListData" 
		TypeName="myProject.Employee"
         SelectMethod="GetEmployeeList_FirstLetter">
            <SelectParameters>
                <asp:Parameter Name="FirstLetter" 
		DefaultValue="" ConvertEmptyStringToNull="false" />
            </SelectParameters> 
        </asp:ObjectDataSource>
        <asp:GridView ID="PersonGrid" Visible=false 
		runat="server" DataSourceID="PersonListData" AllowPaging="true"
        PageSize="20" AutoGenerateColumns="false" style="z-index:4;"
        RowStyle-CssClass="rowA" AlternatingRowStyle-CssClass="rowB">
            <Columns>
                <asp:BoundField DataField="Fullname" HeaderText="Person's Name" />
            </Columns>
        </asp:GridView>
    </ContentTemplate>
</asp:UpdatePanel>
<asp:Button runat="server" ID="hiddenButton" style="display:none;" 
	OnClick="LetterSelected" UseSubmitBehavior="false" />

And, we need a couple lines in the aspx.vb file to handle the postback.  Namely, we want to set the value of the ObjectDataSource's Select parameter to whatever letter has been selected.  I have enumerated the choices for each letter for convenience, but using this approach you could conceivable internationalize these controls by using ASCII coding instead of my simple 1 through 26 approach.

VB.NET
Protected Sub LetterSelected(ByVal sender As Object, ByVal e As EventArgs)
    Dim choice As LetterChoice = CType(SliderBox.Text, LetterChoice)
     If choice = LetterChoice.All Then
        PersonListData.SelectParameters("FirstLetter").DefaultValue = ""
    Else
        PersonListData.SelectParameters("FirstLetter").DefaultValue = choice.ToString()
    End If
 End Sub 
  Public Enum LetterChoice
    All = 0
    A = 1
    B = 2
    C = 3
    D = 4
    E = 5
    F = 6
    G = 7
    H = 8
    I = 9
    J = 10
    K = 11
    L = 12
    M = 13
    N = 14
    O = 15
    P = 16
    Q = 17
    R = 18
    S = 19
    T = 20
    U = 21
    V = 22
    W = 23
    X = 24
    Y = 25
    Z = 26
End Enum

Really, that's it. If you make sure the submitForm() is uncommented (;)) you can run the page and it will work as expect. Of course, after doing this a few times, I realized that as a user I expected to be able to click on the letter as well as work the slider. No problem! Just add a little JavaScript to the <p> tags and a little function that changes the value of the slider, and we have the whole package.

The new <p> tags looks like this:

ASP.NET
<td>
    <p id="row_0" onclick="setVal(this.id)">All</p>
    <p id="row_1" onclick="setVal(this.id)">A</p>
    <p id="row_2" onclick="setVal(this.id)">B</p>
    <p id="row_3" onclick="setVal(this.id)">C</p>
    <p id="row_4" onclick="setVal(this.id)">D</p>
    <p id="row_5" onclick="setVal(this.id)">E</p>
    <p id="row_6" onclick="setVal(this.id)">F</p>
    <p id="row_7" onclick="setVal(this.id)">G</p>
    <p id="row_8" onclick="setVal(this.id)">H</p>
    <p id="row_9" onclick="setVal(this.id)">I</p>
    <p id="row_10" onclick="setVal(this.id)">J</p>
    <p id="row_11" onclick="setVal(this.id)">K</p>
    <p id="row_12" onclick="setVal(this.id)">L</p>
    <p id="row_13" onclick="setVal(this.id)">M</p>
    <p id="row_14" onclick="setVal(this.id)">N</p>
    <p id="row_15" onclick="setVal(this.id)">O</p>
    <p id="row_16" onclick="setVal(this.id)">P</p>
    <p id="row_17" onclick="setVal(this.id)">Q</p>
    <p id="row_18" onclick="setVal(this.id)">R</p>
    <p id="row_19" onclick="setVal(this.id)">S</p>
    <p id="row_20" onclick="setVal(this.id)">T</p>
    <p id="row_21" onclick="setVal(this.id)">U</p>
    <p id="row_22" onclick="setVal(this.id)">V</p>
    <p id="row_23" onclick="setVal(this.id)">W</p>
    <p id="row_24" onclick="setVal(this.id)">X</p>
    <p id="row_25" onclick="setVal(this.id)">Y</p>
    <p id="row_26" onclick="setVal(this.id)">Z</p>
</td>

The setVal function looks like this:

JavaScript
function setVal(pID)
{
    //grab the slider object
    var slider = $find('<%=SliderBoxExtender.ClientID %>');
     //remove the row_ text from the ID to get the "number" of the row
    var val = pID.replace('row_','')
     //set the value of the slider
    slider.set_Value(val);
     //run the valChanged() function to set all the controls appropriately
    valChanged();
     //trigger the postback
    submitForm();
} 

Here is the finished product:

capture_5.gif

Conclusion

Designing web controls that require NO training is my passion. This rolodex control is so common to the human experience, any user should be able to figure out how to use it.

History

  • 5th May, 2009: Initial post

License

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


Written By
United States United States
I have been coding web applications since 2001. Starting with classic .asp and rolling from there, I have a passion for user interface design and building zero-training applications.

Comments and Discussions

 
GeneralMy vote of 5 Pin
CS140112-Feb-12 17:03
CS140112-Feb-12 17:03 
GeneralMy vote of 5 Pin
ninadnaik251-Nov-11 0:28
ninadnaik251-Nov-11 0:28 
GeneralMy vote of 5 Pin
kiran dangar6-Oct-11 19:24
kiran dangar6-Oct-11 19:24 
GeneralMy vote of 4 Pin
Slacker00710-Mar-11 5:54
professionalSlacker00710-Mar-11 5:54 
GeneralMy vote of 5 Pin
tgadadhar17-Sep-10 21:57
tgadadhar17-Sep-10 21:57 
Questioncc1 prefix problem Pin
Kevin Olson3-Sep-10 18:43
Kevin Olson3-Sep-10 18:43 
AnswerRe: cc1 prefix problem Pin
Kevin Olson4-Sep-10 17:28
Kevin Olson4-Sep-10 17:28 
GeneralGiood one. Pin
ashleyjohn14-Jun-10 19:15
ashleyjohn14-Jun-10 19:15 
GeneralGreat Article Pin
Gary Stafford2-Apr-10 8:58
Gary Stafford2-Apr-10 8:58 
GeneralRe: Great Article Pin
Steve Krile2-Apr-10 9:25
Steve Krile2-Apr-10 9:25 
GeneralRe: Great Article Pin
Gary Stafford2-Apr-10 11:15
Gary Stafford2-Apr-10 11:15 
Generalconverted to c#, need help bubbling an event Pin
mrbikejoc8-Aug-09 13:27
professionalmrbikejoc8-Aug-09 13:27 
GeneralRe: converted to c#, need help bubbling an event Pin
mrbikejoc8-Aug-09 13:28
professionalmrbikejoc8-Aug-09 13:28 
GeneralRe: converted to c#, need help bubbling an event Pin
Steve Krile8-Oct-09 8:51
Steve Krile8-Oct-09 8:51 
QuestionAwesome article! Pin
bretBolton27-Jun-09 9:04
bretBolton27-Jun-09 9:04 
Generalnot only good article, but good idea as well Pin
cinamon14-Jun-09 11:11
cinamon14-Jun-09 11:11 
both idea and article are good, nice execution as well. brilliant job!
GeneralRe: not only good article, but good idea as well Pin
Steve Krile15-Jun-09 1:02
Steve Krile15-Jun-09 1:02 
GeneralGood article -- code file missing in the download Pin
kmudda7-May-09 6:22
kmudda7-May-09 6:22 
GeneralRe: Good article -- code file missing in the download Pin
Steve Krile7-May-09 6:35
Steve Krile7-May-09 6:35 
Generalnice Pin
Jeff Circeo6-May-09 12:42
Jeff Circeo6-May-09 12:42 

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.