In my ckeditor instance, I want to let my users insert a horizontal rule but only once. If there is an existing line, it should be replaced by the new one (same as the Read-More functionality on Wordpress). I can get it to work if I want only the last HR tag to remain, but what if a user wants to insert his HR tag higher up in the document than an existing one?
I used a variable (say, savedContent) to store the default content (without any HR) on instantiation. Following the steps in Set cursor to specific position in CKEditor , my idea was to use the savedContent variable to revert the CKEditor contents to the default HR-less content before (using the ranges or bookmarks) to insert a new HR at the cursor position.
This is the code:
CKEDITOR.on('instanceReady', function() {
$(".cke_button__horizontalrule").attr("title","End Preview here");
var savedContent = CKEDITOR.instances['pro_story'].getData();
$(".cke_button__horizontalrule").on("click",function(){
var ranges = editor.getSelection().getRanges();
CKEDITOR.instances['pro_story'].setData(savedContent);
editor.getSelection().selectRanges( ranges );
editor.insertHtml("<hr />");
});
});
Now the problem with this code is that, for some reason, it gives me the following error: The given range isn't in document.
What do I do?
Get an array of existing <hr />
tags before inserting a new one. Then, remove all these tags after inserting the new one.
let hrArray;
CKEDITOR.instances['pro_story'].on('beforeCommandExec', function(evt) {
if (evt.data.name == 'horizontalrule') {
hrArray = evt.editor.document.getElementsByTag('hr').toArray();
}
});
CKEDITOR.instances['pro_story'].on('afterCommandExec', function(evt) {
if (evt.data.name == 'horizontalrule') {
hrArray.forEach(el => el.remove());
}
});