Now it's time to use the Editor`s API features. We can access the API using the api object passed to the Tool constructor. For Marker Tool we need styles and selection APIs.
Styles API provides some CSS classes` names to stylize elements of our Tool with common Editor.js style:
Selection API has some useful methods to work with selected text fragments. For the Marker Tool we will use following API methods: findParentTag and expandToTag. First one accepts tag name and class name as arguments and returns first found parent element of anchorNode of the Selection with passed parameters and null if such element doesn't exist. Second one accepts HTML element as argument and expand current selection to that element.
After we replace selected text with mark element we need to expand selection to the inserted element:
surround(range) {
if (this.state) {
return;
}
const selectedText = range.extractContents();
const mark = document.createElement('MARK');
mark.appendChild(selectedText);
range.insertNode(mark);
this.api.selection.expandToTag(mark);
}
Let's move code of surrounding text to another method called wrap and create unwrap method to remove highlighting. To remove highlight we need to find mark tag from selection position and replace it with plain text:
surround(range) {
if (this.state) {
this.unwrap(range);
return;
}
this.wrap(range);
}
wrap(range) {
const selectedText = range.extractContents();
const mark = document.createElement('MARK');
mark.appendChild(selectedText);
range.insertNode(mark);
this.api.selection.expandToTag(mark);
}
unwrap(range) {
const mark = this.api.selection.findParentTag('MARK');
const text = range.extractContents();
mark.remove();
range.insertNode(text);
}
Also we can modify checkState method using the API:
checkState() {
const mark = this.api.selection.findParentTag(this.tag);
this.state = !!mark;
}
Now Tool works actually how it should but we can make it prettier. Let's add icon and change button state in accordance with current state of highlighting: