advmultiselect.php 47 KB

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