Problem/Motivation
It is impossible to load additional JS libraries in an Ajax response and then call that code through Ajax commands, because Drupal.ajax
does not guarantee that the JS library will already have loaded.
The issue is more apparent when there is an \Drupal\Core\Ajax\InsertCommand
"insert" AJAX command containing <script>
tags which should be loaded in a specific manner (as it would on a normal DOM load), but aren't due to how jQuery currently works, and will result in a crash when the scripts are ran out of order.
Quick Javascript snippet to showcase the current behaviour:
var $el = jQuery('#element').length ? jQuery('#element') : jQuery('<div id="element"></div>').appendTo('body');
// https://javascript.info/script-async-defer
// long.js should ideally be loaded first, before small.js is. But currently doesn't.
$el.html(`
<script src="https://javascript.info/article/script-async-defer/long.js?speed=1"></script>
<script src="https://javascript.info/article/script-async-defer/small.js"></script>
`);
References:
See #23 and #31 for further details.
Proposed resolution
Create a new add_js
ajax command that uses the loadjs library to ensure all external JS resources are loaded before continuing execution.
Remaining tasks
User interface changes
None.
API changes
Ajax commands can now return Promises to ensure command execution will wait for the promise to be resolved before continuing execution.
The ajaxing
property of Drupal.Ajax
objects is now set to false
after all ajax command have been executed. Previously it was set to false
as soon as the request came back from the network.
See the long list of related issues.
Release notes snippet
The processing of Ajax commands has changed. Ajax commands can now return promises when they need to ensure some code has been executed before executing the next Ajax command in the list. This is used for the new add_js
command that ensures Additional JS files have been loaded before executing the next Ajax command.
When altering the success
method of a Drupal.Ajax
object please make sure a Promise is returned to ensure proper execution.
Conditional comments for IE will not be honored for JavaScript files with the new add_js
command, all JS files will be added regardless of the value of #browsers
. There are no changes for conditional comments on CSS files they will still work on Drupal 9.
Original report by [username]
Hi,
Thanks for your module, it works perfect for me.
But I found there one small bug there: if all my .js files are mapped to the external CDN, ajax redirects doesn't execute. After some tests I found that CDN rewrites all js urls, even for ajax. So I attached a small patch that solved this problem for me.
Best regards,
Spleshka.