Blocks: Select ALL on Ctrl+A outside editable DOM elements#1211
Blocks: Select ALL on Ctrl+A outside editable DOM elements#1211youknowriad merged 4 commits intomasterfrom
Conversation
aduth
left a comment
There was a problem hiding this comment.
Noting that this takes over select-all for the entire screen, which may be what we're expecting. Try Cmd-A on any page (including this GitHub page) to see the effect I'm illustrating.
| */ | ||
| import { __ } from 'i18n'; | ||
| import { Component, findDOMNode } from 'element'; | ||
| import { LETTER_A, SMALL_LETTER_A } from 'utils/keycodes'; |
There was a problem hiding this comment.
Two things:
- Maybe
LOWER_LETTER_A(lowercase, uppercase distinction) - Do we need to capture uppercase A? Cmd-Shift-A is not typically a valid combination for Select All behavior.
There was a problem hiding this comment.
Actually, I'm going to use only LETTER_A because there's no difference between the two in keydown events. (The keycode is the same)
|
|
||
| onKeyDown( event ) { | ||
| const { uids } = this.props; | ||
| const isEditable = [ 'textarea', 'input', 'select' ].indexOf( document.activeElement.tagName.toLowerCase() ) !== -1 |
There was a problem hiding this comment.
Starting to see these conditions pop up in a few PRs with minor variations. Seems prone to edge cases or errors. Tested utilities might be more appropriate.
Wondering if there's another way to test here:
- If there's no
activeElement(or is the default,document.bodyI think) - If there's no focused blocks
There was a problem hiding this comment.
The idea was to enable Ctrl+A even if we're focusing a button or any focusable but not editable. We could restrict to document.body of course.
There was a problem hiding this comment.
I'm still a bit hesitant about this logic. Do you think this should be in a utility class, e.g. isActiveElementEditable, or isEditableElement( document.activeElement ) ?
I'd found that in some browsers, window.getSelection() has a type property against which we could perhaps test === 'caret' for reasonable accuracy, but unfortunately not all browsers define this property:
https://developer.mozilla.org/en-US/docs/Web/API/Selection/type
|
This is really really really nice! Thanks for working on it. ⌘ A inside a block selects all there, ⌘ A outside, selects all blocks.
I could go either way on this one. On the one hand, having it be unrestricted (i.e. ⌘ A no matter what has focus, unless of course it's inside a textarea selects all blocks) is similar to many desktop apps, even ones that have served in part as inspiration for some of our efforts, like Sketch. On the other hand, it's a non-standard web-page behavior. So which are we more, an app, or a web-page? I'm leaning towards the former, i.e. keeping the behavior as is. One thing though — it would be nice (not super important, can be separate PR, low priority), if clicking anywhere outside the selected blocks deselected. Right now you can press the white area outside of the blocks to deselect. It'd be nice if you could also click the empty space under the sidebars. But I'd like a sanity check. @melchoyce @folletto any thoughts? Here's a video where I talk over: https://cloudup.com/csoAyszQ-Bf |
|
The interaction feels nice! I like the top bar with the number of blocks selected and "delete." Only weird thing IMO is copying the blocks, copies the HTML. I expected it to just copy the text of the blocks so I could paste it into another text editor. |
This has implications, because we want to keep selection if we click the inserter and post settings. I think the "deselection" behaviour should be addressed separately, it's more complex than it seems. Should we merge here? |
|
I'm okay with merging, if there are no code objections. |
| export const RIGHT = 39; | ||
| export const DOWN = 40; | ||
| export const DELETE = 46; | ||
| export const LETTER_A = 65; |
There was a problem hiding this comment.
Where we can, would it be better to calculate for clarity? Also maybe it's better to call it CHAR_A (broader collection)?
export const CHAR_A = 'A'.charCodeAt(0);Here is some useful info on using event.keyCode: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode. Could we use event.key instead? https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
There was a problem hiding this comment.
I recall discussions about compatibility issues for event.key in some browsers. cc @aduth
And we're using keyCode everywhere now.
There was a problem hiding this comment.
Related: #1215 (comment)
Not sure what the issues are with IE11 and "non-standard key identifiers", also only available in latest iOS version, which violates documented browser support.
|
Nice one! 👍 I +1 Mel's comment. ;) |
Yes, Copy/Paste need more ❤️ and is tracked here #943 |
| || document.activeElement.isContentEditable; | ||
| if ( | ||
| ! isEditable && | ||
| ( event.ctrlKey || event.metaKey ) && |
There was a problem hiding this comment.
A bit unexpected that Ctrl-A on Mac will select all (not default behavior), but trying to distinguish by OS seems to devolve into absurdity quite quickly, so I'm not sure we care to spend the effort.
There was a problem hiding this comment.
Is event.metaKey defined by other OSs? If not, we could look at that.
There was a problem hiding this comment.
On Windows, it's the Windows key (⊞), and conversely ⊞+a is not a valid "select all" combination.
There was a problem hiding this comment.
I suppose in windows, it won't trigger because it triggers the "start" menu?
There was a problem hiding this comment.
trying to distinguish by OS seems to devolve into absurdity quite quickly, so I'm not sure we care to spend the effort
😆
There was a problem hiding this comment.
Ok let's get this merged then :). An approval?
|
|
||
| onKeyDown( event ) { | ||
| const { uids } = this.props; | ||
| const isEditable = [ 'textarea', 'input', 'select' ].indexOf( document.activeElement.tagName.toLowerCase() ) !== -1 |
There was a problem hiding this comment.
I'm still a bit hesitant about this logic. Do you think this should be in a utility class, e.g. isActiveElementEditable, or isEditableElement( document.activeElement ) ?
I'd found that in some browsers, window.getSelection() has a type property against which we could perhaps test === 'caret' for reasonable accuracy, but unfortunately not all browsers define this property:
https://developer.mozilla.org/en-US/docs/Web/API/Selection/type
closes #3
So basically, I'm listening to all Ctrl+A and Command+A events and if the active element is not editable (is not an input, textarea, select or contenteditable), I trigger a global multi selection.