PageSourceSearch

https://lums.edu.pk/core/misc/dialog/dialog.ajax.js?v=10.2.12

js lums.edu.pk collected 2026-09-24 09:03:23 UTC 9,667 bytes, 294 lines download raw bytes

1/**
2 * @file
3 * Extends the Drupal AJAX functionality to integrate the dialog API.
4 */
5
6(function ($, Drupal, { focusable }) {
7  /**
8   * Initialize dialogs for Ajax purposes.
9   *
10   * @type {Drupal~behavior}
11   *
12   * @prop {Drupal~behaviorAttach} attach
13   *   Attaches the behaviors for dialog ajax functionality.
14   */
15  Drupal.behaviors.dialog = {
16    attach(context, settings) {
17      const $context = $(context);
18
19      // Provide a known 'drupal-modal' DOM element for Drupal-based modal
20      // dialogs. Non-modal dialogs are responsible for creating their own
21      // elements, since there can be multiple non-modal dialogs at a time.
22      if (!$('#drupal-modal').length) {
23        // Add 'ui-front' jQuery UI class so jQuery UI widgets like autocomplete
24        // sit on top of dialogs. For more information see
25        // http://api.jqueryui.com/theming/stacking-elements/.
26        $('<div id="drupal-modal" class="ui-front"></div>')
27          .hide()
28          .appendTo('body');
29      }
30
31      // Special behaviors specific when attaching content within a dialog.
32      // These behaviors usually fire after a validation error inside a dialog.
33      const $dialog = $context.closest('.ui-dialog-content');
34      if ($dialog.length) {
35        // Remove and replace the dialog buttons with those from the new form.
36        if ($dialog.dialog('option', 'drupalAutoButtons')) {
37          // Trigger an event to detect/sync changes to buttons.
38          $dialog.trigger('dialogButtonsChange');
39        }
40
41        setTimeout(function () {
42          // Account for pre-existing focus handling that may have already moved
43          // the focus inside the dialog.
44          if (!$dialog[0].contains(document.activeElement)) {
45            // Move focus to the first focusable element in the next event loop
46            // to allow dialog buttons to be changed first.
47            $dialog.dialog('instance')._focusedElement = null;
48            $dialog.dialog('instance')._focusTabbable();
49          }
50        }, 0);
51      }
52
53      const originalClose = settings.dialog.close;
54      // Overwrite the close method to remove the dialog on closing.
55      settings.dialog.close = function (event, ...args) {
56        originalClose.apply(settings.dialog, [event, ...args]);
57        // Check if the opener element is inside an AJAX container.
58        const $element = $(event.target);
59        const ajaxContainer = $element.data('uiDialog')
60          ? $element
61              .data('uiDialog')
62              .opener.closest('[data-drupal-ajax-container]')
63          : [];
64
65        // If the opener element was in an ajax container, and focus is on the
66        // body element, we can assume focus was lost. To recover, focus is
67        // moved to the first focusable element in the container.
68        if (
69          ajaxContainer.length &&
70          (document.activeElement === document.body ||
71            $(document.activeElement).not(':visible'))
72        ) {
73          const focusableChildren = focusable(ajaxContainer[0]);
74          if (focusableChildren.length > 0) {
75            setTimeout(() => {
76              focusableChildren[0].focus();
77            }, 0);
78          }
79        }
80
81        $(event.target).remove();
82      };
83    },
84
85    /**
86     * Scan a dialog for any primary buttons and move them to the button area.
87     *
88     * @param {jQuery} $dialog
89     *   A jQuery object containing the element that is the dialog target.
90     *
91     * @return {Array}
92     *   An array of buttons that need to be added to the button area.
93     */
94    prepareDialogButtons($dialog) {
95      const buttons = [];
96      const $buttons = $dialog.find(
97        '.form-actions input[type=submit], .form-actions a.button, .form-actions a.action-link',
98      );
99      $buttons.each(function () {
100        const $originalButton = $(this);
101        this.style.display = 'none';
102        buttons.push({
103          text: $originalButton.html() || $originalButton.attr('value'),
104          class: $originalButton.attr('class'),
105          'data-once': $originalButton.data('once'),
106          click(e) {
107            // If the original button is an anchor tag, triggering the "click"
108            // event will not simulate a click. Use the click method instead.
109            if ($originalButton[0].tagName === 'A') {
110              $originalButton[0].click();
111            } else {
112              $originalButton
113                .trigger('mousedown')
114                .trigger('mouseup')
115                .trigger('click');
116            }
117            e.preventDefault();
118          },
119        });
120      });
121      return buttons;
122    },
123  };
124
125  /**
126   * Command to open a dialog.
127   *
128   * @param {Drupal.Ajax} ajax
129   *   The Drupal Ajax object.
130   * @param {object} response
131   *   Object holding the server response.
132   * @param {number} [status]
133   *   The HTTP status code.
134   *
135   * @return {boolean|undefined}
136   *   Returns false if there was no selector property in the response object.
137   */
138  Drupal.AjaxCommands.prototype.openDialog = function (ajax, response, status) {
139    if (!response.selector) {
140      return false;
141    }
142    let $dialog = $(response.selector);
143    if (!$dialog.length) {
144      // Create the element if needed.
145      $dialog = $(
146        `<div id="${response.selector.replace(
147          /^#/,
148          '',
149        )}" class="ui-front"></div>`,
150      ).appendTo('body');
151    }
152    // Set up the wrapper, if there isn't one.
153    if (!ajax.wrapper) {
154      ajax.wrapper = $dialog.attr('id');
155    }
156
157    // Use the ajax.js insert command to populate the dialog contents.
158    response.command = 'insert';
159    response.method = 'html';
160    ajax.commands.insert(ajax, response, status);
161
162    // Move the buttons to the jQuery UI dialog buttons area.
163    response.dialogOptions = response.dialogOptions || {};
164    if (typeof response.dialogOptions.drupalAutoButtons === 'undefined') {
165      response.dialogOptions.drupalAutoButtons = true;
166    } else if (response.dialogOptions.drupalAutoButtons === 'false') {
167      response.dialogOptions.drupalAutoButtons = false;
168    } else {
169      response.dialogOptions.drupalAutoButtons =
170        !!response.dialogOptions.drupalAutoButtons;
171    }
172    if (
173      !response.dialogOptions.buttons &&
174      response.dialogOptions.drupalAutoButtons
175    ) {
176      response.dialogOptions.buttons =
177        Drupal.behaviors.dialog.prepareDialogButtons($dialog);
178    }
179
180    // Bind dialogButtonsChange.
181    $dialog.on('dialogButtonsChange', () => {
182      const buttons = Drupal.behaviors.dialog.prepareDialogButtons($dialog);
183      $dialog.dialog('option', 'buttons', buttons);
184    });
185
186    // Open the dialog itself.
187    response.dialogOptions = response.dialogOptions || {};
188    const dialog = Drupal.dialog($dialog.get(0), response.dialogOptions);
189    if (response.dialogOptions.modal) {
190      dialog.showModal();
191    } else {
192      dialog.show();
193    }
194
195    // Add the standard Drupal class for buttons for style consistency.
196    $dialog.parent().find('.ui-dialog-buttonset').addClass('form-actions');
197  };
198
199  /**
200   * Command to close a dialog.
201   *
202   * If no selector is given, it defaults to trying to close the modal.
203   *
204   * @param {Drupal.Ajax} [ajax]
205   *   The ajax object.
206   * @param {object} response
207   *   Object holding the server response.
208   * @param {string} response.selector
209   *   The selector of the dialog.
210   * @param {boolean} response.persist
211   *   Whether to persist the dialog element or not.
212   * @param {number} [status]
213   *   The HTTP status code.
214   */
215  Drupal.AjaxCommands.prototype.closeDialog = function (
216    ajax,
217    response,
218    status,
219  ) {
220    const $dialog = $(response.selector);
221    if ($dialog.length) {
222      Drupal.dialog($dialog.get(0)).close();
223      if (!response.persist) {
224        $dialog.remove();
225      }
226    }
227
228    // Unbind dialogButtonsChange.
229    $dialog.off('dialogButtonsChange');
230  };
231
232  /**
233   * Command to set a dialog property.
234   *
235   * JQuery UI specific way of setting dialog options.
236   *
237   * @param {Drupal.Ajax} [ajax]
238   *   The Drupal Ajax object.
239   * @param {object} response
240   *   Object holding the server response.
241   * @param {string} response.selector
242   *   Selector for the dialog element.
243   * @param {string} response.optionsName
244   *   Name of a key to set.
245   * @param {string} response.optionValue
246   *   Value to set.
247   * @param {number} [status]
248   *   The HTTP status code.
249   */
250  Drupal.AjaxCommands.prototype.setDialogOption = function (
251    ajax,
252    response,
253    status,
254  ) {
255    const $dialog = $(response.selector);
256    if ($dialog.length) {
257      $dialog.dialog('option', response.optionName, response.optionValue);
258    }
259  };
260
261  /**
262   * Binds a listener on dialog creation to handle the cancel link.
263   *
264   * @param {jQuery.Event} e
265   *   The event triggered.
266   * @param {Drupal.dialog~dialogDefinition} dialog
267   *   The dialog instance.
268   * @param {jQuery} $element
269   *   The jQuery collection of the dialog element.
270   * @param {object} [settings]
271   *   Dialog settings.
272   */
273  $(window).on('dialog:aftercreate', (e, dialog, $element, settings) => {
274    $element.on('click.dialog', '.dialog-cancel', (e) => {
275      dialog.close('cancel');
276      e.preventDefault();
277      e.stopPropagation();
278    });
279  });
280
281  /**
282   * Removes all 'dialog' listeners.
283   *
284   * @param {jQuery.Event} e
285   *   The event triggered.
286   * @param {Drupal.dialog~dialogDefinition} dialog
287   *   The dialog instance.
288   * @param {jQuery} $element
289   *   jQuery collection of the dialog element.
290   */
291  $(window).on('dialog:beforeclose', (e, dialog, $element) => {
292    $element.off('.dialog');
293  });
294})(jQuery, Drupal, window.tabbable);

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.