CGI-WebToolkit

 view release on metacpan or  search on metacpan

t/private/javascripts/datepicker.js  view on Meta::CPAN

/*
 * Control.DatePicker
 * 
 * Transforms an ordinary input textbox into an interactive date picker.
 * When the textbox is clicked (or the down arrow is pressed), a calendar
 * appears that the user can browse through and select a date.
 *
 * Features:
 *  - Allows user to specify a date format
 *  - Easy to localize
 *  - Customizable by CSS
 *
 * Written and maintained by Jeremy Jongsma (jeremy@jongsma.org)
 */
if (window.Control == undefined) Control = {};

Control.DatePicker = Class.create();
Control.DatePicker.activePicker = null;
Control.DatePicker.prototype = {
	initialize: function(element, options) {
		this.element = $(element);
		this.i18n = new Control.DatePicker.i18n(options && options.locale ? options.locale : 'en_US');
		options = this.i18n.inheritOptions(options);
		options = Object.extend({
						datePicker: true,
						timePicker: false
					}, options || {});

		this.handlers = { onClick: options.onClick,
				onHover: options.onHover,
				onSelect: options.onSelect };

		this.options = Object.extend(options || {}, {
				onClick: this.pickerClicked.bind(this),
				onHover: this.dateHover.bind(this),
				onSelect: this.datePicked.bind(this)
			});

		if (this.options.timePicker && this.options.datePicker)
			this.options.currentFormat = this.options.dateTimeFormat;
		else if (this.options.timePicker)
			this.options.currentFormat = this.options.timeFormat;
		else
			this.options.currentFormat = this.options.dateFormat;
//		this.options.currentFormat = this.options.timePicker ? this.options.dateTimeFormat : this.options.dateFormat;
		this.options.date = DateFormat.parseFormat(this.element.value, this.options.currentFormat);

		// Lazy load to avoid excessive CPU usage with lots of controls on one page
		this.datepicker = null;

		this.originalValue = null;
		this.hideTimeout = null;

		if (this.options.icon) {
			var cont = new Element('div', {'style': 'position: relative;'});
			this.element.parentNode.replaceChild(cont, this.element);
			cont.appendChild(this.element);

			this.icon = new Element('img', {'src': this.options.icon, 'title': this.tr('Open calendar'), 'className': 'inputExtension'});

			var padding = this.options.padding;
			if (!padding) {
				// No icon padding specified, default to 3px and calculate
				// dynamically on image load
				padding = 3;
				Event.observe(this.icon, 'load', function() {
					padding = parseInt(this.element.offsetHeight - this.icon.offsetHeight) / 2;
					var right = (this.element.offsetParent.offsetWidth - (this.element.offsetLeft + this.element.offsetWidth) + padding) + 'px';
					Element.setStyle(this.icon, {'right': right, 'top': padding + 'px'});
				}.bind(this));
			}
			var right = (this.element.offsetParent.offsetWidth - (this.element.offsetLeft + this.element.offsetWidth) + padding) + 'px';
			Element.setStyle(this.icon, {'position': 'absolute', 'right': right, 'top': padding + 'px'});
			cont.appendChild(this.icon);

			Event.observe(this.icon, 'click', this.togglePicker.bindAsEventListener(this));
		} else {
			Event.observe(this.element, 'click', this.togglePicker.bindAsEventListener(this));
		}

		this.hidePickerListener = this.delayedHide.bindAsEventListener(this);
		Event.observe(this.element, 'keydown', this.keyHandler.bindAsEventListener(this));
		Event.observe(document, 'keydown', this.docKeyHandler.bindAsEventListener(this));

		this.pickerActive = false;
	},
	tr: function(str) {
		return this.i18n.tr(str);
	},
	delayedHide: function(e) {
		this.hideTimeout = setTimeout(this.hide.bind(this), 100);
	},
	pickerClicked: function() {
		if (this.hideTimeout) {
			clearTimeout(this.hideTimeout);
			this.hideTimeout = null;
		}
		if (this.handlers.onClick)
			this.handlers.onClick();
	},
	datePicked: function(date) {
		this.element.value = DateFormat.format(date, this.options.currentFormat);
		this.element.focus();
		this.hide();
		if (this.handlers.onSelect)
			this.handlers.onSelect(date);
		if (this.element.onchange)
			this.element.onchange();
	},
	dateHover: function(date) {
		if (this.hideTimeout) {
			clearTimeout(this.hideTimeout);
			this.hideTimeout = null;
		}
		if (this.pickerActive) {
			this.element.value = DateFormat.format(date, this.options.currentFormat);
			if (this.handlers.onHover)
				this.handlers.onHover(date);
		}
	},
	togglePicker: function(e) {
		if (this.pickerActive) {
			this.element.value = this.originalValue;
			this.hide();
		} else {
			this.show();
		}
		Event.stop(e);
		return false;
	},
	docKeyHandler: function(e) {
		if (e.keyCode == Event.KEY_ESC)
			if (this.pickerActive) {
				this.element.value = this.originalValue;
				this.hide();
			}

	},
	keyHandler: function(e) {
		switch (e.keyCode) {
			case Event.KEY_ESC:
				if (this.pickerActive)
					this.element.value = this.originalValue;
			case Event.KEY_TAB:
				this.hide();
				return;
			case Event.KEY_DOWN:	
				if (!this.pickerActive) {
					this.show();
					Event.stop(e);
				}
		}
		if (this.pickerActive)
			return false;
	},
	hide: function() {
		if(this.pickerActive && !this.element.disabled) {
			this.datepicker.releaseKeys();
			Element.remove(this.datepicker.element);
			Event.stopObserving(document, 'click', this.hidePickerListener, true);
			this.pickerActive = false;
			Control.DatePicker.activePicker = null;
		}
	},
	show: function () {
		if (!this.pickerActive) {
			if (Control.DatePicker.activePicker)
				Control.DatePicker.activePicker.hide();
			this.element.focus();
			if (!this.datepicker)
				this.datepicker = new Control.DatePickerPanel(this.options);
			this.originalValue = this.element.value;
			var pos = Position.positionedOffset(this.element);

t/private/javascripts/datepicker.js  view on Meta::CPAN

					cell.width = '14%';
					cell.innerHTML = (j*6)+i+(this.options.use24hrs?0:1);
					cell.onclick = this.hourClickedListener((j*6)+i+(this.options.use24hrs?0:1));
					this.hourCells[(j*6)+i] = cell;
				}
				if (!this.options.use24hrs) {
					cell = row.insertCell(i);
					cell.className = 'ampm';
					cell.width = '14%';
					if (j) {
						cell.innerHTML = this.tr('PM');
						cell.onclick = this.pmClickedListener();
						this.pmCell = cell;
					} else {
						cell.innerHTML = this.tr('AM');
						cell.onclick = this.amClickedListener();
						this.amCell = cell;
					}
				}
			}

			row = timeTable.insertRow(rows++);
			cell = row.insertCell(0);
			cell.colSpan = 6;

			var hr = document.createElement('hr');
			Element.setStyle(hr, {'color': '#CCCCCC', 'backgroundColor': '#CCCCCC', 'height': '1px', 'border': '0', 'marginTop': '2px', 'marginBottom': '2px', 'padding': '0'});
			cell.appendChild(hr);
			cell = row.insertCell(1);

			for (var j = 0; j < (10/this.minInterval); ++j) {
				row = timeTable.insertRow(rows++);
				for (var i = 0; i < 6; ++i){
					cell = row.insertCell(i);
					cell.className = 'minute';
					cell.width = '14%';
					var minval = ((j*6+i)*this.minInterval);
					if (minval < 10) minval = '0'+minval;
					cell.innerHTML = ':'+minval;
					cell.onclick = this.minuteClickedListener(minval);
					this.minuteCells[(j*6)+i] = cell;
				}
				if (!this.options.use24hrs) {
					cell = row.insertCell(i);
					cell.width = '14%';
				}
			}

			row = timeTable.insertRow(rows++);
			cell = row.insertCell(0);
			cell.style.textAlign = 'right';
			cell.colSpan = 5;
			cell.innerHTML = '<i>'+this.tr('Exact minutes')+':</i>';

			cell = row.insertCell(1);
			cell.className = 'otherminute';
			var otherInput = document.createElement('input');
			otherInput.type = 'text';
			otherInput.maxLength = 2;
			otherInput.style.width = '2em';
			var inputTimeout = null;
			otherInput.onkeyup = function(e) {
						if (!isNaN(otherInput.value)) {
							this.currentDate.setMinutes(otherInput.value);
							this.dateChanged(this.currentDate);
						}
					}.bindAsEventListener(this);
			otherInput.onkeydown = function(e) {
						if (e.keyCode == Event.KEY_RETURN)
							if (this.options.onSelect) this.options.onSelect(this.currentDate);
					}.bindAsEventListener(this);
			// Remove event key capture to allow use of arrow keys
			otherInput.onfocus = this.releaseKeys.bindAsEventListener(this);
			otherInput.onblur = this.captureKeys.bindAsEventListener(this);
			this.otherMinutes = otherInput;
			cell.appendChild(otherInput);
			// Padding cell
			if (!this.options.use24hrs)
				cell = row.insertCell(2);

			row = timeTable.insertRow(rows++);
			cell = row.insertCell(0);
			cell.colSpan = rowwidth;

			hr = document.createElement('hr');
			Element.setStyle(hr, {'color': 'gray', 'backgroundColor': 'gray', 'height': '1px', 'border': '0', 'marginTop': '3px', 'marginBottom': '3px', 'padding': '0'});
			cell.appendChild(hr);

			row = timeTable.insertRow(rows++);
			cell = row.insertCell(0);
			cell.colSpan = rowwidth;

			selectButton = document.createElement('input');
			selectButton.type = 'button';
			if (this.options.datePicker)
				selectButton.value = this.tr('Select Date and Time');
			else
				selectButton.value = this.tr('Select Time');
			selectButton.onclick = function(e) {
						this.options.onSelect && this.options.onSelect(this.currentDate);
					}.bindAsEventListener(this);
			cell.appendChild(selectButton);

		} else {
			calCont.appendChild(calTable);
		}

		return calCont;

	},
	createCalendar: function(date) {
		this.currentDate = date;
		this.currentDays = [];

		var today = new Date();
		var previousYear = new Date(date.getFullYear() - 1, date.getMonth(), 1)
		var previousMonth = new Date(date.getFullYear(), date.getMonth() - 1, 1)
		var nextMonth = new Date(date.getFullYear(), date.getMonth() + 1, 1)
		var nextYear = new Date(date.getFullYear() + 1, date.getMonth(), 1)

		var row;



( run in 0.566 second using v1.01-cache-2.11-cpan-39bf76dae61 )