Wednesday, November 14, 2007

window.location.search Property

window.location.search Property

One of the not so commonly-used properties of window.location object in javascript is the window.location.searchproperty.

For example, in a web address like

http://www.my.org/pg.htm?user=2&role=admin

the window.location.search property will have all the characters after the "?" including it(?user=2&role=admin).
How can this information be useful? Well, for starter, we can access all the request parameters at client-side (using javascript) instead of processing it at server-side using codebehind. Since we have access to the request parameters,
we can do manipulations on its value or use the values contained in the request parameters to populate the value of the controls on the current page. For example, we have a web address like:

http://www.sample.org/login.htm?username=gotwald
if login.html contains usename and password input textboxes, we can automatically populate the username field with the value from the request parameters. See the screenshot below:
Here's the complete source of the sample:

<html xmlns="http://www.w3.org/1999/xhtml">
<
head>
<title>Untitled Page</title>
<script type="text/javascript">
window.onload = function()
{
if(window.location != null && window.location.search.length > 1 )
{
var urlParameters = window.location.search.substring(1);
var
parameterPair = urlParameters.split('&');
var
pos = parameterPair[0].indexOf('=');
var
argName = parameterPair[0].substring(0, pos);
var
argVal = parameterPair[0].substring(pos + 1);
if
(argName == 'username' )
{
document.getElementById('user').innerText = argVal;
}
}
}
</script>
</head>
<body>
<table cellpadding="4" cellspacing="0">
<
tr>
<td colspan="2">Enter login information</td>
</tr>
<tr>
<
td align="right">username:</td>
<td><input type="text" size="25" id="user" name="user" /></td>
</tr>
<
tr>
<
td align="right">password:</td><td><input type="text" size="25" id="pass" name="pass" /></td>
</tr>
lt;tr>
<td align="right"></td>
<td><input type="button" value="login" /></td>
</tr>
</table>
</
body>
</html>

Still you need to add input validation and error-handling in your code should you
need to adopt this sample code but the code itself is running on a "happy scenario",
if you know what I mean.

I thought You'd Like to Know

Difference between RegisterClientScriptBlock and RegisterStartupScript

Page.RegisterStartupScript (System.Web.UI)
Emits a client-side script block in the page response.
This method is now obsolete. Use ClientScript.RegisterStartupScript instead.

Page.RegisterClientScriptBlock (System.Web.UI)
Emits client-side script blocks to the response.
This method is now obsolete. Use ClientScript.RegisterClientScriptBlock instead.

A control can place a startup script on a page via the RegisterStartupScript method. You can also place a script block that needs to be explicitly called by other script code on the same page using the RegisterClientScriptBlock method.

