-
Notifications
You must be signed in to change notification settings - Fork 12
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
Features: UI #127
Comments
Note that we also need some simple way to handle assets. |
Connected with #133 |
Yep, that will be handled in #104. I think it will be the same mechanism as for the code – the builder gathers all the files and then the bundler does the rest. And again the focus should be on simplifying the work of the bundler. |
Why features define their UI? (and how to separate features from their UI?)It would be really inconvenient for developers integrating CKEditor with their websites if they had to define that features A, B, C need such buttons and features D, E, F such select boxes and A, C, F such dialogs, etc. A feature package should define the editing functionality of the feature as well as the default UI that it proposes. It needs to be a plug-and-play solution for a certain problem. On the other hand, there must be ways to:
For the first point to be possible, the modular architecture was introduced. Any bigger part of code should be defined as a separate module. For instance, if a feature has a dialog it is recommended that it's defined as a separate module(s), so other features can use them. The same must be true for the editing functionality, so we define commands, converters, scheme, etc. The second point would be a no-brainer if features didn't have to define their UI. Since this cannot be avoided, there are couple options:
I'm a bit torn, because the separation on headless features and normal features sounds that good. I'm quite sure developers will like that. On the other hand, is it worth going that far? |
As I think about types of features that we'll have we can define:
I think it's quite clear that separating "headless" parts of image resizing or autocompletion would be ridiculous, as well as separation UI of the bold feature. Doable but artificial. So I'm rather leaning towards other solutions such as headless creators and headless UI lib as a last resort. But we'll need to watch out and perhaps define some recommendations on how to write features so they are UI and DOM independent. |
As I said before I don't see from architecture point of view why features define it's UI. It's like packaging two separate things in one module.
Again my point of view on that is separating feature from UI (button) is much cleaner even though it will require two modules - which in my opinion is good. Anyway it might be a problem with naming things. As default action dev might need a "feature" bold. This feature consists Also locking features to some UI thing might be problematic later on when one would like to develop an UI for two features in one UI component (simple example instead of button there are 2 checkboxes for bold and italic). Also some default implementations might drive development of a feature in a way that changing it's visible component might be harder later on. |
I've spotted an interesting side topic here – what should the commands exposed by a feature actually do? Let's say we've got the old table feature. It has the table button which executes the table command which:
What do we see here? That such feature's command would be totally useless in a headless editor. That the insertion algorithm (unless exposed in the API in a different way) is absolutely not reusable and not testable. This raises a question whether a feature like table shouldn't consists of two commands (UI agnostic As I see it now, those commands should be based on two commands, because one command would either be useless in a headless environment or we wouldn't have a command to bind to a button. |
That's why I proposed to split actual |
Meh easy ;) I think that more future proof is a generic table feature without any UI thingy (which as @Reinmar wrote above makes things harder).
This will made more coding but I think that will be more flexible as you would have loosely coupled code inside. |
I agree with @jodator on this one. |
No doubt that we all agree that having a generic, UI independent feature first, and then decorating it sounds best :D. We definitely all agree about that. I'm more asking on how to do that in our reality. Two commands or one? Two modules or one? If two modules what naming convention? I don't see a clear picture of all this yet. |
Brainstorming... no clear understanding of what I'm saying here. Table plugin:
Then:
|
Why not having two modules in one package? Actually table stuff will be probably more than two modules anyway. Probably more like six. As @jodator proposed, we might have a It's hard to say right now how many modules will be in table package and what will be their name. Maybe it's best to look at CKE4. We have column and row inserting which will be separate commands (easily testable under node, UI independent, no need for dialogs, etc.). We will probably have Since we decided that commands will be used for everything we could have two commands. One just for opening dialog (probably not testable under Node.js) and other will simply get some parameters and insert table in the editor. Unless you want to review your opinion on |
Hm... I need to try to adjust this idea to the existing architecture, because while the idea is of course great it is too detached. But I've been already considering something similar, so that may be feasible. |
That's a misunderstanding. A command for me looks like a single action that executes one of the dozens of features in the editor just like an enduser would do. For example, I would go with the "table" command, which simply opens the table dialog. In a headless editor, in fact, it would have no effect. Other things are pure API. If I want to insert a table by API, I would retrieve the table feature and execute specific methods. The same to open a dialog and manipulate its contents. |
For me ps. happy refactoring |
No problem with that, really... up to a point when we'll need to decide whether a bold feature is made of two features as well :D. While something is clear in case of a complex features like tables, it's much more unclear when applied to other cases that I mentioned in #127 (comment). Also, this is a question of whether we want to make a super strict rule here or just a recommendation. If a rule, then what architectural consequences could such a rule have. |
Same here. Bold plugin (package):
If we want to avoid code to "register" things (having unnecessary code on headless, for example), we could use configuration instead, in package.json. In other words, the above second bullet could be moved to package.json (and the same for the previous example for table). |
If we follow this rule, then commands are totally UI stuff. It means that there's no other concept that would be UI independent and which would expose logic such as "is the subpart of the feature enabled now?" Imagine how much code you would need to write if you would like to replace the whole editor UI with your own, as @jodator mentioned. If you attempt this in the easiest possible way, so by using a headless editor, then you would need to reimplement pieces of commands in your integration with a different UI. I can't see any reasons to make some UI agnostic commands, so I'm voting for this. |
As I wrote above – I'm trying to convert this to an implementable idea :D The thing is that packages do not register anything. Packages contain modules. The user needs to know what to use. So I'm trying to figure out how the builder could help, what can be automated and what the user needs to do manually. |
No. It's the simplest representation of the single user action that represents the feature. For instance, the "bold" command would not "click the button" but would execute the bold feature. Just like "table" could open a dialog or insert a table straight. Still a default implementation must exist and if you want to change the behavior, you need to code. Then what "dialog" means is a different story because a custom UI implementation should be able to replace the default dialog component with its custom one. So, my custom table button would simply call the "table" command. Then it is up to the command implementation. By default it would open a dialog and hopefully my custom dialog. So in fact, I'm not coding anything other than my custom UI components. |
That's a good point. Commands speak about state and it really matters. Both editor features and external code might want to know whether some action is possible or not i.e. in the context of current selection. A Table Feature could bring multiple commands like Otherwise how would we handle a case when some external code calls |
If it's the simplest representation then why opening a dialog? Why couldn't the dialog button insert a 3x3 table? Or NxN table, because the table dialog could open a table picker panel like in Google Docs. You make an assumption here that your table command knows how it should interact with the user. How could it know it? It's just a command :D. Despite the fact that your table button may work in at least 3 different ways, depending on what UI you'll attach, in all cases it should check its state (selection vs scheme) in the same way. So button's action may differ, but the state is the same. That state should be materialised in a form of a generic command –
BTW. See what native |
Because that's the way the command has been implemented by the developer and the user has no other way to execute that command. So, in the user point of view and for the specific implementation the user has in his hands, that's the simplest representation of that command. That's why I classified commands as user actions while you want to propose it as developer API that for some unclear reason is proposed as commands and not as simple methods. |
Yes, commands are developers' API (what else could they be?). They should be used for most popular feature actions. And those feature actions may have an accompanying state. That's why for those actions it's worth to use commands which nicely wrap action+state. Beside, if we'll define commands only (because no one says that those "final" commands won't exist) for the final buttons' actions, we have nothing for the headless editor users. That's a clear argument for having base commands and UI-related commands if the situation requires them. If not, if the base action is absolutely stateless, then a command isn't necessary. It's optional, because, who loses something if the developer defines it? No one. |
I’m trying to understand one thing while writing the spec proposal – what part of the features we need to run in Node.js? We were talking about feature-less editor which just servers as a collaboration server client that decorates the content. But do we need to run any part of the features as well? Do we see any use case for that? Because we need to answer – what's a more importat use case – headless editor in the browser or running editor with features in Node.js? |
This one. |
But why? If that's never going to be used for real the only use case I can see is running tests, bots or whatever. |
To give you more context – I've asked this question myself when trying to draw a line between the "data" and "UI" parts of features. DOM listeners and any other DOM dependencies (buttons, dialogs, etc. are a hardcore DOM dependencies; but there are softer dependencies like geolocation API, onbeforeunload, localstorage, etc.). I see a 3 layers that a features could define – data, base DOM, UI, but that sounds like too much ;/. |
Some facts
AnalysisDivisionThe division on the feature data layer and the feature UI layer described in fact 4 theoretically draws a clear line for how features could be implemented. However, an input-like editor (which we consider quite headless because it doesn't have the "UI chrome") would need key bindings and many DOM listeners. In Node.js though, all the DOM event listeners are unnecessary and may require jsdom to not blow up. Actually, big part of the data layer may also be unnecessary. As you can see these two cases aren't the same and we would need to break features into 3 layers (data, base-DOM, UI) in order to satisfy both of them. There's a an interesting third case though – cross-implementation compatibility. The only way how I can see this work is that in all implementation base layer of the same set of features is always loaded. This will ensure that:
This case seems to be very similar to Node.js scenario. You want the editor to understand the data, but not to provide editing options for it (the user interface). Therefore, if we split features in the following way:
We'll satisfy 2 out of 3 cases and we'll open doors for producing a different interaction layer for some features. This may be useful e.g. on small screen touch devices where we've got very little space so we may be forced to create special UI. ImplementationI think that the most important conclusion can be drawn from the 2nd fact – the developer creating some kind of a headless editor will need and perhaps want to better understand the structure of feature modules and possibilities they create. This case doesn't need to be as intuitive and exposed as the case in which the developer builds a normal editor and needs to quickly choose features for it. This means that under the usual names we should keep what most of the developers will look for, so the UI-rich features (to make it clear – UI-rich features will require their UI-less partners so the user needs to remember only about the former ones). Where to keep the UI-less base features?
I'm against 1. because that will nearly duplicate number of packages and most often you'll need to install both anyway. Separate directories may make some sense, but there will be some features which will operate only on the data with no UI and any DOM dependency (e.g. a feature which marks all characters over 140 limit with red background, like on Twitter). Could be ok if we wouldn't move such features to As for prefixes and suffixes – they are problematic for one reason – we should rather avoid using dashes as we don't use them in class names. I think I'd be ok with:
Note: In this case we can also have features which are only manipulating on data. But if a feature is "base" it does not make sense to prefix it. I think that I like the prefixes more. To make static analysis possible we can introduce the The only doubt I have is whether "base" is the right name. It doesn't clearly indicate that it's the "data layer" of a feature, but the question is whether that would be accurate anyway, because maybe the base isn't only about the data? I was actually also considering the word "model", but it has the same problem – converters are more of a controllers. So perhaps "base" isn't that bad name? |
Maybe shifting:
|
👍 @jodator |
Please remember guys about the fact that the developer will have to configure the editor by specifying which features should be loaded. It will be strange if he/she has to type |
Short summary from my f2f talk with Fred:
Finer granularity of the feature model (or "data" – I'm still unsure what would be the most intuitive word) will allow changing the feature's representation in the data. This is not only useful for other developers (they may use converter priorities) but can also be useful for us if we'll want to ship two versions of a features. E.g. we've been talking in Editor Recommendations that an image should always be wrapped with a |
Naming schema looks nice. 👍 |
Similarly to #124 – done, working, will be documented soon. |
Features concept
This is a part of Features concept. This issue discusses UI. See also #129.
UI
It has not been yet decided how exactly
Feature
should be linked with UI however most probable solution will be thatFeature
creates required UI components, bind them withFeature
orCommands
and registers / publishes them for other parts of code to use. Those UI components might be then used byCreator
s to compose appropriate UI.The text was updated successfully, but these errors were encountered: