PageSourceSearch

https://theartssociety.org/sites/all/modules/civicrm/templates/CRM/common/TabHeader.js?tlvm4t

js theartssociety.org collected 2026-09-24 20:53:22 UTC 6,806 bytes, 192 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.