Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/pear/HTML/QuickForm/hierselect.php
Go to the documentation of this file.
00001 <?php
00002 /* vim: set expandtab tabstop=4 shiftwidth=4: */
00003 // +----------------------------------------------------------------------+
00004 // | PHP version 4.0                                                      |
00005 // +----------------------------------------------------------------------+
00006 // | Copyright (c) 1997-2004 The PHP Group                                |
00007 // +----------------------------------------------------------------------+
00008 // | This source file is subject to version 2.0 of the PHP license,       |
00009 // | that is bundled with this package in the file LICENSE, and is        |
00010 // | available at through the world-wide-web at                           |
00011 // | http://www.php.net/license/2_02.txt.                                 |
00012 // | If you did not receive a copy of the PHP license and are unable to   |
00013 // | obtain it through the world-wide-web, please send a note to          |
00014 // | license@php.net so we can mail you a copy immediately.               |
00015 // +----------------------------------------------------------------------+
00016 // | Authors: Herim Vasquez <vasquezh@iro.umontreal.ca>                   |
00017 // |          Bertrand Mansion <bmansion@mamasam.com>                     |
00018 // |          Alexey Borzov <avb@php.net>
00019 // +----------------------------------------------------------------------+
00020 //
00021 // $Id: hierselect.php,v 1.3 2010/12/14 17:35:24 moodlerobot Exp $
00022 
00023 require_once('HTML/QuickForm/group.php');
00024 require_once('HTML/QuickForm/select.php');
00025 
00038 class HTML_QuickForm_hierselect extends HTML_QuickForm_group
00039 {
00040     // {{{ properties
00041 
00084     var $_options = array();
00085 
00092     var $_nbElements = 0;
00093 
00100     var $_js = '';
00101 
00102     // }}}
00103     // {{{ constructor
00104 
00117     function HTML_QuickForm_hierselect($elementName=null, $elementLabel=null, $attributes=null, $separator=null)
00118     {
00119         $this->HTML_QuickForm_element($elementName, $elementLabel, $attributes);
00120         $this->_persistantFreeze = true;
00121         if (isset($separator)) {
00122             $this->_separator = $separator;
00123         }
00124         $this->_type = 'hierselect';
00125         $this->_appendName = true;
00126     } //end constructor
00127 
00128     // }}}
00129     // {{{ setOptions()
00130 
00140     function setOptions($options)
00141     {
00142         $this->_options = $options;
00143 
00144         if (empty($this->_elements)) {
00145             $this->_nbElements = count($this->_options);
00146             $this->_createElements();
00147         } else {
00148             // setDefaults has probably been called before this function
00149             // check if all elements have been created
00150             $totalNbElements = count($this->_options);
00151             for ($i = $this->_nbElements; $i < $totalNbElements; $i ++) {
00152                 $this->_elements[] = new HTML_QuickForm_select($i, null, array(), $this->getAttributes());
00153                 $this->_nbElements++;
00154             }
00155         }
00156 
00157         $this->_setOptions();
00158     } // end func setMainOptions
00159 
00160     // }}}
00161     // {{{ setMainOptions()
00162 
00172     function setMainOptions($array)
00173     {
00174         $this->_options[0] = $array;
00175 
00176         if (empty($this->_elements)) {
00177             $this->_nbElements = 2;
00178             $this->_createElements();
00179         }
00180     } // end func setMainOptions
00181 
00182     // }}}
00183     // {{{ setSecOptions()
00184 
00195     function setSecOptions($array)
00196     {
00197         $this->_options[1] = $array;
00198 
00199         if (empty($this->_elements)) {
00200             $this->_nbElements = 2;
00201             $this->_createElements();
00202         } else {
00203             // setDefaults has probably been called before this function
00204             // check if all elements have been created
00205             $totalNbElements = 2;
00206             for ($i = $this->_nbElements; $i < $totalNbElements; $i ++) {
00207                 $this->_elements[] = new HTML_QuickForm_select($i, null, array(), $this->getAttributes());
00208                 $this->_nbElements++;
00209             }
00210         }
00211 
00212         $this->_setOptions();
00213     } // end func setSecOptions
00214 
00215     // }}}
00216     // {{{ _setOptions()
00217 
00224     function _setOptions()
00225     {
00226         $toLoad = '';
00227         foreach (array_keys($this->_elements) AS $key) {
00228             $array = eval("return isset(\$this->_options[{$key}]{$toLoad})? \$this->_options[{$key}]{$toLoad}: null;");
00229             if (is_array($array)) {
00230                 $select =& $this->_elements[$key];
00231                 $select->_options = array();
00232                 $select->loadArray($array);
00233 
00234                 $value  = is_array($v = $select->getValue()) ? $v[0] : key($array);
00235                 $toLoad .= '[\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $value) . '\']';
00236             }
00237         }
00238     } // end func _setOptions
00239 
00240     // }}}
00241     // {{{ setValue()
00242 
00252     function setValue($value)
00253     {
00254         // fix for bug #6766. Hope this doesn't break anything more
00255         // after bug #7961. Forgot that _nbElements was used in
00256         // _createElements() called in several places...
00257         $this->_nbElements = max($this->_nbElements, count($value));
00258         parent::setValue($value);
00259         $this->_setOptions();
00260     } // end func setValue
00261 
00262     // }}}
00263     // {{{ _createElements()
00264 
00271     function _createElements()
00272     {
00273         for ($i = 0; $i < $this->_nbElements; $i++) {
00274             $this->_elements[] = new HTML_QuickForm_select($i, null, array(), $this->getAttributes());
00275         }
00276     } // end func _createElements
00277 
00278     // }}}
00279     // {{{ toHtml()
00280 
00281     function toHtml()
00282     {
00283         $this->_js = '';
00284         if (!$this->_flagFrozen) {
00285             // set the onchange attribute for each element except last
00286             $keys     = array_keys($this->_elements);
00287             $onChange = array();
00288             for ($i = 0; $i < count($keys) - 1; $i++) {
00289                 $select =& $this->_elements[$keys[$i]];
00290                 $onChange[$i] = $select->getAttribute('onchange');
00291                 $select->updateAttributes(
00292                     array('onchange' => '_hs_swapOptions(this.form, \'' . $this->_escapeString($this->getName()) . '\', ' . $keys[$i] . ');' . $onChange[$i])
00293                 );
00294             }
00295 
00296             // create the js function to call
00297             if (!defined('HTML_QUICKFORM_HIERSELECT_EXISTS')) {
00298                 $this->_js .= <<<JAVASCRIPT
00299 function _hs_findOptions(ary, keys)
00300 {
00301     var key = keys.shift();
00302     if (!key in ary) {
00303         return {};
00304     } else if (0 == keys.length) {
00305         return ary[key];
00306     } else {
00307         return _hs_findOptions(ary[key], keys);
00308     }
00309 }
00310 
00311 function _hs_findSelect(form, groupName, selectIndex)
00312 {
00313     if (groupName+'['+ selectIndex +']' in form) {
00314         return form[groupName+'['+ selectIndex +']'];
00315     } else {
00316         return form[groupName+'['+ selectIndex +'][]'];
00317     }
00318 }
00319 
00320 function _hs_unescapeEntities(str)
00321 {
00322     var div = document.createElement('div');
00323     div.innerHTML = str;
00324     return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
00325 }
00326 
00327 function _hs_replaceOptions(ctl, optionList)
00328 {
00329     var j = 0;
00330     ctl.options.length = 0;
00331     for (i in optionList) {
00332         var optionText = (-1 == optionList[i].indexOf('&'))? optionList[i]: _hs_unescapeEntities(optionList[i]);
00333         ctl.options[j++] = new Option(optionText, i, false, false);
00334     }
00335 }
00336 
00337 function _hs_setValue(ctl, value)
00338 {
00339     var testValue = {};
00340     if (value instanceof Array) {
00341         for (var i = 0; i < value.length; i++) {
00342             testValue[value[i]] = true;
00343         }
00344     } else {
00345         testValue[value] = true;
00346     }
00347     for (var i = 0; i < ctl.options.length; i++) {
00348         if (ctl.options[i].value in testValue) {
00349             ctl.options[i].selected = true;
00350         }
00351     }
00352 }
00353 
00354 function _hs_swapOptions(form, groupName, selectIndex)
00355 {
00356     var hsValue = [];
00357     for (var i = 0; i <= selectIndex; i++) {
00358         hsValue[i] = _hs_findSelect(form, groupName, i).value;
00359     }
00360 
00361     _hs_replaceOptions(_hs_findSelect(form, groupName, selectIndex + 1),
00362                        _hs_findOptions(_hs_options[groupName][selectIndex], hsValue));
00363     if (selectIndex + 1 < _hs_options[groupName].length) {
00364         _hs_swapOptions(form, groupName, selectIndex + 1);
00365     }
00366 }
00367 
00368 function _hs_onReset(form, groupNames)
00369 {
00370     for (var i = 0; i < groupNames.length; i++) {
00371         try {
00372             for (var j = 0; j <= _hs_options[groupNames[i]].length; j++) {
00373                 _hs_setValue(_hs_findSelect(form, groupNames[i], j), _hs_defaults[groupNames[i]][j]);
00374                 if (j < _hs_options[groupNames[i]].length) {
00375                     _hs_replaceOptions(_hs_findSelect(form, groupNames[i], j + 1),
00376                                        _hs_findOptions(_hs_options[groupNames[i]][j], _hs_defaults[groupNames[i]].slice(0, j + 1)));
00377                 }
00378             }
00379         } catch (e) {
00380             if (!(e instanceof TypeError)) {
00381                 throw e;
00382             }
00383         }
00384     }
00385 }
00386 
00387 function _hs_setupOnReset(form, groupNames)
00388 {
00389     setTimeout(function() { _hs_onReset(form, groupNames); }, 25);
00390 }
00391 
00392 function _hs_onReload()
00393 {
00394     var ctl;
00395     for (var i = 0; i < document.forms.length; i++) {
00396         for (var j in _hs_defaults) {
00397             if (ctl = _hs_findSelect(document.forms[i], j, 0)) {
00398                 for (var k = 0; k < _hs_defaults[j].length; k++) {
00399                     _hs_setValue(_hs_findSelect(document.forms[i], j, k), _hs_defaults[j][k]);
00400                 }
00401             }
00402         }
00403     }
00404 
00405     if (_hs_prevOnload) {
00406         _hs_prevOnload();
00407     }
00408 }
00409 
00410 var _hs_prevOnload = null;
00411 if (window.onload) {
00412     _hs_prevOnload = window.onload;
00413 }
00414 window.onload = _hs_onReload;
00415 
00416 var _hs_options = {};
00417 var _hs_defaults = {};
00418 
00419 JAVASCRIPT;
00420                 define('HTML_QUICKFORM_HIERSELECT_EXISTS', true);
00421             }
00422             // option lists
00423             $jsParts = array();
00424             for ($i = 1; $i < $this->_nbElements; $i++) {
00425                 $jsParts[] = $this->_convertArrayToJavascript($this->_options[$i]);
00426             }
00427             $this->_js .= "\n_hs_options['" . $this->_escapeString($this->getName()) . "'] = [\n" .
00428                           implode(",\n", $jsParts) .
00429                           "\n];\n";
00430             // default value; if we don't actually have any values yet just use
00431             // the first option (for single selects) or empty array (for multiple)
00432             $values = array();
00433             foreach (array_keys($this->_elements) as $key) {
00434                 if (is_array($v = $this->_elements[$key]->getValue())) {
00435                     $values[] = count($v) > 1? $v: $v[0];
00436                 } else {
00437                     // XXX: accessing the supposedly private _options array
00438                     $values[] = $this->_elements[$key]->getMultiple() || empty($this->_elements[$key]->_options[0])?
00439                                 array():
00440                                 $this->_elements[$key]->_options[0]['attr']['value'];
00441                 }
00442             }
00443             $this->_js .= "_hs_defaults['" . $this->_escapeString($this->getName()) . "'] = " .
00444                           $this->_convertArrayToJavascript($values, false) . ";\n";
00445         }
00446         include_once('HTML/QuickForm/Renderer/Default.php');
00447         $renderer = new HTML_QuickForm_Renderer_Default();
00448         $renderer->setElementTemplate('{element}');
00449         parent::accept($renderer);
00450 
00451         if (!empty($onChange)) {
00452             $keys     = array_keys($this->_elements);
00453             for ($i = 0; $i < count($keys) - 1; $i++) {
00454                 $this->_elements[$keys[$i]]->updateAttributes(array('onchange' => $onChange[$i]));
00455             }
00456         }
00457         return (empty($this->_js)? '': "<script type=\"text/javascript\">\n//<![CDATA[\n" . $this->_js . "//]]>\n</script>") .
00458                $renderer->toHtml();
00459     } // end func toHtml
00460 
00461     // }}}
00462     // {{{ accept()
00463 
00464     function accept(&$renderer, $required = false, $error = null)
00465     {
00466         $renderer->renderElement($this, $required, $error);
00467     } // end func accept
00468 
00469     // }}}
00470     // {{{ onQuickFormEvent()
00471 
00472     function onQuickFormEvent($event, $arg, &$caller)
00473     {
00474         if ('updateValue' == $event) {
00475             // we need to call setValue() so that the secondary option
00476             // matches the main option
00477             return HTML_QuickForm_element::onQuickFormEvent($event, $arg, $caller);
00478         } else {
00479             $ret = parent::onQuickFormEvent($event, $arg, $caller);
00480             // add onreset handler to form to properly reset hierselect (see bug #2970)
00481             if ('addElement' == $event) {
00482                 $onReset = $caller->getAttribute('onreset');
00483                 if (strlen($onReset)) {
00484                     if (strpos($onReset, '_hs_setupOnReset')) {
00485                         $caller->updateAttributes(array('onreset' => str_replace('_hs_setupOnReset(this, [', "_hs_setupOnReset(this, ['" . $this->_escapeString($this->getName()) . "', ", $onReset)));
00486                     } else {
00487                         $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()) . "']); } "));
00488                     }
00489                 } else {
00490                     $caller->updateAttributes(array('onreset' => "if (typeof _hs_setupOnReset != 'undefined') { return _hs_setupOnReset(this, ['" . $this->_escapeString($this->getName()) . "']); } "));
00491                 }
00492             }
00493             return $ret;
00494         }
00495     } // end func onQuickFormEvent
00496 
00497     // }}}
00498     // {{{ _convertArrayToJavascript()
00499 
00508     function _convertArrayToJavascript($array, $assoc = true)
00509     {
00510         if (!is_array($array)) {
00511             return $this->_convertScalarToJavascript($array);
00512         } else {
00513             $items = array();
00514             foreach ($array as $key => $val) {
00515                 $item = $assoc? "'" . $this->_escapeString($key) . "': ": '';
00516                 if (is_array($val)) {
00517                     $item .= $this->_convertArrayToJavascript($val, $assoc);
00518                 } else {
00519                     $item .= $this->_convertScalarToJavascript($val);
00520                 }
00521                 $items[] = $item;
00522             }
00523         }
00524         $js = implode(', ', $items);
00525         return $assoc? '{ ' . $js . ' }': '[' . $js . ']';
00526     }
00527 
00528     // }}}
00529     // {{{ _convertScalarToJavascript()
00530 
00538     function _convertScalarToJavascript($val)
00539     {
00540         if (is_bool($val)) {
00541             return $val ? 'true' : 'false';
00542         } elseif (is_int($val) || is_double($val)) {
00543             return $val;
00544         } elseif (is_string($val)) {
00545             return "'" . $this->_escapeString($val) . "'";
00546         } elseif (is_null($val)) {
00547             return 'null';
00548         } else {
00549             // don't bother
00550             return '{}';
00551         }
00552     }
00553 
00554     // }}}
00555     // {{{ _escapeString()
00556 
00564     function _escapeString($str)
00565     {
00566         return strtr($str,array(
00567             "\r"    => '\r',
00568             "\n"    => '\n',
00569             "\t"    => '\t',
00570             "'"     => "\\'",
00571             '"'     => '\"',
00572             '\\'    => '\\\\'
00573         ));
00574     }
00575 
00576     // }}}
00577 } // end class HTML_QuickForm_hierselect
00578 ?>
 All Data Structures Namespaces Files Functions Variables Enumerations