I generally don't post stuff like this but…what the hell…
Are you a good developer? A great developer? A World Class developer? Perhaps you only think you are a good developer. Maybe you are a terrible developer and don't even know it. The only way to know for sure is to get feedback from other developers and the users of your software.
I believe developers go through several learning phases on their way to becoming World Class developers. There are no short cuts…the dues must be paid. Here are five phases I have observed…as they relate to the code produced:
Phase I: It Works.
The first time you get a program to work is immensely rewarding: You have mastered the computer. It was tough…but patience and persistence paid off. Not everyone can do what you just did. Not everyone can make a program work. You are special. You have experienced the magic of bending a machine to your will.
However, sometimes your program crashes. Sometimes it gives unexpected results. How were you to know those pesky users would type in letters when digits were expected? Sadly, some developers never get beyond this phase. Some begin to see themselves as 'creative visionaries': their code is 'proof of concept' and wasn't designed for actual use (so they say). Implementation details are left to others. Often these people are arrogant and fool managers into believing they are gifted. It is a sad programming shop where this occurs.
Phase II: It Works Good. At this phase, the developer has learned to really test the code. They test every input and account for every output. They check the return value of every function. They installed exception handlers and deal with the exceptions raised in testing. The program is now bullet-proof, tsunami-proof and even pointy-haired manager proof. It took extra work but now it is rock solid. No more embarrassing crashes.
But there is a slight problem; the code is a pile of convoluted spaghetti with deeply nested if-else clauses and case statements. It's disgusting to look at and it's embarrassing to admit you can't maintain your own code. When someone asks for a new feature, you take a sick day and update your resume.
Phase III: It is Good. The code works well and it's solid. But, you rewrite it anyway—sometimes several times. You re-organize it so it is clear to read and easy to understand. The code is logically separated into functions, classes and modules. There are concise helpful comments in the code. An intern may view the code and sneer, "What's the big deal, that's simple, I could have written that". No, he couldn't. He has no idea what it took to get the code to that state. Simplifying complexity is an art that cannot be taught.
Phase IV: It has Added Value. While working on the code, you created several functions and classes that can be reused in other projects. It takes more work to make a module reusable...three times as much work is the general consensus. The reusable modules help other projects get a head start. Other developers trust you and, more importantly, they trust your code. You recognize when to consider 'outside' code and understand the risk/reward of doing so. Leveraging the work of skilled developers is not a short cut, it's smart.
Phase V: It is Delivered Early. After mastering code, design and system architecture, there is only one frontier left to keep the job interesting…beat the schedule. Statistically, 30 to 50 percent of software projects fail. Even more are late. When you can deliver on-time solid code that is easy to maintain, you are gold. Caveat: Schedules are calculated guesses. You can plan all you want but as Mike Tyson succinctly put it: "Everyone has a plan, until they get hit."
So, there it is—my two ¢ents.
Steve Wellens
Note to Professional Editors: I'm aware the text vacillates between second and third person form…but it seemed to work that way so I broke the rules.
CodeProject
Once upon a time, long, long ago, I was working at a company that gave their engineers some shiny, state-of-the-art, new-fangled HP calculators. They were awesome; instead of battery-draining LEDs for display, they used something called an LCD. And, they had buttons galore: more buttons than any other calculator at that time. We positively drooled at their appearance. They looked something like this:
But when it came time to do something useful, like adding two numbers, instead of entering:
3 + 5
You had to enter:
3 5 +
What the heck? Crazy! It's all mixed up! It was using something called: Reverse Polish Notation (postfix instead of infix notation).
A small number of people used their calculators for a few weeks but eventually everyone retired them to a bottom desk drawer. After spending our entire lives with infix notation, no one wanted to change: Learning something new is hard; unlearning something old is harder.
Years later, while I was becoming a software engineer by going to school at night, we studied designing calculator software. Then it made sense: Pushing and popping operators and operands on and off a stack is very efficient for the developer and the computer. Sadly, it is unfriendly for the user.
I believe Linq suffers from the same malady.
Here is a pseudo SQL statement:
select MyNumber from MyTable where MyNumber > 1
Here is a similar Linq query:
from MyNumber in MyList where MyNumber > 1 select MyNumber
What the heck? Crazy! It's all mixed up!
It's Reverse Polish SQL!
How many developers have looked at Linq the first time and said, "No thanks, please go away"? A plethora, I'm sure.
Recently however, I took on a contract that required Linq knowledge. Guess what? You can use the Linq library functions, which are extension methods, without having to delve into the abomination of Reverse Polish SQL.
Here's an example, create a new array that contains the elements common to two other arrays:
int[] MyList1 = new int[] { 1, 2, 3, 4 };
int[] MyList2 = new int[] { 1, 7, 3, 12 };
int[] MyList3 = MyList1.Intersect(MyList2).ToArray();
One line of code! The Intersect method is a Linq extension method. Being able to accomplish a complex task with one line of code is exhilarating and empowering. Did I really say exhilarating? I've got to get out more.
Here are a few more Linq extension method examples:
double Average = MyList1.Average();
int Sum = MyList1.Sum();
MyList3 = MyList1.Where(x => x > 2).ToArray();
OK, Linq is awesome. I am sold. To get a list of available functions, right-click on a Linq Extension method and select "Go To Definition". There are too many functions and overloads to list here. The functions above are in the System.Linq namespace in the static Enumerable class. There are other classes in the namespace but Enumerable is the easiest one to jump into. Here are the others: Linq Namespace.
I hope someone finds this useful.
Steve Wellens
BTW, I have gotten used to the abomination of Reverse Polish SQL. Hmmm, I wonder where that old HP calculator went to.
CodeProject
In my never-ending wandering of technical web sites, I've been encountering links to jsFiddle.net more and more. Why? Because it is an incredibly useful site:
- It is a great 'sandbox' to play in. You can test, modify and retest HTML, CSS, and JavaScript code.
- It is a great way to communicate technical issues and share code samples.
There are four screen areas: Three inputs* and one output:
The three inputs are:
The output is:
Here's a cropped screen shot:

