skip to main | skip to sidebar
Showing posts with label HTML. Show all posts
Showing posts with label HTML. Show all posts

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..
Paging Listbox
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="&#9660;" />
      <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

Mike

Mike MoreWeb developer, jQuery plugin author, social media fan and Technology Blogger.
My favorite topics are: jQuery , Javascript , ASP.Net , Twitter , Google..
<connect with="me"> </connect>

Subscribe by email

Enter your email address:

or via RSS