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);
		}

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

			dateFormat: 'dd-MM-yyyy',
			firstWeekDay: 1,
			weekend: [0,6],
			timeFormat: 'HH:mm'
		},
		'iso8601': {
			dateTimeFormat: 'yyyy-MM-dd HH:mm',
			dateFormat: 'yyyy-MM-dd',
			firstWeekDay: 1,
			weekend: [0,6],
			timeFormat: 'HH:mm'
		}
	},
	createLocale: function(base, lang) {
		return Object.extend(Object.clone(Control.DatePicker.i18n.baseLocales[base]), {'language': lang});
	}
});
Control.DatePicker.i18n.prototype = {
	initialize: function(code) {
		var lang = code.charAt(2) == '_' ? code.substring(0,2) : code;
		var locale = (Control.DatePicker.Locale[code] || Control.DatePicker.Locale[lang]);
		this.opts = Object.clone(locale || {});
		var language = locale ? Control.DatePicker.Language[locale.language] : null;
		if (language) Object.extend(this.opts, language);
	},
	opts: null,
	inheritOptions: function(options) {
		if (!this.opts) this.setLocale('en_US');
		return Object.extend(this.opts, options || {});
	},
	tr: function(str) {
		return this.opts && this.opts.strings ? this.opts.strings[str] || str : str;
	}
};

Control.DatePicker.Locale = {};
with (Control.DatePicker) {
	// Full locale definitions not needed if countries use the language default format
	// Datepicker will fallback to the language default; i.e. 'es_AR' will use 'es'
	Locale['es'] = i18n.createLocale('eu', 'es');
	Locale['en'] = i18n.createLocale('us', 'en');
	Locale['en_GB'] = i18n.createLocale('eu', 'en');
	Locale['en_AU'] = Locale['en_GB'];
	Locale['de'] = i18n.createLocale('eu', 'de');
	Locale['es_iso8601'] = i18n.createLocale('iso8601', 'es');
	Locale['en_iso8601'] = i18n.createLocale('iso8601', 'en');
	Locale['de_iso8601'] = i18n.createLocale('iso8601', 'de');
}

Control.DatePicker.Language = {
	'es': {
		months: ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Augosto', 'Septiembre', 'Octubre', 'Novimbre', 'Diciembre'],
		days: ['Do', 'Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sa'],
		strings: {
			'Now': 'Ahora',
			'Today': 'Hoy',
			'Time': 'Hora',
			'Exact minutes': 'Minuto exacto',
			'Select Date and Time': 'Selecciona Dia y Hora',
			'Select Time': 'Selecciona Hora',
			'Open calendar': 'Abre calendario'
		}
	},
	'de': { 
		months: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'], 
		days: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'], 
		strings: { 
			'Now': 'Jetzt', 
			'Today': 'Heute', 
			'Time': 'Zeit', 
			'Exact minutes': 'Exakte minuten', 
			'Select Date and Time': 'Zeit und Datum Auswählen',
			'Select Time': 'Zeit Auswählen',
			'Open calendar': 'Kalender öffnen'
		}
	}	
};

