Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

first commit

  • Loading branch information...
commit 71582a48fee3079640127d22d033a4a2814345e1 0 parents
Jan Dolecek authored

Showing 2 changed files with 283 additions and 0 deletions. Show diff stats Hide diff stats

  1. +251 0 DatePicker.php
  2. +32 0 composer.json
251 DatePicker.php
... ... @@ -0,0 +1,251 @@
  1 +<?php
  2 +/**
  3 + * Addons and code snippets for Nette Framework. (unofficial)
  4 + *
  5 + * @author Jan Tvrdík
  6 + * @license MIT
  7 + */
  8 +
  9 +namespace JanTvrdik\Components;
  10 +
  11 +use Nette;
  12 +use Nette\Forms;
  13 +use DateTime;
  14 +
  15 +/**
  16 + * Form control for selecting date.
  17 + *
  18 + * – compatible with jQuery UI DatePicker and HTML 5
  19 + * – works with DateTime
  20 + *
  21 + * @author Jan Tvrdík
  22 + * @version 2.3
  23 + * @link http://nette.merxes.cz/date-picker/
  24 + */
  25 +class DatePicker extends Forms\Controls\BaseControl
  26 +{
  27 + /** @link http://dev.w3.org/html5/spec/common-microsyntaxes.html#valid-date-string */
  28 + const W3C_DATE_FORMAT = 'Y-m-d';
  29 +
  30 + /** @var DateTime|NULL internal date reprezentation */
  31 + protected $value;
  32 +
  33 + /** @var string value entered by user (unfiltered) */
  34 + protected $rawValue;
  35 +
  36 + /** @var string class name */
  37 + private $className = 'date';
  38 +
  39 +
  40 +
  41 + /**
  42 + * Class constructor.
  43 + *
  44 + * @author Jan Tvrdík
  45 + * @param string label
  46 + */
  47 + public function __construct($label = NULL)
  48 + {
  49 + parent::__construct($label);
  50 + $this->control->type = 'date';
  51 + }
  52 +
  53 +
  54 +
  55 + /**
  56 + * Returns class name.
  57 + *
  58 + * @author Jan Tvrdík
  59 + * @return string
  60 + */
  61 + public function getClassName()
  62 + {
  63 + return $this->className;
  64 + }
  65 +
  66 +
  67 +
  68 + /**
  69 + * Sets class name for input element.
  70 + *
  71 + * @author Jan Tvrdík
  72 + * @param string
  73 + * @return self
  74 + */
  75 + public function setClassName($className)
  76 + {
  77 + $this->className = $className;
  78 + return $this;
  79 + }
  80 +
  81 +
  82 +
  83 + /**
  84 + * Generates control's HTML element.
  85 + *
  86 + * @author Jan Tvrdík
  87 + * @return Nette\Utils\Html
  88 + */
  89 + public function getControl()
  90 + {
  91 + $control = parent::getControl();
  92 + $control->addClass($this->className);
  93 + list($min, $max) = $this->extractRangeRule($this->getRules());
  94 + if ($min !== NULL) $control->min = $min->format(self::W3C_DATE_FORMAT);
  95 + if ($max !== NULL) $control->max = $max->format(self::W3C_DATE_FORMAT);
  96 + if ($this->value) $control->value = $this->value->format(self::W3C_DATE_FORMAT);
  97 + return $control;
  98 + }
  99 +
  100 +
  101 +
  102 + /**
  103 + * Sets DatePicker value.
  104 + *
  105 + * @author Jan Tvrdík
  106 + * @param DateTime|int|string
  107 + * @return self
  108 + */
  109 + public function setValue($value)
  110 + {
  111 + if ($value instanceof DateTime) {
  112 +
  113 + } elseif (is_int($value)) { // timestamp
  114 +
  115 + } elseif (empty($value)) {
  116 + $rawValue = $value;
  117 + $value = NULL;
  118 +
  119 + } elseif (is_string($value)) {
  120 + $rawValue = $value;
  121 +
  122 + if (preg_match('#^(?P<dd>\d{1,2})[. -] *(?P<mm>\d{1,2})([. -] *(?P<yyyy>\d{4})?)?$#', $value, $matches)) {
  123 + $dd = $matches['dd'];
  124 + $mm = $matches['mm'];
  125 + $yyyy = isset($matches['yyyy']) ? $matches['yyyy'] : date('Y');
  126 +
  127 + if (checkdate($mm, $dd, $yyyy)) {
  128 + $value = "$yyyy-$mm-$dd";
  129 + } else {
  130 + $value = NULL;
  131 + }
  132 + }
  133 +
  134 + } else {
  135 + throw new \InvalidArgumentException();
  136 + }
  137 +
  138 + if ($value !== NULL) {
  139 + // DateTime constructor throws Exception when invalid input given
  140 + try {
  141 + $value = Nette\DateTime::from($value); // clone DateTime when given
  142 + } catch (\Exception $e) {
  143 + $value = NULL;
  144 + }
  145 + }
  146 +
  147 + if (!isset($rawValue) && isset($value)) {
  148 + $rawValue = $value->format(self::W3C_DATE_FORMAT);
  149 + }
  150 +
  151 + $this->value = $value;
  152 + $this->rawValue = $rawValue;
  153 +
  154 + return $this;
  155 + }
  156 +
  157 +
  158 +
  159 + /**
  160 + * Returns unfiltered value.
  161 + *
  162 + * @author Jan Tvrdík
  163 + * @return string
  164 + */
  165 + public function getRawValue()
  166 + {
  167 + return $this->rawValue;
  168 + }
  169 +
  170 +
  171 +
  172 + /**
  173 + * Does user enter anything? (the value doesn't have to be valid)
  174 + *
  175 + * @author Jan Tvrdík
  176 + * @param DatePicker
  177 + * @return bool
  178 + */
  179 + public static function validateFilled(Forms\IControl $control)
  180 + {
  181 + if (!$control instanceof self) throw new Nette\InvalidStateException('Unable to validate ' . get_class($control) . ' instance.');
  182 + $rawValue = $control->rawValue;
  183 + return !empty($rawValue);
  184 + }
  185 +
  186 +
  187 +
  188 + /**
  189 + * Is entered value valid? (empty value is also valid!)
  190 + *
  191 + * @author Jan Tvrdík
  192 + * @param DatePicker
  193 + * @return bool
  194 + */
  195 + public static function validateValid(Forms\IControl $control)
  196 + {
  197 + if (!$control instanceof self) throw new Nette\InvalidStateException('Unable to validate ' . get_class($control) . ' instance.');
  198 + $value = $control->value;
  199 + return (empty($control->rawValue) || $value instanceof DateTime);
  200 + }
  201 +
  202 +
  203 +
  204 + /**
  205 + * Is entered values within allowed range?
  206 + *
  207 + * @author Jan Tvrdík, David Grudl
  208 + * @param DatePicker
  209 + * @param array 0 => minDate, 1 => maxDate
  210 + * @return bool
  211 + */
  212 + public static function validateRange(Forms\IControl $control, $range)
  213 + {
  214 + return Nette\Utils\Validators::isInRange($control->getValue(), $range);
  215 + }
  216 +
  217 +
  218 +
  219 + /**
  220 + * Finds minimum and maximum allowed dates.
  221 + *
  222 + * @author Jan Tvrdík
  223 + * @param Forms\Rules
  224 + * @return array 0 => DateTime|NULL $minDate, 1 => DateTime|NULL $maxDate
  225 + */
  226 + private function extractRangeRule(Forms\Rules $rules)
  227 + {
  228 + $controlMin = $controlMax = NULL;
  229 + foreach ($rules as $rule) {
  230 + if ($rule->type === Forms\Rule::VALIDATOR) {
  231 + if ($rule->operation === Forms\Form::RANGE && !$rule->isNegative) {
  232 + $ruleMinMax = $rule->arg;
  233 + }
  234 +
  235 + } elseif ($rule->type === Forms\Rule::CONDITION) {
  236 + if ($rule->operation === Forms\Form::FILLED && !$rule->isNegative && $rule->control === $this) {
  237 + $ruleMinMax = $this->extractRangeRule($rule->subRules);
  238 + }
  239 + }
  240 +
  241 + if (isset($ruleMinMax)) {
  242 + list($ruleMin, $ruleMax) = $ruleMinMax;
  243 + if ($ruleMin !== NULL && ($controlMin === NULL || $ruleMin > $controlMin)) $controlMin = $ruleMin;
  244 + if ($ruleMax !== NULL && ($controlMax === NULL || $ruleMax < $controlMax)) $controlMax = $ruleMax;
  245 + $ruleMinMax = NULL;
  246 + }
  247 + }
  248 + return array($controlMin, $controlMax);
  249 + }
  250 +
  251 +}
32 composer.json
... ... @@ -0,0 +1,32 @@
  1 +{
  2 + "name": "juzna/nette-date-picker",
  3 + "description": "Date input",
  4 + "keywords": ["input", "date", "forms", "nette"],
  5 + "homepage": "http://nette.merxes.cz/date-picker",
  6 + "license": "BSD-3",
  7 + "authors": [
  8 + {
  9 + "name": "Jan Tvrdík"
  10 + },
  11 + {
  12 + "name": "Jan Dolecek",
  13 + "email": "juzna.cz@gmail.com"
  14 + }
  15 + ],
  16 + "autoload": {
  17 + "classmap": [ "DatePicker.php" ]
  18 + },
  19 + "require": {
  20 + "nette/nette": "2.0.*"
  21 + },
  22 + "extra": {
  23 + "nette": {
  24 + "assets": {
  25 +
  26 + },
  27 + "assets-optional": {
  28 +
  29 + }
  30 + }
  31 + }
  32 +}

0 comments on commit 71582a4

Please sign in to comment.
Something went wrong with that request. Please try again.