Selecting element of an contenteditable div when Enter Key is pressed - javascript

I want to get the element where the event occured. This snippet only logs the parent element
eg. .
How to log the current element where the key is being pressed
eg. 1st or 2nd
document.getElementById('text').addEventListener('keypress', event => {
console.clear();
console.log(event.target)})
<body>
<div id="text" contenteditable="true">
<div>1st</div>
<div>2nd</div>
</div>
</body>

UPDATE: This should do the trick:
<div id="text" contenteditable="true">
<div>1st</div>
<div>2nd</div>
</div>
<script>
document.getElementById('text').addEventListener('keypress', function(ev) {
var selection = window.getSelection();
var range = selection.getRangeAt(0);
var container = range.commonAncestorContainer;
var nodeParent = container.parentNode;
console.log(nodeParent);
});
</script>
It checks the current selection (the text that is selected by the cursor from start to beginning). In your case, i.e. at keypress, the selection will be the same from start the end, being the actual position of the cursor.
The Selection can contain multiple ranges (all kinds of nodes, including text nodes), depending on what the user selected on the page. Here we are only interested in the first one, where the cursor is, so we do getRangeAt(0).
It then looks at the common ancestor container, being the text that is currently being edited. The commonAncestorContainer is the node in which the Range is situated. In this case it is either the text node with the text "1st" or the text node with the text "2nd".
Now that we have the Text Node that contains the first Range of the current Selection, we can see its parentNode, being the current div.
Does that do the trick?

Related

How to scope user selection

I'm currently developing a Web Application that consists of different panels and areas.
One panel contains a huge table, another panel contains a description box, etc.
Usually, users can drag their mouse and select any range of text inside an html page.
I want the user to only be able to select text inside of one panel or up to a barrier.
For example, when the table is in focus, selecting text by mouse or hitting Ctrl-A should only select text inside of it. Not every selectable text on the page.
<div id="application">
<p>Not this text</p>
<div id="another-panel">Nor that</div>
<div id="special-panel-including-big-table">
Hitting Ctrl-A here should only select THIS text
</div>
</div>
I need to somehow define a barrier on a parent element (like the table panel) that prevents expanding the selection further up the DOM tree.
I consulted https://developer.mozilla.org/en-US/docs/Web/API/Selection and
https://w3c.github.io/selection-api/
I tried to use stopPropagation() on dragstart-events, but this doesn't seem to have any effect.
You can prevent the default selection with e.preventDefault() and create your own selection instead.
If your table contains input elements that can get the focus you can build in an extra check for that. That is not included in my example.
document.addEventListener('keydown', (e) => {
if(e.ctrlKey && e.key === 'a') {
//Prevent the default select all
e.preventDefault();
//Select only the contents of div#special-panel-including-big-table
var targetEl = document.getElementById('special-panel-including-big-table');
var range;
if (window.getSelection && document.createRange) {
var selection = window.getSelection();
range = document.createRange();
range.selectNodeContents(targetEl);
selection.removeAllRanges();
selection.addRange(range);
}
}
});
<div id="application">
<p>Not this text</p>
<div id="another-panel">Nor that</div>
<div id="special-panel-including-big-table">
Hitting Ctrl-A here should only select THIS text
</div>
</div>

Get bounding rectangle of selected text javascript

