Subversion Repositories Applications.papyrus

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
320 jpm 1
<?php
2
/* vim: set expandtab tabstop=4 shiftwidth=4: */
3
// +----------------------------------------------------------------------+
4
// | PHP version 4.0                                                      |
5
// +----------------------------------------------------------------------+
6
// | Copyright (c) 1997-2004 The PHP Group                                |
7
// +----------------------------------------------------------------------+
8
// | This source file is subject to version 2.0 of the PHP license,       |
9
// | that is bundled with this package in the file LICENSE, and is        |
10
// | available at through the world-wide-web at                           |
11
// | http://www.php.net/license/2_02.txt.                                 |
12
// | If you did not receive a copy of the PHP license and are unable to   |
13
// | obtain it through the world-wide-web, please send a note to          |
14
// | license@php.net so we can mail you a copy immediately.               |
15
// +----------------------------------------------------------------------+
16
// | Authors: Herim Vasquez <vasquezh@iro.umontreal.ca>                   |
17
// |          Bertrand Mansion <bmansion@mamasam.com>                     |
18
// +----------------------------------------------------------------------+
19
//
20
// $Id: hierselect.php,v 1.1 2005-03-30 08:50:33 jpm Exp $
21
 
22
require_once('HTML/QuickForm/group.php');
23
require_once('HTML/QuickForm/select.php');
24
 
25
/**
26
 * Class to dynamically create two or more HTML Select elements
27
 * The first select changes the content of the second select and so on.
28
 * This element is considered as a group. Selects will be named
29
 * groupName[0], groupName[1], groupName[2]...
30
 *
31
 * @author       Herim Vasquez <vasquezh@iro.umontreal.ca>
32
 * @author       Bertrand Mansion <bmansion@mamasam.com>
33
 * @version      1.0
34
 * @since        PHP4.04pl1
35
 * @access       public
36
 */
37
class HTML_QuickForm_hierselect extends HTML_QuickForm_group
38
{
39
    // {{{ properties
40
 
41
    /**
42
     * Options for all the select elements
43
     *
44
     * Format is a bit more complex as we need to know which options
45
     * are related to the ones in the previous select:
46
     *
47
     * Ex:
48
     * // first select
49
     * $select1[0] = 'Pop';
50
     * $select1[1] = 'Classical';
51
     * $select1[2] = 'Funeral doom';
52
     *
53
     * // second select
54
     * $select2[0][0] = 'Red Hot Chil Peppers';
55
     * $select2[0][1] = 'The Pixies';
56
     * $select2[1][0] = 'Wagner';
57
     * $select2[1][1] = 'Strauss';
58
     * $select2[2][0] = 'Pantheist';
59
     * $select2[2][1] = 'Skepticism';
60
     *
61
     * // If only need two selects
62
     * //     - and using the depracated functions
63
     * $sel =& $form->addElement('hierselect', 'cds', 'Choose CD:');
64
     * $sel->setMainOptions($select1);
65
     * $sel->setSecOptions($select2);
66
     *
67
     * //     - and using the new setOptions function
68
     * $sel =& $form->addElement('hierselect', 'cds', 'Choose CD:');
69
     * $sel->setOptions(array($select1, $select2));
70
     *
71
     * // If you have a third select with prices for the cds
72
     * $select3[0][0][0] = '15.00$';
73
     * $select3[0][0][1] = '17.00$';
74
     * etc
75
     *
76
     * // You can now use
77
     * $sel =& $form->addElement('hierselect', 'cds', 'Choose CD:');
78
     * $sel->setOptions(array($select1, $select2, $select3));
79
     *
80
     * @var       array
81
     * @access    private
82
     */
83
    var $_options = array();
84
 
85
    /**
86
     * Number of select elements on this group
87
     *
88
     * @var       int
89
     * @access    private
90
     */
91
    var $_nbElements = 0;
92
 
93
    /**
94
     * The javascript used to set and change the options
95
     *
96
     * @var       string
97
     * @access    private
98
     */
99
    var $_js = '';
100
 
101
    /**
102
    * The javascript array name
103
    */
104
    var $_jsArrayName = '';
105
 
106
    // }}}
107
    // {{{ constructor
108
 
109
    /**
110
     * Class constructor
111
     *
112
     * @param     string    $elementName    (optional)Input field name attribute
113
     * @param     string    $elementLabel   (optional)Input field label in form
114
     * @param     mixed     $attributes     (optional)Either a typical HTML attribute string
115
     *                                      or an associative array. Date format is passed along the attributes.
116
     * @param     mixed     $separator      (optional)Use a string for one separator,
117
     *                                      use an array to alternate the separators.
118
     * @access    public
119
     * @return    void
120
     */
121
    function HTML_QuickForm_hierselect($elementName=null, $elementLabel=null, $attributes=null, $separator=null)
122
    {
123
        $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes);
124
        $this->_persistantFreeze = true;
125
        if (isset($separator)) {
126
            $this->_separator = $separator;
127
        }
128
        $this->_type = 'hierselect';
129
        $this->_appendName = true;
130
    } //end constructor
