Merge pull request #17310 from agh1/autorenew-active-icon
[civicrm-core.git] / CRM / Core / QuickForm / GroupMultiSelect.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright U.S. PIRG Education Fund (c) 2007 |
7 | Licensed to CiviCRM under the Academic Free License version 3.0. |
8 +--------------------------------------------------------------------+
9 | This file is a part of CiviCRM. |
10 | |
11 | CiviCRM is free software; you can copy, modify, and distribute it |
12 | under the terms of the GNU Affero General Public License |
13 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | |
15 | CiviCRM is distributed in the hope that it will be useful, but |
16 | WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
18 | See the GNU Affero General Public License for more details. |
19 | |
20 | You should have received a copy of the GNU Affero General Public |
21 | License and the CiviCRM Licensing Exception along |
22 | with this program; if not, contact CiviCRM LLC |
23 | at info[AT]civicrm[DOT]org. If you have questions about the |
24 | GNU Affero General Public License or the licensing of CiviCRM, |
25 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
26 +--------------------------------------------------------------------+
27 */
28
29 /**
30 *
31 * @package CRM
32 * @copyright U.S. PIRG Education Fund 2007
33 * $Id$
34 *
35 */
36 class CRM_Core_QuickForm_GroupMultiSelect extends CRM_Core_QuickForm_NestedAdvMultiSelect {
37
38 /**
39 * Returns the HTML generated for the advanced multiple select component.
40 *
41 * @return string
42 * @since version 0.4.0 (2005-06-25)
43 */
44 public function toHtml() {
45 if ($this->_flagFrozen) {
46 return $this->getFrozenHtml();
47 }
48
49 $tabs = $this->_getTabs();
50 $tab = $this->_getTab();
51 $strHtml = '';
52
53 if ($this->getComment() != '') {
54 $strHtml .= $tabs . '<!-- ' . $this->getComment() . " //-->" . PHP_EOL;
55 }
56
57 $selectName = $this->getName() . '[]';
58
59 // placeholder {unselected} existence determines if we will render
60 if (strpos($this->_elementTemplate, '{unselected}') === FALSE) {
61 // ... a single multi-select with checkboxes
62
63 $id = $this->getAttribute('id');
64
65 $strHtmlSelected = $tab . '<div id="' . $id . 'amsSelected">' . PHP_EOL;
66
67 foreach ($this->_options as $option) {
68
69 $_labelAttributes = ['style', 'class', 'onmouseover', 'onmouseout'];
70 $labelAttributes = [];
71 foreach ($_labelAttributes as $attr) {
72 if (isset($option['attr'][$attr])) {
73 $labelAttributes[$attr] = $option['attr'][$attr];
74 unset($option['attr'][$attr]);
75 }
76 }
77
78 if (is_array($this->_values) && in_array((string) $option['attr']['value'], $this->_values)) {
79 // The items is *selected*
80 $checked = ' checked="checked"';
81 }
82 else {
83 // The item is *unselected* so we want to put it
84 $checked = '';
85 }
86 $strHtmlSelected .= $tab . '<label' . $this->_getAttrString($labelAttributes) . '>' . '<input type="checkbox"' . ' id="' . $this->getName() . '"' . ' name="' . $selectName . '"' . $checked . $this->_getAttrString($option['attr']) . ' />' . $option['text'] . '</label>' . PHP_EOL;
87 }
88 $strHtmlSelected .= $tab . '</div>' . PHP_EOL;
89
90 $strHtmlHidden = '';
91 $strHtmlUnselected = '';
92 $strHtmlAdd = '';
93 $strHtmlRemove = '';
94
95 // build the select all button with all its attributes
96 $attributes = ['onclick' => "{$this->_jsPrefix}{$this->_jsPostfix}('" . $this->getName() . "', 1);"];
97 $this->_allButtonAttributes = array_merge($this->_allButtonAttributes, $attributes);
98 $attrStrAll = $this->_getAttrString($this->_allButtonAttributes);
99 $strHtmlAll = "<input$attrStrAll />" . PHP_EOL;
100
101 // build the select none button with all its attributes
102 $attributes = ['onclick' => "{$this->_jsPrefix}{$this->_jsPostfix}('" . $this->getName() . "', 0);"];
103 $this->_noneButtonAttributes = array_merge($this->_noneButtonAttributes, $attributes);
104 $attrStrNone = $this->_getAttrString($this->_noneButtonAttributes);
105 $strHtmlNone = "<input$attrStrNone />" . PHP_EOL;
106
107 // build the toggle selection button with all its attributes
108 $attributes = ['onclick' => "{$this->_jsPrefix}{$this->_jsPostfix}('" . $this->getName() . "', 2);"];
109 $this->_toggleButtonAttributes = array_merge($this->_toggleButtonAttributes, $attributes);
110 $attrStrToggle = $this->_getAttrString($this->_toggleButtonAttributes);
111 $strHtmlToggle = "<input$attrStrToggle />" . PHP_EOL;
112
113 $strHtmlMoveUp = '';
114 $strHtmlMoveDown = '';
115 }
116 else {
117 // ... or a dual multi-select
118
119 // set name of Select From Box
120 $this->_attributesUnselected = [
121 'name' => '__' . $selectName,
122 'ondblclick' => "{$this->_jsPrefix}{$this->_jsPostfix}(this.form.elements['__" . $selectName . "'], this.form.elements['_" . $selectName . "'], this.form.elements['" . $selectName . "'], 'add')",
123 ];
124 $this->_attributesUnselected = array_merge($this->_attributes, $this->_attributesUnselected);
125 $attrUnselected = $this->_getAttrString($this->_attributesUnselected);
126
127 // set name of Select To Box
128 $this->_attributesSelected = [
129 'name' => '_' . $selectName,
130 'ondblclick' => "{$this->_jsPrefix}{$this->_jsPostfix}(this.form.elements['__" . $selectName . "'], this.form.elements['_" . $selectName . "'], this.form.elements['" . $selectName . "'], 'remove')",
131 ];
132 $this->_attributesSelected = array_merge($this->_attributes, $this->_attributesSelected);
133 $attrSelected = $this->_getAttrString($this->_attributesSelected);
134
135 // set name of Select hidden Box
136 $this->_attributesHidden = [
137 'name' => $selectName,
138 'style' => 'overflow: hidden; visibility: hidden; width: 1px; height: 0;',
139 ];
140 $this->_attributesHidden = array_merge($this->_attributes, $this->_attributesHidden);
141 $attrHidden = $this->_getAttrString($this->_attributesHidden);
142
143 // prepare option tables to be displayed as in POST order
144 $append = count($this->_values);
145 if ($append > 0) {
146 $arrHtmlSelected = array_fill(0, $append, ' ');
147 }
148 else {
149 $arrHtmlSelected = [];
150 }
151
152 $options = count($this->_options);
153 $arrHtmlUnselected = [];
154 if ($options > 0) {
155 $arrHtmlHidden = array_fill(0, $options, ' ');
156
157 foreach ($this->_options as $option) {
158 if (is_array($this->_values) &&
159 in_array((string) $option['attr']['value'], $this->_values)
160 ) {
161 // Get the post order
162 $key = array_search($option['attr']['value'], $this->_values);
163
164 // The items is *selected* so we want to put it in the 'selected' multi-select
165 $arrHtmlSelected[$key] = $option;
166 // Add it to the 'hidden' multi-select and set it as 'selected'
167 $option['attr']['selected'] = 'selected';
168 $arrHtmlHidden[$key] = $option;
169 }
170 else {
171 // The item is *unselected* so we want to put it in the 'unselected' multi-select
172 $arrHtmlUnselected[] = $option;
173 // Add it to the hidden multi-select as 'unselected'
174 $arrHtmlHidden[$append] = $option;
175 $append++;
176 }
177 }
178 }
179 else {
180 $arrHtmlHidden = [];
181 }
182
183 // The 'unselected' multi-select which appears on the left
184 $strHtmlUnselected = "<select$attrUnselected>" . PHP_EOL;
185 if (count($arrHtmlUnselected) > 0) {
186 foreach ($arrHtmlUnselected as $data) {
187 $strHtmlUnselected .= $tabs . $tab . '<option' . $this->_getAttrString($data['attr']) . '>' . $data['text'] . '</option>' . PHP_EOL;
188 }
189 }
190 $strHtmlUnselected .= '</select>';
191
192 // The 'selected' multi-select which appears on the right
193 $strHtmlSelected = "<select$attrSelected>" . PHP_EOL;
194 if (count($arrHtmlSelected) > 0) {
195 foreach ($arrHtmlSelected as $data) {
196 $strHtmlSelected .= $tabs . $tab . '<option' . $this->_getAttrString($data['attr']) . '>' . $data['text'] . '</option>' . PHP_EOL;
197 }
198 }
199 $strHtmlSelected .= '</select>';
200
201 // The 'hidden' multi-select
202 $strHtmlHidden = "<select$attrHidden>" . PHP_EOL;
203 if (count($arrHtmlHidden) > 0) {
204 foreach ($arrHtmlHidden as $data) {
205 $strHtmlHidden .= $tabs . $tab . '<option' . $this->_getAttrString($data['attr']) . '>' . $data['text'] . '</option>' . PHP_EOL;
206 }
207 }
208 $strHtmlHidden .= '</select>';
209
210 // build the remove button with all its attributes
211 $attributes = ['onclick' => "{$this->_jsPrefix}{$this->_jsPostfix}(this.form.elements['__" . $selectName . "'], this.form.elements['_" . $selectName . "'], this.form.elements['" . $selectName . "'], 'remove'); return false;"];
212 $this->_removeButtonAttributes = array_merge($this->_removeButtonAttributes, $attributes);
213 $attrStrRemove = $this->_getAttrString($this->_removeButtonAttributes);
214 $strHtmlRemove = "<input$attrStrRemove />" . PHP_EOL;
215
216 // build the add button with all its attributes
217 $attributes = ['onclick' => "{$this->_jsPrefix}{$this->_jsPostfix}(this.form.elements['__" . $selectName . "'], this.form.elements['_" . $selectName . "'], this.form.elements['" . $selectName . "'], 'add'); return false;"];
218 $this->_addButtonAttributes = array_merge($this->_addButtonAttributes, $attributes);
219 $attrStrAdd = $this->_getAttrString($this->_addButtonAttributes);
220 $strHtmlAdd = "<input$attrStrAdd />" . PHP_EOL;
221
222 // build the select all button with all its attributes
223 $attributes = ['onclick' => "{$this->_jsPrefix}{$this->_jsPostfix}(this.form.elements['__" . $selectName . "'], this.form.elements['_" . $selectName . "'], this.form.elements['" . $selectName . "'], 'all'); return false;"];
224 $this->_allButtonAttributes = array_merge($this->_allButtonAttributes, $attributes);
225 $attrStrAll = $this->_getAttrString($this->_allButtonAttributes);
226 $strHtmlAll = "<input$attrStrAll />" . PHP_EOL;
227
228 // build the select none button with all its attributes
229 $attributes = ['onclick' => "{$this->_jsPrefix}{$this->_jsPostfix}(this.form.elements['__" . $selectName . "'], this.form.elements['_" . $selectName . "'], this.form.elements['" . $selectName . "'], 'none'); return false;"];
230 $this->_noneButtonAttributes = array_merge($this->_noneButtonAttributes, $attributes);
231 $attrStrNone = $this->_getAttrString($this->_noneButtonAttributes);
232 $strHtmlNone = "<input$attrStrNone />" . PHP_EOL;
233
234 // build the toggle button with all its attributes
235 $attributes = ['onclick' => "{$this->_jsPrefix}{$this->_jsPostfix}(this.form.elements['__" . $selectName . "'], this.form.elements['_" . $selectName . "'], this.form.elements['" . $selectName . "'], 'toggle'); return false;"];
236 $this->_toggleButtonAttributes = array_merge($this->_toggleButtonAttributes, $attributes);
237 $attrStrToggle = $this->_getAttrString($this->_toggleButtonAttributes);
238 $strHtmlToggle = "<input$attrStrToggle />" . PHP_EOL;
239
240 // build the move up button with all its attributes
241 $attributes = ['onclick' => "{$this->_jsPrefix}moveUp(this.form.elements['_" . $selectName . "'], this.form.elements['" . $selectName . "']); return false;"];
242 $this->_upButtonAttributes = array_merge($this->_upButtonAttributes, $attributes);
243 $attrStrUp = $this->_getAttrString($this->_upButtonAttributes);
244 $strHtmlMoveUp = "<input$attrStrUp />" . PHP_EOL;
245
246 // build the move down button with all its attributes
247 $attributes = ['onclick' => "{$this->_jsPrefix}moveDown(this.form.elements['_" . $selectName . "'], this.form.elements['" . $selectName . "']); return false;"];
248 $this->_downButtonAttributes = array_merge($this->_downButtonAttributes, $attributes);
249 $attrStrDown = $this->_getAttrString($this->_downButtonAttributes);
250 $strHtmlMoveDown = "<input$attrStrDown />" . PHP_EOL;
251 }
252
253 // render all part of the multi select component with the template
254 $strHtml = $this->_elementTemplate;
255
256 // Prepare multiple labels
257 $labels = $this->getLabel();
258 if (is_array($labels)) {
259 array_shift($labels);
260 }
261 // render extra labels, if any
262 if (is_array($labels)) {
263 foreach ($labels as $key => $text) {
264 $key = is_int($key) ? $key + 2 : $key;
265 $strHtml = str_replace("{label_{$key}}", $text, $strHtml);
266 $strHtml = str_replace("<!-- BEGIN label_{$key} -->", '', $strHtml);
267 $strHtml = str_replace("<!-- END label_{$key} -->", '', $strHtml);
268 }
269 }
270 // clean up useless label tags
271 if (strpos($strHtml, '{label_')) {
272 $strHtml = preg_replace('/\s*<!-- BEGIN label_(\S+) -->.*<!-- END label_\1 -->\s*/i', '', $strHtml);
273 }
274
275 $placeHolders = [
276 '{stylesheet}',
277 '{javascript}',
278 '{class}',
279 '{unselected}',
280 '{selected}',
281 '{add}',
282 '{remove}',
283 '{all}',
284 '{none}',
285 '{toggle}',
286 '{moveup}',
287 '{movedown}',
288 ];
289 $htmlElements = [
290 $this->getElementCss(FALSE),
291 $this->getElementJs(FALSE),
292 $this->_tableAttributes,
293 $strHtmlUnselected,
294 $strHtmlSelected . $strHtmlHidden,
295 $strHtmlAdd,
296 $strHtmlRemove,
297 $strHtmlAll,
298 $strHtmlNone,
299 $strHtmlToggle,
300 $strHtmlMoveUp,
301 $strHtmlMoveDown,
302 ];
303
304 $strHtml = str_replace($placeHolders, $htmlElements, $strHtml);
305
306 return $strHtml;
307 }
308
309 }