|
| 1 | +/* |
| 2 | + * Calendar math built on jquery-global |
| 3 | + * |
| 4 | + * Based on Marc Grabanski's jQuery Date Plugin |
| 5 | + * http://marcgrabanski.com/articles/jquery-date-plugin |
| 6 | + */ |
| 7 | +(function( $, undefined ) { |
| 8 | + |
| 9 | +$.date = function( datestring, formatstring ) { |
| 10 | + //TODO: Need to refactor $.date to be a constructor, move the methods to a prototype. |
| 11 | + var calendar = Globalize.culture().calendar, |
| 12 | + format = formatstring ? formatstring : calendar.patterns.d, |
| 13 | + date = datestring ? Globalize.parseDate( datestring, format ) : new Date(); |
| 14 | + |
| 15 | + if ( !date ) { |
| 16 | + date = new Date(); |
| 17 | + } |
| 18 | + |
| 19 | + return { |
| 20 | + refresh: function() { |
| 21 | + calendar = Globalize.culture().calendar; |
| 22 | + format = formatstring || calendar.patterns.d; |
| 23 | + return this; |
| 24 | + }, |
| 25 | + setFormat: function( formatstring ) { |
| 26 | + if ( formatstring ) { |
| 27 | + format = formatstring; |
| 28 | + } |
| 29 | + return this; |
| 30 | + }, |
| 31 | + //TODO: same as the underlying Date object's terminology, but still misleading. |
| 32 | + //TODO: We can use .setTime() instead of new Date and rename to setTimestamp. |
| 33 | + setTime: function( time ) { |
| 34 | + date = new Date( time ); |
| 35 | + return this; |
| 36 | + }, |
| 37 | + setDay: function( day ) { |
| 38 | + date = new Date( date.getFullYear(), date.getMonth(), day, date.getHours(), date.getMinutes(), date.getSeconds() ); |
| 39 | + return this; |
| 40 | + }, |
| 41 | + setMonth: function( month ) { |
| 42 | + // Overflow example: Month is October 31 (yeah Halloween) and month is changed to April with 30 days, |
| 43 | + // the new date will me May 1. We will honor the month the user wants to set and if and overflow |
| 44 | + // occurs, set to last day of month. |
| 45 | + var days = date.getDay(), year = date.getFullYear(); |
| 46 | + if ( days > this.daysInMonth( year, month ) ) { |
| 47 | + // Overflow |
| 48 | + days = this.daysInMonth( year, month ); |
| 49 | + } |
| 50 | + date = new Date( year, month, days, date.getHours(), date.getMinutes(), date.getSeconds() ); |
| 51 | + return this; |
| 52 | + }, |
| 53 | + setYear: function( year ) { |
| 54 | + var day = date.getDate(), |
| 55 | + month = date.getMonth(); |
| 56 | + // Check if Leap, and February and day is 29th |
| 57 | + if ( this.isLeapYear( year ) && month == 1 && day == 29 ) { |
| 58 | + // set day to last day of February |
| 59 | + day = this.daysInMonth( year, month ); |
| 60 | + } |
| 61 | + date = new Date( year, month, day, date.getHours(), date.getMinutes(), date.getSeconds() ); |
| 62 | + return this; |
| 63 | + }, |
| 64 | + setFullDate: function( year, month, day ) { |
| 65 | + date = new Date( year, month, day ); |
| 66 | + return this; |
| 67 | + }, |
| 68 | + adjust: function( period, offset ) { |
| 69 | + var day = period == "D" ? date.getDate() + offset : date.getDate(), |
| 70 | + month = period == "M" ? date.getMonth() + offset : date.getMonth(), |
| 71 | + year = period == "Y" ? date.getFullYear() + offset : date.getFullYear(); |
| 72 | + // If not day, update the day to the new month and year |
| 73 | + if ( period != "D" ) { |
| 74 | + day = Math.max( 1, Math.min( day, this.daysInMonth( year, month ) ) ); |
| 75 | + } |
| 76 | + date = new Date( year, month, day, date.getHours(), date.getMinutes(), date.getSeconds() ); |
| 77 | + return this; |
| 78 | + }, |
| 79 | + daysInMonth: function( year, month ) { |
| 80 | + year = year || date.getFullYear(); |
| 81 | + month = month || date.getMonth(); |
| 82 | + return 32 - new Date( year, month, 32 ).getDate(); |
| 83 | + }, |
| 84 | + monthName: function() { |
| 85 | + return calendar.months.names[ date.getMonth() ]; |
| 86 | + }, |
| 87 | + day: function() { |
| 88 | + return date.getDate(); |
| 89 | + }, |
| 90 | + month: function() { |
| 91 | + return date.getMonth(); |
| 92 | + }, |
| 93 | + year: function() { |
| 94 | + return date.getFullYear(); |
| 95 | + }, |
| 96 | + isLeapYear: function( year ) { |
| 97 | + year = year || date.getFullYear(); |
| 98 | + return new Date( year, 1, 29 ).getMonth() == 1; |
| 99 | + |
| 100 | + }, |
| 101 | + weekdays: function() { |
| 102 | + var result = []; |
| 103 | + for ( var dow = 0; dow < 7; dow++ ) { |
| 104 | + var day = ( dow + calendar.firstDay ) % 7; |
| 105 | + result.push({ |
| 106 | + shortname: calendar.days.namesShort[ day ], |
| 107 | + fullname: calendar.days.names[ day ] |
| 108 | + }); |
| 109 | + } |
| 110 | + return result; |
| 111 | + }, |
| 112 | + days: function() { |
| 113 | + var result = [], |
| 114 | + today = $.date(), |
| 115 | + firstDayOfMonth = new Date( this.year(), date.getMonth(), 1 ).getDay(), |
| 116 | + leadDays = ( firstDayOfMonth - calendar.firstDay + 7 ) % 7, |
| 117 | + rows = Math.ceil( ( leadDays + this.daysInMonth() ) / 7 ), |
| 118 | + printDate = new Date( this.year(), date.getMonth(), 1 - leadDays ); |
| 119 | + for ( var row = 0; row < rows; row++ ) { |
| 120 | + var week = result[ result.length ] = { |
| 121 | + number: this.iso8601Week( printDate ), |
| 122 | + days: [] |
| 123 | + }; |
| 124 | + for ( var dayx = 0; dayx < 7; dayx++ ) { |
| 125 | + var day = week.days[ week.days.length ] = { |
| 126 | + lead: printDate.getMonth() != date.getMonth(), |
| 127 | + date: printDate.getDate(), |
| 128 | + timestamp: printDate.getTime(), |
| 129 | + current: this.selected && this.selected.equal( printDate ), |
| 130 | + today: today.equal( printDate ) |
| 131 | + }; |
| 132 | + day.render = day.selectable = !day.lead; |
| 133 | + // TODO undefined in picker demos, fix it |
| 134 | + // this.eachDay( day ); |
| 135 | + // TODO use adjust("D", 1)? |
| 136 | + printDate.setDate( printDate.getDate() + 1 ); |
| 137 | + } |
| 138 | + } |
| 139 | + return result; |
| 140 | + }, |
| 141 | + // specialized for multi-month template, could be used in general |
| 142 | + months: function( add ) { |
| 143 | + var clone, |
| 144 | + result = [ this ]; |
| 145 | + |
| 146 | + for ( var i = 0; i < add; i++ ) { |
| 147 | + clone = this.clone(); |
| 148 | + clone.adjust( "M", i + 1 ); |
| 149 | + result.push( clone ); |
| 150 | + } |
| 151 | + result[ 0 ].first = true; |
| 152 | + result[ result.length - 1 ].last = true; |
| 153 | + return result; |
| 154 | + }, |
| 155 | + iso8601Week: function(date) { |
| 156 | + var checkDate = new Date( date.getTime() ); |
| 157 | + // Find Thursday of this week starting on Monday |
| 158 | + checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) ); |
| 159 | + var time = checkDate.getTime(); |
| 160 | + // Compare with Jan 1 |
| 161 | + checkDate.setMonth( 0 ); |
| 162 | + checkDate.setDate( 1 ); |
| 163 | + return Math.floor( Math.round( ( time - checkDate ) / 86400000) / 7 ) + 1; |
| 164 | + }, |
| 165 | + select: function() { |
| 166 | + this.selected = this.clone(); |
| 167 | + return this; |
| 168 | + }, |
| 169 | + clone: function() { |
| 170 | + return $.date( new Date(date.getFullYear(), date.getMonth(), |
| 171 | + date.getDate(), date.getHours(), |
| 172 | + date.getMinutes(), date.getSeconds()), formatstring ); |
| 173 | + }, |
| 174 | + // TODO compare year, month, day each for better performance |
| 175 | + equal: function( other ) { |
| 176 | + function format( date ) { |
| 177 | + return Globalize.format( date, "d" ); |
| 178 | + } |
| 179 | + return format( date ) === format( other ); |
| 180 | + }, |
| 181 | + date: function() { |
| 182 | + return date; |
| 183 | + }, |
| 184 | + format: function( formatstring ) { |
| 185 | + return Globalize.format( date, formatstring ? formatstring : format ); |
| 186 | + }, |
| 187 | + calendar: function( newcalendar ) { |
| 188 | + if ( newcalendar ) { |
| 189 | + calendar = newcalendar; |
| 190 | + return this; |
| 191 | + } |
| 192 | + return calendar; |
| 193 | + } |
| 194 | + }; |
| 195 | +}; |
| 196 | + |
| 197 | +}( jQuery )); |
0 commit comments