I have some html text i.e.
This is line1
I can get the initial user selection using window.getSelection() assume it is 'This'. On a click of a button, I like the user selection to move to the next word i.e. 'is'. How can I do this? I currently have the following code which does not work:
function myFunction()
{
var selection=window.getSelection();
selection.collapse(selection.focusNode, 0);
selection.modify("move","forward","word");
selection.extend(selection.focusNode, selection.focusOffSet);
}
and this is't good for me, because even the earlier word stays selected
var selection = window.getSelection();
selection.modify("extend", "forward", "word");
Related
In my automation script I have a sentence - "when will my account be ready?". From this sentence I want to select the word "account". So basically I want to highlight that text and then right click on it. I am stuck at highlighting the text "account" using automation tool playwright.
Page element looks like this.
<div class="line-text">when will may account be ready</div>
After trying many things, below code worked for me. Basically the word I was trying to select, didn't have any tag around it so was hard to select that word. I used JavaScript first to select the text and then right clicked using playwright.
// element handle of a complete sentence
const elementHandle = await this.getMessageByText(messageText);
// below code selects the given word from the line. text is the word I want to //select
await elementHandle.evaluate((element, text) => {
const selection = window.getSelection();
const content = element.innerText;
const range = document.createRange();
range.setStart(element.childNodes[0], content.indexOf(text));
range.setEnd(element.childNodes[0], content.indexOf(text) + text.length);
selection.removeAllRanges();
selection.addRange(range);
}, textToMask);
await this.click(SELECTORS.messageBodyTextelementHandle, { button: 'right' });
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.
I've built a page where you can filter results by typing into an input box.
Basic mechanics are:
Start typing, input event is fired, elements without matching text begin hiding
If input becomes empty (or if you click a reset button), all elements are shown again
I have noticed a problem, though, when highlighting text. Say I type "apple" into the input. Then I highlight it, and type "orange."
If an element exists on the page containing "orange," but it was already hidden because I filtered for "apple," it does not show up. I have gathered this is because the input never truly empties; rather, I simply replace "apple" with the "o" from orange before continuing with "r-a-n-g-e." This means I get a subset of "apple" results that contain "orange," as if I had typed "apple orange."
What I really want to do is clear my input on the keypress for the "o" in "orange" before hiding nonmatching elements, so I'm effectively searching the whole page for "orange."
What I've tried so far
1: Set input value to '' on select event:
$('.myinput').on('select', function(){
$(this).val('');
});
This doesn't work because it just deletes my highlighted text, which is unexpected. I only want to reset the input on the keypress following the highlight.
2: Include an if statement in my input event that checks if there is a selection within the input:
$('.myinput').on('input', function(){
var highlightedText = window.getSelection();
if($(highlightedText).parent('.myinput')) {
//reset my input
}
});
This doesn't work because it seems to fire on every keypress, regardless of if there is any actual selection. (Are user inputs always treated as selected?)
3: Add a select event listener to the input element, and set a variable to true if there's a selection. Then, in my input event, check if the variable is true on keypress.
$(function(){
var highlightedText = false;
$('.myinput').on('input', function(){
if(highlightedText = true) {
//reset my input
}
//do stuff
highlightedText = false;
});
$('.myinput').on('select', function(){
highlightedText = true;
});
});
I really thought this one would work because a basic console log in the select function only fires when I want it to – when text in the input is highlighted, but not when other text is highlighted and not when text is entered into the input. But alas, when I change that to a variable toggle, it seems to fire on every keypress again.
So the question is: How can I fire a function on input only if text in my input is highlighted?
I have found this question that suggests binding to the mouseup event, but it seems like overkill to check every single click when I'm only worried about a pretty particular situation. Also, that solution relies on window.getSelection(), which so far isn't working for me.
I've also found another question that suggests to use window.selectionEnd instead of window.getSelection() since I'm working with a text input. I tried incorporating that into option 2 above, but it also seems to fire on every keypress, rather than on highlight.
This answer is not about text selection at all.
But still solve your problem to refilter text when highlighted text is being replaced with new input.
var input = document.getElementById('ok');
var character = document.getElementById('char');
var previousCount = 0;
var currentCount = 0;
input.addEventListener('input', function(){
currentCount = this.value.length;
if (currentCount <= previousCount){
/*
This will detect if you replace the highlighted text into new text.
You can redo the filter here.
*/
console.log('Highlighted text replaced with: ' + this.value);
}
previousCount = currentCount;
char.innerHTML = this.value;
});
<input type="text" id="ok">
<div id="char"></div>
I'll agree with others that you will save yourself some trouble if you change your filtering strategy - I'd say you should filter all content from scratch at each keypress, as opposed to filtering successively the content that remains.
Anyway, to solve your immediate problem, I think you can just get the selection and see if it is empty. You can modify your second attempt:
$('.myinput').on('input', function(){
// get the string representation of the selection
var highlightedText = window.getSelection().toString();
if(highlightedText.length) {
//reset my input
}
});
EDIT
As this solution seems to have various problems, I can suggest another, along the lines of the comment from #Bee157. You can save the old search string and check if the new one has the old as a substring (and if not, reset the display).
var oldSearch = '';
$('.myinput').on('input', function(){
var newSearch = $('.myinput').val();
if (newSearch.indexOf(oldSearch) == -1) {
// reset the display
console.log('RESET');
}
oldSearch = newSearch;
// filter the results...
});
This approach has the added benefit that old results will reappear when you backspace. I tried it in your codepen, and I was able to log 'RESET' at all the appropriate moments.
I have been struggling to get a very simple feature working using jqxGrid and a cell rendered with a jqxNumberInput
editor.jqxNumberInput({ decimalDigits: 2, spinButtonsStep: 0.1, spinMode: "simple", decimalSeparator: decimalSeparator, groupSeparator: groupSeparator });
Basically when the user clicks on the cell the cursor is placed all the way to the right of the text (number), my boss wants the contents of the cell to be highlighted (text selected) so the user does not have to move the cursor to the left in order to start typing
I have been digging through the jqx grid docs for quite some time and there doesnt seem to be anything I can find to achieve this.
http://www.jqwidgets.com/jquery-widgets-documentation/documentation/jqxgrid/jquery-grid-api.htm
I attempted to tie into the cellbeginedit event and assumed I could use the event to get the target element and selected it that way, but the event.target value is the entire grid, not the cell itself.
$(element).on('cellbeginedit', function (event) { // event.target == grid not cell });
I also attempted to get the cell by using the getcell method, but this returns the data for that cell not the element itself.
var cell = $(element).jqxGrid("getcell", args.rowindex, args.datafield);
// cell then equals the data for the row not with no reference to the
element in question
To reiterate, i need to modify, hack update do something so when a user clicks on a jqxNumberInput and the cell goes into edit mode all the text in the cell is selected (highlighted)
any help on this issue would be greatly appreciated
You should put your editor customization logic within your column's initeditor callback function. There you can try with jqxNumberInput API such as "focus" or code for selecting all text within input.
var input = editor.find('input');
var length = input.val().length;
try {
if ('selectionStart' in input) {
input.focus();
input.setSelectionRange(0, length);
}
else {
var range = input.createTextRange();
range.collapse(true);
range.moveEnd('character', length);
range.moveStart('character', 0);
range.select();
}
}
catch (error) {
}
In the above code, editor is the argument passed from jqxGrid to your column's initeditor function.
I would like to be able to preserve the users' selection when I change the contents of an HTML element. If the element is updated while the beginning or end of the selection happens to be inside, the entire selection is lost. This also happens while dragging to create a selection, so that if the user is dragging a selection and the element's inner HTML is updated while the cursor is over the element, the user must start over.
I have a <span> that contains a time in the format 'hh:mm:ss am' and is updated each second. The length of the text never changes, so that isn't an issue.
I have tried the following:
var s = window.getSelection();
if (!s.isCollapsed) {
var range = document.createRange();
range.setStart(s.anchorNode,s.anchorOffset);
range.setEnd(s.focusNode,s.focusOffset);
}
document.getElementById('time').innerHTML = new Date().toString();
if (typeof range != 'undefined') { s.removeAllRanges(); s.addRange(range); }
It's the best my research has yielded, but it doesn't seem to make a difference.
What should I do to prevent the selection from vanishing if it happens to start or end in this span?
You need to set the selection again: range.selectNodeContents(newNode);
newNode = document.getElementById("[span id]");