131
 
132
    // }}}
133
    // {{{ setOptions()
134
 
135
    /**
136
     * Initialize the array structure containing the options for each select element.
137
     * Call the functions that actually do the magic.
138
     *
139
     * @param     array    $options    Array of options defining each element
140
     *
141
     * @access    public
142
     * @return    void
143
     */
144
    function setOptions($options)
145
    {
146
        $this->_options = $options;
147
 
148
        if (empty($this->_elements)) {
149
            $this->_nbElements = count($this->_options);
150
            $this->_createElements();
151
        } else {
152
            // setDefaults has probably been called before this function
153
            // check if all elements have been created
154
            $totalNbElements = count($this->_options);
155
            for ($i = $this->_nbElements; $i < $totalNbElements; $i ++) {
156
                $this->_elements[] =& new HTML_QuickForm_select($i, null, array(), $this->getAttributes());
157
                $this->_nbElements++;
158
            }
159
        }
160
 
161
        $this->_setOptions();
162
        $this->_setJS();
163
    } // end func setMainOptions
164
 
165
    // }}}
166
    // {{{ setMainOptions()
167
 
168
    /**
169
     * Sets the options for the first select element. Deprecated. setOptions() should be used.
170
     *
171
     * @param     array     $array    Options for the first select element
172
     *
173
     * @access    public
174
     * @return    void
175
     */
176
    function setMainOptions($array)
177
    {
178
        $this->_options[0] = $array;
179
 
180
        if (empty($this->_elements)) {
181
            $this->_nbElements = 2;
182
            $this->_createElements();
183
        }
184
    } // end func setMainOptions
185
 
186
    // }}}
187
    // {{{ setSecOptions()
188
 
189
    /**
190
     * Sets the options for the second select element. Deprecated. setOptions() should be used.
191
     * The main _options array is initialized and the _setOptions function is called.
192
     *
193
     * @param     array     $array    Options for the second select element
194
     *
195
     * @access    public
196
     * @return    void
197
     */
198
    function setSecOptions($array)
199
    {
200
        $this->_options[1] = $array;
201
 
202
        if (empty($this->_elements)) {
203
            $this->_nbElements = 2;
204
            $this->_createElements();
205
        } else {
206
            // setDefaults has probably been called before this function
207
            // check if all elements have been created
208
            $totalNbElements = 2;
209
            for ($i = $this->_nbElements; $i < $totalNbElements; $i ++) {
210
                $this->_elements[] =& new HTML_QuickForm_select($i, null, array(), $this->getAttributes());
211
                $this->_nbElements++;
212
            }
213
        }
214
 
215
        $this->_setOptions();
216
        $this->_setJS();
217
    } // end func setSecOptions
218
 
219
    // }}}
220
    // {{{ _setOptions()
221
 
222
    /**
223
     * Sets the options for each select element
224
     *
225
     * @access    private
226
     * @return    void
227
     */
228
    function _setOptions()
