Commit | Line | Data |
---|---|---|
25523059 CW |
1 | (function(angular, $, _) { |
2 | "use strict"; | |
3 | ||
493f83d4 | 4 | angular.module('crmSearchKit').directive('crmSearchValue', function($interval, formatForSelect2) { |
25523059 CW |
5 | return { |
6 | scope: { | |
7 | data: '=crmSearchValue' | |
8 | }, | |
9 | require: 'ngModel', | |
10 | link: function (scope, element, attrs, ngModel) { | |
11 | var ts = scope.ts = CRM.ts(), | |
12 | multi = _.includes(['IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN'], scope.data.op), | |
13 | format = scope.data.format; | |
14 | ||
15 | function destroyWidget() { | |
16 | var $el = $(element); | |
17 | if ($el.is('.crm-form-date-wrapper .crm-hidden-date')) { | |
18 | $el.crmDatepicker('destroy'); | |
19 | } | |
20 | if ($el.is('.select2-container + input')) { | |
21 | $el.crmEntityRef('destroy'); | |
22 | } | |
23 | $(element).removeData().removeAttr('type').removeAttr('placeholder').show(); | |
24 | } | |
25 | ||
26 | function makeWidget(field, op, optionKey) { | |
27 | var $el = $(element), | |
28 | inputType = field.input_type, | |
29 | dataType = field.data_type; | |
30 | if (!op) { | |
31 | op = field.serialize || dataType === 'Array' ? 'IN' : '='; | |
32 | } | |
33 | multi = _.includes(['IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN'], op); | |
34 | if (op === 'IS NULL' || op === 'IS NOT NULL') { | |
35 | $el.hide(); | |
36 | return; | |
37 | } | |
38 | if (inputType === 'Date') { | |
7156e4b0 | 39 | if (_.includes(['=', '!=', '>', '>=', '<', '<='], op)) { |
25523059 CW |
40 | $el.crmDatepicker({time: (field.input_attrs && field.input_attrs.time) || false}); |
41 | } | |
7156e4b0 | 42 | } else if (_.includes(['=', '!=', 'IN', 'NOT IN', 'CONTAINS'], op) && (field.fk_entity || field.options || dataType === 'Boolean')) { |
25523059 CW |
43 | if (field.options) { |
44 | if (field.options === true) { | |
45 | $el.addClass('loading'); | |
46 | var waitForOptions = $interval(function() { | |
47 | if (field.options !== true) { | |
48 | $interval.cancel(waitForOptions); | |
49 | $el.removeClass('loading').crmSelect2({data: getFieldOptions, multiple: multi}); | |
50 | } | |
51 | }, 200); | |
52 | } | |
53 | $el.attr('placeholder', ts('select')).crmSelect2({data: getFieldOptions, multiple: multi}); | |
54 | } else if (field.fk_entity) { | |
55 | $el.crmEntityRef({entity: field.fk_entity, select:{multiple: multi}}); | |
56 | } else if (dataType === 'Boolean') { | |
57 | $el.attr('placeholder', ts('- select -')).crmSelect2({allowClear: false, multiple: multi, placeholder: ts('- select -'), data: [ | |
58 | // FIXME: it would be more correct to use real true/false booleans instead of numbers, but select2 doesn't seem to like them | |
59 | {id: 1, text: ts('Yes')}, | |
60 | {id: 0, text: ts('No')} | |
61 | ]}); | |
62 | } | |
63 | } else if (dataType === 'Integer' && !multi) { | |
64 | $el.attr('type', 'number'); | |
65 | } | |
66 | ||
67 | function getFieldOptions() { | |
68 | return {results: formatForSelect2(field.options, optionKey, 'label', ['description', 'color', 'icon'])}; | |
69 | } | |
70 | } | |
71 | ||
72 | // Copied from ng-list but applied conditionally if field is multi-valued | |
73 | var parseList = function(viewValue) { | |
74 | // If the viewValue is invalid (say required but empty) it will be `undefined` | |
75 | if (_.isUndefined(viewValue)) return; | |
76 | ||
77 | if (!multi) { | |
78 | return format === 'json' ? JSON.stringify(viewValue) : viewValue; | |
79 | } | |
80 | ||
81 | var list = []; | |
82 | ||
83 | if (viewValue) { | |
84 | _.each(viewValue.split(','), function(value) { | |
85 | if (value) list.push(_.trim(value)); | |
86 | }); | |
87 | } | |
88 | ||
89 | return list; | |
90 | }; | |
91 | ||
92 | // Copied from ng-list | |
93 | ngModel.$parsers.push(parseList); | |
94 | ngModel.$formatters.push(function(value) { | |
95 | return _.isArray(value) ? value.join(', ') : (format === 'json' && value !== '' ? JSON.parse(value) : value); | |
96 | }); | |
97 | ||
98 | // Copied from ng-list | |
99 | ngModel.$isEmpty = function(value) { | |
100 | return !value || !value.length; | |
101 | }; | |
102 | ||
103 | scope.$watchCollection('data', function(data) { | |
104 | destroyWidget(); | |
493f83d4 CW |
105 | if (data.field) { |
106 | makeWidget(data.field, data.op, data.optionKey || 'id'); | |
25523059 CW |
107 | } |
108 | }); | |
109 | } | |
110 | }; | |
111 | }); | |
112 | ||
113 | })(angular, CRM.$, CRM._); |