Problem/Motivation

The polyfill added in #1974580: Introduce domReady to remove jQuery dependency from drupal.js and clean it up. was added in 2013 to remove a dependency on jQuery in drupal.js.
See: https://www.drupal.org/node/1994482

Since the 1.0 version, domready dropped support for browsers that don't listen for the DOMContentLoaded event.
Drupal uses the latest version of domready as of #2485573: Update JS library domready to version 1.0.8.

All of the browsers supported by Drupal core natively support DOMContentLoaded so there is no current need for this polyfill.

Proposed resolution

Remove any usages of domready in core and mark the asset library deprecated in core.libraries.yml.

Remaining tasks

  1. Write patch
  2. Test against supported browsers to ensure no change in behavior

User interface changes

API changes

Data model changes

Release notes snippet

Comments

zrpnr created an issue. See original summary.

zrpnr’s picture

Status: Active » Needs review
StatusFileSize
new5.51 KB

The domready library is only used in one file: drupal.init.js. I wrote a function to replace it based on domready itself, the example from http://youmightnotneedjquery.com/ for "ready", and the MDN doc listed in the IS.

If the document.readyState is not loading it fires immediately, otherwise it adds a listener for DOMContentLoaded, the same event domready is listening for. After the event the listener gets removed.

I was curious about

hack = doc && doc.documentElement.doScroll
https://github.com/ded/domready/blob/master/ready.js

which seems to be meant to work for IE8-10, so it should be safe to remove for this replacement.

The tests in AttachedAssetsTest are checking that assets are attached correctly, I'm not sure if there are other good asset libraries that could be tested instead here. For example in testHeaderHTML it was the example of an "indirect dependency".

I'm also not clear on the consequences of removing it from hook_page_attachments, because it is an API function.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

zrpnr’s picture

Version: 8.9.x-dev » 8.8.x-dev
StatusFileSize
new5.6 KB
new2.55 KB

I discussed this with @lauriii in slack and he suggested exposing the replacement function as a global so that it could be used elsewhere.
This patch moves and renames the function so it is added to Drupal

lauriii’s picture

