whatwg / html

HTML Standard
https://html.spec.whatwg.org/multipage/
Other
8.12k stars 2.67k forks source link

contenteditabledisabled attribute to control browser editing UI #5863

Open gked opened 4 years ago

gked commented 4 years ago

Hi all,

We've been working on adding a new attribute contenteditabledisabled to control browser editing UI. Specifically, a way to disable undesired browser UI in cases where editors do not support it.

We wanted to get your feedback on the shape of an API and approach we are taking. Secondly, the question was brought up whether this (all or some parts of the proposal) should live in Html spec.

The idea is to provide web authors a way to query and specify what editing commands should be disabled by a browser. Here is the code sample from the draft of how we envision this to happen:

<div contenteditable="true" contenteditabledisabled="
    formatbackcolor
    formatdent
    formatfont
    formatjustify
    formatscript
    formatstrikethrough
    formatunderline
    inserthorizontalrule">
    This is a contenteditable region of a document that supports:
    <ul>
        <li>bold text</li>
        <li>italic text</li>
        <li>links</li>
        <li>lists</li>
        <li>and possibly other formatting outside the scope of this specification.</li>
    </ul>

    This contenteditable region explicitly does not support:
    <ul>
        <li>background colors</li>
        <li>indentation</li>
        <li>font name, size or color customization</li>
        <li>justification</li>
        <li>superscript or subscript text</li>
        <li>strikethrough</li>
        <li>underlines</li>
        <li>horizontal rules</li>
    </ul>
</div>

Outstanding PR with detailed information for your reference: https://github.com/w3c/editing/pull/265.

Thank you

P.S. There is another piece, currently missing from the spec a way for authors to query what commands are currently enabled. Tracked here

domenic commented 4 years ago

Thanks for filing this issue for cross-coordination!

The shape of this API looks reasonable. The token names are a bit strange but I see that they match the "inputType" column in https://w3c.github.io/editing/docs/execCommand/#dfn-map-an-edit-command-to-input-type-value. (Question: why not the shorter "edit command" column values?) It will also be important to specify the case-sensitivity or insensitivity of these tokens; I think it'd be fine for them to be (ASCII) case-insensitive to match things like <link>'s rel="".

New HTML attributes should indeed be defined in the HTML Standard. In this case the https://html.spec.whatwg.org/#contenteditable section would be the right place.

johanneswilm commented 4 years ago

@domenic There is a big disclaimer at the top of the execCommand spec on how this is not currently the recommended way of creating editors. The table you are looking at there is the mapping of the old execCommand commands to the inputTypes of newer input events spec [1] that we are currently moving through the W3C process. There is no equivalent to the edit command in the input events spec and as we expect this to be used together with the input events spec rather than the execCommand spec, we use the values of inputEvents rather than execCommand commands.

[1] https://www.w3.org/TR/input-events-1/

gked commented 4 years ago

@domenic thank you for your response. I can start working on the PR against HTML spec. I'll update the wording for case sensitivity there as well.

Also, does @johanneswilm 's explanation suffice or would you want to us to explore updates to naming?

johanneswilm commented 4 years ago

Additionally: The values for the inputTypes were chosen so that a JS editor could filter based on the prefix. And that same advantage would be here. For example, if you want to create a JS editor that takes away all formatting related UI, you could do something like:

const editorDom = document.querySelector('#editor')
const supportedValues = editorDom.contenteditableDisabled.supported.split(' ')
const disabledValues = supportedValues.filter(value => value.slice(0, 6) === 'format')
editorDom.contenteditableDisabled.add(...disabledValues)

Also the values in input events correspond to things that browsers actually offer to end users - often by means of UI. So that fits well what we are trying to do here in that we want to disable that UI.

This is different from execCommand, which is a way for JavaScript to do some action on the DOM for which there may or may not exist a UI for the user to execute this same action, right?

domenic commented 4 years ago

I don't see why we invented a second set of types. execCommand() is an established API that all browsers support. Is the same true of the new API? If so, it's a real shame that we duplicated the concepts with slightly longer and more annoying to use names; I'm not sure we should carry that forward. If it's not yet supported in all browsers, then we should be sure not to spread this bifurcation into contenteditabledisabled="".

In particular, I don't see why formatBold or formatbackcolor "corresponds to things that browsers actually offer to end users" more than bold or backColor.

domenic commented 4 years ago

Also, there is no supported property; editorDom.contenteditableDisabled.supported is not a thing.

johanneswilm commented 4 years ago

I don't see why we invented a second set of types. execCommand() is an established API that all browsers support. Is the same true of the new API?

The beforeinput event is only present in Chromium/Safari, but the input event including the list of input types has been shipped in all three Chromium, Safari and Firefox.

If so, it's a real shame that we duplicated the concepts with slightly longer and more annoying to use names

