-
Notifications
You must be signed in to change notification settings - Fork 48
Expand file tree
/
Copy pathSelect.php
More file actions
400 lines (335 loc) · 16 KB
/
Copy pathSelect.php
File metadata and controls
400 lines (335 loc) · 16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
<?php
/**
* Class for select box controls.
*
* @author Stefan Gabos <contact@stefangabos.ro>
* @copyright (c) 2006 - 2016 Stefan Gabos
* @package Controls
*/
class Zebra_Form_Select extends Zebra_Form_Control
{
/**
* Adds an <select> control to the form.
*
* <b>Do not instantiate this class directly! Use the {@link Zebra_Form::add() add()} method instead!</b>
*
* By default, unless the <b>multiple</b> attribute is set, the control will have a default first option added
* automatically inviting users to select one of the available options. Default value for English is
* "<i>- select -</i>" taken from the language file - see the {@link Zebra_Form::language() language()}
* method. If you don't want it or want to set it at runtime, set the <i>overwrite</i> argument to TRUE when calling
* the {@link add_options()} method.
*
* <code>
* // create a new form
* $form = new Zebra_Form('my_form');
*
* // single-option select box
* $obj = $form->add('select', 'my_select');
*
* // add selectable values with default indexes
* // values will be "0", "1" and "2", respectively
* // a default first value, "- select -" (language dependent) will also be added
* $obj->add_options(array(
* 'Value 1',
* 'Value 2',
* 'Value 3'
* ));
*
* // single-option select box
* $obj = $form->add('select', 'my_select2');
*
* // add selectable values with specific indexes
* // values will be "v1", "v2" and "v3", respectively
* // a default first value, "- select -" (language dependent) will also be added
* $obj->add_options(array(
* 'v1' => 'Value 1',
* 'v2' => 'Value 2',
* 'v3' => 'Value 3'
* ));
*
* // single-option select box with the second value selected
* $obj = $form->add('select', 'my_select3', 'v2');
*
* // add selectable values with specific indexes
* // values will be "v1", "v2" and "v3", respectively
* // also, overwrite the language-specific default first value (notice the boolean TRUE at the end)
* $obj->add_options(array(
* '' => '- select a value -',
* 'v1' => 'Value 1',
* 'v2' => 'Value 2',
* 'v3' => 'Value 3'
* ), true);
*
* // multi-option select box with the first two options selected
* $obj = $form->add('select', 'my_select4[]', array('v1', 'v2'), array('multiple' => 'multiple'));
*
* // add selectable values with specific indexes
* // values will be "v1", "v2" and "v3", respectively
* $obj->add_options(array(
* 'v1' => 'Value 1',
* 'v2' => 'Value 2',
* 'v3' => 'Value 3'
* ));
*
* // don't forget to always call this method before rendering the form
* if ($form->validate()) {
* // put code here
* }
*
* // output the form using an automatically generated template
* $form->render();
* </code>
*
* <samp>By default, for checkboxes, radio buttons and select boxes, the library will prevent the submission of other
* values than those declared when creating the form, by triggering the error: "SPAM attempt detected!". Therefore,
* if you plan on adding/removing values dynamically, from JavaScript, you will have to call the
* {@link Zebra_Form_Control::disable_spam_filter() disable_spam_filter()} method to prevent that from happening!</samp>
*
* @param string $id Unique name to identify the control in the form.
*
* The control's <b>name</b> attribute will be as specified by the <i>$id</i>
* argument.<br>
* The <b>id</b> attribute will be as specified by the <i>$id</i> argument but with
* square brackets trimmed off (if any).
*
* This is the name to be used when referring to the control's value in the
* POST/GET superglobals, after the form is submitted.
*
* This is also the name of the variable (again, with square brackets trimmed off
* if it's the case) to be used in the template file, containing the generated HTML
* for the control.
*
* <code>
* // in a template file, in order to print the generated HTML
* // for a control named "my_select", one would use:
* echo $my_select;
* </code>
*
* @param mixed $default (Optional) Default selected option.
*
* This argument can also be an array in case the <b>multiple</b> attribute is set
* and multiple options need to be preselected by default.
*
* @param array $attributes (Optional) An array of attributes valid for
* {@link http://www.w3.org/TR/REC-html40/interact/forms.html#edef-SELECT select}
* controls (multiple, readonly, style, etc)
*
* Must be specified as an associative array, in the form of <i>attribute => value</i>.
* <code>
* // setting the "multiple" attribute
* $obj = $form->add(
* 'select',
* 'my_select',
* '',
* array(
* 'multiple' => 'multiple'
* )
* );
* </code>
*
* <b>Special attribute:</b>
*
* When setting the special attribute <b>other</b> to <b>true</b>, a
* {@link Zebra_Form_Text textbox} control will be automatically created having the
* name <i>[id]_other</i> where [id] is the select control's <b>id</b> attribute.
* The text box will be hidden until the user selects the automatically added
* <i>Other...</i> option (language dependent) from the selectable options. The
* option's value will be <b>other</b>. If the template is not automatically
* generated you will have to manually add the automatically generated control to
* the template.
*
* See {@link Zebra_Form_Control::set_attributes() set_attributes()} on how to set
* attributes, other than through the constructor.
*
* The following attributes are automatically set when the control is created and
* should not be altered manually:<br>
*
* <b>id</b>, <b>name</b>
*
* @param string $default_other The default value in the "other" field (if the "other" attribute is set to true,
* see above)
*
* @return void
*/
function __construct($id, $default = '', $attributes = '', $default_other = '')
{
// call the constructor of the parent class
parent::__construct();
// set the private attributes of this control
// these attributes are private for this control and are for internal use only
// and will not be rendered by the _render_attributes() method
$this->private_attributes = array(
'default_other',
'disable_spam_filter',
'disable_xss_filters',
'locked',
'options',
'titles',
'other',
'type',
'value',
);
// set the default attributes for the textarea control
// put them in the order you'd like them rendered
$this->set_attributes(
array(
'name' => $id,
'id' => str_replace(array('[', ']'), '', $id),
'class' => 'control',
'options' => array(),
'titles' => array(),
'type' => 'select',
'value' => $default,
'default_other' => $default_other,
)
);
// if "class" is amongst user specified attributes
if (is_array($attributes) && isset($attributes['class'])) {
// we need to set the "class" attribute like this, so it doesn't overwrite previous values
$this->set_attributes(array('class' => $attributes['class']), false);
// make sure we don't set it again below
unset($attributes['class']);
}
// sets user specified attributes for the control
$this->set_attributes($attributes);
}
/**
* Adds options to the select box control
*
* <b>If the "multiple" attribute is not set, the first option will be always considered as the "nothing is selected"
* state of the control!</b>
*
* @param array $options An associative array of options where the key is the value of the option and the
* value is the actual text to be displayed for the option.
*
* <b>Option groups</b> can be set by giving an array of associative arrays as argument:
*
* <code>
* // add as groups:
* $obj->add_options(array(
* 'group' => array('option 1', 'option 2')
* ));
* </code>
*
* @param boolean $overwrite (Optional) By default, succesive calls of this method will appended the options
* given as arguments to the already existing options.
*
* Setting this argument to TRUE will instead overwrite the previously existing options.
*
* Default is FALSE
*
* @return void
*/
function add_options($options, $overwrite = false)
{
// continue only if parameter is an array
if (is_array($options)) {
// get some properties of the select control
$attributes = $this->get_attributes(array('options', 'multiple'));
// if there are no options so far AND
// we're not overwriting existing options AND
// the "multiple" attribute is not set
if (empty($attributes['options']) && $overwrite === false && !isset($attributes['multiple']))
// add the default value
// we'll replace the value with the appropriate language
$options = array('' => $this->form_properties['language']['select']) + $options;
// set the options attribute of the control
$this->set_attributes(
array(
'options' => ($overwrite ? $options : $attributes['options'] + $options)
)
);
// if options are not specified as an array
} else {
// trigger an error message
_zebra_form_show_error('
Selectable values for the <strong>' . $this->attributes['id'] . '</strong> control must be specified as
an array
');
}
}
/**
* Generates the control's HTML code.
*
* <i>This method is automatically called by the {@link Zebra_Form::render() render()} method!</i>
*
* @return string The control's HTML code
*/
function toHTML()
{
// get the options of the select control
$attributes = $this->get_attributes(array('options', 'value' ,'titles', 'multiple', 'other'));
// if select box is not "multi-select" and the "other" attribute is set
if (!isset($attributes['multiple']) && isset($attributes['other']))
// add an extra options to the already existing ones
$attributes['options'] += array('other' => $this->form_properties['language']['other']);
// if the default value, as added when instantiating the object is still there
// or if no options were specified
if (($key = array_search('#replace-with-language#', $attributes['options'])) !== false || empty($attributes['options']))
// put the label from the language file
$attributes['options'][$key] = $this->form_properties['language']['select'];
// use a private, recursive method to generate the select's content
$optContent = $this->_generate($attributes['options'], $attributes['value'], $attributes['titles']);
// return generated HTML
return '<select '. $this->_render_attributes() . '>' . $optContent . '</select>';
}
/**
* Takes the options array and recursively generates options and optiongroups
*
* @return string Resulted HTML code
*
* @access private
*/
private function _generate(&$options, &$selected, &$titles, $level = 0)
{
$content = '';
// character(s) used for indenting levels
$indent = ' ';
// iterate through the available options
foreach ($options as $value => $caption) {
// if option has child options
if (is_array($caption)) {
// create a dummy option group (for valid HTML/XHTML we are not allowed to create nested option groups
// and also empty optiongroups are not allowed)
// BUT because in IE7 the "disabled" attribute is not supported and in all versions of IE these
// can't be styled, we will remove them from JavaScript
// having a dummy option in them (the option is disabled and, from CSS, rendered invisible)
$content .= '
<optgroup label="' . str_repeat($indent, $level) . $value . '">
<option disabled="disabled" class="dummy"></option>
</optgroup>
';
// get titles array for option group, if there is oone
if (is_array($titles) && isset($titles[$value]) && is_array($titles[$value])) {
$sub_titles = $titles[$value];
} else {
$sub_titles = "";
}
// call the method recursively to generate the output for the children options
$content .= $this->_generate($caption, $selected, $sub_titles, $level + 1);
// if entry is a standard option
} else {
// create the appropriate code
$content .= '<option value="' . $value . '"' .
// if anything was selected
($selected !== '' && $value !== '' &&
(
// and the current option is selected
(is_array($selected) && in_array($value, $selected)) ||
(!is_array($selected) && (string)$value === (string)$selected)
// set the appropriate attribute
) ? ' selected="selected"' : ''
) . (
// if any titles provided
(is_array($titles) && isset($titles[$value]))
? ' title="' . $titles[$value] . '"' : ''
) . '>' .
// indent appropriately
str_repeat($indent, $level) . $caption . '</option>';
}
}
// return generated content
return $content;
}
}
?>