What am I thinking? Here's the actual page: Demo
*There are other inputs. You can select the level of HTML you want to run against (HTM5, HTML4.01 Strict, etc). You can add various versions of JavaScript libraries (jQuery, MooTools, YUI, etc.). Many other options are available.
If I wanted to share this code with someone manually, they would have to copy and paste three separate code chunks into their development environment. And maybe load some external libraries. Not many people are willing to make such an effort. Instead, with jsFiddler, they can just go to the link and click Run. Awesome.
I hope someone finds this useful (and I was kidding about the five bucks).
Steve Wellens
CodeProject
I've always appreciated these tools: Expresso and XPath Builder. They make designing regular expressions and XPath selectors almost fun! Did I say fun? I meant less painful. Being able to paste/load text and then interactively play with the search criteria is infinitely better than the code/compile/run/test cycle. It's faster and you get a much better feel for how the expressions work.
So, I decided to make my own interactive tool to test jQuery selectors: jQuery Selector Tester.
Here's a sneak peek:

Note: There are some existing tools you may like better:
http://www.woods.iki.fi/interactive-jquery-tester.html
http://www.w3schools.com/jquery/trysel.asp?filename=trysel_basic&jqsel=p.intro,%23choose
My tool is different:
- It is one page. You can save it and run it locally without a Web Server.
- It shows the results as a list of iterated objects instead of highlighted html.
- A cheat sheet is on the same page as the tester which is handy.
I couldn't upload an .htm or .html file to this site so I hosted it on my personal site here: jQuery Selector Tester.
Design Highlights:
To make the interactive search work, I added a hidden div to the page:
<!--Hidden div holds DOM elements for jQuery to search-->
<div id="HiddenDiv" style="display: none">
</div>
When ready to search, the searchable html text is copied into the hidden div…this renders the DOM tree in the hidden div:
// get the html to search, insert it to the hidden div
var Html = $("#TextAreaHTML").val();
$("#HiddenDiv").html(Html);
When doing a search, I modify the search pattern to look only in the HiddenDiv. To do that, I put a space between the patterns. The space is the Ancestor operator (see the Cheat Sheet):
// modify search string to only search in our
// hidden div and do the search
var SearchString = "#HiddenDiv " + SearchPattern;
try
{
var $FoundItems = $(SearchString);
}
Big Fat Stinking Faux Pas:
I was about to publish this article when I made a big mistake: I tested the tool with Mozilla FireFox. It blowed up…it blowed up real good. In the past I’ve only had to target IE so this was quite a revelation.
When I started to learn JavaScript, I was disgusted to see all the browser dependent code. Who wants to spend their time testing against different browsers and versions of browsers? Adding a bunch of ‘if-else’ code is a tedious and thankless task. I avoided client code as much as I could.
Then jQuery came along and all was good. It was browser independent and freed us from the tedium of worrying about version N of the Acme browser.
Right? Wrong!
I had used outerHTML to display the selected elements. The problem is Mozilla FireFox doesn’t implement outerHTML.
I replaced this:
// encode the html markup
var OuterHtml = $('<div/>').text(this.outerHTML).html();
With this:
// encode the html markup
var Html = $('<div>').append(this).html();
var OuterHtml = $('<div>').text(Html).html();
Another problem was that Mozilla FireFox doesn’t implement srcElement.
I replaced this:
var Row = e.srcElement.parentNode;
With this:
var Row = e.target.parentNode;
Another problem was the indexing. The browsers have different ways of indexing.
I replaced this:
// this cell has the search pattern
var Cell = Row.childNodes[1];
// put the pattern in the search box and search
$("#TextSearchPattern").val(Cell.innerText);
With this:
// get the correct cell and the text in the cell
// place the text in the seach box and serach
var Cell = $(Row).find("TD:nth-child(2)");
var CellText = Cell.text();
$("#TextSearchPattern").val(CellText);
So much for the myth of browser independence. Was I overly optimistic and gullible? I don’t think so. And when I get my millions from the deposed Nigerian prince I sent money to, you’ll see that having faith is not futile.
Notes:
My goal was to have a single standalone file. I tried to keep the features and CSS to a minimum–adding only enough to make it useful and visually pleasing.
When testing, I often thought there was a problem with the jQuery selector. Invariable it was invalid html code. If your results aren't what you expect, don't assume it's the jQuery selector pattern: The html may be invalid.
To help in development and testing, I added a double-click handler to the rows in the Cheat Sheet table. If you double-click a row, the search pattern is put in the search box, a search is performed and the page is scrolled so you can see the results. I left the test html and code in the page.
If you are using a CDN (non-local) version of the jQuery libraray, the designer in Visual Studio becomes extremely slow. That's why there are two version of the library in the header and one is commented out.
For reference, here is the jQuery documentation on selectors:
http://api.jquery.com/category/selectors/
Here is a much more comprehensive list of CSS selectors (which jQuery uses):
http://www.w3.org/TR/CSS2/selector.html
I hope someone finds this useful.
Steve Wellens
CodeProject
Having a clickable image in a web page is not a big deal. Having an image in a web page with clickable hotspots is a big deal. The powerful GIMP editor has a tool to make creating clickable hotspots much easier.
GIMP stands for GNU Image Manipulation Program. Its home page and download links are here: http://www.gimp.org/ (it is completely free).
Beware: GIMP is an extraordinarily advanced and powerful image editor. If you wish to use it for general image editing tasks, you have a steep learning curve to climb. FYI: I used it to create the shadows you see on the images below. Fortunately, the tool to make Image Maps is separate from the main program.
To start, open an image with GIMP or, drag and drop an image onto the GIMP main window. I'm using the image of a bar graph.
Next, we have to find the Image Map tool and launch it (Filters->Web->Image Map…):

