📜 ⬆️ ⬇️

WYSIWYG HTML editor in the browser. Part 2

This is the second part of the translation of an article about the designMode and contentEditable properties, their behavior and features.

The article discusses the basic principles and problems of unifying the features of editing in modern browsers. Topics covered in the article:

WYSIWYG HTML editor in the browser. Part 1 is here.

Editing commands


Browsers support many editing commands. The HTML generated by these commands is not standardized and differs from browser to browser. For example, in IE "Bold" will generate the code:
  1. < strong > Hello! < / strong >
Safari generates:
  1. < span class = "Apple-style-span" style = "font-weight: bold;" > hello! < / span >

')
The code, at least in IE, is somewhat old-fashioned. Many commands use a terrible font tag:
  1. < FONT color = # ff0000> 23 < / FONT >

The generated markup is not valid XHTML and, as a rule, even valid HTML code.

Opera generates code similar to IE (no, not completely), using the font tag and so on.

Safari generates formatting using spans and inline CSS. The advantage of Safari is that it is at least valid HTML 4.01 Strict.

Mozilla supports 2 modes of operation - it either generates presentation tags like IE / Opera or styles containers like Safari.

If you are sure that you need valid HTML code, then you should clean the server-generated code generated by the editor in order to get valid (X) HTML from this disgrace. (Well, in any case, you should do this to avoid XSS attacks).

Hot Keyboard Shortcuts


Many commands are available via hotkeys, for example, Ctrl / Cmd + B for bold, Ctrl / Cmd + Z for undoing the last action, etc. But these combinations may vary depending on the localization of the browser.

The assigned keyboard shortcuts cannot be changed, but they can be overwritten using the keyboard intercepting keyboard script.

Editor API


You might want to make a control panel to allow the user to use editing commands. This can be done using the API editor. This API is not similar to the usual DOM API, in fact it is a script adaptation of the IOleCommandTarget interface, which is the COM interface used by Microsoft to synchronize the control panel and edit the document.

The API is located in the document object and consists of the execCommand method and several methods with the “query” prefix that returns information about the command.

All methods take a command ID as the first argument; this is a string containing the name of the command. Actually, methods:

ExecCommand


Executes the command for the current selection. Some commands switch between states depending on context. For example, if you apply the “Bold” command to a selection that already has a bold face, then the selection will be displayed in a normal style. Some commands thread arguments, for example, forecolor requires a color code as an argument.

Some commands invoke modal dialogs — for example, the link command will invoke a dialog that prompts you to enter a URL. Dialogues cannot be changed, but it is possible to replace them. For example:
  1. result = document. execCommand ( command , useDialog , value )
What is what:
command: string; team name.
useDialog: Boolean type; Whether to show the built-in dialog (Not all commands can cause dialogs).
value: The value received by the command. Not all commands accept values; If it causes a dialogue, then the value is taken from it.
result: true if the command is executed, false if canceled by the user (closing the dialog) or the command cannot be executed.

If there is no selection (only the cursor), the text formatting commands are applied differently, depending on the browser. If the cursor is inside a word, IE will apply formatting to the word; other browsers will apply it to the next character that will be typed if the cursor is not moved back.

QueryCommands

It makes sense to use Query commands to determine the state of buttons on the control panel depending on the current selection and the position of the cursor.

QueryCommandEnabled

Determines whether the command execution is possible with respect to the current selection. For example, “unlink” can be applied only if the cursor is inside a link. If the selection contains an area unavailable for editing, no commands will be executed.

QueryCommandState

Indicates whether the command was applied to the selection, that is, if the selection is bold, QueryCommandState will return true for the bold command.

QueryCommandValue

Returns the value of some command to select. The value corresponds to the one that was set when using execCommand, that is, for example, for ForeColor it will be the color code (as a string) for the current selection.

The format will be different in different browsers. For example, ForeColor returns a hexadecimal value in IE (such as # ff0000), while others return an RGB expression, such as Rgb (255.0.0).

Some values ​​vary depending on the browser localization, for example, the value for FormatBlock in IE returns the name for a paragraph in the localization language of the browser interface.

Commands for which there are no values, for example bold, will simply return false. (The API contains two additional methods, queryCommandSupported and queryCommandIndeterminate, but they are too buggy to use at least something.)

Range and Selection API


Built-in commands are useful, but you cannot change their behavior or add a non-standard implementation. Using the Range and Selection API you can use arbitrary HTML transformations that you can use to implement non-standard commands.

The problem is that any transformations affecting the DOM destroy the undo stack, which is used to implement the UnDo / ReDo commands. This is not good, but it can be an acceptable price for non-standard teams.

The range / selection APIs have two main classes:

Range is a continuous range of document characters. The range may overlap the borders of the elements. The range has a start and end point. If the starting point coincides with the end point, then the range is called degenerate.

Selection - represents the current user selection in the document. Selection contains one highlighted range. If the selection range is degenerate, then it is displayed as a cursor. (Ranges and selections can be used outside of elements in edit mode. You can create a selection in a read-only document. Such a selection, however, cannot be degenerate, since the cursor is shown only when the element is in edit mode.)

These principles are identical in all browsers, but the APIs themselves differ in implementation in IE and all other browsers. IE uses its own proprietary solution for the range and selection API, other browsers use the W3C DOM Range API in combination with the non-standardized selection API.

The main difference is that in IE the content of the range is available as a string with HTML markup. In the W3C DOM Range API, the contents of the range are available as a tree of DOM nodes.

Example range

To show the different approaches, below is a command that applies the “code” tag to the current selection.

In IE (editWindow is a link to frame in designMode):
  1. var rng = editWindow. document . selection . createRange ( ) ;
  2. rng. pasteHTML ( "" + rng. htmlText + "" ) ;
In Mozilla:
  1. var rng = editWindow. getSelection ( ) . getRangeAt ( 0 ) ;
  2. rng. surroundContents ( document. createElement ( "code" ) ) ;

Selecting controls


IE supports the selection of controls, which differs from the usual range selection. The selection of a control occurs when you click on an object, such as an image, a form control, or a table frame.

In IE, it is possible to select more than one element at the same time using the ctrl + click combination. Other browsers do not support the concept of selection of controls; in other browsers, highlighting is always a text range.

findings


The article discusses the basic principles of editing data in the browser. Part two of the article shows many examples of the application of the above API.

From the translator: if this is not only interesting to me, then I will translate the second article .

And a couple of links to additional materials:

Source: https://habr.com/ru/post/107880/


All Articles