PageSourceSearch

https://lycee-louise-michel.fr/wp-content/plugins/h5p/h5p-php-library/js/h5p-confirmation-dialog.js?ver=1.15.0

js lycee-louise-michel.fr collected 2026-10-07 17:38:10 UTC 12,149 bytes, 410 lines download raw bytes

1/*global H5P*/
2H5P.ConfirmationDialog = (function (EventDispatcher) {
3  "use strict";
4
5  /**
6   * Create a confirmation dialog
7   *
8   * @param [options] Options for confirmation dialog
9   * @param [options.instance] Instance that uses confirmation dialog
10   * @param [options.headerText] Header text
11   * @param [options.dialogText] Dialog text
12   * @param [options.cancelText] Cancel dialog button text
13   * @param [options.confirmText] Confirm dialog button text
14   * @param [options.hideCancel] Hide cancel button
15   * @param [options.hideExit] Hide exit button
16   * @param [options.skipRestoreFocus] Skip restoring focus when hiding the dialog
17   * @param [options.classes] Extra classes for popup
18   * @constructor
19   */
20  function ConfirmationDialog(options) {
21    EventDispatcher.call(this);
22    var self = this;
23
24    // Make sure confirmation dialogs have unique id
25    H5P.ConfirmationDialog.uniqueId += 1;
26    var uniqueId = H5P.ConfirmationDialog.uniqueId;
27
28    // Default options
29    options = options || {};
30    options.headerText = options.headerText || H5P.t('confirmDialogHeader');
31    options.dialogText = options.dialogText || H5P.t('confirmDialogBody');
32    options.cancelText = options.cancelText || H5P.t('cancelLabel');
33    options.confirmText = options.confirmText || H5P.t('confirmLabel');
34
35    /**
36     * Handle confirming event
37     * @param {Event} e
38     */
39    function dialogConfirmed(e) {
40      self.hide();
41      self.trigger('confirmed');
42      e.preventDefault();
43    }
44
45    /**
46     * Handle dialog canceled
47     * @param {Event} e
48     */
49    function dialogCanceled(e) {
50      self.hide();
51      self.trigger('canceled');
52      e.preventDefault();
53    }
54
55    /**
56     * Flow focus to element
57     * @param {HTMLElement} element Next element to be focused
58     * @param {Event} e Original tab event
59     */
60    function flowTo(element, e) {
61      element.focus();
62      e.preventDefault();
63    }
64
65    // Offset of exit button
66    var exitButtonOffset = 2 * 16;
67    var shadowOffset = 8;
68
69    // Determine if we are too large for our container and must resize
70    var resizeIFrame = false;
71
72    // Create background
73    var popupBackground = document.createElement('div');
74    popupBackground.classList
75      .add('h5p-confirmation-dialog-background', 'hidden', 'hiding');
76
77    // Create outer popup
78    var popup = document.createElement('div');
79    popup.classList.add('h5p-confirmation-dialog-popup', 'hidden');
80    if (options.classes) {
81      options.classes.forEach(function (popupClass) {
82        popup.classList.add(popupClass);
83      });
84    }
85
86    popup.setAttribute('role', 'dialog');
87    popup.setAttribute('aria-labelledby', 'h5p-confirmation-dialog-dialog-text-' + uniqueId);
88    popupBackground.appendChild(popup);
89    popup.addEventListener('keydown', function (e) {
90      if (e.which === 27) {// Esc key
91        // Exit dialog
92        dialogCanceled(e);
93      }
94    });
95
96    // Popup header
97    var header = document.createElement('div');
98    header.classList.add('h5p-confirmation-dialog-header');
99    popup.appendChild(header);
100
101    // Header text
102    var headerText = document.createElement('div');
103    headerText.classList.add('h5p-confirmation-dialog-header-text');
104    headerText.innerHTML = options.headerText;
105    header.appendChild(headerText);
106
107    // Popup body
108    var body = document.createElement('div');
109    body.classList.add('h5p-confirmation-dialog-body');
110    popup.appendChild(body);
111
112    // Popup text
113    var text = document.createElement('div');
114    text.classList.add('h5p-confirmation-dialog-text');
115    text.innerHTML = options.dialogText;
116    text.id = 'h5p-confirmation-dialog-dialog-text-' + uniqueId;
117    body.appendChild(text);
118
119    // Popup buttons
120    var buttons = document.createElement('div');
121    buttons.classList.add('h5p-confirmation-dialog-buttons');
122    body.appendChild(buttons);
123
124    // Cancel button
125    var cancelButton = document.createElement('button');
126    cancelButton.classList.add('h5p-core-cancel-button');
127    cancelButton.textContent = options.cancelText;
128
129    // Confirm button
130    var confirmButton = document.createElement('button');
131    confirmButton.classList.add('h5p-core-button');
132    confirmButton.classList.add('h5p-confirmation-dialog-confirm-button');
133    confirmButton.textContent = options.confirmText;
134
135    // Exit button
136    var exitButton = document.createElement('button');
137    exitButton.classList.add('h5p-confirmation-dialog-exit');
138    exitButton.setAttribute('aria-hidden', 'true');
139    exitButton.tabIndex = -1;
140    exitButton.title = options.cancelText;
141
142    // Cancel handler
143    cancelButton.addEventListener('click', dialogCanceled);
144    cancelButton.addEventListener('keydown', function (e) {
145      if (e.which === 32) { // Space
146        dialogCanceled(e);
147      }
148      else if (e.which === 9 && e.shiftKey) { // Shift-tab
149        flowTo(confirmButton, e);
150      }
151    });
152
153    if (!options.hideCancel) {
154      buttons.appendChild(cancelButton);
155    }
156    else {
157      // Center buttons
158      buttons.classList.add('center');
159    }
160
161    // Confirm handler
162    confirmButton.addEventListener('click', dialogConfirmed);
163    confirmButton.addEventListener('keydown', function (e) {
164      if (e.which === 32) { // Space
165        dialogConfirmed(e);
166      }
167      else if (e.which === 9 && !e.shiftKey) { // Tab
168        const nextButton = !options.hideCancel ? cancelButton : confirmButton;
169        flowTo(nextButton, e);
170      }
171    });
172    buttons.appendChild(confirmButton);
173
174    // Exit handler
175    exitButton.addEventListener('click', dialogCanceled);
176    exitButton.addEventListener('keydown', function (e) {
177      if (e.which === 32) { // Space
178        dialogCanceled(e);
179      }
180    });
181    if (!options.hideExit) {
182      popup.appendChild(exitButton);
183    }
184
185    // Wrapper element
186    var wrapperElement;
187
188    // Focus capturing
189    var focusPredator;
190
191    // Maintains hidden state of elements
192    var wrapperSiblingsHidden = [];
193    var popupSiblingsHidden = [];
194
195    // Element with focus before dialog
196    var previouslyFocused;
197
198    /**
199     * Set parent of confirmation dialog
200     * @param {HTMLElement} wrapper
201     * @returns {H5P.ConfirmationDialog}
202     */
203    this.appendTo = function (wrapper) {
204      wrapperElement = wrapper;
205      return this;
206    };
207
208    /**
209     * Capture the focus element, send it to confirmation button
210     * @param {Event} e Original focus event
211     */
212    var captureFocus = function (e) {
213      if (!popupBackground.contains(e.target)) {
214        e.preventDefault();
215        confirmButton.focus();
216      }
217    };
218
219    /**
220     * Hide siblings of element from assistive technology
221     *
222     * @param {HTMLElement} element
223     * @returns {Array} The previous hidden state of all siblings
224     */
225    var hideSiblings = function (element) {
226      var hiddenSiblings = [];
227      var siblings = element.parentNode.children;
228      var i;
229      for (i = 0; i < siblings.length; i += 1) {
230        // Preserve hidden state
231        hiddenSiblings[i] = siblings[i].getAttribute('aria-hidden') ?
232          true : false;
233
234        if (siblings[i] !== element) {
235          siblings[i].setAttribute('aria-hidden', true);
236        }
237      }
238      return hiddenSiblings;
239    };
240
241    /**
242     * Restores assistive technology state of element's siblings
243     *
244     * @param {HTMLElement} element
245     * @param {Array} hiddenSiblings Hidden state of all siblings
246     */
247    var restoreSiblings = function (element, hiddenSiblings) {
248      var siblings = element.parentNode.children;
249      var i;
250      for (i = 0; i < siblings.length; i += 1) {
251        if (siblings[i] !== element && !hiddenSiblings[i]) {
252          siblings[i].removeAttribute('aria-hidden');
253        }
254      }
255    };
256
257    /**
258     * Start capturing focus of parent and send it to dialog
259     */
260    var startCapturingFocus = function () {
261      focusPredator = wrapperElement.parentNode || wrapperElement;
262      focusPredator.addEventListener('focus', captureFocus, true);
263    };
264
265    /**
266     * Clean up event listener for capturing focus
267     */
268    var stopCapturingFocus = function () {
269      focusPredator.removeAttribute('aria-hidden');
270      focusPredator.removeEventListener('focus', captureFocus, true);
271    };
272
273    /**
274     * Hide siblings in underlay from assistive technologies
275     */
276    var disableUnderlay = function () {
277      wrapperSiblingsHidden = hideSiblings(wrapperElement);
278      popupSiblingsHidden = hideSiblings(popupBackground);
279    };
280
281    /**
282     * Restore state of underlay for assistive technologies
283     */
284    var restoreUnderlay = function () {
285      restoreSiblings(wrapperElement, wrapperSiblingsHidden);
286      restoreSiblings(popupBackground, popupSiblingsHidden);
287    };
288
289    /**
290     * Fit popup to container. Makes sure it doesn't overflow.
291     * @params {number} [offsetTop] Offset of popup
292     */
293    var fitToContainer = function (offsetTop) {
294      var popupOffsetTop = parseInt(popup.style.top, 10);
295      if (offsetTop !== undefined) {
296        popupOffsetTop = offsetTop;
297      }
298
299      if (!popupOffsetTop) {
300        popupOffsetTop = 0;
301      }
302
303      // Overflows height
304      if (popupOffsetTop + popup.offsetHeight > wrapperElement.offsetHeight) {
305        popupOffsetTop = wrapperElement.offsetHeight - popup.offsetHeight - shadowOffset;
306      }
307
308      if (popupOffsetTop - exitButtonOffset <= 0) {
309        popupOffsetTop = exitButtonOffset + shadowOffset;
310
311        // We are too big and must resize
312        resizeIFrame = true;
313      }
314      popup.style.top = popupOffsetTop + 'px';
315    };
316
317    /**
318     * Show confirmation dialog
319     * @params {number} offsetTop Offset top
320     * @returns {H5P.ConfirmationDialog}
321     */
322    this.show = function (offsetTop) {
323      // Capture focused item
324      previouslyFocused = document.activeElement;
325      wrapperElement.appendChild(popupBackground);
326      startCapturingFocus();
327      disableUnderlay();
328      popupBackground.classList.remove('hidden');
329      fitToContainer(offsetTop);
330      setTimeout(function () {
331        popup.classList.remove('hidden');
332        popupBackground.classList.remove('hiding');
333
334        setTimeout(function () {
335          // Focus confirm button
336          confirmButton.focus();
337
338          // Resize iFrame if necessary
339          if (resizeIFrame && options.instance) {
340            var minHeight = parseInt(popup.offsetHeight, 10) +
341              exitButtonOffset + (2 * shadowOffset);
342            self.setViewPortMinimumHeight(minHeight);
343            options.instance.trigger('resize');
344            resizeIFrame = false;
345          }
346        }, 100);
347      }, 0);
348
349      return this;
350    };
351
352    /**
353     * Hide confirmation dialog
354     * @returns {H5P.ConfirmationDialog}
355     */
356    this.hide = function () {
357      popupBackground.classList.add('hiding');
358      popup.classList.add('hidden');
359
360      // Restore focus
361      stopCapturingFocus();
362      if (!options.skipRestoreFocus) {
363        previouslyFocused.focus();
364      }
365      restoreUnderlay();
366      setTimeout(function () {
367        popupBackground.classList.add('hidden');
368        wrapperElement.removeChild(popupBackground);
369        self.setViewPortMinimumHeight(null);
370      }, 100);
371
372      return this;
373    };
374
375    /**
376     * Retrieve element
377     *
378     * @return {HTMLElement}
379     */
380    this.getElement = function () {
381      return popup;
382    };
383
384    /**
385     * Get previously focused element
386     * @return {HTMLElement}
387     */
388    this.getPreviouslyFocused = function () {
389      return previouslyFocused;
390    };
391
392    /**
393     * Sets the minimum height of the view port
394     *
395     * @param {number|null} minHeight
396     */
397    this.setViewPortMinimumHeight = function (minHeight) {
398      var container = document.querySelector('.h5p-container') || document.body;
399      container.style.minHeight = (typeof minHeight === 'number') ? (minHeight + 'px') : minHeight;
400    };
401  }
402
403  ConfirmationDialog.prototype = Object.create(EventDispatcher.prototype);
404  ConfirmationDialog.prototype.constructor = ConfirmationDialog;
405
406  return ConfirmationDialog;
407
408}(H5P.EventDispatcher));
409
410H5P.ConfirmationDialog.uniqueId = -1;

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.