w3c / input-events

Input Events
https://w3c.github.io/input-events/
Other
23 stars 16 forks source link

[beforeinput] Add InputType 'deleteByKill', 'insertFromYank' and 'transpose' #20

Closed johanneswilm closed 7 years ago

johanneswilm commented 7 years ago

From @choniong on August 24, 2016 15:58

On MacOS the hotkey ctrl-t will transpose the two character besides cursor (Chrome and Safari), e.g.

  1. a|b => ba|
  2. ab|$ => ba|$

Should we:

  1. Create a separate InputType, or
  2. Just fire insertText with the target range?

Copied from original issue: w3c/editing#148

johanneswilm commented 7 years ago

What is the usecase for this? Typing errors?

johanneswilm commented 7 years ago

From @choniong on August 24, 2016 19:37

Did some search and cannot find more info about it...(I don't actually use it) Should just be the emacs style hotkeys in Mac OS (similar to ctrl-k for Kill and ctrl-y for Yank).

I think it's not worth adding new InputTypes since nobody uses it (I assume?), but as they are modifying DOM we should at least have some notes about the expected events, e.g.:

  1. Fire InputType=deleteContentForward for Kill
  2. Fire InputType=insertText for Yank
  3. Fire InputType=insertText with target ranges for Transpose
johanneswilm commented 7 years ago

I think it's not worth adding new InputTypes since nobody uses it (I assume?)

I think this has to depend on, whether someone uses it (as you say) and whether this functionality can be interpreted in some way to make a change of semantic significance that applies to a different range than the default handling. For example, how does ctrl+t behave around element boundaries? Does it only ever make changes within a single text node?

johanneswilm commented 7 years ago

From @choniong on August 24, 2016 20:28

For example, how does ctrl+t behave around element boundaries?

It won't pass editing boundary nor paragraph boundary.

Does it only ever make changes within a single text node?

It could pass <b> or <i>, and does the similar thing as select and paste reversed plaintext.

Apple's reference NSResponder - transpose:.

johanneswilm commented 7 years ago

It could pass <b> or <i>, and does the similar thing as select and paste reversed plaintext.

I see. Then this may be somewhat more complicated. Element boundaries have at times a meaning within the editor that the browser isn't aware of.

Say for example, that a particular editor puts span-elements around all words or syllables if the word is longer than ten letters for the purpose of tracking their position or alike. As long as the spans are not styled, the end user doesn't notice this. If now the user intents to "transpose" two characters, but the JS doesn't ever know that this was the intention of the end user and instead only gets to know that the end user has asked for changing some things in and out of two span-elements that happen to end/start in-between the two letters in question, this could lead to all kinds of misunderstandings. Does this makes ense?

So I would say this has to get its own intention. Same with yank/kill. It doesn't take that much for us to define them, and if Apple finds out that really no-one uses them, they can remove them from Mac OS X and we can remove them from a future version of the spec.

johanneswilm commented 7 years ago

From @choniong on August 24, 2016 21:15

Say for example, that a particular editor puts span-elements around all words or syllables if the word is longer than ten letters for the purpose of tracking their position or alike. As long as the spans are not styled, the end user doesn't notice this. If now the user intents to "transpose" two characters, but the JS doesn't ever know that this was the intention of the end user and instead only gets to know that the end user has asked for changing some things in and out of two span-elements that happen to end/start in-between the two letters in question, this could lead to all kinds of misunderstandings. Does this makes ense?

OK, so for example the default behavior for Transpose is similar to Paste

JS might want to detect Transpose and override it to

So I would say this has to get its own intention. Same with yank/kill. It doesn't take that much for us to define them, and if Apple finds out that really no-one uses them, they can remove them from Mac OS X and we can remove them from a future version of the spec.

OK, so how about:

  1. deleteByKill (similar to cut)
  2. insertFromYank (similar to paste)
  3. transpose
johanneswilm commented 7 years ago

OK, so for example the default behavior for Transpose is similar to Paste

  • Bold|Italic -> BolId|talic (Where I was moved into <b>)

JS might want to detect Transpose and override it to

  • Bold|Italic -> BolId|talic (Swap character but keeps style)

That's possible. I was thinking of a case such as:

...<span data-element="101" data-length="3">pic|</span><span data-element="102" data-length="4">ture</span>...

The spans above are something used by the JS editor and what the meaning of data-element and data-length is only clear to the JS. The browser doesn't know what this is. So say the user now hits ctrl+t. The browser may think it can join the two spans or maybe move one extra letter into the first span without increasing the data-length attribute of one and increase the one of the other. So this will have to be handled by JS. But if the JS only receives a beforeinput replaceContent event which says that the user intents to do some complex changes to the two spans, it may be quite difficult for the JS to understand that this was really about transposing.

OK, so how about:

  1. deleteByKill (similar to cut)
  2. insertFromYank (similar to paste)
  3. transpose

That sounds good to me.

johanneswilm commented 7 years ago

@choniong: I have not yet added the deleteByKill inputtype. Reading through Apple's documentation, it seems like several operations can place things on the kill buffer. I wonder if adding to the kill buffer is something that happens for all delete word, line, etc. inputtypes?

chong-z commented 7 years ago

I have not yet added the deleteByKill inputtype. Reading through Apple's documentation, it seems like several operations can place things on the kill buffer. I wonder if adding to the kill buffer is something that happens for all delete word, line, etc. inputtypes?

Yes you are right (sorry for the confusion, I don't actually use Kill/Yank):

And ctrl-k is actually bind to - deleteToEndOfParagraph:, which will delete across soft break.

johanneswilm commented 7 years ago

And ctrl-k is actually bind to - deleteToEndOfParagraph:, which will delete across soft break.

This is as I had understood it earlier, but I wonder if this is simply a bug or if I misunderstood something. Is it correct that deleting backward, one can only delete to the start of the line, whereas forward one can only delete to the end of the paragraph? This seems asymmetric.

johanneswilm commented 7 years ago

Yes you are right (sorry for the confusion, I don't actually use Kill/Yank):

Ok, so this looks fairly similar to the clipboard. If we want to be super consistent, then that means that preventDefaulting any of these delete actions will not not cancel moving things to the kill buffer. The only difference is that we don't currently have events for moving things to the kill buffer, right? But I guess it'll be OK for now as we can cancel things when they are being inserted ("yanked").

At some stage the event order with putting things in the kill buffer and the beforeinput event needs to be defined.

For now we may not have to do anything more to the text. I should add notes to explain that preventing cut doesn't prevent cut and possibly that the above mentioned may add things to the kill buffer on some platforms and that also this isn't prevent when preventDefaulting.

chong-z commented 7 years ago

Is it correct that deleting backward, one can only delete to the start of the line, whereas forward one can only delete to the end of the paragraph? This seems asymmetric.

Seems true to me:

  1. command-delete deletes to the start of the line
  2. ctrl-k deletes to the end of paragraph

And I cannot find hotkeys for deleting to the end of the line or the start of the paragraph on mac OS or Emacs (I would expect fn-command-delete to work).

Ok, so this looks fairly similar to the clipboard. If we want to be super consistent, then that means that preventDefaulting any of these delete actions will not not cancel moving things to the kill buffer. The only difference is that we don't currently have events for moving things to the kill buffer, right? But I guess it'll be OK for now as we can cancel things when they are being inserted ("yanked"). This buffer only exists on a per site basis and is being cleaned every time someone reloads the page? And it's not working across tabs or across applications? (I hope)

Also looks true to me, I guess both canceling Kill or not is fine, JS can always implement Kill/Yank easily.

johanneswilm commented 7 years ago

This manual [1] seems to indicate that when enabling soft-wrapping in Emacs, ctrl-k will delete to end of line, not paragraph. When soft-wrapping isn't enabled, deleting to the end of line or paragraph will be the same thing anyway. In browsers we usually have soft-wrapping enabled. So it seems that if we wanted to be consistent with that, we should go with the line ending as well. But maybe we need to be consistent with something else as well?

[1] https://www.gnu.org/software/emacs/manual/html_node/emacs/Visual-Line-Mode.html#Visual-Line-Mode

johanneswilm commented 7 years ago

@choniong Is it possible at all that the ctrl-k shortcut on mac is linked incorrectly? Does this apply to all browsers, or just Chrome/Webkit?

chong-z commented 7 years ago

Sorry for the late reply.

From my testing on Firefox for Mac

On Chrome/Webkit and mac OS native apps (TextEdit, Notes)

I'm guessing Firefox is incorrect, but it shouldn't matter since the browser should just fire what it does.

If our goal is to list all inputTypes that at least one browser supports, we should add

johanneswilm commented 7 years ago

For ctrl-k Firefox does what it seems to me emacs does and which seems to be the more logical behavior...

However, given that also the native app behavior is different, I agree that we need to go with that.

If our goal is to list all inputTypes that at least one browser supports, we should add

  • deleteParagraphBackward (and forward?)

Unless we can think of a good reason why this should only exist for going backward, I would prefer having it be symmetrical. On the other hand, if no browser supports it, it may just confuse JavaScript developers if they work on creating functionality for a specific inputtype, only to discover later that it's not being used at all. AT least we need to make sure that sites such as caniuse list which inputtypes are not used.

  • deleteEntireLineBackward?

By "entire line backward" you mean delete the line the caret is on both backward and forward? Or is it the equivalent of an entire line going backward?

  • insertFromYank

I've added this one.

chong-z commented 7 years ago

Unless we can think of a good reason why this should only exist for going backward, I would prefer having it be symmetrical. On the other hand, if no browser supports it, it may just confuse JavaScript developers if they work on creating functionality for a specific inputtype, only to discover later that it's not being used at all. AT least we need to make sure that sites such as caniuse list which inputtypes are not used.

Yes I agree we should have both forward and backward, and maybe have an example/notes section listing known hotkeys.

By "entire line backward" you mean delete the line the caret is on both backward and forward? Or is it the equivalent of an entire line going backward?

It's deleting both backward and forward, e.g. On Firefox ctrl-k

I added Backward to deleteEntireLine(better name?) because it reminds me the menu bar delete issue, where the conclusion is JS always wants a direction.

But actually we don't have direction for deleteByDrag and deleteByCut right?

johanneswilm commented 7 years ago

I added Backward to deleteEntireLine(better name?) because it reminds me the menu bar delete issue, where the conclusion is JS always wants a direction.

That makes sense.

But actually we don't have direction for deleteByDrag and deleteByCut right?

We don't. I wonder if it because there is a general idea that the default deletion is backward. But if this is the case, it should likely be noted somewhere.

johanneswilm commented 7 years ago

How about using "deleteBlockBackward" or similar instead of "deleteParagraphBackward" to make clear that it also works in things other than <p>-elements?

johanneswilm commented 7 years ago

Delete Line backward could also have meant that

1234567890
abcd|efghijkl

becomes

1234|efghijkl

That's why I was asking.

chong-z commented 7 years ago

Sorry actually please ignore the example '^abc|def$' becomes '^|$' as it's not accurate.

Just to confirm we are in the same page, my proposal is:

e.g. In a narrow box

<p>
This is a
very v|ery
long line.
<br>
This is
another
line.
</p>

Press ctrl-k on Webkit

<p>
This is a
very v|
<br>
This is
another
line.
</p>
johanneswilm commented 7 years ago

Ok, I have tested it myself now.

  • Webkit command-delete (deleteLineBackward) stops at line wrap
    • deleteSoftLineBackward?
  • Firefox command-delete (deleteEntireLine) stops at line wrap
    • deleteEntireSoftLine?
  • ctrl-k aka. deleteBlockForward will stop at <br>, </p> or \n
    • deleteHardLineForward?

Yes, let's use the terms deleteSoftLineBackward, deleteEntireSoftLine and deleteHardLineForward for now.