Source for file InstantClientScript.php
Documentation is available at InstantClientScript.php
6: * Copyright (c) 2004, 2009 David Grudl (http://davidgrudl.com)
8: * This source file is subject to the "Nette license" that is bundled
9: * with this package in the file license.txt.
11: * For more information please see https://nette.org
13: * @copyright Copyright (c) 2004, 2009 David Grudl
14: * @license https://nette.org/license Nette license
15: * @link https://nette.org
17: * @package Nette\Forms
23: require_once dirname(__FILE__) .
'/../../Object.php';
28: * Instant validation JavaScript generator.
30: * @author David Grudl
31: * @copyright Copyright (c) 2004, 2009 David Grudl
32: * @package Nette\Forms
36: /** @var string JavaScript event handler name */
39: /** @var string JavaScript event handler name */
42: /** @var string JavaScript code */
43: public $doAlert =
'if (element) element.focus(); alert(message);';
45: /** @var string JavaScript code */
46: public $doToggle =
'if (element) element.style.display = visible ? "" : "none";';
65: $name =
ucfirst($form->getName()); //ucfirst(strtr($form->getUniqueId(), Form::NAME_SEPARATOR, '_'));
76: $this->central =
TRUE;
78: foreach ($this->form->getControls() as $control) {
79: $script =
$this->getValidateScript($control->getRules());
86: $this->central =
FALSE;
91: if ($this->central) {
95: foreach ($this->form->getComponents(TRUE, 'Nette\Forms\ISubmitterControl') as $control) {
96: if ($control->getValidationScope()) {
107: * Generates the client side validation script.
116: .
"var element, message, res;\n\t"
124: .
"var element, visible, res;\n\t"
131: return "<script type=\"text/javascript\">\n"
132: .
"/* <![CDATA[ */\n"
141: private function getValidateScript(Rules $rules, $onlyCheck =
FALSE)
144: foreach ($rules as $rule) {
147: if (strcasecmp($rule->operation, 'Nette\Forms\InstantClientScript::javascript') ===
0) {
148: $res .=
"$rule->arg\n\t";
152: $script =
$this->getClientScript($rule->control, $rule->operation, $rule->arg);
153: if (!$script) continue;
155: if (!empty($rule->message)) { // this is rule
157: $res .=
"$script\n\tif (" .
($rule->isNegative ?
'' :
'!') .
"res) { return false; }\n\t";
160: $res .=
"$script\n\t"
161: .
"if (" .
($rule->isNegative ?
'' :
'!') .
"res) { "
162: .
"message = " .
json_encode((string)
vsprintf($rule->control->translate($rule->message), (array)
$rule->arg)) .
"; "
164: .
" return false; }\n\t";
168: if ($rule->type ===
Rule::CONDITION) { // this is condition
169: $innerScript =
$this->getValidateScript($rule->subRules, $onlyCheck);
171: $res .=
"$script\n\tif (" .
($rule->isNegative ?
'!' :
'') .
"res) {\n\t\t" .
str_replace("\n\t", "\n\t\t", rtrim($innerScript)) .
"\n\t}\n\t";
173: $this->central =
FALSE;
183: private function getToggleScript(Rules $rules, $cond =
NULL)
186: foreach ($rules->getToggles() as $id =>
$visible) {
187: $s .=
"visible = true; {$cond}element = document.getElementById('" .
$id .
"');\n\t"
188: .
($visible ?
'' :
'visible = !visible; ')
192: foreach ($rules as $rule) {
194: $script =
$this->getClientScript($rule->control, $rule->operation, $rule->arg);
196: $res =
$this->getToggleScript($rule->subRules, $cond .
"$script visible = visible && " .
($rule->isNegative ?
'!' :
'') .
"res;\n\t");
198: $el =
$rule->control->getControlPrototype();
199: if ($el->getName() ===
'select') {
203: //$el->onkeyup("$this->toggleFunction(this)", TRUE);
215: private function getValueScript(IFormControl $control)
217: $tmp =
"element = document.getElementById(" .
json_encode($control->getHtmlId()) .
");\n\t";
220: return $tmp .
"var val = element.checked;\n\t";
223: return "for (var val=null, i=0; i<" .
count($control->getItems()) .
"; i++) {\n\t\t"
224: .
"element = document.getElementById(" .
json_encode($control->getHtmlId() .
'-') .
"+i);\n\t\t"
225: .
"if (element.checked) { val = element.value; break; }\n\t"
229: return $tmp .
"var val = element.value.replace(/^\\s+|\\s+\$/g, '');\n\t";
235: private function getClientScript(IFormControl $control, $operation, $arg)
242: case $operation ===
':filled' &&
$control instanceof
RadioList:
243: return $this->getValueScript($control) .
"res = val !== null;";
246: return "element=null; res=sender && sender.name==" .
json_encode($control->getHtmlName()) .
";";
250: foreach ((is_array($arg) ?
$arg :
array($arg)) as $item) {
253: $first =
$control->isFirstSkipped() ?
1 :
0;
254: return "element = document.getElementById(" .
json_encode($control->getHtmlId()) .
");\n\tres = false;\n\t"
255: .
"for (var i=$first;i<element.options.length;i++)\n\t\t"
256: .
"if (element.options[i].selected && (" .
implode(' || ', $tmp) .
")) { res = true; break; }";
258: case $operation ===
':filled' &&
$control instanceof
SelectBox:
259: return "element = document.getElementById(" .
json_encode($control->getHtmlId()) .
");\n\t"
260: .
"res = element.selectedIndex >= " .
($control->isFirstSkipped() ?
1 :
0) .
";";
262: case $operation ===
':filled' &&
$control instanceof
TextInput:
263: return $this->getValueScript($control) .
"res = val!='' && val!=" .
json_encode((string)
$control->getEmptyValue()) .
";";
265: case $operation ===
':minlength' &&
$control instanceof
TextBase:
266: return $this->getValueScript($control) .
"res = val.length>=" . (int)
$arg .
";";
268: case $operation ===
':maxlength' &&
$control instanceof
TextBase:
269: return $this->getValueScript($control) .
"res = val.length<=" . (int)
$arg .
";";
271: case $operation ===
':length' &&
$control instanceof
TextBase:
273: $arg =
array($arg, $arg);
275: return $this->getValueScript($control) .
"res = " .
($arg[0] ===
NULL ?
"true" :
"val.length>=" . (int)
$arg[0]) .
" && "
276: .
($arg[1] ===
NULL ?
"true" :
"val.length<=" . (int)
$arg[1]) .
";";
278: case $operation ===
':email' &&
$control instanceof
TextBase:
279: return $this->getValueScript($control) .
'res = /^[^@]+@[^@]+\.[a-z]{2,6}$/i.test(val);';
281: case $operation ===
':url' &&
$control instanceof
TextBase:
282: return $this->getValueScript($control) .
'res = /^.+\.[a-z]{2,6}(\\/.*)?$/i.test(val);';
284: case $operation ===
':regexp' &&
$control instanceof
TextBase:
288: return $this->getValueScript($control) .
"res = $arg.test(val);";
290: case $operation ===
':integer' &&
$control instanceof
TextBase:
291: return $this->getValueScript($control) .
"res = /^-?[0-9]+$/.test(val);";
293: case $operation ===
':float' &&
$control instanceof
TextBase:
294: return $this->getValueScript($control) .
"res = /^-?[0-9]*[.,]?[0-9]+$/.test(val);";
296: case $operation ===
':range' &&
$control instanceof
TextBase:
297: return $this->getValueScript($control) .
"res = " .
($arg[0] ===
NULL ?
"true" :
"parseFloat(val)>=" .
json_encode((float)
$arg[0])) .
" && "
298: .
($arg[1] ===
NULL ?
"true" :
"parseFloat(val)<=" .
json_encode((float)
$arg[1])) .
";";
301: return $this->getValueScript($control) .
"res = val!='';";
304: return $this->getValueScript($control) .
"res = function(){\n\t" .
$this->getValidateScript($control->getRules(), TRUE) .
"return true; }();";
309: foreach ((is_array($arg) ?
$arg :
array($arg)) as $item) {
311: $tmp[] =
"val==function(){var element;" .
$this->getValueScript($item).
"return val;}()";
316: return $this->getValueScript($control) .
"res = (" .
implode(' || ', $tmp) .
");";