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 mixed */
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: return is_scalar($this->value) && isset($this->allowed[$this->value]) ? $this->value : NULL;
66: }
67:
68:
69:
70: /**
71: * Returns selected item key (not checked).
72: * @return mixed
73: */
74: public function getRawValue()
75: {
76: return is_scalar($this->value) ? $this->value : NULL;
77: }
78:
79:
80:
81: /**
82: * Has been any item selected?
83: * @return bool
84: */
85: public function isFilled()
86: {
87: $value = $this->getValue();
88: return is_array($value) ? count($value) > 0 : $value !== NULL;
89: }
90:
91:
92:
93: /**
94: * Sets first prompt item in select box.
95: * @param string
96: * @return NSelectBox provides a fluent interface
97: */
98: public function setPrompt($prompt)
99: {
100: if ($prompt === TRUE) { // back compatibility
101: $prompt = reset($this->items);
102: unset($this->allowed[key($this->items)], $this->items[key($this->items)]);
103: }
104: $this->prompt = $prompt;
105: return $this;
106: }
107:
108:
109:
110: /** @deprecated */
111: function skipFirst($v = NULL)
112: {
113: trigger_error(__METHOD__ . '() is deprecated; use setPrompt() instead.', E_USER_WARNING);
114: return $this->setPrompt($v);
115: }
116:
117:
118:
119: /**
120: * Returns first prompt item?
121: * @return mixed
122: */
123: final public function getPrompt()
124: {
125: return $this->prompt;
126: }
127:
128:
129:
130: /**
131: * Are the keys used?
132: * @return bool
133: */
134: final public function areKeysUsed()
135: {
136: return $this->useKeys;
137: }
138:
139:
140:
141: /**
142: * Sets items from which to choose.
143: * @param array
144: * @param bool
145: * @return NSelectBox provides a fluent interface
146: */
147: public function setItems(array $items, $useKeys = TRUE)
148: {
149: $allowed = array();
150: foreach ($items as $k => $v) {
151: foreach ((is_array($v) ? $v : array($k => $v)) as $key => $value) {
152: if (!$useKeys) {
153: if (!is_scalar($value)) {
154: throw new InvalidArgumentException("All items must be scalar.");
155: }
156: $key = $value;
157: }
158:
159: if (isset($allowed[$key])) {
160: throw new InvalidArgumentException("Items contain duplication for key '$key'.");
161: }
162:
163: $allowed[$key] = $value;
164: }
165: }
166:
167: $this->items = $items;
168: $this->allowed = $allowed;
169: $this->useKeys = (bool) $useKeys;
170: return $this;
171: }
172:
173:
174:
175: /**
176: * Returns items from which to choose.
177: * @return array
178: */
179: final public function getItems()
180: {
181: return $this->items;
182: }
183:
184:
185:
186: /**
187: * Returns selected value.
188: * @return string
189: */
190: public function getSelectedItem()
191: {
192: $value = $this->getValue();
193: return ($this->useKeys && $value !== NULL) ? $this->allowed[$value] : $value;
194: }
195:
196:
197:
198: /**
199: * Generates control's HTML element.
200: * @return NHtml
201: */
202: public function getControl()
203: {
204: $selected = $this->getValue();
205: $selected = is_array($selected) ? array_flip($selected) : array($selected => TRUE);
206: $control = parent::getControl();
207: $option = NHtml::el('option');
208:
209: if ($this->prompt !== FALSE) {
210: $control->add($this->prompt instanceof NHtml
211: ? $this->prompt->value('')
212: : (string) $option->value('')->setText($this->translate((string) $this->prompt))
213: );
214: }
215:
216: foreach ($this->items as $key => $value) {
217: if (!is_array($value)) {
218: $value = array($key => $value);
219: $dest = $control;
220: } else {
221: $dest = $control->create('optgroup')->label($this->translate($key));
222: }
223:
224: foreach ($value as $key2 => $value2) {
225: if ($value2 instanceof NHtml) {
226: $dest->add((string) $value2->selected(isset($selected[$key2])));
227:
228: } else {
229: $key2 = $this->useKeys ? $key2 : $value2;
230: $value2 = $this->translate((string) $value2);
231: $dest->add((string) $option->value($key2)
232: ->selected(isset($selected[$key2]))
233: ->setText($value2));
234: }
235: }
236: }
237: return $control;
238: }
239:
240: }
241: