Panel's DefaultButton whims: not every IButtonControl is the same...
The creative director said: "Hey, I'd like them to be rendered as html anchors!". The poor developer replied saying: "I can't see any difference, what about leaving them as they are (html input buttons)?". And the other: "Well, we can apply CSS styles better to html anchors than to html input buttons!".
So, the poor developer started reflecting his creative director desires.
After some hours spent in playing nicely with the new html anchor based buttons, something hurt the poor developer heart: all the Panels which uses the DefaultButton property in the web application and previously worked well now started behaving in a strange manner. To his amazement, the poor developer discovered that all of the DefaultButtons now worked only in Internet Explorer. Oh my... What about that cross browser thing?
Let's help that poor developer.
Whenever you use the DefaultButton property of the Panel control, you can choose among a set of ready to use controls which could act as buttons, all of them implementing the IButtonControl interface. At runtime, the Panel control registers a client script which would fire that default button, upon the user has hitted the enter key inside one of the html element hosted inside that Panel.
The client function which handles the keypress event for the Panel client element is WebForm_FireDefaultButton. Here's its body:
var __defaultFired = false;
function WebForm_FireDefaultButton(event, target) {
if (!__defaultFired && event.keyCode == 13 && !(event.srcElement && (event.srcElement.tagName.toLowerCase() == "textarea"))) {
var defaultButton;
if (__nonMSDOMBrowser) {
defaultButton = document.getElementById(target);
}
else {
defaultButton = document.all[target];
}
if (defaultButton && typeof(defaultButton.click) != "undefined") {
__defaultFired = true;
defaultButton.click();
event.cancelBubble = true;
if (event.stopPropagation) event.stopPropagation();
return false;
}
}
return true;
}
As you could see, it checks (among other things) if the default button "click" property is defined before getting the work done. Unluckily, and this is the culprit of our poor developer pain, the "click" property is not supported by every IButtonControl rendered html element. In fact, html anchors seem to not support that property (yes, IE does support it, but we wanted it to be cross browser, do you remember?).
So, how could we solve this problem and make DefaultProperty works with... say... FireFox? One way could be to redefine WebForm_FireDefaultButton and make it smarter than the original one; we could check for the "click" property first and then for the "href" property, which html anchors have.
So, here's a little smarter reimplementation of the aforementioned client function, ready to be pasted in your web page or client script file:
function WebForm_FireDefaultButton(event, target) {
if (!__defaultFired && event.keyCode == 13 && !(event.srcElement && (event.srcElement.tagName.toLowerCase() == "textarea"))) {
var defaultButton;
if (__nonMSDOMBrowser)
defaultButton = document.getElementById(target);
else
defaultButton = document.all[target];
if (typeof(defaultButton.click) != "undefined") {
__defaultFired = true;
defaultButton.click();
event.cancelBubble = true;
if (event.stopPropagation) event.stopPropagation();
return false;
}
if (typeof(defaultButton.href) != "undefined") {
__defaultFired = true;
eval(defaultButton.href.substr(11));
event.cancelBubble = true;
if (event.stopPropagation) event.stopPropagation();
return false;
}
}
return true;
}
As all of the postback event references begin with the "javascript :" fake protocol, we could get the href of the DefaultButton, strip that protocol prefix and evaluate the rest. That will perform our craved postback, in a cross browser way.
And our poor developer is finally happy. Now guess who was that poor developer... :)