I wanted to figure out a way to have a single calendarExtender per page that I could use on any Date Field whether it be a startDate and an endDate or some customer date records in a repeater. Basically I didn't want to have a million CalendarExtenders on the page, so I decided to set out on an adventure and conquer the unknown!!...Well, 4 days later and with less hair on my head I have figured out a really simple way to use a single ( only one ) calendarExtender per page for many different Date Fields. The best part is that there is no need to modify the Ajax Control Toolkit framework!
I have provided a simple example of only 1 startDate and 1 endDate, but really you could have as many startDates and endDates as you desire. Please contact me if you have any questions or problems implementing it.
Enjoy,
Greg Benoit (Benwah)
--
GregBenoit.com
PrecisionSoftware.Net
StaffKeeper.com
<html xmlns="http://www.w3.org/1999/xhtml" ><head runat="server"> <title> A single CalendarExtender for multiple date fields </title> <script type="text/javascript"> /* Author: Greg Benoit (Benwah) Last Modified: 3/16/2007 This is an example of using a single CalendarExtender DatePicker is MS Ajax for an unlimited number of date field text boxes. This is a simple example, but could easily be extended into a more robust solution of having a single CalendarExtedner within a repeater. */ function pageLoad() { // the ensureCalendar must be called in the pageLoad to hookup the PopupBehavior $find('popupCalBhvr')._ensureCalendar(); } /* Given an element (el) and an event (ev) this method fires a javascript function attached to the element...such as onclick, onfocus, onchange etc... */ function FireEvent(el, ev) { if (document.createEventObject) { el.fireEvent(ev); } else if (document.createEvent) { var localE = document.createEvent("HTMLEvents"); localE.initEvent(ev.substring(2, ev.length), true, true); el.dispatchEvent(localE); } } /* Takes the Date value in the txtHidden field and sees if it is different from the one already in the parentElement. If they are different, then change the value of the parentElement to reflect the new date and fire the onchange event of the parent. */ function UpdateClientDate(cal) { var parentDateElement = $find('popupCalBhvr')._popupBehavior.get_parentElement(); var hiddenTxtBox = $get('txtHidden'); // the ID could be ctl00_txtHidden if you're using master pages if(parentDateElement.value != hiddenTxtBox.value) { parentDateElement.value = hiddenTxtBox.value; FireEvent(parentDateElement, 'onchange'); } } /* */ function ShowPopupCalendar(calPopupTarget) { $find('popupCalBhvr').hide(); // hide the calendar if it already showing // set the parentElement of the CalendarPopup behavior...this is what the calendar will popup under. $find('popupCalBhvr')._popupBehavior.set_parentElement(calPopupTarget); var hiddenTxtBox = $get('txtHidden'); // the ID could be ctl00_txtHidden if you're using master pages var theDate = new Date(calPopupTarget.value); // figure out what date is selected...default is today if(isNaN(theDate)) { // Set the currently selected date to today's date b/c no date exists // in the parentElement right now. $find('popupCalBhvr').set_selectedDate(new Date()); hiddenTxtBox.value = ''; } else { // Set the currently selected date to that date that already exists in the // parentElement. $find('popupCalBhvr').set_selectedDate(theDate); hiddenTxtBox.value = calPopupTarget.value; } // fire the onfocus event of the hiddentTextBox to make the Calendar popup. FireEvent(hiddenTxtBox, 'onfocus'); } /* Both of these function are just functions I made up to show how to handle the selection of a new date...The functions would typically have some sort of key passed into them so you know what record to update in the DB. */ function UpdateStartDate(txtStartDate) { alert('Here you would send the new start date ('+txtStartDate.value+') to the server via WebService'); } function UpdateEndDate(txtEndDate) { alert('Here you would send the new end date ('+txtEndDate.value+') to the server via WebService'); } /* HTML Notes: Notice the txtStartDate and txtEndDate values can either be set to a date or be blank */ </script></head><body> <form id="form1" runat="server"> <ajax:ScriptManager ID="ScriptManager1" runat="server"> </ajax:ScriptManager> <table> <tr> <td> Start Date: </td> <td> End Date: </td> </tr> <tr> <td> <input id="txtStartDate" value="3/1/2007" onclick="ShowPopupCalendar(this);" readonly="readonly" onchange="UpdateStartDate(this);" type="text" /> </td> <td> <input id="txtEndDate" value="" onclick="ShowPopupCalendar(this);" readonly="readonly" onchange="UpdateEndDate(this);" type="text" /> </td> </tr> </table> <asp:TextBox ID="txtHidden" style="z-index: 1001; position: absolute;" Width="0px" Height="0px" runat="server" BackColor="White" BorderColor="White" BorderStyle="None" BorderWidth="0px" ForeColor="White"></asp:TextBox> <ajaxToolkit:CalendarExtender ID="calPopup" runat="server" BehaviorID="popupCalBhvr" TargetControlID="txtHidden" OnClientDateSelectionChanged="UpdateClientDate" Format="MM/dd/yyyy"> </ajaxToolkit:CalendarExtender> </form></body></html>
One more thing...Remember you can style the CalendarExtender anyway you desire using the css classes of the Calendar found herehttp://community.bennettadelson.com/blogs/rbuckton/archive/2007/02/02/Skinning-model-for-Calendar-and-Tabs-in-Ajax-Control-Toolkit.aspx
Hot Tip man, thanks for sharing it with us :?)
I'm making a slight alteration to allow for the calendar to be aligned specifiacally for a control as i have some date fields at the top of the page and some at the bottom and sometimes i want eh calendar postioned over the top of the control as opposed to the bottom
I really do like this solution though man
cheers
Tim
The only problem i'm having is setting the date correctly on subsequent calls
I'm in the UK and we use the dd/MM/yyyy format on the CalendarExtender. All is well until I go to repopulate the date. JavaScript uses MM/dd/yyyy and suddently 04/10/2007 from the hiddenbox becomes 10/04/2007 and i get the SelectedDate as October 4th 2007
I'm wondering if we could do something clever by determining the Format property of the calendar and moving the parts around to suit
just a thought
Just in case anyone's interested, here is the code to covnert the date back to a JavaScript date is you are using a special dateformat, as opposed to mm/dd/yyyy
theDate = GetFormattedDate(calPopupTarget.value,$find('popupCalBhvr')._format);
should be used to collect the date, and this function is used to convert it across
function GetFormattedDate(dateString,dateFormat){ //need to split the years, months and days according to the specified string var theSecond = ""; var theMinute = ""; var theHour = ""; var theDay = ""; var theMonth = ""; var theYear = ""; for(var i = 0; i < dateFormat.length ; i++) { switch(dateFormat.charAt(i)) { case "M": theMonth += dateString.charAt(i); break; case "y": theYear += dateString.charAt(i); break; case "d": theDay += dateString.charAt(i); break; } } var theReturnedDate = new Date(); theReturnedDate.setFullYear(parseInt(theYear), parseInt(theMonth) - 1, parseInt(theDay)); return theReturnedDate; }
This looks great...I am glad it is working for you and let me know if you come up with anymore fixes/updates!
Thanks for the input,
Greg
Well, i had a minor issue i just had to fix.
I couldn't get the pageLoad() method to fire on pageload but it didn't make any difference previously as the _popupBehavior object was set up by the time i called the method which hooked it all up. "No biggie" i thought and carried on anyway
However, i just upgraded to the latest AjaxToolkit and i was getting the error that "_popupBehavior is null or not an object". I still can't get the pageLoad thing to work without hooking it up via PageRequestManager.add_pageLoaded(), and even then the behavior object isn't initialised so it was kinda useless for me. I now have the _ensureCalendar() call on my ShowPopup() method but i'm not convinced this is the right place since it fires every time, not just on pageLoad
How did you get the pageLoad() method to fire your end Greg?
and now i'm convinced something has changed with this release
I'd actually used that pageLoad() method in another section which i use to populate a textbox with data from the server via a JavaScript but this is no longer firing on pageLoad() :?(
good article thanks.
I've got this is working great as long as the page does not have any vertical scrolling.
However, I'd like to use multiple CalendarExtenders going down a page that may have some scrolling.
In Firefox, If the page has vertical scrolling and a Date is clicked on the CalendarExtender, the page scrolls down to the bottom of the page, and the calendar click event doesn't seem to trigger.
In IE, it appears to operate normally.
I've created an example using the exact code provided, just duplicated so that enough instances occurr to cause the page to scroll.
Please let me know if there is a fix to this! Thanks!
Here is my example:http://test.dev.isoc.net/CalendarExtenderTest/
-John Berman
John,
I'm glad to see you're using the code... I know of this issue and it is because the hidden Text box is at the top of the page and when it gets the focus, the page automatically tries to scroll it into view. There are some work arounds, but I wanted to let you know that the link you provided above is not working...
-Greg
The link should be working now. If you know of a work around or can point me in the right direction I'd really appreciate it!
Hey,
I talked with a few friends of mine over at Microsoft (Ted Glaza and Scott Guthrie) and they advised me to submit a Bug on the CodePlex site. Please vote for our issue at the following link:
http://www.codeplex.com/AtlasControlToolkit/WorkItem/View.aspx?WorkItemId=12206
Also please keep that test site up there showing the problem b/c I included the link to it in my description.
Thanks,Greg
--
GregBenoit.com
PrecisionSoftware.Net
QGenda.com
StaffKeeper.com
Hey,
Can you provide the code for placing the calender extender above the control.
I was searching on google and came to this blog but unfortunatly no solution is attached to it...
I spent a ton of time trying to track down the cause to the calendarplacement when the page has vertical scrolling. I even went as far aswriting a fix javascript function for the onShown event that called thepopupBehavior.set_y() function and passed in the value ofdocument.body.scrollTop. But then i went back to the examples andcould not understand why the examples worked but my page was notworking. After a considerabe amount of time of modifying and tweakingthe example page i found the cause for the placement issue ...
if you add
<!DOCTYPE>
tothe top of your page before the html tag then the vertical scroll is nolonger an issue for the calendar placement. I'm not sure why ...couldnt find anything that would explain it in the source but addingthat resolved my issue.
0 件のコメント:
コメントを投稿