I have a rather intricate Vue component that includes a contenteditable
div. My goal is to highlight words within this div using the Rangy library and add extra markup while retaining this markup even after editing the text.
Initially, I planned on asking for help because adding extra markup seemed to render the contenteditable
div uneditable; I couldn't delete or insert characters. However, as I attempted to set up a code snippet, another error surfaced.
When editing the contenteditable
div, three main actions are expected:
In the
storeIndexes
method, ranges are created and stored for each element in thehighlights
array. This process occurs during the@beforeinput
event which might not be supported by all browsers (I am using Chrome).Following that, the text content inside the
contenteditable
div should be updated.Lastly, the saved ranges should be restored through the
restoreIndexes
method triggered by the@input
event.
Although my code isn't supposed to visibly alter anything, an error message pops up when attempting to edit the text:
Rangy warning: Module SaveRestore: Marker element has been removed. Cannot restore selection.
What seems to be the issue here?
new Vue({
el: '#app',
data: {
currentHighlights: [],
highlights: [
{
start: 10,
end: 20
}
],
},
methods: {
// Actions before applying an edit
storeIndexes: function(event) {
// Create a new range object
let range = rangy.createRange();
// Get the contenteditable element
let container = document.getElementById('text-with-highlights');
// Store all existing highlights and add DOM markers
this.highlights.forEach(highlight => {
// Adjust the range based on character indexes
range.selectCharacters(container, highlight.start, highlight.end);
// Set DOM markers and save the range
this.currentHighlights.push(rangy.saveRange(range))
});
},
// Actions after making an edit
restoreIndexes: function(event) {
// Create a new range object
let range = rangy.createRange();
// Retrieve range based on character indexes
let container = document.getElementById('text-with-highlights');
this.currentHighlights.forEach(highlight => {
range.selectCharacters(container, highlight.start, highlight.end);
rangy.restoreRange(range);
});
this.currentHighlights = [];
},
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/rangy/1.3.0/rangy-core.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rangy/1.3.0/rangy-selectionsaverestore.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rangy/1.3.0/rangy-textrange.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id='app'>
<div @beforeinput='storeIndexes' @input='restoreIndexes' contenteditable id='text-with-highlights'>
Just some text to show the problem.
</div>
</div>