The editing taskforce has been working on this since around 2013/14, but the proposal itself is even older than that. The names for the input types were proposed by Ojan Vafai, if I recall correctly. That must have been around TPAC 2016 as I can see that the old, non-prefixed names were still used in 2015. Unfortunately I have not been able to find the minutes from the 2016 TPAC meeting. The reasoning that was given was what I mentioned above with the example: to make it easier to categorize the inputTypes. I don't recall there being much opposition on this naming scheme from any side.

Also, there is no supported property; editorDom.contenteditableDisabled.supported is not a thing.

Not yet, but the current state of the discussion is that something like this should exist. A resolution on this was made at TPAC 2018. When it was missing in the proposal that Microsoft came with in 2020, there was another resolution to get it back. How exactly the feature would work is still up for discussion.

johanneswilm commented 4 years ago

In particular, I don't see why formatBold or formatbackcolor "corresponds to things that browsers actually offer to end users" more than bold or backColor.

Those two are the same thing, that is true. But the focus of what is included is different. In execCommand there are, for example, unlink and a styleWithCSS commands. But as we were not able to find any keyboard shortcut or UI for that in any of the browsers, there is no corresponding inputType. Instead there is, for example, a formatSetInlineTextDirection inputType, as that corresponds to a control that users have in their context menu.

domenic commented 4 years ago

Are there any cases in the contenteditabledisabled proposal (the topic of this issue) where the longer name is more accurate than the simple one?

johanneswilm commented 4 years ago

I don't think so. But the two sets of names do not map 1:1 onto each other. The list of simpler names are things which let JS, by means of execcommand, instruct the browser to do something to a contenteditable element whereas the longer ones correspond to controls and keyboard shortcuts that the end user can use to instruct the browser to do something to the contenteditable element.

For contenteditabledisabled we need another list of things where the end user instructs the browser to do things (to disable those). So if we start out with the list of execCommand names, we will likely have to make up for lack of the existence of some of them and fill in with new names.

If inputtypes had not yet been shipped already and if the Chromium team would not have had a strong opinion on that topic at the time, I would not be opposed to using shorter names. But now that this has happened already, I wonder if it would not be best to stick with that terminology.

It is different with execCommand. While it is true that execCommand is implemented in all browsers, the implementations are unfortunately not entirely compatible. There has been a long discussion over the past decade or so on why this API does not actually work well for production level editors even if execcommand would behave in the exact same way in all browsers, and with the exception of a few commands that have no alternative, execcommand is largely not used by production ready JS editors as of today. This includes both editors made by independent third parties as well as those developed by the browser makers themselves [1]. If you think it would be useful, I could give a longer presentation on this topic. But I don't want to drag this into the discussion unless it's something that not everyone is aware of.

[1] There are some minor exceptions to this rule. For example, there is an editor to clean up the contents of a clipboard or another one that allows to insert foreign characters through an onpage virtual keyboard that is only loading documents by letting end users paste content and isn't too concerned about breaking, etc. that claims to have a lot of users.

gked commented 4 years ago

I just checked and FF actually shipped beforeInput events as well, although, it is currently behind a flag. image

It sounds like the two options are

  1. Conform to the wording of execCommands which is currently stuck in draft stage and probably not going to move forward any time soon.
  2. Adhere to what we use in input events

I, personally, could go with shorter names as well but I do see @johanneswilm's point that we already shipped this for better or worse and this is what authors are getting used to today.

For the sake of consistency, should we stick to verbose names, @domenic?

domenic commented 4 years ago

I don't understand the consistency point. execCommand is something that's shipping everywhere. input events is behind a flag. If anything, we should be consistent with the widely-implemented technology.

johanneswilm commented 4 years ago

input events is behind a flag.

Actually only beforeinput on FF. There is both a beforeinput and an input event that both use the inputtypes. The input event is shipped everywhere without any flags, also on FF.

johanneswilm commented 4 years ago

I, personally, could go with shorter names as well

I could personally go with anything - short names, numbers, another thing we come up with that will make it more likely to be accepted. But I have a feeling that the same browser people who thought it was important to have these longer names for the input types will also eventually come back with the same arguments in this case. Because they are very much addressing the same thing and it would be more consistent.

I could be wrong though. And in the end it won't take more than a few minutes for any JS dev to learn both sets of terms. And I'm sure must would prefer that if they get the functionality over not having the functionality at all.

johanneswilm commented 3 years ago

@domenic Get we move on with this? The names used in inputevents have been shipped with all major browsers without flags.

domenic commented 3 years ago

I'm not sure what you're suggesting. Have you put up a PR to review?

I'm very surprised that three browsers shipped a feature unflagged with no HTML spec PR, much less a merged one. But if you say that's the case, then oh well.

johanneswilm commented 3 years ago

I'm very surprised that three browsers shipped a feature unflagged with no HTML spec PR, much less a merged one. But if you say that's the case, then oh well.

They shipped the beforeinput event as specced in the Input Events spec. The update from last time here is that now also Firefox has removed the flag.

