PageSourceSearch

https://www.warresisters.org/wp-content/plugins/civicrm/civicrm/js/crm.ajax.js?r=fMxNhen_US

js warresisters.org collected 2026-09-24 09:26:41 UTC 25,553 bytes, 687 lines download raw bytes

1// https://civicrm.org/licensing
2/**
3 * @see https://docs.civicrm.org/dev/en/latest/api/interfaces/#ajax
4 * @see https://docs.civicrm.org/dev/en/latest/framework/ajax/
5 */
6(function($, CRM, _, undefined) {
7  /**
8   * @param string path
9   * @param string|object query
10   * @param string mode - optionally specify "front" or "back"
11   */
12  var tplURL;
13  CRM.url = function (path, query, mode) {
14    if (path === null) {
15      throw new Error('null passed to CRM.url');
16    }
17    if (typeof path === 'object') {
18      tplURL = path;
19      return path;
20    }
21    if (!tplURL) {
22      CRM.console('error', 'Error: CRM.url called before initialization');
23    }
24    if (!mode) {
25      mode = CRM.config && CRM.config.isFrontend ? 'front' : 'back';
26    }
27    query = query || '';
28    var url, frag, hash = '';
29    if (path.indexOf('#') > -1) {
30      hash = '#' + path.split('#')[1];
31      path = path.split('#')[0];
32    }
33    frag = path.split('?');
34    // Remove basepage as it can be changed on some CMS eg. WordPress frontend.
35    frag[0] = frag[0].replace('civicrm/', '/');
36    // Encode url path only if slashes in placeholder were also encoded
37    if (tplURL[mode].indexOf('/crmajax-placeholder-url-path') >= 0) {
38      url = tplURL[mode].replace('/crmajax-placeholder-url-path', frag[0]);
39    } else {
40      url = tplURL[mode].replace('%2Fcrmajax-placeholder-url-path', encodeURIComponent(frag[0]));
41    }
42
43    if (_.isEmpty(query)) {
44      url = url.replace(/[?&]civicrm-placeholder-url-query=1/, '');
45    } else {
46      url = url.replace('civicrm-placeholder-url-query=1', typeof query === 'string' ? query : $.param(query));
47    }
48    if (frag[1]) {
49      url += (url.indexOf('?') < 0 ? '?' : '&') + frag[1];
50    }
51    return url + hash;
52  };
53
54  $.fn.crmURL = function () {
55    return this.each(function() {
56      if (this.href) {
57        this.href = CRM.url(this.href);
58      }
59    });
60  };
61
62  // result is an array, but in js, an array is also an object
63  // Assign all the metadata properties to it, mirroring the results arrayObject in php
64  function arrayObject(data) {
65    const result = data?.values || [];
66    if (Array.isArray(result) && data?.constructor === Object) {
67      Object.keys(data).forEach(key => {
68        if (key !== 'values') {
69          result[key] = data[key];
70        }
71      });
72    }
73    return result;
74  }
75
76  // https://docs.civicrm.org/dev/en/latest/api/interfaces/#ajax
77  CRM.api4 = function(entity, action, params, index) {
78    return new Promise(function(resolve, reject) {
79      if (typeof entity === 'string') {
80        $.post(CRM.url('civicrm/ajax/api4/' + entity + '/' + action), {
81          params: JSON.stringify(params),
82          index: index
83        })
84          .done(function (data) {
85            resolve(arrayObject(data));
86          })
87          .fail(function (data) {
88            reject(data.responseJSON);
89          });
90      } else {
91        $.post(CRM.url('civicrm/ajax/api4'), {
92          calls: JSON.stringify(entity)
93        })
94          .done(function(data) {
95            _.each(data, function(item, key) {
96              data[key] = arrayObject(item);
97            });
98            resolve(data);
99          })
100          .fail(function (data) {
101            reject(data.responseJSON);
102          });
103      }
104    });
105  };
106
107  /**
108   * AJAX api
109   * @link https://docs.civicrm.org/dev/en/latest/api/interfaces/#ajax
110   */
111  CRM.api3 = function(entity, action, params, status) {
112    if (typeof(entity) === 'string') {
113      params = {
114        entity: entity,
115        action: action.toLowerCase(),
116        json: JSON.stringify(params || {})
117      };
118    } else {
119      params = {
120        entity: 'api3',
121        action: 'call',
122        json: JSON.stringify(entity)
123      };
124      status = action;
125    }
126    var ajax = $.ajax({
127      url: CRM.url('civicrm/ajax/rest'),
128      dataType: 'json',
129      data: params,
130      type: params.action.indexOf('get') === 0 ? 'GET' : 'POST'
131    });
132    if (status) {
133      // Default status messages
134      if (status === true) {
135        status = {success: params.action === 'delete' ? ts('Removed') : ts('Saved')};
136        if (params.action.indexOf('get') === 0) {
137          status.start = ts('Loading...');
138          status.success = null;
139        }
140      }
141      var messages = status === true ? {} : status;
142      CRM.status(status, ajax);
143    }
144    return ajax;
145  };
146
147  /**
148   * @deprecated
149   * AJAX api
150   */
151  CRM.api = function(entity, action, params, options) {
152    // Default settings
153    var settings = {
154      context: null,
155      success: function(result, settings) {
156        return true;
157      },
158      error: function(result, settings) {
159        $().crmError(result.error_message, ts('Error'));
160        return false;
161      },
162      callBack: function(result, settings) {
163        if (result.is_error == 1) {
164          return settings.error.call(this, result, settings);
165        }
166        return settings.success.call(this, result, settings);
167      },
168      ajaxURL: 'civicrm/ajax/rest'
169    };
170    action = action.toLowerCase();
171    // Default success handler
172    switch (action) {
173      case "update":
174      case "create":
175      case "setvalue":
176      case "replace":
177        settings.success = function() {
178          CRM.status(ts('Saved'));
179          return true;
180        };
181        break;
182      case "delete":
183        settings.success = function() {
184          CRM.status(ts('Removed'));
185          return true;
186        };
187    }
188    params = {
189      entity: entity,
190      action: action,
191      json: JSON.stringify(params)
192    };
193    // Pass copy of settings into closure to preserve its value during multiple requests
194    (function(stg) {
195      $.ajax({
196        url: stg.ajaxURL.indexOf('http') === 0 ? stg.ajaxURL : CRM.url(stg.ajaxURL),
197        dataType: 'json',
198        data: params,
199        type: action.indexOf('get') < 0 ? 'POST' : 'GET',
200        success: function(result) {
201          stg.callBack.call(stg.context, result, stg);
202        }
203      });
204    })($.extend({}, settings, options));
205  };
206
207  $.widget('civi.crmSnippet', {
208    options: {
209      url: null,
210      block: true,
211      post: null,
212      crmForm: null
213    },
214    _originalContent: null,
215    _originalUrl: null,
216    isOriginalUrl: function() {
217      var
218        args = {},
219        same = true,
220        newUrl = this._formatUrl(this.options.url),
221        oldUrl = this._formatUrl(this._originalUrl);
222      // Compare path
223      if (newUrl.split('?')[0] !== oldUrl.split('?')[0]) {
224        return false;
225      }
226      // Compare arguments
227      $.each((newUrl.split('?')[1] || '').split('&'), function(k, v) {
228        var arg = v.split('=');
229        args[arg[0]] = arg[1];
230      });
231      $.each((oldUrl.split('?')[1] || '').split('&'), function(k, v) {
232        var arg = v.split('=');
233        if (args[arg[0]] !== undefined && arg[1] !== args[arg[0]]) {
234          same = false;
235        }
236      });
237      return same;
238    },
239    resetUrl: function() {
240      this.options.url = this._originalUrl;
241    },
242    _create: function() {
243      this.element.addClass('crm-ajax-container');
244      if (!this.element.is('.crm-container *')) {
245        this.element.addClass('crm-container');
246      }
247      this._handleOrderLinks();
248      // Set default if not supplied
249      this.options.url = this.options.url || document.location.href;
250      this._originalUrl = this.options.url;
251    },
252    _onFailure: function(data, status) {
253      var msg, title = ts('Network Error');
254      if (this.options.block) this.element.unblock();
255      this.element.trigger('crmAjaxFail', data);
256      switch (status) {
257        case 'Forbidden':
258          title = ts('Access Denied');
259          msg = ts('Ensure you are still logged in and have permission to access this feature.');
260          break;
261        default:
262          msg = ts('Unable to reach the server. Please refresh this page in your browser and try again.');
263      }
264      CRM.alert(msg, title, 'error');
265    },
266    _onError: function(data) {
267      this.element.attr('data-unsaved-changes', 'false').trigger('crmAjaxError', data);
268      if (this.options.crmForm && this.options.crmForm.autoClose && this.element.data('uiDialog')) {
269        this.element.dialog('close');
270      }
271    },
272    _formatUrl: function(url, snippetType) {
273      // Strip hash
274      url = url.split('#')[0];
275      // Add snippet argument to url
276      if (snippetType) {
277        if (url.search(/[&?]snippet=/) < 0) {
278          url += (url.indexOf('?') < 0 ? '?' : '&') + 'snippet=' + snippetType;
279        } else {
280          url = url.replace(/([&?])snippet=[^&]*/, '$1snippet=' + snippetType);
281        }
282        // See Civi\Angular\AngularLoader
283        if (snippetType === 'json' && CRM.angular) {
284          url += '&crmAngularModules=' + CRM.angular.modules.join();
285        }
286      }
287      return url;
288    },
289    // Hack to deal with civicrm legacy sort functionality
290    _handleOrderLinks: function() {
291      var that = this;
292      $('a.crm-weight-arrow', that.element).click(function(e) {
293        if (that.options.block) that.element.block();
294        $.getJSON(that._formatUrl(this.href, 'json')).done(function() {
295          that.refresh();
296        });
297        e.stopImmediatePropagation();
298        return false;
299      });
300    },
301    _ajax: function(url) {
302      if (!this.options.post || !this.isOriginalUrl()) {
303        return $.getJSON(url);
304      }
305      return $.post({
306        url: url,
307        dataType: 'json',
308        data: this.options.post
309      });
310    },
311    refresh: function() {
312      var that = this,
313        hash = this.options.url.split('#')[1],
314        url = this._formatUrl(this.options.url, 'json');
315      $(this.element).data('urlHash', hash);
316      if (this.options.crmForm) $('form', this.element).ajaxFormUnbind();
317      if (this.options.block) this.element.block();
318      this._ajax(url).then(function(data) {
319        if (data.status === 'redirect') {
320          that.options.url = data.userContext;
321          return that.refresh();
322        }
323        if (that.options.block) that.element.unblock();
324        if (!$.isPlainObject(data)) {
325          that._onFailure(data);
326          return;
327        }
328        if (data.status === 'error') {
329          that._onError(data);
330          return;
331        }
332        if (data.settings) {
333          $.extend(true, CRM, data.settings);
334        }
335        if (data.scriptUrls) {
336          data.scriptUrls.forEach(function(scriptUrl) {
337            if ($('script[src="' + scriptUrl + '"]').length === 0) {
338              $('<script type="text/javascript" src="' + scriptUrl + '"></script>').appendTo('head');
339            }
340          });
341        }
342        if (data.styleUrls) {
343          data.styleUrls.forEach(function(styleUrl) {
344            if ($('link[href="' + styleUrl + '"]').length === 0) {
345              $('<link rel="stylesheet" href="' + styleUrl + '">').appendTo('head');
346            }
347          });
348        }
349        data.url = url;
350        that.element.trigger('crmUnload').trigger('crmBeforeLoad', data);
351        that._beforeRemovingContent();
352        that.element.html(data.content);
353        that._handleOrderLinks();
354        that.element.trigger('crmLoad', data);
355        if (that.options.crmForm) that.element.trigger('crmFormLoad', data);
356        // This is only needed by forms that load via ajax but submit without ajax, e.g. configure contribution page tabs
357        // TODO: remove this when those forms have been converted to use ajax submit
358        if (data.status === 'form_error' && $.isPlainObject(data.errors)) {
359          that.element.trigger('crmFormError', data);
360          $.each(data.errors, function(formElement, msg) {
361            $('[name="'+formElement+'"]', that.element).crmError(msg);
362          });
363        }
364      }, function(data, msg, status) {
365        that._onFailure(data, status);
366      });
367    },
368    // Perform any cleanup needed before removing/replacing content
369    _beforeRemovingContent: function() {
370      var that = this;
371      // Save original content to be restored if widget is destroyed
372      if (this._originalContent === null) {
373        $('.blockUI', this.element).remove();
374        this._originalContent = this.element.contents().detach();
375      }
376      if (this.options.crmForm) $('form', this.element).ajaxFormUnbind();
377    },
378    _destroy: function() {
379      this.element.removeClass('crm-ajax-container').trigger('crmUnload');
380      this._beforeRemovingContent();
381      if (this._originalContent !== null) {
382        this.element.empty().append(this._originalContent);
383      }
384    }
385  });
386
387  var dialogCount = 0,
388    exclude = '[href^="#"], [href^=javascript], [onclick], .no-popup, .cancel';
389
390  CRM.loadPage = function(url, options) {
391    var settings = {
392      target: '#crm-ajax-dialog-' + (dialogCount++),
393      dialog: (options && options.target) ? false : {}
394    };
395    if (options) $.extend(true, settings, options);
396    settings.url = url;
397    // Create new dialog
398    if (settings.dialog) {
399      settings.dialog = CRM.utils.adjustDialogDefaults(settings.dialog);
400      $('<div id="' + settings.target.substring(1) + '"></div>')
401        .dialog(settings.dialog)
402        .parent().find('.ui-dialog-titlebar')
403        .append($('<a class="crm-dialog-titlebar-print ui-dialog-titlebar-close" title="'+ts('Print window')+'" target="_blank" style="right:3.8em;"/>')
404          .button({icons: {primary: 'fa-print'}, text: false}));
405    }
406    // Add handlers to new or existing dialog
407    if ($(settings.target).data('uiDialog')) {
408      $(settings.target)
409        .on('dialogclose', function() {
410          if (settings.dialog && $(this).attr('data-unsaved-changes') !== 'true') {
411            $(this).crmSnippet('destroy').dialog('destroy').remove();
412          }
413        })
414        .on('crmLoad', function(e, data) {
415          // Set title
416          if (e.target === $(settings.target)[0] && data && !settings.dialog.title && data.title) {
417            $(this).dialog('option', 'title', data.title);
418          }
419          // Update print url
420          $(this).parent().find('a.crm-dialog-titlebar-print').attr('href', $(this).data('civiCrmSnippet')._formatUrl($(this).crmSnippet('option', 'url'), '1'));
421        });
422    }
423    $(settings.target).crmSnippet(settings).crmSnippet('refresh');
424    return $(settings.target);
425  };
426  CRM.loadForm = function(url, options) {
427    var formErrors = [], settings = {
428      crmForm: {
429        ajaxForm: {},
430        autoClose: true,
431        validate: true,
432        refreshAction: ['next_new', 'upload_new'],
433        cancelButton: '.cancel',
434        openInline: 'a.open-inline, a.button, a.action-item, a.open-inline-noreturn',
435        onCancel: function(event) {}
436      }
437    };
438    // Move options that belong to crmForm. Others will be passed through to crmSnippet
439    if (options) $.each(options, function(key, value) {
440      if (typeof(settings.crmForm[key]) !== 'undefined') {
441        settings.crmForm[key] = value;
442      }
443      else {
444        settings[key] = value;
445      }
446    });
447
448    var widget = CRM.loadPage(url, settings).off('.crmForm');
449
450    // CRM-14353 - Warn of unsaved changes for all forms except those which have opted out
451    function cancelAction() {
452      var dirty = CRM.utils.initialValueChanged($('form:not([data-warn-changes=false])', widget));
453      widget.attr('data-unsaved-changes', dirty ? 'true' : 'false');
454      if (dirty) {
455        var id = widget.attr('id') + '-unsaved-alert',
456          title = widget.dialog('option', 'title'),
457          alert = CRM.alert('<p>' + ts('%1 has not been saved.', {1: title}) + '</p><p><a href="#" id="' + id + '">' + ts('Restore') + '</a></p>', ts('Unsaved Changes'), 'alert unsaved-dialog', {expires: 60000});
458        $('#' + id).button({icons: {primary: 'fa-undo'}}).click(function(e) {
459          widget.attr('data-unsaved-changes', 'false').dialog('open');
460          e.preventDefault();
461        });
462      }
463    }
464
465    if (widget.data('uiDialog')) widget.on('dialogbeforeclose', function(e) {
466      // CRM-14353 - Warn unsaved changes if user clicks close button or presses "esc"
467      if (e.originalEvent) {
468        cancelAction();
469      }
470    });
471
472    widget.on('crmFormLoad.crmForm', function(event, data) {
473      var $el = $(this).attr('data-unsaved-changes', 'false'),
474        settings = $el.crmSnippet('option', 'crmForm');
475      if (settings.cancelButton) $(settings.cancelButton, this).click(function(e) {
476        e.preventDefault();
477        var returnVal = settings.onCancel.call($el, e);
478        if (returnVal !== false) {
479          $el.trigger('crmFormCancel', e);
480          if ($el.data('uiDialog') && settings.autoClose) {
481            cancelAction();
482            $el.dialog('close');
483          }
484          else if (!settings.autoClose) {
485            $el.crmSnippet('resetUrl').crmSnippet('refresh');
486          }
487        }
488      });
489      if (settings.validate) {
490        // Validate all forms that are not angular-based
491        $("form", this).not('crm-angular-js *').crmValidate();
492      }
493      $("form:not('[data-no-ajax-submit=true]')", this).ajaxForm($.extend({
494        url: data.url.replace(/reset=1[&]?/, ''),
495        dataType: 'json',
496        success: function(response) {
497          if (response.content === undefined) {
498            $el.trigger('crmFormSuccess', response);
499            // Reset form for e.g. "save and new"
500            if (response.userContext && (response.status === 'redirect' || (settings.refreshAction && $.inArray(response.buttonName, settings.refreshAction) >= 0))) {
501              // Force reset of original url
502              $el.data('civiCrmSnippet')._originalUrl = response.userContext;
503              $el.crmSnippet('resetUrl').crmSnippet('refresh');
504            }
505            // Close if we are on the original url or the action was "delete" (in which case returning to view may be inappropriate)
506            else if ($el.data('uiDialog') && (settings.autoClose || response.action === 8)) {
507              $el.dialog('close');
508            }
509            else if (settings.autoClose === false) {
510              $el.crmSnippet('resetUrl').crmSnippet('refresh');
511            }
512          }
513          else {
514            if ($el.crmSnippet('option', 'block')) $el.unblock();
515            response.url = data.url;
516            $el.html(response.content).trigger('crmLoad', response).trigger('crmFormLoad', response);
517            if (response.status === 'form_error') {
518              formErrors = [];
519              $el.trigger('crmFormError', response);
520              $.each(response.errors || [], function(formElement, msg) {
521                formErrors.push($('[name="'+formElement+'"]', $el).crmError(msg));
522              });
523            }
524          }
525        },
526        beforeSubmit: function(submission) {
527          $.each(formErrors, function() {
528            if (this && this.close) this.close();
529          });
530          if ($el.crmSnippet('option', 'block')) $el.block();
531          $el.trigger('crmFormSubmit', submission);
532        }
533      }, settings.ajaxForm));
534      if (settings.openInline) {
535        settings.autoClose = $el.crmSnippet('isOriginalUrl');
536        $(this).off('.openInline').on('click.openInline', settings.openInline, function(e) {
537          if ($(this).is(exclude + ', .crm-popup, [target=crm-popup]')) {
538            return;
539          }
540          if ($(this).hasClass('open-inline-noreturn')) {
541            // Force reset of original url
542            $el.data('civiCrmSnippet')._originalUrl = $(this).attr('href');
543          }
544          $el.crmSnippet('option', 'url', $(this).attr('href')).crmSnippet('refresh');
545          e.preventDefault();
546        });
547      }
548      if ($el.data('uiDialog')) {
549        // Show form buttons as part of the dialog
550        var buttonContainers = '.crm-submit-buttons, .action-link',
551          buttons = [],
552          added = [];
553        $(buttonContainers, $el).find('.crm-form-submit, .crm-form-xbutton, a.button, button').each(function() {
554          var $el = $(this),
555            label = $el.is('input') ? $el.attr('value') : $el.text(),
556            identifier = $el.attr('name') || $el.attr('href');
557          $el.attr('tabindex', '-1');
558          if (!identifier || identifier === '#' || $.inArray(identifier, added) < 0) {
559            var $icon = $el.find('.icon, .crm-i'),
560              button = {'data-identifier': identifier, text: label, click: function() {
561                $el[0].click();
562              }};
563            if ($icon.length) {
564              button.icons = {primary: $icon.attr('class')};
565            } else {
566              var action = $el.attr('crm-icon') || ($el.hasClass('cancel') ? 'fa-times' : 'fa-check');
567              button.icons = {primary: action};
568            }
569            buttons.push(button);
570            added.push(identifier);
571          }
572          // display:none causes the form to not submit when pressing "enter"
573          $el.parents(buttonContainers).css({height: 0, padding: 0, margin: 0, overflow: 'hidden'}).attr('aria-hidden', 'true');
574        });
575        $el.dialog('option', 'buttons', buttons);
576      }
577      // Allow a button to prevent ajax submit
578      $('input[data-no-ajax-submit=true], button[data-no-ajax-submit=true]').click(function() {
579        $(this).closest('form').ajaxFormUnbind();
580      });
581      // For convenience, focus the first field
582      $('input[type=text], textarea, select', this).filter(':visible').first().not('.dateplugin').focus();
583    });
584    return widget;
585  };
586  /**
587   * Handler for jQuery click event e.g. $('a').click(CRM.popup);
588   */
589  CRM.popup = function(e) {
590    var $el = $(this).first(),
591      url = $el.attr('href'),
592      popup = $el.data('popup-type') === 'page' ? CRM.loadPage : CRM.loadForm,
593      settings = $el.data('popup-settings') || {},
594      formData = false;
595    settings.dialog = settings.dialog || {};
596    if (e.isDefaultPrevented() || !CRM.config.ajaxPopupsEnabled || !url || $el.is(exclude + ', .open-inline, .open-inline-noreturn')) {
597      return;
598    }
599    // Sized based on css class
600    if ($el.hasClass('small-popup')) {
601      settings.dialog.width = 400;
602      settings.dialog.height = 300;
603    }
604    else if ($el.hasClass('medium-popup')) {
605      settings.dialog.width = '50%';
606      settings.dialog.height = '30%';
607    }
608    var dialog = popup(url, settings);
609    // Trigger events from the dialog on the original link element
610    $el.trigger('crmPopupOpen', [dialog]);
611    // Listen for success events and buffer them so we only trigger once
612    dialog.on('crmFormSuccess.crmPopup crmPopupFormSuccess.crmPopup', function(e, data) {
613      formData = data;
614    });
615    dialog.on('dialogclose.crmPopup', function(e, data) {
616      if (formData) {
617        $el.trigger('crmPopupFormSuccess', [dialog, formData]);
618      }
619      $el.trigger('crmPopupClose', [dialog, data]);
620    });
621    e.preventDefault();
622  };
623  /**
624   * An event callback for CRM.popup or a standalone function to refresh the content around a given element
625   * @param e {event|selector}
626   */
627  CRM.refreshParent = function(e) {
628    // Use e.target if input smells like an event, otherwise assume it's a jQuery selector
629    var $el = (e.stopPropagation && e.target) ? $(e.target) : $(e),
630      $table = $el.closest('.dataTable');
631    // Call native refresh method on ajax datatables
632    if ($table.length && $.fn.DataTable.fnIsDataTable($table[0]) && $table.dataTable().fnSettings().sAjaxSource) {
633      // Refresh ALL datatables - needed for contact relationship tab
634      $.each($.fn.dataTable.fnTables(), function() {
635        if ($(this).dataTable().fnSettings().sAjaxSource) $(this).unblock().dataTable().fnDraw();
636      });
637    }
638    // Otherwise refresh the nearest crmSnippet
639    else {
640      $el.closest('.crm-ajax-container, #crm-main-content-wrapper').crmSnippet().crmSnippet('refresh');
641    }
642  };
643
644  $(function($) {
645    $('body')
646      .on('click', 'a.crm-popup, a[target=crm-popup]', CRM.popup)
647      // Close unsaved dialog messages
648      .on('dialogopen', function(e) {
649        $('.alert.unsaved-dialog .ui-notify-cross', '#crm-notification-container').click();
650      })
651      // Destroy old unsaved dialog
652      .on('dialogcreate', function(e) {
653        $('.ui-dialog-content.crm-ajax-container:hidden[data-unsaved-changes=true]').crmSnippet('destroy').dialog('destroy').remove();
654      })
655      // Ensure wysiwyg content is updated prior to ajax submit
656      .on('form-pre-serialize', function(e) {
657        $('.crm-wysiwyg-enabled', e.target).each(function() {
658          CRM.wysiwyg.updateElement(this);
659        });
660      })
661      // Auto-resize dialogs when loading content
662      .on('crmLoad dialogopen', 'div.ui-dialog.ui-resizable.crm-container', function(e) {
663        var
664          $wrapper = $(this),
665          $dialog = $wrapper.children('.ui-dialog-content');
666        // small delay to allow contents to render
667        window.setTimeout(function() {
668          var currentHeight = $wrapper.outerHeight(),
669            padding = currentHeight - $dialog.height(),
670            newHeight = $dialog.prop('scrollHeight') + padding,
671            menuHeight = $('#civicrm-menu').outerHeight();
672          if ($('body').hasClass('crm-menubar-below-cms-menu')) {
673            menuHeight += $('#civicrm-menu').offset().top;
674          }
675          var maxHeight = $(window).height() - menuHeight;
676          newHeight = newHeight > maxHeight ? maxHeight : newHeight;
677          if (newHeight > (currentHeight + 15)) {
678            $dialog.dialog('option', {
679              position: {my: 'center', at: 'center center+' + (menuHe
679ight / 2), of: window},
680              height: newHeight
681            });
682          }
683        }, 500);
684      });
685  });
686
687}(jQuery, 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.