Add is empty filter to search / api
[civicrm-core.git] / ext / search / ang / crmSearchAdmin / crmSearchClause.component.js
CommitLineData
9b057f1e
CW
1(function(angular, $, _) {
2 "use strict";
3
493f83d4 4 angular.module('crmSearchAdmin').component('crmSearchClause', {
9b057f1e
CW
5 bindings: {
6 fields: '<',
7 clauses: '<',
8 format: '@',
9 op: '@',
10 skip: '<',
11 label: '@',
12 deleteGroup: '&'
13 },
493f83d4
CW
14 templateUrl: '~/crmSearchAdmin/crmSearchClause.html',
15 controller: function ($scope, $element, $timeout, searchMeta) {
9b057f1e 16 var ts = $scope.ts = CRM.ts(),
493f83d4
CW
17 ctrl = this,
18 meta = {};
9b057f1e 19 this.conjunctions = {AND: ts('And'), OR: ts('Or'), NOT: ts('Not')};
493f83d4 20 this.operators = CRM.crmSearchAdmin.operators;
9b057f1e
CW
21 this.sortOptions = {
22 axis: 'y',
23 connectWith: '.api4-clause-group-sortable',
24 containment: $element.closest('.api4-clause-fieldset'),
25 over: onSortOver,
26 start: onSort,
27 stop: onSort
28 };
29
30 this.$onInit = function() {
31 ctrl.hasParent = !!$element.attr('delete-group');
32 };
33
493f83d4
CW
34 this.getField = function(expr) {
35 if (!meta[expr]) {
36 meta[expr] = searchMeta.parseExpr(expr);
37 }
38 return meta[expr].field;
39 };
40
41 this.getOptionKey = function(expr) {
42 if (!meta[expr]) {
43 meta[expr] = searchMeta.parseExpr(expr);
44 }
45 return meta[expr].suffix ? meta[expr].suffix.slice(1) : 'id';
46 };
47
9b057f1e
CW
48 this.addGroup = function(op) {
49 ctrl.clauses.push([op, []]);
50 };
51
52 function onSort(event, ui) {
53 $($element).closest('.api4-clause-fieldset').toggleClass('api4-sorting', event.type === 'sortstart');
54 $('.api4-input.form-inline').css('margin-left', '');
55 }
56
57 // Indent clause while dragging between nested groups
58 function onSortOver(event, ui) {
59 var offset = 0;
60 if (ui.sender) {
61 offset = $(ui.placeholder).offset().left - $(ui.sender).offset().left;
62 }
63 $('.api4-input.form-inline.ui-sortable-helper').css('margin-left', '' + offset + 'px');
64 }
65
66 this.addClause = function() {
67 $timeout(function() {
68 if (ctrl.newClause) {
69 ctrl.clauses.push([ctrl.newClause, '=', '']);
70 ctrl.newClause = null;
71 }
72 });
73 };
74
75 this.deleteRow = function(index) {
76 ctrl.clauses.splice(index, 1);
77 };
78
79 // Remove empty values
80 this.changeClauseField = function(clause, index) {
81 if (clause[0] === '') {
82 ctrl.deleteRow(index);
83 }
84 };
85
c0e68893 86 // Returns false for 'IS NULL', 'IS EMPTY', etc. true otherwise.
87 this.operatorTakesInput = function(operator) {
88 return operator.indexOf('IS ') !== 0;
89 };
90
9b057f1e 91 this.changeClauseOperator = function(clause) {
c0e68893 92 // Add/remove value depending on whether operator allows for one
93 if (!ctrl.operatorTakesInput(clause[1])) {
9b057f1e 94 clause.length = 2;
014174e7
CW
95 } else {
96 if (clause.length === 2) {
97 clause.push('');
98 }
99 // Change multi/single value to/from an array
100 var shouldBeArray = (clause[1] === 'IN' || clause[1] === 'NOT IN' || clause[1] === 'BETWEEN' || clause[1] === 'NOT BETWEEN');
101 if (!_.isArray(clause[2]) && shouldBeArray) {
102 clause[2] = [];
103 } else if (_.isArray(clause[2]) && !shouldBeArray) {
104 clause[2] = '';
105 }
106 if (clause[1] === 'BETWEEN' || clause[1] === 'NOT BETWEEN') {
107 clause[2].length = 2;
108 }
9b057f1e
CW
109 }
110 };
111
112 }
113 });
114
115})(angular, CRM.$, CRM._);