Render RadioButtonList as an Unordered List UL

In my latest project, I found the need to use the RadioButtonList which spits out the absolute nastiest HTML to render it unusable (for me anyway). The control gives you to HTML options using the RepeatLayout attribute.

Flow spits out a series of span’s and label’s with BR’s if you don’t specify RepeatDirection of Horizontal. And choosing Table gives you a nicely unaccessible table you can’t format easily. Because of these limitation’s, I have always stayed away from CheckBoxList and RadioButtonList controls.

My solution is to write my own RadioButtonList, but to spit it out as an Unordered List which I can style very easily horizontally or vertically, little or lots of padding, all with CSS.

I unfortunately have been forced to regress back to ASP.NET 1.1 and VB.NET for a little while until the company upgrades to 2.0. Hence why I wrote the following instead of writing a CSS Control Adapter.

Imports System
Imports System.ComponentModel
Imports System.Text
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls

Namespace MyControls

 <DefaultProperty("Text"), _
ToolboxData("<{0}:ULRadioButtonList runat=server />") _
, Description("Creates a RadioButtonList using an Unordered List.")> _
Public Class ULRadioButtonList
Inherits RadioButtonList

 Protected Overrides Sub Render(ByVal writer As HtmlTextWriter)

//"SBE 01/28/2007:  just in case...not sure if this is needed or not
Controls.Clear()

//"SBE 01/28/2007:  not sure why I am leaving quotes as a param...I was just undecided if I would ever need to use " instead of "
Dim inputFormatString As String = "<input id={0}{1}{0} name={0}{2}{0} type={0}radio{0} value={0}{3}{0} {4} />"
Dim labelFormatString As String = "<label for={0}{1}{0}>{2}</label>"

//"SBE 01/28/2007:  if user sets the cssclass, add it to the <ul> tag
If (Not MyBase.CssClass Is Nothing AndAlso MyBase.CssClass <> "") Then
     writer.WriteLine("<ul class="" & MyBase.CssClass & "">")
Else
     writer.WriteLine("<ul>")
End If

