SharePoint's version of the DateTimePicker |
Everytime a client loads the page, the server generates its own ID for the Hour and Minute elements.
HTML for the Hour dropdown |
HTML for the Minute dropdown |
As you can see in the screenshots above, ASP.NET mauled the client-side IDs with "ct100........."
Google searching yielded one possible solution: <%=#YourControlID.ClientID%>. I tried this and got "An error occurred during the processing of Page.aspx. Code blocks are not allowed in this file." This error meant that my SharePoint environment was configured to stop any server-side code from being executed on the client-side. Asking my SharePoint administrator to relax the security settings would be pretty stupid so it was not an option.
After five additional hours of futile Google searching, I got lucky and found this post on Marc Anderson's blog. Although it was not a direct solution, it was something I could work with. I modified the function to return the control's client-side generated ID and used it with jQuery to gain a handle on the Hour and Minute fields.
$(document).ready(function() {
// Get the control IDs of the DateTimePicker dropdowns
var startHourID = getTimeID('ff3_1', 'DateTimeFieldDateHours');
var startMinuteID = getTimeID('ff3_1', 'DateTimeFieldDateMinutes');
// Get the hour and minute value from their IDs using jQuery
var startHour = $("[id='" + startHourID + "'] :selected").text();
var startMinute = $("[id='" + startMinuteID + "'] :selected").text();
// Display the hours and minutes
alert("Hour: " + startHour);
alert("Minute: " + startMinute);
});
/** Get the client-side ID of the Hours or Minutes control in the DateTimePicker field.
* @param fieldID The control's ID before being mauled client-side
* @param fieldType Use DateTimeFieldDateHours or DateTimeFieldDateMinutes
* @return The client-side ID
*/
function getTimeID(fieldID, fieldType) {
// Get all dropdown elements in the page
var tags = document.getElementsByTagName('select');
var controlID;
for (var i = 0; i < tags.length; i++) {
// alert(' tags[' + i + '].id=' + tags[i].id);
// Find the element with the matching fieldID and fieldType
if (tags[i].id.indexOf(fieldID) > 0 && tags[i].id.indexOf(fieldType) > 0) {
controlID = tags[i].id;
}
}
return controlID;
}
To get the control's client-side generated ID, simply call getTimeID with the appropriate parameters. The caveat here is that fieldID and fieldType must always be present in the generated ID ctl00_PlaceHolderMain_g_dcc91698_d7a9_43a3_baf2_91d2ae764f94_ff3_1_ctl00_ctl00_DateTimeField_DateTimeFieldDateHours. This function will not work if a completely random ID is generated each time the page is loaded because there will be nothing static for you to latch onto.
To test whether I hooked on correctly to the Hour and Minute fields, I alerted their values.
To test whether I hooked on correctly to the Hour and Minute fields, I alerted their values.
I hope this saves many people hours of anguish. Happy coding!