Less than 200 lines of JavaScript code to implement the Rich Text Editor method, 200 lines of javascript
Some time ago, I was searching for some information about the Rich Text Editor and found this project named Pell, which is a WYSIWYG text editor. Although its function is very simple, but surprisingly, it is only 1 kb. The project's core file pell. js contains only 130 lines. Even if other parts are added, the total number of js lines is less than 200. This aroused my interest and decided to see how its source code achieves this.
The main code of the project is in the pell. js file. Its structure is very simple. The implementation of the main functions depends on the following parts:
- Actions object
- Exec () function
- Init () function
Document.exe cCommand ()
Starting from the simplest part, the exec () function has only the following three rows:
export const exec = (command, value =null) => { document.execCommand(command, false, value);};
It wraps document.exe cCommand () in a simple way. Document.exe cCommand () is the core of the editor. Its syntax is as follows:
bool = document.execCommand(aCommandName, aShowDefaultUI, aValueArgument)
- ACommandName is a string that indicates the command to be executed, for example, bold, createLink, fontSize, and so on.
- Does aShowDefaultUI display the Default User Interface?
- AValueArgument some commands require additional input, such as the address required when inserting images or links
Note: After my experiments, changing the ashowdefaui UI value in Chrome has not been affected. This stackoverflow problem mentions that this is a parameter from the earlier version of IE, therefore, set this parameter to false by default.
Actions object
The file defines an object named actions, corresponding to this row of buttons on the toolbar, each sub-object in actions stores the attribute of a button.
Some code:
const actions = { bold: { icon: '<b>B</b>', title: 'Bold', result: ()=> exec('bold') }, italic: { icon: '<i>I</i>', title: 'Italic', result: ()=> exec('italic') }, underline: { icon: '<u>U</u>', title: 'Underline', result: ()=> exec('underline') }, // …}
The code shows three object attributes named bold, italic, and underline, which correspond to the bold, italic, and underline buttons in front of the toolbar. We can see that their structures are the same, all have the following three attributes:
- Icon: how to display
- Title: The title.
- Result: a function is assigned to a button as a click event. The previously mentioned exec () function is called to operate the text.
Now that actions object is available, how can we use it? This takes a look at the init () function. It selects elements from the actions object according to certain rules to form an array. Each item of the array generates a button. In the following code, settings. actions corresponds to this array. Each element corresponds to a button displayed on the toolbar. The rules for generating settings. actions will be explained later.
// Pell. the init () function settings in js. actions. forEach (action => {// create a button element const button = document. createElement ('button ') // Add a css style button to the button. className = settings. classes. button // display the icon attribute as the content. innerHTML = action. icon button. title = action. title // assign the result attribute to the button as the click event button. onclick = action. result // Add the created button to the actionbar on the toolbar. appendChild (button )})
In this way, each element in the array generates a button on the toolbar.
Init () initialization Function
To use the pell editor, you only need to call the init () function to initialize an editor. It receives a setting object as a parameter, which contains the following attributes:
- Element: DOM element of the Editor
- StyleWithCSS: if it is set to true, <span style = "font-weight: bold;"> </span> is used instead of <B> </B>
- Actions
- OnChange
The most important one is actions, which is an array that contains the list of buttons you want to display on the toolbar.
The actions array can contain these elements:
- A string
- An object with the name attribute
- An object that does not have the name attribute, but has required attributes such as icon and result for generating a button
actions: [ 'bold', 'underline', 'italic', { name: 'image', result: ()=> { const url = window.prompt('Enter the image URL') if (url) window.pell.exec('insertImage', ensureHTTP(url)) } }, // ...]
In the init () function, the actions parameter is combined with the actions object defined in pell. js to treat the actions object as a default setting. See the following code:
// The init () function settings. actions = settings. actions in pell. js? Settings. actions. map (action => {if (typeof action = 'string') return actions [action] // if the input action in the parameter already exists in the default setting, overwrite the default else if (actions [action. name]) {return {... actions [action. name],... action} return action}): Object. keys (actions ). map (action => actions [action])
If the setting Parameter object does not contain the actions array, the previously defined actions object is used for initialization by default.
An important part of the init () function is to create an editable area where a div element is created and its contentEditable attribute is set to true, so that you can use the document.exe cCommand () command mentioned earlier here.
// Create the settings element of the editing area. element. content = document. createElement ('div ') // make the div editable settings. element. content. contentEditable = truesettings. element. content. className = settings. classes. content // when the user inputs, the corresponding part of the page is updated. element. content. oninput = event => settings.onChange(event.tar get. innerHTML) settings. element. content. onkeydown = preventTabsettings. element. appendChild (settings. element. content)
Process Arrangement
Finally, we take "insert link" as an example to sort out the entire editor process:
1. When calling the init () function, add the following to the action array of the parameter object:
{ name: 'link', result: ()=> { const url = window.prompt('Enter the link URL') if (url) window.pell.exec('createLink', ensureHTTP(url)) }}
2. Check whether the link attribute exists in the defined actions object during the init () operation. The checked property does exist.
link: { icon: '', title: 'Link', result: ()=> { const url = window.prompt('Enter the link URL') if (url) exec('createLink', url) }}
Because there is a result in the input parameter, the passed result is used to replace the default value in the link object, and then the modified link object is placed in the settings. actions array.
3. Execute an iteration on the settings. actions array to generate the toolbar. The link object generates a button for "insert link" as one of the links. The result property becomes its click event.
4. Click "insert link" to enter a url and then call exec ('createlink ', url) to insert the url in the editing area.
The functional process of other buttons in the editor is similar.
In this way, most of the content in the Pell editor is explained, and the remaining part still needs to go to the source code. After all, the project code is not long, so it is good to get started with this text editor.
Summary
The above section describes how to implement the rich text editor with less than 200 lines of JavaScript code. I hope it will be helpful to you. If you have any questions, please leave a message for me, the editor will reply to you in a timely manner. Thank you very much for your support for the help House website!