CRM-15578 - crmUiSelect - Update to work with ngModel
[civicrm-core.git] / js / angular-crmMailing2-directives.js
CommitLineData
5d72b4e2
TO
1(function (angular, $, _) {
2 var partialUrl = function (relPath) {
3 return CRM.resourceUrls['civicrm'] + '/partials/crmMailing2/' + relPath;
4 };
5
6 var crmMailing2 = angular.module('crmMailing2');
7
f4f103fa 8 crmMailing2.directive('crmMailingReviewBool', function () {
47bacc20
TO
9 return {
10 scope: {
11 crmOn: '@',
12 crmTitle: '@'
13 },
14 template: '<span ng-class="spanClasses"><span class="icon" ng-class="iconClasses"></span>{{crmTitle}} </span>',
f4f103fa 15 link: function (scope, element, attrs) {
47bacc20
TO
16 function refresh() {
17 if (scope.$parent.$eval(attrs.crmOn)) {
18 scope.spanClasses = {'crmMailing2-active': true};
19 scope.iconClasses = {'ui-icon-check': true};
f4f103fa
TO
20 }
21 else {
47bacc20
TO
22 scope.spanClasses = {'crmMailing2-inactive': true};
23 scope.iconClasses = {'ui-icon-close': true};
24 }
25 scope.crmTitle = scope.$parent.$eval(attrs.crmTitle);
26 }
f4f103fa 27
47bacc20
TO
28 refresh();
29 scope.$parent.$watch(attrs.crmOn, refresh);
30 scope.$parent.$watch(attrs.crmTitle, refresh);
31 }
32 };
33 });
34
5d72b4e2
TO
35 // example: <input name="subject" /> <input crm-mailing-token crm-for="subject"/>
36 // WISHLIST: Instead of global CRM.crmMailing.mailTokens, accept token list as an input
38737af8 37 crmMailing2.directive('crmMailingToken', function (crmUiId) {
5d72b4e2
TO
38 return {
39 scope: {
40 crmFor: '@'
41 },
42 template: '<input type="text" class="crmMailingToken" />',
43 link: function (scope, element, attrs) {
44 // 1. Find the corresponding input element (crmFor)
45
46 var form = $(element).closest('form');
47 var crmForEl = $('input[name="' + attrs.crmFor + '"],textarea[name="' + attrs.crmFor + '"]', form);
48 if (form.length != 1 || crmForEl.length != 1) {
38737af8 49 if (console.log) {
5d72b4e2 50 console.log('crmMailingToken cannot be matched to input element. Expected to find one form and one input.', form.length, crmForEl.length);
38737af8 51 }
5d72b4e2
TO
52 return;
53 }
54
55 // 2. Setup the token selector
38737af8
TO
56 $(element).select2({
57 width: "10em",
5d72b4e2
TO
58 dropdownAutoWidth: true,
59 data: CRM.crmMailing.mailTokens,
60 placeholder: ts('Insert')
61 });
62 $(element).on('select2-selecting', function (e) {
38737af8
TO
63 var id = crmUiId(crmForEl);
64 if (CKEDITOR.instances[id]) {
65 CKEDITOR.instances[id].insertText(e.val);
66 $(element).select2('close').select2('val', '');
67 CKEDITOR.instances[id].focus();
68 }
69 else {
70 var origVal = crmForEl.val();
71 var origPos = crmForEl[0].selectionStart;
72 var newVal = origVal.substring(0, origPos) + e.val + origVal.substring(origPos, origVal.length);
73 crmForEl.val(newVal);
74 var newPos = (origPos + e.val.length);
75 crmForEl[0].selectionStart = newPos;
76 crmForEl[0].selectionEnd = newPos;
5d72b4e2 77
38737af8
TO
78 $(element).select2('close').select2('val', '');
79 crmForEl.triggerHandler('change');
80 crmForEl.focus();
81 }
5d72b4e2
TO
82
83 e.preventDefault();
84 });
85 }
86 };
87 });
88
b0461279
TO
89 // example: <select multiple crm-mailing-recipients crm-mailing="mymailing" crm-avail-groups="myGroups" crm-avail-mailings="myMailings"></select>
90 crmMailing2.directive('crmMailingRecipients', function () {
91 return {
92 restrict: 'AE',
93 scope: {
94 crmAvailGroups: '@', // available groups
95 crmAvailMailings: '@', // available mailings
96 crmMailing: '@' // the mailing for which we are choosing recipients
97 },
98 templateUrl: partialUrl('directive/recipients.html'),
99 link: function (scope, element, attrs) {
100 scope.mailing = scope.$parent.$eval(attrs.crmMailing);
101 scope.groups = scope.$parent.$eval(attrs.crmAvailGroups);
102 scope.mailings = scope.$parent.$eval(attrs.crmAvailMailings);
103
104 scope.ts = CRM.ts('CiviMail');
105
106 /// Convert MySQL date ("yyyy-mm-dd hh:mm:ss") to JS date object
107 scope.parseDate = function (date) {
f4f103fa 108 if (!angular.isString(date)) {
b0461279 109 return date;
f4f103fa 110 }
b0461279
TO
111 var p = date.split(/[\- :]/);
112 return new Date(p[0], p[1], p[2], p[3], p[4], p[5]);
113 };
114
115 /// Remove {value} from {array}
116 function arrayRemove(array, value) {
117 var idx = array.indexOf(value);
118 if (idx >= 0) {
119 array.splice(idx, 1);
120 }
121 }
122
123 // @param string id an encoded string like "4 civicrm_mailing include"
124 // @return Object keys: entity_id, entity_type, mode
125 function convertValueToObj(id) {
126 var a = id.split(" ");
127 return {entity_id: parseInt(a[0]), entity_type: a[1], mode: a[2]};
128 }
129
130 // @param Object mailing
131 // @return array list of values like "4 civicrm_mailing include"
132 function convertMailingToValues(mailing) {
133 var r = [];
134 angular.forEach(mailing.groups.include, function (v) {
135 r.push(v + " civicrm_group include");
136 });
137 angular.forEach(mailing.groups.exclude, function (v) {
138 r.push(v + " civicrm_group exclude");
139 });
140 angular.forEach(mailing.mailings.include, function (v) {
141 r.push(v + " civicrm_mailing include");
142 });
143 angular.forEach(mailing.mailings.exclude, function (v) {
144 r.push(v + " civicrm_mailing exclude");
145 });
146 return r;
147 }
148
149 // Update $(element) view based on latest data
150 function refreshUI() {
151 $(element).select2('val', convertMailingToValues(scope.mailing));
152 }
153
154 /// @return string HTML representingn an option
155 function formatItem(item) {
156 if (!item.id) {
157 // return `text` for optgroup
158 return item.text;
159 }
160 var option = convertValueToObj(item.id);
161 var icon = (option.entity_type === 'civicrm_mailing') ? 'EnvelopeIn.gif' : 'group.png';
162 var spanClass = (option.mode == 'exclude') ? 'crmMailing2-exclude' : 'crmMailing2-include';
163 return "<img src='../../sites/all/modules/civicrm/i/" + icon + "' height=12 width=12 /> <span class='" + spanClass + "'>" + item.text + "</span>";
164 }
165
166 $(element).select2({
167 dropdownAutoWidth: true,
168 placeholder: "Groups or Past Recipients",
169 formatResult: formatItem,
170 formatSelection: formatItem,
171 escapeMarkup: function (m) {
172 return m;
173 },
174 });
175
176 $(element).on('select2-selecting', function (e) {
177 var option = convertValueToObj(e.val);
178 var typeKey = option.entity_type == 'civicrm_mailing' ? 'mailings' : 'groups';
179 if (option.mode == 'exclude') {
180 scope.mailing[typeKey].exclude.push(option.entity_id);
181 arrayRemove(scope.mailing[typeKey].include, option.entity_id);
f4f103fa
TO
182 }
183 else {
b0461279
TO
184 scope.mailing[typeKey].include.push(option.entity_id);
185 arrayRemove(scope.mailing[typeKey].exclude, option.entity_id);
186 }
187 scope.$apply();
188 $(element).select2('close');
189 e.preventDefault();
190 });
191
192 $(element).on("select2-removing", function (e) {
193 var option = convertValueToObj(e.val);
194 var typeKey = option.entity_type == 'civicrm_mailing' ? 'mailings' : 'groups';
f4f103fa 195 scope.$parent.$apply(function () {
89a50c67
TO
196 arrayRemove(scope.mailing[typeKey][option.mode], option.entity_id);
197 });
b0461279
TO
198 e.preventDefault();
199 });
200
201 scope.$watchCollection(attrs.crmMailing + ".groups.include", refreshUI);
202 scope.$watchCollection(attrs.crmMailing + ".groups.exclude", refreshUI);
203 scope.$watchCollection(attrs.crmMailing + ".mailings.include", refreshUI);
204 scope.$watchCollection(attrs.crmMailing + ".mailings.exclude", refreshUI);
205 setTimeout(refreshUI, 50);
206 }
207 };
208 });
209
5d72b4e2 210})(angular, CRM.$, CRM._);