//"SBE 01/28/2007:  loop through the dataitems
For index As Integer = 0 To Items.Count - 1
     writer.Indent += 1
     writer.WriteLine("<li>")
     writer.Indent += 1

     Dim inputBuilder As New StringBuilder
     Dim labelBuilder As New StringBuilder
     Dim checked As String = ""

     If (Items(index).Selected) Then
          checked = "checked"
     End If

     inputBuilder.AppendFormat(inputFormatString, """", MyBase.ClientID & "_" & index.ToString(), MyBase.UniqueID, Items(index).Value, checked)
     labelBuilder.AppendFormat(labelFormatString, """", MyBase.ClientID & "_" & index.ToString(), Items(index).Text)

     writer.WriteLine(inputBuilder.ToString())
     writer.WriteLine(labelBuilder.ToString())

     writer.Indent -= 1

     writer.WriteLine("</li>")
     writer.WriteLine()
     writer.Indent -= 1

 Next

 writer.WriteLine("</ul>")

 End Sub

 End Class

End Namespace

Before I started writing this, I found a beautiful website SimplyGold who had already wrote something similar for the CheckBoxList. Thanks for saving me some time!

Now playing: MenomenaMuscle n’ Flo

Emulating Digg Spy using AJAX.NET

In my latest project, I need to build a lead system for our sales people. It will work very similarly to the digg.com/spy application, so I took advantage of their model in order to learn AJAX.NET.

I decided to go with AJAX.NET, rather than the new Anthem, just to get my feet wet. I will make it work in Anthem next.

This is what my example will look like:

Beforesubmit
and after you click the button:

Aftersubmit
Using AJAX, it went and grabbed a new item, and inserted it to the top row, and removed the bottom row. Digg’s Spy is obviously nicer, but it does essentially the same thing.

Yes, there are TONS of ways I can optimize this and make it slimmer and nicer, but his was a proof of concept. I know I didn’t have to use a DataSet, but since I wanted to see it work, I used it. I also didn’t care about formatting a date in javascript.

Here is my code behind code:

public class test : System.Web.UI.Page
{
   private void Page_Load(object sender, EventArgs e) {
     Ajax.Utility.RegisterTypeForAjax(typeof(test));
   }

   [Ajax.AjaxMethod()]
   public DataSet GetLeads() {
        DataSet ds = new DataSet();
        DataTable dt = new DataTable("MyTable");
        ds.Tables.Add(dt);
        dt.Columns.Add("ID", typeof(int));
        dt.Columns.Add("Firstname", typeof(string));
        dt.Columns.Add("Date", typeof(DateTime));

        dt.Rows.Add(new object[] { 1, "steve", DateTime.Now });
        return ds;
   }

And here is my sample for the .aspx file:

<html>
<head>
<style>

.lead {
clear: both;
border-top: 1px solid #ccc;
}

#mostrecent { font-weight:bold; }

.column1, .column2, .column3 {
float: left;
display: block;
text-decoration: none;
}

.header span {
font-weight: bold;
background:#eee;
}

.column1 {
width: 6em;
text-align: center;
/*border: 1px solid green;*/
}

.column2 {
display: block;
width: 10em;
/*border: 1px solid blue;*/
}

.column3 {
display: block;
width: 20em;
/*border: 1px solid yellow;*/
}
.button {
clear: left;
}
</style>
</head>
<body> 

<form id="Form1" method="post" runat="server">
<div id="leads">
   <div class="header">
      <span class="column1">ID</span><span class="column2">Name</span><span class="column3">Date</span>
   </div>

   <div class="lead" id="mostrecent"><span class="column1">54</span><span class="column2">scott</span><span class="column3">1/1/2006</span></div>
   <div class="lead"><span class="column1">22</span><span class="column2">peter</span><span class="column3">1/2/2006</span></div>
   <div class="lead"><span class="column1">12</span><span class="column2">sam</span><span class="column3">1/3/2006</span></div>
   <div class="lead"><span class="column1">44</span><span class="column2">sally</span><span class="column3">1/4/2006</span></div>
   <div class="lead"><span class="column1">51</span><span class="column2">paul</span><span class="column3">1/5/2006</span></div>
</div>
<div class="button">
   <input type="button" onclick="buttonClick()" value="blah"/>
</div>

<script language="javascript">

function buttonClick() {
   test.GetLeads(GetLeads_CallBack);
}

function GetLeads_CallBack(response){

//SBE 02/08/2006:  create the div element
var newLead = document.createElement('div');

//SBE 02/08/2006:  set its class to lead
newLead.setAttribute('class', 'lead');

var leadTable = document.getElementById('leads');
var rows = leadTable.getElementsByTagName('div');
var numrows = rows.length;
var html = "";

//SBE 02/08/2006:  make sure we got a dataset to loop through
var ds = response.value;
if(ds != null && typeof(ds) == "object" && ds.Tables != null){
   var s = new Array();

   s[s.length] = "<span class='column1'>" + ds.Tables[0].Rows[0].ID + "</span>";
   s[s.length] = "<span class='column2'>" + ds.Tables[0].Rows[0].Firstname + "</span>";
   s[s.length] = "<span class='column3'>" + ds.Tables[0].Rows[0].Date + "</span>";

   html = s.join("");
}
else{
   alert("Error. [3001] " + response.request.responseText);
}

//SBE 02/08/2006:  assign the html to the new lead
newLead.innerHTML = html;

oldItem = document.getElementById('mostrecent');
leadTable.insertBefore(newLead, oldItem);
newLead.setAttribute('id', 'mostrecent');
oldItem.setAttribute('id', '');

// remove last row
leadTable.removeChild(rows[rows.length-1]);

}
</script>
</form> 

</body>
</html>

CSS Fun With MySpace

A bunch of kids at my work are on myspace, and they spend TONS of time on the website. I spent some time looking at their sites they created, and came to the realization that the basic point is to make something so disgusting and hard to read than your friend. There is no observation of usable design, no understanding the pink text on a green flowery background hurts your eyes, or that if you have 10 videos running at the same time it slows your computer down to a crawl.

For giggles, I signed into my account after not logging in for a year and tried to create a site that was actually normal. My goal was to:

  • Cover up the top banner
  • Hide all the top navigation
  • Replace with my own navigation
  • Replace the background

I created my own buttons, but it is just one big image. I could of spent more time and actually created hyperlinks, but as it was I spent an hour working on this uselessness and finally woke up and got back to work. In any sense, here is the CSS I threw in my profile:


<div class="assSpace"></div>
<style>
.navbar {visibility:hidden;}
.man {visibility:hidden;color:..003399;}
.assSpace {
   background-color:white;
   background-image:url(http://www.scottelkin.com/images/myspaceheader.jpg);
   background-position:top left;
   margin-left: -363px;
   margin-right: auto;
   width:798px;
   height:150px;
   position:absolute;
   top:0px;
}
html>body .assSpace {
   margin-left:-368px;
}
div table form tr td {background-color:white;}
Table, Td{ background-color:transparent; }
table table table{ border:0px;}
table table table table{ width:auto; }
table table table table, table table table td{ border-style:none; }
body {
   background-image:url(http://www.scottelkin.com/images/myspacebg.gif);
   background-position:top center;
   font:small Verdana,Sans-serif;
   line-height:1.6em;
}
input  {
   font: 11px arial,helvetica, sans-serif;
   font-weight: bold;
   letter-spacing: 1;
   color: gray;
   cursor: pointer;
   cursor: hand;
   background-image : url(http://www.statify.com/images/button.gif);
   background-color : White;
}
</style>