229
    {
230
        $toLoad = '';
231
        foreach (array_keys($this->_elements) AS $key) {
232
            if (eval("return isset(\$this->_options[{$key}]{$toLoad});") ) {
233
                $array = eval("return \$this->_options[{$key}]{$toLoad};");
234
                if (is_array($array)) {
235
                    $select =& $this->_elements[$key];
236
                    $select->_options = array();
237
                    $select->loadArray($array);
238
 
239
                    $value  = is_array($v = $select->getValue()) ? $v[0] : key($array);
240
                    $toLoad .= '[\''.$value.'\']';
241
                }
242
            }
243
        }
244
    } // end func _setOptions
245
 
246
    // }}}
247
    // {{{ setValue()
248
 
249
    /**
250
     * Sets values for group's elements
251
     *
252
     * @param     array     $value    An array of 2 or more values, for the first,
253
     *                                the second, the third etc. select
254
     *
255
     * @access    public
256
     * @return    void
257
     */
258
    function setValue($value)
259
    {
260
        $this->_nbElements = count($value);
261
        parent::setValue($value);
262
        $this->_setOptions();
263
    } // end func setValue
264
 
265
    // }}}
266
    // {{{ _createElements()
267
 
268
    /**
269
     * Creates all the elements for the group
270
     *
271
     * @access    private
272
     * @return    void
273
     */
274
    function _createElements()
275
    {
276
        for ($i = 0; $i < $this->_nbElements; $i++) {
277
            $this->_elements[] =& new HTML_QuickForm_select($i, null, array(), $this->getAttributes());
278
        }
279
    } // end func _createElements
280
 
281
    // }}}
282
    // {{{ _setJS()
283
 
284
    /**
285
     * Set the JavaScript for each select element (excluding de main one).
286
     *
287
     * @access    private
288
     * @return    void
289
     */
290
    function _setJS()
291
    {
292
        $this->_js = $js = '';
293
        $this->_jsArrayName = 'hs_' . $this->getName();
294
        for ($i = 1; $i < $this->_nbElements; $i++) {
295
            $this->_setJSArray($this->_jsArrayName, $this->_options[$i], $js);
296
        }
297
    } // end func _setJS
298
 
299
    // }}}
300
    // {{{ _setJSArray()
301
 
302
    /**
303
     * Recursively builds the JavaScript array defining the options that a select
304
     * element can have.
305
     *
306
     * @param       string      $grpName    Group Name attribute
307
     * @param       array       $options    Select element options
308
     * @param       string      $js         JavaScript definition is build using this variable
309
     * @param       string      $optValue   The value for the current JavaScript option
310
     *
311
     * @access      private
312
     * @return      void
313
     */
314
    function _setJSArray($grpName, $options, &$js, $optValue = '')
315
    {
316
        if (is_array($options)) {
317
            $js = '';
318
            // For a hierselect containing 3 elements:
319
            //      if option 1 has been selected for the 1st element
320
            //      and option 3 has been selected for the 2nd element,
321
            //      then the javascript array containing the values to load
322
            //      on the 3rd element will have the following name:   grpName_1_3
323
            $name  = ($optValue === '') ? $grpName : $grpName.'_'.$optValue;
324
            foreach($options AS $k => $v) {
325
                $this->_setJSArray($name, $v, $js, $k);
326
            }
327
 
328
            // if $js !== '' add it to the JavaScript
329
            $this->_js .= ($js !== '') ? $name." = {\n".$js."\n}\n" : '';
330
            $js = '';
331
        } else {
332
            // $js empty means that we are adding the first element to the JavaScript.
333
            if ($js != '') {
334
                $js .= ",\n";
335
            }
336
            $js .= '"'.$optValue.'":"'.$options.'"';
337
        }
338
    }
339
 
340
    // }}}
341
    // {{{ toHtml()
342
 
343
    /**
344
     * Returns Html for the group
345
     *
346
     * @access      public
347
     * @return      string
348
     */
349
    function toHtml()
