Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | /* |
2 | +--------------------------------------------------------------------+ | |
3 | | CiviCRM version 4.3 | | |
4 | +--------------------------------------------------------------------+ | |
5 | | Copyright CiviCRM LLC (c) 2004-2013 | | |
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 | +--------------------------------------------------------------------+ | |
0f5816a6 | 25 | */ |
6a488035 TO |
26 | |
27 | /** | |
28 | * @file: global functions for CiviCRM | |
29 | * FIXME: We are moving away from using global functions. DO NOT ADD MORE. | |
30 | * @see CRM object - the better alternative to adding global functions | |
31 | */ | |
32 | ||
33 | var CRM = CRM || {}; | |
34 | var cj = jQuery; | |
35 | ||
36 | /** | |
37 | * Short-named function for string translation, defined in global scope so it's available everywhere. | |
38 | * | |
39 | * @param $text string string for translating | |
40 | * @param $params object key:value of additional parameters | |
41 | * | |
42 | * @return string the translated string | |
43 | */ | |
44 | function ts(text, params) { | |
7553cf23 | 45 | "use strict"; |
6a488035 TO |
46 | text = CRM.strings[text] || text; |
47 | if (params && typeof(params) === 'object') { | |
48 | for (var i in params) { | |
49 | // sprintf emulation: escape % characters in the replacements to avoid conflicts | |
0f5816a6 | 50 | text = text.replace(new RegExp('%' + i, 'g'), params[i].replace(/%/g, '%-crmescaped-')); |
6a488035 TO |
51 | } |
52 | return text.replace(/%-crmescaped-/g, '%'); | |
53 | } | |
54 | return text; | |
55 | } | |
56 | ||
57 | /** | |
58 | * This function is called by default at the bottom of template files which have forms that have | |
59 | * conditionally displayed/hidden sections and elements. The PHP is responsible for generating | |
60 | * a list of 'blocks to show' and 'blocks to hide' and the template passes these parameters to | |
61 | * this function. | |
62 | * | |
63 | * @access public | |
64 | * @param showBlocks Array of element Id's to be displayed | |
65 | * @param hideBlocks Array of element Id's to be hidden | |
66 | * @param elementType Value to set display style to for showBlocks (e.g. 'block' or 'table-row' or ...) | |
67 | * @return none | |
68 | */ | |
0f5816a6 KJ |
69 | function on_load_init_blocks(showBlocks, hideBlocks, elementType) { |
70 | if (elementType == null) { | |
71 | var elementType = 'block'; | |
72 | } | |
73 | ||
74 | /* This loop is used to display the blocks whose IDs are present within the showBlocks array */ | |
75 | for (var i = 0; i < showBlocks.length; i++) { | |
76 | var myElement = document.getElementById(showBlocks[i]); | |
77 | /* getElementById returns null if element id doesn't exist in the document */ | |
78 | if (myElement != null) { | |
79 | myElement.style.display = elementType; | |
6a488035 | 80 | } |
0f5816a6 KJ |
81 | else { |
82 | alert('showBlocks array item not in .tpl = ' + showBlocks[i]); | |
83 | } | |
84 | } | |
6a488035 | 85 | |
0f5816a6 KJ |
86 | /* This loop is used to hide the blocks whose IDs are present within the hideBlocks array */ |
87 | for (var i = 0; i < hideBlocks.length; i++) { | |
88 | var myElement = document.getElementById(hideBlocks[i]); | |
89 | /* getElementById returns null if element id doesn't exist in the document */ | |
90 | if (myElement != null) { | |
91 | myElement.style.display = 'none'; | |
92 | } | |
93 | else { | |
94 | alert('showBlocks array item not in .tpl = ' + hideBlocks[i]); | |
6a488035 | 95 | } |
0f5816a6 | 96 | } |
6a488035 TO |
97 | } |
98 | ||
99 | /** | |
100 | * This function is called when we need to show or hide a related form element (target_element) | |
101 | * based on the value (trigger_value) of another form field (trigger_field). | |
102 | * | |
103 | * @access public | |
104 | * @param trigger_field_id HTML id of field whose onchange is the trigger | |
105 | * @param trigger_value List of integers - option value(s) which trigger show-element action for target_field | |
106 | * @param target_element_id HTML id of element to be shown or hidden | |
107 | * @param target_element_type Type of element to be shown or hidden ('block' or 'table-row') | |
108 | * @param field_type Type of element radio/select | |
109 | * @param invert Boolean - if true, we HIDE target on value match; if false, we SHOW target on value match | |
110 | * @return none | |
0f5816a6 KJ |
111 | */ |
112 | function showHideByValue(trigger_field_id, trigger_value, target_element_id, target_element_type, field_type, invert) { | |
113 | if (target_element_type == null) { | |
114 | var target_element_type = 'block'; | |
115 | } | |
116 | else { | |
117 | if (target_element_type == 'table-row') { | |
118 | var target_element_type = ''; | |
119 | } | |
120 | } | |
121 | ||
122 | if (field_type == 'select') { | |
123 | var trigger = trigger_value.split("|"); | |
124 | var selectedOptionValue = document.getElementById(trigger_field_id).options[document.getElementById(trigger_field_id).selectedIndex].value; | |
125 | ||
126 | var target = target_element_id.split("|"); | |
127 | for (var j = 0; j < target.length; j++) { | |
128 | if (invert) { | |
129 | cj('#' + target[j]).show(); | |
130 | } | |
131 | else { | |
132 | cj('#' + target[j]).hide(); | |
133 | } | |
134 | for (var i = 0; i < trigger.length; i++) { | |
135 | if (selectedOptionValue == trigger[i]) { | |
136 | if (invert) { | |
137 | cj('#' + target[j]).hide(); | |
138 | } | |
139 | else { | |
140 | cj('#' + target[j]).show(); | |
141 | } | |
6a488035 | 142 | } |
0f5816a6 KJ |
143 | } |
144 | } | |
6a488035 | 145 | |
0f5816a6 KJ |
146 | } |
147 | else { | |
148 | if (field_type == 'radio') { | |
149 | var target = target_element_id.split("|"); | |
150 | for (var j = 0; j < target.length; j++) { | |
151 | if (document.getElementsByName(trigger_field_id)[0].checked) { | |
152 | if (invert) { | |
153 | cj('#' + target[j]).hide(); | |
154 | } | |
155 | else { | |
156 | cj('#' + target[j]).show(); | |
157 | } | |
6a488035 | 158 | } |
0f5816a6 KJ |
159 | else { |
160 | if (invert) { | |
161 | cj('#' + target[j]).show(); | |
162 | } | |
163 | else { | |
164 | cj('#' + target[j]).hide(); | |
165 | } | |
166 | } | |
167 | } | |
6a488035 | 168 | } |
0f5816a6 | 169 | } |
6a488035 TO |
170 | } |
171 | ||
172 | /** | |
173 | * | |
174 | * Function for checking ALL or unchecking ALL check boxes in a resultset page. | |
175 | * | |
176 | * @access public | |
177 | * @param fldPrefix - common string which precedes unique checkbox ID and identifies field as | |
178 | * belonging to the resultset's checkbox collection | |
179 | * @param object - checkbox | |
180 | * Sample usage: onClick="javascript:changeCheckboxValues('chk_', cj(this) );" | |
181 | * | |
182 | * @return | |
183 | */ | |
184 | function toggleCheckboxVals(fldPrefix, object) { | |
0f5816a6 KJ |
185 | if (object.id == 'toggleSelect' && cj(object).is(':checked')) { |
186 | cj('Input[id*="' + fldPrefix + '"],Input[id*="toggleSelect"]').attr('checked', true); | |
187 | } | |
188 | else { | |
189 | cj('Input[id*="' + fldPrefix + '"],Input[id*="toggleSelect"]').attr('checked', false); | |
190 | } | |
191 | // change the class of selected rows | |
192 | on_load_init_checkboxes(object.form.name); | |
6a488035 TO |
193 | } |
194 | ||
195 | function countSelectedCheckboxes(fldPrefix, form) { | |
0f5816a6 KJ |
196 | fieldCount = 0; |
197 | for (i = 0; i < form.elements.length; i++) { | |
198 | fpLen = fldPrefix.length; | |
199 | if (form.elements[i].type == 'checkbox' && form.elements[i].name.slice(0, fpLen) == fldPrefix && form.elements[i].checked == true) { | |
200 | fieldCount++; | |
6a488035 | 201 | } |
0f5816a6 KJ |
202 | } |
203 | return fieldCount; | |
6a488035 TO |
204 | } |
205 | ||
206 | /** | |
207 | * Function to enable task action select | |
208 | */ | |
0f5816a6 KJ |
209 | function toggleTaskAction(status) { |
210 | var radio_ts = document.getElementsByName('radio_ts'); | |
211 | if (!radio_ts[1]) { | |
212 | radio_ts[0].checked = true; | |
213 | } | |
214 | if (radio_ts[0].checked || radio_ts[1].checked) { | |
215 | status = true; | |
216 | } | |
217 | ||
218 | var formElements = ['task', 'Go', 'Print']; | |
219 | for (var i = 0; i < formElements.length; i++) { | |
220 | var element = document.getElementById(formElements[i]); | |
221 | if (element) { | |
222 | if (status) { | |
223 | element.disabled = false; | |
224 | } | |
225 | else { | |
226 | element.disabled = true; | |
227 | } | |
6a488035 | 228 | } |
0f5816a6 | 229 | } |
6a488035 TO |
230 | } |
231 | ||
232 | /** | |
233 | * This function is used to check if any actio is selected and also to check if any contacts are checked. | |
234 | * | |
235 | * @access public | |
236 | * @param fldPrefix - common string which precedes unique checkbox ID and identifies field as | |
237 | * belonging to the resultset's checkbox collection | |
238 | * @param form - name of form that checkboxes are part of | |
239 | * Sample usage: onClick="javascript:checkPerformAction('chk_', myForm );" | |
240 | * | |
241 | */ | |
0f5816a6 KJ |
242 | function checkPerformAction(fldPrefix, form, taskButton, selection) { |
243 | var cnt; | |
244 | var gotTask = 0; | |
245 | ||
246 | // taskButton TRUE means we don't need to check the 'task' field - it's a button-driven task | |
247 | if (taskButton == 1) { | |
248 | gotTask = 1; | |
249 | } | |
250 | else { | |
251 | if (document.forms[form].task.selectedIndex) { | |
252 | //force user to select all search contacts, CRM-3711 | |
253 | if (document.forms[form].task.value == 13 || document.forms[form].task.value == 14) { | |
254 | var toggleSelect = document.getElementsByName('toggleSelect'); | |
255 | if (toggleSelect[0].checked || document.forms[form].radio_ts[0].checked) { | |
256 | return true; | |
6a488035 | 257 | } |
0f5816a6 KJ |
258 | else { |
259 | alert("Please select all contacts for this action.\n\nTo use the entire set of search results, click the 'all records' radio button."); | |
260 | return false; | |
261 | } | |
262 | } | |
263 | gotTask = 1; | |
6a488035 | 264 | } |
0f5816a6 | 265 | } |
6a488035 | 266 | |
0f5816a6 KJ |
267 | if (gotTask == 1) { |
268 | // If user wants to perform action on ALL records and we have a task, return (no need to check further) | |
269 | if (document.forms[form].radio_ts[0].checked) { | |
270 | return true; | |
271 | } | |
6a488035 | 272 | |
0f5816a6 KJ |
273 | cnt = (selection == 1) ? countSelections() : countSelectedCheckboxes(fldPrefix, document.forms[form]); |
274 | if (!cnt) { | |
275 | alert("Please select one or more contacts for this action.\n\nTo use the entire set of search results, click the 'all records' radio button."); | |
276 | return false; | |
6a488035 | 277 | } |
0f5816a6 KJ |
278 | } |
279 | else { | |
280 | alert("Please select an action from the drop-down menu."); | |
281 | return false; | |
282 | } | |
6a488035 TO |
283 | } |
284 | ||
285 | /** | |
286 | * This function changes the style for a checkbox block when it is selected. | |
287 | * | |
288 | * @access public | |
289 | * @param chkName - it is name of the checkbox | |
290 | * @return null | |
291 | */ | |
0f5816a6 KJ |
292 | function checkSelectedBox(chkName) { |
293 | var checkElement = cj('#' + chkName); | |
294 | if (checkElement.attr('checked')) { | |
295 | cj('input[value=ts_sel]:radio').attr('checked', true); | |
296 | checkElement.parents('tr').addClass('crm-row-selected'); | |
297 | } | |
298 | else { | |
299 | checkElement.parents('tr').removeClass('crm-row-selected'); | |
300 | } | |
6a488035 TO |
301 | } |
302 | ||
303 | /** | |
304 | * This function is to show the row with selected checkbox in different color | |
305 | * @param form - name of form that checkboxes are part of | |
306 | * | |
307 | * @access public | |
308 | * @return null | |
309 | */ | |
0f5816a6 KJ |
310 | function on_load_init_checkboxes(form) { |
311 | var formName = form; | |
312 | var fldPrefix = 'mark_x'; | |
313 | for (i = 0; i < document.forms[formName].elements.length; i++) { | |
314 | fpLen = fldPrefix.length; | |
315 | if (document.forms[formName].elements[i].type == 'checkbox' && document.forms[formName].elements[i].name.slice(0, fpLen) == fldPrefix) { | |
316 | checkSelectedBox(document.forms[formName].elements[i].name, formName); | |
6a488035 | 317 | } |
0f5816a6 | 318 | } |
6a488035 TO |
319 | } |
320 | ||
321 | /** | |
322 | * Function to change the color of the class | |
323 | * | |
324 | * @param form - name of the form | |
325 | * @param rowid - id of the <tr>, <div> you want to change | |
326 | * | |
327 | * @access public | |
328 | * @return null | |
329 | */ | |
0f5816a6 KJ |
330 | function changeRowColor(rowid, form) { |
331 | switch (document.getElementById(rowid).className) { | |
332 | case 'even-row' : | |
333 | document.getElementById(rowid).className = 'selected even-row'; | |
334 | break; | |
335 | case 'odd-row' : | |
336 | document.getElementById(rowid).className = 'selected odd-row'; | |
337 | break; | |
338 | case 'selected even-row' : | |
339 | document.getElementById(rowid).className = 'even-row'; | |
340 | break; | |
341 | case 'selected odd-row' : | |
342 | document.getElementById(rowid).className = 'odd-row'; | |
343 | break; | |
344 | case 'form-item' : | |
345 | document.getElementById(rowid).className = 'selected'; | |
346 | break; | |
347 | case 'selected' : | |
348 | document.getElementById(rowid).className = 'form-item'; | |
349 | } | |
6a488035 TO |
350 | } |
351 | ||
352 | /** | |
353 | * This function is to show the row with selected checkbox in different color | |
354 | * @param form - name of form that checkboxes are part of | |
355 | * | |
356 | * @access public | |
357 | * @return null | |
358 | */ | |
0f5816a6 KJ |
359 | function on_load_init_check(form) { |
360 | for (i = 0; i < document.forms[form].elements.length; i++) { | |
361 | if (( document.forms[form].elements[i].type == 'checkbox' | |
362 | && document.forms[form].elements[i].checked == true ) | |
363 | || ( document.forms[form].elements[i].type == 'hidden' | |
364 | && document.forms[form].elements[i].value == 1 )) { | |
365 | var ss = document.forms[form].elements[i].id; | |
366 | var row = 'rowid' + ss; | |
367 | changeRowColor(row, form); | |
6a488035 | 368 | } |
0f5816a6 | 369 | } |
6a488035 TO |
370 | } |
371 | ||
372 | /** | |
373 | * reset all the radio buttons with a given name | |
374 | * | |
375 | * @param string fieldName | |
376 | * @param object form | |
377 | * @return null | |
378 | */ | |
379 | function unselectRadio(fieldName, form) { | |
0f5816a6 KJ |
380 | for (i = 0; i < document.forms[form].elements.length; i++) { |
381 | if (document.forms[form].elements[i].name == fieldName) { | |
382 | document.forms[form].elements[i].checked = false; | |
6a488035 | 383 | } |
0f5816a6 KJ |
384 | } |
385 | return; | |
6a488035 TO |
386 | } |
387 | ||
388 | /** | |
389 | * Function to change button text and disable one it is clicked | |
390 | * | |
391 | * @param obj object - the button clicked | |
392 | * @param formID string - the id of the form being submitted | |
393 | * @param string procText - button text after user clicks it | |
394 | * @return null | |
395 | */ | |
0f5816a6 | 396 | var submitcount = 0; |
6a488035 | 397 | /* Changes button label on submit, and disables button after submit for newer browsers. |
0f5816a6 KJ |
398 | Puts up alert for older browsers. */ |
399 | function submitOnce(obj, formId, procText) { | |
400 | // if named button clicked, change text | |
401 | if (obj.value != null) { | |
402 | obj.value = procText + " ..."; | |
403 | } | |
404 | if (document.getElementById) { // disable submit button for newer browsers | |
405 | obj.disabled = true; | |
406 | document.getElementById(formId).submit(); | |
407 | return true; | |
408 | } | |
409 | else { // for older browsers | |
410 | if (submitcount == 0) { | |
411 | submitcount++; | |
412 | return true; | |
413 | } | |
414 | else { | |
415 | alert("Your request is currently being processed ... Please wait."); | |
416 | return false; | |
6a488035 | 417 | } |
0f5816a6 | 418 | } |
6a488035 TO |
419 | } |
420 | ||
421 | function popUp(URL) { | |
422 | day = new Date(); | |
0f5816a6 | 423 | id = day.getTime(); |
6a488035 TO |
424 | eval("page" + id + " = window.open(URL, '" + id + "', 'toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=0,width=640,height=420,left = 202,top = 184');"); |
425 | } | |
426 | ||
0f5816a6 KJ |
427 | function imagePopUp(path) { |
428 | window.open(path, 'popupWindow', 'toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=yes,copyhistory=no,screenX=150,screenY=150,top=150,left=150'); | |
6a488035 TO |
429 | } |
430 | ||
431 | /** | |
432 | * Function to show / hide the row in optionFields | |
433 | * | |
434 | * @param element name index, that whose innerHTML is to hide else will show the hidden row. | |
435 | */ | |
0f5816a6 KJ |
436 | function showHideRow(index) { |
437 | if (index) { | |
438 | cj('tr#optionField_' + index).hide(); | |
439 | if (cj('table#optionField tr:hidden:first').length) { | |
440 | cj('div#optionFieldLink').show(); | |
6a488035 | 441 | } |
0f5816a6 KJ |
442 | } |
443 | else { | |
444 | cj('table#optionField tr:hidden:first').show(); | |
445 | if (!cj('table#optionField tr:hidden:last').length) { | |
446 | cj('div#optionFieldLink').hide(); | |
447 | } | |
448 | } | |
449 | return false; | |
6a488035 TO |
450 | } |
451 | ||
452 | /** | |
453 | * Function to check activity status in relavent to activity date | |
454 | * | |
455 | * @param element message JSON object. | |
456 | */ | |
0f5816a6 KJ |
457 | function activityStatus(message) { |
458 | var d = new Date(), time = [], i; | |
459 | var currentDateTime = d.getTime() | |
460 | var activityTime = cj("input#activity_date_time_time").val().replace(":", ""); | |
461 | ||
462 | //chunk the time in bunch of 2 (hours,minutes,ampm) | |
463 | for (i = 0; i < activityTime.length; i += 2) { | |
464 | time.push(activityTime.slice(i, i + 2)); | |
465 | } | |
466 | var activityDate = new Date(cj("input#activity_date_time_hidden").val()); | |
6a488035 | 467 | |
0f5816a6 KJ |
468 | d.setFullYear(activityDate.getFullYear()); |
469 | d.setMonth(activityDate.getMonth()); | |
470 | d.setDate(activityDate.getDate()); | |
471 | var hours = time['0']; | |
472 | var ampm = time['2']; | |
6a488035 | 473 | |
0f5816a6 KJ |
474 | if (ampm == "PM" && hours != 0 && hours != 12) { |
475 | // force arithmetic instead of string concatenation | |
476 | hours = hours * 1 + 12; | |
477 | } | |
478 | else { | |
479 | if (ampm == "AM" && hours == 12) { | |
480 | hours = 0; | |
6a488035 | 481 | } |
0f5816a6 KJ |
482 | } |
483 | d.setHours(hours); | |
484 | d.setMinutes(time['1']); | |
6a488035 | 485 | |
0f5816a6 | 486 | var activity_date_time = d.getTime(); |
6a488035 | 487 | |
0f5816a6 | 488 | var activityStatusId = cj('#status_id').val(); |
6a488035 | 489 | |
0f5816a6 KJ |
490 | if (activityStatusId == 2 && currentDateTime < activity_date_time) { |
491 | if (!confirm(message.completed)) { | |
492 | return false; | |
493 | } | |
494 | } | |
495 | else { | |
496 | if (activity_date_time && activityStatusId == 1 && currentDateTime >= activity_date_time) { | |
497 | if (!confirm(message.scheduled)) { | |
498 | return false; | |
499 | } | |
6a488035 | 500 | } |
0f5816a6 | 501 | } |
6a488035 TO |
502 | } |
503 | ||
6a488035 TO |
504 | CRM.strings = CRM.strings || {}; |
505 | CRM.validate = CRM.validate || { | |
506 | params: {}, | |
507 | functions: [] | |
508 | }; | |
509 | ||
0f5816a6 | 510 | (function ($, undefined) { |
7553cf23 | 511 | "use strict"; |
0f5816a6 | 512 | $(document).ready(function () { |
6a488035 | 513 | $().crmtooltip(); |
0f5816a6 | 514 | $('.crm-container table.row-highlight').on('change', 'input.select-row, input.select-rows', function () { |
e24b17b9 | 515 | var target, table = $(this).closest('table'); |
6a488035 | 516 | if ($(this).hasClass('select-rows')) { |
e24b17b9 | 517 | target = $('tbody tr', table); |
6a488035 TO |
518 | $('input.select-row', table).prop('checked', $(this).prop('checked')); |
519 | } | |
520 | else { | |
e24b17b9 | 521 | target = $(this).closest('tr'); |
6a488035 TO |
522 | $('input.select-rows', table).prop('checked', $(".select-row:not(':checked')", table).length < 1); |
523 | } | |
524 | target.toggleClass('crm-row-selected', $(this).is(':checked')); | |
525 | }); | |
0f5816a6 | 526 | $('#crm-container').live('click', function (event) { |
e24b17b9 | 527 | if ($(event.target).is('.btn-slide')) { |
0f5816a6 KJ |
528 | var currentActive = $('#crm-container .btn-slide-active'); |
529 | currentActive.children().hide(); | |
530 | currentActive.removeClass('btn-slide-active'); | |
531 | $(event.target).children().show(); | |
532 | $(event.target).addClass('btn-slide-active'); | |
533 | } | |
534 | else { | |
535 | $('.btn-slide .panel').hide(); | |
536 | $('.btn-slide-active').removeClass('btn-slide-active'); | |
6a488035 TO |
537 | } |
538 | }); | |
539 | }); | |
148c4e8d CW |
540 | |
541 | /** | |
542 | * Function to make multiselect boxes behave as fields in small screens | |
543 | */ | |
544 | function advmultiselectResize() { | |
545 | var amswidth = $("#crm-container form:has(table.advmultiselect)").width(); | |
546 | if (amswidth < 700) { | |
547 | $("form table.advmultiselect td").css('display', 'block'); | |
0f5816a6 KJ |
548 | } |
549 | else { | |
148c4e8d CW |
550 | $("form table.advmultiselect td").css('display', 'table-cell'); |
551 | } | |
552 | var contactwidth = $('#crm-container #mainTabContainer').width(); | |
553 | if (contactwidth < 600) { | |
554 | $('#crm-container #mainTabContainer').addClass('narrowpage'); | |
0f5816a6 | 555 | $('#crm-container #mainTabContainer.narrowpage #contactTopBar td').each(function (index) { |
148c4e8d | 556 | if (index > 1) { |
0f5816a6 | 557 | if (index % 2 == 0) { |
148c4e8d CW |
558 | $(this).parent().after('<tr class="narrowadded"></tr>'); |
559 | } | |
560 | var item = $(this); | |
561 | $(this).parent().next().append(item); | |
562 | } | |
563 | }); | |
0f5816a6 KJ |
564 | } |
565 | else { | |
148c4e8d | 566 | $('#crm-container #mainTabContainer.narrowpage').removeClass('narrowpage'); |
0f5816a6 | 567 | $('#crm-container #mainTabContainer #contactTopBar tr.narrowadded td').each(function () { |
148c4e8d CW |
568 | var nitem = $(this); |
569 | var parent = $(this).parent(); | |
570 | $(this).parent().prev().append(nitem); | |
0f5816a6 | 571 | if (parent.children().size() == 0) { |
148c4e8d CW |
572 | parent.remove(); |
573 | } | |
574 | }); | |
575 | $('#crm-container #mainTabContainer.narrowpage #contactTopBar tr.added').detach(); | |
576 | } | |
577 | var cformwidth = $('#crm-container #Contact .contact_basic_information-section').width(); | |
0f5816a6 | 578 | |
148c4e8d CW |
579 | if (cformwidth < 720) { |
580 | $('#crm-container .contact_basic_information-section').addClass('narrowform'); | |
581 | $('#crm-container .contact_basic_information-section table.form-layout-compressed td .helpicon').parent().addClass('hashelpicon'); | |
582 | if (cformwidth < 480) { | |
583 | $('#crm-container .contact_basic_information-section').addClass('xnarrowform'); | |
0f5816a6 KJ |
584 | } |
585 | else { | |
148c4e8d CW |
586 | $('#crm-container .contact_basic_information-section.xnarrowform').removeClass('xnarrowform'); |
587 | } | |
0f5816a6 KJ |
588 | } |
589 | else { | |
148c4e8d CW |
590 | $('#crm-container .contact_basic_information-section.narrowform').removeClass('narrowform'); |
591 | $('#crm-container .contact_basic_information-section.xnarrowform').removeClass('xnarrowform'); | |
592 | } | |
593 | } | |
0f5816a6 | 594 | |
148c4e8d | 595 | advmultiselectResize(); |
0f5816a6 | 596 | $(window).resize(function () { |
6a488035 TO |
597 | advmultiselectResize(); |
598 | }); | |
599 | ||
0f5816a6 | 600 | $.fn.crmtooltip = function () { |
e24b17b9 CW |
601 | $('a.crm-summary-link:not(.crm-processed)') |
602 | .addClass('crm-processed') | |
0f5816a6 | 603 | .on('mouseover', function (e) { |
e24b17b9 CW |
604 | $(this).addClass('crm-tooltip-active'); |
605 | var topDistance = e.pageY - $(window).scrollTop(); | |
606 | if (topDistance < 300 | topDistance < $(this).children('.crm-tooltip-wrapper').height()) { | |
607 | $(this).addClass('crm-tooltip-down'); | |
608 | } | |
609 | if (!$(this).children('.crm-tooltip-wrapper').length) { | |
6a488035 TO |
610 | $(this).append('<div class="crm-tooltip-wrapper"><div class="crm-tooltip"></div></div>'); |
611 | $(this).children().children('.crm-tooltip') | |
612 | .html('<div class="crm-loading-element"></div>') | |
613 | .load(this.href); | |
614 | } | |
615 | }) | |
0f5816a6 | 616 | .on('mouseout', function () { |
e24b17b9 CW |
617 | $(this).removeClass('crm-tooltip-active crm-tooltip-down'); |
618 | }) | |
619 | .on('click', false); | |
6a488035 TO |
620 | }; |
621 | ||
622 | var h; | |
0f5816a6 | 623 | CRM.help = function (title, params) { |
6a488035 TO |
624 | h && h.close && h.close(); |
625 | var options = { | |
626 | expires: 0 | |
627 | }; | |
628 | h = CRM.alert('...', title, 'crm-help crm-msg-loading', options); | |
629 | params.class_name = 'CRM_Core_Page_Inline_Help'; | |
630 | params.type = 'page'; | |
631 | $.ajax(CRM.url('civicrm/ajax/inline'), | |
632 | { | |
633 | data: params, | |
634 | dataType: 'html', | |
e24b17b9 | 635 | success: function (data) { |
6a488035 TO |
636 | $('#crm-notification-container .crm-help .notify-content:last').html(data); |
637 | $('#crm-notification-container .crm-help').removeClass('crm-msg-loading').addClass('info'); | |
638 | }, | |
e24b17b9 | 639 | error: function () { |
6a488035 TO |
640 | $('#crm-notification-container .crm-help .notify-content:last').html('Unable to load help file.'); |
641 | $('#crm-notification-container .crm-help').removeClass('crm-msg-loading').addClass('error'); | |
642 | } | |
643 | } | |
644 | ); | |
645 | }; | |
646 | ||
647 | /** | |
648 | * @param string text Displayable message | |
649 | * @param string title Displayable title | |
650 | * @param string type 'alert'|'info'|'success'|'error' (default: 'alert') | |
651 | * @param {object} options | |
652 | * @return {*} | |
653 | * @see http://wiki.civicrm.org/confluence/display/CRM/Notifications+in+CiviCRM | |
654 | */ | |
0f5816a6 | 655 | CRM.alert = function (text, title, type, options) { |
6a488035 TO |
656 | type = type || 'alert'; |
657 | title = title || ''; | |
658 | options = options || {}; | |
659 | if ($('#crm-notification-container').length) { | |
660 | var params = { | |
661 | text: text, | |
662 | title: title, | |
663 | type: type | |
664 | }; | |
665 | // By default, don't expire errors and messages containing links | |
666 | var extra = { | |
667 | expires: (type == 'error' || text.indexOf('<a ') > -1) ? 0 : (text ? 10000 : 5000), | |
668 | unique: true | |
669 | }; | |
670 | options = $.extend(extra, options); | |
e24b17b9 | 671 | options.expires = options.expires === false ? 0 : parseInt(options.expires, 10); |
6a488035 | 672 | if (options.unique && options.unique !== '0') { |
0f5816a6 | 673 | $('#crm-notification-container .ui-notify-message').each(function () { |
6a488035 TO |
674 | if (title === $('h1', this).html() && text === $('.notify-content', this).html()) { |
675 | $('.icon.ui-notify-close', this).click(); | |
676 | } | |
677 | }); | |
678 | } | |
679 | return $('#crm-notification-container').notify('create', params, options); | |
680 | } | |
681 | else { | |
682 | if (title.length) { | |
683 | text = title + "\n" + text; | |
684 | } | |
685 | alert(text); | |
686 | return null; | |
687 | } | |
e24b17b9 | 688 | }; |
6a488035 TO |
689 | |
690 | /** | |
691 | * Close whichever alert contains the given node | |
692 | * | |
693 | * @param node | |
694 | */ | |
0f5816a6 | 695 | CRM.closeAlertByChild = function (node) { |
6a488035 | 696 | $(node).closest('.ui-notify-message').find('.icon.ui-notify-close').click(); |
e24b17b9 | 697 | }; |
6a488035 TO |
698 | |
699 | /** | |
700 | * Prompt the user for confirmation. | |
701 | * | |
7553cf23 CW |
702 | * @param buttons {object|function} key|value pairs where key == button label and value == callback function |
703 | * passing in a function instead of an object is a shortcut for a sinlgle button labeled "Continue" | |
704 | * @param options {object|void} Override defaults, keys include 'title', 'message', | |
705 | * see jQuery.dialog for full list of available params | |
6a488035 | 706 | */ |
0f5816a6 | 707 | CRM.confirm = function (buttons, options) { |
7553cf23 CW |
708 | var dialog, callbacks = {}; |
709 | var settings = { | |
710 | title: ts('Confirm Action'), | |
711 | message: ts('Are you sure you want to continue?'), | |
6a488035 TO |
712 | resizable: false, |
713 | modal: true, | |
0f5816a6 KJ |
714 | close: function () { |
715 | $(dialog).remove(); | |
716 | }, | |
7553cf23 CW |
717 | buttons: {} |
718 | }; | |
0f5816a6 KJ |
719 | settings.buttons[ts('Cancel')] = function () { |
720 | dialog.dialog('close'); | |
721 | }; | |
7553cf23 CW |
722 | options = options || {}; |
723 | $.extend(settings, options); | |
724 | if (typeof(buttons) === 'function') { | |
725 | callbacks[ts('Continue')] = buttons; | |
0f5816a6 KJ |
726 | } |
727 | else { | |
7553cf23 CW |
728 | callbacks = buttons; |
729 | } | |
0f5816a6 KJ |
730 | $.each(callbacks, function (label, callback) { |
731 | settings.buttons[label] = function () { | |
7553cf23 CW |
732 | callback.call(dialog); |
733 | dialog.dialog('close'); | |
e24b17b9 | 734 | }; |
6a488035 | 735 | }); |
7553cf23 CW |
736 | dialog = $('<div class="crm-container crm-confirm-dialog"></div>') |
737 | .html(options.message) | |
738 | .appendTo('body') | |
739 | .dialog(settings); | |
740 | return dialog; | |
e24b17b9 | 741 | }; |
6a488035 TO |
742 | |
743 | /** | |
744 | * Sets an error message | |
745 | * If called for a form item, title and removal condition will be handled automatically | |
746 | */ | |
0f5816a6 | 747 | $.fn.crmError = function (text, title, options) { |
6a488035 TO |
748 | title = title || ''; |
749 | text = text || ''; | |
750 | options = options || {}; | |
751 | ||
752 | var extra = { | |
753 | expires: 0 | |
754 | }; | |
755 | if ($(this).length) { | |
756 | if (title == '') { | |
757 | var label = $('label[for="' + $(this).attr('name') + '"], label[for="' + $(this).attr('id') + '"]').not('[generated=true]'); | |
758 | if (label.length) { | |
759 | label.addClass('crm-error'); | |
760 | var $label = label.clone(); | |
761 | if (text == '' && $('.crm-marker', $label).length > 0) { | |
762 | text = $('.crm-marker', $label).attr('title'); | |
763 | } | |
764 | $('.crm-marker', $label).remove(); | |
765 | title = $label.text(); | |
766 | } | |
767 | } | |
768 | $(this).addClass('error'); | |
769 | } | |
770 | var msg = CRM.alert(text, title, 'error', $.extend(extra, options)); | |
771 | if ($(this).length) { | |
772 | var ele = $(this); | |
0f5816a6 KJ |
773 | setTimeout(function () { |
774 | ele.one('change', function () { | |
775 | msg && msg.close && msg.close(); | |
776 | ele.removeClass('error'); | |
777 | label.removeClass('crm-error'); | |
778 | }); | |
779 | }, 1000); | |
6a488035 TO |
780 | } |
781 | return msg; | |
e24b17b9 | 782 | }; |
6a488035 TO |
783 | |
784 | // Display system alerts through js notifications | |
785 | function messagesFromMarkup() { | |
0f5816a6 | 786 | $('div.messages:visible', this).not('.help').not('.no-popup').each(function () { |
e24b17b9 | 787 | var text, title = ''; |
6a488035 TO |
788 | $(this).removeClass('status messages'); |
789 | var type = $(this).attr('class').split(' ')[0] || 'alert'; | |
790 | type = type.replace('crm-', ''); | |
791 | $('.icon', this).remove(); | |
6a488035 | 792 | if ($('.msg-text', this).length > 0) { |
e24b17b9 | 793 | text = $('.msg-text', this).html(); |
6a488035 TO |
794 | title = $('.msg-title', this).html(); |
795 | } | |
796 | else { | |
e24b17b9 | 797 | text = $(this).html(); |
6a488035 TO |
798 | } |
799 | var options = $(this).data('options') || {}; | |
800 | $(this).remove(); | |
801 | // Duplicates were already removed server-side | |
802 | options.unique = false; | |
803 | CRM.alert(text, title, type, options); | |
804 | }); | |
805 | // Handle qf form errors | |
0f5816a6 | 806 | $('form :input.error', this).one('blur', function () { |
6a488035 TO |
807 | $('.ui-notify-message.error a.ui-notify-close').click(); |
808 | $(this).removeClass('error'); | |
809 | $(this).next('span.crm-error').remove(); | |
810 | $('label[for="' + $(this).attr('name') + '"], label[for="' + $(this).attr('id') + '"]') | |
811 | .removeClass('crm-error') | |
812 | .find('.crm-error').removeClass('crm-error'); | |
813 | }); | |
814 | } | |
815 | ||
0f5816a6 | 816 | $(function () { |
ef3309b6 | 817 | if ($('#crm-notification-container').length) { |
6a488035 TO |
818 | // Initialize notifications |
819 | $('#crm-notification-container').notify(); | |
820 | messagesFromMarkup.call($('#crm-container')); | |
821 | $('#crm-container').on('crmFormLoad', '*', messagesFromMarkup); | |
822 | } | |
823 | }); | |
824 | ||
0f5816a6 | 825 | $.fn.crmAccordions = function (speed) { |
e24b17b9 | 826 | var container = $('#crm-container'); |
6a488035 TO |
827 | if (speed === undefined) { |
828 | speed = 200; | |
829 | } | |
830 | if ($(this).length > 0) { | |
e24b17b9 | 831 | container = $(this); |
6a488035 TO |
832 | } |
833 | if (container.length > 0 && !container.hasClass('crm-accordion-processed')) { | |
834 | // Allow normal clicking of links | |
835 | container.on('click', 'div.crm-accordion-header a', function (e) { | |
836 | e.stopPropagation && e.stopPropagation(); | |
837 | }); | |
838 | container.on('click', '.crm-accordion-header, .crm-collapsible .collapsible-title', function () { | |
839 | if ($(this).parent().hasClass('collapsed')) { | |
840 | $(this).next().css('display', 'none').slideDown(speed); | |
841 | } | |
842 | else { | |
843 | $(this).next().css('display', 'block').slideUp(speed); | |
844 | } | |
845 | $(this).parent().toggleClass('collapsed'); | |
846 | return false; | |
847 | }); | |
848 | container.addClass('crm-accordion-processed'); | |
e24b17b9 | 849 | } |
6a488035 | 850 | }; |
0f5816a6 KJ |
851 | $.fn.crmAccordionToggle = function (speed) { |
852 | $(this).each(function () { | |
6a488035 TO |
853 | if ($(this).hasClass('collapsed')) { |
854 | $('.crm-accordion-body', this).first().css('display', 'none').slideDown(speed); | |
855 | } | |
856 | else { | |
857 | $('.crm-accordion-body', this).first().css('display', 'block').slideUp(speed); | |
858 | } | |
859 | $(this).toggleClass('collapsed'); | |
860 | }); | |
861 | }; | |
862 | })(jQuery); |