I\'ve got a web form with a start date field. I\'ve tied a jquery datepicker to the txt field. Now when I choose a date in FF, the selected date is populated in the text box
The fix...
onSelect: function() {}
..does not appear to work if the problem is with a CustomValidator that relies on a servewr side event handler to validate input.
There are a couple of other fixes mentioned here...
http://dev.jqueryui.com/ticket/4071
The problem is down to IE's event handling differing from other browsers and the client side validation code supplied by ASP Net not reacting gracefully to a situation not contemplated by it's authors.
change jquery.ui.datepicker.js line 1504
'" href="#" >' + printDate.getDate() + '</a>')
with
'" href="javascript:DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);" >' + printDate.getDate() + '</a>')
test works OK!
It seems to be a bug of sorts, but adding this line in the datepicker declaration should solve it:
onSelect: function() {}
The solutions provided above only prevents the error from occurring.
On the datepicker:
onSelect : function(dateText, inst){ inst.input.trigger('cValidate')
and bind the event to the calendar input element.
.bind('cValidate', function (event) { window.ValidatorOnChange(event); });
this will fire the validatorchanged event with the correct event args (input field).
This is an endemic problem with jQuery datepickers and ASP validation controls. As you are saying, the wrong element cross-triggers an ASP NET javascript validation routine, and then the M$ code throws an error because the triggering element in the routine is undefined.
I solved this one differently from anyone else I have seen - by deciding that M$ should have written their code more robustly, and hence redeclaring some of the M$ validator code to cope with the undefined element. Everything else I have seen is essentially a workaround on the jQuery side, and cuts possible functionality out (eg. using the click event instead of change).
The bit that fails is
for (i = 0; i < vals.length; i++) {
ValidatorValidate(vals[i], null, event);
}
which throws an error when it tries to get a length for the undefined 'vals'.
I just added
if (vals) {
for (i = 0; i < vals.length; i++) {
ValidatorValidate(vals[i], null, event);
}
}
and she's good to go. Final code, which redeclares the entire offending function, is below. I put it as a script include at the bottom of my master page or page (so it occurs after the default declarations and replaces the earlier version).
Yes, this does break upwards compatibility if M$ decide to change their validator code in the future. But one would hope they'll fix it and then we can get rid of this patch altogether.
// Fix issue with datepicker and ASPNET validators: redeclare MS validator code with fix
function ValidatorOnChange(event) {
if (!event) {
event = window.event;
}
Page_InvalidControlToBeFocused = null;
var targetedControl;
if ((typeof (event.srcElement) != "undefined") && (event.srcElement != null)) {
targetedControl = event.srcElement;
}
else {
targetedControl = event.target;
}
var vals;
if (typeof (targetedControl.Validators) != "undefined") {
vals = targetedControl.Validators;
}
else {
if (targetedControl.tagName.toLowerCase() == "label") {
targetedControl = document.getElementById(targetedControl.htmlFor);
vals = targetedControl.Validators;
}
}
var i;
if (vals) {
for (i = 0; i < vals.length; i++) {
ValidatorValidate(vals[i], null, event);
}
}
ValidatorUpdateIsValid();
}
The root bug (I think it's probably meant to be a feature, or maybe a workaround for a known IE bug?) is in ASP.Net's ValidatorHookupEvent
:
var func;
if (navigator.appName.toLowerCase().indexOf('explorer') > -1) {
func = new Function(functionPrefix + " " + ev);
}
else {
func = new Function("event", functionPrefix + " " + ev);
}
As a result, in the default case that there's no other onchange
registered, this sets up the onchange
for the input to be the equivalent of
function() { ValidatorOnChange(event); }
in IE and
function(event) { ValidatorOnChange(event); }
in other browsers. So iff you're using IE, the event passed to ValidatorOnChange
will be window.event
(since window
is the global object).
If you don't want to hack around with the ASP.Net scripts then I think the nicest way to handle this is to detect the broken event handler and replace it. As with other suggestions here, I offer an onSelect
to include in the datepicker
options.
onSelect: function(dateStr, datePicker) {
// http://stackoverflow.com/questions/1704398
if (datePicker.input[0].onchange.toString().match(/^[^(]+\(\)\s*{\s*ValidatorOnChange\(event\);\s*}\s*$/)) {
datePicker.input[0].onchange = ValidatorOnChange;
}
datePicker.input.trigger("change");
}
I'm applying this globally with
$.datepicker.setDefaults({
onSelect: function(dateStr, datePicker) {
etc.
}
});