350
    {
351
        if ($this->_flagFrozen) {
352
            $this->_js = '';
353
        } else {
354
            // set the onchange attribute for each element
355
            $keys               = array_keys($this->_elements);
356
            $nbElements         = count($keys);
357
            $nbElementsUsingFnc = $nbElements - 1; // last element doesn't need it
358
            for ($i = 0; $i < $nbElementsUsingFnc; $i++) {
359
                $select =& $this->_elements[$keys[$i]];
360
                $select->updateAttributes(
361
                    array('onChange' => 'swapOptions(this, \''.$this->getName().'\', '.$keys[$i].', '.$nbElements.', \''.$this->_jsArrayName.'\');')
362
                );
363
            }
364
 
365
            // create the js function to call
366
            if (!defined('HTML_QUICKFORM_HIERSELECT_EXISTS')) {
367
                $this->_js .= "function swapOptions(frm, grpName, eleIndex, nbElements, arName)\n"
368
                             ."{\n"
369
                             ."    var n = \"\";\n"
370
                             ."    var ctl;\n\n"
371
                             ."    for (var i = 0; i < nbElements; i++) {\n"
372
                             ."        ctl = frm.form[grpName+'['+i+']'];\n"
373
                             ."        if (!ctl) {\n"
374
                             ."            ctl = frm.form[grpName+'['+i+'][]'];\n"
375
                             ."        }\n"
376
                             ."        if (i <= eleIndex) {\n"
377
                             ."            n += \"_\"+ctl.value;\n"
378
                             ."        } else {\n"
379
                             ."            ctl.length = 0;\n"
380
                             ."        }\n"
381
                             ."    }\n\n"
382
                             ."    var t = eval(\"typeof(\"+arName + n +\")\");\n"
383
                             ."    if (t != 'undefined') {\n"
384
                             ."        var the_array = eval(arName+n);\n"
385
                             ."        var j = 0;\n"
386
                             ."        n = eleIndex + 1;\n"
387
                             ."        ctl = frm.form[grpName+'['+ n +']'];\n"
388
                             ."        if (!ctl) {\n"
389
                             ."            ctl = frm.form[grpName+'['+ n +'][]'];\n"
390
                             ."        }\n"
391
                             ."        for (var i in the_array) {\n"
392
                             ."            opt = new Option(the_array[i], i, false, false);\n"
393
                             ."            ctl.options[j++] = opt;\n"
394
                             ."        }\n"
395
                             ."    }\n"
396
                             ."    if (eleIndex+1 < nbElements) {\n"
397
                             ."        swapOptions(frm, grpName, eleIndex+1, nbElements, arName);\n"
398
                             ."    }\n"
399
                             ."}\n";
400
                define('HTML_QUICKFORM_HIERSELECT_EXISTS', true);
401
            }
402
        }
403
        include_once('HTML/QuickForm/Renderer/Default.php');
404
        $renderer =& new HTML_QuickForm_Renderer_Default();
405
        $renderer->setElementTemplate('{element}');
406
        parent::accept($renderer);
407
        return "<script type=\"text/javascript\">\n//<![CDATA[\n" . $this->_js . "//]]>\n</script>" .
408
               $renderer->toHtml();
409
    } // end func toHtml
410
 
411
    // }}}
412
    // {{{ accept()
413
 
414
   /**
415
    * Accepts a renderer
416
    *
417
    * @param object     An HTML_QuickForm_Renderer object
418
    * @param bool       Whether a group is required
419
    * @param string     An error message associated with a group
420
    * @access public
421
    * @return void
422
    */
423
    function accept(&$renderer, $required = false, $error = null)
424
    {
425
        $renderer->renderElement($this, $required, $error);
426
    } // end func accept
427
 
428
    // }}}
429
    // {{{ onQuickFormEvent()
430
 
431
    function onQuickFormEvent($event, $arg, &$caller)
432
    {
433
        if ('updateValue' == $event) {
434
            // we need to call setValue() so that the secondary option
435
            // matches the main option
436
            return HTML_QuickForm_element::onQuickFormEvent($event, $arg, $caller);
437
        } else {
438
            return parent::onQuickFormEvent($event, $arg, $caller);
439
        }
440
    } // end func onQuickFormEvent
441
 
442
    // }}}
443
} // end class HTML_QuickForm_hierselect
444
?>