Subversion Repositories Applications.papyrus

Rev

Rev 320 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 320 Rev 443
Line 13... Line 13...
13
// | obtain it through the world-wide-web, please send a note 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.               |
14
// | license@php.net so we can mail you a copy immediately.               |
15
// +----------------------------------------------------------------------+
15
// +----------------------------------------------------------------------+
16
// | Authors: Herim Vasquez <vasquezh@iro.umontreal.ca>                   |
16
// | Authors: Herim Vasquez <vasquezh@iro.umontreal.ca>                   |
17
// |          Bertrand Mansion <bmansion@mamasam.com>                     |
17
// |          Bertrand Mansion <bmansion@mamasam.com>                     |
-
 
18
// |          Alexey Borzov <avb@php.net>
18
// +----------------------------------------------------------------------+
19
// +----------------------------------------------------------------------+
19
//
20
//
20
// $Id: hierselect.php,v 1.1 2005-03-30 08:50:33 jpm Exp $
21
// $Id: hierselect.php,v 1.2 2005-09-20 17:01:22 ddelon Exp $
Line 21... Line 22...
21
 
22
 
22
require_once('HTML/QuickForm/group.php');
23
require_once('HTML/QuickForm/group.php');
Line 23... Line 24...
23
require_once('HTML/QuickForm/select.php');
24
require_once('HTML/QuickForm/select.php');
Line 95... Line 96...
95
     *
96
     *
96
     * @var       string
97
     * @var       string
97
     * @access    private
98
     * @access    private
98
     */
99
     */
99
    var $_js = '';
100
    var $_js = '';
100
    
-
 
101
    /**
-
 
102
    * The javascript array name
-
 
103
    */
-
 
104
    var $_jsArrayName = '';
-
 
Line 105... Line 101...
105
 
101
 
106
    // }}}
102
    // }}}
Line 107... Line 103...
107
    // {{{ constructor
103
    // {{{ constructor
Line 157... Line 153...
157
                $this->_nbElements++;
153
                $this->_nbElements++;
158
            }
154
            }
159
        }
155
        }
Line 160... Line 156...
160
        
156
        
161
        $this->_setOptions();
-
 
162
        $this->_setJS();
157
        $this->_setOptions();
Line 163... Line 158...
163
    } // end func setMainOptions
158
    } // end func setMainOptions
164
 
159
 
Line 211... Line 206...
211
                $this->_nbElements++;
206
                $this->_nbElements++;
212
            }
207
            }
213
        }
208
        }
Line 214... Line 209...
214
        
209
        
215
        $this->_setOptions();
-
 
216
        $this->_setJS();
210
        $this->_setOptions();
Line 217... Line 211...
217
    } // end func setSecOptions
211
    } // end func setSecOptions
218
    
212
    
Line 227... Line 221...
227
     */
221
     */
228
    function _setOptions()
222
    function _setOptions()
229
    {
223
    {
230
        $toLoad = '';
224
        $toLoad = '';
231
        foreach (array_keys($this->_elements) AS $key) {
225
        foreach (array_keys($this->_elements) AS $key) {
232
            if (eval("return isset(\$this->_options[{$key}]{$toLoad});") ) {
226
            $array = eval("return isset(\$this->_options[{$key}]{$toLoad})? \$this->_options[{$key}]{$toLoad}: null;");
233
                $array = eval("return \$this->_options[{$key}]{$toLoad};");
-
 
234
                if (is_array($array)) {
227
            if (is_array($array)) {
235
                    $select =& $this->_elements[$key];
228
                $select =& $this->_elements[$key];
236
                    $select->_options = array();
229
                $select->_options = array();
237
                    $select->loadArray($array);
230
                $select->loadArray($array);
Line 238... Line 231...
238
 
231
 
239
                    $value  = is_array($v = $select->getValue()) ? $v[0] : key($array);
232
                $value  = is_array($v = $select->getValue()) ? $v[0] : key($array);
240
                    $toLoad .= '[\''.$value.'\']';
-
 
241
                }
233
                $toLoad .= '[\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $value) . '\']';
242
            }
234
            }
243
        }
235
        }
Line 244... Line 236...
244
    } // end func _setOptions
236
    } // end func _setOptions
Line 277... Line 269...
277
            $this->_elements[] =& new HTML_QuickForm_select($i, null, array(), $this->getAttributes());
