When I first built WriteTrack for National Novel Writing Month, I took a slight short-cut with the calendar. Since I knew NaNoWriMo was a single month, I hid the Next, Previous, and Today buttons (I also hid the Daily and Weekly buttons, since those views don't make sense for the tool). And I forced the calendar to always show November by setting the source of P1_CALENDAR_DATE to be the start date of the challenge. When I opened the tool up to let the users define their own challenge dates, these shortcuts needed to be addressed.
First, I had to turn the previous and next buttons back on. But I still don't want users wandering “off challenge” and trying to put in weights or word counts for random dates, nor do I want them getting lost in the calendar, so I only wanted to display the next button if the challenge extends beyond the end of the currently displayed month. Same idea for the previous button, going the other way. Unfortunately, the standard APEX calendar doesn't know how to do any of that, and doesn't seem to have any functionality exposed for conditionally showing and hiding the buttons. Adding to the difficulty, the Next and Previous buttons don't refresh the page (which would allow for conditions directly on the buttons), but rather issue JQuery commands to the calendar region. I needed something dynamic to make the buttons behave.
Yep, I needed Dynamic Actions (go figure). I created two DA's, one for the Previous button and one for the Next button. The condition for the Previous button's DA was simple–if the start date is less than P1_CALENDAR_DATE, which seems to always be the start date of the currently displayed month–but the Next button was harder, since any end date within the month is still greater than P1_CALENDAR_DATE. There may be a more elegant solution, but I eventually just created a new page item to hold the first day of the month that contains the end date:
select to_char(trunc(end_date,'MM'),'YYYYMMDD') from challenges where...
I could easily compare this to P1_CALENDAR_DATE to determine whether or not to display the Next button.
Grabbing hold of the buttons themselves was also awkward, as they aren't page items. The quick and dirty solution I ended up with was to use jQuery Selectors: button[value=”< Previous"] and button[value="Next >“]. If I ever change the labels on my buttons, this will break. It'd probably be better to add a custom attribute to the buttons and use that to grab them, but, well…
As for setting the value of P1_CALENDAR_DATE: because of the way WriteTrack lets users edit dates (modal pop-up, triggering a page refresh on save), I needed to change how P1_CALENDAR_DATE was set. What I ended up with is the following SQL for the source:
select to_char(decode(sign(sysdate - start_date),-1,start_date, decode(sign(sysdate - end_date),1, end_date, sysdate)),'YYYYMMDD') cal_date from challenges where challenge_id = :P0_CHALLENGE_ID
This isn't as complex as it looks, and allows the user to stay on the current month while doing edits, while getting as close to today as possible when they change challenges.