Open chong-z opened 8 years ago
RESOLUTION: Yes we can do the issues 33/34 proposal for cancelable at each end of IME. https://www.w3.org/2016/09/22-webapps-minutes.html#resolution02
@choniong I tried to add a non-normative note in humanly readable language about how the beforeinput events should relate to IME composition [1]. This is meant largely for JavaScript developers who try to built their apps on top of the spec. Some terms still need to be linked to the p[roper definitions, but let me know if this is more or less correct.
Thanks for the explainer, that's really helpful!
Just a small concern about
4.. ...or a part of it does while another part of the composition string continues to be composed in the IME...
This feels confusing to me, as there is actually no way for IME to remove/commit part of the composition. What Japanese IME doing is just commit the original composition and start a new one (although visually looks weird, it actually makes sense from JS's side), and JS shouldn't need to be aware of it as long as they have the implementation for normal IME.
If we really want to mention the Japanese IME case, would it be better to put it into a separate note, and have the current note only for atomic actions?
@choniong I see. yes that can be confusing. I agree that it would be better to have two different notes. But also I think I misunderstood part of this for these Japanese IMEs:
So in the case of this Japanese IME, when this happens, how many beforeinput events do we get whent his happens? Do we get
?
If this is the case, I think this can be problematic if the JS handles step 2 and inserts the string in a way the browser doesn't expect, because that will mean it won't know what it can delete in step 3. Of course, the JS could simply handle both 2 and 3, but the JS doesn't know which part of the string will be moved back into the DOM.
That's why I thought that it would only move that part into the DOM in step 2 that is finished and can be committed.
Is there any way we can expose which part of the string is done and can be committed permanently in step 2?
So during a single keydown/up
, there will be 1 compositionend
and 1 new compositionstart
.
deleteCompositionText
- One, for the first compositioninsertFromComposition
- One, for the first compositiondeleteByComposition
- NoneinsertCompositionText
- One, for the second compositionHere is the expected event order for pressing 'a'
when the marked text is 'あああああああああああああ' (x13), the result is 2 committed 'あ' and 12 marked 'あ'.
Event | InputType/data | DOM | Notes |
---|---|---|---|
keydown | 'a' | 'あああああああああああああ' x13 | This key will cause 'partial commit' |
beforeinput | 'deleteCompositionText' | 'あああああああああああああ' | About to commit composition 1, clearing marked text |
compositionupdate | '' | 'あああああああああああああ' | |
input | 'deleteCompositionText' | '' | |
-Important- beforeinput | 'insertFromComposition', 'ああ' | '' | 'partial commit' first 2 characters, no 'compositionupdate' |
input | 'insertFromComposition' | 'ああ' | |
compositionend | 'ああ' | 'ああ' | 'Composition 1, commit 2 characters' |
--Just-- | --A-- | --hr-- | ---- |
compositionstart | '' | 'ああ' | 'Start composition 2' |
beforeinput | 'insertCompositionText', 'ああああああああああああ' | 'ああ' | Re-insert leftover text |
compositionupdate | 'ああああああああああああ' | 'ああ' | |
input | 'insertCompositionText' | 'ああああああああああああああ' x14 | The rear 12 characters are composition |
keyup | 'a' | 'ああああああああああああああ' x14 | All of this happens in one keydown/up |
@choniong Ah sorry. Then I had understood you correctly the first time and it's all not a problem. Then it's all a matter of turning 1 note into 2 notes. I will make sure to do that. I have tried to avoid such words as "commit" or say they will become part of the "permanent DOM" as that may invoke wrong connotations. But now I am thinking maybe we need to use the term "commit" and then add a description for it.
The point of this exercise is of course to make IME handling so obvious and easy to the JS readers of the spec that they all will do it. For that purpose: could I include your above example as well?
Yep sure.
Just want to conclude, my point is: JS doesn't need to have any knowledge about Japanese IME, all they need to do is to handle those 4 inputTypes, and there is no special cases.
Just want to conclude, my point is: JS doesn't need to have any knowledge about Japanese IME, all they need to do is to handle those 4 inputTypes, and there is no special cases.
Yes, I get it now. The thing I wasn't sure about was whether it would reinsert the entire composition string and then delete just the part that needs to go into the next composition. That's what I feared after I read
What Japanese IME doing is just commit the original composition and start a new one
But with your example you made it clear that only the part that is final goes into the first 'insertFromComposition'. That way it's all quite easy for JS. In many cases, JS developers only need to listen to 'deleteByComposition' and 'insertFromComposition', handling those themselves and recording them in their undo stack.
Reopened because the event order should probably be added as normative text to a spec. For example tge new event order spec, @garykac?
And the example could be added to the input events spec.
@choniong What do you think should happen in these cases:
beforeinput - 'deleteByComposition'
but does make changes to the DOM that possibly interrupt the range which covers the initial composition string?beforeinput - 'deleteByComposition'
and does some changes to the selection and the DOM which mean that the selection is not collapsed or there is no selection at the end of the JS function that handles the event?beforeinput - 'insertFromComposition'
in the case where only part of the string is submitted.All these are situations which JS may mess up and I think it's totally fine to say that JS is responsible for leaving a collapsed selection for or else the site simple doesn't work as expected. But I'm a bit afraid that if for example Chrome and Firefox coincidentally end up implementing this in a way where removing the selection in the code that handles 'deleteByComposition'
leads to the IME process being cancelled, JS developers will discover that and start depending on this behavior.
That's some difficult situations, and I'm afraid it will cause more potential issues by splitting the first text replacing into 'deleteByComposition'
and 'insertCompositionText'
.
Do you think it would be better to make 'deleteByComposition'
as a flag and only do real mutation in the next event? e.g.
'deleteByComposition'
doesn't have default action by it self
'insertCompositionText'
will collapse selection forward and insert marked text.'insertCompositionText'
will replace selection, similar to current IME behavior.Do you think it would be better to make
'deleteByComposition'
as a flag and only do real mutation in the next event?
I would prefer to keep things as they are now if at all possible, as it's quite easy to understand. JS editor developer should be perfectly capable of ensuring that they leave a collapsed selection and to remove all that is is covered by the target ranges. But we should still spec what happens in those situations. One simple solution would be to say that the composition is canceled automatically if there is no collapsed selection at the end of those JS functions. But that would break a bit with the principle that canceling beforeinput events only prevents DOM changes.
Or are there other reasons why you would prefer to unite the two dom changes? I don't think it would be a huge issue either, as JS should still be able to do everything in more or less the same way. The only "odd" thing would be that the second beforeinput event will be called before any of the DOM has changed, right?
Original Discussion https://github.com/w3c/editing/issues/118#issuecomment-209646801 We want
'deleteComposedCharacter'
during composition because of it's special non-cancelable attribute.Issues
'insertText'
during composition is also non-cancelable, do we want'insertCompositionText'
?'deleteComposedCharacter'
is not so helpful as Chrome (and maybe WebKit) always replace the entire composition textProposal
'deleteByComposition'
, fired before'compositionstart'
, cancelable'insertCompositionText'
, fired during composition, non-cancelable'deleteCompositionText'
, fired before'compositionend'
, non-cancelable'insertFromComposition'
, fired between iii. and'compositionend'
, cancelableDefault Action
'deleteByComposition'
'insertCompositionText'
will pre-insert selected text in certain cases'insertCompositionText'
'deleteCompositionText'
'insertFromComposition'
Example Order
Example of Recomposition on Android
'beforeinput'
'deleteByComposition'
'input'
'deleteByComposition'
'compositionstart'
'beforeinput'
'insertCompositionText'
'compositionupdate'
'input'
'insertCompositionText'
'beforeinput'
'insertCompositionText'
'compositionupdate'
'input'
'insertCompositionText'
'beforeinput'
'deleteCompositionText'
'compositionupdate'
'input'
'deleteCompositionText'
'beforeinput'
'insertFromComposition'
'input'
'insertFromComposition'
'compositionend'