269
            $this->_elements[] =& new HTML_QuickForm_select($i, null, array(), $this->getAttributes());
278
        }
270
        }
279
    } // end func _createElements
271
    } // end func _createElements
Line 280... Line 272...
280
 
272
 
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
    // }}}
273
    // }}}
Line 341... Line -...
341
    // {{{ toHtml()
-
 
342
 
-
 
343
    /**
-
 
344
     * Returns Html for the group
-
 
345
     * 
-
 
346
     * @access      public
-
 
347
     * @return      string
274
    // {{{ toHtml()
348
     */
275
 
349
    function toHtml()
-
 
350
    {
276
    function toHtml()
351
        if ($this->_flagFrozen) {
277
    {
352
            $this->_js = '';
278
        $this->_js = '';
353
        } else {
279
        if (!$this->_flagFrozen) {
354
            // set the onchange attribute for each element
280
            // set the onchange attribute for each element except last
355
            $keys               = array_keys($this->_elements);
-
 
356
            $nbElements         = count($keys);
281
            $keys     = array_keys($this->_elements);
357
            $nbElementsUsingFnc = $nbElements - 1; // last element doesn't need it
282
            $onChange = array();
-
 
283
            for ($i = 0; $i < count($keys) - 1; $i++) {
358
            for ($i = 0; $i < $nbElementsUsingFnc; $i++) {
284
                $select =& $this->_elements[$keys[$i]];
359
                $select =& $this->_elements[$keys[$i]];
285
                $onChange[$i] = $select->getAttribute('onchange');
360
                $select->updateAttributes(
286
                $select->updateAttributes(
361
                    array('onChange' => 'swapOptions(this, \''.$this->getName().'\', '.$keys[$i].', '.$nbElements.', \''.$this->_jsArrayName.'\');')
287
                    array('onchange' => '_hs_swapOptions(this.form, \'' . $this->_escapeString($this->getName()) . '\', ' . $keys[$i] . ');' . $onChange[$i])
Line 362... Line 288...
362
                );
288
                );
363
            }
289
            }
364
            
290
            
-
 
291
            // create the js function to call
-
 
292
            if (!defined('HTML_QUICKFORM_HIERSELECT_EXISTS')) {
-
 
293
                $this->_js .= <<<JAVASCRIPT
-
 
294
function _hs_findOptions(ary, keys)
-
 
295
{
365
            // create the js function to call
296
    var key = keys.shift();
-
 
297
    if (!key in ary) {
-
 
298
        return {};
366
            if (!defined('HTML_QUICKFORM_HIERSELECT_EXISTS')) {
299
    } else if (0 == keys.length) {
-
 
300
        return ary[key];
-
 
301
    } else {
-
 
302
        return _hs_findOptions(ary[key], keys);
-
 
303
    }
-
 
304
}
367
                $this->_js .= "function swapOptions(frm, grpName, eleIndex, nbElements, arName)\n"
305
 
368
                             ."{\n"
306
function _hs_findSelect(form, groupName, selectIndex)
-
 
307
{
369
                             ."    var n = \"\";\n"
308
    if (groupName+'['+ selectIndex +']' in form) {
-
 
309
        return form[groupName+'['+ selectIndex +']']; 
-
 
310
    } else {
-
 
311
        return form[groupName+'['+ selectIndex +'][]']; 
370
                             ."    var ctl;\n\n"
312
    }
-
 
313
}
-
 
314
 
-
 
315
function _hs_replaceOptions(ctl, optionList)
-
 
316
{
371
                             ."    for (var i = 0; i < nbElements; i++) {\n"
317
    var j = 0;
-
 
318
    ctl.options.length = 0;
-
 
319
    for (i in optionList) {
-
 
320
        ctl.options[j++] = new Option(optionList[i], i, false, false);
-
 
321
    }
-
 
322
}
-
 
323
 
372
                             ."        ctl = frm.form[grpName+'['+i+']'];\n"
324
function _hs_setValue(ctl, value)
373
                             ."        if (!ctl) {\n"
325
{
374
                             ."            ctl = frm.form[grpName+'['+i+'][]'];\n"
326
    var testValue = {};
-
 
327
    if (value instanceof Array) {
-
 
328
        for (var i = 0; i < value.length; i++) {
-
 
329
            testValue[value[i]] = true;
-
 
330
        }
375
                             ."        }\n"
331
    } else {
376
                             ."        if (i <= eleIndex) {\n"
332
        testValue[value] = true;
377
                             ."            n += \"_\"+ctl.value;\n"
333
    }
-
 
334
    for (var i = 0; i < ctl.options.length; i++) {
-
 
335
        if (ctl.options[i].value in testValue) {
-
 
336
            ctl.options[i].selected = true;
-
 
337
        }
-
 
338
    }
-
 
339
}
-
 
340
 
378
                             ."        } else {\n"
341
function _hs_swapOptions(form, groupName, selectIndex)
379
                             ."            ctl.length = 0;\n"
342
{
-
 
343
    var hsValue = [];
-
 
344
    for (var i = 0; i <= selectIndex; i++) {
380
                             ."        }\n"
345
        hsValue[i] = _hs_findSelect(form, groupName, i).value;
381
                             ."    }\n\n"
346
    }
382
                             ."    var t = eval(\"typeof(\"+arName + n +\")\");\n"
347
 
383
                             ."    if (t != 'undefined') {\n"
348
    _hs_replaceOptions(_hs_findSelect(form, groupName, selectIndex + 1), 
-
 
349
                       _hs_findOptions(_hs_options[groupName][selectIndex], hsValue));
-
 
350
    if (selectIndex + 1 < _hs_options[groupName].length) {
-
 
351
        _hs_swapOptions(form, groupName, selectIndex + 1);
-
 
352
    }
-
 
353
}
384
                             ."        var the_array = eval(arName+n);\n"
354
 
-
 
355
function _hs_onReset(form, groupNames)
385
                             ."        var j = 0;\n"
356
{
386
                             ."        n = eleIndex + 1;\n"
357
    for (var i = 0; i < groupNames.length; i++) {
387
                             ."        ctl = frm.form[grpName+'['+ n +']'];\n"
358
        try {
388
                             ."        if (!ctl) {\n"
359
            for (var j = 0; j <= _hs_options[groupNames[i]].length; j++) {
389
                             ."            ctl = frm.form[grpName+'['+ n +'][]'];\n"
360
                _hs_setValue(_hs_findSelect(form, groupNames[i], j), _hs_defaults[groupNames[i]][j]);
-
 
361
                if (j < _hs_options[groupNames[i]].length) {
-
 
362
                    _hs_replaceOptions(_hs_findSelect(form, groupNames[i], j + 1), 
-
 
363
                                       _hs_findOptions(_hs_options[groupNames[i]][j], _hs_defaults[groupNames[i]].slice(0, j + 1)));
390
                             ."        }\n"
364
                }
391
                             ."        for (var i in the_array) {\n"
365
            }
-
 
366
        } catch (e) {
-
 
367
            if (!(e instanceof TypeError)) {
-
 
368
                throw e;
-
 
369
            }
-
 
370
        }
-
 
371
    }
-
 
372
}
-
 
373
 
-
 
374
function _hs_setupOnReset(form, groupNames)
-
 
375
{
-
 
376
    setTimeout(function() { _hs_onReset(form, groupNames); }, 25);
-
 
377
}
-
 
378
 
-
 
379
function _hs_onReload()
392
                             ."            opt = new Option(the_array[i], i, false, false);\n"
380
{
-
 
381
    var ctl;
393
                             ."            ctl.options[j++] = opt;\n"
382
    for (var i = 0; i < document.forms.length; i++) {
394
                             ."        }\n"
383
        for (var j in _hs_defaults) {
395
                             ."    }\n"
384
            if (ctl = _hs_findSelect(document.forms[i], j, 0)) {
-
 
385
                for (var k = 0; k < _hs_defaults[j].length; k++) {
-
 
386
                    _hs_setValue(_hs_findSelect(document.forms[i], j, k), _hs_defaults[j][k]);
-
 
387
                }
-
 
388
            }
-
 
389
        }
-
 
390
    }
-
 
391
 
-
 
392
    if (_hs_prevOnload) {
-
 
393
        _hs_prevOnload();
-
 
394
    }
-
 
395
}
396
                             ."    if (eleIndex+1 < nbElements) {\n"
396
 
-
 
397
var _hs_prevOnload = null;
-
 
398
if (window.onload) {
-
 
399
    _hs_prevOnload = window.onload;
-
 
400
}
-
 
401
window.onload = _hs_onReload;
-
 
402
 
-
 
403
var _hs_options = {};
397
                             ."        swapOptions(frm, grpName, eleIndex+1, nbElements, arName);\n"
404
var _hs_defaults = {};
398
                             ."    }\n"
405
 
-
 
406
JAVASCRIPT;
-
 
407
                define('HTML_QUICKFORM_HIERSELECT_EXISTS', true);
-
 
408
            }
-
 
409
            // option lists
-
 
410
            $jsParts = array();
-
 
411
            for ($i = 1; $i < $this->_nbElements; $i++) {
-
 
412
                $jsParts[] = $this->_convertArrayToJavascript($this->_options[$i]);
-
 
413
            }
-
 
414
            $this->_js .= "\n_hs_options['" . $this->_escapeString($this->getName()) . "'] = [\n" .
-
 
415
                          implode(",\n", $jsParts) .
-
 
416
                          "\n];\n";
-
 
417
            // default value; if we don't actually have any values yet just use
-
 
418
            // the first option (for single selects) or empty array (for multiple)
-
 
419
            $values = array();
-
 
420
            foreach (array_keys($this->_elements) as $key) {
-
 
421
                if (is_array($v = $this->_elements[$key]->getValue())) {
-
 
422
                    $values[] = count($v) > 1? $v: $v[0];
-
 
423
                } else {
-
 
424
                    // XXX: accessing the supposedly private _options array
-
 
425
                    $values[] = $this->_elements[$key]->getMultiple() || empty($this->_elements[$key]->_options[0])?
-
 
426
                                array():
-
 
427
                                $this->_elements[$key]->_options[0]['attr']['value'];
-
 
428
                }
399
                             ."}\n";
429
            }
400
                define('HTML_QUICKFORM_HIERSELECT_EXISTS', true);
430
            $this->_js .= "_hs_defaults['" . $this->_escapeString($this->getName()) . "'] = " .
401
            }
431
                          $this->_convertArrayToJavascript($values, false) . ";\n";
402
        }
432
        }
403
        include_once('HTML/QuickForm/Renderer/Default.php');
433
        include_once('HTML/QuickForm/Renderer/Default.php');
-
 
434
        $renderer =& new HTML_QuickForm_Renderer_Default();
-
 
435
        $renderer->setElementTemplate('{element}');
-
 
436
        parent::accept($renderer);
-
 
437
 
-
 
438
        if (!empty($onChange)) {
-
 
439
            $keys     = array_keys($this->_elements);
-
 
440
            for ($i = 0; $i < count($keys) - 1; $i++) {
404
        $renderer =& new HTML_QuickForm_Renderer_Default();
441
                $this->_elements[$keys[$i]]->updateAttributes(array('onchange' => $onChange[$i]));
405
        $renderer->setElementTemplate('{element}');
442
            }
406
        parent::accept($renderer);
443
        }
Line 407... Line 444...
407
        return "<script type=\"text/javascript\">\n//<![CDATA[\n" . $this->_js . "//]]>\n</script>" .
444
        return (empty($this->_js)? '': "<script type=\"text/javascript\">\n//<![CDATA[\n" . $this->_js . "//]]>\n</script>") .
408
               $renderer->toHtml();
445
               $renderer->toHtml();
Line 409... Line -...
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
446
    } // end func toHtml
419
    * @param string     An error message associated with a group
447
 
420
    * @access public
448
    // }}}
421
    * @return void 
449
    // {{{ accept()
Line 433... Line 461...
433
        if ('updateValue' == $event) {
461
        if ('updateValue' == $event) {
434
            // we need to call setValue() so that the secondary option
462
            // we need to call setValue() so that the secondary option
435
            // matches the main option
463
            // matches the main option
436
            return HTML_QuickForm_element::onQuickFormEvent($event, $arg, $caller);
464
            return HTML_QuickForm_element::onQuickFormEvent($event, $arg, $caller);
437
        } else {
465
        } else {
438
            return parent::onQuickFormEvent($event, $arg, $caller);
466
            $ret = parent::onQuickFormEvent($event, $arg, $caller);
-
 
467
            // add onreset handler to form to properly reset hierselect (see bug #2970)
-
 
468
            if ('addElement' == $event) {
-
 
469
                $onReset = $caller->getAttribute('onreset');
-
 
470
                if (strlen($onReset)) {
-
 
471
                    if (strpos($onReset, '_hs_setupOnReset')) {
-
 
472
                        $caller->updateAttributes(array('onreset' => str_replace('_hs_setupOnReset(this, [', "_hs_setupOnReset(this, ['" . $this->_escapeString($this->getName()) . "', ", $onReset)));
-
 
473
                    } else {
-
 
474
                        $caller->updateAttributes(array('onreset' => "var temp = function() { {$onReset} } ; if (!temp()) { return false; } ; if (typeof _hs_setupOnReset != 'undefined') { return _hs_setupOnReset(this, ['" . $this->_escapeString($this->getName()) . "']); } "));
-
 
475
                    }
-
 
476
                } else {
-
 
477
                    $caller->updateAttributes(array('onreset' => "if (typeof _hs_setupOnReset != 'undefined') { return _hs_setupOnReset(this, ['" . $this->_escapeString($this->getName()) . "']); } "));
-
 
478
                }
-
 
479
            }
-
 
480
            return $ret;
439
        }
481
        }
440
    } // end func onQuickFormEvent
