API Docs for: 1.0.0
Show:

File: src/gallery-querybuilder-daterange/js/daterange.js

/**
 * @module gallery-querybuilder
 * @submodule gallery-querybuilder-daterange
 */

/**********************************************************************
 * Plugin for accepting date/time range.
 * 
 * The `value` argument passed to `QueryBuilder.appendNew()` must be an
 * array with two elements: `[ start_date, end_date ]`.
 * 
 * `var_config` accepts `show_time`, `start_config`, `end_config`.  The
 * configs must define objects: `Calendar`, `InputCalendarSync`,
 * `DateTime`, `date_InputPopup`, `time_InputPopup`.
 * 
 * `op_list` must be an array: `[ greater_than, less_than ]`.
 * 
 * @namespace QueryBuilder
 * @class DateRange
 */

Y.QueryBuilder.DateRange = function(
	/* object */	query_builder,
	/* object */	config)
{
	this.qb = query_builder;

	this.start_date_input_name_pattern = config.field_prefix + 'start_date_{i}';
	this.start_time_input_name_pattern = config.field_prefix + 'start_time_{i}';
	this.end_date_input_name_pattern   = config.field_prefix + 'end_date_{i}';
	this.end_time_input_name_pattern   = config.field_prefix + 'end_time_{i}';
};

