Created
September 11, 2011 14:06
-
-
Save jsmitka/1209626 to your computer and use it in GitHub Desktop.
DatePicker pro aktuální Nette - http://nette.merxes.cz/date-picker/
This file contains hidden or 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 | |
/** | |
* Addons and code snippets for Nette Framework. (unofficial) | |
* | |
* @author Jan Tvrdík | |
* @license MIT | |
*/ | |
namespace JanTvrdik\Components; | |
use Nette; | |
use Nette\Forms; | |
use DateTime; | |
/** | |
* Form control for selecting date. | |
* | |
* – compatible with jQuery UI DatePicker and HTML 5 | |
* – works with DateTime | |
* | |
* @author Jan Tvrdík | |
* @version 2.1 | |
* @link http://nette.merxes.cz/date-picker/ | |
*/ | |
class DatePicker extends Forms\Controls\BaseControl | |
{ | |
/** @link http://dev.w3.org/html5/spec/common-microsyntaxes.html#valid-date-string */ | |
const W3C_DATE_FORMAT = 'Y-m-d'; | |
/** @var DateTime|NULL internal date reprezentation */ | |
protected $value; | |
/** @var string value entered by user (unfiltered) */ | |
protected $rawValue; | |
/** @var string class name */ | |
private $className = 'date'; | |
/** | |
* Class constructor. | |
* | |
* @author Jan Tvrdík | |
* @param string label | |
*/ | |
public function __construct($label = NULL) | |
{ | |
parent::__construct($label); | |
$this->control->type = 'date'; | |
} | |
/** | |
* Returns class name. | |
* | |
* @author Jan Tvrdík | |
* @return string | |
*/ | |
public function getClassName() | |
{ | |
return $this->className; | |
} | |
/** | |
* Sets class name for input element. | |
* | |
* @author Jan Tvrdík | |
* @param string | |
* @return self | |
*/ | |
public function setClassName($className) | |
{ | |
$this->className = $className; | |
return $this; | |
} | |
/** | |
* Generates control's HTML element. | |
* | |
* @author Jan Tvrdík | |
* @return Nette\Web\Html | |
*/ | |
public function getControl() | |
{ | |
$control = parent::getControl(); | |
$control->addClass($this->className); | |
list($min, $max) = $this->extractRangeRule($this->getRules()); | |
if ($min !== NULL) $control->min = $min->format(self::W3C_DATE_FORMAT); | |
if ($max !== NULL) $control->max = $max->format(self::W3C_DATE_FORMAT); | |
if ($this->value) $control->value = $this->value->format(self::W3C_DATE_FORMAT); | |
return $control; | |
} | |
/** | |
* Sets DatePicker value. | |
* | |
* @author Jan Tvrdík | |
* @param DateTime|int|string | |
* @return self | |
*/ | |
public function setValue($value) | |
{ | |
if ($value instanceof DateTime) { | |
} elseif (is_int($value)) { // timestamp | |
} elseif (empty($value)) { | |
$rawValue = $value; | |
$value = NULL; | |
} elseif (is_string($value)) { | |
$rawValue = $value; | |
if (preg_match('#^(?P<dd>\d{1,2})[. -] *(?P<mm>\d{1,2})([. -] *(?P<yyyy>\d{4})?)?$#', $value, $matches)) { | |
$dd = $matches['dd']; | |
$mm = $matches['mm']; | |
$yyyy = isset($matches['yyyy']) ? $matches['yyyy'] : date('Y'); | |
if (checkdate($mm, $dd, $yyyy)) { | |
$value = "$yyyy-$mm-$dd"; | |
} else { | |
$value = NULL; | |
} | |
} | |
} else { | |
throw new \InvalidArgumentException(); | |
} | |
if ($value !== NULL) { | |
// DateTime constructor throws Exception when invalid input given | |
try { | |
$value = Nette\DateTime::from($value); // clone DateTime when given | |
} catch (\Exception $e) { | |
$value = NULL; | |
} | |
} | |
if (!isset($rawValue) && isset($value)) { | |
$rawValue = $value->format(self::W3C_DATE_FORMAT); | |
} | |
$this->value = $value; | |
$this->rawValue = $rawValue; | |
return $this; | |
} | |
/** | |
* Returns unfiltered value. | |
* | |
* @author Jan Tvrdík | |
* @return string | |
*/ | |
public function getRawValue() | |
{ | |
return $this->rawValue; | |
} | |
/** | |
* Does user enter anything? (the value doesn't have to be valid) | |
* | |
* @author Jan Tvrdík | |
* @param DatePicker | |
* @return bool | |
*/ | |
public static function validateFilled(Forms\IControl $control) | |
{ | |
if (!$control instanceof self) throw new \InvalidStateException('Unable to validate ' . get_class($control) . ' instance.'); | |
$rawValue = $control->rawValue; | |
return !empty($rawValue); | |
} | |
/** | |
* Is entered value valid? (empty value is also valid!) | |
* | |
* @author Jan Tvrdík | |
* @param DatePicker | |
* @return bool | |
*/ | |
public static function validateValid(Forms\IControl $control) | |
{ | |
if (!$control instanceof self) throw new \InvalidStateException('Unable to validate ' . get_class($control) . ' instance.'); | |
$value = $control->value; | |
return (empty($control->rawValue) || $value instanceof DateTime); | |
} | |
/** | |
* Is entered values within allowed range? | |
* | |
* @author Jan Tvrdík | |
* @param DatePicker | |
* @param array 0 => minDate, 1 => maxDate | |
* @return bool | |
*/ | |
public static function validateRange(self $control, array $range) | |
{ | |
return ($range[0] === NULL || $control->getValue() >= $range[0]) && ($range[1] === NULL || $control->getValue() <= $range[1]); | |
} | |
/** | |
* Finds minimum and maximum allowed dates. | |
* | |
* @author Jan Tvrdík | |
* @param Forms\Rules | |
* @return array 0 => DateTime|NULL $minDate, 1 => DateTime|NULL $maxDate | |
*/ | |
private function extractRangeRule(Forms\Rules $rules) | |
{ | |
$controlMin = $controlMax = NULL; | |
foreach ($rules as $rule) { | |
if ($rule->type === Forms\Rule::VALIDATOR) { | |
if ($rule->operation === Forms\Form::RANGE && !$rule->isNegative) { | |
$ruleMinMax = $rule->arg; | |
} | |
} elseif ($rule->type === Forms\Rule::CONDITION) { | |
if ($rule->operation === Forms\Form::FILLED && !$rule->isNegative && $rule->control === $this) { | |
$ruleMinMax = $this->extractRangeRule($rule->subRules); | |
} | |
} | |
if (isset($ruleMinMax)) { | |
list($ruleMin, $ruleMax) = $ruleMinMax; | |
if ($ruleMin !== NULL && ($controlMin === NULL || $ruleMin > $controlMin)) $controlMin = $ruleMin; | |
if ($ruleMax !== NULL && ($controlMax === NULL || $ruleMax < $controlMax)) $controlMax = $ruleMax; | |
$ruleMinMax = NULL; | |
} | |
} | |
return array($controlMin, $controlMax); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment