Nette Framework Forms, year 2006
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// history of Nette Framework Forms, year 2006 | |
class NHtml | |
{ | |
static protected $empty = array('img'=>1,'hr'=>1,'br'=>1,'input'=>1,'meta'=>1,'area'=>1,'base'=>1,'col'=>1,'link'=>1,'param'=>1); | |
static public function tag($tag, $attrs=NULL, $content=NULL) | |
{ | |
self::openTag($tag, $attrs); | |
if (!isset(self::$empty[$tag])) { | |
echo $content, '</', $tag, '>'; | |
} | |
} | |
static public function openTag($tag, $attrs=NULL) | |
{ | |
echo '<', $tag; | |
if (is_array($attrs)) { | |
foreach ($attrs as $k => $v) | |
if ($v !== NULL) echo ' ', $k, '="', htmlSpecialChars((string) $v), '"'; | |
} | |
echo isset(self::$empty[$tag]) ? ' />' : '>'; | |
} | |
static public function closeTag($tag) | |
{ | |
echo '</' . $tag . '>'; | |
} | |
} | |
abstract class NFormControl | |
{ | |
protected $name; | |
protected $label; | |
protected $attrs; | |
protected $value; | |
protected $required; | |
protected $rules = array(); | |
protected $errors = array(); | |
public function __construct($name, $label) | |
{ | |
$this->name = $name; | |
$this->label = $label; | |
$this->attrs['name'] = $this->name; | |
$this->attrs['id'] = 'frm-' . $this->name; | |
} | |
abstract public function setValue($value); | |
public function getValue() | |
{ | |
return $this->value; | |
} | |
public function setAttribute($name, $value) | |
{ | |
$this->attrs[$name] = $value; | |
} | |
public function setDisabled($value=TRUE) | |
{ | |
$attrs['disabled'] = $value ? 'disabled' : NULL; | |
} | |
abstract public function renderControl(); | |
public function renderLabel() | |
{ | |
NHtml::tag( | |
'label', | |
array('for' => $this->attrs['id']), | |
htmlSpecialChars($this->label) | |
); | |
} | |
public function addRule($message, $type, $arg) | |
{ | |
$this->rules[] = array($message, $type, $arg); | |
} | |
protected function checkOnServer($type, $arg) | |
{} | |
protected function checkOnClient($type, $arg) | |
{} | |
public function validate() | |
{ | |
$this->errors = array(); | |
foreach ($this->rules as $rule) | |
{ | |
list($message, $type, $arg) = $rule; | |
if (!$this->checkOnServer($type, $arg)) | |
$this->errors[] = vsprintf($message, $arg); | |
} | |
return empty($this->errors); | |
} | |
public function isValid() | |
{ | |
return empty($this->errors); | |
} | |
public function getErrors() | |
{ | |
return $this->errors; | |
} | |
public function validationScript() | |
{ | |
if (!$this->rules) return; | |
echo "var el = f.$this->name;\n"; | |
foreach ($this->rules as $rule) | |
{ | |
list($message, $type, $arg) = $rule; | |
$cond = $this->checkOnClient($type, $arg); | |
if ($cond) { | |
$message = addslashes(vsprintf($message, $arg)); | |
echo " { el.focus(); alert('$message'); return false; }\n"; | |
} | |
} | |
} | |
} | |
class NFormTextControl extends NFormControl | |
{ | |
public function __construct($name, $label, $size, $password) | |
{ | |
parent::__construct($name, $label); | |
$this->attrs['size'] = $size; | |
$this->attrs['type'] = $password ? 'password' : 'text'; | |
} | |
public function setValue($value) | |
{ | |
$this->value = trim($value); | |
} | |
public function renderControl() | |
{ | |
$this->attrs['value'] = (string) $this->value; | |
NHtml::tag('input', $this->attrs); | |
} | |
public function setReadonly($value=TRUE) | |
{ | |
$attrs['readonly'] = $value ? 'readonly' : NULL; | |
} | |
public function addRule($message, $type, $arg) | |
{ | |
switch ($type) { | |
case 'required': | |
$this->required = TRUE; | |
break; | |
case 'length': | |
$this->attrs['maxlength'] = $arg[1]; | |
break; | |
} | |
parent::addRule($message, $type, $arg); | |
} | |
protected function checkOnServer($type, $arg) | |
{ | |
$val = $this->value; | |
switch ($type) { | |
case 'required': | |
return strlen($val) > 1; | |
case 'length': | |
return (strlen($val) >= $arg[0] && strlen($val) <= $arg[1]); | |
case 'email': | |
return preg_match('/^|[^@]+@[^.@]+\..+/', $val); | |
case 'regexp': | |
return preg_match($arg, $val); | |
case 'numeric': | |
return is_numeric($val); | |
case 'range': | |
return is_numeric($val) && $val >= $arg[0] && $val <= $arg[1]; | |
} | |
return parent::checkOnServer($type, $arg); | |
} | |
protected function checkOnClient($type, $arg) | |
{ | |
// trim | |
echo "var val = el.value.replace(/^\\s+/, '').replace(/\\s+\$/, '');\n"; | |
switch ($type) { | |
case 'required': | |
echo "if (val=='')"; | |
return TRUE; | |
case 'length': | |
echo "if (val.length<", (int) $arg[0], " || val.length>", (int) $arg[1], ")"; | |
return TRUE; | |
case 'email': | |
echo 'if (!val.test(/^|[^@]+@[^.@]+\..+/))'; | |
return TRUE; | |
case 'regexp': | |
echo "if (!val.test($arg))"; | |
return TRUE; | |
case 'numeric': | |
echo "if (!val.test(/^-?[0-9]*[.,]?[0-9]+$/))"; | |
return TRUE; | |
case 'range': | |
echo "if (parseFloat(val)<", (int) $arg[0], " || parseFloat(val)>", (int) $arg[1], ")"; | |
return TRUE; | |
} | |
return parent::checkOnClient($type, $arg); | |
} | |
} | |
class NFormTextAreaControl extends NFormTextControl | |
{ | |
public function __construct($name, $label, $cols, $rows) | |
{ | |
NFormControl::__construct($name, $label); | |
$this->attrs['cols'] = $cols; | |
$this->attrs['rows'] = $rows; | |
} | |
public function renderControl() | |
{ | |
NHtml::tag('textarea', $this->attrs, htmlSpecialChars((string) $this->value)); | |
} | |
} | |
class NFormFileControl extends NFormControl | |
{ | |
public function setValue($value) | |
{ | |
// must be array | |
$this->value = $value; | |
} | |
public function renderControl() | |
{ | |
$this->attrs['type'] = 'file'; | |
NHtml::tag('input', $this->attrs); | |
} | |
public function moveUploadedFile($path) | |
{ | |
return move_uploaded_file($this->value['tmp_name'], $path); | |
} | |
protected function checkOnServer($type, $arg) | |
{ | |
switch ($type) { | |
case 'required': | |
// TODO | |
case 'maxfilesize': | |
// TODO! | |
case 'mimetype': | |
// TODO! | |
} | |
return parent::checkOnServer($type, $arg); | |
} | |
} | |
class NFormHiddenControl extends NFormControl | |
{ | |
public function setValue($value) | |
{ | |
$this->value = (string) $value; | |
} | |
public function setDisabled($value=TRUE) | |
{} | |
public function renderControl() | |
{ | |
$this->attrs['value'] = (string) $this->value; | |
$this->attrs['type'] = 'hidden'; | |
NHtml::tag('input', $this->attrs); | |
} | |
public function renderLabel() | |
{} | |
} | |
class NFormButtonControl extends NFormControl | |
{ | |
public function __construct($name, $label, $type) | |
{ | |
parent::__construct($name, $label); | |
$this->attrs['type'] = $type; | |
} | |
public function setValue($value) | |
{} | |
public function renderControl() | |
{ | |
$this->attrs['value'] = $this->label; | |
NHtml::tag('input', $this->attrs); | |
} | |
public function renderLabel() | |
{} | |
} | |
class NFormCheckboxControl extends NFormControl | |
{ | |
public function setValue($value) | |
{ | |
$this->value = (bool) $value; | |
} | |
public function renderControl() | |
{ | |
NHtml::openTag('label', array('for' => $this->attrs['id'])); | |
$this->attrs['type'] = 'checkbox'; | |
$this->attrs['checked'] = $this->value ? 'checked' : NULL; | |
NHtml::tag('input', $this->attrs); | |
echo htmlSpecialChars($this->label); | |
NHtml::closeTag('label'); | |
} | |
public function renderLabel() | |
{} | |
} | |
class NFormRadioControl extends NFormControl | |
{ | |
protected $items; | |
public function __construct($name, $label, $items) | |
{ | |
parent::__construct($name, $label); | |
$this->items = $items; | |
} | |
public function setValue($value) | |
{ | |
$this->value = isset($this->items[$value]) ? $value : NULL; | |
} | |
public function renderControl() | |
{ | |
$attrs = $this->attrs; | |
$id = $attrs['id'] . '-'; | |
$attrs['type'] = 'radio'; | |
foreach ($this->items as $key => $value) { | |
$attrs['id'] = $id . $key; | |
$attrs['value'] = $key; | |
$attrs['checked'] = $this->value == $key ? 'checked' : NULL; | |
NHtml::openTag('label', array('for' => $attrs['id'])); | |
NHtml::tag('input', $attrs); | |
echo htmlSpecialChars($value); | |
NHtml::closeTag('label'); | |
NHtml::tag('br'); | |
} | |
} | |
protected function checkOnServer($type, $arg) | |
{ | |
switch ($type) { | |
case 'required': | |
return $this->value !== NULL; | |
} | |
return parent::checkOnServer($type, $arg); | |
} | |
} | |
class NFormSelectControl extends NFormControl | |
{ | |
protected $items; | |
protected $keys; | |
public function __construct($name, $label, $items, $size, $multiple) | |
{ | |
parent::__construct($name, $label); | |
$this->attrs['size'] = $size; | |
$this->attrs['multiple'] = $multiple ? 'multiple' : NULL; | |
if ($multiple) $this->attrs['name'] .= '[]'; | |
$this->items = $items; | |
$this->keys = array(); | |
foreach ($items as $key => $item) { | |
if (is_array($item)) | |
foreach ($item as $key => $foo) $this->keys[$key] = TRUE; | |
else | |
$this->keys[$key] = TRUE; | |
} | |
} | |
public function setValue($value) | |
{ | |
$this->value = array(); | |
foreach ((array) $value as $val) { | |
if (isset($this->keys[$val])) $this->value[] = $val; | |
} | |
} | |
public function renderControl() | |
{ | |
NHtml::openTag('select', $this->attrs); | |
$attrs = array(); | |
$selected = array_flip($this->value); | |
foreach ($this->items as $key => $value) { | |
$group = is_array($value); | |
if ($group) | |
NHtml::openTag('optgroup', array('label' => $key)); | |
else | |
$value = array($key => $value); | |
foreach ($value as $key2 => $value2) { | |
$attrs['value'] = $key2; | |
$attrs['selected'] = isset($selected[$key2]) ? 'selected' : NULL; | |
NHtml::tag('option', $attrs, htmlSpecialChars($value2)); | |
} | |
if ($group) NHtml::closeTag('optgroup'); | |
} | |
NHtml::closeTag('select'); | |
} | |
protected function checkOnServer($type, $arg) | |
{ | |
switch ($type) { | |
case 'required': | |
return !empty($this->value); | |
} | |
return parent::checkOnServer($type, $arg); | |
} | |
} | |
class NForm | |
{ | |
const POST = 'post'; | |
const GET = 'get'; | |
protected $name; | |
protected $attrs; | |
protected $controls = array(); | |
protected $hasFile = FALSE; | |
protected $hasRules = FALSE; | |
protected $submitValues; | |
protected $submitted; | |
public function __construct($name='', $method = self::POST) | |
{ | |
$this->name = $name; | |
$this->attrs['method'] = $method; | |
$this->attrs['action'] = $_SERVER['PHP_SELF']; | |
if ($method == self::GET) $values = $_GET; | |
else $values = $_POST + $_FILES; | |
$this->submitted = isset($values['_f']) && ($values['_f'] === $name); | |
if ($this->submitted) $this->submitValues = $values; | |
} | |
public function setAction($action) | |
{ | |
$this->attrs['action'] = $action; | |
} | |
protected function add($name, $control) | |
{ | |
if (isset($this->controls[$name])) { | |
throw new Exception("Control '$name' exists yet."); | |
} | |
$this->controls[$name] = $control; | |
if (isset($this->submitValues[$name])) | |
$control->setValue($this->submitValues[$name]); | |
} | |
public function addText($name, $label, $size=NULL) | |
{ | |
return $this->add($name, new NFormTextControl($name, $label, $size, FALSE)); | |
} | |
public function addPassword($name, $label, $size=NULL) | |
{ | |
return $this->add($name, new NFormTextControl($name, $label, $size, TRUE)); | |
} | |
public function addTextArea($name, $label, $cols, $rows) | |
{ | |
return $this->add($name, new NFormTextAreaControl($name, $label, $cols, $rows)); | |
} | |
public function addFile($name, $label) | |
{ | |
$this->hasFile = TRUE; | |
return $this->add($name, new NFormFileControl($name, $label)); | |
} | |
public function addHidden($name) | |
{ | |
return $this->add($name, new NFormHiddenControl($name, NULL)); | |
} | |
public function addCheckbox($name, $label) | |
{ | |
return $this->add($name, new NFormCheckboxControl($name, $label)); | |
} | |
public function addRadio($name, $label, $items) | |
{ | |
return $this->add($name, new NFormRadioControl($name, $label, $items)); | |
} | |
public function addSelect($name, $label, $items, $size=NULL, $multiple=FALSE) | |
{ | |
return $this->add($name, new NFormSelectControl($name, $label, $items, $size, $multiple)); | |
} | |
public function addSubmit($name, $label) | |
{ | |
if (isset($this->submitValues[$name])) | |
$this->submitted = $name; | |
return $this->add($name, new NFormButtonControl($name, $label, 'submit')); | |
} | |
public function addButton($name, $label) | |
{ | |
return $this->add($name, new NFormButtonControl($name, $label, 'button')); | |
} | |
public function addImage($name, $src, $alt) | |
{ | |
if (isset($this->submitValues[$name . '_x'])) | |
$this->submitted = $name; | |
$c = new NFormButtonControl($name, NULL, 'image'); | |
$c->setAttribute('src', $src); | |
$c->setAttribute('alt', $alt); | |
return $this->add($name, $c); | |
} | |
public function getControl($name) | |
{ | |
return $this->controls[$name]; | |
} | |
public function setDefaults($values) | |
{ | |
foreach ($values as $name => $value) | |
if (isset($this->controls[$name])) | |
$this->controls[$name]->setValue($value); | |
} | |
public function getValues() | |
{ | |
$values = array(); | |
foreach ($this->controls as $name => $control) | |
$values[$name] = $control->getValue(); | |
return $values; | |
} | |
public function addRule($name, $message, $type, $arg=NULL) | |
{ | |
$this->hasRules = TRUE; | |
$this->controls[$name]->addRule($message, $type, $arg); | |
} | |
public function validate() | |
{ | |
$this->errors = array(); | |
foreach ($this->controls as $control) | |
if (!$control->validate()) | |
{ | |
$this->errors = array_merge($this->errors, $control->getErrors()); | |
} | |
return empty($this->errors); | |
} | |
public function getErrors() | |
{ | |
return $this->errors; | |
} | |
public function isSubmitted($name=NULL) | |
{ | |
return $name === NULL | |
? (bool) $this->submitted | |
: $this->submitted === $name; | |
} | |
public function renderBegin() | |
{ | |
$this->attrs['onsubmit'] = $this->hasRules ? "return validate$this->name(this)" : NULL; | |
$this->attrs['enctype'] = $this->hasFile ? 'multipart/form-data' : NULL; | |
NHtml::openTag('form', $this->attrs); | |
echo "\n<div>"; | |
NHtml::tag('input', array( | |
'type' => 'hidden', | |
'name' => '_f', | |
'value' => $this->name, | |
)); | |
echo "</div>\n"; | |
} | |
public function renderControl($name) | |
{ | |
$this->controls[$name]->renderControl(); | |
} | |
public function renderLabel($name) | |
{ | |
$this->controls[$name]->renderLabel(); | |
} | |
public function renderForm() | |
{ | |
$this->renderBegin(); | |
if ($this->isSubmitted()) { | |
if (!$this->validate()) { | |
echo "<ul style=\"color:red\">\n"; | |
foreach ($this->getErrors() as $error) | |
echo "\t<li>", htmlSpecialChars($error), "</li>\n"; | |
echo "</ul>\n\n"; | |
} | |
} | |
echo "\n<table>\n"; | |
foreach ($this->controls as $control) { | |
echo "<tr>\n\t<th>"; | |
$control->renderLabel(); | |
echo "</th>\n\t<td>"; | |
$control->renderControl(); | |
echo "</td>\n</tr>\n\n"; | |
} | |
echo "</table>\n"; | |
echo "</form>\n"; | |
echo "<script type=\"text/javascript\">\n"; | |
echo "/* <![CDATA[ */\n"; | |
echo "function validate$this->name(f) {\n"; | |
foreach ($this->controls as $control) | |
$control->validationScript(); | |
echo " return true\n"; | |
echo "}\n"; | |
echo "/* ]]> */\n"; | |
echo "</script>\n"; | |
} | |
} | |
$countries = array( | |
'Europe' => array( | |
'CZ' => 'Czech Republic', | |
'SK' => 'Slovakia', | |
), | |
'US' => 'United States', | |
); | |
$sex = array( | |
'm' => 'male', | |
'f' => 'female', | |
); | |
$form = new NForm('login'); | |
$form->addText('name', 'Name:', 10); | |
$form->addPassword('password', 'Password:', 10); | |
$form->addCheckbox('accept', 'I agree'); | |
$form->addFile('avatar', 'Avatar:'); | |
$form->addHidden('userid'); | |
$form->addSelect('country', 'Country:', $countries); | |
$form->addRadio('sex', 'Gender:', $sex); | |
$form->addTextArea('note', 'Note:', 30, 5); | |
$form->addSubmit('submit', 'Send'); | |
$form->addImage('submit2', 'image.gif', 'alternative text'); | |
$form->addRule('name', 'Enter your name', 'required'); | |
$form->addRule('name', 'The password must have at least 3 characters', 'length', array(3, 20)); | |
$default = array( | |
'accept' => TRUE, | |
'userid' => 12345, | |
'country' => 'CZ', | |
'sex' => 'm', | |
'note' => 'Nette Forms!', | |
); | |
if ($form->isSubmitted()) { | |
echo 'Submitted'; | |
} else { | |
$form->setDefaults($default); | |
} | |
$form->renderForm(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment