Always show parent/child nesting in group selectors
[civicrm-core.git] / templates / CRM / Batch / Form / Entry.tpl
CommitLineData
6a488035
TO
1{*
2 +--------------------------------------------------------------------+
819d0d41 3 | CiviCRM version 4.5 |
6a488035 4 +--------------------------------------------------------------------+
819d0d41 5 | Copyright CiviCRM LLC (c) 2004-2014 |
6a488035
TO
6 +--------------------------------------------------------------------+
7 | This file is a part of CiviCRM. |
8 | |
9 | CiviCRM is free software; you can copy, modify, and distribute it |
10 | under the terms of the GNU Affero General Public License |
11 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
12 | |
13 | CiviCRM is distributed in the hope that it will be useful, but |
14 | WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
16 | See the GNU Affero General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU Affero General Public |
19 | License and the CiviCRM Licensing Exception along |
20 | with this program; if not, contact CiviCRM LLC |
21 | at info[AT]civicrm[DOT]org. If you have questions about the |
22 | GNU Affero General Public License or the licensing of CiviCRM, |
23 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
24 +--------------------------------------------------------------------+
25*}
26<div class="batch-entry form-item">
261371e1 27 <div id="help">
b4ae0bee 28 {ts}Click Validate & Process below when you've entered all items for the batch. You can also Save & Continue Later at any time. Go to Administer > Customize Data and Screens > Profiles > Reserved Profiles > to add, remove or change the order of columns.{/ts}
6a488035 29 </div>
261371e1 30 {if $batchAmountMismatch}
31 <div class="status message status-warning">
32 <div
33 class="icon alert-icon"></div> {ts}Total for amounts entered below does not match the expected batch total.{/ts}
34 </div>
35 <div class="crm-button crm-button_qf_Entry_upload_force-save">
36 {$form._qf_Entry_upload_force.html}
37 </div>
38 <div class="clear"></div>
39 {/if}
40 <table class="form-layout-compressed batch-totals">
41 <tr>
42 <td class="label">{ts}Total amount expected{/ts}</td>
43 <td class="right"><span class="batch-expected-total">{$batchTotal|crmMoney}</span></td>
44 </tr>
45 <tr>
46 <td class="label">{ts}Total amount entered{/ts}</td>
47 <td class="right">{$config->defaultCurrencySymbol} <span class="batch-actual-total"></span></td>
48 </tr>
49 </table>
50
51 <div class="crm-copy-fields crm-grid-table" id="crm-batch-entry-table">
52 <div class="crm-grid-header">
53 <div class="crm-grid-cell">&nbsp;</div>
54 <div class="crm-grid-cell">{ts}Contact{/ts}</div>
55 {if $batchType eq 2 }
6a488035 56 <div class="crm-grid-cell">&nbsp;</div>
261371e1 57 {/if}
58 {foreach from=$fields item=field key=fieldName}
59 <div class="crm-grid-cell">
694ca46e 60 {if $field.name|substr:0:11 ne 'soft_credit'}
261371e1 61 <img src="{$config->resourceBase}i/copy.png"
62 alt="{ts 1=$field.title}Click to copy %1 from row one to all rows.{/ts}"
63 fname="{$field.name}" class="action-icon"
694ca46e 64 title="{ts}Click here to copy the value in row one to ALL rows.{/ts}"/>
65 {/if}{$field.title}
261371e1 66 </div>
67 {/foreach}
68 </div>
cdeb4bdf 69
6a488035 70 {section name='i' start=1 loop=$rowCount}
261371e1 71 {assign var='rowNumber' value=$smarty.section.i.index}
72 <div class="{cycle values="odd-row,even-row"} selector-rows crm-grid-row" entity_id="{$rowNumber}">
6a488035
TO
73 <div class="compressed crm-grid-cell"><span class="batch-edit"></span></div>
74 {* contact select/create option*}
75 <div class="compressed crm-grid-cell">
ccec9d6b 76 {$form.primary_contact_id.$rowNumber.html|crmAddClass:big}
6a488035
TO
77 </div>
78
79 {if $batchType eq 2 }
80 {$form.member_option.$rowNumber.html}
81 {/if}
82
83 {foreach from=$fields item=field key=fieldName}
261371e1 84 {assign var=n value=$field.name}
85 {if ( $fields.$n.data_type eq 'Date') or ( in_array( $n, array( 'thankyou_date', 'cancel_date', 'receipt_date', 'receive_date', 'join_date', 'membership_start_date', 'membership_end_date' ) ) ) }
86 <div class="compressed crm-grid-cell">
87 <span class="crm-batch-{$n}-{$rowNumber}">
88 {include file="CRM/common/jcalendar.tpl" elementName=$n elementIndex=$rowNumber batchUpdate=1}
89 </span>
90 </div>
91 {elseif $n eq 'soft_credit'}
92 <div class="compressed crm-grid-cell">
ccec9d6b 93 {$form.soft_credit_contact_id.$rowNumber.html|crmAddClass:big}
3e77035d 94 {$form.soft_credit_amount.$rowNumber.label}&nbsp;{$form.soft_credit_amount.$rowNumber.html|crmAddClass:eight}
261371e1 95 </div>
96 {elseif in_array( $fields.$n.html_type, array('Radio', 'CheckBox'))}
6a488035 97 <div class="compressed crm-grid-cell">&nbsp;{$form.field.$rowNumber.$n.html}</div>
261371e1 98 {else}
6a488035 99 <div class="compressed crm-grid-cell">{$form.field.$rowNumber.$n.html}</div>
261371e1 100 {/if}
6a488035 101 {/foreach}
261371e1 102 </div>
6a488035 103 {/section}
261371e1 104 </div>
105 <div class="crm-submit-buttons">{if $fields}{$form._qf_Batch_refresh.html}{/if} &nbsp; {$form.buttons.html}</div>
6a488035
TO
106</div>
107{literal}
108<script type="text/javascript">
3cc60a06 109CRM.$(function($) {
d5cf4608 110 cj('.selector-rows').change(function () {
261371e1 111 var options = {
112 'url': {/literal}"{crmURL p='civicrm/ajax/batch' h=0}"{literal}
113 };
6a488035 114
261371e1 115 cj("#Entry").ajaxSubmit(options);
d5cf4608 116 });
6a488035 117
eac283fc 118 cj('#crm-container').on('keyup change', '*.selector-rows', function () {
261371e1 119 // validate rows
120 checkColumns(cj(this));
121 });
6a488035 122
261371e1 123 // validate rows
124 validateRow();
6a488035 125
261371e1 126 //calculate the actual total for the batch
127 calculateActualTotal();
6a488035 128
261371e1 129 cj('input[id*="_total_amount"]').bind('keyup change', function () {
130 calculateActualTotal();
131 });
6a488035 132
261371e1 133 {/literal}{if $batchType eq 1 }{literal}
134 // hide all dates if send receipt is checked
135 hideSendReceipt();
6a488035 136
261371e1 137 // hide the receipt date if send receipt is checked
138 cj('input[id*="][send_receipt]"]').change(function () {
139 showHideReceipt(cj(this));
140 });
6a488035 141
261371e1 142 {/literal}{else}{literal}
143 cj('select[id^="member_option_"]').each(function () {
144 if (cj(this).val() == 1) {
6f9cd76f 145 cj(this).prop('disabled', true);
261371e1 146 }
147 });
6a488035 148
261371e1 149 // set payment info accord to membership type
150 cj('select[id*="_membership_type_0"]').change(function () {
151 setPaymentBlock(cj(this), null);
152 });
6a488035 153
261371e1 154 cj('select[id*="_membership_type_1"]').change(function () {
155 setPaymentBlock(cj(this), cj(this).val());
156 });
6a488035 157
261371e1 158 {/literal}{/if}{literal}
6a488035 159
261371e1 160 // line breaks between radio buttons and checkboxes
161 cj('input.form-radio').next().after('<br />');
162 cj('input.form-checkbox').next().after('<br />');
6a488035 163
261371e1 164 //set the focus on first element
165 cj('#primary_contact_1').focus();
6a488035 166
261371e1 167});
6a488035 168
261371e1 169function setPaymentBlock(form, memType) {
170 var rowID = form.closest('div.crm-grid-row').attr('entity_id');
171 var dataUrl = {/literal}"{crmURL p='civicrm/ajax/memType' h=0}"{literal};
6a488035 172
261371e1 173 if (!memType) {
174 memType = cj('select[id="field_' + rowID + '_membership_type_1"]').val();
6a488035
TO
175 }
176
261371e1 177 cj.post(dataUrl, {mtype: memType}, function (data) {
178 cj('#field_' + rowID + '_financial_type').val(data.financial_type_id);
179 cj('#field_' + rowID + '_total_amount').val(data.total_amount).change();
180 }, 'json');
181}
182
183function hideSendReceipt() {
184 cj('input[id*="][send_receipt]"]').each(function () {
185 showHideReceipt(cj(this));
186 });
187}
6a488035 188
261371e1 189function showHideReceipt(elem) {
190 var rowID = elem.closest('div.crm-grid-row').attr('entity_id');
191 if (elem.prop('checked')) {
192 cj('.crm-batch-receipt_date-' + rowID).hide();
193 }
194 else {
195 cj('.crm-batch-receipt_date-' + rowID).show();
196 }
197}
198
199function validateRow() {
200 cj('.selector-rows').each(function () {
201 checkColumns(cj(this));
202 });
203}
204
205function checkColumns(parentRow) {
206 // show valid row icon if all required data is field
207 var validRow = 0;
208 var inValidRow = 0;
209 var errorExists = false;
210 var rowID = parentRow.closest('div.crm-grid-row').attr('entity_id');
211
212 parentRow.find('div .required').each(function () {
213 //special case to handle contact autocomplete select
214 var fieldId = cj(this).attr('id');
215 if (fieldId.substring(0, 16) == 'primary_contact_') {
216 // if display value is set then make sure we also check if contact id is set
217 if (!cj(this).val()) {
218 inValidRow++;
219 }
220 else {
eac283fc 221 var contactIdElement = cj('input[name="primary_contact_select_id[' + rowID + ']"]');
222 if (cj(this).val() && !contactIdElement.val()) {
261371e1 223 inValidRow++;
224 errorExists = true;
225 }
eac283fc 226 else if (cj(this).val() && contactIdElement.val()) {
227 // this is hack to remove error span because we are skipping this for autocomplete fields
228 cj(this).next('span.crm-error').remove();
229 }
261371e1 230 }
231 }
232 else {
233 if (!cj(this).val()) {
234 inValidRow++;
235 }
236 else {
eac283fc 237 if (cj(this).hasClass('error') && (cj(this).hasClass('valid') || cj(this).hasClass('required'))) {
261371e1 238 errorExists = true;
239 }
240 else {
241 validRow++;
242 }
243 }
244 }
245 });
246
247 // this means user has entered some data
248 if (errorExists) {
249 parentRow.find("div:first span").prop('class', 'batch-invalid');
250 }
251 else {
252 if (inValidRow == 0 && validRow > 0) {
253 parentRow.find("div:first span").prop('class', 'batch-valid');
254 }
255 else {
256 parentRow.find("div:first span").prop('class', 'batch-edit');
257 }
258 }
259}
260
261function calculateActualTotal() {
262 var total = 0;
263 cj('input[id*="_total_amount"]').each(function () {
264 if (cj(this).val()) {
265 total += parseFloat(cj(this).val());
266 }
267 });
268
269 cj('.batch-actual-total').html(formatMoney(total));
270}
271
272//money formatting/localization
273function formatMoney(amount) {
274 var c = 2;
275 var t = '{/literal}{$config->monetaryThousandSeparator}{literal}';
276 var d = '{/literal}{$config->monetaryDecimalPoint}{literal}';
277
278 var n = amount,
279 c = isNaN(c = Math.abs(c)) ? 2 : c,
280 d = d == undefined ? "," : d,
281 t = t == undefined ? "." : t, s = n < 0 ? "-" : "",
282 i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "",
283 j = (j = i.length) > 3 ? j % 3 : 0;
284
285 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) : "");
286}
287
288function updateContactInfo(blockNo, prefix) {
289 var contactHiddenElement = 'input[name="' + prefix + 'contact_select_id[' + blockNo + ']"]';
290 var contactId = cj(contactHiddenElement).val();
291
292 var returnProperties = '';
293 var profileFields = new Array();
294 {/literal}
295 {if $contactFields}
296 {foreach from=$contactFields item=val key=fldName}
297 var fldName = "{$fldName}";
298 {literal}
299 if (returnProperties) {
300 returnProperties = returnProperties + ',';
301 }
302 var fld = fldName.split('-');
303 returnProperties = returnProperties + fld[0];
304 profileFields[fld[0]] = fldName;
305 {/literal}
306 {/foreach}
307 {/if}
308 {literal}
309
310 CRM.api('Contact', 'get', {
311 'sequential': '1',
6a488035
TO
312 'contact_id': contactId,
313 'return': returnProperties },
261371e1 314 { success: function (data) {
315 cj.each(data.values[0], function (key, value) {
316 // set the values
317 var actualFldName = profileFields[key];
318 if (key == 'country' || key == 'state_province') {
319 idFldName = key + '_id';
320 value = data.values[0][idFldName];
321 }
322 setFieldValue(actualFldName, value, blockNo)
323 });
6a488035 324
261371e1 325 // for membership batch entry based on contact we need to enable / disable
326 // add membership select
327 {/literal}{if $batchType eq 2}{literal}
328 CRM.api('Membership', 'get', {
329 'sequential': '1',
330 'contact_id': contactId,
331 },
332 { success: function (data) {
333 if (data.count > 0) {
334 //get the information on membership type
335 var membershipTypeId = data.values[0].membership_type_id;
336 var membershipJoinDate = data.values[0].join_date;
337 CRM.api('MembershipType', 'get', {
338 'sequential': '1',
339 'id': membershipTypeId
340 },
341 { success: function (data) {
342 var memTypeContactId = data.values[0].member_of_contact_id;
6f9cd76f 343 cj('select[id="member_option_' + blockNo + '"]').prop('disabled', false).val(2);
261371e1 344 cj('select[id="field_' + blockNo + '_membership_type_0"]').val(memTypeContactId).change();
345 cj('select[id="field_' + blockNo + '_membership_type_1"]').val(membershipTypeId).change();
346 setDateFieldValue('join_date', membershipJoinDate, blockNo)
347 }
6a488035 348 });
6a488035 349 }
261371e1 350 }
6a488035 351 });
261371e1 352 {/literal}{/if}{literal}
353 }
6a488035 354 });
261371e1 355}
6a488035
TO
356
357/**
358 * This function is use to setdefault elements via ajax
359 *
360 * @param fname string field name
361 * @return void
362 */
261371e1 363function setFieldValue(fname, fieldValue, blockNo) {
364 var elementId = cj('[name="field[' + blockNo + '][' + fname + ']"]');
6a488035 365
261371e1 366 if (elementId.length == 0) {
367 elementId = cj('input[type=checkbox][name^="field[' + blockNo + '][' + fname + ']"][type!=hidden]');
368 }
6a488035 369
261371e1 370 // if element not found than return
371 if (elementId.length == 0) {
372 return;
373 }
6a488035 374
261371e1 375 //check if it is date element
376 var isDateElement = elementId.attr('format');
6a488035 377
261371e1 378 // check if it is wysiwyg element
379 var editor = elementId.attr('editor');
6a488035 380
261371e1 381 //get the element type
382 var elementType = elementId.attr('type');
6a488035 383
261371e1 384 // set the value for all the elements, elements needs to be handled are
385 // select, checkbox, radio, date fields, text, textarea, multi-select
386 // wysiwyg editor, advanced multi-select ( to do )
387 if (elementType == 'radio') {
388 if (fieldValue) {
389 elementId.filter("[value=" + fieldValue + "]").prop("checked", true);
390 }
391 else {
392 elementId.removeProp('checked');
393 }
394 }
395 else {
396 if (elementType == 'checkbox') {
6a488035
TO
397 // handle checkbox
398 elementId.removeProp('checked');
261371e1 399 if (fieldValue) {
400 cj.each(fieldValue, function (key, value) {
401 cj('input[name="field[' + blockNo + '][' + fname + '][' + value + ']"]').prop('checked', true);
6a488035
TO
402 });
403 }
261371e1 404 }
405 else {
406 if (editor) {
407 switch (editor) {
408 case 'ckeditor':
409 var elemtId = elementId.attr('id');
410 oEditor = CKEDITOR.instances[elemtId];
411 oEditor.setData(htmlContent);
412 break;
413 case 'tinymce':
414 var elemtId = element.attr('id');
415 tinyMCE.get(elemtId).setContent(htmlContent);
416 break;
417 case 'joomlaeditor':
6a488035 418 // TO DO
261371e1 419 case 'drupalwysiwyg':
6a488035 420 // TO DO
261371e1 421 default:
422 elementId.val(fieldValue);
423 }
424 }
425 else {
426 elementId.val(fieldValue);
6a488035 427 }
6a488035 428 }
261371e1 429 }
6a488035 430
261371e1 431 // since we use different display field for date we also need to set it.
432 // also check for date time field and set the value correctly
433 if (isDateElement && fieldValue) {
434 setDateFieldValue(fname, fieldValue, blockNo)
435 }
6a488035
TO
436}
437
261371e1 438function setDateFieldValue(fname, fieldValue, blockNo) {
439 var dateValues = fieldValue.split(' ');
6a488035 440
261371e1 441 var actualDateElement = cj('#field_' + blockNo + '_' + fname);
442 var date_format = actualDateElement.attr('format');
443 var altDateFormat = 'yy-mm-dd';
6a488035 444
261371e1 445 var actualDateValue = cj.datepicker.parseDate(altDateFormat, dateValues[0]);
6a488035 446
261371e1 447 // format date according to display field
448 var hiddenDateValue = cj.datepicker.formatDate('mm/dd/yy', actualDateValue);
6a488035 449
261371e1 450 actualDateElement.val(hiddenDateValue);
6a488035 451
261371e1 452 var displayDateValue = actualDateElement.val();
453 if (date_format != 'mm/dd/yy') {
454 displayDateValue = cj.datepicker.formatDate(date_format, actualDateValue);
455 }
6a488035 456
261371e1 457 cj('#field_' + blockNo + '_' + fname + '_display').val(displayDateValue);
6a488035 458
261371e1 459 // need to fix time formatting
460 if (dateValues[1]) {
461 cj('#field_' + blockNo + '_' + fname + '_time').val(dateValues[1].substr(0, 5));
462 }
6a488035
TO
463}
464
465</script>
466{/literal}
467
468{*include batch copy js js file*}
469{include file="CRM/common/batchCopy.tpl"}