“This is the 8th day of my participation in the First Challenge 2022. For details: First Challenge 2022”

preface

Editor.js is a rich text Editor that can be used to create a rich text Editor. If you want to create a rich text Editor, you can use juejin to create a rich text Editor.

This article mainly takes you to implement three extension functions: temporary data and echo, storage data verification and small tool custom style

Temporary data and echo

Save the data

As mentioned above, we can customize the saved data output of the block by using the save function in the class

And we bind the data to the bottom of the class for easy manipulation of the datadataProperties:

The value of data.value can be changed in real time via the unique onchange event on the input:

The editor will save our changes, so now we need to find a place to store our data.

Here because there is no back-end support, so for the moment to use window. localStorage to save data, and then have a place to save data, we are going to get our data, we first define a save button

On our editor instance, there is an editor.save() method that holds all the data we entered. Note that this method is asynchronous and we need to fetch the data using.then

 editor.save().then((outputData) = > { console.log(outputData); }
Copy the code

You can see our custom stars block with data in itvalueAnd then we can save the data towindow.localStorageamong

The echo data

EditorJS provides a property data during instantiation. As the name implies, we only need to assign the value of outputData just obtained to it, so that the previous content can be loaded during initialization. In this way, the input content will not be lost even if the refresh, and further data saving needs the support of the back-end database

const editor = new EditorJS({
    holder: 'editorjs',
    data: storage.getData('noteData') || '',
});
Copy the code

Storage data verification

The official document also provides the Saved data validation method. For example, for the data Saved above, we can find that the data in the second block is blank. We can cancel the Saved data by checking the data.

Validate (savedData) : this method passes in the savedData as an argument, which allows us to do some basic data validation:

validate(savedData) {
    console.log(savedData);
    if(! savedData.value.trim()){return false;
    }
    return true;
}
Copy the code

As you can see, after data validation is added, our save method will not return data that does not meet the criteria and thus will not be savedwindow.localStorage. Based on this method, we can also define the re to do some more complex data verification, such as data format is not the correct url will not save and so on, so that we can realize the storage data verification

Gadget custom styles

If you’ve used the rich text editor, you may have noticed that there’s a gadget in the editor as well

Normal text has only three widgets, images have six widgets, click on different tools to change the image style, and this change is saved as a state as part of the image data.

For our custom block, we are also provided with the function of custom widgets. This time, we will define a widget that changes the style of our stars. After clicking on it, we will change the style of the input box and the small icon in front of it.

We can add a renderSettings() method to our class. The return value of this method will directly affect the generation of widgets. Besides the official default of two moves and one delete, we can customize all widgets.

As with the block icon, we’ll give our tool an icon and a name. Again, we’ll mount it under an instance of the class so we can use it anywhere in the class:

this.settings = [{
    name: "starsError".icon: `
      
       ... 
      `,}];Copy the code

Then we can define our renderSettings() method

renderSettings() {
    const wrapper = document.createElement("div");

    this.settings.forEach((tune) = > {
        let button = document.createElement("div");
        button.classList.add(this.api.styles.settingsButton);
        button.classList.toggle(
            this.api.styles.settingsButtonActive,
            this.data[tune.name]
        );
        button.innerHTML = tune.icon;
        wrapper.appendChild(button);
        button.addEventListener("click".() = > {
            this._toggleTune(tune.name);
            button.classList.toggle(this.api.styles.settingsButtonActive);
        });
    });

    return wrapper;
}
Copy the code

If the toggle function passes a parameter, it will add or remove the class name according to the parameter. If the toggle function does not pass a parameter, it will determine whether the current button has a class name. If so, it will remove it, and if not, it will add it. Then this. API. Styles. SettingsButtonActive is one of the official offer our parameters,

button.classList.toggle(
    this.api.styles.settingsButtonActive,
    this.data[tune.name]
);
Copy the code

Is equal to:

button.classList.toggle(
    'cdx-settings-button--active'.this.data[tune.name]
);
Copy the code

The introduction of the API is just to make it easier to use some of the official styles, which we’ll talk about later if we have a chance.

And then again, we’re going to loop through the list of widgets and append them into a parent container, and then we’re going to return that parent container, and we’re going to bind the listener events, and we’re going to determine whether the buttons are active or inactive, and then we’re going to switch their values

The value that determines whether the button is active or not needs to be stored in our data as data to ensure that it is a state that will be saved

 this.data = {
    value: data.value || ' '.starsError: data.withBorder || false};Copy the code

Then in the _toggleTune() function, we change this value, and in the active state, we add a class name under the block element, which we can preset some styles to display when clicked

/ * * *@private
 * Click on the Settings Button
 * @param {string} Tune -- Tune name from this. Settings */
_toggleTune(tune) {
    this.data[tune] = !this.data[tune];
    this._acceptTuneView();
}

/**
 * Add specified class corresponds with activated tunes
 * @private* /
_acceptTuneView() {
    this.settings.forEach((tune) = > {
        this.wrapper.classList.toggle(tune.name, !!this.data[tune.name]);
    });
}
Copy the code

Look at a glancewindow.localStorageWhere the data is successfully stored and it changes as you click on it so the little tool is successful

conclusion

This article is an extension of the previous article, but it is recommended for beginners to follow the previous article with a custom block before adding these additional features. Then, if any friends who use this plug-in have any novel functions that they want to realize, they can also ask for them. I will try my best to help them realize it, which is also a kind of exercise.

Define your own editor.js tool – Nuggets (juejin. Cn)