Problem/Motivation
In #3100937: Update modernizr to 3.8.0, it was discovered that Modernizr's touchevent test is deprecated. https://github.com/Modernizr/Modernizr/pull/2432
There are also problems with that test from Modernizr 3.7.1 onward, which requires an override of that test in Drupal core (added in the aformentioned issue).
Core's custom touchevent, added in #3100937 currently works fine, but may become outdated as newer browser versions are released and different ways of detecting touchevent become available.
What touchevents currently does for core
Modernizr adds a .touchevents or .no-touchevents class to <html> based on if the touchevents test is true or false.
The following CSS files have styles that expect one of these two classes.
./core/misc/dialog/off-canvas.tabledrag.css
./core/misc/dialog/off-canvas.button.css
./core/modules/contextual/css/contextual.theme.css
./core/modules/system/css/components/tabledrag.module.css
./core/themes/stable/css/core/dialog/off-canvas.tabledrag.css
./core/themes/stable/css/core/dialog/off-canvas.button.css
./core/themes/stable/css/contextual/contextual.theme.css
./core/themes/stable/css/system/components/tabledrag.module.css
./core/themes/stable9/css/core/dialog/off-canvas.tabledrag.css
./core/themes/stable9/css/core/dialog/off-canvas.button.css
./core/themes/stable9/css/contextual/contextual.theme.css
./core/themes/stable9/css/system/components/tabledrag.module.css
./core/themes/claro/css/components/dropbutton.css
./core/themes/claro/css/components/form--text.css
./core/themes/claro/css/components/table--file-multiple-widget.css
./core/themes/claro/css/components/tabledrag.css
./core/themes/claro/css/components/button.css
./core/themes/claro/css/components/form--select.css
./core/themes/claro/css/components/action-link.css
./core/themes/claro/css/theme/views_ui.admin.theme.css
./core/themes/seven/css/components/buttons.css
./core/themes/olivero/css/components/tabledrag.css
In many (most?) cases this is not trivial styling, but fairly significant changes.
Contextual Links also use the value of Modernizr.touchevents in two places:
./core/modules/contextual/js/views/VisualView.es6.js
// We only want mouse hover events on non-touch.
if (!Modernizr.touchevents) {
mapping.mouseenter = function () {
this.model.focus();
};
}./core/modules/contextual/js/views/RegionView.es6.j
// We don't want mouse hover events on touch.
if (Modernizr.touchevents) {
mapping = {};
}Proposed resolution
Determine if there is another library capable of detecting touchevent in a way that is useful to core. If so, add that library and deprecate Modernizr touchevent.
If there isn't another library that fits that exact need, determine if it's better to support Drupal core's custom touchevent test, or using a different library that may require refactoring how touchevent/no-touchevent classes are applied and what CSS rules are based on them.
I propose building on the existing logic in core/misc/modernizr-additional-tests.es6.js. This is in core because Modernizr itself has deprecated touchevents , and for good reason: it's not an accurate test. However, the criteria used by the former Modernizr.touchevents is very established in core, with many styles (and a little bit of JS) relying on its verdict. Switching to logic that is different from this (admittedly flawed) touchevents check would be very disruptive. The fact that it was disruptive is why core/misc/modernizr-additional-tests.es6.js is in core to begin with.
So I suggest keeeping the logic in core/misc/modernizr-additional-tests.es6.js, but making it a standalone asset, not a modernizr feature. This would be expanded to add the .touchevents/.no-touchevents as needed, and the contextual links JavaScript could either look for
'html.touchevents'
or we can move the touchevents result into drupalSettings.
TLDR: although better touchevents detection might exist, changing this would be prohibitively disruptive. 50% of the logic is already part of core, so adding the missing 50% will get us closer to being able to remove Modernizr altogether.
Remaining tasks
User interface changes
API changes
Data model changes
Release notes snippet
The Modernizr.touchevents test has been deprecated. In addition, Modernizr is no longer responsible within Drupal for detecting touch devices and adding the touchevents/no-touchevents classes to the html element based on the detection result. The specific functionality of adding classes based on touch device detection is now provided via a core library: core/drupal.touchevents-test. The detection method used is identical to Modernizr's.
| Comment | File | Size | Author |
|---|---|---|---|
| #30 | 3101922-30-10x.patch | 13.27 KB | bnjmnm |
| #29 | interdiff-26-29.txt | 1.46 KB | nod_ |
| #29 | core-touch-3101922-29.patch | 23.68 KB | nod_ |
| #26 | interdiff_23-26.txt | 913 bytes | bnjmnm |
| #26 | 3101922-26.patch | 23.57 KB | bnjmnm |
Issue fork drupal-3101922
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
lauriiiThis quote is from the PR. I'm wondering if we use the test correctly? Could we update the issue summary with info on what depends on the touchevent test so we could try to evaluate that?
Comment #5
xjmComment #6
xjmComment #7
bnjmnmComment #8
bnjmnmComment #9
bnjmnmThe touchdevices check can potentially be simplified/
Part of Modernizr's check looks for what is essentially the following:
@media (touch-enabled),(-webkit-touch-enabled),(-moz-touch-enabled),(-o-touch-enabled),(-ms-touch-enabled)-moz-touch-enabledwas removed in Firefox 73 a few years ago, it's well past the "last two major relesases" supported browsers range. 👉 https://bugzilla.mozilla.org/show_bug.cgi?id=1486964. I see no evidence of any browser other than Firefox supporting atouch-enabledmedia query. Another set of eyes could be useful, but I think the media-query-checking logic isn't needed since no supported browsers recognize atouch-enabledmedia query.That could make replacing the modernizr touchevents pretty easy, just run this on load.
Comment #10
nod_Sounds good to me
Comment #11
lauriiiBefore we go deeper into figuring out the approach for implementing replacement for this, we should evaluate if we this is something we should be doing at all as mentioned in #2. The reason this was removed from Modernizr was that they thought it was harmful for the web to do checks like this, because having touch enabled on a device doesn't indicate that the user is using touch, since the device could have touch enabled while still having a mouse.
Comment #12
bnjmnmRe #11: I updated the issue summary in #8 and I hoped the proposed solution had a good justification of the approach, but I'll try a differently worded version here and see what people think.
touchevents/no-touchevents classesand remove this detection entirely. There doesn't seem to be a reliable way to do this in general. That doesn't need to be in the scope of eliminating Modernizr as a dependency, though. This could take a bit of time, though. Claro in particular has a good amount of styling based on these classes. I think it's best to quickly eliminate the Modernizr dependency with my approach, then phase out touch detection carefully.Comment #13
lauriiiThank you for explaining the thought process behind #9! That is really helpful. 💯
I was curious and reviewed most of the CSS uses. Those seem fine since they are enhancements making the UI more touch friendly.
The JavaScript uses are a bit concerning and those could be something we should look into deeper and potentially try to deprecate (either this issue or follow-up). I'm wondering if #2168711: Modernizr.touchevents use can lead to scenarios that break contextual links is potentially related to that.
I like the idea of limiting the API to the CSS class. However, documenting the concerns on using those CSS classes is harder than if it was a JavaScript API.
I'm wondering if the steps are then:
core/misc/modernizr-additional-tests.es6.jscore/misc/modernizr-additional-tests.es6.jswhich adds a CSS class to the<html>elementcore/misc/modernizr-additional-tests.es6.js, document the downsides/concerns of using the touchevents detectionComment #14
bnjmnmI added a patch to #2168711: Modernizr.touchevents use can lead to scenarios that break contextual links that eliminates the Modernizr dependency. If that landed we'd only have to be concerned with steps 1-3 of #13!
Comment #15
bnjmnmHere's a first try of deprecating & adding the replacement. Lets see what the tests do.
Comment #16
nod_Might need to do a
Modernizr = Drupal.deprecateProperty…Should probably be below the Modernizr.addTest() too.
Comment #18
bnjmnmre #16
Yep that was the wrong use of
deprecatedPropertyI have
deprecatedPropertyhappening first as theModernizr.addTest()will only be called ifdrupal.touchevents-testisn't loaded. Deprecating the property is always necessary, but the test isn't. An early return seems like the most elegant way to do it, but if the order seems important I could wrap Modernizr.addTest() in a conditional instead.This patch adds tests, and I'm running into a problem where Nightwatch isn't seeing the deprecations, but when I pause the Chromedriver window I can see the deprecations in the console. Seems like a "I forgot {x} setting" kind of thing, but I'll put what I have as is for the time being.
Comment #19
nod_Seems dangerous to pass the input as-is. It looks safe but I would restrict the possibilities just in case.
We have the
drupalInstallModulecommand to simplify a bit:Comment #20
bnjmnmAddresses #19.
Still not sure how to get the deprecations detected in the tests. As mentioned earlier, I can see those deprecations if I pause the tests locally, but
deprecationErrorExistsisn't seeing them and I bet it's some simple little thing I'm overlooking 🙂Comment #21
nod_There is a little load order issue in the last patch.
Drupal is used in the modernizr additional tests file, but core/drupal is not a dependency and drupal.js is not loaded in the head. So the various deprecation methods are not available at this point.
Comment #22
bnjmnmSome acrobatics were required to make the deprecation detectable in tests due to Modernizr's library definition being set to
header: trueand the weights set to load beforejs_testing_log.jsand its related dependencies. The test module I added (modernizr_deprecation_test) useslibrary_info_alter()to get around this, but I'm unsure if the deprecation is visible to tooling without that module running.Comment #23
bnjmnmComment #24
nod_haven't looked in detail yet but copy/paste solution for the deprecation method is +1 from me
Comment #25
nod_This makes drupal and once load in the header and they are not required as far as I can see.
The condition is a bit hard to read but it prevents a temporary variable to be created.
So shortest code achieve that +1
so modernizr test is at -21 and -20. so this should be -22.
Not sure we need the preprocess = 0 either. That might simplify the tests as well?
Comment #26
bnjmnmAddresses #25
Comment #27
nod_Perfect, thanks. Test looks good too.
Comment #28
lauriiiDid some research related to #9 and I agree that it seems fine to remove the media query based check since it was highly unlikely to do anything on the supported browsers.
Should we remove the console log?
Can we add a short comment explaining why we are not using this from the
core/drupal? I saw that was discussed here and agree that there's a good reason to do so but would be nice to have that documented in the code too.Comment #29
nod_I really struggle with comments so I did my best there even if it doesn't look like it :/
Comment #30
bnjmnmComment #31
nod_should that be -20 to match the weight of the old modernizr test?
The weight thing is a detail so either way RTBC for me.
Comment #32
bnjmnmRe #31
Intentionally set to -21. The old test was -20 because it required Modernizr to be present. Now that this is a dependency-free test I thought it best to put it at the same weight as the Modernizr so -21 is the home to all JS that adds classes to
<html>based on feature detection results.Comment #33
nod_works for me
Comment #37
lauriiiCommitted 199f2b4 and pushed to 10.0.x. Committed #29 to 9.5.x. and cherry-picked to 9.4.x. Thanks!
Comment #38
bnjmnm