johanneswilm commented 3 years ago

You @domenic asked last time we discussed this whether we could change the names used to those in execCommand. The argument was that execCommand shipped everywhere while input events were behind a flag. Now they are no longer behind a flag. So I'm asking whether that point has changed or whether you still want us to change the values to match execCommand instead?

domenic commented 3 years ago

Oh. No, I still think the shorter names are better. I'm sad that input events did not take advantage of the period of non-shipping to align with them and instead chose to fracture the ecosystem, but I don't think we should carry that mistake forward.

johanneswilm commented 3 years ago

@domenic It had been shipping for years also when we had our last conversation about this. It was just a matter of one of the two events (beforeinput not input) that was behind a flag in one single browser.

ExecCommand is not exactly part of the ecosystem of commands used in JS editors, but ok, I guess we are still stuck here then.

saschanaz commented 3 years ago

Soo...

  1. The longer naming in InputEvent#inputType has been there for years, sadly. (Since 2017 on Chrome and 2019 on Firefox, per MDN.) beforeinput just shares the naming because it uses the same interface InputEvent. https://w3c.github.io/input-events/#overview
  2. But why must contenteditabledisabled follow it? To achieve https://github.com/whatwg/html/issues/5863#issuecomment-684040036 there is another way: contenteditableDisabled.supported.format being a sequence that includes the tokens about formatting.
johanneswilm commented 3 years ago

I do not recall exactly who came up with this naming scheme, but it was many years ago at a time when the Chromium team were mostly driving the spec. I do recall that there was a specific point with the naming scheme: JS editor developers could filter for the prefix and then have different parts of their apps respond to formatting, insertion, deletion, etc. . There was a large and elaborate discussion on the terms to be used at that time.

Unfortunately, it seems like there is a small group of execCommand supporters that have not been part of the discussions over the years in the editing taskforce nor the overall JS editor landscape over the past 10-15 years and who therefore have a different view of what is central for JavaScript editors in 2021 and what is not.

The names chosen in input events are not a mistake or a sad decision but rather part of a very large and long process that it seems unfortunately did not include people like you two, @domenic or @saschanaz. In hindsight, there should likely have been a more thorough search for people supporting execCommand when the decision was made to give it up so conflicts like these could have been avoided in the following years, but this was also before my participation and that of all the people currently active in the Web Editing Working Group. But for example @annevk has participated in some of our meetings over the years though.

I am not really sure how to continue with this. If the compromise that was reached a few years ago in concerns of execCommand (simplified version: don't remove but also don't encourage anyone to use it) was reached just because some execCommand-supporters were not in the right meeting at the right time, then maybe we need to find a new compromise. I don't think it is a good idea to have execCommand-supporters trying to save it by forcing the naming scheme used in an entirely different feature to match that of execCommand because that happens to have to land in the HTML spec, whereas the Web Editing Working Group continues to work on a plan to not have execCommand be part of the commonly used editing APIs altogether.

How about we put the question of execCommand on the agenda for TPAC and then the two of you can make a proposal to go back to making execCommand an actively developed spec and a central part of the editing landscape and we will invite some of the browser people who have worked the most for providing replacements for execCommand a well and then we all stick to whatever is the outcome of that discussion - both here in this naming scheme question and everywhere else. Would that be a solution?

domenic commented 3 years ago

No, I don't think asking us to take on more spec maintenance is a fair way to resolve a naming dispute.

johanneswilm commented 3 years ago

@domenic That must be a misunderstanding. I did not mean to imply that you should take on the maintenance of another spec. The question is whether you would be willing to have a discussion at TPAC within the Web Editing Working Group on the role of execCommand. Right now it sounds like we are on entirely different planets in that regard.

domenic commented 3 years ago

I'm not sure that TPAC is a particularly good place to resolve this. As far as I can tell this is a fairly narrowly scoped discussion. Someone wants to introduce a new feature to HTML. They can choose between short names and long names. Both sets of names have precedents. The long names do not have any known advantage over the short names; both choices will be aligned with one API and unaligned with another.

The advice from me as the HTML editor is then to choose the short names, because they are shorter and more meaningful.

johanneswilm commented 3 years ago

I am fine with either short or long names or integers or something entirely different. That doesn't worry me too much. What does worry me is that it seems like this question is connected to different views on execCommand and its role going forward. And so if that is the case, then I think it would be best to have a discussion on that and reach some kind of agreement rather than one group making decisions based on the assumption that execCommand will not be important and another group making other decisions in other specs based on the assumption that it continues to be important.

There may be better times/places than tpac though.

rniwa commented 3 years ago

I think we should go with the names we came up with input/beforeinput events. They're more self consistent and the set of names are well spec'ed whereas execCommand has a bunch of vendor specific command names that aren't spec'ed anywhere, etc... and it would be extremely confusing for developers to figure out what values are supported where, and that's just not going to change anytime soon (e.g. in the next 10-20 years).