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