I use this code How can I position an element next to user text selection? to get the position of the selected text, but it doesn't work for the selected text inside an input. Sometimes the position is 0.
Is there some universal method for detecting the position of the selected text?
I want to show a tooltip on mouseup or dblclick the selected text.
You can use the following code to get the position of selected text:
var selection = window.getSelection();
var getRange = selection.getRangeAt(0);
getRect = getRange.getBoundingClientRect();
You can use getSelection api.
After selection a text run below code in console.
var selection = window.getSelection()
var baseOffset = selection.baseOffset
var length = selection.focusOffset -selection.baseOffset
var text = selection.focusNode.data.splice(baseOffset, length)
If you just need to get the position where the user doubleclicked, use the following snippet.
$('#thatInput').on('dblclick', function (e) {
alert('Position X: ' + e.clientX + '\nPosition Y: ' + e.clientY);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="thatInput">
The question is about getting the position of mouse pointer when selecting text. I am trying a solution that also works with keyboard events (choosed keyup).
I wrote a sample html page with a "vanilla" script inside to test the capabilities of the Selection API. This is the idea:
When selecting on text nodes, getting the position of selected text is done by means of the Range Object.
But when the selected text is a part of an Input Element, using the getBoundingClientRect() of the Range Object does not work (gave me a full zero ClientRect Object.
So, the function getSel() will try to consider both scenarios: selecting text just from the HTML or inside some input elements (just considered input and textarea).
On the bottom of the page there is a div#results element, for displaying data, then getSel() will create a new div#boundy with the coordinates of the ClientRect object or the related input element coordinates.
I wish to finish it, but I'm out of ideas on how to get the actual position of the selected text inside the input objects. It will have to be adding in a relative way to the coordinates of the element itself.
Answering Andrew, if this works, you'll be able to use the coordinates of div#boundy to place the tooltip wherever you want.
I've created a codepen here.

Using javascript to select text and the containing element using createRange

I'm rolling my own generic wysiwyg editor but Im stuck selecting some text. I'm using a div with contenteditable set to true to enter the text into. The problem is I'm using a <var> tag to highlight some text that the user is supposed to delete and rewrite in their own words. When the text inside the <var> tag is clicked it highlights it as I expect but when you hit backspace it only deletes the text and not the tags (<var>). How can I tell the selection to grab a few more characters on each end of the selection so it also deletes the <var> tags? I'm using the following to make the selection happen.
var range = document.createRange();
range.selectNodeContents(elem);
var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
Placed function on the div's click event.
Selected the <var> tag.
Used .selectNode rather than .selectNodeContents.
Browsers handle it differently though. Some will add <i></i> tags when you enter more text, others don't, but this does remove the <var> tag completely....
var myDiv = document.getElementById("myDiv");
var elem = document.getElementById("myVar");
myDiv.addEventListener("click", function() {
var range = document.createRange();
range.selectNode(elem);
var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
});
<div contenteditable="true" id="myDiv">
Hello, this<var id="myVar"> is a test</var> of the editor
</div>

How to set the cursor in the child of a contentEditable element?

I want to know how to set the cursor in the child of an editable element. I have a content editable DIV with a SPAN inside and I want to set the cursor in the SPAN when the DIV is clicked to prevent someone typing in the DIV.
<div class="custom-input" spellcheck="true" contenteditable="true">
"NOT HERE"
<span data-type="text">
"TYPE HERE"
<br>
</span>
</div>
I have tried to do this with .focus() in jQuery, and it works but it just highlights the SPAN and the cursor remains in the DIV.
I'm trying to make something like Facebook chat does. Facebook chat uses contenteditable elements for the chat input, and if you click anywhere in the chat box the cursor always is focused in a SPAN label that is used for the input.
I had to do this recently and the below is what I ended up with.
NOTE: This will not appear to work here or on jsFiddle due the sandboxing and whatnot. Run the code on your localhost or hosted server and you'll see it works.
$(document).ready(function() {
var $element = $('.type-here');
createCaretPlacer($element, false); // set cursor and select text
createCaretPlacer($element, true, true); // set cursor at start
createCaretPlacer($element, true, false); // set cursor at end
});
function createCaretPlacer($element, collapse, atStart) {
var el = $element[0]; // get the dom node of the given element
el.focus(); // focus to the element
// feature test to see which methods to use for given browser
if (typeof window.getSelection != "undefined" && typeof document.createRange != "undefined") {
// handle real browsers (not IE)
var range = document.createRange(); // create a new range object
range.selectNodeContents(el); // add the contents of the given element to the range
if(collapse) range.collapse(atStart); // collapse the rage to either the first or last index based on "atStart" param
var sel = window.getSelection(); // Returns a Selection object representing the range of text selected by the user or the current position of the caret.
sel.removeAllRanges(); // removes all ranges from the selection, leaving the anchorNode and focusNode properties equal to null and leaving nothing selected.
sel.addRange(range); // add the range we created to the selection effectively setting the cursor position
}
else if (typeof document.body.createTextRange != "undefined") {
// handle IE
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);
if(collapse) textRange.collapse(atStart);
textRange.select();
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="custom-input" spellcheck="true" contenteditable="true">
"NOT HERE"
<span data-type="text" class="type-here">
"TYPE HERE"
<br>
</span>
</div>

javascript / jQuery : get selected text's container

How can i get the id of the container (say, id of the p or div) of a user selected text?
I want to make list of selected texts, user selects a text then clicks on a button to add to the list.
And when user clicks the text from the list i want to highlight the place where original selection was made.
I need the id of the container because the selected text may not be unique and appear multiple times in the document.
i get the selected text like this Return HTML from a user-selected text
Here is one way it can be achieved cross browser (untested)
var getSelectionContainer = function() {
if (document.selection){ // IE
return document.selection.createRange().parentElement();
}
var select = window.getSelection();
if (select.rangeCount > 0) {
return select.getRangeAt(0).startContainer.parentNode;
}
};
Demo
(Select some text before 5 Seconds then look in the console)
Links
MDN window.getSelection
MDN selection.getRangeAt
MDN range.startContainer
MDN selection.rangeCount
window.getSelection().anchorNode - Gives you the DOM element where the selection started
window.getSelection().focusNode - Gives you the DOM element where the selection ended
Reference: https://developer.mozilla.org/en-US/docs/Web/API/Selection?redirectlocale=en-US&redirectslug=DOM%2FSelection

Categories