1: <?php
2:
3: /**
4: * This file is part of the Nette Framework (http://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\Controls
11: */
12:
13:
14:
15: /**
16: * Select box control that allows single item selection.
17: *
18: * @author David Grudl
19: *
20: * @property-read mixed $rawValue
21: * @property bool $prompt
22: * @property array $items
23: * @property-read string $selectedItem
24: * @package Nette\Forms\Controls
25: */
26: class NSelectBox extends NFormControl
27: {
28: /** @var array */
29: private $items = array();
30:
31: /** @var array */
32: protected $allowed = array();
33:
34: /** @var bool */
35: private $prompt = FALSE;
36:
37: /** @var bool */
38: private $useKeys = TRUE;
39:
40:
41:
42: /**
43: * @param string label
44: * @param array items from which to choose
45: * @param int number of rows that should be visible
46: */
47: public function __construct($label = NULL, array $items = NULL, $size = NULL)
48: {
49: parent::__construct($label);
50: $this->control->setName('select');
51: $this->control->size = $size > 1 ? (int) $size : NULL;
52: if ($items !== NULL) {
53: $this->setItems($items);
54: }
55: }
56:
57:
58:
59: /**
60: * Returns selected item key.
61: * @return mixed
62: */
63: public function getValue()
64: {
65: $allowed = $this->allowed;
66: if ($this->prompt) {
67: $allowed = array_slice($allowed, 1, count($allowed), TRUE);
68: }
69:
70: return is_scalar($this->value) && isset($allowed[$this->value]) ? $this->value : NULL;
71: }
72:
73:
74:
75: /**
76: * Returns selected item key (not checked).
77: * @return mixed
78: */
79: public function getRawValue()
80: {
81: return is_scalar($this->value) ? $this->value : NULL;
82: }
83:
84:
85:
86: /**
87: * Has been any item selected?
88: * @return bool
89: */
90: public function isFilled()
91: {
92: $value = $this->getValue();
93: return is_array($value) ? count($value) > 0 : $value !== NULL;
94: }
95:
96:
97:
98: /**
99: * Ignores the first item in select box.
100: * @param string
101: * @return NSelectBox provides a fluent interface
102: */
103: public function setPrompt($prompt)
104: {
105: if (is_bool($prompt)) {
106: $this->prompt = $prompt;
107: } else {
108: $this->prompt = TRUE;
109: if ($prompt !== NULL) {
110: $this->items = array('' => $prompt) + $this->items;
111: $this->allowed = array('' => '') + $this->allowed;
112: }
113: }
114: return $this;
115: }
116:
117:
118:
119: /** @deprecated */
120: function skipFirst($v = NULL)
121: {
122: trigger_error(__METHOD__ . '() is deprecated; use setPrompt() instead.', E_USER_WARNING);
123: return $this->setPrompt($v);
124: }
125:
126:
127:
128: /**
129: * Is first item in select box ignored?
130: * @return bool
131: */
132: final public function getPrompt()
133: {
134: return $this->prompt;
135: }
136:
137:
138:
139: /**
140: * Are the keys used?
141: * @return bool
142: */
143: final public function areKeysUsed()
144: {
145: return $this->useKeys;
146: }
147:
148:
149:
150: /**
151: * Sets items from which to choose.
152: * @param array
153: * @return NSelectBox provides a fluent interface
154: */
155: public function setItems(array $items, $useKeys = TRUE)
156: {
157: $this->items = $items;
158: $this->allowed = array();
159: $this->useKeys = (bool) $useKeys;
160:
161: foreach ($items as $key => $value) {
162: if (!is_array($value)) {
163: $value = array($key => $value);
164: }
165:
166: foreach ($value as $key2 => $value2) {
167: if (!$this->useKeys) {
168: if (!is_scalar($value2)) {
169: throw new InvalidArgumentException("All items must be scalar.");
170: }
171: $key2 = $value2;
172: }
173:
174: if (isset($this->allowed[$key2])) {
175: throw new InvalidArgumentException("Items contain duplication for key '$key2'.");
176: }
177:
178: $this->allowed[$key2] = $value2;
179: }
180: }
181: return $this;
182: }
183:
184:
185:
186: /**
187: * Returns items from which to choose.
188: * @return array
189: */
190: final public function getItems()
191: {
192: return $this->items;
193: }
194:
195:
196:
197: /**
198: * Returns selected value.
199: * @return string
200: */
201: public function getSelectedItem()
202: {
203: if (!$this->useKeys) {
204: return $this->getValue();
205:
206: } else {
207: $value = $this->getValue();
208: return $value === NULL ? NULL : $this->allowed[$value];
209: }
210: }
211:
212:
213:
214: /**
215: * Generates control's HTML element.
216: * @return NHtml
217: */
218: public function getControl()
219: {
220: $control = parent::getControl();
221: if ($this->prompt) {
222: reset($this->items);
223: $control->data('nette-empty-value', $this->useKeys ? key($this->items) : current($this->items));
224: }
225: $selected = $this->getValue();
226: $selected = is_array($selected) ? array_flip($selected) : array($selected => TRUE);
227: $option = NHtml::el('option');
228:
229: foreach ($this->items as $key => $value) {
230: if (!is_array($value)) {
231: $value = array($key => $value);
232: $dest = $control;
233:
234: } else {
235: $dest = $control->create('optgroup')->label($this->translate($key));
236: }
237:
238: foreach ($value as $key2 => $value2) {
239: if ($value2 instanceof NHtml) {
240: $dest->add((string) $value2->selected(isset($selected[$key2])));
241:
242: } else {
243: $key2 = $this->useKeys ? $key2 : $value2;
244: $value2 = $this->translate((string) $value2);
245: $dest->add((string) $option->value($key2)
246: ->selected(isset($selected[$key2]))
247: ->setText($value2));
248: }
249: }
250: }
251: return $control;
252: }
253:
254: }
255: