Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blocks: Select ALL on Ctrl+A outside editable DOM elements #1211

Merged
merged 4 commits into from
Jun 22, 2017

Conversation

youknowriad
Copy link
Contributor

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.

@youknowriad youknowriad self-assigned this Jun 16, 2017
Copy link
Member

@aduth aduth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.


/**
* WordPress dependencies
*/
import { __ } from 'i18n';
import { Component, findDOMNode } from 'element';
import { LETTER_A, SMALL_LETTER_A } from 'utils/keycodes';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

@@ -40,6 +52,20 @@ class VisualEditor extends Component {
}
}

onKeyDown( event ) {
const { uids } = this.props;
const isEditable = [ 'textarea', 'input', 'select' ].indexOf( document.activeElement.tagName.toLowerCase() ) !== -1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.body I think)
  • If there's no focused blocks

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@jasmussen
Copy link
Contributor

This is really really really nice! Thanks for working on it.

⌘ A inside a block selects all there, ⌘ A outside, selects all blocks.

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.

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.

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

@melchoyce
Copy link
Contributor

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.

@youknowriad
Copy link
Contributor Author

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.

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?

@jasmussen
Copy link
Contributor

I'm okay with merging, if there are no code objections.

@@ -7,3 +7,4 @@ export const UP = 38;
export const RIGHT = 39;
export const DOWN = 40;
export const DELETE = 46;
export const LETTER_A = 65;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recall discussions about compatibility issues for event.key in some browsers. cc @aduth
And we're using keyCode everywhere now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@folletto
Copy link
Contributor

Nice one! 👍

I +1 Mel's comment. ;)

@youknowriad
Copy link
Contributor Author

youknowriad commented Jun 19, 2017

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.

Yes, Copy/Paste need more ❤️ and is tracked here #943

|| document.activeElement.isContentEditable;
if (
! isEditable &&
( event.ctrlKey || event.metaKey ) &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is event.metaKey defined by other OSs? If not, we could look at that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Windows, it's the Windows key (), and conversely +a is not a valid "select all" combination.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose in windows, it won't trigger because it triggers the "start" menu?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😱

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trying to distinguish by OS seems to devolve into absurdity quite quickly, so I'm not sure we care to spend the effort

😆

Copy link
Contributor Author

@youknowriad youknowriad Jun 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok let's get this merged then :). An approval?

@@ -40,6 +52,20 @@ class VisualEditor extends Component {
}
}

onKeyDown( event ) {
const { uids } = this.props;
const isEditable = [ 'textarea', 'input', 'select' ].indexOf( document.activeElement.tagName.toLowerCase() ) !== -1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@ellatrix ellatrix mentioned this pull request Jun 21, 2017
20 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

“Select All” behavior
6 participants