[ Index ] |
PHP Cross Reference of YOURLS |
[Summary view] [Print] [Text view]
1 /** 2 the script only works on "input [type=text]" 3 http://teddevito.com/demos/calendar.php 4 **/ 5 6 // don't declare anything out here in the global namespace 7 8 (function($) { // create private scope (inside you can use $ instead of jQuery) 9 10 // functions and vars declared here are effectively 'singletons'. there will be only a single 11 // instance of them. so this is a good place to declare any immutable items or stateless 12 // functions. for example: 13 14 var today = new Date(); // used in defaults 15 var months = 'January,February,March,April,May,June,July,August,September,October,November,December'.split(','); 16 var months = l10n_cal_month; 17 var monthlengths = '31,28,31,30,31,30,31,31,30,31,30,31'.split(','); 18 var dateRegEx = /^\d{1,2}\/\d{1,2}\/\d{2}|\d{4}$/; 19 var yearRegEx = /^\d{4,4}$/; 20 21 // next, declare the plugin function 22 $.fn.simpleDatepicker = function(options) { 23 24 // functions and vars declared here are created each time your plugn function is invoked 25 26 // you could probably refactor your 'build', 'load_month', etc, functions to be passed 27 // the DOM element from below 28 29 var opts = jQuery.extend({}, jQuery.fn.simpleDatepicker.defaults, options); 30 31 // replaces a date string with a date object in opts.startdate and opts.enddate, if one exists 32 // populates two new properties with a ready-to-use year: opts.startyear and opts.endyear 33 34 setupYearRange(); 35 /** extracts and setup a valid year range from the opts object **/ 36 function setupYearRange () { 37 38 var startyear, endyear; 39 if (opts.startdate.constructor == Date) { 40 startyear = opts.startdate.getFullYear(); 41 } else if (opts.startdate) { 42 if (yearRegEx.test(opts.startdate)) { 43 startyear = opts.startdate; 44 } else if (dateRegEx.test(opts.startdate)) { 45 opts.startdate = new Date(opts.startdate); 46 startyear = opts.startdate.getFullYear(); 47 } else { 48 startyear = today.getFullYear(); 49 } 50 } else { 51 startyear = today.getFullYear(); 52 } 53 opts.startyear = startyear; 54 55 if (opts.enddate.constructor == Date) { 56 endyear = opts.enddate.getFullYear(); 57 } else if (opts.enddate) { 58 if (yearRegEx.test(opts.enddate)) { 59 endyear = opts.enddate; 60 } else if (dateRegEx.test(opts.enddate)) { 61 opts.enddate = new Date(opts.enddate); 62 endyear = opts.enddate.getFullYear(); 63 } else { 64 endyear = today.getFullYear(); 65 } 66 } else { 67 endyear = today.getFullYear(); 68 } 69 opts.endyear = endyear; 70 } 71 72 /** HTML factory for the actual datepicker table element **/ 73 // has to read the year range so it can setup the correct years in our HTML <select> 74 function newDatepickerHTML () { 75 76 var years = []; 77 78 // process year range into an array 79 for (var i = 0; i <= opts.endyear - opts.startyear; i ++) years[i] = opts.startyear + i; 80 81 // build the table structure 82 var table = jQuery('<table class="datepicker" cellpadding="0" cellspacing="0"></table>'); 83 table.append('<thead></thead>'); 84 table.append('<tfoot></tfoot>'); 85 table.append('<tbody></tbody>'); 86 87 // month select field 88 var monthselect = '<select name="month">'; 89 for (var i in l10n_cal_month) monthselect += '<option value="'+i+'">'+l10n_cal_month[i]+'</option>'; 90 monthselect += '</select>'; 91 92 // year select field 93 var yearselect = '<select name="year">'; 94 for (var i in years) yearselect += '<option>'+years[i]+'</option>'; 95 yearselect += '</select>'; 96 97 jQuery("thead",table).append('<tr class="controls"><th colspan="7"><span class="prevMonth">«</span> '+monthselect+yearselect+' <span class="nextMonth">»</span></th></tr>'); 98 jQuery("thead",table).append('<tr class="days"><th>'+l10n_cal_days[0]+'</th><th>'+l10n_cal_days[1]+'</th><th>'+l10n_cal_days[2]+'</th><th>'+l10n_cal_days[3]+'</th><th>'+l10n_cal_days[4]+'</th><th>'+l10n_cal_days[5]+'</th><th>'+l10n_cal_days[6]+'</th></tr>'); 99 jQuery("tfoot",table).append('<tr><td colspan="2"><span class="today">'+l10n_cal_today+'</span></td><td colspan="3"> </td><td colspan="2"><span class="close">'+l10n_cal_close+'</span></td></tr>'); 100 for (var i = 0; i < 6; i++) jQuery("tbody",table).append('<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>'); 101 return table; 102 } 103 104 /** get the real position of the input (well, anything really) **/ 105 //http://www.quirksmode.org/js/findpos.html 106 function findPosition (obj) { 107 var curleft = curtop = 0; 108 if (obj.offsetParent) { 109 do { 110 curleft += obj.offsetLeft; 111 curtop += obj.offsetTop; 112 } while (obj = obj.offsetParent); 113 return [curleft,curtop]; 114 } else { 115 return false; 116 } 117 } 118 119 /** load the initial date and handle all date-navigation **/ 120 // initial calendar load (e is null) 121 // prevMonth & nextMonth buttons 122 // onchange for the select fields 123 function loadMonth (e, el, datepicker, chosendate) { 124 125 // reference our years for the nextMonth and prevMonth buttons 126 var mo = jQuery("select[name=month]", datepicker).get(0).selectedIndex; 127 var yr = jQuery("select[name=year]", datepicker).get(0).selectedIndex; 128 var yrs = jQuery("select[name=year] option", datepicker).get().length; 129 130 // first try to process buttons that may change the month we're on 131 if (e && jQuery(e.target).hasClass('prevMonth')) { 132 if (0 == mo && yr) { 133 yr -= 1; mo = 11; 134 jQuery("select[name=month]", datepicker).get(0).selectedIndex = 11; 135 jQuery("select[name=year]", datepicker).get(0).selectedIndex = yr; 136 } else { 137 mo -= 1; 138 jQuery("select[name=month]", datepicker).get(0).selectedIndex = mo; 139 } 140 } else if (e && jQuery(e.target).hasClass('nextMonth')) { 141 if (11 == mo && yr + 1 < yrs) { 142 yr += 1; mo = 0; 143 jQuery("select[name=month]", datepicker).get(0).selectedIndex = 0; 144 jQuery("select[name=year]", datepicker).get(0).selectedIndex = yr; 145 } else { 146 mo += 1; 147 jQuery("select[name=month]", datepicker).get(0).selectedIndex = mo; 148 } 149 } 150 151 // maybe hide buttons 152 if (0 == mo && !yr) jQuery("span.prevMonth", datepicker).hide(); 153 else jQuery("span.prevMonth", datepicker).show(); 154 if (yr + 1 == yrs && 11 == mo) jQuery("span.nextMonth", datepicker).hide(); 155 else jQuery("span.nextMonth", datepicker).show(); 156 157 // clear the old cells 158 var cells = jQuery("tbody td", datepicker).unbind().empty().removeClass('date'); 159 160 // figure out what month and year to load 161 var m = jQuery("select[name=month]", datepicker).val(); 162 var y = jQuery("select[name=year]", datepicker).val(); 163 var d = new Date(y, m, 1); 164 var startindex = d.getDay(); 165 var numdays = monthlengths[m]; 166 167 // http://en.wikipedia.org/wiki/Leap_year 168 if (1 == m && ((y%4 == 0 && y%100 != 0) || y%400 == 0)) numdays = 29; 169 170 // test for end dates (instead of just a year range) 171 if (opts.startdate.constructor == Date) { 172 var startMonth = opts.startdate.getMonth(); 173 var startDate = opts.startdate.getDate(); 174 } 175 if (opts.enddate.constructor == Date) { 176 var endMonth = opts.enddate.getMonth(); 177 var endDate = opts.enddate.getDate(); 178 } 179 180 // walk through the index and populate each cell, binding events too 181 for (var i = 0; i < numdays; i++) { 182 183 var cell = jQuery(cells.get(i+startindex)).removeClass('chosen'); 184 185 // test that the date falls within a range, if we have a range 186 if ( 187 (yr || ((!startDate && !startMonth) || ((i+1 >= startDate && mo == startMonth) || mo > startMonth))) && 188 (yr + 1 < yrs || ((!endDate && !endMonth) || ((i+1 <= endDate && mo == endMonth) || mo < endMonth)))) { 189 190 cell 191 .text(i+1) 192 .addClass('date') 193 .hover( 194 function () { jQuery(this).addClass('over'); }, 195 function () { jQuery(this).removeClass('over'); }) 196 .click(function () { 197 var chosenDateObj = new Date(jQuery("select[name=year]", datepicker).val(), jQuery("select[name=month]", datepicker).val(), jQuery(this).text()); 198 closeIt(el, datepicker, chosenDateObj); 199 }); 200 201 // highlight the previous chosen date 202 if (i+1 == chosendate.getDate() && m == chosendate.getMonth() && y == chosendate.getFullYear()) cell.addClass('chosen'); 203 } 204 } 205 } 206 207 /** closes the datepicker **/ 208 // sets the currently matched input element's value to the date, if one is available 209 // remove the table element from the DOM 210 // indicate that there is no datepicker for the currently matched input element 211 function closeIt (el, datepicker, dateObj) { 212 if (dateObj && dateObj.constructor == Date) 213 el.val(jQuery.fn.simpleDatepicker.formatOutput(dateObj)); 214 datepicker.remove(); 215 datepicker = null; 216 jQuery.data(el.get(0), "simpleDatepicker", { hasDatepicker : false }); 217 } 218 219 // iterate the matched nodeset 220 return this.each(function() { 221 222 // functions and vars declared here are created for each matched element. so if 223 // your functions need to manage or access per-node state you can defined them 224 // here and use $this to get at the DOM element 225 226 if ( jQuery(this).is('input') && 'text' == jQuery(this).attr('type')) { 227 228 var datepicker; 229 jQuery.data(jQuery(this).get(0), "simpleDatepicker", { hasDatepicker : false }); 230 231 // open a datepicker on the click event 232 jQuery(this).click(function (ev) { 233 234 var $this = jQuery(ev.target); 235 236 if (false == jQuery.data($this.get(0), "simpleDatepicker").hasDatepicker) { 237 238 // store data telling us there is already a datepicker 239 jQuery.data($this.get(0), "simpleDatepicker", { hasDatepicker : true }); 240 241 // validate the form's initial content for a date 242 var initialDate = $this.val(); 243 244 if (initialDate && dateRegEx.test(initialDate)) { 245 var chosendate = new Date(initialDate); 246 } else if (opts.chosendate.constructor == Date) { 247 var chosendate = opts.chosendate; 248 } else if (opts.chosendate) { 249 var chosendate = new Date(opts.chosendate); 250 } else { 251 var chosendate = today; 252 } 253 254 // insert the datepicker in the DOM 255 datepicker = newDatepickerHTML(); 256 jQuery("body").prepend(datepicker); 257 258 // position the datepicker 259 var elPos = findPosition($this.get(0)); 260 var x = (parseInt(opts.x) ? parseInt(opts.x) : 0) + elPos[0]; 261 var y = (parseInt(opts.y) ? parseInt(opts.y) : 0) + elPos[1]; 262 jQuery(datepicker).css({ position: 'absolute', left: x, top: y }); 263 264 // bind events to the table controls 265 jQuery("span", datepicker).css("cursor","pointer"); 266 jQuery("select", datepicker).bind('change', function () { loadMonth (null, $this, datepicker, chosendate); }); 267 jQuery("span.prevMonth", datepicker).click(function (e) { loadMonth (e, $this, datepicker, chosendate); }); 268 jQuery("span.nextMonth", datepicker).click(function (e) { loadMonth (e, $this, datepicker, chosendate); }); 269 jQuery("span.today", datepicker).click(function () { closeIt($this, datepicker, new Date()); }); 270 jQuery("span.close", datepicker).click(function () { closeIt($this, datepicker); }); 271 272 // set the initial values for the month and year select fields 273 // and load the first month 274 jQuery("select[name=month]", datepicker).get(0).selectedIndex = chosendate.getMonth(); 275 jQuery("select[name=year]", datepicker).get(0).selectedIndex = Math.max(0, chosendate.getFullYear() - opts.startyear); 276 loadMonth(null, $this, datepicker, chosendate); 277 } 278 279 }); 280 } 281 282 }); 283 284 }; 285 286 // finally, I like to expose default plugin options as public so they can be manipulated. one 287 // way to do this is to add a property to the already-public plugin fn 288 289 jQuery.fn.simpleDatepicker.formatOutput = function (dateObj) { 290 return (dateObj.getMonth() + 1) + "/" + dateObj.getDate() + "/" + dateObj.getFullYear(); 291 }; 292 293 jQuery.fn.simpleDatepicker.defaults = { 294 // date string matching /^\d{1,2}\/\d{1,2}\/\d{2}|\d{4}$/ 295 chosendate : today, 296 297 // date string matching /^\d{1,2}\/\d{1,2}\/\d{2}|\d{4}$/ 298 // or four digit year 299 startdate : today.getFullYear(), 300 enddate : today.getFullYear() + 1, 301 302 // offset from the top left corner of the input element 303 x : 1, // must be in px 304 y : 18 // must be in px 305 }; 306 307 })(jQuery); 308 309 // Init the form 310 $(document).ready(function(){ 311 $('#date_first').simpleDatepicker({startdate: 2005, enddate: 2100}); 312 $('#date_second').simpleDatepicker({startdate: 2005, enddate: 2100}); 313 314 $('#date_filter').change(function(){ 315 var show = $(this).val() == 'between' ? 'inline' : 'none'; 316 $('#date_second').css('display', show); 317 $('#date_and').css('display', show); 318 }); 319 });
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Jan 21 05:10:11 2025 | Cross-referenced by PHPXref 0.7.1 |