I wish to capitalize the first letter of a sentence, on-the-fly, as the user types the text in a CKEditor content instance.
The strategy consists in catching each keystroke and try to replace it when necessary, that is for instance, when the inserted character follows a dot and a space. I'm fine with catching the event, but can't find a way to parse characters surrounding the caret position:
var instance = CKEDITOR.instances.htmlarea
instance.document.getBody().on('keyup', function(event) {
console.log(event);
// Would like to parse here from the event object...
event.data.preventDefault();
});
Any help would be much appreciated including a strategy alternative.
You should use keydown
event (close to what you proposed):
var editor = CKEDITOR.instances.editor1;
editor.document.getBody().on('keydown', function(event) {
if (event.data.getKeystroke() === 65 /*a*/ && isFirstLetter()) {
// insert 'A' instead of 'a'
editor.insertText('A');
event.data.preventDefault();
}
});
Now - how should isFirstLetter()
look like?
editor.getSelection().getRanges()
to get caret position.range.setStartAt( editor.document.getBody(), CKEDITOR.POSITION_AFTER_START )
,CKEDITOR.dom.walker
to traverse through DOM tree in source order,/\. $/
) - remember that you have to skip inline tags and stop on block tags - hint: return false
from guard
function to stop traversing.Example of how you can use walker
on range
:
var range, walker, node;
range = editor.getSelection().getRanges()[0];
range.setStartAt(editor.document.getBody(), CKEDITOR.POSITION_AFTER_START);
walker = new CKEDITOR.dom.walker(range);
walker.guard = function(node) {
console.log(node);
};
while (node = walker.previous()) {}
And now few sad things.
insertText
. You can use range#deleteContents
to do this.range#select
(on the range after deleteContents
), but in some cases it can place caret in incorrect place - like between paragraphs. Fixing this is... is not doable without deeeeeeeep knowledge about HTML+editables+insertions+other things :).paste
event, deleting content (one can delete words from the start of sentence), etc, etc.So this approach isn't realistic. If you still want to implement this feature I think that you should set timer and by traversing DOM (you can use walker
on range containing entire document, or recently typed text (hard to find out where it is)) find all sentences starting from lower letter and fix them.