| 1 | // https://civicrm.org/licensing |
| 2 | /** |
| 3 | * By default this simply loads tabs via ajax CRM.loadPage method |
| 4 | * Tabs with class 'ajaxForm' will use CRM.loadForm instead, suitable for most forms |
| 5 | * Tabs with class 'livePage' will get popup action links, suitable for crud tables |
| 6 | */ |
| 7 | CRM.$(function($) { |
| 8 | var tabSettings = CRM.tabSettings || {}; |
| 9 | tabSettings.active = tabSettings.active ? $('#tab_' + tabSettings.active).prevAll().length : 0; |
| 10 | $("#mainTabContainer") |
| 11 | .on('tabsbeforeactivate', function(e, ui) { |
| 12 | // CRM-14353 - Warn of unsaved changes for all forms except those which have opted out |
| 13 | if (CRM.utils.initialValueChanged($('form:not([data-warn-changes=false])', ui.oldPanel))) { |
| 14 | CRM.alert(ts('Your changes in the <em>%1</em> tab have not been saved.', {1: ui.oldTab.text()}), ts('Unsaved Changes'), 'warning'); |
| 15 | } |
| 16 | }) |
| 17 | .on('tabsbeforeload', function(e, ui) { |
| 18 | // Use civicrm ajax wrappers rather than the default $.load |
| 19 | if (!ui.panel.data("civiCrmSnippet")) { |
| 20 | var method = ui.tab.hasClass('ajaxForm') ? 'loadForm' : 'loadPage'; |
| 21 | var params = {target: ui.panel}; |
| 22 | if (method === 'loadForm') { |
| 23 | params.autoClose = params.openInline = params.cancelButton = params.refreshAction = false; |
| 24 | ui.panel.on('crmFormLoad', function() { |
| 25 | // Hack: "Save and done" and "Cancel" buttons submit without ajax |
| 26 | $('.cancel.crm-form-submit, input[name$=upload_done]', this).on('click', function(e) { |
| 27 | $(this).closest('form').ajaxFormUnbind(); |
| 28 | }); |
| 29 | }); |
| 30 | } |
| 31 | if (ui.tab.hasClass('livePage') && CRM.config.ajaxPopupsEnabled) { |
| 32 | ui.panel |
| 33 | .off('click.crmLivePage') |
| 34 | .on('click.crmLivePage', 'a.button, a.action-item', CRM.popup) |
| 35 | .on('crmPopupFormSuccess.crmLivePage', 'a.button, a.action-item:not(.crm-enable-disable)', CRM.refreshParent); |
| 36 | } |
| 37 | ui.panel |
| 38 | .off('.tabInfo') |
| 39 | .on('crmLoad.tabInfo crmFormSuccess.tabInfo', function(e, data) { |
| 40 | if (data) { |
| 41 | if (typeof(data.tabCount) !== 'undefined') { |
| 42 | CRM.tabHeader.updateCount(ui.tab, data.tabCount); |
| 43 | } |
| 44 | if (typeof(data.tabValid) !== 'undefined') { |
| 45 | var method = data.tabValid ? 'removeClass' : 'addClass'; |
| 46 | ui.tab[method]('disabled'); |
| 47 | } |
| 48 | } |
| 49 | }); |
| 50 | CRM[method]($('a', ui.tab).attr('href'), params); |
| 51 | } |
| 52 | e.preventDefault(); |
| 53 | }) |
| 54 | .tabs(tabSettings); |
| 55 | // Any load/submit event could potentially call for tabs to refresh. |
| 56 | $(document).on('crmLoad.tabInfo crmFormSuccess.tabInfo', function(e, data) { |
| 57 | if (data && $.isPlainObject(data.updateTabs)) { |
| 58 | $.each(data.updateTabs, CRM.tabHeader.updateCount); |
| 59 | $.each(data.updateTabs, CRM.tabHeader.resetTab); |
| 60 | } |
| 61 | }); |
| 62 | }); |
| 63 | (function($) { |
| 64 | // Utility functions |
| 65 | CRM.tabHeader = CRM.tabHeader || {}; |
| 66 | |
| 67 | /** |
| 68 | * Return active tab |
| 69 | */ |
| 70 | CRM.tabHeader.getActiveTab = function() { |
| 71 | return $('.ui-tabs-active', '#mainTabContainer'); |
| 72 | }; |
| 73 | |
| 74 | /** |
| 75 | * Make a given tab the active one |
| 76 | * @param tab jQuery selector |
| 77 | */ |
| 78 | CRM.tabHeader.focus = function(tab) { |
| 79 | $('#mainTabContainer').tabs('option', 'active', $(tab).prevAll().length); |
| 80 | }; |
| 81 | |
| 82 | /** |
| 83 | * @param tab jQuery selector |
| 84 | * @returns panel jQuery object |
| 85 | */ |
| 86 | CRM.tabHeader.getTabPanel = function(tab) { |
| 87 | var selector = $(tab).attr('aria-controls'); |
| 88 | return selector ? $('#' + selector) : $(); |
| 89 | }; |
| 90 | |
| 91 | /** |
| 92 | * @param tab jQuery selector |
| 93 | * @returns {string|null} |
| 94 | */ |
| 95 | function getCountClass(tab) { |
| 96 | var $tab = $(tab), |
| 97 | css = $tab.attr('class') || '', |
| 98 | val = css.match(/(crm-count-\d+)/); |
| 99 | return val && val.length ? val[0] : null; |
| 100 | } |
| 101 | |
| 102 | /** |
| 103 | * @param tab jQuery selector |
| 104 | * @returns {Number|null} |
| 105 | */ |
| 106 | CRM.tabHeader.getCount = function(tab) { |
| 107 | var cssClass = getCountClass(tab); |
| 108 | return cssClass ? parseInt(cssClass.slice(10), 10) : null; |
| 109 | }; |
| 110 | |
| 111 | /** |
| 112 | * Update the counter in a tab |
| 113 | * @param tab jQuery selector |
| 114 | * @param count {Number} |
| 115 | */ |
| 116 | CRM.tabHeader.updateCount = function(tab, count) { |
| 117 | var oldClass = getCountClass(tab); |
| 118 | if (oldClass) { |
| 119 | $(tab).removeClass(oldClass); |
| 120 | } |
| 121 | $(tab) |
| 122 | .addClass('crm-count-' + count) |
| 123 | .find('a em').html('' + count); |
| 124 | }; |
| 125 | |
| 126 | /** |
| 127 | * Refresh tab immediately if it is active (or force=true) |
| 128 | * otherwise ensure it will be refreshed next time the user clicks on it |
| 129 | * |
| 130 | * @param tab |
| 131 | * @param force |
| 132 | */ |
| 133 | CRM.tabHeader.resetTab = function(tab, force) { |
| 134 | var $panel = CRM.tabHeader.getTabPanel(tab); |
| 135 | if ($(tab).hasClass('ui-tabs-active')) { |
| 136 | $panel.crmSnippet('refresh'); |
| 137 | } |
| 138 | else if (force) { |
| 139 | if ($panel.data("civiCrmSnippet")) { |
| 140 | $panel.crmSnippet('refresh'); |
| 141 | } else { |
| 142 | $("#mainTabContainer").trigger('tabsbeforeload', [{panel: $panel, tab: $(tab)}]); |
| 143 | } |
| 144 | } |
| 145 | else if ($panel.data("civiCrmSnippet")) { |
| 146 | $panel.crmSnippet('destroy'); |
| 147 | } |
| 148 | }; |
| 149 | })(CRM.$); |