1 // https://civicrm.org/licensing
4 // Enable administrators to edit option lists in a dialog
5 .on('click', 'a.crm-option-edit-link', CRM
.popup
)
6 .on('crmPopupFormSuccess', 'a.crm-option-edit-link', function() {
7 $(this).trigger('crmOptionsEdited');
8 var optionEditPath
= $(this).data('option-edit-path');
9 var $selects
= $('select[data-option-edit-path="' + optionEditPath
+ '"]');
10 var $inputs
= $('input[data-option-edit-path="' + optionEditPath
+ '"]');
11 var $radios
= $inputs
.filter('[type=radio]');
12 var $checkboxes
= $inputs
.filter('[type=checkbox]');
14 if ($selects
.length
> 0) {
15 rebuildOptions($selects
, CRM
.utils
.setOptions
);
17 else if ($radios
.length
> 0) {
18 rebuildOptions($radios
, rebuildRadioOptions
);
20 else if ($checkboxes
.length
> 0) {
21 rebuildOptions($checkboxes
, rebuildCheckboxOptions
);
26 * Fetches options using metadata from the existing ones and calls the
27 * function to rebuild them
28 * @param $existing {object} The existing options, used as metadata store
29 * @param rebuilder {function} Function to be called to rebuild the options
31 function rebuildOptions($existing
, rebuilder
) {
32 if ($existing
.data('api-entity') && $existing
.data('api-field')) {
35 field
: $existing
.data('api-field')
37 $.extend(params
, $existing
.data('option-edit-context'));
39 CRM
.api3($existing
.data('api-entity'), 'getoptions', params
)
40 .done(function(data
) {
41 rebuilder($existing
, data
.values
);
47 * Rebuild checkbox input options, overwriting the existing options
49 * @param $existing {object} the existing checkbox options
50 * @param newOptions {array} in format returned by api.getoptions
52 function rebuildCheckboxOptions($existing
, newOptions
) {
53 var $parent
= $existing
.first().parent(),
54 $firstExisting
= $existing
.first(),
55 optionName
= $firstExisting
.attr('name'),
57 'data-option-edit-path =' + $firstExisting
.data('option-edit-path') +
58 ' data-api-entity = ' + $firstExisting
.data('api-entity') +
59 ' data-api-field = ' + $firstExisting
.data('api-field');
61 var prefix
= optionName
.substr(0, optionName
.lastIndexOf("["));
63 var checkedBoxes
= [];
64 $parent
.find('input:checked').each(function() {
65 checkedBoxes
.push($(this).attr('id'));
68 // remove existing checkboxes
69 $parent
.find('input[type=checkbox]').remove();
71 // find existing labels for the checkboxes
72 var $checkboxLabels
= $parent
.find('label').filter(function() {
73 var forAttr
= $(this).attr('for') || '';
75 return forAttr
.indexOf(prefix
) !== -1;
78 // find what is used to separate the elements; spaces or linebreaks
79 var $elementAfterLabel
= $checkboxLabels
.first().next();
80 var separator
= $elementAfterLabel
.is('br') ? '<br/>' : ' ';
82 // remove existing labels
83 $checkboxLabels
.remove();
85 // remove linebreaks in container
86 $parent
.find('br').remove();
88 // remove separator whitespace in container
89 $parent
.html(function (i
, html
) {
90 return html
.replace(/ /g, '');
93 var renderedOptions
= '';
94 // replace missing br at start of element
95 if (separator
=== '<br/>') {
96 $parent
.prepend(separator
);
97 renderedOptions
= separator
;
100 newOptions
.forEach(function(option
) {
101 var optionId
= prefix
+ '_' + option
.key
,
104 if ($.inArray(optionId
, checkedBoxes
) !== -1) {
105 checked
= ' checked="checked"';
108 renderedOptions
+= '<input type="checkbox" ' +
110 ' id="' + optionId
+ '"' +
111 ' name="' + prefix
+ '[' + option
.key
+']' + '"' +
113 ' class="crm-form-checkbox"' +
115 '><label for="' + optionId
+ '">' + option
.value
+ '</label>' +
119 // remove final separator
120 renderedOptions
= renderedOptions
.substring(0, renderedOptions
.lastIndexOf(separator
));
122 var $editLink
= $parent
.find('.crm-option-edit-link');
124 // try to insert before the edit link to maintain structure
125 if ($editLink
.length
> 0) {
126 $(renderedOptions
).insertBefore($editLink
);
129 $parent
.append(renderedOptions
);
134 * Rebuild radio input options, overwriting the existing options
136 * @param $existing {object} the existing input options
137 * @param newOptions {array} in format returned by api.getoptions
139 function rebuildRadioOptions($existing
, newOptions
) {
140 var $parent
= $existing
.first().parent(),
141 $firstExisting
= $existing
.first(),
142 optionName
= $firstExisting
.attr('name'),
143 renderedOptions
= '',
144 checkedValue
= parseInt($parent
.find('input:checked').attr('value')),
146 'data-option-edit-path =' + $firstExisting
.attr('data-option-edit-path') +
147 ' data-api-entity = ' + $firstExisting
.attr('data-api-entity') +
148 ' data-api-field = ' + $firstExisting
.attr('data-api-field');
150 // remove existing radio inputs and labels
151 $parent
.find('input, label').remove();
153 newOptions
.forEach(function(option
) {
154 var optionId
= 'CIVICRM_QFID_' + option
.key
+ '_' + optionName
,
155 checked
= (option
.key
=== checkedValue
) ? ' checked="checked"' : '';
157 renderedOptions
+= '<input type="radio" ' +
158 ' value=' + option
.key
+
159 ' id="' + optionId
+'"' +
160 ' name="' + optionName
+ '"' +
162 ' class="crm-form-radio"' +
164 '><label for="' + optionId
+ '">' + option
.value
+ '</label> ';
167 $parent
.prepend(renderedOptions
);