HTML_QuickForm_advmultiselect
[ class tree: HTML_QuickForm_advmultiselect ] [ index: HTML_QuickForm_advmultiselect ] [ all elements ]

Source for file advmultiselect.php

Documentation is available at advmultiselect.php

  1. <?php
  2. /**
  3.  * Copyright (c) 2005-2009, Laurent Laville <pear@laurent-laville.org>
  4.  *
  5.  * All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  *     * Redistributions of source code must retain the above copyright
  12.  *       notice, this list of conditions and the following disclaimer.
  13.  *     * Redistributions in binary form must reproduce the above copyright
  14.  *       notice, this list of conditions and the following disclaimer in the
  15.  *       documentation and/or other materials provided with the distribution.
  16.  *     * Neither the name of the authors nor the names of its contributors
  17.  *       may be used to endorse or promote products derived from this software
  18.  *       without specific prior written permission.
  19.  *
  20.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23.  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
  24.  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  25.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  26.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  29.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  30.  * POSSIBILITY OF SUCH DAMAGE.
  31.  *
  32.  * PHP versions 4 and 5
  33.  *
  34.  * @category  HTML
  35.  * @package   HTML_QuickForm_advmultiselect
  36.  * @author    Laurent Laville <pear@laurent-laville.org>
  37.  * @copyright 2005-2009 Laurent Laville
  38.  * @license   http://www.opensource.org/licenses/bsd-license.php  BSD
  39.  * @version   CVS: $Id: advmultiselect.php,v 1.36 2009/04/05 07:03:39 farell Exp $
  40.  * @link      http://pear.php.net/package/HTML_QuickForm_advmultiselect
  41.  * @since     File available since Release 0.4.0
  42.  */
  43.  
  44. require_once 'HTML/QuickForm/select.php';
  45.  
  46. /**
  47.  * Basic error codes
  48.  *
  49.  * @var        integer 
  50.  * @since      1.5.0
  51.  */
  52. define('HTML_QUICKFORM_ADVMULTISELECT_ERROR_INVALID_INPUT'1);
  53.  
  54. /**
  55.  * Element for HTML_QuickForm that emulate a multi-select.
  56.  *
  57.  * The HTML_QuickForm_advmultiselect package adds an element to the
  58.  * HTML_QuickForm package that is two select boxes next to each other
  59.  * emulating a multi-select.
  60.  *
  61.  * @category  HTML
  62.  * @package   HTML_QuickForm_advmultiselect
  63.  * @author    Laurent Laville <pear@laurent-laville.org>
  64.  * @copyright 2005-2009 Laurent Laville
  65.  * @license   http://www.opensource.org/licenses/bsd-license.php  BSD
  66.  * @version   Release: @package_version@
  67.  * @link      http://pear.php.net/package/HTML_QuickForm_advmultiselect
  68.  * @since     Class available since Release 0.4.0
  69.  */
  70. class HTML_QuickForm_advmultiselect extends HTML_QuickForm_select
  71. {
  72.     /**
  73.      * Prefix function name in javascript move selections
  74.      *
  75.      * @var        string 
  76.      * @access     private
  77.      * @since      0.4.0
  78.      */
  79.     var $_jsPrefix;
  80.  
  81.     /**
  82.      * Postfix function name in javascript move selections
  83.      *
  84.      * @var        string 
  85.      * @access     private
  86.      * @since      0.4.0
  87.      */
  88.     var $_jsPostfix;
  89.  
  90.     /**
  91.      * Associative array of the multi select container attributes
  92.      *
  93.      * @var        array 
  94.      * @access     private
  95.      * @since      0.4.0
  96.      */
  97.     var $_tableAttributes;
  98.  
  99.     /**
  100.      * Associative array of the add button attributes
  101.      *
  102.      * @var        array 
  103.      * @access     private
  104.      * @since      0.4.0
  105.      */
  106.     var $_addButtonAttributes;
  107.  
  108.     /**
  109.      * Associative array of the remove button attributes
  110.      *
  111.      * @var        array 
  112.      * @access     private
  113.      * @since      0.4.0
  114.      */
  115.     var $_removeButtonAttributes;
  116.  
  117.     /**
  118.      * Associative array of the select all button attributes
  119.      *
  120.      * @var        array 
  121.      * @access     private
  122.      * @since      1.1.0
  123.      */
  124.     var $_allButtonAttributes;
  125.  
  126.     /**
  127.      * Associative array of the select none button attributes
  128.      *
  129.      * @var        array 
  130.      * @access     private
  131.      * @since      1.1.0
  132.      */
  133.     var $_noneButtonAttributes;
  134.  
  135.     /**
  136.      * Associative array of the toggle selection button attributes
  137.      *
  138.      * @var        array 
  139.      * @access     private
  140.      * @since      1.1.0
  141.      */
  142.     var $_toggleButtonAttributes;
  143.  
  144.     /**
  145.      * Associative array of the move up button attributes
  146.      *
  147.      * @var        array 
  148.      * @access     private
  149.      * @since      0.5.0
  150.      */
  151.     var $_upButtonAttributes;
  152.  
  153.     /**
  154.      * Associative array of the move up button attributes
  155.      *
  156.      * @var        array 
  157.      * @access     private
  158.      * @since      0.5.0
  159.      */
  160.     var $_downButtonAttributes;
  161.  
  162.     /**
  163.      * Associative array of the move top button attributes
  164.      *
  165.      * @var        array 
  166.      * @access     private
  167.      * @since      1.5.0
  168.      */
  169.     var $_topButtonAttributes;
  170.  
  171.     /**
  172.      * Associative array of the move bottom button attributes
  173.      *
  174.      * @var        array 
  175.      * @access     private
  176.      * @since      1.5.0
  177.      */
  178.     var $_bottomButtonAttributes;
  179.  
  180.     /**
  181.      * Defines if both list (unselected, selected) will have their elements be
  182.      * arranged from lowest to highest (or reverse)
  183.      * depending on comparaison function.
  184.      *
  185.      * SORT_ASC  is used to sort in ascending order
  186.      * SORT_DESC is used to sort in descending order
  187.      *
  188.      * @var    string    ('none' == false, 'asc' == SORT_ASC, 'desc' == SORT_DESC)
  189.      * @access private
  190.      * @since  0.5.0
  191.      */
  192.     var $_sort;
  193.  
  194.     /**
  195.      * Associative array of the unselected item box attributes
  196.      *
  197.      * @var        array 
  198.      * @access     private
  199.      * @since      0.4.0
  200.      */
  201.     var $_attributesUnselected;
  202.  
  203.     /**
  204.      * Associative array of the selected item box attributes
  205.      *
  206.      * @var        array 
  207.      * @access     private
  208.      * @since      0.4.0
  209.      */
  210.     var $_attributesSelected;
  211.  
  212.     /**
  213.      * Associative array of the internal hidden box attributes
  214.      *
  215.      * @var        array 
  216.      * @access     private
  217.      * @since      0.4.0
  218.      */
  219.     var $_attributesHidden;
  220.  
  221.     /**
  222.      * Default Element template string
  223.      *
  224.      * @var        string 
  225.      * @access     private
  226.      * @since      0.4.0
  227.      */
  228.     var $_elementTemplate;
  229.  
  230.     /**
  231.      * Default Element stylesheet string
  232.      *
  233.      * @var        string 
  234.      * @access     private
  235.      * @since      0.4.0
  236.      */
  237.     var $_elementCSS '
  238. #qfams_{id} {
  239.   font: 13.3px sans-serif;
  240.   background-color: #fff;
  241.   overflow: auto;
  242.   height: 14.3em;
  243.   width: 12em;
  244.   border-left:   1px solid #404040;
  245.   border-top:    1px solid #404040;
  246.   border-bottom: 1px solid #d4d0c8;
  247.   border-right:  1px solid #d4d0c8;
  248. }
  249. #qfams_{id} label {
  250.   padding-right: 3px;
  251.   display: block;
  252. }
  253. ';
  254.  
  255.     /**
  256.      * Class constructor
  257.      *
  258.      * Class constructors :
  259.      * Zend Engine 1 uses HTML_QuickForm_advmultiselect, while
  260.      * Zend Engine 2 uses __construct
  261.      *
  262.      * @param string  $elementName  Dual Select name attribute
  263.      * @param mixed   $elementLabel Label(s) for the select boxes
  264.      * @param mixed   $options      Data to be used to populate options
  265.      * @param mixed   $attributes   Either a typical HTML attribute string or
  266.      *                               an associative array
  267.      * @param integer $sort         Either SORT_ASC for auto ascending arrange,
  268.      *                                      SORT_DESC for auto descending arrange, or
  269.      *                                      NULL for no sort (append at end: default)
  270.      *
  271.      * @access     public
  272.      * @return     void 
  273.      * @since      version 0.4.0 (2005-06-25)
  274.      */
  275.     function HTML_QuickForm_advmultiselect($elementName = null$elementLabel = null,
  276.                                            $options = null$attributes = null,
  277.                                            $sort = null)
  278.     {
  279.         $opts    $options;
  280.         $options = null;  // prevent to use the default select element load options
  281.         $this->HTML_QuickForm_select($elementName$elementLabel,
  282.             $options$attributes);
  283.  
  284.         // allow to load options at once and take care of fancy attributes
  285.         $this->load($opts);
  286.  
  287.         // add multiple selection attribute by default if missing
  288.         $this->updateAttributes(array('multiple' => 'multiple'));
  289.  
  290.         if (is_null($this->getAttribute('size'))) {
  291.             // default size is ten item on each select box (left and right)
  292.             $this->updateAttributes(array('size' => 10));
  293.         }
  294.         if (is_null($this->getAttribute('style'))) {
  295.             // default width of each select box
  296.             $this->updateAttributes(array('style' => 'width:100px;'));
  297.         }
  298.         $this->_tableAttributes $this->getAttribute('class');
  299.         if (is_null($this->_tableAttributes)) {
  300.             // default table layout
  301.             $attr = array('border' => '0',
  302.                           'cellpadding' => '10''cellspacing' => '0');
  303.         else {
  304.             $attr = array('class' => $this->_tableAttributes);
  305.             $this->_removeAttr('class'$this->_attributes);
  306.         }
  307.         $this->_tableAttributes $this->_getAttrString($attr);
  308.  
  309.         // set default add button attributes
  310.         $this->setButtonAttributes('add');
  311.         // set default remove button attributes
  312.         $this->setButtonAttributes('remove');
  313.         // set default selectall button attributes
  314.         $this->setButtonAttributes('all');
  315.         // set default selectnone button attributes
  316.         $this->setButtonAttributes('none');
  317.         // set default toggle selection button attributes
  318.         $this->setButtonAttributes('toggle');
  319.         // set default move up button attributes
  320.         $this->setButtonAttributes('moveup');
  321.         // set default move up button attributes
  322.         $this->setButtonAttributes('movedown');
  323.         // set default move top button attributes
  324.         $this->setButtonAttributes('movetop');
  325.         // set default move bottom button attributes
  326.         $this->setButtonAttributes('movebottom');
  327.         // defines javascript functions names
  328.         $this->_jsPrefix  'QFAMS.';
  329.         $this->_jsPostfix 'moveSelection';
  330.  
  331.         // set select boxes sort order (none by default)
  332.         if (!isset($sort)) {
  333.             $sort = false;
  334.         }
  335.         if ($sort === SORT_ASC{
  336.             $this->_sort 'asc';
  337.         elseif ($sort === SORT_DESC{
  338.             $this->_sort 'desc';
  339.         else {
  340.             $this->_sort 'none';
  341.         }
  342.  
  343.         // set the default advmultiselect element template (with javascript embedded)
  344.         $this->setElementTemplate();
  345.     }
  346.  
  347.     /**
  348.      * Sets the button attributes
  349.      *
  350.      * In <b>custom example 1</b>, the <i>add</i> and <i>remove</i> buttons
  351.      * have look set by the css class <i>inputCommand</i>.
  352.      *
  353.      * In <b>custom example 2</b>, the basic text <i>add</i> and <i>remove</i>
  354.      * buttons are now replaced by images.
  355.      *
  356.      * In <b>custom example 5</b>, we have ability to sort the selection list
  357.      * (on right side) by :
  358.      * <pre>
  359.      *  - <b>user-end</b>: with <i>Up</i> and <i>Down</i> buttons
  360.      *  - <b>programming</b>: with the QF element constructor $sort option
  361.      * </pre>
  362.      *
  363.      * @param string $button     Button identifier, either 'add', 'remove',
  364.      *                                                      'all', 'none', 'toggle',
  365.      *                                                      'movetop', 'movebottom'
  366.      *                                                      'moveup' or 'movedown'
  367.      * @param mixed  $attributes (optional) Either a typical HTML attribute string
  368.      *                                       or an associative array
  369.      *
  370.      * @return     void 
  371.      * @throws     PEAR_Error   $button argument
  372.      *                           is not a string, or not in range
  373.      *                           (add, remove, all, none, toggle,
  374.      *                            movetop, movebottom, moveup, movedown)
  375.      * @access     public
  376.      * @since      version 0.4.0 (2005-06-25)
  377.      *
  378.      * @example    examples/qfams_custom_5.php
  379.      *              Custom example 5: source code
  380.      * @link       http://www.laurent-laville.org/img/qfams/screenshot/custom5.png
  381.      *              Custom example 5: screenshot
  382.      *
  383.      * @example    examples/qfams_custom_2.php
  384.      *              Custom example 2: source code
  385.      * @link       http://www.laurent-laville.org/img/qfams/screenshot/custom2.png
  386.      *              Custom example 2: screenshot
  387.      *
  388.      * @example    examples/qfams_custom_1.php
  389.      *              Custom example 1: source code
  390.      * @link       http://www.laurent-laville.org/img/qfams/screenshot/custom1.png
  391.      *              Custom example 1: screenshot
  392.      */
  393.     function setButtonAttributes($button$attributes = null)
  394.     {
  395.         if (!is_string($button)) {
  396.             return PEAR::throwError('Argument 1 of HTML_QuickForm_advmultiselect::' .
  397.                        'setButtonAttributes is not a string',
  398.                        HTML_QUICKFORM_ADVMULTISELECT_ERROR_INVALID_INPUT,
  399.                        array('level' => 'exception'));
  400.         }
  401.  
  402.         switch ($button{
  403.         case 'add':
  404.             if (is_null($attributes)) {
  405.                 $this->_addButtonAttributes
  406.                     = array('name'  => 'add',
  407.                             'value' => ' >> ',
  408.                             'type'  => 'button');
  409.             else {
  410.                 $this->_updateAttrArray($this->_addButtonAttributes,
  411.                                         $this->_parseAttributes($attributes));
  412.             }
  413.             break;
  414.         case 'remove':
  415.             if (is_null($attributes)) {
  416.                 $this->_removeButtonAttributes
  417.                     = array('name'  => 'remove',
  418.                             'value' => ' << ',
  419.                             'type'  => 'button');
  420.             else {
  421.                 $this->_updateAttrArray($this->_removeButtonAttributes,
  422.                                         $this->_parseAttributes($attributes));
  423.             }
  424.             break;
  425.         case 'all':
  426.             if (is_null($attributes)) {
  427.                 $this->_allButtonAttributes
  428.                     = array('name'  => 'all',
  429.                             'value' => ' Select All ',
  430.                             'type'  => 'button');
  431.             else {
  432.                 $this->_updateAttrArray($this->_allButtonAttributes,
  433.                                         $this->_parseAttributes($attributes));
  434.             }
  435.             break;
  436.         case 'none':
  437.             if (is_null($attributes)) {
  438.                 $this->_noneButtonAttributes
  439.                     = array('name'  => 'none',
  440.                             'value' => ' Select None ',
  441.                             'type'  => 'button');
  442.             else {
  443.                 $this->_updateAttrArray($this->_noneButtonAttributes,
  444.                                         $this->_parseAttributes($attributes));
  445.             }
  446.             break;
  447.         case 'toggle':
  448.             if (is_null($attributes)) {
  449.                 $this->_toggleButtonAttributes
  450.                     = array('name'  => 'toggle',
  451.                             'value' => ' Toggle Selection ',
  452.                             'type'  => 'button');
  453.             else {
  454.                 $this->_updateAttrArray($this->_toggleButtonAttributes,
  455.                                         $this->_parseAttributes($attributes));
  456.             }
  457.             break;
  458.         case 'moveup':
  459.             if (is_null($attributes)) {
  460.                 $this->_upButtonAttributes
  461.                     = array('name'  => 'up',
  462.                             'value' => ' Up ',
  463.                             'type'  => 'button');
  464.             else {
  465.                 $this->_updateAttrArray($this->_upButtonAttributes,
  466.                                         $this->_parseAttributes($attributes));
  467.             }
  468.             break;
  469.         case 'movedown':
  470.             if (is_null($attributes)) {
  471.                 $this->_downButtonAttributes
  472.                     = array('name'  => 'down',
  473.                             'value' => ' Down ',
  474.                             'type'  => 'button');
  475.             else {
  476.                 $this->_updateAttrArray($this->_downButtonAttributes,
  477.                                         $this->_parseAttributes($attributes));
  478.             }
  479.             break;
  480.         case 'movetop':
  481.             if (is_null($attributes)) {
  482.                 $this->_topButtonAttributes
  483.                     = array('name'  => 'top',
  484.                             'value' => ' Top ',
  485.                             'type'  => 'button');
  486.             else {
  487.                 $this->_updateAttrArray($this->_topButtonAttributes,
  488.                                         $this->_parseAttributes($attributes));
  489.             }
  490.             break;
  491.         case 'movebottom':
  492.             if (is_null($attributes)) {
  493.                 $this->_bottomButtonAttributes
  494.                     = array('name'  => 'bottom',
  495.                             'value' => ' Bottom ',
  496.                             'type'  => 'button');
  497.             else {
  498.                 $this->_updateAttrArray($this->_bottomButtonAttributes,
  499.                                         $this->_parseAttributes($attributes));
  500.             }
  501.             break;
  502.         default;
  503.             return PEAR::throwError('Argument 1 of HTML_QuickForm_advmultiselect::' .
  504.                        'setButtonAttributes has unexpected value',
  505.                        HTML_QUICKFORM_ADVMULTISELECT_ERROR_INVALID_INPUT,
  506.                        array('level' => 'error'));
  507.         }
  508.     }
  509.  
  510.     /**
  511.      * Sets element template
  512.      *
  513.      * @param string $html (optional) The HTML surrounding select boxes and buttons
  514.      * @param string $js   (optional) if we need to include qfams javascript handler
  515.      *
  516.      * @access     public
  517.      * @return     string 
  518.      * @since      version 0.4.0 (2005-06-25)
  519.      */
  520.     function setElementTemplate($html = null$js = true)
  521.     {
  522.         $oldTemplate $this->_elementTemplate;
  523.  
  524.         if (isset($html&& is_string($html)) {
  525.             $this->_elementTemplate $html;
  526.         else {
  527.             $this->_elementTemplate '
  528. {javascript}
  529. <table{class}>
  530. <!-- BEGIN label_2 --><tr><th>{label_2}</th><!-- END label_2 -->
  531. <!-- BEGIN label_3 --><th>&nbsp;</th><th>{label_3}</th></tr><!-- END label_3 -->
  532. <tr>
  533.   <td valign="top">{unselected}</td>
  534.   <td align="center">{add}{remove}</td>
  535.   <td valign="top">{selected}</td>
  536. </tr>
  537. </table>
  538. ';
  539.         }
  540.         if ($js == false{
  541.             $this->_elementTemplate str_replace('{javascript}''',
  542.                                                   $this->_elementTemplate);
  543.         }
  544.         return $oldTemplate;
  545.     }
  546.  
  547.     /**
  548.      * Gets default element stylesheet for a single multi-select shape render
  549.      *
  550.      * In <b>custom example 4</b>, the template defined allows
  551.      * a single multi-select checkboxes shape. Useful when javascript is disabled
  552.      * (or when browser is not js compliant). In our example, no need to add
  553.      * javascript code, but css is mandatory.
  554.      *
  555.      * @param boolean $raw (optional) html output with style tags or just raw data
  556.      *
  557.      * @access     public
  558.      * @return     string 
  559.      * @since      version 0.4.0 (2005-06-25)
  560.      *
  561.      * @example    qfams_custom_4.php
  562.      *              Custom example 4: source code
  563.      * @link       http://www.laurent-laville.org/img/qfams/screenshot/custom4.png
  564.      *              Custom example 4: screenshot
  565.      */
  566.     function getElementCss($raw = true)
  567.     {
  568.         $id  $this->getAttribute('name');
  569.         $css str_replace('{id}'$id$this->_elementCSS);
  570.  
  571.         if ($raw !== true{
  572.             $css '<style type="text/css">' . PHP_EOL
  573.                  . '<!--' $css ' -->'    . PHP_EOL
  574.                  . '</style>';
  575.         }
  576.         return $css;
  577.     }
  578.  
  579.     /**
  580.      * Returns the HTML generated for the advanced mutliple select component
  581.      *
  582.      * @access     public
  583.      * @return     string 
  584.      * @since      version 0.4.0 (2005-06-25)
  585.      */
  586.     function toHtml()
  587.     {
  588.         if ($this->_flagFrozen{
  589.             return $this->getFrozenHtml();
  590.         }
  591.  
  592.         $tabs    $this->_getTabs();
  593.         $tab     $this->_getTab();
  594.  
  595.         $selectId       $this->getName();
  596.         $selectName     $this->getName('[]';
  597.         $selectNameFrom $this->getName('-f[]';
  598.         $selectNameTo   $this->getName('-t[]';
  599.         $selected_count = 0;
  600.  
  601.         // placeholder {unselected} existence determines if we will render
  602.         if (strpos($this->_elementTemplate'{unselected}'=== false{
  603.             // ... a single multi-select with checkboxes
  604.             $this->_jsPostfix 'editSelection';
  605.  
  606.             $id $this->getAttribute('name');
  607.  
  608.             $strHtmlSelected  $tab '<div id="qfams_'.$id.'">'  . PHP_EOL;
  609.             $unselected_count count($this->_options);
  610.  
  611.             $checkbox_id_suffix = 0;
  612.  
  613.             foreach ($this->_options as $option{
  614.                 $_labelAttributes
  615.                     = array('style''class''onmouseover''onmouseout');
  616.                 $labelAttributes = array();
  617.                 foreach ($_labelAttributes as $attr{
  618.                     if (isset($option['attr'][$attr])) {
  619.                         $labelAttributes[$attr$option['attr'][$attr];
  620.                         unset($option['attr'][$attr]);
  621.                     }
  622.                 }
  623.  
  624.                 if (is_array($this->_values)
  625.                     && in_array((string)$option['attr']['value']$this->_values)) {
  626.                     // The items is *selected*
  627.                     $checked ' checked="checked"';
  628.                     $selected_count++;
  629.                 else {
  630.                     // The item is *unselected* so we want to put it
  631.                     $checked '';
  632.                 }
  633.                 $checkbox_id_suffix++;
  634.                 $strHtmlSelected .= $tab
  635.                                  .  '<label'
  636.                                  .  $this->_getAttrString($labelAttributes.'>'
  637.                                  .  '<input type="checkbox"'
  638.                                  .  ' id="'.$selectId $checkbox_id_suffix.'"'
  639.                                  .  ' name="'.$selectName.'"'
  640.                                  .  $checked
  641.                                  .  $this->_getAttrString($option['attr'])
  642.                                  .  ' />' .  $option['text''</label>'
  643.                                  .  PHP_EOL;
  644.             }
  645.             $strHtmlSelected .= $tab '</div>'. PHP_EOL;
  646.  
  647.             $strHtmlHidden     '';
  648.             $strHtmlUnselected '';
  649.             $strHtmlAdd        '';
  650.             $strHtmlRemove     '';
  651.  
  652.             // build the select all button with all its attributes
  653.             $jsName     $this->_jsPrefix $this->_jsPostfix;
  654.             $attributes = array('onclick' => $jsName .
  655.                                              "('"$selectId ."', 1);");
  656.             $this->_allButtonAttributes
  657.                         = array_merge($this->_allButtonAttributes$attributes);
  658.             $attrStrAll $this->_getAttrString($this->_allButtonAttributes);
  659.             $strHtmlAll = "<input$attrStrAll />". PHP_EOL;
  660.  
  661.             // build the select none button with all its attributes
  662.             $attributes = array('onclick' => $jsName .
  663.                                              "('"$selectId ."', 0);");
  664.             $this->_noneButtonAttributes
  665.                          = array_merge($this->_noneButtonAttributes$attributes);
  666.             $attrStrNone $this->_getAttrString($this->_noneButtonAttributes);
  667.             $strHtmlNone = "<input$attrStrNone />". PHP_EOL;
  668.  
  669.             // build the toggle selection button with all its attributes
  670.             $attributes = array('onclick' => $jsName .
  671.                                              "('"$selectId ."', 2);");
  672.             $this->_toggleButtonAttributes
  673.                            = array_merge($this->_toggleButtonAttributes,
  674.                                  $attributes);
  675.             $attrStrToggle $this->_getAttrString($this->_toggleButtonAttributes);
  676.             $strHtmlToggle = "<input$attrStrToggle />". PHP_EOL;
  677.  
  678.             $strHtmlMoveUp      '';
  679.             $strHtmlMoveDown    '';
  680.             $strHtmlMoveTop     '';
  681.             $strHtmlMoveBottom  '';
  682.  
  683.             // default selection counters
  684.             $strHtmlSelectedCount $selected_count '/' $unselected_count;
  685.         else {
  686.             // ... or a dual multi-select
  687.             $this->_jsPostfix 'moveSelection';
  688.             $jsName           $this->_jsPrefix $this->_jsPostfix;
  689.  
  690.             // set name of Select From Box
  691.             $this->_attributesUnselected
  692.                 = array('id' => $selectId '-f',
  693.                         'name' => $selectNameFrom,
  694.                         'ondblclick' => $jsName .
  695.                             "('{$selectId}', ".
  696.                             "this.form.elements['" $selectNameFrom "'], " .
  697.                             "this.form.elements['" $selectNameTo "'], " .
  698.                             "this.form.elements['" $selectName "'], " .
  699.                             "'add', '{$this->_sort}')");
  700.             $this->
  701. _attributesUnselected
  702.                 = array_merge($this->_attributes$this->_attributesUnselected);
  703.             $attrUnselected $this->_getAttrString($this->_attributesUnselected);
  704.  
  705.             // set name of Select To Box
  706.             $this->
  707. _attributesSelected
  708.                 = array('id' => $selectId '-t',
  709.                         'name' => $selectNameTo,
  710.                         'ondblclick' => $jsName .
  711.                             "('{$selectId}', " .
  712.                             "this.form.elements['" . $selectNameFrom . "'], " .
  713.                             "this.form.elements['" . $selectNameTo . "'], ".
  714.                             "this.form.elements['" . $selectName . "'], " .
  715.                             "'remove', '{$this->_sort}')");
  716.             $this->
  717. _attributesSelected
  718.                 = array_merge($this->_attributes$this->_attributesSelected);
  719.             $attrSelected $this->_getAttrString($this->_attributesSelected);
  720.  
  721.             // set name of Select hidden Box
  722.             $this->
  723. _attributesHidden
  724.                 = array('name' => $selectName,
  725.                         'style' => 'overflow: hidden; visibility: hidden; ' .
  726.                                    'width: 1px; height: 0;');
  727.             $this->
  728. _attributesHidden
  729.                 = array_merge($this->_attributes$this->_attributesHidden);
  730.             $attrHidden $this->_getAttrString($this->_attributesHidden);
  731.  
  732.             // prepare option tables to be displayed as in POST order
  733.             $append = count($this->_values);
  734.             if ($append > 0{
  735.                 $arrHtmlSelected = array_fill(0, $append, ' ');
  736.             } else {
  737.                 $arrHtmlSelected = array();
  738.             }
  739.  
  740.             $options           = count($this->_options);
  741.             $arrHtmlUnselected = array();
  742.             if ($options > 0{
  743.                 $arrHtmlHidden = array_fill(0, $options, ' ');
  744.  
  745.                 foreach ($this->_options as $option{
  746.                     if (is_array($this->_values)
  747.                         && in_array((string)$option['attr']['value'],
  748.                                $this->_values)) {
  749.                         // Get the post order
  750.                         $key = array_search($option['attr']['value'],
  751.                                    $this->_values);
  752.  
  753.                         /** The items is *selected* so we want to put it
  754.                             in the 'selected' multi-select */
  755.                         $arrHtmlSelected[$key$option;
  756.                         /** Add it to the 'hidden' multi-select
  757.                             and set it as 'selected' */
  758.                         if (isset($option['attr']['disabled'])) {
  759.                             unset($option['attr']['disabled']);
  760.                         }
  761.                         $option['attr']['selected'] = 'selected';
  762.                         $arrHtmlHidden[$key]        = $option;
  763.                     } else {
  764.                         /** The item is *unselected* so we want to put it
  765.                             in the 'unselected' multi-select */
  766.                         $arrHtmlUnselected[] = $option;
  767.                         // Add it to the hidden multi-select as 'unselected'
  768.                         $arrHtmlHidden[$append] = $option;
  769.                         $append++;
  770.                     }
  771.                 }
  772.             } else {
  773.                 $arrHtmlHidden = array();
  774.             }
  775.  
  776.             // The 'unselected' multi-select which appears on the left
  777.             $unselected_count = count($arrHtmlUnselected);
  778.  
  779.             if ($unselected_count == 0) {
  780.                 $this->_attributesUnselected['disabled''disabled';
  781.                 $this->
  782. _attributesUnselected
  783.                     = array_merge($this->_attributes$this->_attributesUnselected);
  784.                 $attrUnselected $this->_getAttrString($this->_attributesUnselected);
  785.             }
  786.             $strHtmlUnselected = "<select$attrUnselected>". PHP_EOL;
  787.             if ($unselected_count > 0) {
  788.                 foreach ($arrHtmlUnselected as $data) {
  789.                     $strHtmlUnselected
  790.                         .= $tabs . $tab
  791.                         . '<option' . $this->_getAttrString($data['attr']'>'
  792.                         . $data['text''</option>' . PHP_EOL;
  793.                 }
  794.             } else {
  795.                 $strHtmlUnselected .= '<option value="">&nbsp;</option>';
  796.             }
  797.             $strHtmlUnselected .= '</select>';
  798.  
  799.             // The 'selected' multi-select which appears on the right
  800.             $selected_count = count($arrHtmlSelected);
  801.  
  802.             if ($selected_count == 0) {
  803.                 $this->_attributesSelected['disabled''disabled';
  804.                 $this->
  805. _attributesSelected
  806.                     = array_merge($this->_attributes$this->_attributesSelected);
  807.                 $attrSelected $this->_getAttrString($this->_attributesSelected);
  808.             }
  809.             $strHtmlSelected = "<select$attrSelected>". PHP_EOL;
  810.             if ($selected_count > 0) {
  811.                 foreach ($arrHtmlSelected as $data) {
  812.                     $strHtmlSelected
  813.                         .= $tabs . $tab
  814.                         . '<option' . $this->_getAttrString($data['attr']'>'
  815.                         . $data['text''</option>' . PHP_EOL;
  816.                 }
  817.             } else {
  818.                 $strHtmlSelected .= '<option value="">&nbsp;</option>';
  819.             }
  820.             $strHtmlSelected .= '</select>';
  821.  
  822.             // The 'hidden' multi-select
  823.             $strHtmlHidden = "<select$attrHidden>". PHP_EOL;
  824.             if (count($arrHtmlHidden) > 0) {
  825.                 foreach ($arrHtmlHidden as $data) {
  826.                     $strHtmlHidden
  827.                         .= $tabs . $tab
  828.                         . '<option' . $this->_getAttrString($data['attr']'>'
  829.                         . $data['text''</option>' . PHP_EOL;
  830.                 }
  831.             }
  832.             $strHtmlHidden .= '</select>';
  833.  
  834.             // build the remove button with all its attributes
  835.             $attributes
  836.                 = array('onclick' => $jsName .
  837.                             "('{$selectId}', " .
  838.                             "this.form.elements['" . $selectNameFrom . "'], " .
  839.                             "this.form.elements['" . $selectNameTo . "'], " .
  840.                             "this.form.elements['" . $selectName . "'], " .
  841.                             "'remove', '{$this->_sort}'); return false;");
  842.             $this->
  843. _removeButtonAttributes
  844.                 = array_merge($this->_removeButtonAttributes$attributes);
  845.             $attrStrRemove $this->_getAttrString($this->_removeButtonAttributes);
  846.             $strHtmlRemove "<input$attrStrRemove />". PHP_EOL;
  847.  
  848.             // build the add button with all its attributes
  849.             $attributes
  850.                 = array('onclick' => $jsName .
  851.                             "('{$selectId}', " .
  852.                             "this.form.elements['" . $selectNameFrom . "'], " .
  853.                             "this.form.elements['" . $selectNameTo . "'], " .
  854.                             "this.form.elements['" . $selectName . "'], " .
  855.                             "'add', '{$this->_sort}'); return false;");
  856.             $this->
  857. _addButtonAttributes
  858.                 = array_merge($this->_addButtonAttributes$attributes);
  859.             $attrStrAdd $this->_getAttrString($this->_addButtonAttributes);
  860.             $strHtmlAdd "<input$attrStrAdd />". PHP_EOL;
  861.  
  862.             // build the select all button with all its attributes
  863.             $attributes
  864.                 = array('onclick' => $jsName .
  865.                             "('{$selectId}', " .
  866.                             "this.form.elements['" . $selectNameFrom . "'], " .
  867.                             "this.form.elements['" . $selectNameTo . "'], " .
  868.                             "this.form.elements['" . $selectName . "'], " .
  869.                             "'all', '{$this->_sort}'); return false;");
  870.             $this->
  871. _allButtonAttributes
  872.                 = array_merge($this->_allButtonAttributes$attributes);
  873.             $attrStrAll $this->_getAttrString($this->_allButtonAttributes);
  874.             $strHtmlAll "<input$attrStrAll />". PHP_EOL;
  875.  
  876.             // build the select none button with all its attributes
  877.             $attributes
  878.                 = array('onclick' => $jsName .
  879.                             "('{$selectId}', " .
  880.                             "this.form.elements['" . $selectNameFrom . "'], " .
  881.                             "this.form.elements['" . $selectNameTo . "'], " .
  882.                             "this.form.elements['" . $selectName . "'], " .
  883.                             "'none', '{$this->_sort}'); return false;");
  884.             $this->
  885. _noneButtonAttributes
  886.                 = array_merge($this->_noneButtonAttributes$attributes);
  887.             $attrStrNone $this->_getAttrString($this->_noneButtonAttributes);
  888.             $strHtmlNone "<input$attrStrNone />". PHP_EOL;
  889.  
  890.             // build the toggle button with all its attributes
  891.             $attributes
  892.                 = array('onclick' => $jsName .
  893.                             "('{$selectId}', " .
  894.                             "this.form.elements['" . $selectNameFrom . "'], " .
  895.                             "this.form.elements['" . $selectNameTo . "'], " .
  896.                             "this.form.elements['" . $selectName . "'], " .
  897.                             "'toggle', '{$this->_sort}'); return false;");
  898.             $this->
  899. _toggleButtonAttributes
  900.                 = array_merge($this->_toggleButtonAttributes$attributes);
  901.             $attrStrToggle $this->_getAttrString($this->_toggleButtonAttributes);
  902.             $strHtmlToggle "<input$attrStrToggle />". PHP_EOL;
  903.  
  904.             // build the move up button with all its attributes
  905.             $attributes
  906.                 = array('onclick' => "{$this->_jsPrefix}moveUp" .
  907.                             "(this.form.elements['" . $selectNameTo . "'], " .
  908.                             "this.form.elements['" . $selectName . "']); " .
  909.                             "return false;");
  910.             $this->
  911. _upButtonAttributes
  912.                 = array_merge($this->_upButtonAttributes$attributes);
  913.             $attrStrUp     $this->_getAttrString($this->_upButtonAttributes);
  914.             $strHtmlMoveUp "<input$attrStrUp />". PHP_EOL;
  915.  
  916.             // build the move down button with all its attributes
  917.             $attributes
  918.                 = array('onclick' => "{$this->_jsPrefix}moveDown" .
  919.                             "(this.form.elements['" . $selectNameTo . "'], " .
  920.                             "this.form.elements['" . $selectName . "']); " .
  921.                             "return false;");
  922.             $this->
  923. _downButtonAttributes
  924.                 = array_merge($this->_downButtonAttributes$attributes);
  925.             $attrStrDown     $this->_getAttrString($this->_downButtonAttributes);
  926.             $strHtmlMoveDown "<input$attrStrDown />". PHP_EOL;
  927.  
  928.             // build the move top button with all its attributes
  929.             $attributes
  930.                 = array('onclick' => "{$this->_jsPrefix}moveTop" .
  931.                             "(this.form.elements['" . $selectNameTo . "'], " .
  932.                             "this.form.elements['" . $selectName . "']); " .
  933.                             "return false;");
  934.             $this->
  935. _topButtonAttributes
  936.                 = array_merge($this->_topButtonAttributes$attributes);
  937.             $attrStrTop     $this->_getAttrString($this->_topButtonAttributes);
  938.             $strHtmlMoveTop "<input$attrStrTop />". PHP_EOL;
  939.  
  940.             // build the move bottom button with all its attributes
  941.             $attributes
  942.                 = array('onclick' => "{$this->_jsPrefix}moveBottom" .
  943.                             "(this.form.elements['" . $selectNameTo . "'], " .
  944.                             "this.form.elements['" . $selectName . "']); " .
  945.                             "return false;");
  946.             $this->
  947. _bottomButtonAttributes
  948.                 = array_merge($this->_bottomButtonAttributes$attributes);
  949.             $attrStrBottom     $this->_getAttrString($this->_bottomButtonAttributes);
  950.             $strHtmlMoveBottom "<input$attrStrBottom />". PHP_EOL;
  951.  
  952.             // default selection counters
  953.             $strHtmlSelectedCount = $selected_count;
  954.         }
  955.         $strHtmlUnselectedCount = $unselected_count;
  956.  
  957.         $strHtmlSelectedCountId   = $selectId .'_selected';
  958.         $strHtmlUnselectedCountId = $selectId .'_unselected';
  959.  
  960.         // render all part of the multi select component with the template
  961.         $strHtml = $this->_elementTemplate;
  962.  
  963.         // Prepare multiple labels
  964.         $labels $this->getLabel();
  965.         if (is_array($labels)) {
  966.             array_shift($labels);
  967.         }
  968.         // render extra labels, if any
  969.         if (is_array($labels)) {
  970.             foreach ($labels as $key => $text) {
  971.                 $key     = is_int($key)$key + 2: $key;
  972.                 $strHtml = str_replace("{label_{$key}}", $text, $strHtml);
  973.                 $strHtml = str_replace("<!-- BEGIN label_{$key} -->", '', $strHtml);
  974.                 $strHtml = str_replace("<!-- END label_{$key} -->", '', $strHtml);
  975.             }
  976.         }
  977.         // clean up useless label tags
  978.         if (strpos($strHtml, '{label_')) {
  979.             $strHtml = preg_replace('/\s*<!-- BEGIN label_(\S+) -->'.
  980.                            '.*<!-- END label_\1 -->\s*/i', '', $strHtml);
  981.         }
  982.  
  983.         $placeHolders = array(
  984.             '{stylesheet}', '{javascript}',
  985.             '{class}',
  986.             '{unselected_count_id}', '{selected_count_id}',
  987.             '{unselected_count}', '{selected_count}',
  988.             '{unselected}', '{selected}',
  989.             '{add}', '{remove}',
  990.             '{all}', '{none}', '{toggle}',
  991.             '{moveup}', '{movedown}',
  992.             '{movetop}', '{movebottom}'
  993.         );
  994.         $htmlElements = array(
  995.             $this->getElementCss(false)$this->getElementJs(false),
  996.             $this->_tableAttributes,
  997.             $strHtmlUnselectedCountId$strHtmlSelectedCountId,
  998.             $strHtmlUnselectedCount$strHtmlSelectedCount,
  999.             $strHtmlUnselected$strHtmlSelected $strHtmlHidden,
  1000.             $strHtmlAdd$strHtmlRemove,
  1001.             $strHtmlAll$strHtmlNone$strHtmlToggle,
  1002.             $strHtmlMoveUp$strHtmlMoveDown,
  1003.             $strHtmlMoveTop$strHtmlMoveBottom
  1004.         );
  1005.  
  1006.         $strHtml = str_replace($placeHolders$htmlElements$strHtml);
  1007.  
  1008.         $comment $this->getComment();
  1009.  
  1010.         if (!empty($comment)) {
  1011.             $strHtml = $tabs . '<!-- ' . $comment . " //-->" . PHP_EOL . $strHtml;
  1012.         }
  1013.  
  1014.         return $strHtml;
  1015.     }
  1016.  
  1017.     /**
  1018.      * Returns the javascript code generated to handle this element
  1019.      *
  1020.      * @param boolean $raw (optional) html output with script tags or just raw data
  1021.      * @param boolean $min (optional) uses javascript compressed version
  1022.      *
  1023.      * @access     public
  1024.      * @return     string
  1025.      * @since      version 0.4.0 (2005-06-25)
  1026.      */
  1027.     function getElementJs($raw = true, $min = false)
  1028.     {
  1029.         $js = '@data_dir@' . DIRECTORY_SEPARATOR
  1030.             . '@package_name@' . DIRECTORY_SEPARATOR;
  1031.  
  1032.         if ($min) {
  1033.             $js .= 'qfamsHandler-min.js';
  1034.         } else {
  1035.             $js .= 'qfamsHandler.js';
  1036.         }
  1037.  
  1038.         if (file_exists($js)) {
  1039.             $js = file_get_contents($js);
  1040.         } else {
  1041.             $js = '';
  1042.         }
  1043.  
  1044.         if ($raw !== true) {
  1045.             $js = '<script type="text/javascript">'
  1046.                 . PHP_EOL . '//<![CDATA['
  1047.                 . PHP_EOL . $js
  1048.                 . PHP_EOL . '//]]>'
  1049.                 . PHP_EOL . '</script>'
  1050.                 . PHP_EOL;
  1051.         }
  1052.         return $js;
  1053.     }
  1054.  
  1055.     /**
  1056.      * Loads options from different types of data sources
  1057.      *
  1058.      * This method overloaded parent method of select element, to allow
  1059.      * loading options with fancy attributes.
  1060.      *
  1061.      * @param mixed &$options Options source currently supports assoc array or DB_result
  1062.      * @param mixed $param1   (optional) See function detail
  1063.      * @param mixed $param2   (optional) See function detail
  1064.      * @param mixed $param3   (optional) See function detail
  1065.      * @param mixed $param4   (optional) See function detail
  1066.      *
  1067.      * @access     public
  1068.      * @since      version 1.5.0 (2009-02-15)
  1069.      * @return     PEAR_Error|NULL on error and TRUE on success
  1070.      * @throws     PEAR_Error
  1071.      * @see        loadArray()
  1072.      */
  1073.     function load(&$options,
  1074.                   $param1 = null, $param2 = null, $param3 = null, $param4 = null)
  1075.     {
  1076.         if (is_array($options)) {
  1077.             $ret = $this->loadArray($options$param1);
  1078.         } else {
  1079.             $ret = parent::load($options, $param1, $param2, $param3, $param4);
  1080.         }
  1081.         return $ret;
  1082.     }
  1083.  
  1084.     /**
  1085.      * Loads the options from an associative array
  1086.      *
  1087.      * This method overloaded parent method of select element, to allow to load
  1088.      * array of options with fancy attributes.
  1089.      *
  1090.      * @param array $arr    Associative array of options
  1091.      * @param mixed $values (optional) Array or comma delimited string of selected values
  1092.      *
  1093.      * @since      version 1.5.0 (2009-02-15)
  1094.      * @access     public
  1095.      * @return     PEAR_Error on error and TRUE on success
  1096.      * @throws     PEAR_Error
  1097.      * @see        load()
  1098.      */
  1099.     function loadArray($arr, $values = null)
  1100.     {
  1101.         if (!is_array($arr)) {
  1102.             return PEAR::throwError('Argument 1 of HTML_QuickForm_advmultiselect::' .
  1103.                        'loadArray is not a valid array',
  1104.                        HTML_QUICKFORM_ADVMULTISELECT_ERROR_INVALID_INPUT,
  1105.                        array('level' => 'exception'));
  1106.         }
  1107.         if (isset($values)) {
  1108.             $this->setSelected($values);
  1109.         }
  1110.         if (is_array($arr)) {
  1111.             foreach ($arr as $key => $val) {
  1112.                 if (is_array($val)) {
  1113.                     $this->addOption($val[0]$key$val[1]);
  1114.                 } else {
  1115.                     $this->addOption($val$key);
  1116.                 }
  1117.             }
  1118.         }
  1119.         return true;
  1120.     }
  1121.  
  1122.     /**
  1123.      * Sets which items should be persistant
  1124.      *
  1125.      * Sets which items should have the disabled attribute
  1126.      * to keep it persistant
  1127.      *
  1128.      * @param mixed $optionValues Options (key-values) that should be persistant
  1129.      * @param bool  $persistant   (optional) TRUE if persistant, FALSE otherwise
  1130.      *
  1131.      * @since      version 1.5.0 (2009-02-15)
  1132.      * @access     public
  1133.      * @return     PEAR_Error on error and TRUE on success
  1134.      * @throws     PEAR_Error
  1135.      */
  1136.     function setPersistantOptions($optionValues, $persistant = true)
  1137.     {
  1138.         if (!is_bool($persistant)) {
  1139.             return PEAR::throwError('Argument 2 of HTML_QuickForm_advmultiselect::' .
  1140.                        'setPersistantOptions is not a boolean',
  1141.                        HTML_QUICKFORM_ADVMULTISELECT_ERROR_INVALID_INPUT,
  1142.                        array('level' => 'exception'));
  1143.         }
  1144.         if (is_string($optionValues)) {
  1145.             $optionValues = array($optionValues);
  1146.         }
  1147.         if (!is_array($optionValues)) {
  1148.             return PEAR::throwError('Argument 1 of HTML_QuickForm_advmultiselect::' .
  1149.                        'setPersistantOptions is not a valid array',
  1150.                        HTML_QUICKFORM_ADVMULTISELECT_ERROR_INVALID_INPUT,
  1151.                        array('level' => 'exception'));
  1152.         }
  1153.  
  1154.         foreach ($this->_options as $k => $v{
  1155.             if (in_array($v['attr']['value'], $optionValues)) {
  1156.                 if ($persistant) {
  1157.                     $this->_options[$k]['attr']['disabled''disabled';
  1158.                 } else {
  1159.                     unset($this->_options[$k]['attr']['disabled']);
  1160.                 }
  1161.             }
  1162.         }
  1163.         return true;
  1164.     }
  1165.  
  1166.     /**
  1167.      * Returns list of persistant options
  1168.      *
  1169.      * Returns list of persistant options (key-values) that could not
  1170.      * be selected or unselected.
  1171.      *
  1172.      * @since      version 1.5.0 (2009-02-15)
  1173.      * @access     public
  1174.      * @return     array
  1175.      */
  1176.     function getPersistantOptions()
  1177.     {
  1178.         $options = array();
  1179.  
  1180.         foreach ($this->_options as $k => $v{
  1181.             if (isset($v['attr']['disabled'])) {
  1182.                 $options[] = $this->_options[$k]['attr']['value'];
  1183.             }
  1184.         }
  1185.  
  1186.         return $options;
  1187.     }
  1188. }
  1189.  
  1190. if (class_exists('HTML_QuickForm')) {
  1191.     HTML_QuickForm::registerElementType('advmultiselect',
  1192.         'HTML/QuickForm/advmultiselect.php', 'HTML_QuickForm_advmultiselect');
  1193. }

Documentation generated on Sun, 05 Apr 2009 07:30:04 +0000 by phpDocumentor 1.4.2. PEAR Logo Copyright © PHP Group 2004.