Merge pull request #5593 from relldoesphp/CRM-15992
[civicrm-core.git] / templates / CRM / Contact / Page / View / Summary.js
1 // http://civicrm.org/licensing
2 (function($, _) {
3 // FIXME: Much of this code is redundant with CRM.loadForm
4
5 var ajaxFormParams = {
6 dataType:'json',
7 beforeSubmit: function(arr, $form, options) {
8 $form.block();
9 },
10 success: requestHandler,
11 error: errorHandler
12 };
13
14 function crmFormInline(o) {
15 var data = o.data('edit-params');
16 if (o.is('.crm-edit-ready .crm-inline-edit') && data) {
17 o.animate({height: '+=50px'}, 200);
18 data.snippet = 6;
19 data.reset = 1;
20 o.addClass('form');
21 $('.crm-edit-ready').removeClass('crm-edit-ready');
22 o.block();
23 $.getJSON(CRM.url('civicrm/ajax/inline', data))
24 .fail(errorHandler)
25 .done(function(response) {
26 o.unblock();
27 o.css('overflow', 'hidden').wrapInner('<div class="inline-edit-hidden-content" style="display:none" />').append(response.content);
28 // Smooth resizing
29 var newHeight = $('.crm-container-snippet', o).height();
30 var diff = newHeight - parseInt(o.css('height'), 10);
31 if (diff < 0) {
32 diff = 0 - diff;
33 }
34 o.animate({height: '' + newHeight + 'px'}, diff * 2, function() {
35 o.removeAttr('style');
36 });
37 $('form', o).validate(CRM.validate.params);
38 ajaxFormParams.data = data;
39 $('form', o).ajaxForm(ajaxFormParams);
40 o.trigger('crmLoad').trigger('crmFormLoad');
41 });
42 }
43 }
44
45 function reloadBlock(el) {
46 return $(el).each(function() {
47 var data = $(this).data('edit-params');
48 data.snippet = data.reset = 1;
49 data.class_name = data.class_name.replace('Form', 'Page');
50 data.type = 'page';
51 $(this).closest('.crm-summary-block').load(CRM.url('civicrm/ajax/inline', data), function() {$(this).trigger('crmLoad');});
52 });
53 }
54
55 function requestHandler(response) {
56 var o = $('div.crm-inline-edit.form');
57 $('form', o).ajaxFormUnbind();
58
59 if (response.status == 'success' || response.status == 'cancel') {
60 o.trigger('crmFormSuccess', [response]);
61 $('.crm-inline-edit-container').addClass('crm-edit-ready');
62 var data = o.data('edit-params');
63 var dependent = $((o.data('dependent-fields') || []).join(','));
64 // Clone the add-new link if replacing it, and queue the clone to be refreshed as a dependent block
65 if (o.hasClass('add-new') && response.addressId) {
66 data.aid = response.addressId;
67 var clone = o.closest('.crm-summary-block').clone();
68 o.data('edit-params', data);
69 $('form', clone).remove();
70 if (clone.hasClass('contactCardLeft')) {
71 clone.removeClass('contactCardLeft').addClass('contactCardRight');
72 }
73 else if (clone.hasClass('contactCardRight')) {
74 clone.removeClass('contactCardRight').addClass('contactCardLeft');
75 }
76 var cl = $('.crm-inline-edit', clone);
77 var clData = cl.data('edit-params');
78 var locNo = clData.locno++;
79 cl.attr('id', cl.attr('id').replace(locNo, clData.locno)).removeClass('form');
80 o.closest('.crm-summary-block').after(clone);
81 dependent = dependent.add($('.crm-inline-edit', clone));
82 }
83 $('a.ui-notify-close', '#crm-notification-container').click();
84 // Delete an address
85 if (o.hasClass('address') && !o.hasClass('add-new') && !response.addressId) {
86 o.parent().remove();
87 CRM.status(ts('Address Deleted'));
88 }
89 else {
90 // Reload this block plus all dependent blocks
91 reloadBlock(dependent.add(o));
92 CRM.status(ts('Saved'));
93 }
94 }
95 else {
96 // Handle formRule error
97 $('.crm-container-snippet', o).replaceWith(response.content);
98 $('form', o).validate(CRM.validate.params);
99 $('form', o).ajaxForm(ajaxFormParams);
100 o.trigger('crmFormError', [response]).trigger('crmFormLoad').trigger('crmLoad');
101 }
102 }
103
104 /**
105 * Configure optimistic locking mechanism for inplace editing
106 *
107 * options.ignoreLabel: string, text for a button
108 * options.reloadLabel: string, text for a button
109 */
110 $.fn.crmFormContactLock = function(options) {
111 var form = this;
112 // AFTER ERROR: Render any "Ignore" and "Restart" buttons
113 return this.on('crmFormError', function(event, obj, status) {
114 var o = $(event.target);
115 var data = o.data('edit-params');
116 var errorTag = o.find('.update_oplock_ts');
117 if (errorTag.length > 0) {
118 $('<span>')
119 .addClass('crm-lock-button css_right')
120 .appendTo(errorTag);
121
122 var buttonContainer = o.find('.crm-lock-button');
123 $('<button>')
124 .addClass('crm-button')
125 .text(options.saveAnywayLabel)
126 .click(function() {
127 $(form).find('input[name=oplock_ts]').val(errorTag.attr('data:update_oplock_ts'));
128 errorTag.parent().hide();
129 $(this).closest('form').find('.crm-form-submit.default').first().click();
130 return false;
131 })
132 .appendTo(buttonContainer)
133 ;
134 $('<button>')
135 .addClass('crm-button')
136 .text(options.reloadLabel)
137 .click(function() {
138 window.location.reload();
139 return false;
140 })
141 .appendTo(buttonContainer)
142 ;
143 }
144 });
145 };
146
147 function errorHandler(response) {
148 CRM.alert(ts('Unable to reach the server. Please refresh this page in your browser and try again.'), ts('Network Error'), 'error');
149 $('.crm-inline-edit.form form').unblock();
150 }
151
152 $(function() {
153 // don't perform inline edit during print mode
154 if (CRM.summaryPrint.mode) {
155 $('div').removeClass('crm-inline-edit');
156 $('.crm-inline-block-content > div.crm-edit-help').remove();
157 $('div.crm-inline-block-content').removeAttr('title');
158 }
159 // Set page title
160 var oldName = 'CiviCRM';
161 var nameTitle = $('#crm-remove-title');
162 if (nameTitle.length > 0) {
163 oldName = nameTitle.text();
164 nameTitle.parent('h1').remove();
165 }
166 else {
167 $('h1').each(function() {
168 if ($(this).text() == oldName) {
169 $(this).remove();
170 }
171 });
172 }
173 function refreshTitle() {
174 var contactName = $('.crm-summary-display_name').text();
175 contactName = $.trim(contactName);
176 document.title = $('title').html().replace(oldName, contactName);
177 oldName = contactName;
178 }
179 $('#contactname-block').load(refreshTitle);
180 refreshTitle();
181
182 var clicking;
183 $('.crm-inline-edit-container')
184 .addClass('crm-edit-ready')
185 // Allow links inside edit blocks to be clicked without triggering edit
186 .on('mousedown', '.crm-inline-edit:not(.form) a, .crm-inline-edit:not(.form) .crm-accordion-header, .crm-inline-edit:not(.form) .collapsible-title', function(event) {
187 if (event.which == 1) {
188 event.stopPropagation();
189 return false;
190 }
191 })
192 // Respond to a click (not drag, not right-click) of crm-inline-edit blocks
193 .on('mousedown', '.crm-inline-edit:not(.form)', function(button) {
194 if (button.which == 1) {
195 clicking = this;
196 setTimeout(function() {clicking = null;}, 500);
197 }
198 })
199 .on('mouseup', '.crm-inline-edit:not(.form)', function(button) {
200 if (clicking === this && button.which == 1) {
201 crmFormInline($(this));
202 }
203 })
204 // Inline edit form cancel button
205 .on('click', '.crm-inline-edit :submit[name$=cancel]', function() {
206 var container = $(this).closest('.crm-inline-edit.form');
207 $('form', container).ajaxFormUnbind();
208 $('.inline-edit-hidden-content', container).nextAll().remove();
209 $('.inline-edit-hidden-content > *:first-child', container).unwrap();
210 container.removeClass('form');
211 $('.crm-inline-edit-container').addClass('crm-edit-ready');
212 $('a.ui-notify-close', '#crm-notification-container').click();
213 return false;
214 })
215 // Switch tabs when clicking tag link
216 .on('click', '#tagLink a', function() {
217 $('#tab_tag a').click();
218 return false;
219 })
220 // make sure only one is_primary radio is checked
221 .on('change', '[class$=is_primary] input', function() {
222 if ($(this).is(':checked')) {
223 $('[class$=is_primary] input', $(this).closest('form')).not(this).prop('checked', false);
224 }
225 })
226 // make sure only one builk_mail radio is checked
227 .on('change', '.crm-email-bulkmail input', function(){
228 if ($(this).is(':checked')) {
229 $('.crm-email-bulkmail input').not(this).prop('checked', false);
230 }
231 })
232 // handle delete link within blocks
233 .on('click', '.crm-delete-inline', function(e) {
234 var row = $(this).closest('tr');
235 var form = $(this).closest('form');
236 row.hide();
237 $('input', row).val('');
238 //if the primary is checked for deleted block
239 //unset and set first as primary
240 if ($('[class$=is_primary] input:checked', row).length > 0) {
241 $('[class$=is_primary] input', row).prop('checked', false);
242 $('[class$=is_primary] input:first', form).prop('checked', true );
243 }
244 $('.add-more-inline', form).show();
245 e.preventDefault();
246 })
247 // Delete an address
248 .on('click', '.crm-inline-edit.address .delete-button', function(e) {
249 var $block = $(this).closest('.crm-inline-edit.address');
250 CRM.confirm({message: ts('Are you sure you want to delete this address?')})
251 .on('crmConfirm:yes', function() {
252 CRM.api3('address', 'delete', {id: $block.data('edit-params').aid}, true)
253 .done(function(data) {
254 $('.crm-inline-edit-container').addClass('crm-edit-ready');
255 $block.remove();
256 reloadBlock('.crm-inline-edit.address:not(.add-new)');
257 });
258 });
259 e.preventDefault();
260 })
261 // add more and set focus to new row
262 .on('click', '.add-more-inline', function(e) {
263 var form = $(this).closest('form');
264 var row = $('tr[class="hiddenElement"]:first', form);
265 row.removeClass('hiddenElement');
266 $('input:focus', form).blur();
267 $('input:first', row).focus();
268 if ($('tr[class="hiddenElement"]').length < 1) {
269 $(this).hide();
270 }
271 e.preventDefault();
272 });
273 // Trigger cancel button on esc keypress
274 $(document).keydown(function(key) {
275 if (key.which == 27) {
276 $('.crm-inline-edit.form :submit[name$=cancel]').click();
277 }
278 });
279 $('#crm-container')
280 // Switch tabs when clicking log link
281 .on('click', '#crm-record-log a.crm-log-view', function() {
282 $('#tab_log a').click();
283 return false;
284 })
285 // Handle action links in popup
286 .on('click', '.crm-contact_actions-list a, .crm-contact_activities-list a', function(e) {
287 $('#crm-contact-actions-list').hide();
288 if ($(this).attr('href') === '#') {
289 var $tab = $('#tab_' + ($(this).data('tab') || 'summary'));
290 CRM.tabHeader.focus($tab);
291 e.preventDefault();
292 } else {
293 CRM.popup.call(this, e);
294 }
295 })
296 .on('crmPopupFormSuccess', '.crm-contact_actions-list a, .crm-contact_activities-list a', function() {
297 var $tab = $('#tab_' + ($(this).data('tab') || 'summary'));
298 CRM.tabHeader.resetTab($tab);
299 CRM.tabHeader.focus($tab);
300 });
301 $(document)
302 // Actions menu
303 .on('click', function(e) {
304 if ($(e.target).is('#crm-contact-actions-link, #crm-contact-actions-link *')) {
305 $('#crm-contact-actions-list').show();
306 return false;
307 }
308 $('#crm-contact-actions-list').hide();
309 })
310 .on('crmFormSuccess crmLoad', function(e, data) {
311 // Update changelog tab and contact footer
312 if (data && data.changeLog) {
313 if (data.changeLog.count) {
314 CRM.tabHeader.updateCount('#tab_log', data.changeLog.count);
315 }
316 if (data.changeLog.markup) {
317 $("#crm-record-log").replaceWith(data.changeLog.markup);
318 }
319 }
320 })
321 .on('crmFormSuccess', function(e, data) {
322 // Refresh changeLog - advanced logging
323 if (CRM.reloadChangeLogTab) {
324 CRM.reloadChangeLogTab();
325 }
326 // Refresh changeLog - simple logging
327 // If we didn't get a changelog count in the response, force refresh the changelog tab to populate it
328 else {
329 CRM.tabHeader.resetTab('#tab_log', !(data && data.changeLog && data.changeLog.count));
330 }
331 // Refresh dependent blocks
332 if (data && data.reloadBlocks) {
333 reloadBlock(data.reloadBlocks.join(','));
334 }
335 });
336
337 /**
338 * Make contact summary fit in small screens
339 */
340 function onResize() {
341 var contactwidth = $('#crm-container #mainTabContainer').width();
342 if (contactwidth < 600) {
343 $('#crm-container #mainTabContainer').addClass('narrowpage');
344 $('#crm-container #mainTabContainer.narrowpage #contactTopBar td').each(function (index) {
345 if (index > 1) {
346 if (index % 2 === 0) {
347 $(this).parent().after('<tr class="narrowadded"></tr>');
348 }
349 var item = $(this);
350 $(this).parent().next().append(item);
351 }
352 });
353 }
354 else {
355 $('#crm-container #mainTabContainer.narrowpage').removeClass('narrowpage');
356 $('#crm-container #mainTabContainer #contactTopBar tr.narrowadded td').each(function () {
357 var nitem = $(this);
358 var parent = $(this).parent();
359 $(this).parent().prev().append(nitem);
360 if (parent.children().size() === 0) {
361 parent.remove();
362 }
363 });
364 $('#crm-container #mainTabContainer.narrowpage #contactTopBar tr.added').detach();
365 }
366 var cformwidth = $('#crm-container #Contact .contact_basic_information-section').width();
367
368 if (cformwidth < 720) {
369 $('#crm-container .contact_basic_information-section').addClass('narrowform');
370 $('#crm-container .contact_basic_information-section table.form-layout-compressed td .helpicon').parent().addClass('hashelpicon');
371 if (cformwidth < 480) {
372 $('#crm-container .contact_basic_information-section').addClass('xnarrowform');
373 }
374 else {
375 $('#crm-container .contact_basic_information-section.xnarrowform').removeClass('xnarrowform');
376 }
377 }
378 else {
379 $('#crm-container .contact_basic_information-section.narrowform').removeClass('narrowform');
380 $('#crm-container .contact_basic_information-section.xnarrowform').removeClass('xnarrowform');
381 }
382 }
383
384 onResize();
385 $(window).resize(onResize);
386 });
387 })(CRM.$, CRM._);