Control.DatePickerPanel = Class.create();
Object.extend(Control.DatePickerPanel.prototype, {
	initialize: function(options) {
		this.i18n = new Control.DatePicker.i18n(options && options.locale ? options.locale : 'en_US');
		options = this.i18n.inheritOptions(options);
		this.options = Object.extend({
						className: 'datepickerControl',
						closeOnToday: true,
						selectToday: true,
						showOnFocus: false,
						datePicker: true,
						timePicker: false,
						use24hrs: false,
						firstWeekDay: 0,
						weekend: [0,6],
						months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
						days: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']
					}, options || {});
		// Make sure first weekday is in the correct range
		with (this.options)
			if (isNaN(firstWeekDay*1)) firstWeekDay = 0;
			else firstWeekDay = firstWeekDay % 7;

		this.keysCaptured = false;
		this.calendarCont = null;
		this.currentDate = this.options.date ? this.options.date : new Date();
		this.dayOfWeek = 0;
		this.minInterval = 5;

		this.selectedDay = null;
		this.selectedHour = null;
		this.selectedMinute = null;
		this.selectedAmPm = null;

		this.currentDays = [];
		this.hourCells = [];
		this.minuteCells = [];
		this.otherMinutes = null;
		this.amCell = null;
		this.pmCell = null;

		this.element = this.createPicker();
		this.selectDate(this.currentDate);
	},
	createPicker: function() {
		var elt = document.createElement('div');
		elt.style.position = 'absolute';
		elt.className = this.options.className;
		this.calendarCont = this.drawCalendar(elt, this.currentDate);

		Event.observe(elt, 'click', this.clickHandler.bindAsEventListener(this));
		Event.observe(elt, 'dblclick', this.dblClickHandler.bindAsEventListener(this));
		this.documentKeyListener = this.keyHandler.bindAsEventListener(this);
		if (this.options.captureKeys)
			this.captureKeys();
		
		return elt;
	},
	tr: function(str) {
		return this.i18n.tr(str);
	},
	captureKeys: function() {
		Event.observe(document, 'keydown', this.documentKeyListener, true);
		this.keysCaptured = true;
	},
	releaseKeys: function() {
		Event.stopObserving(document, 'keydown', this.documentKeyListener, true);
		this.keysCaptured = false;
	},
	setDate: function(date) {
		if (date) {
			// Clear container
			while (this.element.firstChild)
				this.element.removeChild(this.element.firstChild);
			this.calendarCont = this.drawCalendar(this.element, date);
		}
	},
	drawCalendar: function(container, date) {
		var calCont = container;
		if (!this.options.datePicker) {
			var calTable =  document.createElement('table');
			calTable.cellSpacing = 0;
			calTable.cellPadding = 0;
			calTable.border = 0;
		} else {
			var calTable = this.createCalendar(date);
		}

		var rowwidth = this.options.use24hrs ? 6 : 7;
		if (this.options.timePicker) {
			var timeTable;
			if (this.options.timePickerAdjacent && this.options.datePicker) {
				var rows = 0;

				var adjTable = document.createElement('table');
				adjTable.cellSpacing = 0;
				adjTable.cellPadding = 0;
				adjTable.border = 0;
				
				row = adjTable.insertRow(0);

				cell = row.insertCell(0);
				cell.vAlign = 'top';
				cell.appendChild(calTable);
				calCont = cell;

				cell = row.insertCell(1);
				cell.style.width = '5px';

				cell = row.insertCell(2);
				cell.vAlign = 'top';
				timeTable = document.createElement('table');
				timeTable.cellSpacing = 0;
				timeTable.cellPadding = 0;
				timeTable.border = 0;
				cell.appendChild(timeTable);

				container.appendChild(adjTable);

				row = timeTable.insertRow(rows++);
				row.className = 'monthLabel';
				cell = row.insertCell(0);
				cell.colSpan = rowwidth;
				cell.innerHTML = this.tr('Time');

				row = timeTable.insertRow(rows++);
				cell = row.insertCell(0);
				cell.colSpan = rowwidth;
				cell.style.height = '1px';

			} else {
				container.appendChild(calTable);
				timeTable = calTable;
				var rows = calTable.rows.length;

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


		row = calTable.insertRow(rows++);
		row.className = 'monthLabel';
		cell = row.insertCell(0);
		cell.colSpan = 7;
		cell.innerHTML = this.monthName(date.getMonth()) + ' ' + date.getFullYear();

		row = calTable.insertRow(rows++);
		row.className = 'navigation';

		cell = row.insertCell(0);
		cell.className = 'navbutton';
		cell.title = this.monthName(previousYear.getMonth()) + ' ' + previousYear.getFullYear();
		cell.onclick = this.movePreviousYearListener();
		cell.innerHTML = '<<';

		cell = row.insertCell(1);
		cell.className = 'navbutton';
		cell.title = this.monthName(previousMonth.getMonth()) + ' ' + previousMonth.getFullYear();
		cell.onclick = this.movePreviousMonthListener();
		cell.innerHTML = '<';

		cell = row.insertCell(2);
		cell.colSpan = 3;
		cell.className = 'navbutton';
		cell.title = today.getDate() + ' ' + this.monthName(today.getMonth()) + ' ' + today.getFullYear();
		cell.onclick = this.dateClickedListener(today, true);
		if (this.options.timePicker)
			cell.innerHTML = this.tr('Now');
		else
			cell.innerHTML = this.tr('Today');

		cell = row.insertCell(3);
		cell.className = 'navbutton';
		cell.title = this.monthName(nextMonth.getMonth()) + ' ' + nextMonth.getFullYear();
		cell.onclick = this.moveNextMonthListener();
		cell.innerHTML = '>';

		cell = row.insertCell(4);
		cell.className = 'navbutton';
		cell.title = this.monthName(nextYear.getMonth()) + ' ' + nextYear.getFullYear();
		cell.onclick = this.moveNextYearListener();
		cell.innerHTML = '>>';

		row = calTable.insertRow(rows++);
		row.className = 'dayLabel';
		for (var i = 0; i < 7; ++i){
			cell = row.insertCell(i);
			cell.width = '14%';
			cell.innerHTML = this.dayName((this.options.firstWeekDay + i) % 7);
		}
		
		row = null;
		var workDate = new Date(date.getFullYear(), date.getMonth(), 1);
		var day = workDate.getDay();
		var j = 0;

		// Pad with previous month
		if (day != this.options.firstWeekDay) {
			row = calTable.insertRow(rows++);
			row.className = 'calendarRow';
			workDate.setDate(workDate.getDate() - ((day - this.options.firstWeekDay + 7) % 7));
			day = workDate.getDay();
			while (workDate.getMonth() != date.getMonth()) {
				cell = row.insertCell(row.cells.length);
				this.assignDayClasses(cell, 'dayothermonth', workDate);
				cell.innerHTML = workDate.getDate();
				cell.onclick = this.dateClickedListener(workDate);
				workDate.setDate(workDate.getDate() + 1);
				day = workDate.getDay();
			}
		}

		// Display days
		while (workDate.getMonth() == date.getMonth()) {
			if (day == this.options.firstWeekDay) {
				row = calTable.insertRow(rows++);
				row.className = 'calendarRow';
			}
			cell = row.insertCell(row.cells.length);
			this.assignDayClasses(cell, 'day', workDate);
			cell.innerHTML = workDate.getDate();
			cell.onclick = this.dateClickedListener(workDate);
			this.currentDays[workDate.getDate()] = cell;
			workDate.setDate(workDate.getDate() + 1);
			day = workDate.getDay();
		}

		// Pad with next month
		if (day != this.options.firstWeekDay)
			do {
				cell = row.insertCell(row.cells.length);
				this.assignDayClasses(cell, 'dayothermonth', workDate);
				cell.innerHTML = workDate.getDate();
				var thisDate = new Date(workDate.getTime());
				cell.onclick = this.dateClickedListener(workDate);
				workDate.setDate(workDate.getDate() + 1);
				day = workDate.getDay();
			} while (workDate.getDay() != this.options.firstWeekDay);

		return calTable;
	},
	movePreviousMonthListener: function() {
		return function(e) {
				var prevMonth = new Date(
						this.currentDate.getFullYear(),
						this.currentDate.getMonth() - 1,
						this.currentDate.getDate(),
						this.currentDate.getHours(),
						this.currentDate.getMinutes());
				if (prevMonth.getMonth() != (this.currentDate.getMonth() + 11) % 12) prevMonth.setDate(0);
				this.selectDate(prevMonth);
			}.bindAsEventListener(this);
	},
	moveNextMonthListener: function() {
		return function(e) {
				var nextMonth = new Date(
						this.currentDate.getFullYear(),
						this.currentDate.getMonth() + 1,
						this.currentDate.getDate(),
						this.currentDate.getHours(),
						this.currentDate.getMinutes());
				if (nextMonth.getMonth() != (this.currentDate.getMonth() + 1) % 12) nextMonth.setDate(0);
				this.selectDate(nextMonth);
			}.bindAsEventListener(this);
	},
	moveNextYearListener: function() {
		return function(e) {
				var nextYear = new Date(
						this.currentDate.getFullYear() + 1,
						this.currentDate.getMonth(),
						this.currentDate.getDate(),
						this.currentDate.getHours(),
						this.currentDate.getMinutes());
				if (nextYear.getMonth() != this.currentDate.getMonth()) nextYear.setDate(0);
				this.selectDate(nextYear);
			}.bindAsEventListener(this);
	},



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