Monday, September 19, 2011

jQuery Simple Date Selector

I was trying forever to find a simple javascript date selector that would do well on mobile applications. Couldn't find one, so I rolled my own. It takes a text or hidden input element and inserts three select elements after it, one each for months, days, and the year. The onchange event for each select copies the selected date back to the input, and the selects are initialized from the input on page load.

The code below should be enough to give you the idea.

The selector follows the jQuery UI widget template (another good widget tutorial here).

// attach widget to input
$(document).ready(function () { 
	$('#mydate').dateselector(); 
});

// some display formatting
Date.prototype.toMMDDYYYY = function () {
    return isNaN(this) ? 'NaN' : [this.getMonth() > 8 ? this.getMonth() + 1 : '0' + (this.getMonth() + 1), this.getDate() > 9 ? this.getDate() : '0' + this.getDate(), this.getFullYear()].join('/')
}

// date selector widget
; (function ($) {
	$.widget("ui.dateselector", {
		options: {},
		shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
		_syncToSelector: function () {
			var self = this;
			var date = new Date($(self.element).val());
			self.$container.find('select:eq(0)').val(date.getMonth());
			self.$container.find('select:eq(1)').val(date.getDate());
			self.$container.find('select:eq(2)').val(date.getFullYear());
		},
		_syncFromSelector: function () {
			var self = this;
			var date = new Date();
			date.setFullYear(self.$container.find('select:eq(2)').val());
			date.setDate(self.$container.find('select:eq(1)').val());
			date.setMonth(self.$container.find('select:eq(0)').val());
			$(self.element).val(date.toMMDDYYYY());
		},
		destroy: function () {
			var self = this;
			if (self.$container) self.$container.remove();
			$.Widget.prototype.destroy.apply(this, arguments);
		},
		_init: function () {
			var self = this;

			var $months = $('<select></select>').change($.proxy(this._syncFromSelector, this));
			for (var i = 0; i &lt; 12; i++) { $('<option></option>').val(i).text(this.shortMonths[i]).appendTo($months); }

			var $days = $('<select></select>').change($.proxy(this._syncFromSelector, this));
			for (var i = 1; i &lt;= 31; i++) { $('<option></option>').val(i).text(i).appendTo($days); }

			var thisYear = new Date().getFullYear();
			var $years = $('<select></select>').change($.proxy(this._syncFromSelector, this));
			for (var i = -2; i &lt;= 2; i++) { $('<option></option>').val(thisYear + i).text(thisYear + i).appendTo($years); }

			self.$container = $('<span class="dateselectorContainer"></span>').append($months).append($days).append($years);

			this._syncToSelector();

			self.element.hide().after(self.$container);
		}
	});
})(jQuery);

No comments:

Post a Comment