netteForms.js a validace RadioListu

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
chloris
Člen | 23
+
0
-

Zdravím vás,

narazil jsem na zjevně chybné chování v netteForms.js spojené s validací RadioListu.
Mám formulář, v něm mám RadioList ve kterém je pouze jedno radio.
Je to výběr z několika provedení produktů, kde někdy zkrátka může být k dispozici pouze jedna varianta.

Mám na to navěšené validační pravidlo pro povinný výběr.

$form->addRadioList('provedeni', 'Provedení', $provedeniItems)->setDefaultValue($default)
          ->addRule(Form::FILLED, 'Zvolte si provedení produktu');

Pokud nechám validaci v javascriptu proběhnout a je tam více než 1 provedení (více než jeden radio button), tak vše zafunguje správně. Pokud ovšem je dostupný pouze jeden radio button, validace selže js chybou „Uncaught RangeError: Maximum call stack size exceeded“.

Celý zakopaný pes je v netteForms zde (viz komentáře v kódu):

Nette.getValue = function(elem) {
	var i, len;
	if (!elem) {
		return null;

	// TADY BY MĚLA PODMÍNKA VYHOVĚT A VRÁTIT HODNOTU RADIA ...
	} else if (!elem.nodeName) { // radio
		for (i = 0, len = elem.length; i < len; i++) {
			if (elem[i].checked) {
				return elem[i].value;
			}
		}
		return null;

	} else if (elem.nodeName.toLowerCase() === 'select') {
		var index = elem.selectedIndex, options = elem.options;

		if (index < 0) {
			return null;

		} else if (elem.type === 'select-one') {
			return options[index].value;
		}

		for (i = 0, values = [], len = options.length; i < len; i++) {
			if (options[i].selected) {
				values.push(options[i].value);
			}
		}
		return values;

	} else if (elem.type === 'checkbox') {
		return elem.checked;

	} else if (elem.type === 'radio') {
		// ... MÍSTO TOHO SPADNE AŽ SEM A VOLÁ SAMA SEBE REKURZIVNĚ POŘÁD DOKOLA
		return Nette.getValue(elem.form.elements[elem.name]);

	} else {
		return elem.value.replace(/^\s+|\s+$/g, '');
	}
};

Problém je v tom, že je-li tam pouze jedno radio, tak elem.nodeName je nastaveno.

chloris
Člen | 23
+
0
-

Navrhuji následující fix:

Nette.getValue = function(elem) {
	var i, len;
	if (!elem) {
		return null;

	} else if (!elem.nodeName) { // radio
		for (i = 0, len = elem.length; i < len; i++) {
			if (elem[i].checked) {
				return elem[i].value;
			}
		}
		return null;

	} else if (elem.nodeName.toLowerCase() === 'select') {
		var index = elem.selectedIndex, options = elem.options;

		if (index < 0) {
			return null;

		} else if (elem.type === 'select-one') {
			return options[index].value;
		}

		for (i = 0, values = [], len = options.length; i < len; i++) {
			if (options[i].selected) {
				values.push(options[i].value);
			}
		}
		return values;

	} else if (elem.type === 'checkbox') {
		return elem.checked;

	} else if (elem.type === 'radio') {
		var radio = elem.form.elements[elem.name];
		if(!radio.length) radio = [radio];
		return Nette.getValue(radio);

	} else {
		return elem.value.replace(/^\s+|\s+$/g, '');
	}
};
David Grudl
Nette Core | 8147
+
0
-

fixed