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