A calendar control helper using Yahoo Calendar
I've never found a very good calendar control that is easy to configure and update and I spendt what seemed like forever creating this one, so hopefully someone else finds it useful...
1 2 #code is in 3 parts: 3 # 4 #first this goes in the helper for the application or the controller that you want to use the calendar helper 5 # 6 # 7 #so, for example it would go in /app/helpers/application_helper.rb 8 # 9 #def calendar_field(object_name,field_name,cal_number,date=Date.today) 10 ################################## 11 #Function to update the dates in a calendar control when a user makes a selection 12 #Takes: 1) object_name (class of the object that the date is for) 13 # 2) field_name (name of the field in the database) 14 # 3) cal_number (an integer marking the cardinality of this calendar, so if it's the first, use 15 # 1, if it's the third, use 3 16 # 4) default date (must be a Date object) 17 #Returns: an html/javascript string that produces a hidden field with the name object_name[field_name] and the ID object_name_field_name that contains the date selected on the calendar 18 # if you want to have multiple instances of an object just make it object_name[0] and object_name[1], just like any other helper 19 ################################## 20 21 ret = '<input type="hidden"' 22 ret += 'name="' + object_name + '[' + field_name + ']"' 23 ret += 'id="' + object_name + '_' + field_name + '"' 24 ret += 'value="' + date.strftime("%Y-%m-%d") + '">' 25 ret += '<select id="' + object_name + '_' + field_name + '[0]"' 26 ret += ' onChange="updateDate($(\'' + object_name + '_' + field_name + '[2]' + '\').value + \',\' + $(\'' + object_name + '_' + field_name + '[0]' + '\').value + \',\' + $(\'' + object_name + '_' + field_name + '[1]' + '\').value,\'' + object_name + '_' + field_name + '\',cal' + cal_number + ');">' 27 ret += '<option value=\'1\'>Jan</option>' 28 ret += '<option value=\'2\'>Feb</option>' 29 ret += '<option value=\'3\'>Mar</option>' 30 ret += '<option value=\'4\'>Apr</option>' 31 ret += '<option value=\'5\'>May</option>' 32 ret += '<option value=\'6\'>Jun</option>' 33 ret += '<option value=\'7\'>Jul</option>' 34 ret += '<option value=\'8\'>Aug</option>' 35 ret += '<option value=\'9\'>Sep</option>' 36 ret += '<option value=\'10\'>Oct</option>' 37 ret += '<option value=\'11\'>Now</option>' 38 ret += '<option value=\'12\'>Dec</option>' 39 ret += '</select>' 40 ret += '<input type="text"' 41 ret += 'id=\'' + object_name + '_' + field_name + '[1]\'' 42 ret += 'value="' + date.strftime("%d") + '"' 43 ret += ' onChange="updateDate($(\'' + object_name + '_' + field_name + '[2]' + '\').value + \',\' + $(\'' + object_name + '_' + field_name + '[0]' + '\').value + \',\' + $(\'' + object_name + '_' + field_name + '[1]' + '\').value,\'' + object_name + '_' + field_name + '\',cal' + cal_number + ');">' 44 ret += '<select id=\'' + object_name + '_' + field_name + '[2]\'' 45 ret += ' onChange="updateDate($(\'' + object_name + '_' + field_name + '[2]' + '\').value + \',\' + $(\'' + object_name + '_' + field_name + '[0]' + '\').value + \',\' + $(\'' + object_name + '_' + field_name + '[1]' + '\').value,\'' + object_name + '_' + field_name + '\',cal' + cal_number + ');">' 46 ret += '<option value=\'2006\'>2006</option>' 47 ret += '<option value=\'2007\'>2007</option>' 48 ret += '<option value=\'2008\'>2008</option>' 49 ret += '<option value=\'2009\'>2009</option>' 50 ret += '</select>' 51 ret += image_tag 'icons/Calendar24', :onClick => "Element.show('" + object_name + "_" + field_name + "_div')" 52 ret += '<div id="' + object_name + '_' + field_name + '_div" style="display:none"></div>' 53 ret += '<script type="text/javascript">' 54 ret += 'cal' + cal_number + ' = new YAHOO.widget.Calendar(' 55 ret += '"cal' + cal_number + '",' 56 ret += '"' + object_name + '_' + field_name + '_div","' + date.strftime("%m/%Y") + '","' + format_time(date) + '");' 57 ret += 'cal' + cal_number + '.onSelect = function(e){updateDate(e,\'' + object_name + '_' + field_name + '\',cal' + cal_number + ',true);Element.hide(\'' + object_name + '_' + field_name + '_div\');};' 58 ret += 'cal' + cal_number + '.render();' 59 ret += 'updateDate(\'' + date.strftime("%Y,%m,%d") + '\',\'' + object_name + '_' + field_name + '\',cal' + cal_number + ');' 60 ret += '</script>' 61 62 #next is the javascript file that actually updates the dates on the calendar control when you change them in the select box or vice versa. 63 # 64 #It should go in /public/javascripts/application.js 65 # 66 function updateDate(date, field_id, calendar_id, from_cal) 67 { 68 /******************************** 69 Function to update the dates in a calendar control when a user makes a selection 70 Takes: 1) a date in 'YYYY,MM,DD' format, 71 2) the id of the hidden field that houses the final calendar date 72 3) calendar object related to the date 73 4) a boolean 'from_cal' - 74 *note - this is to set a break when the calendar control has set the date. If it is not set to 75 true when a calendar control (graphic) sets the date, it will result in an infinite loop 76 77 Returns: none 78 *********************************/ 79 if (from_cal != true) 80 { 81 from_cal = false; 82 } 83 84 date += '' 85 $(field_id).value = date.replace(RegExp(",","g"),"-"); 86 87 dateParts = $(field_id).value.split("-") 88 $(field_id + '[2]').value = dateParts[0] 89 $(field_id + '[0]').value = dateParts[1] 90 $(field_id + '[1]').value = dateParts[2] 91 92 if (from_cal != true) 93 { 94 calendar_id.select(dateParts[1] + '/' + dateParts[2] + '/' + dateParts[0]) 95 calendar_id.setMonth(dateParts[1]) 96 calendar_id.subtractMonths(1) 97 calendar_id.setYear(dateParts[0]) 98 calendar_id.render(); 99 } 100 } 101 102 #Usage example: 103 # 104 #You need to download and import the yahoo calendar controls to get this to work 105 <%= javascript_include_tag 'yahoo/yahoo'%> 106 <%= javascript_include_tag 'dom/dom'%> 107 <%= javascript_include_tag 'event/event'%> 108 <%= javascript_include_tag 'calendar/calendar'%> 109 110 #Then simply add a field like so: 111 112 <div class="calendar">Season Start Date:<br> 113 <%= calendar_field('season','start_date','1') %> 114 </div> 115 116 #Here is the stylesheet that I am using for it, most of this is from Yahoo with some slight modifications 117 118 styles.css 119 120 /******************** 121 Styles for Calendar Control 122 ********************/ 123 #body #content div.calendar {font-size:.8em;} 124 #body #content div.calendar input {width:40px; margin:0px 5px; font-size:.8em;} 125 #body #content div.calendar select {width:auto; font-size:.8em;} 126 #body #content div.calendar img {vertical-align:middle;} 127 128 /* 129 Copyright (c) 2006, Yahoo! Inc. All rights reserved. 130 Code licensed under the BSD License: 131 http://developer.yahoo.net/yui/license.txt 132 Version 0.11.3 133 */ 134 135 .yui-cal2upwrapper {*height:1%;} /* IE */ 136 .yui-cal2upwrapper:after {content:'.';clear:both;display:block;visibility:hidden;height:0;} /* others */ 137 138 .yui-calcontainer { 139 float:left; 140 padding:5px; 141 background-color:#F7F9FB; 142 border:1px solid #7B9EBD; 143 position:relative; 144 } 145 146 .yui-calcontainer .title { 147 font:100% sans-serif; 148 color:#000; 149 font-weight:bold; 150 margin-bottom:5px; 151 height:auto; 152 position:relative; 153 } 154 155 .yui-calcontainer .title .close-icon { 156 position:absolute; 157 right:0; 158 top:0; 159 border:none; 160 } 161 162 .yui-calcontainer .cal2up { 163 float:left; 164 } 165 166 .yui-calendar .calnavleft { 167 position:absolute; 168 background-repeat:no-repeat; 169 cursor:pointer; 170 top:2px; 171 bottom:0; 172 width:9px; 173 height:12px; 174 left:2px; 175 } 176 177 .yui-calendar .calnavright { 178 position:absolute; 179 background-repeat:no-repeat; 180 cursor:pointer; 181 top:2px; 182 bottom:0; 183 width:9px; 184 height:12px; 185 right:2px; 186 } 187 188 /* Calendar element styles */ 189 190 .yui-calendar { 191 font:50% sans-serif !important; 192 width:auto !important; 193 text-align:center; 194 border-spacing:0; 195 border-collapse:separate; 196 position:absolute; 197 background-color:#FFFFFF; 198 } 199 200 .yui-calendar td.calcell { 201 padding:.05em !important; 202 border:1px solid #E0E0E0; 203 background-color:#FFF; 204 text-align:center !important; 205 } 206 207 .yui-calendar td.calcell a { 208 color:#003DB8; 209 text-decoration:none; 210 } 211 212 .yui-calendar td.calcell.today { 213 border:1px solid #000; 214 } 215 216 .yui-calendar td.calcell.oom { 217 cursor:default; 218 color:#999; 219 background-color:#EEE; 220 border:1px solid #E0E0E0; 221 } 222 223 .yui-calendar td.calcell.selected { 224 color:#003DB8; 225 background-color:#FFF19F; 226 border:1px solid #FF9900; 227 } 228 229 .yui-calendar td.calcell.calcellhover { 230 cursor:pointer; 231 color:#FFF; 232 background-color:#FF9900; 233 border:1px solid #FF9900; 234 } 235 236 .yui-calendar td.calcell.calcellhover a { 237 color:#FFF; 238 } 239 240 .yui-calendar td.calcell.restricted { 241 text-decoration:line-through; 242 } 243 244 .yui-calendar td.calcell.previous { 245 color:#CCC; 246 } 247 248 .yui-calendar td.calcell.highlight1 { background-color:#CCFF99; } 249 .yui-calendar td.calcell.highlight2 { background-color:#99CCFF; } 250 .yui-calendar td.calcell.highlight3 { background-color:#FFCCCC; } 251 .yui-calendar td.calcell.highlight4 { background-color:#CCFF99; } 252 253 254 .yui-calendar .calhead { 255 border:1px solid #E0E0E0; 256 vertical-align:middle; 257 background-color:#FFF; 258 } 259 260 .yui-calendar .calheader { 261 position:relative; 262 width:100%; 263 text-align:center; 264 } 265 266 .yui-calendar .calheader img { 267 border:none; 268 } 269 270 .yui-calendar .calweekdaycell { 271 color:#666; 272 font-weight:normal; 273 } 274 275 .yui-calendar .calfoot { 276 background-color:#EEE; 277 } 278 279 .yui-calendar .calrowhead, .yui-calendar .calrowfoot { 280 color:#666; 281 font-size:9px; 282 font-style:italic; 283 font-weight:normal; 284 width:15px; 285 } 286 287 .yui-calendar .calrowhead { 288 border-right-width:2px; 289 } 290 291 /*Specific changes for calendar running under fonts/reset */ 292 .yui-calendar a:hover {background:inherit;} 293 p#clear {clear:left; padding-top:10px;} 294
One final thing, I use an image from KDE for the calendar image, you can replace it with whatever you want. The image is included in the helper file
Hope someone finds this useful