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..
Old fashioned guys use SQL Server varchar/text fields to store strings of multiple languages that uses 1 byte encoding like [Windows Character Table] :
Windows-1252 : English, French , Spanish, German,Italian,Spanish (Western European characters)...
Windows-1251 : Russian,Bulgarian,Serbian,Ukrainian
Windows-1253 : Greek
Windows-1256 : Arabic
.....
Of course, 1 byte encoding field can contain English + only one other language characters - unlike UTF-8) , just as a file encoded in 1-byte encoding..
To know about Character sets, you should check :
The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
in that case : Asp pages codepage should remain as default = 1252
<% @ LANGUAGE=VBScript CODEPAGE=1252 %>
and setting the Response.Charset or HTML meta tag for charset correctly will show things right.. and HTML page size is smaller than the same one in UTF-8
of course running a site like that in IIS, will require that windows > Control Panel > Regional and Language options > Advanced > must be English or Strings read from SQL server will be corrupted...
A disadvantage is that you can't show more than one language (Other than English) in the same page without using escape codes... ,which suitable is for small text (a link to other language home page)
but, if you need to output UTF-8 file (text,Xml ,RSS,..) from non UTF-8 page, you must remember that Strings are Unicode in memory, so if you read a string from SQL Server using settings as mentioned before , and as an example :
- if we have that string "привет" which is "hi" in Russian
- and saved in varchar field in SQL Server it will look like "ïðèâåò"
- when you read that string in memory using ado it will look like "ïðèâåò" , cause VB string can't know it is Russian ( it is readed from varchar and default codepage is 1252 ,so it thinks it is Western European characters)
- So To Convert it to Russian will use ADO Stream :
AlterCharset("ïðèâåò","windows-1252", "windows-1251")
- After that it would be saved in memory as "привет"
- and when written to UTf-8 file , it will be "привет" , but if u don't do the Conversion step it will be "ïðèâåò"
enough talking , here is the code
For this code to work in VB6, you will need to add a reference to the Microsoft ActiveX Data Objects 2.5+ Library and change [Dim Stream : Set Stream=Server.CreateObject("ADODB.Stream") ] to [Dim Stream as new ADODB.Stream]Const adTypeBinary = 1
Const adTypeText = 2
' accept a string and convert it to Bytes array in the selected Charset
Function StringToBytes(Str,Charset)
Dim Stream : Set Stream = Server.CreateObject("ADODB.Stream")
Stream.Type = adTypeText
Stream.Charset = Charset
Stream.Open
Stream.WriteText Str
Stream.Flush
Stream.Position = 0
' rewind stream and read Bytes
Stream.Type = adTypeBinary
StringToBytes= Stream.Read
Stream.Close
Set Stream = Nothing
End Function
' accept Bytes array and convert it to a string using the selected charset
Function BytesToString(Bytes, Charset)
Dim Stream : Set Stream = Server.CreateObject("ADODB.Stream")
Stream.Charset = Charset
Stream.Type = adTypeBinary
Stream.Open
Stream.Write Bytes
Stream.Flush
Stream.Position = 0
' rewind stream and read text
Stream.Type = adTypeText
BytesToString= Stream.ReadText
Stream.Close
Set Stream = Nothing
End Function
' This will alter charset of a string from 1-byte charset(as windows-1252)
' to another 1-byte charset(as windows-1251)
Function AlterCharset(Str, FromCharset, ToCharset)
Dim Bytes
Bytes = StringToBytes(Str, FromCharset)
AlterCharset = BytesToString(Bytes, ToCharset)
End Function

Web developer, jQuery plugin author, social media fan and Technology Blogger.