Merge pull request #2006 from civicrm/4.3
[civicrm-core.git] / templates / CRM / Batch / Form / Entry.js
1 //@todo functions partially moved from tpl but still need an enclosure / cleanup
2 // jslinting etc
3 cj(function () {
4 cj('.selector-rows').change(function () {
5 var options = {
6 'url': CRM.url('civicrm/ajax/batch')
7 };
8
9 cj("#Entry").ajaxSubmit(options);
10
11 // validate rows
12 checkColumns(cj(this));
13 });
14
15 cj('input[name^="soft_credit_contact["]').change(function(){
16 var rowNum = cj(this).attr('id').replace('soft_credit_contact_','');
17 var totalAmount = cj('#field_'+rowNum+'_total_amount').val();
18 //assign total amount as default soft credit amount
19 cj('#soft_credit_amount_'+ rowNum).val(totalAmount);
20 });
21
22 // validate rows
23 validateRow();
24
25 //calculate the actual total for the batch
26 calculateActualTotal();
27
28 cj('input[id*="_total_amount"]').bind('keyup change', function () {
29 calculateActualTotal();
30 });
31
32 if (CRM.batch.type_id == 1) {
33 // hide all dates if send receipt is checked
34 hideSendReceipt();
35
36 // hide the receipt date if send receipt is checked
37 cj('input[id*="][send_receipt]"]').change(function () {
38 showHideReceipt(cj(this));
39 });
40
41 }
42 else{
43 cj('select[id^="member_option_"]').each(function () {
44 if (cj(this).val() == 1) {
45 cj(this).attr('disabled', true);
46 }
47 });
48
49 // set payment info accord to membership type
50 cj('select[id*="_membership_type_0"]').change(function () {
51 setPaymentBlock(cj(this), null);
52 });
53
54 cj('select[id*="_membership_type_1"]').change(function () {
55 setPaymentBlock(cj(this), cj(this).val());
56 });
57
58 }
59
60 // line breaks between radio buttons and checkboxes
61 cj('input.form-radio').next().after('<br />');
62 cj('input.form-checkbox').next().after('<br />');
63
64 //set the focus on first element
65 cj('#primary_contact_1').focus();
66
67 });
68
69
70 function updateContactInfo(blockNo, prefix) {
71 var contactHiddenElement = 'input[name="' + prefix + 'contact_select_id[' + blockNo + ']"]';
72 var contactId = cj(contactHiddenElement).val();
73
74 var profileFields = CRM.contact.fieldmap;
75
76 CRM.api('Contact', 'get', {
77 'sequential': '1',
78 'contact_id': contactId,
79 'return': CRM.contact.return },
80 { success: function (data) {
81 cj.each(data.values[0], function (key, value) {
82 // set the values
83 var actualFldName = profileFields[key];
84 if (key == 'country' || key == 'state_province') {
85 idFldName = key + '_id';
86 value = data.values[0][idFldName];
87 }
88 setFieldValue(actualFldName, value, blockNo)
89 });
90
91 // for membership batch entry based on contact we need to enable / disable
92 // add membership select
93 if(CRM.batch.type_id == 2) {
94 CRM.api('Membership', 'get', {
95 'sequential': '1',
96 'contact_id': contactId,
97 },
98 { success: function (data) {
99 if (data.count > 0) {
100 //get the information on membership type
101 var membershipTypeId = data.values[0].membership_type_id;
102 var membershipJoinDate = data.values[0].join_date;
103 CRM.api('MembershipType', 'get', {
104 'sequential': '1',
105 'id': membershipTypeId
106 },
107 { success: function (data) {
108 var memTypeContactId = data.values[0].member_of_contact_id;
109 cj('select[id="member_option_' + blockNo + '"]').removeAttr('disabled').val(2);
110 cj('select[id="field_' + blockNo + '_membership_type_0"]').val(memTypeContactId).change();
111 cj('select[id="field_' + blockNo + '_membership_type_1"]').val(membershipTypeId).change();
112 setDateFieldValue('join_date', membershipJoinDate, blockNo)
113 }
114 });
115 }
116 }
117 });
118 }
119 }
120 });
121 }
122
123 function setPaymentBlock(form, memType) {
124 var rowID = form.closest('div.crm-grid-row').attr('entity_id');
125 var dataUrl = CRM.url('civicrm/ajax/memType');
126
127 if (!memType) {
128 memType = cj('select[id="field_' + rowID + '_membership_type_1"]').val();
129 }
130
131 cj.post(dataUrl, {mtype: memType}, function (data) {
132 cj('#field_' + rowID + '_financial_type').val(data.financial_type_id);
133 cj('#field_' + rowID + '_total_amount').val(data.total_amount).change();
134 }, 'json');
135 }
136
137 function hideSendReceipt() {
138 cj('input[id*="][send_receipt]"]').each(function () {
139 showHideReceipt(cj(this));
140 });
141 }
142
143 function showHideReceipt(elem) {
144 var rowID = elem.closest('div.crm-grid-row').attr('entity_id');
145 if (elem.prop('checked')) {
146 cj('.crm-batch-receipt_date-' + rowID).hide();
147 }
148 else {
149 cj('.crm-batch-receipt_date-' + rowID).show();
150 }
151 }
152
153 function validateRow() {
154 cj('.selector-rows').each(function () {
155 checkColumns(cj(this));
156 });
157 }
158
159 function checkColumns(parentRow) {
160 // show valid row icon if all required data is field
161 var validRow = 0;
162 var inValidRow = 0;
163 var errorExists = false;
164 var rowID = parentRow.closest('div.crm-grid-row').attr('entity_id');
165
166 parentRow.find('div .required').each(function () {
167 //special case to handle contact autocomplete select
168 var fieldId = cj(this).attr('id');
169 if (fieldId.substring(0, 16) == 'primary_contact_') {
170 // if display value is set then make sure we also check if contact id is set
171 if (!cj(this).val()) {
172 inValidRow++;
173 }
174 else {
175 if (cj(this).val() && !cj('input[name="primary_contact_select_id[' + rowID + ']"]').val()) {
176 inValidRow++;
177 errorExists = true;
178 }
179 }
180 }
181 else {
182 if (!cj(this).val()) {
183 inValidRow++;
184 }
185 else {
186 if (cj(this).hasClass('error') && !cj(this).hasClass('valid')) {
187 errorExists = true;
188 }
189 else {
190 validRow++;
191 }
192 }
193 }
194 });
195
196 // this means user has entered some data
197 if (errorExists) {
198 parentRow.find("div:first span").prop('class', 'batch-invalid');
199 }
200 else {
201 if (inValidRow == 0 && validRow > 0) {
202 parentRow.find("div:first span").prop('class', 'batch-valid');
203 }
204 else {
205 parentRow.find("div:first span").prop('class', 'batch-edit');
206 }
207 }
208 }
209
210 function calculateActualTotal() {
211 var total = 0;
212 cj('input[id*="_total_amount"]').each(function () {
213 if (cj(this).val()) {
214 total += parseFloat(cj(this).val());
215 }
216 });
217
218 cj('.batch-actual-total').html(formatMoney(total));
219 }
220
221 //money formatting/localization
222 function formatMoney(amount) {
223 var c = 2;
224 var t = CRM.setting.monetaryThousandSeparator;
225 var d = CRM.setting.monetaryDecimalPoint;
226
227 var n = amount,
228 c = isNaN(c = Math.abs(c)) ? 2 : c,
229 d = d == undefined ? "," : d,
230 t = t == undefined ? "." : t, s = n < 0 ? "-" : "",
231 i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "",
232 j = (j = i.length) > 3 ? j % 3 : 0;
233
234 return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
235 }
236
237 /**
238 * This function is use to setdefault elements via ajax
239 *
240 * @param fname string field name
241 * @return void
242 */
243 function setFieldValue(fname, fieldValue, blockNo) {
244 var elementId = cj('[name="field[' + blockNo + '][' + fname + ']"]');
245
246 if (elementId.length == 0) {
247 elementId = cj('input[type=checkbox][name^="field[' + blockNo + '][' + fname + ']"][type!=hidden]');
248 }
249
250 // if element not found than return
251 if (elementId.length == 0) {
252 return;
253 }
254
255 //check if it is date element
256 var isDateElement = elementId.attr('format');
257
258 // check if it is wysiwyg element
259 var editor = elementId.attr('editor');
260
261 //get the element type
262 var elementType = elementId.attr('type');
263
264 // set the value for all the elements, elements needs to be handled are
265 // select, checkbox, radio, date fields, text, textarea, multi-select
266 // wysiwyg editor, advanced multi-select ( to do )
267 if (elementType == 'radio') {
268 if (fieldValue) {
269 elementId.filter("[value=" + fieldValue + "]").prop("checked", true);
270 }
271 else {
272 elementId.removeProp('checked');
273 }
274 }
275 else {
276 if (elementType == 'checkbox') {
277 // handle checkbox
278 elementId.removeProp('checked');
279 if (fieldValue) {
280 cj.each(fieldValue, function (key, value) {
281 cj('input[name="field[' + blockNo + '][' + fname + '][' + value + ']"]').prop('checked', true);
282 });
283 }
284 }
285 else {
286 if (editor) {
287 switch (editor) {
288 case 'ckeditor':
289 var elemtId = elementId.attr('id');
290 oEditor = CKEDITOR.instances[elemtId];
291 oEditor.setData(htmlContent);
292 break;
293 case 'tinymce':
294 var elemtId = element.attr('id');
295 tinyMCE.get(elemtId).setContent(htmlContent);
296 break;
297 case 'joomlaeditor':
298 // TO DO
299 case 'drupalwysiwyg':
300 // TO DO
301 default:
302 elementId.val(fieldValue);
303 }
304 }
305 else {
306 elementId.val(fieldValue);
307 }
308 }
309 }
310
311 // since we use different display field for date we also need to set it.
312 // also check for date time field and set the value correctly
313 if (isDateElement && fieldValue) {
314 setDateFieldValue(fname, fieldValue, blockNo)
315 }
316 }
317
318 function setDateFieldValue(fname, fieldValue, blockNo) {
319 var dateValues = fieldValue.split(' ');
320
321 var actualDateElement = cj('#field_' + blockNo + '_' + fname);
322 var date_format = actualDateElement.attr('format');
323 var altDateFormat = 'yy-mm-dd';
324
325 var actualDateValue = cj.datepicker.parseDate(altDateFormat, dateValues[0]);
326
327 // format date according to display field
328 var hiddenDateValue = cj.datepicker.formatDate('mm/dd/yy', actualDateValue);
329
330 actualDateElement.val(hiddenDateValue);
331
332 var displayDateValue = actualDateElement.val();
333 if (date_format != 'mm/dd/yy') {
334 displayDateValue = cj.datepicker.formatDate(date_format, actualDateValue);
335 }
336
337 cj('#field_' + blockNo + '_' + fname + '_display').val(displayDateValue);
338
339 // need to fix time formatting
340 if (dateValues[1]) {
341 cj('#field_' + blockNo + '_' + fname + '_time').val(dateValues[1].substr(0, 5));
342 }
343 }