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>
Related
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?
This question already has answers here:
Select all DIV text with single mouse click
(15 answers)
Closed 4 years ago.
after a bit of help, I'm relatively new to Javascript, I've got the contents of a div tag that I want to select when the user clicks a button, but I can't get it to work. It seems relativity simple, but I've been playing around for hours and can't find a solution
<div id="targetText">content content </div>
<button type="button" onclick="selectBox()">Push to Select</button>
With the following Javascript
function selectBox() {
document.getElementById("targetText").select();
}
But nothing happens when I click the button!
It works fine when I ask it to select an input (as below), but the content I want selected is in a div
<input type="text" id="targetText" value="content content">
Any suggestions? Thanks in advance
<button type="button" onclick="selectBox(document.getElementById('targetText'))">Push to Select</button>
function selectBox(elem) {
//Create a range (a range is a like the selection but invisible)
var range = document.createRange();
// Select the entire contents of the element
range.selectNodeContents(elem);
// Don't select, just positioning caret:
// In front
// range.collapse();
// Behind:
// range.collapse(false);
// Get the selection object
var selection = window.getSelection();
// Remove any current selections
selection.removeAllRanges();
// Make the range you have just created the visible selection
selection.addRange(range);
}
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>
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>
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