Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | // http://civicrm.org/licensing |
2 | (function($, CRM) { | |
057428a0 | 3 | 'use strict'; |
6a488035 TO |
4 | |
5 | /** | |
057428a0 CW |
6 | * Handle user input - field or operator selection. |
7 | * | |
8 | * Decide whether to display select drop down, regular text or date | |
9 | * field for the given field and row. | |
6a488035 | 10 | */ |
057428a0 | 11 | function handleUserInputField() { |
6a488035 | 12 | var row = $(this).closest('tr'); |
057428a0 CW |
13 | var field = $('select[id^=mapper][id$="_1"]', row).val(); |
14 | var op = $('select[id^=operator]', row).val(); | |
15 | ||
16 | // These Ops don't get any input field. | |
17 | var noFieldOps = ['', 'IS EMPTY', 'IS NOT EMPTY', 'IS NULL', 'IS NOT NULL']; | |
18 | ||
19 | if ($.inArray(op, noFieldOps) > -1) { | |
20 | // Hide the fields and return. | |
21 | $('.crm-search-value', row).hide().find('input, select').val(''); | |
22 | return; | |
23 | } | |
24 | $('.crm-search-value', row).show(); | |
25 | ||
6a488035 TO |
26 | if (!CRM.searchBuilder.fieldOptions[field]) { |
27 | removeSelect(row); | |
28 | } | |
6a488035 | 29 | else { |
057428a0 | 30 | buildSelect(row, field, op); |
6a488035 | 31 | } |
6a488035 | 32 | |
057428a0 CW |
33 | if ($.inArray(field, CRM.searchBuilder.dateFields) < 0) { |
34 | removeDate(row); | |
6a488035 | 35 | } |
6a488035 | 36 | else { |
057428a0 | 37 | buildDate(row, op); |
6a488035 TO |
38 | } |
39 | } | |
40 | ||
41 | /** | |
057428a0 | 42 | * Add select list if appropriate for this operation |
6a488035 TO |
43 | * @param row: jQuery object |
44 | * @param field: string | |
45 | */ | |
057428a0 CW |
46 | function buildSelect(row, field, op) { |
47 | var multiSelect = ''; | |
48 | // Operators that will get a single drop down list of choices. | |
49 | var dropDownSingleOps = ['=', '!=']; | |
50 | // Multiple select drop down list. | |
51 | var dropDownMultipleOps = ['IN', 'NOT IN']; | |
52 | ||
53 | if ($.inArray(op, dropDownMultipleOps) > -1) { | |
54 | multiSelect = 'multiple="multiple"'; | |
6a488035 | 55 | } |
057428a0 CW |
56 | else if ($.inArray(op, dropDownSingleOps) < 0) { |
57 | // If this op is neither supported by single or multiple selects, then we should not render a select list. | |
58 | removeSelect(row); | |
59 | return; | |
6a488035 | 60 | } |
057428a0 | 61 | |
6a488035 | 62 | $('.crm-search-value select', row).remove(); |
057428a0 CW |
63 | $('input[id^=value]', row) |
64 | .hide() | |
0bdc50a1 | 65 | .after('<select class="crm-form-' + multiSelect.substr(0, 5) + 'select required" ' + multiSelect + '><option value="">' + ts('Loading') + '...</option></select>'); |
057428a0 | 66 | |
6a488035 TO |
67 | fetchOptions(row, field); |
68 | } | |
69 | ||
70 | /** | |
71 | * Retrieve option list for given row | |
72 | * @param row: jQuery object | |
73 | * @param field: string | |
74 | */ | |
75 | function fetchOptions(row, field) { | |
76 | if (CRM.searchBuilder.fieldOptions[field] === 'yesno') { | |
15a1171a | 77 | CRM.searchBuilder.fieldOptions[field] = [{key: 1, value: ts('Yes')}, {key: 0, value: ts('No')}]; |
6a488035 TO |
78 | } |
79 | if (typeof(CRM.searchBuilder.fieldOptions[field]) == 'string') { | |
15a1171a | 80 | CRM.api(CRM.searchBuilder.fieldOptions[field], 'getoptions', {field: field, sequential: 1}, { |
6a488035 TO |
81 | success: function(result, settings) { |
82 | var field = settings.field; | |
83 | if (result.count) { | |
84 | CRM.searchBuilder.fieldOptions[field] = result.values; | |
85 | buildOptions(settings.row, field); | |
86 | } | |
87 | else { | |
88 | removeSelect(settings.row); | |
89 | } | |
90 | }, | |
91 | error: function(result, settings) { | |
92 | removeSelect(settings.row); | |
93 | }, | |
94 | row: row, | |
95 | field: field | |
96 | }); | |
97 | } | |
98 | else { | |
99 | buildOptions(row, field); | |
100 | } | |
101 | } | |
102 | ||
103 | /** | |
104 | * Populate option list for given row | |
105 | * @param row: jQuery object | |
106 | * @param field: string | |
107 | */ | |
108 | function buildOptions(row, field) { | |
109 | var select = $('.crm-search-value select', row); | |
110 | var value = $('input[id^=value]', row).val(); | |
111 | if (value.length && value.charAt(0) == '(' && value.charAt(value.length - 1) == ')') { | |
112 | value = value.slice(1, -1); | |
113 | } | |
114 | var options = value.split(','); | |
057428a0 CW |
115 | if (select.attr('multiple') == 'multiple') { |
116 | select.find('option').remove(); | |
117 | } | |
118 | else { | |
119 | select.find('option').text(ts('- select -')); | |
120 | if (options.length > 1) { | |
121 | options = [options[0]]; | |
122 | } | |
6a488035 | 123 | } |
15a1171a | 124 | $.each(CRM.searchBuilder.fieldOptions[field], function(key, option) { |
feaf129f | 125 | var selected = ($.inArray(''+option.key, options) > -1) ? 'selected="selected"' : ''; |
15a1171a | 126 | select.append('<option value="' + option.key + '"' + selected + '>' + option.value + '</option>'); |
6a488035 TO |
127 | }); |
128 | select.change(); | |
129 | } | |
130 | ||
131 | /** | |
132 | * Remove select options and restore input to a plain textfield | |
133 | * @param row: jQuery object | |
134 | */ | |
135 | function removeSelect(row) { | |
136 | $('.crm-search-value input', row).show(); | |
137 | $('.crm-search-value select', row).remove(); | |
6a488035 TO |
138 | } |
139 | ||
140 | /** | |
057428a0 | 141 | * Add a datepicker if appropriate for this operation |
6a488035 TO |
142 | * @param row: jQuery object |
143 | */ | |
057428a0 | 144 | function buildDate(row, op) { |
6a488035 | 145 | var input = $('.crm-search-value input', row); |
057428a0 CW |
146 | // These are operations that should not get a datepicker |
147 | var datePickerOp = ($.inArray(op, ['IN', 'NOT IN', 'LIKE', 'RLIKE']) < 0); | |
148 | if (!datePickerOp) { | |
149 | removeDate(row); | |
150 | } | |
151 | else if (!input.hasClass('hasDatepicker')) { | |
6a488035 TO |
152 | input.addClass('dateplugin').datepicker({ |
153 | dateFormat: 'yymmdd', | |
154 | changeMonth: true, | |
155 | changeYear: true, | |
156 | yearRange: '-100:+20' | |
157 | }); | |
158 | } | |
159 | } | |
160 | ||
161 | /** | |
162 | * Remove datepicker | |
163 | * @param row: jQuery object | |
164 | */ | |
165 | function removeDate(row) { | |
166 | var input = $('.crm-search-value input', row); | |
167 | if (input.hasClass('hasDatepicker')) { | |
6a488035 TO |
168 | input.removeClass('dateplugin').val('').datepicker('destroy'); |
169 | } | |
170 | } | |
171 | ||
057428a0 CW |
172 | // Initialize display: Hide empty blocks & fields |
173 | var newBlock = CRM.searchBuilder && CRM.searchBuilder.newBlock || 0; | |
634a9e99 CW |
174 | function initialize() { |
175 | $('.crm-search-block', '#Builder').each(function(blockNo) { | |
176 | var block = $(this); | |
177 | var empty = blockNo + 1 > newBlock; | |
178 | var skippedRow = false; | |
179 | $('tr:not(.crm-search-builder-add-row)', block).each(function(rowNo) { | |
180 | var row = $(this); | |
181 | if ($('select:first', row).val() === '') { | |
182 | if (!skippedRow && (rowNo == 0 || blockNo + 1 == newBlock)) { | |
183 | skippedRow = true; | |
184 | } | |
185 | else { | |
186 | row.hide(); | |
187 | } | |
6a488035 TO |
188 | } |
189 | else { | |
634a9e99 | 190 | empty = false; |
6a488035 | 191 | } |
634a9e99 CW |
192 | }); |
193 | if (empty) { | |
194 | block.hide(); | |
6a488035 TO |
195 | } |
196 | }); | |
634a9e99 | 197 | } |
6a488035 | 198 | |
634a9e99 | 199 | $('#crm-main-content-wrapper') |
057428a0 CW |
200 | // Reset and hide row |
201 | .on('click', '.crm-reset-builder-row', function() { | |
202 | var row = $(this).closest('tr'); | |
203 | $('input, select', row).val('').change(); | |
204 | row.hide(); | |
205 | // Hide entire block if this is the only visible row | |
206 | if (row.siblings(':visible').length < 2) { | |
207 | row.closest('.crm-search-block').hide(); | |
208 | } | |
209 | return false; | |
210 | }) | |
211 | // Add new field - if there's a hidden one, show it | |
212 | // Otherwise allow form to submit and fetch more from the server | |
213 | .on('click', 'input[name^=addMore]', function() { | |
214 | var table = $(this).closest('table'); | |
215 | if ($('tr:hidden', table).length) { | |
216 | $('tr:hidden', table).first().show(); | |
6a488035 | 217 | return false; |
057428a0 CW |
218 | } |
219 | }) | |
220 | // Add new block - if there's a hidden one, show it | |
221 | // Otherwise allow form to submit and fetch more from the server | |
222 | .on('click', '#addBlock', function() { | |
223 | if ($('.crm-search-block:hidden', '#Builder').length) { | |
224 | var block = $('.crm-search-block:hidden', '#Builder').first(); | |
225 | block.show(); | |
226 | $('tr:first-child, tr.crm-search-builder-add-row', block).show(); | |
227 | return false; | |
228 | } | |
229 | }) | |
230 | // Handle field and operator selection | |
231 | .on('change', 'select[id^=mapper][id$="_1"], select[id^=operator]', handleUserInputField) | |
232 | // Handle option selection - update hidden value field | |
233 | .on('change', '.crm-search-value select', function() { | |
234 | var value = $(this).val() || ''; | |
235 | if ($(this).attr('multiple') == 'multiple' && value.length) { | |
236 | value = '(' + value.join(',') + ')'; | |
237 | } | |
238 | $(this).siblings('input').val(value); | |
239 | }) | |
634a9e99 CW |
240 | .on('crmLoad', function() { |
241 | initialize(); | |
242 | $('select[id^=mapper][id$="_1"]', '#Builder').each(handleUserInputField); | |
243 | }); | |
057428a0 | 244 | |
634a9e99 | 245 | initialize(); |
3eb318ac CW |
246 | |
247 | // Fetch initial options during page refresh - it's more efficient to bundle them in a single ajax request | |
248 | var initialFields = {}, fetchFields = false; | |
249 | $('select[id^=mapper][id$="_1"] option:selected', '#Builder').each(function() { | |
250 | var field = $(this).attr('value'); | |
251 | if (typeof(CRM.searchBuilder.fieldOptions[field]) == 'string') { | |
252 | initialFields[field] = [CRM.searchBuilder.fieldOptions[field], 'getoptions', {field: field, sequential: 1}]; | |
253 | fetchFields = true; | |
254 | } | |
255 | }); | |
256 | if (fetchFields) { | |
257 | CRM.api3(initialFields).done(function(data) { | |
258 | $.each(data, function(field, result) { | |
259 | CRM.searchBuilder.fieldOptions[field] = result.values; | |
260 | }); | |
261 | $('select[id^=mapper][id$="_1"]', '#Builder').each(handleUserInputField); | |
262 | }); | |
263 | } else { | |
264 | $('select[id^=mapper][id$="_1"]', '#Builder').each(handleUserInputField); | |
265 | } | |
6a488035 | 266 | })(cj, CRM); |