home *** CD-ROM | disk | FTP | other *** search
/ Enter 2004 June / ENTER.ISO / files / xampp-win32-1.4.5-installer.exe / xampp / hierselect.php < prev    next >
Encoding:
PHP Script  |  2004-03-24  |  14.4 KB  |  425 lines

  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.7 2004/03/22 10:02:50 mansion 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.      * // third select
  62.      * $select3[0][0][0] = '15.00$';
  63.      * etc
  64.      *
  65.      * // and then
  66.      * $opts[0] = $select1;
  67.      * $opts[1] = $select2;
  68.      * $opts[2] = $select3;
  69.      *
  70.      * @var       array
  71.      * @access    private
  72.      */
  73.     var $_options = array();
  74.     
  75.     /**
  76.      * Number of select elements on this group
  77.      *
  78.      * @var       int
  79.      * @access    private
  80.      */
  81.     var $_nbElements = 0;
  82.  
  83.     /**
  84.      * The javascript used to set and change the options
  85.      *
  86.      * @var       string
  87.      * @access    private
  88.      */
  89.     var $_js = "<script type=\"text/javascript\">\n";
  90.     
  91.     /**
  92.     * The javascript array name
  93.     */
  94.     var $_jsArrayName = '';
  95.  
  96.     // }}}
  97.     // {{{ constructor
  98.  
  99.     /**
  100.      * Class constructor
  101.      * 
  102.      * @param     string    $elementName    (optional)Input field name attribute
  103.      * @param     string    $elementLabel   (optional)Input field label in form
  104.      * @param     mixed     $attributes     (optional)Either a typical HTML attribute string 
  105.      *                                      or an associative array. Date format is passed along the attributes.
  106.      * @param     mixed     $separator      (optional)Use a string for one separator,
  107.      *                                      use an array to alternate the separators.
  108.      * @access    public
  109.      * @return    void
  110.      */
  111.     function HTML_QuickForm_hierselect($elementName=null, $elementLabel=null, $attributes=null, $separator=null)
  112.     {
  113.         $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes);
  114.         $this->_persistantFreeze = true;
  115.         if (isset($separator)) {
  116.             $this->_separator = $separator;
  117.         }
  118.         $this->_type = 'hierselect';
  119.         $this->_appendName = true;
  120.     } //end constructor
  121.  
  122.     // }}}
  123.     // {{{ setOptions()
  124.  
  125.     /**
  126.      * Initialize the array structure containing the options for each select element.
  127.      * Call the functions that actually do the magic.
  128.      *
  129.      * @param     array    $options    Array of options defining each element
  130.      *
  131.      * @access    public
  132.      * @return    void
  133.      */
  134.     function setOptions(&$options)
  135.     {
  136.         $this->_options = &$options;
  137.  
  138.         if (empty($this->_elements)) {
  139.             $this->_nbElements = count($this->_options);
  140.             $this->_createElements();
  141.         } else {
  142.             // setDefaults has probably been called before this function
  143.             // check if all elements have been created
  144.             $totalNbElements = count($this->_options);
  145.             for ($i = $this->_nbElements; $i < $totalNbElements; $i ++) {
  146.                 $this->_elements[] =& new HTML_QuickForm_select($i, null, array(), $this->getAttributes());
  147.                 $this->_nbElements++;
  148.             }
  149.         }
  150.         
  151.         $this->_setOptions();
  152.         $this->_setJS();
  153.     } // end func setMainOptions
  154.  
  155.     // }}}
  156.     // {{{ setMainOptions()
  157.     
  158.     /**
  159.      * Sets the options for the first select element. Deprecated. setOptions() should be used.
  160.      *
  161.      * @param     array     $array    Options for the first select element
  162.      *
  163.      * @access    public
  164.      * @return    void
  165.      */
  166.     function setMainOptions(&$array)
  167.     {
  168.         $this->_options[0] = &$array;
  169.  
  170.         if (empty($this->_elements)) {
  171.             $this->_nbElements = 2;
  172.             $this->_createElements();
  173.         }
  174.     } // end func setMainOptions
  175.     
  176.     // }}}
  177.     // {{{ setSecOptions()
  178.     
  179.     /**
  180.      * Sets the options for the second select element. Deprecated. setOptions() should be used.
  181.      * The main _options array is initialized and the _setOptions function is called.
  182.      *
  183.      * @param     array     $array    Options for the second select element
  184.      *
  185.      * @access    public
  186.      * @return    void
  187.      */
  188.     function setSecOptions(&$array)
  189.     {
  190.         $this->_options[1] = &$array;
  191.         
  192.         if (empty($this->_elements)) {
  193.             $this->_nbElements = 2;
  194.             $this->_createElements();
  195.         } else {
  196.             // setDefaults has probably been called before this function
  197.             // check if all elements have been created
  198.             $totalNbElements = 2;
  199.             for ($i = $this->_nbElements; $i < $totalNbElements; $i ++) {
  200.                 $this->_elements[] =& new HTML_QuickForm_select($i, null, array(), $this->getAttributes());
  201.                 $this->_nbElements++;
  202.             }
  203.         }
  204.         
  205.         $this->_setOptions();
  206.         $this->_setJS();
  207.     } // end func setSecOptions
  208.     
  209.     // }}}
  210.     // {{{ _setOptions()
  211.     
  212.     /**
  213.      * Sets the options for each select element
  214.      *
  215.      * @access    private
  216.      * @return    void
  217.      */
  218.     function _setOptions()
  219.     {
  220.         $toLoad = '';
  221.         foreach (array_keys($this->_elements) AS $key) {
  222.             if (eval("return isset(\$this->_options[{$key}]{$toLoad});") ) {
  223.                 $array = eval("return \$this->_options[{$key}]{$toLoad};");
  224.                 if (is_array($array)) {                
  225.                     $select =& $this->_elements[$key];
  226.                     $select->_options = array();
  227.                     $select->loadArray($array);
  228.                     
  229.                     $value  = is_array($v = $select->getValue()) ? $v[0] : key($array);                    
  230.                     $toLoad .= '['.$value.']';
  231.                 }
  232.             }
  233.         }
  234.     } // end func _setOptions
  235.     
  236.     // }}}
  237.     // {{{ setValue()
  238.  
  239.     /**
  240.      * Sets values for group's elements
  241.      * 
  242.      * @param     array     $value    An array of 2 or more values, for the first,
  243.      *                                the second, the third etc. select
  244.      *
  245.      * @access    public
  246.      * @return    void
  247.      */
  248.     function setValue($value)
  249.     {
  250.         $this->_nbElements = count($value);
  251.         parent::setValue($value);
  252.         $this->_setOptions();
  253.     } // end func setValue
  254.     
  255.     // }}}
  256.     // {{{ _createElements()
  257.  
  258.     /**
  259.      * Creates all the elements for the group
  260.      * 
  261.      * @access    private
  262.      * @return    void
  263.      */
  264.     function _createElements()
  265.     {
  266.         for ($i = 0; $i < $this->_nbElements; $i++) {
  267.             $this->_elements[] =& new HTML_QuickForm_select($i, null, array(), $this->getAttributes());
  268.         }
  269.     } // end func _createElements
  270.  
  271.     // }}}
  272.     // {{{ _setJS()
  273.     
  274.     /**
  275.      * Set the JavaScript for each select element (excluding de main one).
  276.      *
  277.      * @access    private
  278.      * @return    void
  279.      */
  280.     function _setJS()
  281.     {
  282.         $js      = '';
  283.         $this->_jsArrayName = $this->getName();
  284.         for ($i = 1; $i < $this->_nbElements; $i++) {
  285.             $this->_setJSArray($this->_jsArrayName, $this->_options[$i], $js);
  286.         }
  287.     } // end func _setJS
  288.     
  289.     // }}}
  290.     // {{{ _setJSArray()
  291.     
  292.     /**
  293.      * Recursively builds the JavaScript array defining the options that a select
  294.      * element can have.
  295.      *
  296.      * @param       string      $grpName    Group Name attribute
  297.      * @param       array       $options    Select element options
  298.      * @param       string      $js         JavaScript definition is build using this variable
  299.      * @param       string      $optValue   The value for the current JavaScript option
  300.      *
  301.      * @access      private
  302.      * @return      void
  303.      */
  304.     function _setJSArray($grpName, $options, &$js, $optValue = '')
  305.     {
  306.         if (is_array($options)) {
  307.             $js = '';
  308.             // For a hierselect containing 3 elements:
  309.             //      if option 1 has been selected for the 1st element
  310.             //      and option 3 has been selected for the 2nd element,
  311.             //      then the javascript array containing the values to load 
  312.             //      on the 3rd element will have the following name:   grpName_1_3
  313.             $name  = ($optValue === '') ? $grpName : $grpName.'_'.$optValue;
  314.             foreach($options AS $k => $v) {
  315.                 $this->_setJSArray($name, $v, $js, $k);
  316.             }
  317.             
  318.             // if $js !== '' add it to the JavaScript
  319.             $this->_js .= ($js !== '') ? $name." = {\n".$js."\n}\n" : '';
  320.             $js = '';
  321.         } else {
  322.             // $js empty means that we are adding the first element to the JavaScript.
  323.             if ($js != '') {
  324.                 $js .= ",\n";
  325.             }
  326.             $js .= '"'.$optValue.'":"'.$options.'"';
  327.         }
  328.     }
  329.  
  330.     // }}}
  331.     // {{{ toHtml()
  332.  
  333.     /**
  334.      * Returns Html for the group
  335.      * 
  336.      * @access      public
  337.      * @return      string
  338.      */
  339.     function toHtml()
  340.     {
  341.         if ($this->_flagFrozen) {
  342.             $this->_js = '';
  343.         } else {
  344.             // set the onchange attribute for each element
  345.             $keys               = array_keys($this->_elements);
  346.             $nbElements         = count($keys);
  347.             $nbElementsUsingFnc = $nbElements - 1; // last element doesn't need it
  348.             for ($i = 0; $i < $nbElementsUsingFnc; $i++) {
  349.                 $select =& $this->_elements[$keys[$i]];
  350.                 $select->updateAttributes(
  351.                     array('onChange' => 'swapOptions(this, \''.$this->getName().'\', '.$keys[$i].', '.$nbElements.', \''.$this->_jsArrayName.'\');')
  352.                 );
  353.             }
  354.             
  355.             // create the js function to call
  356.             if (!defined('HTML_QUICKFORM_HIERSELECT_EXISTS')) {
  357.                 $this->_js .= "function swapOptions(frm, grpName, eleIndex, nbElements, arName)\n"
  358.                              ."{\n"
  359.                              ."    var n = \"\";\n"
  360.                              ."    var ctl;\n\n"
  361.                              ."    for (var i = 0; i < nbElements; i++) {\n"
  362.                              ."        ctl = frm.form[grpName+'['+i+']'];\n"
  363.                              ."        if (i <= eleIndex) {\n"
  364.                              ."            n += \"_\"+ctl.value;\n"
  365.                              ."        } else {\n"
  366.                              ."            ctl.length = 0;\n"
  367.                              ."        }\n"
  368.                              ."    }\n\n"
  369.                              ."    var t = eval(\"typeof(\"+arName + n +\")\");\n"
  370.                              ."    if (t != 'undefined') {\n"
  371.                              ."        var the_array = eval(arName+n);\n"
  372.                              ."        var j = 0;\n"
  373.                              ."        n = eleIndex + 1;\n"
  374.                              ."        ctl = frm.form[grpName+'['+ n +']'];\n"
  375.                              ."        for (var i in the_array) {\n"
  376.                              ."            opt = new Option(the_array[i], i, false, false);\n"
  377.                              ."            ctl.options[j++] = opt;\n"
  378.                              ."        }\n"
  379.                              ."    }\n"
  380.                              ."}\n";
  381.                 define('HTML_QUICKFORM_HIERSELECT_EXISTS', true);
  382.             }
  383.             $this->_js .= "</script>\n";
  384.         }
  385.         include_once('HTML/QuickForm/Renderer/Default.php');
  386.         $renderer =& new HTML_QuickForm_Renderer_Default();
  387.         $renderer->setElementTemplate('{element}');
  388.         parent::accept($renderer);
  389.         return $this->_js.$renderer->toHtml();
  390.     } // end func toHtml
  391.  
  392.     // }}}
  393.     // {{{ accept()
  394.  
  395.    /**
  396.     * Accepts a renderer
  397.     *
  398.     * @param object     An HTML_QuickForm_Renderer object
  399.     * @param bool       Whether a group is required
  400.     * @param string     An error message associated with a group
  401.     * @access public
  402.     * @return void 
  403.     */
  404.     function accept(&$renderer, $required = false, $error = null)
  405.     {
  406.         $renderer->renderElement($this, $required, $error);
  407.     } // end func accept
  408.  
  409.     // }}}
  410.     // {{{ onQuickFormEvent()
  411.  
  412.     function onQuickFormEvent($event, $arg, &$caller)
  413.     {
  414.         if ('updateValue' == $event) {
  415.             // we need to call setValue() so that the secondary option
  416.             // matches the main option
  417.             return HTML_QuickForm_element::onQuickFormEvent($event, $arg, $caller);
  418.         } else {
  419.             return parent::onQuickFormEvent($event, $arg, $caller);
  420.         }
  421.     } // end func onQuickFormEvent
  422.  
  423.     // }}}    
  424. } // end class HTML_QuickForm_hierselect
  425. ?>