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')) {
33 CRM
.api3($existing
.data('api-entity'), 'getoptions', {
35 field
: $existing
.data('api-field')
37 .done(function(data
) {
38 rebuilder($existing
, data
.values
);
44 * Rebuild checkbox input options, overwriting the existing options
46 * @param $existing {object} the existing checkbox options
47 * @param newOptions {array} in format returned by api.getoptions
49 function rebuildCheckboxOptions($existing
, newOptions
) {
50 var $parent
= $existing
.first().parent(),
51 $firstExisting
= $existing
.first(),
52 optionName
= $firstExisting
.attr('name'),
54 'data-option-edit-path =' + $firstExisting
.data('option-edit-path') +
55 ' data-api-entity = ' + $firstExisting
.data('api-entity') +
56 ' data-api-field = ' + $firstExisting
.data('api-field');
58 var prefix
= optionName
.substr(0, optionName
.lastIndexOf("["));
60 var checkedBoxes
= [];
61 $parent
.find('input:checked').each(function() {
62 checkedBoxes
.push($(this).attr('id'));
65 // remove existing checkboxes
66 $parent
.find('input[type=checkbox]').remove();
68 // find existing labels for the checkboxes
69 var $checkboxLabels
= $parent
.find('label').filter(function() {
70 var forAttr
= $(this).attr('for') || '';
72 return forAttr
.indexOf(prefix
) !== -1;
75 // find what is used to separate the elements; spaces or linebreaks
76 var $elementAfterLabel
= $checkboxLabels
.first().next();
77 var separator
= $elementAfterLabel
.is('br') ? '<br/>' : ' ';
79 // remove existing labels
80 $checkboxLabels
.remove();
82 // remove linebreaks in container
83 $parent
.find('br').remove();
85 // remove separator whitespace in container
86 $parent
.html(function (i
, html
) {
87 return html
.replace(/ /g, '');
90 var renderedOptions
= '';
91 // replace missing br at start of element
92 if (separator
=== '<br/>') {
93 $parent
.prepend(separator
);
94 renderedOptions
= separator
;
97 newOptions
.forEach(function(option
) {
98 var optionId
= prefix
+ '_' + option
.key
,
101 if ($.inArray(optionId
, checkedBoxes
) !== -1) {
102 checked
= ' checked="checked"';
105 renderedOptions
+= '<input type="checkbox" ' +
107 ' id="' + optionId
+ '"' +
108 ' name="' + prefix
+ '[' + option
.key
+']' + '"' +
110 ' class="crm-form-checkbox"' +
112 '><label for="' + optionId
+ '">' + option
.value
+ '</label>' +
116 // remove final separator
117 renderedOptions
= renderedOptions
.substring(0, renderedOptions
.lastIndexOf(separator
));
119 var $editLink
= $parent
.find('.crm-option-edit-link');
121 // try to insert before the edit link to maintain structure
122 if ($editLink
.length
> 0) {
123 $(renderedOptions
).insertBefore($editLink
);
126 $parent
.append(renderedOptions
);
131 * Rebuild radio input options, overwriting the existing options
133 * @param $existing {object} the existing input options
134 * @param newOptions {array} in format returned by api.getoptions
136 function rebuildRadioOptions($existing
, newOptions
) {
137 var $parent
= $existing
.first().parent(),
138 $firstExisting
= $existing
.first(),
139 optionName
= $firstExisting
.attr('name'),
140 renderedOptions
= '',
141 checkedValue
= parseInt($parent
.find('input:checked').attr('value')),
143 'data-option-edit-path =' + $firstExisting
.attr('data-option-edit-path') +
144 ' data-api-entity = ' + $firstExisting
.attr('data-api-entity') +
145 ' data-api-field = ' + $firstExisting
.attr('data-api-field');
147 // remove existing radio inputs and labels
148 $parent
.find('input, label').remove();
150 newOptions
.forEach(function(option
) {
151 var optionId
= 'CIVICRM_QFID_' + option
.key
+ '_' + optionName
,
152 checked
= (option
.key
=== checkedValue
) ? ' checked="checked"' : '';
154 renderedOptions
+= '<input type="radio" ' +
155 ' value=' + option
.key
+
156 ' id="' + optionId
+'"' +
157 ' name="' + optionName
+ '"' +
159 ' class="crm-form-radio"' +
161 '><label for="' + optionId
+ '">' + option
.value
+ '</label> ';
164 $parent
.prepend(renderedOptions
);