I am working on an app that has multiple editors in the same page and it requires that I check whether the caret is in the beginning/end of the contenteditable and also to set the caret to the beginning/end of it.
I can integrate my code into medium-editor and I wonder if this is something useful to anyone?
@nmielnik @daviferreira
Thank you!
This sounds like it could be something useful, but we probably don't want to add code that isn't going to get covered internally...however, I guess we could always just add a bunch of tests for now and leave it as an exposed utility.
Would you be willing to open a PR with the code, or maybe share a gist so we could look at it? I'm definitely curious what kind of mechanisms you're using.
@nmielnik
Here is what I currently have for my own application.
https://gist.github.com/dominicwong617/d9f4188b4d364d052b45#file-medium_editor_caret-js-coffee
(Sorry it's in coffeescript at the moment)
@nmielnik so I guess it might not be useful to be added to the library?
Sorry @dominicwong617 I had some comments I forgot to add to you gist, I'll add those now.
I closed the issue because I don't think there's a big need to add in the extra code, at least it's not something that needed to be tracked by an issue.
I'm on the fence about adding code that won't get exercised by any of our flows, we removed a bunch of code like this before the v5.0.0 release. I do however see how this code _could_ be used for certain fixes and html cleanup logic in the future, so I see the value in it.
How about for now we just keep this code in mind and when we have a fix / feature where taking advantage of this makes sense, we can refer back to this issue and do it then?
Out of curiousity, what are you using the utilities for? Why do you need to know whether the cursor is at the begining or end of an editor?
@nmielnik No problem. I appreciate you getting back to me.
I need these because I am working on an application that requires multiple medium editors in the same page. It's a note with an unordered list of 'blocks'. Each block is an editor. For example, if the cursor is in the beginning of one block and the user presses backspace, the block is removed and the content is appended to the previous block.
Anyway, just let me know anytime. I am very happy to help out as your library made my life a lot easier :joy:
Ah, ok thanks, that makes a lot of sense.
Definitely don't hesitate to share out a reference to your app if you're comfortable, we would love to compile a list of applications that are using MediumEditor so whenever we make our fancy landing page we can add links to everyone!
@nmielnik cool! I will send you the link after we launch. Thank you!
Hey @dominicwong617 why not make an extension out of it?
@daviferreira It sounds like a good idea. Thanks!
Oh, I need this feature. Any news whether there is an extension or the code has been added to get the caret positions? My usage scenario is exactly as @dominicwong617 explained.
@kadishmal The code hasn't been added to the repo, and I'm not aware of any extension built for this. @dominicwong617 did provide a gist that apparently worked, though it might need to be ported to javascript.
After mulling this over, this probably is fine as a helper function in the MediumEditor.selection object (selection.js).
@nmielnik it was a very good reminder. I almost forgot to share my working solution. Here is unedited, unformatted code. Hope it helps or gives some ideas.
focus() {
const editor = this.editor,
editorNode = this.refs.editor;
var { caretPosition } = this.props;
function setCaret(el, caretPosition) {
el.focus();
var range = document.createRange(),
sel;
range.selectNodeContents(el);
function findTargetNode(node) {
// console.log('node.nodeType = %d, caretPosition = %d.', node.nodeType, caretPosition, node);
if (node.nodeType > 3) {
// Only iterate over elements and text nodes.
return;
}
// If we hit a text node, we need to add the
// amount of characters to the overall count.
if (node.nodeType === 3) {
// console.log('node.length', node.length);
if (node.length > caretPosition) {
return {
node: node,
offset: caretPosition
};
} else if (node.length == caretPosition) {
return {
node: node,
offset: 0
};
} else {
caretPosition -= node.length;
}
}
// Otherwise, the `nodeType = 1` meaning it is a node.
for (var i = 0, nodeObj; i < node.childNodes.length; ++i) {
nodeObj = findTargetNode(node.childNodes[i]);
if (nodeObj) {
return nodeObj;
}
}
}
switch (caretPosition) {
case -1:
// `-1` caret position indicates that we need
// to position the caret at the end of the section.
// Passing `false` to `collapse` sets the start
// and end points at the same end position.
range.collapse(false);
break;
case 0:
// `0` caret position indicates that we need
// to position the caret at the start of the section.
// Passing `true` to `collapse` sets the start
// and end points at the same start position.
range.collapse(true);
break;
default:
// Otherwise, position the caret at the specific
// index.
var nodeObj = findTargetNode(el);
// console.log('nodeObj', nodeObj);
if (nodeObj) {
range.setStart(nodeObj.node, nodeObj.offset);
range.setEnd(nodeObj.node, nodeObj.offset);
}
}
sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}
setCaret(editorNode.childNodes[0], caretPosition);
}
For detecting whether or not the selection is at the beginning or end of an element, you can use MediumEditor.selection.getCarefOffsets(element) which will return an object with a left and a right property giving you the offset of the cursor from the begging and end of the element. When left is 0 the cursor is a the beginning, and when right is 0 the cursor is at the end. It uses the same method of detecting how far from the beginning/end the cursor is as the gist that @dominicwong617 provided a while back.
For moving the cursor to the beginning or end, you can call editor.selectElement(element) to select the element and put focus properly into the editor, and then call MediumEditor.selection.clearSelection(document, moveCursorToStart) to collapse the selection to the start or end of the editor element.
Guess we've had these helpers for a while and I either didn't know about them or didn't put everything together in my head until I actually started considering implementing them 馃槃
looks good to me.
Most helpful comment
For detecting whether or not the selection is at the beginning or end of an element, you can use
MediumEditor.selection.getCarefOffsets(element)which will return an object with aleftand arightproperty giving you the offset of the cursor from the begging and end of the element. Whenleftis 0 the cursor is a the beginning, and whenrightis 0 the cursor is at the end. It uses the same method of detecting how far from the beginning/end the cursor is as the gist that @dominicwong617 provided a while back.For moving the cursor to the beginning or end, you can call
editor.selectElement(element)to select the element and put focus properly into the editor, and then callMediumEditor.selection.clearSelection(document, moveCursorToStart)to collapse the selection to the start or end of the editor element.Guess we've had these helpers for a while and I either didn't know about them or didn't put everything together in my head until I actually started considering implementing them 馃槃