Issue #3390549 by finnsky, nod_, smustgrave, larowlan, catch, bnjmnm: Get rid of jQuery in dialog events

merge-requests/7879/head
Dave Long 2024-05-01 16:39:19 +01:00
parent a244fdde34
commit 99af345889
No known key found for this signature in database
GPG Key ID: ED52AE211E142771
13 changed files with 221 additions and 142 deletions

View File

@ -549,6 +549,7 @@ drupal.debounce:
drupal.dialog:
version: VERSION
js:
misc/dialog/dialog-deprecation.js: {}
misc/dialog/dialog.js: {}
misc/dialog/dialog.position.js: {}
misc/dialog/dialog.jquery-ui.js: {}
@ -582,6 +583,7 @@ drupal.dialog:
- core/drupal.debounce
- core/drupal.displace
- core/tabbable.jquery.shim
- core/once
- core/drupal.jquery.position
drupal.dialog.ajax:

View File

@ -0,0 +1,40 @@
/**
* @file
* Maintains and deprecates Dialog jQuery events.
*/
(function ($, Drupal, once) {
if (once('drupal-dialog-deprecation-listener', 'html').length) {
const eventSpecial = {
handle($event) {
const $element = $($event.target);
const event = $event.originalEvent;
const dialog = event.dialog;
const dialogArguments = [$event, dialog, $element, event?.settings];
$event.handleObj.handler.apply(this, dialogArguments);
},
};
$.event.special['dialog:beforecreate'] = eventSpecial;
$.event.special['dialog:aftercreate'] = eventSpecial;
$.event.special['dialog:beforeclose'] = eventSpecial;
$.event.special['dialog:afterclose'] = eventSpecial;
const listenDialogEvent = (event) => {
const windowEvents = $._data(window, 'events');
const isWindowHasDialogListener = windowEvents[event.type];
if (isWindowHasDialogListener) {
Drupal.deprecationError({
message: `jQuery event ${event.type} is deprecated in 10.3.0 and is removed from Drupal:12.0.0. See https://www.drupal.org/node/3422670`,
});
}
};
[
'dialog:beforecreate',
'dialog:aftercreate',
'dialog:beforeclose',
'dialog:afterclose',
].forEach((e) => window.addEventListener(e, listenDialogEvent));
}
})(jQuery, Drupal, once);

View File

