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 http://nettephp.com
13: * @copyright Copyright (c) 2004, 2009 David Grudl
14: * @license http://nettephp.com/license Nette license
15: * @link http://nettephp.com
17: * @package Nette\Forms
22: require_once dirname(__FILE__) .
'/../../Object.php';
27: * Instant validation JavaScript generator.
29: * @author David Grudl
30: * @copyright Copyright (c) 2004, 2009 David Grudl
31: * @package Nette\Forms
35: /** @var string JavaScript event handler name */
38: /** @var string JavaScript event handler name */
41: /** @var string JavaScript code */
42: public $doAlert =
'if (element) element.focus(); alert(message);';
44: /** @var string JavaScript code */
45: public $doToggle =
'if (element) element.style.display = visible ? "" : "none";';
64: $name =
ucfirst($form->getName()); //ucfirst(strtr($form->getUniqueId(), Form::NAME_SEPARATOR, '_'));
75: $this->central =
TRUE;
77: foreach ($this->form->getControls() as $control) {
78: $script =
$this->getValidateScript($control->getRules());
85: $this->central =
FALSE;
90: if ($this->central) {
94: foreach ($this->form->getComponents(TRUE, 'Nette\Forms\ISubmitterControl') as $control) {
95: if ($control->getValidationScope()) {
106: * Generates the client side validation script.
115: .
"var element, message, res;\n\t"
123: .
"var element, visible, res;\n\t"
130: return "<script type=\"text/javascript\">\n"
131: .
"/* <![CDATA[ */\n"
140: private function getValidateScript(Rules $rules, $onlyCheck =
FALSE)
143: foreach ($rules as $rule) {
146: if (strcasecmp($rule->operation, 'Nette\Forms\InstantClientScript::javascript') ===
0) {
147: $res .=
"$rule->arg\n\t";
151: $script =
$this->getClientScript($rule->control, $rule->operation, $rule->arg);
152: if (!$script) continue;
154: if (!empty($rule->message)) { // this is rule
156: $res .=
"$script\n\tif (" .
($rule->isNegative ?
'' :
'!') .
"res) { return false; }\n\t";
159: $res .=
"$script\n\t"
160: .
"if (" .
($rule->isNegative ?
'' :
'!') .
"res) { "
161: .
"message = " .
json_encode((string)
vsprintf($rule->control->translate($rule->message), (array)
$rule->arg)) .
"; "
163: .
" return false; }\n\t";
167: if ($rule->type ===
Rule::CONDITION) { // this is condition
168: $innerScript =
$this->getValidateScript($rule->subRules, $onlyCheck);
170: $res .=
"$script\n\tif (" .
($rule->isNegative ?
'!' :
'') .
"res) {\n\t\t" .
str_replace("\n\t", "\n\t\t", rtrim($innerScript)) .
"\n\t}\n\t";
172: $this->central =
FALSE;
182: private function getToggleScript(Rules $rules, $cond =
NULL)
185: foreach ($rules->getToggles() as $id =>
$visible) {
186: $s .=
"visible = true; {$cond}element = document.getElementById('" .
$id .
"');\n\t"
187: .
($visible ?
'' :
'visible = !visible; ')
191: foreach ($rules as $rule) {
193: $script =
$this->getClientScript($rule->control, $rule->operation, $rule->arg);
195: $res =
$this->getToggleScript($rule->subRules, $cond .
"$script visible = visible && " .
($rule->isNegative ?
'!' :
'') .
"res;\n\t");
197: $el =
$rule->control->getControlPrototype();
198: if ($el->getName() ===
'select') {
202: //$el->onkeyup("$this->toggleFunction(this)", TRUE);
214: private function getValueScript(IFormControl $control)
216: $tmp =
"element = document.getElementById(" .
json_encode($control->getHtmlId()) .
");\n\t";
219: return $tmp .
"var val = element.checked;\n\t";
222: return "for (var val=null, i=0; i<" .
count($control->getItems()) .
"; i++) {\n\t\t"
223: .
"element = document.getElementById(" .
json_encode($control->getHtmlId() .
'-') .
"+i);\n\t\t"
224: .
"if (element.checked) { val = element.value; break; }\n\t"
228: return $tmp .
"var val = element.value.replace(/^\\s+|\\s+\$/g, '');\n\t";
234: private function getClientScript(IFormControl $control, $operation, $arg)
241: case $operation ===
':filled' &&
$control instanceof
RadioList:
242: return $this->getValueScript($control) .
"res = val !== null;";
245: return "element=null; res=sender && sender.name==" .
json_encode($control->getHtmlName()) .
";";
249: foreach ((is_array($arg) ?
$arg :
array($arg)) as $item) {
252: $first =
$control->isFirstSkipped() ?
1 :
0;
253: return "element = document.getElementById(" .
json_encode($control->getHtmlId()) .
");\n\tres = false;\n\t"
254: .
"for (var i=$first;i<element.options.length;i++)\n\t\t"
255: .
"if (element.options[i].selected && (" .
implode(' || ', $tmp) .
")) { res = true; break; }";
257: case $operation ===
':filled' &&
$control instanceof
SelectBox:
258: return "element = document.getElementById(" .
json_encode($control->getHtmlId()) .
");\n\t"
259: .
"res = element.selectedIndex >= " .
($control->isFirstSkipped() ?
1 :
0) .
";";
261: case $operation ===
':filled' &&
$control instanceof
TextBase:
262: return $this->getValueScript($control) .
"res = val!='' && val!=" .
json_encode((string)
$control->getEmptyValue()) .
";";
264: case $operation ===
':minlength' &&
$control instanceof
TextBase:
265: return $this->getValueScript($control) .
"res = val.length>=" . (int)
$arg .
";";
267: case $operation ===
':maxlength' &&
$control instanceof
TextBase:
268: return $this->getValueScript($control) .
"res = val.length<=" . (int)
$arg .
";";
270: case $operation ===
':length' &&
$control instanceof
TextBase:
272: $arg =
array($arg, $arg);
274: return $this->getValueScript($control) .
"res = " .
($arg[0] ===
NULL ?
"true" :
"val.length>=" . (int)
$arg[0]) .
" && "
275: .
($arg[1] ===
NULL ?
"true" :
"val.length<=" . (int)
$arg[1]) .
";";
277: case $operation ===
':email' &&
$control instanceof
TextBase:
278: return $this->getValueScript($control) .
'res = /^[^@\s]+@[^@\s]+\.[a-z]{2,10}$/i.test(val);';
280: case $operation ===
':url' &&
$control instanceof
TextBase:
281: return $this->getValueScript($control) .
'res = /^.+\.[a-z]{2,6}(\\/.*)?$/i.test(val);';
283: case $operation ===
':regexp' &&
$control instanceof
TextBase:
287: return $this->getValueScript($control) .
"res = $arg.test(val);";
289: case $operation ===
':integer' &&
$control instanceof
TextBase:
290: return $this->getValueScript($control) .
"res = /^-?[0-9]+$/.test(val);";
292: case $operation ===
':float' &&
$control instanceof
TextBase:
293: return $this->getValueScript($control) .
"res = /^-?[0-9]*[.,]?[0-9]+$/.test(val);";
295: case $operation ===
':range' &&
$control instanceof
TextBase:
296: return $this->getValueScript($control) .
"res = " .
($arg[0] ===
NULL ?
"true" :
"parseFloat(val)>=" .
json_encode((float)
$arg[0])) .
" && "
297: .
($arg[1] ===
NULL ?
"true" :
"parseFloat(val)<=" .
json_encode((float)
$arg[1])) .
";";
300: return $this->getValueScript($control) .
"res = val!='';";
303: return $this->getValueScript($control) .
"res = function(){\n\t" .
$this->getValidateScript($control->getRules(), TRUE) .
"return true; }();";
308: foreach ((is_array($arg) ?
$arg :
array($arg)) as $item) {
310: $tmp[] =
"val==function(){var element;" .
$this->getValueScript($item).
"return val;}()";
315: return $this->getValueScript($control) .
"res = (" .
implode(' || ', $tmp) .
");";