Packages

  • Nette
    • Application
    • Caching
    • Collections
    • Config
    • Forms
    • IO
    • Loaders
    • Mail
    • Reflection
    • Security
    • Templates
    • Web
  • None
  • PHP

Classes

  • NButton
  • NCheckbox
  • NConventionalRenderer
  • NFileUpload
  • NForm
  • NFormContainer
  • NFormGroup
  • NHiddenField
  • NImageButton
  • NInstantClientScript
  • NMultiSelectBox
  • NRadioList
  • NRule
  • NRules
  • NSelectBox
  • NSubmitButton
  • NTextArea
  • NTextBase
  • NTextInput

Interfaces

  • IFormControl
  • IFormRenderer
  • INamingContainer
  • ISubmitterControl
  • Overview
  • Package
  • Class
  • Tree
  • Other releases
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://nette.org)
  5:  *
  6:  * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
  7:  *
  8:  * For the full copyright and license information, please view
  9:  * the file license.txt that was distributed with this source code.
 10:  * @package Nette\Forms
 11:  */
 12: 
 13: 
 14: 
 15: /**
 16:  * Instant validation JavaScript generator.
 17:  *
 18:  * @author     David Grudl
 19:  * @package Nette\Forms
 20:  */
 21: final class NInstantClientScript extends NObject
 22: {
 23:     /** @var array */
 24:     private $validateScripts;
 25: 
 26:     /** @var string */
 27:     private $toggleScript;
 28: 
 29:     /** @var bool */
 30:     private $central;
 31: 
 32:     /** @var NForm */
 33:     private $form;
 34: 
 35: 
 36: 
 37:     public function __construct(NForm $form)
 38:     {
 39:         $this->form = $form;
 40:     }
 41: 
 42: 
 43: 
 44:     public function enable()
 45:     {
 46:         $this->validateScripts = array();
 47:         $this->toggleScript = '';
 48:         $this->central = TRUE;
 49: 
 50:         foreach ($this->form->getControls() as $control) {
 51:             $script = $this->getValidateScript($control->getRules());
 52:             if ($script) {
 53:                 $this->validateScripts[$control->getHtmlName()] = $script;
 54:             }
 55:             $this->toggleScript .= $this->getToggleScript($control->getRules());
 56: 
 57:             if ($control instanceof ISubmitterControl && $control->getValidationScope() !== TRUE) {
 58:                 $this->central = FALSE;
 59:             }
 60:         }
 61: 
 62:         if ($this->validateScripts || $this->toggleScript) {
 63:             if ($this->central) {
 64:                 $this->form->getElementPrototype()->onsubmit("return nette.validateForm(this)", TRUE);
 65: 
 66:             } else {
 67:                 foreach ($this->form->getComponents(TRUE, 'ISubmitterControl') as $control) {
 68:                     if ($control->getValidationScope()) {
 69:                         $control->getControlPrototype()->onclick("return nette.validateForm(this)", TRUE);
 70:                     }
 71:                 }
 72:             }
 73:         }
 74:     }
 75: 
 76: 
 77: 
 78:     /**
 79:      * Generates the client side validation script.
 80:      * @return string
 81:      */
 82:     public function renderClientScript()
 83:     {
 84:         if (!$this->validateScripts && !$this->toggleScript) {
 85:             return;
 86:         }
 87: 
 88:         $formName = json_encode((string) $this->form->getElementPrototype()->id);
 89:         ob_start();
 90:         require dirname(__FILE__) . '/InstantClientScript.phtml';
 91:         return ob_get_clean();
 92:     }
 93: 
 94: 
 95: 
 96:     private function getValidateScript(NRules $rules)
 97:     {
 98:         $res = '';
 99:         foreach ($rules as $rule) {
100:             if (!is_string($rule->operation)) continue;
101: 
102:             if (strcasecmp($rule->operation, 'Nette\\Forms\\InstantClientScript::javascript') === 0) {
103:                 $res .= "$rule->arg\n";
104:                 continue;
105:             }
106: 
107:             $script = $this->getClientScript($rule->control, $rule->operation, $rule->arg);
108:             if (!$script) continue;
109: 
110:             if ($rule->type === NRule::VALIDATOR && !empty($rule->message)) {
111:                 $message = NRules::formatMessage($rule, FALSE);
112:                 $res .= "$script\n"
113:                     . "if (" . ($rule->isNegative ? '' : '!') . "res) "
114:                     . "return " . json_encode((string) $message) . (strpos($message, '%value') === FALSE ? '' : ".replace('%value', val);\n") . ";\n";
115: 
116:             } elseif ($rule->type === NRule::CONDITION) {
117:                 $innerScript = $this->getValidateScript($rule->subRules);
118:                 if ($innerScript) {
119:                     $res .= "$script\nif (" . ($rule->isNegative ? '!' : '') . "res) {\n" . NString::indent($innerScript) . "}\n";
120:                     if ($rule->control instanceof ISubmitterControl) {
121:                         $this->central = FALSE;
122:                     }
123:                 }
124:             }
125:         }
126:         return $res;
127:     }
128: 
129: 
130: 
131:     private function getToggleScript(NRules $rules, $cond = NULL)
132:     {
133:         $s = '';
134:         foreach ($rules->getToggles() as $id => $visible) {
135:             $s .= "visible = true; {$cond}\n"
136:                 . "nette.toggle(" . json_encode((string) $id) . ", " . ($visible ? '' : '!') . "visible);\n";
137:         }
138:         $formName = json_encode((string) $this->form->getElementPrototype()->id);
139:         foreach ($rules as $rule) {
140:             if ($rule->type === NRule::CONDITION && is_string($rule->operation)) {
141:                 $script = $this->getClientScript($rule->control, $rule->operation, $rule->arg);
142:                 if ($script) {
143:                     $res = $this->getToggleScript($rule->subRules, $cond . "$script visible = visible && " . ($rule->isNegative ? '!' : '') . "res;\n");
144:                     if ($res) {
145:                         $el = $rule->control->getControlPrototype();
146:                         if ($el->getName() === 'select') {
147:                             $el->onchange("nette.forms[$formName].toggle(this)", TRUE);
148:                         } else {
149:                             $el->onclick("nette.forms[$formName].toggle(this)", TRUE);
150:                             //$el->onkeyup("nette.forms[$formName].toggle(this)", TRUE);
151:                         }
152:                         $s .= $res;
153:                     }
154:                 }
155:             }
156:         }
157:         return $s;
158:     }
159: 
160: 
161: 
162:     private function getClientScript(IFormControl $control, $operation, $arg)
163:     {
164:         $operation = strtolower($operation);
165:         $elem = 'form[' . json_encode($control->getHtmlName()) . ']';
166: 
167:         switch (TRUE) {
168:         case $control instanceof NHiddenField || $control->isDisabled():
169:             return NULL;
170: 
171:         case $operation === ':filled' && $control instanceof NRadioList:
172:             return "res = (val = nette.getValue($elem)) !== null;";
173: 
174:         case $operation === ':submitted' && $control instanceof NSubmitButton:
175:             return "res = sender && sender.name==" . json_encode($control->getHtmlName()) . ";";
176: 
177:         case $operation === ':equal' && $control instanceof NMultiSelectBox:
178:             $tmp = array();
179:             foreach ((is_array($arg) ? $arg : array($arg)) as $item) {
180:                 $tmp[] = "options[i].value==" . json_encode((string) $item);
181:             }
182:             $first = $control->isFirstSkipped() ? 1 : 0;
183:             return "var options = $elem.options; res = false;\n"
184:                 . "for (var i=$first, len=options.length; i<len; i++)\n\t"
185:                 . "if (options[i].selected && (" . implode(' || ', $tmp) . ")) { res = true; break; }";
186: 
187:         case $operation === ':filled' && $control instanceof NSelectBox:
188:             return "res = $elem.selectedIndex >= " . ($control->isFirstSkipped() ? 1 : 0) . ";";
189: 
190:         case $operation === ':filled' && $control instanceof NTextBase:
191:             return "val = nette.getValue($elem); res = val!='' && val!=" . json_encode((string) $control->getEmptyValue()) . ";";
192: 
193:         case $operation === ':minlength' && $control instanceof NTextBase:
194:             return "res = (val = nette.getValue($elem)).length>=" . (int) $arg . ";";
195: 
196:         case $operation === ':maxlength' && $control instanceof NTextBase:
197:             return "res = (val = nette.getValue($elem)).length<=" . (int) $arg . ";";
198: 
199:         case $operation === ':length' && $control instanceof NTextBase:
200:             if (!is_array($arg)) {
201:                 $arg = array($arg, $arg);
202:             }
203:             return "val = nette.getValue($elem); res = " . ($arg[0] === NULL ? "true" : "val.length>=" . (int) $arg[0]) . " && "
204:                 . ($arg[1] === NULL ? "true" : "val.length<=" . (int) $arg[1]) . ";";
205: 
206:         case $operation === ':email' && $control instanceof NTextBase:
207:             return 'res = /^[^@\s]+@[^@\s]+\.[a-z]{2,10}$/i.test(val = nette.getValue('.$elem.'));';
208: 
209:         case $operation === ':url' && $control instanceof NTextBase:
210:             return 'res = /^.+\.[a-z]{2,6}(\\/.*)?$/i.test(val = nette.getValue('.$elem.'));';
211: 
212:         case $operation === ':regexp' && $control instanceof NTextBase:
213:             if (!preg_match('#^(/.*/)([imu]*)$#', $arg, $matches)) {
214:                 return NULL; // regular expression must be JavaScript compatible
215:             }
216:             $arg = $matches[1] . str_replace('u', '', $matches[2]);
217:             return "res = $arg.test(val = nette.getValue($elem));";
218: 
219:         case $operation === ':integer' && $control instanceof NTextBase:
220:             return "res = /^-?[0-9]+$/.test(val = nette.getValue($elem));";
221: 
222:         case $operation === ':float' && $control instanceof NTextBase:
223:             return "res = /^-?[0-9]*[.,]?[0-9]+$/.test(val = nette.getValue($elem));";
224: 
225:         case $operation === ':range' && $control instanceof NTextBase:
226:             return "val = nette.getValue($elem); res = " . ($arg[0] === NULL ? "true" : "parseFloat(val)>=" . json_encode((float) $arg[0])) . " && "
227:                 . ($arg[1] === NULL ? "true" : "parseFloat(val)<=" . json_encode((float) $arg[1])) . ";";
228: 
229:         case $operation === ':filled' && $control instanceof NFormControl:
230:             return "res = (val = nette.getValue($elem)) != '';";
231: 
232:         case $operation === ':valid' && $control instanceof NFormControl:
233:             return "res = !this[" . json_encode($control->getHtmlName()) . "](sender);";
234: 
235:         case $operation === ':equal' && $control instanceof NFormControl:
236:             if ($control instanceof NCheckbox) $arg = (bool) $arg;
237:             $tmp = array();
238:             foreach ((is_array($arg) ? $arg : array($arg)) as $item) {
239:                 if ($item instanceof IFormControl) { // compare with another form control?
240:                     $tmp[] = "val==nette.getValue(form[" . json_encode($item->getHtmlName()) . "])";
241:                 } else {
242:                     $tmp[] = "val==" . json_encode($item);
243:                 }
244:             }
245:             return "val = nette.getValue($elem); res = (" . implode(' || ', $tmp) . ");";
246:         }
247:     }
248: 
249: 
250: 
251:     public static function javascript()
252:     {
253:         return TRUE;
254:     }
255: 
256: }
257: 
Nette Framework 0.9.7 (for PHP 5.2) API documentation generated by ApiGen 2.3.0