482
    } // end func onQuickFormEvent
Line -... Line 483...
-
 
483
 
-
 
484
    // }}}
-
 
485
    // {{{ _convertArrayToJavascript()
-
 
486
 
-
 
487
   /**
-
 
488
    * Converts PHP array to its Javascript analog
-
 
489
    *
-
 
490
    * @access private
-
 
491
    * @param  array     PHP array to convert
-
 
492
    * @param  bool      Generate Javascript object literal (default, works like PHP's associative array) or array literal
-
 
493
    * @return string    Javascript representation of the value
-
 
494
    */
-
 
495
    function _convertArrayToJavascript($array, $assoc = true)
-
 
496
    {
-
 
497
        if (!is_array($array)) {
-
 
498
            return $this->_convertScalarToJavascript($array);
-
 
499
        } else {
-
 
500
            $items = array();
-
 
501
            foreach ($array as $key => $val) {
-
 
502
                $item = $assoc? "'" . $this->_escapeString($key) . "': ": '';
-
 
503
                if (is_array($val)) {
-
 
504
                    $item .= $this->_convertArrayToJavascript($val, $assoc);
-
 
505
                } else {
-
 
506
                    $item .= $this->_convertScalarToJavascript($val);
-
 
507
                }
-
 
508
                $items[] = $item;
-
 
509
            }
-
 
510
        }
-
 
511
        $js = implode(', ', $items);
-
 
512
        return $assoc? '{ ' . $js . ' }': '[' . $js . ']';
-
 
513
    }
