Many times in web forms we need to provide a listbox with lots of elements, A good solution is to filter and page these elements to speedup page loading and optimize DB/Network usage..
Update! I've rewritten the code as jQuery plugin, made few enhancements and provided a complete sample code in VB.Net and C#. check-out the new plugin of Paging Listbox.
This is a complete implementation of a paging listbox using jQuery on client side and ASP.Net on server side. and should look like this..
The form web page, which also contains the JavaScript class to build the select box, of course don't forget to download the jQuery library.<html>
<head>
<title>jQuery & Ajax Fun: Implementing a Paging Listbox</title>
<script type="text/javascript" src="JS/jquery-1.3.min.js"></script>
<script type="text/javascript">
function AjaxListBox() {
this.source = '';
this.divID= '';
this.keyID= '';
this.buttonID= '';
this.lastKey= '';
this.startup= true;
this.minWidth=0;
this.position = {'top':0,'left':0};
var self = this;
this.init= function() {
$(document).ready(function(){
//calc position and min-width for listbox
self.minWidth = $('#'+self.keyID).width()+ $('#'+self.buttonID).width()+4;
self.position = $('#'+self.keyID).position();
self.position.top= self.position.top + $('#'+self.keyID).height()+2;
// Position and hide div
$('#'+self.divID).css({'display':'none','border':'gray 1px solid','position':'absolute','z-index':5,'top':self.position.top,'left':self.position.left});
// bind onclick handler for 'toggle' button
$('#'+self.buttonID).bind('click',null,self.toggle);
// bind onkeydown handler for 'Key' textinput and call find function
$('#'+self.keyID).bind('keydown',null,self.keydown);
//load list
self.load();
});
}
this.load= function(key,pi) {
if(key==null ||key=='undefined') key='';
if(pi==null ||pi=='undefined') pi='';
//Save key to use when move through pages
this.lastKey= key;
$('#'+this.divID).html('please wait..');
$.get(this.source,{'key':key,'pi': pi},this.loaded,'html' );
}
this.loaded = function(data,txtStatus) {
//Set Inner html with response of Ajax request
$('#'+self.divID).html(data);
$('#'+self.divID+' > select').css({'border-width':'0'});
//Add handler for onchange to reload when another page is requested
$('#'+self.divID+' > select').bind('change',null,self.change);
//Add handler for onblur to hide box
$('#'+self.divID+' > select').bind('blur',null,self.hide);
if (self.startup) self.startup=false;
else self.show();
}
this.change = function() {
//Get Value of Select Box
var v = $('#'+self.divID+' > select').val();
//To do paging the value must be like 'pi=2' which means go to page 2
if (/^pi=\d+$/i.test(v)) {
var pi= v.replace(/pi=/i,'');
self.load(self.lastKey,pi);
}
}
this.toggle = function(e) {
if ($('#'+self.divID).css('display')=='none') self.show();
else self.hide();
}
this.show = function(e){
$('#'+self.divID).show();
//Insure width is more than min-width
var w = $('#'+self.divID+' > select').width();
if (w>0 && w<self.minWidth) $('#'+self.divID+' > select').width(self.minWidth);
}
this.hide = function(e){
$('#'+self.divID).hide();
}
this.find = function() {
//text to search for
self.load($('#'+self.keyID).val());
}
this.keydown = function(e) {
// this will catch pressing enter and call find function
var intKey = e.keyCode;
if(intKey == 13) {
self.find();
//and prevent submitting the form that contain this input box
return false;
}
}
}
</script>
<style type="text/css">
* {
font:12px arial
}
.AjaxListBoxKey {
border:gray 1px solid;
width:120px;
}
.AjaxListBoxKeyBTN{
border:silver 1px solid;
background-color:#333333;
color:white;
padding:.5px;
font:12px arial;
}
</style>
</head>
<body>
<form id="form1" action="" method="post">
Select Product
<input id="key" name="key" type="text" class="AjaxListBoxKey" /><input type="button" id="find" class="AjaxListBoxKeyBTN" value="▼" />
<div id="box"></div>
<script type="text/javascript">
var box = new AjaxListBox();
box.source = "listbox.aspx";
box.divID = "box";
box.keyID = "key";
box.buttonID= "find";
box.init();
</script>
</form>
</body>
</html>
The server side page(whatever the language is!) is requested to handle query string parameters (pi: PageIndex, key: Search keyword) and response with just a list box(no other tags!) that contains the matched elements at the requested page index, plus 2 extra elements to go to previous and next pages indexes with value like 'pi=3' which means go to page 3. Of course you can select the PageSize and listbox size that works for you.
Here is server side page "listbox.aspx"<%@ Page Language="VB" %>
<script runat="server" language="VB">
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim key As String = Request.QueryString("key") & ""
Dim PageIndex As Integer = 1
Try
PageIndex = Integer.Parse(Request.QueryString("PI"))
Catch ex As Exception
PageIndex = 1
End Try
Dim ps As New Products
ps.PageSize = 5
ps.PageIndex = PageIndex
ps.SelectItems(Product.ProductStatus.Active, key)
Response.Write(ps.PagingBox("ProductID", 0, , , 5))
ps = Nothing
End Sub
</script>
On Listbox.aspx I'm using my favorite[Traditional yet Powerful : Data Access Layer for ASP.Net] to access the products Table after adding the following function to the collection class to build the listbox.Public Function PagingBox(ByVal FieldID As String, ByVal SelectedID As Integer, Optional ByVal FieldClass As String = "", Optional ByVal Onchange As String = "", Optional ByVal size As Integer = 0) As String
Dim ret As New StringBuilder("<select name=""" & FieldID & """ id=""" & FieldID & """")
If FieldClass > "" Then ret.Append(" FieldClass=""" & FieldClass & """")
If Onchange > "" Then ret.Append(" Onchange=""" & Onchange & """")
If size > 0 Then ret.Append(" size=""" & size + 2 & """")
ret.Append(">")
If Me.Count = 0 Then
ret.Append("<option value="""">-- No Results! --</option>")
End If
If PageIndex > 1 Then
ret.Append("<option value=""pi=" & (PageIndex - 1) & """>" & _
"-- to Page " & (PageIndex - 1) & " of " & PageCount & " --</option>")
End If
For i As Integer = 0 To Me.Count - 1
Dim P As Product = Item(i)
ret.Append("<option value=""" & P.ID & """")
If P.ID = SelectedID Then ret.Append(" selected")
ret.Append(">" & P.Name & "</option>")
Next
If PageIndex < PageCount And PageIndex > 0 Then
ret.Append("<option value=""pi=" & (PageIndex + 1) & """>" & _
"-- to Page " & (PageIndex + 1) & " of " & PageCount & " --</option>")
End If
ret.Append("</select>")
Return ret.ToString
End Function
Many greetings to jQuery folks..
I tried to implement this article with my code. i have a dataset which contain value more than 10,000+ . So i want to implement this paging mechanism but how can i embeed my dataset with this code. Also i do in C sharp. Plz help me to bind with dataset.
@Anonymous,
Wherever data is coming from.. you need to have an aspx page that loops your dataset and response.write the <select> and <option> tags that constructs the listbox.. without using master page or any extra html..
Like that...
good articles..
thank u