Status: Needs review » Needs work
  1. +++ b/core/lib/Drupal/Core/Render/theme.api.php
    @@ -1039,8 +1039,6 @@ function hook_css_alter(&$css, \Drupal\Core\Asset\AttachedAssetsInterface $asset
     function hook_page_attachments(array &$attachments) {
    -  // Unconditionally attach an asset to the page.
    -  $attachments['#attached']['library'][] = 'core/domready';
    

    Let's keep this in but let's switch to another library. This is just example code for documentation.

  2. +++ b/core/tests/Drupal/KernelTests/Core/Asset/AttachedAssetsTest.php
    @@ -235,7 +235,6 @@ public function testHeaderHTML() {
    -    $this->assertNotIdentical(strpos($rendered_js, '<script src="' . file_url_transform_relative(file_create_url('core/assets/vendor/domready/ready.min.js'))), FALSE, 'The JS asset of the indirect dependency (core/domready) of common_test/js-header appears in the header.');
    

    Maybe we should make the common_test/js-header depend on another library that has nested dependencies?

zrpnr’s picture

Status: Needs work » Needs review
StatusFileSize
new5.89 KB
new1.73 KB

#5.1 I restored these lines, and used drupalSettings as the example.

The JS asset of the indirect dependency (core/domready) of common_test/js-header appears in the header.
#5/2 If I'm understanding this test assertion correctly, drupalSettings is also a good candidate here since it is a dependency of core/drupal which is the only dependency of common_test/js-header

lauriii’s picture

Issue tags: +Needs manual testing
  1. +++ b/core/lib/Drupal/Core/Render/theme.api.php
    @@ -1040,7 +1040,7 @@ function hook_css_alter(&$css, \Drupal\Core\Asset\AttachedAssetsInterface $asset
    -  $attachments['#attached']['library'][] = 'core/domready';
    +  $attachments['#attached']['library'][] = 'core/drupalSettings';
    
    +++ b/core/tests/Drupal/KernelTests/Core/Asset/AttachedAssetsTest.php
    @@ -235,7 +235,7 @@ public function testHeaderHTML() {
    -    $this->assertNotIdentical(strpos($rendered_js, '<script src="' . file_url_transform_relative(file_create_url('core/assets/vendor/domready/ready.min.js'))), FALSE, 'The JS asset of the indirect dependency (core/domready) of common_test/js-header appears in the header.');
    +    $this->assertNotIdentical(strpos($rendered_js, '<script src="' . file_url_transform_relative(file_create_url('core/misc/drupalSettingsLoader.js'))), FALSE, 'The JS asset of the indirect dependency (core/drupalSettings) of common_test/js-header appears in the header.');
    

    Nice 👍

  2. +++ b/core/misc/drupal.init.es6.js
    @@ -6,12 +6,29 @@ if (window.jQuery) {
    +    document.addEventListener('DOMContentLoaded', listener);
    

    Double checked that the event is supported by Drupals supported browser. Looks all good: https://developer.mozilla.org/en-US/docs/Web/API/Window/DOMContentLoaded...

  3. +++ b/core/misc/drupal.init.es6.js
    @@ -6,12 +6,29 @@ if (window.jQuery) {
    +Drupal.domReady = callback => {
    

    We don't have any explicit test coverage for this but that's probably fine since if this doesn't work, most Drupal behaviors will be broken.

    Given the implications of this not working, it would be probably good to do a bit of manual testing on this across our supported browsers. Other than that, this looks good.

nod_’s picture

Status: Needs review » Needs work

Couple of things.

As is the Drupal.domready is not overridable. We define it in the file then immediately use it, there is no chance for anything else to override the function. if we want to make it overridable the definition of Drupal.domready needs to be in a separate file like the current domready lib.

Usually we declare everything inside the closure so Drupal.domReady sould be inside the closure.

The domready lib can handle several callbacks, whereas this version can't.

Given that I'd be up to not make the domready thing overridable and just go with how #2 declares a onReady function inside the closure. It's simply a way to trigger behaviors which are what should be used to do things anyway.

zrpnr’s picture

Status: Needs work » Needs review
StatusFileSize
new5.85 KB
new3.07 KB
new2.56 KB

just go with how #2 declares a onReady function inside the closure

Made another version of #6 using the function from #2.

nod_’s picture

Thanks, ok for me now.

lauriii’s picture

The domready lib can handle several callbacks, whereas this version can't.

Good catch! 👍Thank you @nod_!

zrpnr’s picture

StatusFileSize
new950.03 KB

I tested this manually with crossbrowsertesting.com, that service can take screnshots of a given url.
It has additional browsers available for "live" tests so some of the less common ones were possible to test here too, like opera mini and mobile.

I used ngrok to make a public url for my localhost, then I loaded the core/drupal library with hook_page_attachments_alter so it would load on an anonymous front page view.
and inside the callback function I added test code to change a page element red so it would be easy to see in the screenshot.

domReady(() => {
    document.getElementById('content').setAttribute('style', 'background-color: #ff0000');
    Drupal.attachBehaviors(document, drupalSettings);
});

All of these screenshots show the red background, indicating that the domReady function executed the callback.

The browsers I checked against came from browerslist, run npx browerslist in the core folder to have it read the list in package.json
There are more here than listed in Drupal's current browser requirements

Tested

chrome 77 - tested manually on OSX
chrome 76 - Mac_OSX_10.14_Google_Chrome_76_(64-bit)_1024x768_window.png
chrome 75 - Mac_OSX_10.11_Google_Chrome_75_(64-bit)_1366x768_window.png
chrome 74 - Mac_OSX_10.11_Google_Chrome_74_(64-bit)_1366x768_window.png

edge 18 - Windows_10_Microsoft_Edge_18_1024x768_window.png
edge 17 - Windows_10_Microsoft_Edge_17_1024x768_window.png

firefox 69 - Mac_OSX_10.14_Firefox_69_1366x768_window.png
firefox 68 - Mac_OSX_10.14_Firefox_68_1024x768_window.png
firefox 60 - Mac_OSX_10.13_Firefox_60_1366x768_window.png

safari 13 - tested manually on OSX
safari 12.1 - Mac_OSX_10.14_Safari_12_1024x768_window.png

ie 11 - Windows_10_Internet_Explorer_11_1024x768_window.png

opera 62 - tested Opera 63 - Windows_10_Opera_63_1366x768_window.png
opera 60 - Mac_OSX_10.14_Opera_60_1366x768_window.png

and_chr 76 - tested android chrome 75 - Android_Galaxy_S8_8.0_Chrome_Mobile_75_1080x2220_window.png
and_ff 68 - Android_Galaxy_S9_Firefox_mobile_68.png
and_uc 12.12

ios_saf 13 - tested on iPhone
ios_saf 12.0-12.1 iPad_6th_Gen_Simulator_Mobile_Safari_12.0_2732x2048_window.png

op_mini all - tested opera mini 32 - Nexus_9_Opera-mini_32.png
op_mob 46 - tested opera mobile 44 - Nexus_9_Opera_mobile_44.png

samsung 9.2 - Galaxy_S8_Samsung_9.2.png
samsung 8.2 - Galaxy_S6_Samsung_6.2.png

Not tested

ios_saf 12.2-12.3 - but should be covered by testing the older version
android 76 - not sure what this refers to
and_qq 1.2 - QQ browser
baidu 7.12 - did not install Baidu, but it is based on chromium
ie_mob 11 - not available for testing
kaios 2.5

lauriii’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs manual testing +Needs release manager review

Awesome! Thanks for testing the patch manually on a broad range of browsers!

After this has been committed, we could update the change record to link to a Gitlab page of this file to show this function so that people who need this, could copy it from there.

The code itself looks good. The deprecation message links to the correct change record and the replacing function looks fine. It has been also reviewed by @nod_ who is a JavaScript subsystem maintainer. Moving to RTBC and tagging with needs release manager review. 👏

  • xjm committed 099c897 on 9.0.x
    Issue #3086375 by zrpnr, lauriii, nod_: Deprecate domready and remove...

  • xjm committed 805391a on 8.9.x
    Issue #3086375 by zrpnr, lauriii, nod_: Deprecate domready and remove...

  • xjm committed 4331ea9 on 8.8.x
    Issue #3086375 by zrpnr, lauriii, nod_: Deprecate domready and remove...
xjm’s picture

Status: Reviewed & tested by the community » Fixed
Issue tags: -Needs release manager review +8.8.0 release notes

Committed and pushed to 9.0.x, 8.9.x, and 8.8.x, and published the change record. Thanks!

xjm’s picture

I didn't quite follow the updates that were to be made to https://www.drupal.org/node/3086669 but I think they probably involve putting in the name of the new function and linking it to the source code?

lauriii’s picture

@xjm I updated the change record with what I thought at the time of writing that comment. We can't really reference to a function name because it's just a local variable.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.