@ -270,7 +270,9 @@
* @param {object} [settings]
* Dialog settings.
*/
$(window).on('dialog:aftercreate', (e, dialog, $element, settings) => {
window.addEventListener('dialog:aftercreate', (event) => {
const $element = $(event.target);
const dialog = event.dialog;
$element.on('click.dialog', '.dialog-cancel', (e) => {
dialog.close('cancel');
e.preventDefault();
@ -288,7 +290,8 @@
* @param {jQuery} $element
* jQuery collection of the dialog element.
*/
$(window).on('dialog:beforeclose', (e, dialog, $element) => {
window.addEventListener('dialog:beforeclose', (e) => {
const $element = $(e.target);
$element.off('.dialog');
});

View File

@ -5,6 +5,14 @@
* @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.
@ -61,7 +69,10 @@
*/
Drupal.dialog = function (element, options) {
let undef;
const $element = $(element);
const domElement = $element.get(0);
const dialog = {
open: false,
returnValue: undef,
@ -70,28 +81,33 @@
function openDialog(settings) {
settings = $.extend({}, drupalSettings.dialog, options, settings);
// Trigger a global event to allow scripts to bind events to the dialog.
$(window).trigger('dialog:beforecreate', [dialog, $element, settings]);
$element.dialog(settings);
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($element.get(0));
bodyScrollLock.lock(domElement);
}
$(window).trigger('dialog:aftercreate', [dialog, $element, settings]);
domElement.dispatchEvent(
new DrupalDialogEvent('aftercreate', dialog, settings),
);
}
function closeDialog(value) {
$(window).trigger('dialog:beforeclose', [dialog, $element]);
domElement.dispatchEvent(new DrupalDialogEvent('beforeclose', dialog));
// Unlocks the body when the dialog closes.
bodyScrollLock.clearBodyLocks();
$element.dialog('close');
dialog.returnValue = value;
dialog.open = false;
$(window).trigger('dialog:afterclose', [dialog, $element]);
domElement.dispatchEvent(new DrupalDialogEvent('afterclose', dialog));
}
dialog.show = () => {

View File

@ -113,28 +113,30 @@
.trigger('dialogContentResize');
}
$(window).on({
'dialog:aftercreate': function (event, dialog, $element, settings) {
const autoResize = debounce(resetSize, 20);
const eventData = { settings, $element };
if (settings.autoResize === true || settings.autoResize === 'true') {
const uiDialog = $element
.dialog('option', { resizable: false, draggable: false })
.dialog('widget');
uiDialog[0].style.position = 'fixed';
$(window)
.on('resize.dialogResize scroll.dialogResize', eventData, autoResize)
.trigger('resize.dialogResize');
$(document).on(
'drupalViewportOffsetChange.dialogResize',
eventData,
autoResize,
);
}
},
'dialog:beforeclose': function (event, dialog, $element) {
$(window).off('.dialogResize');
$(document).off('.dialogResize');
},
window.addEventListener('dialog:aftercreate', (e) => {
const autoResize = debounce(resetSize, 20);
const $element = $(e.target);
const { settings } = e;
const eventData = { settings, $element };
if (settings.autoResize === true || settings.autoResize === 'true') {
const uiDialog = $element
.dialog('option', { resizable: false, draggable: false })
.dialog('widget');
uiDialog[0].style.position = 'fixed';
$(window)
.on('resize.dialogResize scroll.dialogResize', eventData, autoResize)
.trigger('resize.dialogResize');
$(document).on(
'drupalViewportOffsetChange.dialogResize',
eventData,
autoResize,
);
}
});
window.addEventListener('dialog:beforeclose', () => {
$(window).off('.dialogResize');
$(document).off('.dialogResize');
});
})(jQuery, Drupal, drupalSettings, Drupal.debounce, Drupal.displace);

View File

@ -341,23 +341,39 @@
if (!once('off-canvas', 'html').length) {
return;
}
$(window).on({
'dialog:beforecreate': (event, dialog, $element, settings) => {
if (Drupal.offCanvas.isOffCanvas($element)) {
Drupal.offCanvas.beforeCreate({ dialog, $element, settings });
}
},
'dialog:aftercreate': (event, dialog, $element, settings) => {
if (Drupal.offCanvas.isOffCanvas($element)) {
Drupal.offCanvas.render({ dialog, $element, settings });
Drupal.offCanvas.afterCreate({ $element, settings });
}
},
'dialog:beforeclose': (event, dialog, $element) => {
if (Drupal.offCanvas.isOffCanvas($element)) {
Drupal.offCanvas.beforeClose({ dialog, $element });
}
},
window.addEventListener('dialog:beforecreate', (e) => {
const $element = $(e.target);
if (Drupal.offCanvas.isOffCanvas($element)) {
Drupal.offCanvas.beforeCreate({
$element,
settings: e.settings,
});
}
});
window.addEventListener('dialog:aftercreate', (e) => {
const $element = $(e.target);
if (Drupal.offCanvas.isOffCanvas($element)) {
Drupal.offCanvas.render({
$element,
dialog: e.dialog,
settings: e.settings,
});
Drupal.offCanvas.afterCreate({
$element,
settings: e.settings,
});
}
});
window.addEventListener('dialog:beforeclose', (e) => {
const $element = $(e.target);
if (Drupal.offCanvas.isOffCanvas($element)) {
Drupal.offCanvas.beforeClose({
$element,
});
}
});
},
};

View File

@ -650,7 +650,7 @@
);
// Respond to new dialogs that are opened by CKEditor, closing the AJAX loader.
$(window).on('dialog:beforecreate', () => {
window.addEventListener('dialog:beforecreate', () => {
const dialogLoading = document.querySelector('.ckeditor5-dialog-loading');
if (dialogLoading) {
@ -673,7 +673,7 @@
});
// Respond to dialogs that are closed, removing the current save handler.
$(window).on('dialog:afterclose', () => {
window.addEventListener('dialog:afterclose', () => {
if (Drupal.ckeditor5.saveCallback) {
Drupal.ckeditor5.saveCallback = null;
}

View File

@ -219,7 +219,8 @@
};
// After a dialog opens, highlight element that the dialog is acting on.
$(window).on('dialog:aftercreate', (event, dialog, $element) => {
window.addEventListener('dialog:aftercreate', (e) => {
const $element = $(e.target);
if (Drupal.offCanvas.isOffCanvas($element)) {
// Start by removing any existing highlighted elements.
$('.is-layout-builder-highlighted').removeClass(
@ -309,7 +310,8 @@
});
}
$(window).on('dialog:afterclose', (event, dialog, $element) => {
window.addEventListener('dialog:afterclose', (e) => {
const $element = $(e.target);
if (Drupal.offCanvas.isOffCanvas($element)) {
// Remove the highlight from all elements.
$('.is-layout-builder-highlighted').removeClass(

View File

@ -382,7 +382,7 @@
if (!once('media-library-selection-info', 'html').length) {
return;
}
$(window).on('dialog:aftercreate', () => {
window.addEventListener('dialog:aftercreate', () => {
// Since the dialog HTML is not part of the context, we can't use
// context here.
const $buttonPane = $(
@ -410,7 +410,7 @@
if (!once('media-library-clear-selection', 'html').length) {
return;
}
$(window).on('dialog:afterclose', () => {
window.addEventListener('dialog:afterclose', () => {
Drupal.MediaLibrary.currentSelection = [];
});
},

View File

@ -237,24 +237,22 @@
};
// Manage Active editable class on opening and closing of the dialog.
$(window).on({
'dialog:beforecreate': (event, dialog, $element, settings) => {
if ($element[0].id === 'drupal-off-canvas') {
$('body .settings-tray-active-editable').removeClass(
'settings-tray-active-editable',
);
const $activeElement = $(`#${settings.settingsTrayActiveEditableId}`);
if ($activeElement.length) {
$activeElement.addClass('settings-tray-active-editable');
}
window.addEventListener('dialog:beforecreate', (e) => {
if (e.target.id === 'drupal-off-canvas') {
$('body .settings-tray-active-editable').removeClass(
'settings-tray-active-editable',
);
const $activeElement = $(`#${e.settings.settingsTrayActiveEditableId}`);
if ($activeElement.length) {
$activeElement.addClass('settings-tray-active-editable');
}
},
'dialog:beforeclose': (event, dialog, $element) => {
if ($element[0].id === 'drupal-off-canvas') {
$('body .settings-tray-active-editable').removeClass(
'settings-tray-active-editable',
);
}
},
}
});
window.addEventListener('dialog:beforeclose', (e) => {
if (e.target.id === 'drupal-off-canvas') {
$('body .settings-tray-active-editable').removeClass(
'settings-tray-active-editable',
);
}
});
})(jQuery, Drupal);

View File

@ -205,34 +205,35 @@
});
}
$(window).on({
'dialog:aftercreate': (event, dialog, $element, settings) => {
const toolbarBar = document.getElementById('toolbar-bar');
if (toolbarBar) {
toolbarBar.style.marginTop = '0';
window.addEventListener('dialog:aftercreate', (e) => {
const $element = $(e.target);
const { settings } = e;
const toolbarBar = document.getElementById('toolbar-bar');
if (toolbarBar) {
toolbarBar.style.marginTop = '0';
// When off-canvas is positioned in top, toolbar has to be moved down.
if (settings.drupalOffCanvasPosition === 'top') {
const height = Drupal.offCanvas
// When off-canvas is positioned in top, toolbar has to be moved down.
if (settings.drupalOffCanvasPosition === 'top') {
const height = Drupal.offCanvas
.getContainer($element)
.outerHeight();
toolbarBar.style.marginTop = `${height}px`;
$element.on('dialogContentResize.off-canvas', () => {
const newHeight = Drupal.offCanvas
.getContainer($element)
.outerHeight();
toolbarBar.style.marginTop = `${height}px`;
toolbarBar.style.marginTop = `${newHeight}px`;
});
}
}
});
$element.on('dialogContentResize.off-canvas', () => {
const newHeight = Drupal.offCanvas
.getContainer($element)
.outerHeight();
toolbarBar.style.marginTop = `${newHeight}px`;
});
}
}
},
'dialog:beforeclose': () => {
const toolbarBar = document.getElementById('toolbar-bar');
if (toolbarBar) {
toolbarBar.style.marginTop = '0';
}
},
window.addEventListener('dialog:beforeclose', () => {
const toolbarBar = document.getElementById('toolbar-bar');
if (toolbarBar) {
toolbarBar.style.marginTop = '0';
}
});
});

View File

@ -81,7 +81,8 @@
* @param {jQuery} $element
* The jQuery collection of the dialog element.
*/
$(window).on('dialog:aftercreate', (e, dialog, $element) => {
window.addEventListener('dialog:aftercreate', (e) => {
const $element = $(e.target);
const $scroll = $element.find('.scroll');
if ($scroll.length) {
bodyScrollLock.unlock($element.get(0));

View File

@ -20,53 +20,51 @@
if (!once('media-library-selection-info-claro-event', 'html').length) {
return;
}
$(window).on(
'dialog:aftercreate',
(event, dialog, $element, settings) => {
// Since the dialog HTML is not part of the context, we can't use
// context here.
const moveCounter = ($selectedCount, $buttonPane) => {
const $moveSelectedCount = $selectedCount.detach();
$buttonPane.prepend($moveSelectedCount);
};
window.addEventListener('dialog:aftercreate', (e) => {
const $element = $(e.target);
// Since the dialog HTML is not part of the context, we can't use
// context here.
const moveCounter = ($selectedCount, $buttonPane) => {
const $moveSelectedCount = $selectedCount.detach();
$buttonPane.prepend($moveSelectedCount);
};
const $buttonPane = $element
.closest('.media-library-widget-modal')
.find('.ui-dialog-buttonpane');
if (!$buttonPane.length) {
return;
}
const $selectedCount = $buttonPane.find(
'.js-media-library-selected-count',
);
const $buttonPane = $element
.closest('.media-library-widget-modal')
.find('.ui-dialog-buttonpane');
if (!$buttonPane.length) {
return;
}
const $selectedCount = $buttonPane.find(
'.js-media-library-selected-count',
);
// If the `selected` counter is already present, it can be moved from
// the end of the button pane to the beginning.
if ($selectedCount.length) {
moveCounter($selectedCount, $buttonPane);
} else {
// If the `selected` counter is not yet present, create a mutation
// observer that checks for items added to the button pane. As soon
// as the counter is added, move it from the end of the button pane
// to the beginning.
const selectedCountObserver = new MutationObserver(() => {
const $selectedCountFind = $buttonPane.find(
'.js-media-library-selected-count',
);
if ($selectedCountFind.length) {
moveCounter($selectedCountFind, $buttonPane);
selectedCountObserver.disconnect();
}
});
selectedCountObserver.observe($buttonPane[0], {
attributes: false,
childList: true,
characterData: false,
subtree: true,
});
}
},
);
// If the `selected` counter is already present, it can be moved from
// the end of the button pane to the beginning.
if ($selectedCount.length) {
moveCounter($selectedCount, $buttonPane);
} else {
// If the `selected` counter is not yet present, create a mutation
// observer that checks for items added to the button pane. As soon
// as the counter is added, move it from the end of the button pane
// to the beginning.
const selectedCountObserver = new MutationObserver(() => {
const $selectedCountFind = $buttonPane.find(
'.js-media-library-selected-count',
);
if ($selectedCountFind.length) {
moveCounter($selectedCountFind, $buttonPane);
selectedCountObserver.disconnect();
}
});
selectedCountObserver.observe($buttonPane[0], {
attributes: false,
childList: true,
characterData: false,
subtree: true,
});
}
});
},
};
})(jQuery, Drupal, window);