The difference between the two methods is that that the latter goes in the top of the page (immediately below the opening tag of the Page's <form runat='server' /> element) and the former goes at the bottom (just before the closing tag of the Page's <form runat='server' /> element). This is important because inline script generally needs to go at the bottom so that the page objects exist before it executes. However, regular script (script methods that will be called based on other control's events) must go at the top in case a control is referencing it. For example, in an onClick event of a button, you would like to reference function foo(), and foo() was emitted via codebehind. The correct way of registering foo() is by using RegisterClientScriptBlock.

Note: as always, remember to include HTML comment tags (<!-- your script here -->) around your script so that it will not be rendered if the requesting browser does not support scripts.

Tuesday, November 13, 2007

How to add External Tool on Visual Studio IDE

Note: This article is for absolute beginner.

There are some cool external tools that I found valuable in my web development tasks. One of them is a utility called javascript lint, a javascript checker/verifier. In this article, I would discuss how to add js lint as an external tool.

First, you need to download a copy of javascript lint.

  1. Then click on Tool->External Tools
  2. Click Add.
  3. Specify name for the Tool
  4. On the Command field, click browse to locate the javascript lint executable. The value of this field should be complete path to executable plus the executable name.
  5. On the Arguments field, you can just put -process $(ItemPath). The arguments here depends on the arguments that are supported by the external tool. In this case, javascript lint needs a -process parameter.
  6. On the Initial Directory, put $(ProjectDir)
  7. Put a check mark on Use Output Window checkbox.
  8. Click Apply.

Cool! Now you are set. You should be able to see a new Tool Menu item. Go ahead and give it a try.

String Concatenation versus StringBuilder Class

When concatenating large strings (for example, building an HTML table from a database),the length of time to complete can become quite long as the string gets larger. This article demonstrates the difference in string concatenation using String and StringBuilder classes.

String Concatenation using String Class.

An ordinary code to create a string from a subset of two strings is usually implemented this way:

string c = "sample" + "code";

This approach usually does the job for most of the applications that we write. But when the situation comes that we need to create a large subset of string by continuous iteration (e.g. a string that contains all numbers from 0 to 10000 or as mentioned above, building an HTML table from database, this approached was proven to be inefficient. According to the Microsoft KB Article # 170964, here's what really happens when we concatentate two strings:

  1. Allocates temporary memory large enough to hold the result.
  2. Copies Destination to the start of the temporary area.
  3. Copies Source to the end of the temporary area.
  4. De-allocates the old copy of Destination.
  5. Allocates memory for Destination large enough to hold the result.
  6. Copies the temporary data to Destination.

Steps 2 and 6 are very expensive and basically result in the entire concatenated result being copied twice with additional overhead to allocate and de-allocate memory. A typical 100K iterations using this string processing will take more or less four minutes to complete.

String Concatenation using StringBuilder Class.

The performance of a concatenation operation for a String or StringBuilder object depends on how often a memory allocation occurs. A String concatenation operation always allocates memory, whereas a StringBuilder concatenation operation only allocates memory if the StringBuilder object buffer is too small to accommodate the new data. Consequently, the String class is preferable for a concatenation operation if a fixed number of String objects are concatenated. In that case, the individual concatenation operations might even be combined into a single operation by the compiler. A StringBuilder object is preferable for a concatenation operation if an arbitrary number of strings are concatenated; for example, if a loop concatenates a random number of strings of user input.

Here's a sample code that I wrote to demostrate the comparison:



using System;
using
System.Web;
using
System.Text;
public
partial class _Default : System.Web.UI.Page
{
string myString = "";
StringBuilder sb = new StringBuilder();
protected void
Page_Load(object sender, EventArgs e)
{
Response.Write(
"Start 100K loops
using string catenation:"
+
DateTime.Now.ToString(
"HH:mm:ss:ff")+"<br/>");
Iterate100K_With_StringAppend();
Response.Write("End 100K loops using string catenation :" +
DateTime.Now.ToString
"HH:mm:ss:ff") + "<br/>");
Response.Write("Start 100K loops using StringBuilder: " +
DateTime.Now.ToString(
"HH:mm:ss:ff") + "<br/>");
Iterate100K_With_StringBuilder();
Response.Write("End 100K loops using StringBuilder : " +
DateTime.Now.ToString(
"HH:mm:ss:ff") + "<br/>");
}
private void Iterate100K_With_StringAppend()
{
for (int i = 0; i < 99999; i++)
myString +
= i.ToString();
}
private void Iterate100K_With_StringBuilder()
{
for (int i = 0; i < 99999; i++)
sb.Append(i.ToString())
;
}
}

Your result may be slightly different from my result, but you should see signification difference on the time that it takes to perform string concatenation using string class and the time it took using StringBuilder class. The results on my test are as folows:

Start 100K loops using string catenation: 15:22:48:24
End 100K loops using string catenation : 15:26:45:20
Start 100K loops using StringBuilder : 15:26:45:20
End 100K loops using StringBuilder : 15:26:45:26

Note: Most contents are © 2007 Microsoft Corporation aside from some comments and sample code that I added.

Saturday, November 10, 2007

I'm Alive!

Well, it's been a long while. More than a year since my last post here. I was busy (there goes my default alibi) with my work and some other stuff but I think I can give more time now with this blog. I am planning to publish an article on how to create a custom vertical label control on windows forms and with an added support for transparent background.

Stay tuned.