-
 
514
    
-
 
515
    // }}}
-
 
516
    // {{{ _convertScalarToJavascript()
-
 
517
 
-
 
518
   /**
-
 
519
    * Converts PHP's scalar value to its Javascript analog
-
 
520
    *
-
 
521
    * @access private
-
 
522
    * @param  mixed     PHP value to convert
-
 
523
    * @return string    Javascript representation of the value
-
 
524
    */
-
 
525
    function _convertScalarToJavascript($val)
-
 
526
    {
-
 
527
        if (is_bool($val)) {
-
 
528
            return $val ? 'true' : 'false';
-
 
529
        } elseif (is_int($val) || is_double($val)) {
-
 
530
            return $val;
-
 
531
        } elseif (is_string($val)) {
-
 
532
            return "'" . $this->_escapeString($val) . "'";
-
 
533
        } elseif (is_null($val)) {
-
 
534
            return 'null';
-
 
535
        } else {
-
 
536
            // don't bother
-
 
537
            return '{}';
-
 
538
        }
-
 
539
    }
-
 
540
 
-
 
541
    // }}}
-
 
542
    // {{{ _escapeString()
-
 
543
 
-
 
544
   /**
-
 
545
    * Quotes the string so that it can be used in Javascript string constants   
-
 
546
    *
-
 
547
    * @access private
-
 
548
    * @param  string
-
 
549
    * @return string
-
 
550
    */
-
 
551
    function _escapeString($str)
-
 
552
    {
-
 
553
        return strtr($str,array(
-
 
554
            "\r"    => '\r',
-
 
555
            "\n"    => '\n',
-
 
556
            "\t"    => '\t',
-
 
557
            "'"     => "\\'",
-
 
558
            '"'     => '\"',
-
 
559
            '\\'    => '\\\\'
-
 
560
        ));
-
 
561
    }
441
 
562
 
442
    // }}}    
563
    // }}}
443
} // end class HTML_QuickForm_hierselect
564
} // end class HTML_QuickForm_hierselect
444
?>
565
?>