Thursday, January 25, 2007

ClickOnce Button for ASP.Net 2.0

We have a couple of forms from which we get double submissions by people hitting the submit button again and again. We decided to go with a ClickOnce button that disables itself when the form submits. I saw a couple of solutions that implement it but nothing for ASP.Net 2.0.
I ended up implementing it in myself.

About 5 lines of code placed in the Page_Load event handler:


// Define the name and type of the client script on the page.
String csname = "OnSubmitScript";
Type cstype = this.GetType();
// Get a ClientScriptManager reference from the Page class.
ClientScriptManager cs = Page.ClientScript;
// Check to see if the OnSubmit statement is already registered.
if (!cs.IsOnSubmitStatementRegistered(cstype, csname))
{
String cstext = "if (typeof(ValidatorOnSubmit) == 'function' && ValidatorOnSubmit() == false)return false; else { var myCtl = document.getElementById('" + this.SubmitButton.ClientID + "'); myCtl.value = 'Please wait...'; myCtl.disabled = true;}";
cs.RegisterOnSubmitStatement(cstype, csname, cstext);
}

On the aspx page we have:

<asp:button id="SubmitButton" onclick="SubmitButton_Click" usesubmitbehavior="False" runat="server">


There are 2 gotchas here:
1. Make sure validation takes place and the page validates prior to disabling the button. This is done with JavaScript
2. Make sure the button is not rendered as input type submit otherwise when it is disabled it will not trigger the correct event handler on postback - for that we use: UseSubmitBehavior="False".

Friday, January 19, 2007

Temporary Tables and Dynamic SQL

When programming in SQL on occasion there is a need to generate temporaty tables inside a sproc without knowing the colums or type when the sproc is written. One such situation would be when you want to pivot a table. You can create a cursor over a column result set and create a new column for each value.

When you try to create temporary tables with dynamic SQL you will run into a scoping problem.
for example:

DECLARE @SQL nvarchar(4000)
SELECT @SQL = 'CREATE TABLE #Temp (col1 int)'
EXEC (@SQL)
SELECT * FROM #Temp

This will cause an error:

Msg 208, Level 16, State 0, Line 4
Invalid object name '#Temp'.

The problem here is the scope of the session. When we execute dynamic sql via EXEC or sp_executesql a new scope is created for a child session. Any objects created in that session are dropped as soon as the session is closed.

One solution I have found for this problem is creating the table in the "parent" scope and then just using dynamic sql to modify the table. For this to work a table is created with a minimum set of colums. And then we use the ALTER TABLE statement with dynamic SQL. The Child session has access to the objects created in the parent session so the table can be modified with dynamic sql:

DECLARE @SQL NVARCHAR(4000)
CREATE TABLE #Temp ( id int null)
SELECT @SQL = 'ALTER #Temp ADD Col1 int null'
EXEC (@SQL)
SELECT * FROM #Temp
DROP TABLE #Temp

This table is visible and both columns will show up.

Thursday, January 18, 2007

Improving on the ASP.Net Regular expression validator for phone numbers

When I am working on web development I often use the ASP.Net regular expression validator in order to validate phone numbers.
The validation expression for US phone numbers that is built in to Visual Studio expects phone numbers in xxx-xxx-xxxx format.
The problem with that is that you alwas have to preface the prompt for the phone number with a sentence explaining the format and even then people often mess it up and do not understand why their form does not submit.
A good solution for the problem is to wire the onkeyup event that will add the dashes in all the right places.
For example this is in ASP.Net 2.0:

<asp:textbox id="homePhoneTextBox"
runat="server" maxlength="12" onkeyup="phoneFormat(this, event)"></asp:textbox>
In asp.net 1.1 you can do it on the code behind:

in c# this whould be something like:

this.homePhoneTextBox.Attributes.Add("onkeyup", ="phoneFormat(this, event)");

Now all you need to do is handle this event with a JavaScript function that will format the phone number for the user:

function phoneFormat(sender, ev)
{
var theNumber;
var i;
theNumber = '';
for(i = 0; i < thenumber =" theNumber" keycode ="="> 0)
{
theNumber = theNumber.substring(0, theNumber.length -1);
}
if (theNumber.length > 6)
{ sender.value = theNumber.substring(0,3) + '-' + theNumber.substring(3,6) + '-' + theNumber.slice(6);
return(true);
}
if (theNumber.length > 5)
{
sender.value = theNumber.substring(0,3) + '-' + theNumber.substring(3,6)+ '-';
return(true);
}
if(theNumber.length > 3)
{
sender.value = theNumber.substring(0,3) + '-' + theNumber.slice(3)
return(true);
}
if (theNumber.length > 2)
{
sender.value = theNumber.substring(0,3)+ '-';
return(true);
}
sender.value = theNumber;
return(true);
}

Not the shortest function ever but it does the trick.
If you want to grab the file you can do it here:
http://www.shkedy.com/blogFiles/01182007/CustomValidation.js

Wednesday, January 17, 2007

Alternating HTML table Row Styles with javascript and CSS

In a website that we built for a clients http://www.isoabroad.com/ we had to use alternating row styles for the tables. When I generate tables dynamically using server side code this is pretty easy. I can just specify a different class for each . If the tables are static this becomes a mess. For http://www.isoabroad.com/ one of our web designers had to hand code the classes for each of the rows and each time we had to add or remove a row he had to edit all consecuitive rows.
For another website we were working on I had used a different approach. Using JavaScript and CSS I set a class for the table (altRows). When the page load I look for all the table elements and traverse the rows, setting the different classes for alternating rows. If a row already has a class defined the script will not change it which makes it perfect for header rows etc. I tested the solution in IE, Firefox and Opera and it works :)
The code is listed below:

function alternateRowStyles()
{
var i, j;
var table;
for( i =0; i < document.getElementsByTagName("table").length; i++) { if( document.getElementsByTagName("table")[i].className == "altRows") { table = document.getElementsByTagName("table")[i]; for ( j = 0; j < table.rows.length; j++) { if (table.rows[j].className == "") { if (j%2 == 0 ) { table.rows[j].className = "oddClass"; } else { table.rows[j].className ="evenClass"; } } } } } }
You can see it in action at http://www.usnetcare.com

If you want to download the code including a function that will wire the function to the onLoad event of the page you can do so at:
http://www.shkedy.com/blogfiles/01172007/formatting.js

Tuesday, January 16, 2007

Creating GUIDs with Client Side JavaScript

I needed to generate GUIDs (globally unique identifiers) for a web project I was working on.
The only solutions I could see for that task involved evoking an ActiveX control which makes it really useless for general purpose. I ended up writing a short javascript that will achieve this task:

function generateGuid()
{
var result, i, j;
result = '';
for(j=0; j<32; j++)
{
if( j == 8 || j == 12|| j == 16|| j == 20)
result = result + '-';
i = Math.floor(Math.random()*16).toString(16).toUpperCase();
result = result + i;
}
return result
}