YUI Calendar: Using and modifying multiple calendar picker instances on single page

In this third installment of how to create and modify existing widgets from YUI Javascript library, I will explain how to create multiple instances of calendar widget of YUI2. There are many examples of how to use Calendar widget on YUI’s official website but for my application, the requirement was to to schedule multiple actions on the same page, giving each one a date of its own, so I developed my calendar widget with the example found here.  As a matter of fact if you really want to include multiple elements of a same type on a HTML page, you assign them different ids so that they can be accessed and called appropriately (just like you do with your babies).

You can see in the example I have built on, we are using here the power of Dialog container of YUI, we are using its button and context features to support our pop-up calendar.

It’s best that you first see my example code working and then I will explain the code.

View Multiple YUI Calendar Example in New Window

If you see the source code of example, you will see what I have really done is that, I have passed a unique ID for each calendar instance through declaring

<script type="text/javascript">
calendar(1);calendar(2);
</script>

Then I enclosed all of the code in a function, which accepts the calendar ID and each variable which declares the calendar, gets embedded with this calendarID so that whenever a user uses any instance of the calendar, my widget knows about which calendar we are talking about and the calendar instance needs to update which fields. The same id is needed to be embedded in HTML fields which we are updating through (of-course using powerful features of DOM manipulation given by YUI)

Dom.get("month-field"+calendarID).value = month;
Dom.get("day-field"+calendarID).value = day;
Dom.get("year-field"+calendarID).value = year;

and at the end we really need to ensure that our HTML bits have those IDs

<span id="datefields1">
 <label for="year-field">Year:</label>
 <input id="year-field1" type="text" name="year" value="" style="width: 3em;">
 <label for="month-field">Month:</label>
 <input id="month-field1" type="text" name="month" value=""style="width: 2em;">
 <label for="day-field">Day:</label>
 <input id="day-field1" type="text" name="day" value=""style="width: 2em;">
 </span>

Note the input id parameter, which is year-field1, month-field1 and day-field1, you can create as many calendars as you want, if you have specified the input ids and declared calendars with those ids.

There is one other bit which I have manipulated is the default behaviour of calendar when it updates a field, I was required to have date stamps in the format of YYYY:MM:DD while the calendar would update the fields in the format of YYYY-M-D format, for this functionality there may be some call given by YUI Calendar widget itself because I have seen several type of formats floating around in examples section but for me it was really quick to modify my function to include preceding zeros (if there are none) to month and day before I populate the the DOM elements:

//This modification is done to cater calendar out from yui to
//give always the leading zeros for months and days, in case they
//dont have
 var month = ''+aDate[1]+''; //convert month into a string
 var day = ''+aDate[2]+'';    //converty day into a string
 var year = ''+aDate[0]+'';    //converty year into a string 

//embed the preceding 0 if month is of 1 digit
 if (1 === month.length) {month = '0' + month;} 

//emebed the preceding 0 if day is of 1 digit
if (1 === day.length) {day = '0' + day;}

Other than these you will see how this function is subscribing certain events. One important event is to hide the pop-up calendar when a user presses ‘Esc’ key

// Pressing the Esc key will hide the Calendar Menu and send focus back to
 // its parent Button
 Event.on(window["oCalendarMenu"+calendarID].element, "keydown", function (p_oEvent) {
 if (Event.getCharCode(p_oEvent) === 27) {
 window["oCalendarMenu"+calendarID].hide();
 this.focus();
 }
 }, null, this);

For the calendar I am using default button provided by YUI CSS, you can change it by declaring your own calendarpicker button style in CSS like:

#calendarpicker button {
 background: url(../../images/calendar_icon.gif) center center no-repeat;
 text-align: left;
 text-indent: -10em;
 overflow: hidden;
 *margin-left: 10em; /* For IE */
 *padding: 0 2em;    /* For IE */
 white-space: nowrap;
 }

change the background URL to your own image.

Feel free to comment if you have any better ideas to make this example more robust.

Leave a comment ?

12 Comments.

  1. This is really helpful….

    Is there a way in which multiple calendars on one page of each date field of a record displayed from a looped recordset depending on how many records there are in a given recordset?

    Perhaps by adjusting the Javascript to generate a uniquely identified calendar instance for record in the recordset output until the loop count =’s the row count of the recordset ?

  2. Yes you are right, make the calendar HTML a function too, note the span ids and input ids and 1 or 2 or anything at the end should relate to the calendar id, for example if you create your function to be called createCalendar and maybe if you are working in PHP then

    $i = 0;
    foreach($recordset as $record){
    //add the script function to call javascript function calendar($i) 
    createCalendar($i); //then call the PHP function 
    $i++;
    }
    

    createCalendar then should embed the value of $i at the end of input and span fields. I havn’t tested the code, just to give you an idea.

    Thanks,

  3. Thank you for confirmation that it is at least possible.

    I have tried this approach but am unable to get the desired result, could you help ?

    <span id="” class=”fromdate”>
    Year:<input id="” type=”text” name=”year” value=”” style=”width: 3em;”>
    Month:<input id="” type=”text” name=”month” value=””style=”width: 2em;”>
    Day:<input id="” type=”text” name=”day” value=””style=”width: 2em;”>

  4. do {
    $Counter = $Counter +1;
    $FieldID = “datefields” .$Counter;
    $Y = “year-field” .$Counter;
    $M = “month-field” .$Counter;
    $D = “day-field” .$Counter;
    calendar($Counter);

    id=” class=”fromdate”>
    Year:<input id="” type=”text” name=”year” value=”” style=”width: 3em;”>

    } while ($row_Recordset1 = mysql_fetch_assoc($Recordset1));

  5. Calendar($Counter) is javascript, are you putting that in script tags? and also embed the id in html like year1, year2, year3 when calendar id is 1, 2, 3

  6. I’m calling calendar($Counter); from within my recordset PHP loop. Expect it call the function calendar(calendarID) which is with javascript tag. I am echo $Y, result of $Y = “year-field” .$Counter; though to the textfield name and id. I checked this in testing and view source and this part at least seems to be working.

  7. I have a problem that I’ve been fussing with for a couple of days that I thought you might have some insight on. I have a page with multiple calendars used for different functions on the page. I’ve had no problem with the individual functionality but the layout calls for them to be different sizes and skins. So far I haven’t figured out how to modify the size/skin of one without affecting the other.

    Any ideas on how to do that?

    Thanks

  8. I have never done this but all I can suggest is that you have to skin them differently, by default YUI calendar uses Sam skin, you can see it’s CSS for calendar widget here: http://github.com/yui/yui2/blob/master/src/calendar/assets/skins/sam/calendar-skin.css (if it’s YUI2), see the CSS, these are the rules which are getting applied on your calendars, what you will have to do, you will have to write the your calendars in different divs and then you will need to apply your own different skin classes on those divs. You can start by overriding the default classes to see the difference.
    See if that helps!

  9. I just wanted to say thanks for putting this great article together. I needed to format the selected date (before writing it to an input field) and your code helped me a great deal.

    Thanks again!

  10. Very helpfull article

  11. Thank you for the article,it was very helpfull, I want to add time pick with the calendar howto do this

  12. Am a student trying to use the example given above to calculate the difference between two fields of date and the result will be place in a third field. Now my question is, how do i download the calendar on my side or on the page am working so that when i want to fill or click on the date field the calendar will appear.
    Thanks

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Get Adobe Flash player