Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing JS init example #3

Open
repli2dev opened this issue Dec 27, 2020 · 1 comment
Open

Missing JS init example #3

repli2dev opened this issue Dec 27, 2020 · 1 comment

Comments

@repli2dev
Copy link

In README nor in examples there is a note how make this work on client side (ie. nextras.netteForms.js and nextras.datetimepicker.init.js)

@jtojnar
Copy link

jtojnar commented Dec 11, 2021

The input[type="date"] is widely supported by browsers these day so nextras.datetimepicker.init.js should not be necessary. nextras.netteForms.js was used for dealing with MultiOptionList, which was removed in nextras/forms 2.0.0.


AutoComplete is demonstrated in examples.

As for the DateControl validation, the following seems to work:

/**
 * Converts a JSON object produced by calling json_encode
 * on PHP’s DateTime object into a JavaScript’s Date object.
 * For simplicity, it is assumed the DateTime’s timezone
 * matches the local timezone of the user agent.
 */
function fromPhpDateTime(datetime, isDate = false) {
	const parsed = datetime.date.match(/^(?<year>-?[0-9]+)-(?<month>[0-9]{2})-(?<day>[0-9]{2}) (?<hour>[0-9]{2}):(?<min>[0-9]{2}):(?<sec>[0-9]{2})\.(?<msec>[0-9]+)$/);

	let yearString = parsed.groups.year;
	const year = parseInt(yearString, 10);
	if (!(0 <= year && year <= 9999)) {
		// PHP uses four digits for negative years, whereas JavaScript
		// requires six digits and explicit sign:
		// https://tc39.es/ecma262/#sec-expanded-years
		const sign = year < 0 ? '-' : '+';
		yearString = sign + String(Math.abs(year)).padStart(6, '0');
	}

	if (isDate) {
		// When PHP’s DateTime object is converted to JSON, it will contain
		// a date field formatted like 2012-06-23 00:00:00.000000.
		// That will be interpreted as a time in local timezone by JavaScript’s Date.
		// But the value of the input[type="date"] will be something like 2012-06-23,
		// which Date will interpret as UTC time.
		// To make them comparable without having to handle timezones,
		// let’s use just the date part of the datetime string.
		return new Date(`${yearString}-${parsed.groups.month}-${parsed.groups.day}`);
	} else {
		return new Date(`${yearString}-${parsed.groups.month}-${parsed.groups.day} ${parsed.groups.hour}:${parsed.groups.min}:${parsed.groups.sec}.${parsed.groups.msec}`);
	}
}

const originalMinValidator = Nette.validators.min;
Nette.validators.min = function(elem, arg, val) {
	if (elem.type === 'date' || elem.type === 'datetime-local') {
		if (elem.validity.rangeUnderflow) {
			return false;
		} else if (elem.validity.badInput) {
			return null;
		}
		return arg === null || new Date(val) >= fromPhpDateTime(arg, elem.type === 'date');
	}
	return originalMinValidator(elem, arg, val);
};

const originalMaxValidator = Nette.validators.max;
Nette.validators.max = function(elem, arg, val) {
	if (elem.type === 'date' || elem.type === 'datetime-local') {
		if (elem.validity.rangeOverflow) {
			return false;
		} else if (elem.validity.badInput) {
			return null;
		}
		return arg === null || new Date(val) <= fromPhpDateTime(arg, elem.type === 'date');
	}
	return originalMaxValidator(elem, arg, val);
};

const originalRangeValidator = Nette.validators.range;
Nette.validators.range = function(elem, arg, val) {
	if (elem.type === 'date' || elem.type === 'datetime-local') {
		if (elem.validity.rangeUnderflow || elem.validity.rangeOverflow) {
			return false;
		} else if (elem.validity.badInput) {
			return null;
		}
		return Array.isArray(arg) ?
			((arg[0] === null || new Date(val) >= fromPhpDateTime(arg[0], elem.type === 'date')) && (arg[1] === null || new Date(val) <= fromPhpDateTime(arg[1], elem.type === 'date'))) : null;
	}
	return originalRangeValidator(elem, arg, val);
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants