1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
/**
* @file
* Dialog API inspired by HTML5 dialog element.
*
* @see http://www.whatwg.org/specs/web-apps/current-work/multipage/commands.html#the-dialog-element
*/
class DrupalDialogEvent extends Event {
constructor(type, dialog, settings = null) {
super(`dialog:${type}`, { bubbles: true });
this.dialog = dialog;
this.settings = settings;
}
}
(function ($, Drupal, drupalSettings, bodyScrollLock) {
/**
* Default dialog options.
*
* @type {object}
*
* @prop {boolean} [autoOpen=true]
* @prop {string} [buttonClass='button']
* @prop {string} [buttonPrimaryClass='button--primary']
* @prop {function} close
*/
drupalSettings.dialog = {
autoOpen: true,
// Drupal-specific extensions: see dialog.jquery-ui.js.
buttonClass: 'button',
buttonPrimaryClass: 'button--primary',
// When using this API directly (when generating dialogs on the client
// side), you may want to override this method and do
// `jQuery(event.target).remove()` as well, to remove the dialog on
// closing.
close(event) {
Drupal.dialog(event.target).close();
Drupal.detachBehaviors(event.target, null, 'unload');
},
};
/**
* @typedef {object} Drupal.dialog~dialogDefinition
*
* @prop {boolean} open
* Is the dialog open or not.
* @prop {*} returnValue
* Return value of the dialog.
* @prop {function} show
* Method to display the dialog on the page.
* @prop {function} showModal
* Method to display the dialog as a modal on the page.
* @prop {function} close
* Method to hide the dialog from the page.
*/
/**
* Polyfill HTML5 dialog element with jQueryUI.
*
* @param {HTMLElement} element
* The element that holds the dialog.
* @param {object} options
* jQuery UI options to be passed to the dialog.
*
* @return {Drupal.dialog~dialogDefinition}
* The dialog instance.
*/
Drupal.dialog = function (element, options) {
let undef;
const $element = $(element);
const domElement = $element.get(0);
const dialog = {
open: false,
returnValue: undef,
};
function openDialog(settings) {
settings = $.extend({}, drupalSettings.dialog, options, settings);
if (settings.dialogClass) {
Drupal.deprecationError({
message:
'dialogClass is deprecated in drupal:10.4.x and will be removed from drupal:12.0.0.',
});
}
// Trigger a global event to allow scripts to bind events to the dialog.
const event = new DrupalDialogEvent('beforecreate', dialog, settings);
domElement.dispatchEvent(event);
$element.dialog(event.settings);
dialog.open = true;
// Locks the body scroll only when it opens in modal.
if (settings.modal) {
// Locks the body when the dialog opens.
bodyScrollLock.lock(domElement);
}
domElement.dispatchEvent(
new DrupalDialogEvent('aftercreate', dialog, settings),
);
}
function closeDialog(value) {
domElement.dispatchEvent(new DrupalDialogEvent('beforeclose', dialog));
// Unlocks the body when the dialog closes.
bodyScrollLock.clearBodyLocks();
$element.dialog('close');
dialog.returnValue = value;
dialog.open = false;
domElement.dispatchEvent(new DrupalDialogEvent('afterclose', dialog));
}
dialog.show = () => {
openDialog({ modal: false });
};
dialog.showModal = () => {
openDialog({ modal: true });
};
dialog.close = closeDialog;
return dialog;
};
})(jQuery, Drupal, drupalSettings, bodyScrollLock);
|