Y.QueryBuilder.DateRange.prototype =
{
	create: function(
		/* int */		query_index,
		/* object */	var_config,
		/* array */		op_list,
		/* array */		value)
	{
		this.db_query_gt = op_list[0];
		this.db_query_lt = op_list[1];

		this.start_id  = Y.guid();
		this.end_id    = Y.guid();
		this.show_time = var_config.show_time;

		var result    = [],
			separator = ' — ';

		var start_date_cell = this.qb._createContainer();
		start_date_cell.set('className', this.qb.getClassName('start-date'));
		start_date_cell.set('innerHTML',
			this._dateInput(this.start_id, this.dateName('start', query_index)) +
			(var_config.show_time ? '' : separator));
		this.start_date_input = start_date_cell.one('input');
		result.push(start_date_cell);

		if (this.show_time)
		{
			var start_time_cell = this.qb._createContainer();
			start_time_cell.set('className', this.qb.getClassName('start-time'));
			start_time_cell.set('innerHTML',
				this._timeInput(this.start_id, this.timeName('start', query_index)) +
				separator);
			this.start_time_input = start_time_cell.one('input');
			result.push(start_time_cell);
		}

		var end_date_cell = this.qb._createContainer();
		end_date_cell.set('className', this.qb.getClassName('end-date'));
		end_date_cell.set('innerHTML', this._dateInput(this.end_id, this.dateName('end', query_index)));
		this.end_date_input = end_date_cell.one('input');
		result.push(end_date_cell);

		if (this.show_time)
		{
			var end_time_cell = this.qb._createContainer();
			end_time_cell.set('className', this.qb.getClassName('end-time'));
			end_time_cell.set('innerHTML', this._timeInput(this.end_id, this.timeName('end', query_index)));
			this.end_time_input = end_time_cell.one('input');
			result.push(end_time_cell);
		}

		return result;
	},

	postCreate: function(
		/* int */		query_index,
		/* object */	var_config,
		/* array */		op_list,
		/* array */		value)
	{
		value = value || ['', ''];

		if (value[0])
		{
			Y.namespace.call(var_config, 'start_config.DateTime');
			var_config.start_config.DateTime.defaultDateTime = value[0];
		}
		this.start_widgets = this._attachDateTimeWidgets(this.start_id, var_config.start_config);
		if (value[0])
		{
			delete var_config.start_config.DateTime.defaultDateTime;
		}

		if (value[1])
		{
			Y.namespace.call(var_config, 'end_config.DateTime');
			var_config.end_config.DateTime.defaultDateTime = value[1];
		}
		this.end_widgets = this._attachDateTimeWidgets(this.end_id, var_config.end_config);
		if (value[1])
		{
			delete var_config.end_config.DateTime.defaultDateTime;
		}

		this.range = new Y.DateTimeRange(
		{
			startDateTime: this.start_widgets.datetime,
			endDateTime:   this.end_widgets.datetime
		});

		this.start_date_input.focus();

		this.start_date_input.on('valueSet', this.qb._notifyChanged, this.qb);
		this.end_date_input.on('valueSet', this.qb._notifyChanged, this.qb);

		if (this.show_time)
		{
			this.start_time_input.on('valueSet', this.qb._notifyChanged, this.qb);
			this.end_time_input.on('valueSet', this.qb._notifyChanged, this.qb);
		}
	},

	destroy: function()
	{
		this._destroyDateTimeWidgets(this.start_widgets, this.start_date_input);
		this._destroyDateTimeWidgets(this.end_widgets, this.end_date_input);

		this.start_date_input.remove(true);
		this.end_date_input.remove(true);
		if (this.show_time)
		{
			this.start_time_input.remove(true);
			this.end_time_input.remove(true);
		}

		this.start_date_input = null;
	},

	updateName: function(
		/* int */	new_index)
	{
		this.start_date_input.setAttribute('name', this.dateName('start', new_index));
		this.end_date_input.setAttribute('name', this.dateName('end', new_index));
		if (this.show_time)
		{
			this.start_time_input.setAttribute('name', this.timeName('start', new_index));
			this.end_time_input.setAttribute('name', this.timeName('end', new_index));
		}
	},

	toDatabaseQuery: function()
	{
		var start  = this.start_widgets.datetime.getDateTime(),
			end    = this.end_widgets.datetime.getDateTime(),
			result = [];

		if (start)
		{
			result.push([ this.db_query_gt, start ]);
		}

		if (end)
		{
			result.push([ this.db_query_lt, end ]);
		}

		return result;
	},

	_attachDateTimeWidgets: function(id, config)
	{
		config = config || {};

		var selector = '#' + id;

		// Calendar

		var c = config.Calendar || {};
		if (Y.Lang.isUndefined(c.width))
		{
			c.width = 300;
		}
		c.showPrevMonth = c.showNextMonth = true;

		var cal = new Y.Calendar(c);
		cal.render(selector + '-calendar');

		// InputCalendarSync

		c          = config.InputCalendarSync || {};
		c.calendar = cal;

		Y.one(selector + '-date').plug(Y.Plugin.InputCalendarSync, c);	// must be before Y.DateTime

		// Timepicker

		if (this.show_time)
		{
			var tp = new Y.Saw.Timepicker();
			tp.render(selector + '-timepicker');

			tp.on('cellclick', function()
			{
				Y.later(100, null, function()
				{
					Y.one(selector + '-time').set('value', tp.get('time').s24hour);
				});
			});
		}

		// DateTime

		c          = config.DateTime || {};
		c.dateInput = selector + '-date';

		if (this.show_time)
		{
			c.timeInput = selector + '-time';
		}

		var dt = new Y.DateTime(c);

		// date InputPopup

		c                = config.date_InputPopup || {};
		c.srcNode        = selector + '-popup-calendar';
		c.visible        = false;
		c.inputField     = selector + '-date',
		c.clickNodes     = Y.InputPopup.CalendarNodes,
		c.reparentToBody = true;

		if (Y.Lang.isUndefined(c.zIndex))
		{
			c.zIndex = 100;
		}

		var cal_popup = new Y.InputPopup(c);
		cal_popup.render();

		if (this.show_time)
		{
			c                = config.time_InputPopup || {};
			c.srcNode        = selector + '-popup-timepicker';
			c.visible        = false;
			c.inputField     = selector + '-time',
			c.clickNodes     = Y.InputPopup.SawTimepickerNodes,
			c.reparentToBody = true;

			if (Y.Lang.isUndefined(c.zIndex))
			{
				c.zIndex = 100;
			}

			var tp_popup = new Y.InputPopup(c);
			tp_popup.render();
		}

		var result =
		{
			calendar:         cal,
			timepicker:       tp,
			datetime:         dt,
			calendar_popup:   cal_popup,
			timepicker_popup: tp_popup
		};
		return result;
	},

	_destroyDateTimeWidgets: function(obj, input)
	{
		input.unplug(Y.Plugin.InputCalendarSync);

		obj.calendar.destroy();
		obj.datetime.destroy();
		obj.calendar_popup.destroy();

		if (this.show_time)
		{
			obj.timepicker.destroy();
			obj.timepicker_popup.destroy();
		}
	},

	/* *********************************************************************
	 * Form element names.
	 */

	dateName: function(
		/* string */	type,
		/* int */		i)
	{
		return Y.Lang.sub(this[ type + '_date_input_name_pattern' ], {i:i});
	},

	timeName: function(
		/* string */	type,
		/* int */		i)
	{
		return Y.Lang.sub(this[ type + '_time_input_name_pattern' ], {i:i});
	},

	//
	// Markup
	//

	_dateInput: function(
		/* string */ id,
		/* string */ input_name)
	{
		// This must use an input tag!

		var markup =
			'<input type="text" name="{n}" id="{id}-date" class="{f} {c} date"/>' +
			'<div id="{id}-popup-calendar" class="yui3-inputpopup-loading">' +
				'<div id="{id}-calendar"></div>' +
			'</div>';

		return Y.Lang.sub(markup,
		{
			id: id,
			n:  input_name,
			f:  Y.FormManager.field_marker_class,
			c:  this.qb.getClassName('field')
		});
	},

	_timeInput: function(
		/* string */ id,
		/* string */ input_name)
	{
		// This must use an input tag!

		var markup =
			'<input type="text" name="{n}" id="{id}-time" class="{f} {c} time"/>' +
			'<div id="{id}-popup-timepicker" class="popup-timepicker yui3-inputpopup-loading">' +
				'<div id="{id}-timepicker"></div>' +
			'</div>';

		return Y.Lang.sub(markup,
		{
			id: id,
			n:  input_name,
			f:  Y.FormManager.field_marker_class,
			c:  this.qb.getClassName('field')
		});
	}
};

Y.QueryBuilder.plugin_mapping[ 'daterange' ] = Y.QueryBuilder.DateRange;