Why is the Image Map tool under Filters and not Tools? I don't know. It's mystery—much like the Loch Ness Monster, the Bermuda Triangle, or why my socks keep disappearing when I do laundry. I swear I've got twenty single unmatched socks. But I digress…
Here is what the Image Map tool looks like:

If we click the blue 'I' button, we can add information to the Image Map:

Now we'll use the rectangle tool to create some clickable hotspots. Select the Blue Rectangle tool, drag a rectangle, click when done and you'll get something like this:

You can also make circle/oval and polygon areas. You can edit all the parameters of an image map area after drawing it.
Rectangle settings (for fine tweaking):

JavaScript functions (it's up to you to write them):

Here is a setup with two rectangles and one polygon area:

When you hit save a map file is generated that looks something like this:
<img src="BarGraphImage.png" width="326" height="306" border="0" usemap="#BarGraphImageMap">
<map name="BarGraphImageMap">
<!-- #$-:Image map file created by GIMP Image Map plug-in -->
<!-- #$-:GIMP Image Map plug-in by Maurits Rijk -->
<!-- #$-:Please do not edit lines starting with "#$" -->
<!-- #$VERSION:2.3 -->
<!-- #$AUTHOR:Steve Wellens -->
<!-- #$DESCRIPTION:A bar graph with no instrinsic value -->
<area shape="rect" coords="213,62,253,269" onmouseover="ImageMapMouseHover('Biggest Bar')" onmouseout="ImageMapMouseHover('')" nohref="nohref"></area>
<area shape="rect" coords="114,131,158,267" href="~/Details2.aspx"></area>
<area shape="poly" coords="57,44,76,100,181,102,183,62,142,34" href="http://www.microsoft.com"></area>
</map>
Paste the contents into a web page and you are almost there. I made some tweaks before it became usable:
- Replaced ' with apostrophes in the javascript functions.
- Changed the image path so it would find the image in my images directory
- Tweaked the href urls.
- Added Title="Some Text" to get tool tips.
- Cleaned out the comments.
Result:
The final markup (with JavaScript function):
<script type="text/javascript" language="javascript">
function ImageMapMouseHover(Msg)
{
$("#Label1").html(Msg);
}
<img src="Images\BarGraphImage.png" width="326" height="306" border="0" usemap="#BarGraphImageMap">
<map name="BarGraphImageMap">
<area shape="rect" coords="213,62,253,269" onmouseover="ImageMapMouseHover('Biggest Bar')" onmouseout="ImageMapMouseHover('')" nohref="nohref"></area>
<area shape="rect" coords="114,131,158,267" href="Details2.aspx" title="Details 2"></area>
<area shape="poly" coords="57,44,76,100,181,102,183,62,142,34" href="http://www.microsoft.com"></area>
</map>
It may seem like a lot of bother but, the tool does the heavy lifting: i.e. the coordinates. Getting the regions positioned and sized is easy using a visual tool…much better than doing it by hand.
This, of course, isn't a full treatise on the tool but it should give you enough information to decide if it's helpful.
I hope someone finds this useful.
Steve Wellens
CodeProject
On the Asp.Net forums where I am a moderator, a developer was having a problem hooking up click events to the rows of a dynamically created html table. He didn't want to embed the onclick handler in the table rows as each row was created so he tried using jQuery. The problem was he was trying to hook up the click event before the table was created. How to help him?
The jQuery live(…) function comes to the rescue!
What can I say about jQuery and the live(…) function? It's like falling in love with a beautiful woman, who is kind, can cook and keeps a tidy house. So you marry her and then you find out that she's heiress to a trust fund worth millions!
The jQuery live(…) function is an esoteric function; in fact, you may never find cause to use it in your entire career. But if you do use it, it can solve some problems very elegantly.
To put it succinctly, instead of this:
$('#MyTable tr').click(function() { alert("Table row clicked"); })
Use this:
$('#MyTable tr').live('click', function() { alert("Table row clicked"); })
The live(…) function causes the event handler to be automatically assigned to elements matching the selector…including elements that haven't been created yet. You heard that correctly. It assigns events to elements that don't exist.
As rows are created and added to the table element in question, they automatically get the event handler assigned.
While working on this I became curious and looked at the source code for the jQuery live(…) function. That was a mistake. A big mistake. There is a quote from Otto von Bismark that goes something like, "…two things you don't want to see made are sausage and legislation." I think we can add the jQuery source code to that list. To be fair, I understand that jquery code runs on millions of browsers daily. Sacrificing some readability and maintainability for performance is perfectly reasonable under these circumstances.
Fortunately, the online documentation provides a good description of how the function works: http://api.jquery.com/live/
Bonus Information: While I was poking around in the jQuery source code (with a safety rope, hard hat and air-sickness bag) I happened across some lines like these:
if ( name === "find" )
if ( arguments.length === 2 )
I'd never seen this before and it's not even mentioned in a book called The JavaScript Bible. It's called the Identity Equal Operator (there is also an Identity Not Equal operator !==). It checks both type and value. In other words, it does not do a type conversion before checking for equality. Here's an illustration of how it works compared to the equality operator:
var x = 3;
// equality
x == 3 is true
x == '3' is true
x == "3" is true
// identity equality
x === 3 is true
x === '3' is false
x === "3" is false
[Edit/Update]
It has been pointed out to me that jQuery 1.4 introduced the delegate(...) function which does the same thing as the live(...) function but inserts the event handler closer to the selected elements rather than at the root of the DOM so it's performance is better. However, another person pointed out if you are attaching events to dozens of elements (say anchors) it's better to have a single handler at the top of the DOM. Here is the best article I found discussing the differences: http://test.kingdesk.com/jquery/bind_live_delegate.php
I hope someone finds this useful.
Steve Wellens.
CodeProject
There was a question from a student over on the Asp.Net forums about improving site performance. The concern was that every time an app setting was read from the Web.Config file, the disk would be accessed. With many app settings and many users, it was believed performance would suffer.
Their intent was to create a class to hold all the settings, instantiate it and fill it from the Web.Config file on startup. Then, all the settings would be in RAM. I knew this was not correct and didn't want to just say so without any corroboration, so I did some searching.
Surprisingly, this is a common misconception. I found other code postings that cached the app settings from Web.Config. Many people even thanked the posters for the code.
In a later post, the student said their text book recommended caching the Web.Config file.
OK, here's the deal. The Web.Config file is already cached. You do not need to re-cache it.
From this article http://msdn.microsoft.com/en-us/library/aa478432.aspx
It is important to realize that the entire <appSettings> section is read, parsed, and cached the first time we retrieve a setting value. From that point forward, all requests for setting values come from an in-memory cache, so access is quite fast and doesn't incur any subsequent overhead for accessing the file or parsing the XML.
The reason the misconception is prevalent may be because it's hard to search for Web.Config and cache without getting a lot of hits on how to setup caching in the Web.Config file.
So here's a string for search engines to index on: "Is the Web.Config file Cached?"
A follow up question was, are the connection strings cached?
Yes. http://msdn.microsoft.com/en-us/library/ms178683.aspx
At run time, ASP.NET uses the Web.Config files to hierarchically compute a unique collection of configuration settings for each incoming URL request. These settings are calculated only once and then cached on the server.
And, as everyone should know, if you modify the Web.Config file, the web application will restart.
I hope this helps people to NOT write code!
Steve Wellens
CodeProject
Humbled yet again…DOH! No matter how much experience you acquire, no matter how smart you may be, no matter how hard you study, it is impossible to keep fully up to date on all the nuances of the technology we are exposed to. There will always be gaps in our knowledge: Little 'dead zones' of uncertainty. For me, this time, it was about passing string parameters to functions. I thought I knew this stuff cold. First, a little review...
Value Types and Ref
Integers and structs are value types (as opposed to reference types). When declared locally, their memory storage is on the stack; not on the heap. When passed to a function, the function gets a copy of the data and works on the copy. If a function needs to change a value type, you need to use the ref keyword. Here's an example:
// ---- declaration -----------------
public struct MyStruct
{ public string StrTag;
}
// ---- functions -----------------------
void SetMyStruct(MyStruct myStruct) // pass by value
{ myStruct.StrTag = "BBB";
}
void SetMyStruct(ref MyStruct myStruct) // pass by ref
{ myStruct.StrTag = "CCC";
}
// ---- Usage -----------------------
protected void Button1_Click(object sender, EventArgs e)
{ MyStruct Data;
Data.StrTag = "AAA";
SetMyStruct(Data);
// Data.StrTag is still "AAA"
SetMyStruct(ref Data);
// Data.StrTag is now "CCC"
}
No surprises here. All value types like ints, floats, datetimes, enums, structs, etc. work the same way.
And now on to...
Class Types and Ref
// ---- Declaration -----------------------------
public class MyClass
{ public string StrTag;
}
// ---- Functions ----------------------------
void SetMyClass(MyClass myClass) // pass by 'value'
{ myClass.StrTag = "BBB";
}
void SetMyClass(ref MyClass myClass) // pass by ref
{ myClass.StrTag = "CCC";
}
// ---- Usage ---------------------------------------
protected void Button2_Click(object sender, EventArgs e)
{ MyClass Data = new MyClass();
Data.StrTag = "AAA";
SetMyClass(Data);
// Data.StrTag is now "BBB"
SetMyClass(ref Data);
// Data.StrTag is now "CCC"
}
No surprises here either. Since Classes are reference types, you do not need the ref keyword to modify an object. What may seem a little strange is that with or without the ref keyword, the results are the same: The compiler knows what to do.
So, why would you need to use the ref keyword when passing an object to a function?
Because then you can change the reference itself…ie you can make it refer to a completely different object. Inside the function you can do: myClass = new MyClass() and the old object will be garbage collected and the new object will be returned to the caller.
That ends the review. Now let's look at passing strings as parameters.
The String Type and Ref
Strings are reference types. So when you pass a String to a function, you do not need the ref keyword to change the string. Right? Wrong. Wrong, wrong, wrong.
When I saw this, I was so surprised that I fell out of my chair. Getting up, I bumped my head on my desk (which really hurt). My bumping the desk caused a large speaker to fall off of a bookshelf and land squarely on my big toe. I was screaming in pain and hopping on one foot when I lost my balance and fell. I struck my head on the side of the desk (once again) and knocked myself out cold. When I woke up, I was in the hospital where due to a database error (thanks Oracle) the doctors had put casts on both my hands. I'm typing this ever so slowly with just my ton..tong ..tongu…tongue.
But I digress. Okay, the only true part of that story is that I was a bit surprised.
Here is what happens passing a String to a function.
// ---- Functions ----------------------------
void SetMyString(String myString) // pass by 'value'
{ myString = "BBB";
}
void SetMyString(ref String myString) // pass by ref
{ myString = "CCC";
}
// ---- Usage ---------------------------------
protected void Button3_Click(object sender, EventArgs e)
{ String MyString = "AAA";
SetMyString(MyString);
// MyString is still "AAA" What!!!!
SetMyString(ref MyString);
// MyString is now "CCC"
}
What the heck. We should not have to use the ref keyword when passing a String because Strings are reference types. Why didn't the string change? What is going on?
I spent hours unssuccessfully researching this anomaly until finally, I had a
Eureka moment:
This code:
String MyString = "AAA";
Is semantically equivalent to this code (note this code doesn't actually compile):
String MyString = new String();
MyString = "AAA";
Key Point: In the function, the copy of the reference is pointed to a new object and THAT object is modified. The original reference and what it points to is unchanged.
You can simulate this behavior by modifying the class example code to look like this:
void SetMyClass(MyClass myClass) // call by 'value'
{ //myClass.StrTag = "BBB";
myClass = new MyClass();
myClass.StrTag = "BBB";
}
Now when you call the SetMyClass function without using ref, the parameter is unchanged...just like the string example.
I hope someone finds this useful.
Steve Wellens
CodeProject
This question popped up on the Asp.Net forums where I moderate:
"How do I find an HTML element on a Master Page, from a child page, using jQuery?"
I licked my chops. I like questions like this because when I don't know the answer, it gives me an excuse to explore and learn.
The problem is that element ids on Master Pages get mangled, or decorated, to prevent duplicate ids on the final rendered HTML.
For instance a textbox with an id like this: MasterPageTextBox
Ends up with an id like this: ctl00$MasterPageTextBox
Solution 1:
We could hard code the mangled id into the jQuery search criteria and it would work. But what a maintenance nightmare, in the future, the mangled id might change: Not acceptable. When people pay you money to write code, you should write good code.
Solution 2:
If you are using Asp.Net 4, you have control over the generated ids and can make them predictable. Then you can hard code the generated id into the CSS selector. However, that isn't the case for most sites at this time.
Solution 3:
After Googling and Binging around a bit, I came up with this approach to use in the Master Page:
protected void Page_Load(object sender, EventArgs e)
{ Page.ClientScript.RegisterHiddenField("HiddenFieldClientID", this.MasterPageTextBox.ClientID); }
The code above takes the generated ClientID and puts it in a HiddenField that gets sent to the browser. The jQuery code in the child page can then get the value in the HiddenField and use it to search for the element. I thought this was pretty cool but…the jQuery code wouldn't compile because the HiddenField wasn't on its page. So an empty HiddenField control has to be placed on the page. It's messy but it works! Here is how the jQuery on the child page accesses the hidden field and then accesses the textbox on the Master Page:
// ---- SetMasterPageTextBox ---------------------------
// write hello in a textbox field on the master page
function SetMasterPageTextBox()
{ // Get the hidden field
var HidField = $("#HiddenFieldClientID"); if (HidField.length == 1)
{ // get the contents of the hidden field
var ClientID = HidField[0].value;
// use it as the ID of the TextBox control
$("#" + ClientID).val("Hello"); }
}
I went to post my 'brilliant' answer, but in the meantime another forum member posted an answer which was far superior to mine.
Frank Hong suggested wrapping the element with a span tag.
Solution 4:
Two things make this next solution work.
- Span tag ID's are NOT mangled or decorated.
- CSS selectors are cool, really cool…quick review:
|
div, p |
The comma (,) operator means AND. All divs and paragraphs on the page will be selected. |
|
div > p |
The greater than (>) operator means direct parent of. Any paragraphs directly inside of any divs are selected |
|
div p |
The space ( ) operator means ancestor of. Any paragraphs inside a div are selected, even if they are inside of other elements within the div. |
In the Master Page wrap the textbox with a span element:
<%-- Span is to allow child page to jQuery select textbox--%>
<span id="SpanMyTextBox">
<asp:TextBox ID="MyTextBox" runat="server"></asp:TextBox>
</span>
Here's what it looks like rendered, note the TextBox id got mangled but the span id remains unscathed:
<span id="SpanMyTextBox">
<input name="ctl00$MyTextBox" type="text" id="ctl00_MyTextBox" />
</span>
In the Child Page we can use the greater than or the space operator. The greater than operator is more explicit as to our intent. We use 'input' because textboxes render as HTML input elements.
So the CSS selector is: #SpanMyTextBox > input
// ---- SetMasterPageTextBox ---------------------------
// write hello in a textbox field on the master page
function SetMasterPageTextBox()
{ //Textbox is wrapped in span element
$("#SpanMyTextBox > input").val("Hello"); }
Now, isn't that better? Of course, it's up to the developer to ensure duplicate span ids are not used.
[Update:]
Solution 5: (from the comments)
You can also use a wild card CSS selector.
input[id$=MyTextBox]
The above line matches all HTML input elements with an id attribute that ends with "MyTextBox".
It will match:
<asp:TextBox ID="ctl00$MyTextBox" runat="server"...
<asp:TextBox ID="LaLaLaMyTextBox" runat="server"...
<asp:TextBox ID="abc123MyTextBox" runat="server"...
I hope someone finds this useful.
Steve Wellens
CodeProject
Like most developers, I love finding tools that do my work for me and make me look good. And, like most developers, I am extremely wary of adding too much outside crap to a project which can make maintaining it a nightmare. You may end up not only maintaining your own code but someone else's code, or worse, not being able to update the project because a third-party control won't let you.
The Ajax Toolkit has some great stuff that is very easy to use. It's from Microsoft so you can be pretty comfortable adding it to a project. Drag and Drop and off you go. But often things don't work out exactly as you would like. Deploying and debugging are not always easy.
A viable alternative to the Ajax Toolkit is the jQuery UI.
I was happy to see on the jQuery web site they have their own UI controls…very happy. If you are already using jQuery, you don't feel as if you are adding a third party component. And, it seems, Microsoft has 'adopted' jQuery.
Here's their website: http://jqueryui.com/. It's also reachable from http://jquery.com/
I decided to try out the DatePicker control, since picking a date is one of the most useful and common tasks a control can do.
Downloading and installing the jQuery UI was no more difficult than downloading and installing jQuery itself. The download is customizable; you pick which components you want and which visual theme you want.
In the download you get:
- A CSS file and images
- Minimized versions of the jQuery UI and jQuery code
-
"Development bundle"
- Documentation
- Demos
- Separate code files
- Misc.
I added the CSS file, image directory and jQuery code file to my project. I already had the jQuery library. When you drag and drop the files onto the page, you get entries like these:
<script src="Scripts/jquery-1.4.2.min.js" type="text/javascript"></script>
<script src="Scripts/jquery-ui-1.8.4.custom.min.js" type="text/javascript"></script>
<link type="text/css" href="css/smoothness/jquery-ui-1.8.4.custom.css" rel="stylesheet" />
Note: Other versions of the source code are available: non-minimized and documented versions.
Now, let's create a TextBox and hookup the DatePicker control to it:
<script type="text/javascript" language="javascript">
$(document).ready(DocReady);
function DocReady()
{ $('#DatePicker_TextBox').datepicker(); }
<asp:TextBox ID="DatePicker_TextBox" runat="server" ></asp:TextBox>
Note: jQuery code is usually so ugly its own mother would slap it. I strive for legibility and maintainability by NOT nesting and chaining functions and using a more 'traditional' C# style of coding.
Here's what happens when you click on, or tab into, the text box:

Dang, that wasn't hard, it works well and looks pretty. When you select a date, it fills in the textbox:

You can edit the text in the box by hand and the DatePicker control reads it. If the text isn't a valid date, the DatePicker control ignores it. Nice. It has a good solid feel. I know engineers shouldn't talk like that but…it has a good solid feel.
Let's change the date format. Sadly, the date formatting codes are different than the .Net DateTime formatting codes (more on this later). I added a few more options just for fun. For numberOfMonths, you supply a two dimensional array: 3 by 4 would show an entire year.
$(document).ready(DocReady);
function DocReady()
{ var DatePicker = $('#DatePicker_TextBox').datepicker();
DatePicker.datepicker('option', { dateFormat: 'DD, d MM, yy',
numberOfMonths: [1, 2],
showWeek: 'true'
});
}
Why didn't I just chain the formatting code to the creation code? Why did I create a separate variable?
Debugging: If something goes wrong, I can tell if the problem is in the creation of the DatePicker or in the formatting of the DatePicker. Until you have to debug code, you don't know how valuable and useful this is. The local variable avoids a duplicate search operation.
Why the weird code formatting when setting the options?
I tried to make it as readable as possible. When there is more than one option, it is easier to read if each option is on a separate line. It's also easier to tell when the braces and parenthesis match up.
Here's what it looks like with the options set:

Note: In the above image you can see a bug: The fifth day of both months is selected. I checked the website and it was already reported here: http://dev.jqueryui.com/ticket/5984. The posted workaround corrected the problem.
It's pretty cool. But, the textbox is going to be sent back to the server and will need to be converted to a DateTime object. As mentioned earlier: .NET and jQuery use different formatting codes.
So the code to convert the string to a DateTime is:
String DateText = DatePicker_TextBox.Text;
DateTime TheDate;
// jquery format: DD, d MM, yy
// .Net format: dddd, d MMMM, yyyy
// Sample: Friday, 3 September, 2010
if (DateTime.TryParseExact(DateText,
"dddd, d MMMM, yyyy",
null,
DateTimeStyles.None,
out TheDate) == false)
{ TheDate = DateTime.Now.Date; // default value on error
}
In a real application, you'd want to centralize the format strings in one place so they are easy to maintain (by using constants or utility functions).
Once you start playing with and using the jQuery UI components, you'll be hooked.
By the way, I still use and appreciate the Ajax UpdatePanel in the Ajax Extensions toolbox. Although some treat it disdainfully, what you get, for what you pay, is a great bargain.
I hope someone finds this useful.
Steve Wellens.
CodeProject
More Posts
« Previous page -
Next page »