#42822 closed defect (bug) (fixed)
CodeMirror: HTML attributes values hints not fully operable with a keyboard
| Reported by: |
|
Owned by: |
|
|---|---|---|---|
| Milestone: | 7.0 | Priority: | normal |
| Severity: | normal | Version: | 4.9 |
| Component: | Widgets | Keywords: | has-screenshots needs-test-info has-patch |
| Focuses: | accessibility, javascript | Cc: |
Description
To reproduce, add an HTML widget either in the Widgets screen or in the Customizer:
- start typing a HTML tag, for example "<i" for an input field:
- a list of hints appears and it is possible to use the down and up arrow keys to select one of the hints in the list, pressing Enter inserts the tag
- after the input, start typing the "type" attribute followed by a "="
- a list of possible values for the type attribute appears
- press the down arrow key to try to select one of the hints
- as soon as you release the down arrow key (on keyup), the selection moves back to the first hint thus making impossible to select any of the other hints
Worth noting:
- typing a letter after the "=" seems to make selection via arrow keys work again, for example type
type=tand selection via keyboard works - seems the attribute values hints don't work at all in the theme/plugin editors, where typing for example
<input type=does nothing - doesn't seem to happen in the Additional CSS in the Customizer, where all the hints appear to be operable with a keyboard
I'm really not sure if this is related to something specific to the HTML widget or if it's something that should be fixed upstream. Setting the "Widgets" component for now.
Attachments (1)
Change History (28)
This ticket was mentioned in Slack in #accessibility by afercia. View the logs.
8 years ago
#2
@
8 years ago
- Keywords needs-patch added
- Milestone changed from Awaiting Review to Future Release
This ticket was mentioned in Slack in #accessibility by afercia. View the logs.
8 years ago
This ticket was mentioned in Slack in #accessibility by rianrietveld. View the logs.
7 years ago
This ticket was mentioned in Slack in #core by jorbin. View the logs.
10 months ago
#6
follow-up:
↓ 7
@
10 months ago
- Keywords needs-testing added
There is some hope that this is fixed upstream in CodeMirror which #48456 aims to upgrade. That's not a small task and will require an owner to see it through. Alternatively, it may make sense to move to something else entirely (see GB#10423) for the project. Also, this is not currently the default experience, it's only the experience if you install the classic widgets plugin.
This also seems to be inconsistent and could use more testing to reliably determine in what cases this takes place (is it just widgets? Is it the theme/plugin editor as well?)
#7
in reply to:
↑ 6
@
10 months ago
- Keywords needs-test-info added; needs-testing removed
Replying to jorbin:
This also seems to be inconsistent and could use more testing to reliably determine in what cases this takes place (is it just widgets? Is it the theme/plugin editor as well?)
Wrong workflow keyword, I think you meant, needs-test-info (aka we need more use-cases). Switching.
#8
@
6 weeks ago
It seems this isn't fixed with the latest v5 (#48456).
It is fixed in v6, however: https://codemirror.net/examples/autocompletion/
#10
@
6 weeks ago
- Component changed from General to Widgets
This bug actually looks incredibly similar to #63161.
@
6 weeks ago
First draft of a fix. Note that I've only tested it with the old version of CodeMirror - I haven't tested it with the new version. So don't merge this (yet).
#12
@
6 weeks ago
- Milestone changed from Future Release to 7.0
The duplicate of this ticket was milestoned for 7.0; milestoning this one.
#13
@
6 weeks ago
In response to @jorbin's earlier question: yes, this also happens in the theme/plugin editor, for PHP files. (Which is the duplicate issue I closed for this one.) I'm operating on the assumption that it's the same root issue.
It does *not* happen for CSS or JS.
This ticket was mentioned in PR #10807 on WordPress/wordpress-develop by @joedolson.
6 weeks ago
#14
- Keywords has-patch added; needs-patch removed
Uses the work from @siliconforks, and adds a fix for PHP editors.
Trac ticket: https://core.trac.wordpress.org/ticket/42822
#15
@
6 weeks ago
@siliconforks Can you chime in on the PR to explain the reasoning behind the changes? How do they fix the problems?
@siliconforks commented on PR #10807:
6 weeks ago
#16
Just to summarize the situation ... there are two (actually three) separate fixes required here:
- The main problem in #63161 and #42822 is that
codemirror.showHint()is getting called every time the up arrow or down arrow key is pressed. This means that the autocomplete list gets refreshed and the first item gets selected (again), so it is impossible to use the arrow keys to move to any other item - the first item just keeps getting re-selected. To fix this, a condition needs to be added checking which key was pressed. Note that this is already done for CSS and JavaScript autocompletion - the code checks whetherisAlphaKeyis true orevent.keycontains some other character which should trigger autocompletion. By adding theisAlphaKeycondition to the PHP autocompletion code, we should fix the issue in #63161.
- The problem for HTML autocompletion in #42822 is almost exactly the same thing - the code is not checking which key was pressed. Actually, it is slightly more complicated because the code for HTML autocompletion really has five separate conditions all joined together with the
||operator. The first four conditions appear to be fine - they already check which key was pressed. The fifth condition (which handles HTML attribute value autocompletion) is the problem - it apparently never had a check for this. By adding a check forevent.key === '=', we should fix the HTML autocompletion.
- The final problem appears to be a separate bug not really related to the first two - it seems that CodeMirror has changed the structure of the
token.stateobject. When this code was first written (in r41376), there was atoken.state.htmlStateproperty. At some point CodeMirror changed this so that this property no longer exists. Instead they added atoken.state.curState.htmlStateproperty andtoken.state.html.htmlStateproperty, which appear to be the same thing.
@westonruter - are you testing with the old version of CodeMirror (the one that shipped with WordPress 6.9) or the newer version of CodeMirror (the one you're working on upgrading to in #48456)?
@westonruter commented on PR #10807:
6 weeks ago
#17
are you testing with the old version of CodeMirror (the one that shipped with WordPress 6.9) or the newer version of CodeMirror (the one you're working on upgrading to in #48456)?
@siliconforks I'm testing with the latest CodeMirror v5 as Core-48456 was committed (438132fd3658943b02fa382be8990bf8ad61c245) and is part of this PR's commit history.
@westonruter commented on PR #10807:
6 weeks ago
#18
For reference, in the latest CodeMirror, here's what a token contains when editing an HTML file at the moment that = is pressed when typing out <input type=:
{
"start": 11,
"end": 12,
"string": "=",
"type": null,
"state": {
"inTag": null,
"localMode": null,
"htmlState": {
"indented": 0,
"tagName": "input",
"tagStart": 0,
"context": null
}
}
}
@siliconforks commented on PR #10807:
6 weeks ago
#19
On further investigation, it looks like I was wrong about CodeMirror changing the token structure in different versions - it's not actually a version issue, it's an issue with different modes:
- If you edit a .html file, you get a
token.state.htmlState.tagNameproperty. - If you edit a .php file, you get a
token.state.curState.htmlState.tagNameproperty and atoken.state.html.htmlState.tagNameproperty.
So, the it seems that the code needs to handle both cases.
This should work:
shouldAutocomplete = (
'<' === event.key ||
( '/' === event.key && 'tag' === token.type ) ||
( isAlphaKey && 'tag' === token.type ) ||
( isAlphaKey && 'attribute' === token.type ) ||
/*
* In .html files the tag name is in token.state.htmlState.tagName;
* in .php files the tag name is in token.state.curState.htmlState.tagName.
*/
( '=' === event.key && '=' === token.string && ( token.state.htmlState?.tagName || token.state.curState?.htmlState?.tagName ) )
);
@westonruter commented on PR #10807:
5 weeks ago
#20
@siliconforks And what purpose does ( token.state.htmlState?.tagName || token.state.curState?.htmlState?.tagName ) serve? Just to verify that the token is in the context of a tag?
@siliconforks commented on PR #10807:
5 weeks ago
#22
@siliconforks And what purpose does
( token.state.htmlState?.tagName || token.state.curState?.htmlState?.tagName )serve? Just to verify that the token is in the context of a tag?
Yes, I'm assuming the original code (token.state.htmlState && token.state.htmlState.tagName) was there simply to avoid the possibility of autocompletion being triggered by an equals sign outside a tag. But it was also having the effect of preventing autocompletion _inside_ a tag in .php files (although it seemed to be working fine for .html files). That's why I'm suggesting changing it to ( token.state.htmlState?.tagName || token.state.curState?.htmlState?.tagName ).
@westonruter commented on PR #10807:
5 weeks ago
#23
That's why I'm suggesting changing it to
( token.state.htmlState?.tagName || token.state.curState?.htmlState?.tagName ).
OK, I applied that change in 8cd4589. Please test.
@westonruter commented on PR #10807:
5 weeks ago
#25
Committed in r61579 (7965dec)


Agreed during today's bug-scrub this is something that should be fixed, hopefully by someone more familiar with CodeMirror and the HTML widget. Moving to future release. /cc @westonruter