Detect direction of user selection with javascript
Asked Answered
W

6

19

I am emulating text editor in my project with custom caret, but native selection. Is there any way how to detect in which direction did user select the text? Lets say, that user has selected text "hello world". There are two possibilities, he could start with clicking his mouse on letter 'd' and ends on letter 'h', or he could start on letter 'h' and end on letter 'd'. Is there any easy way how to distinguish between these two situations? Thank you.

Whop answered 7/2, 2012 at 16:55 Comment(3)
I don't think the selection object is smart enough for this. You'd have to record mouse-click locations and figure this out on your own.Untaught
@Diodeus Make that an answer so he can accept it. And (at)OP Try and add a custom setters and getters for those actions by using the defaults and adding mouse location calculations too it.Cyclamen
It is possible. https://mcmap.net/q/665481/-how-to-determine-if-a-selection-in-a-contenteditable-div-is-from-left-to-right-or-from-right-to-leftJennette
I
42

Old question, but I thought I'd add an easier solution:

var sel = getSelection(),
position = sel.anchorNode.compareDocumentPosition(sel.focusNode),
backward = false;
// position == 0 if nodes are the same
if (!position && sel.anchorOffset > sel.focusOffset || 
  position === Node.DOCUMENT_POSITION_PRECEDING)
  backward = true; 

Node.compareDocumentPosition (MDN)

Inchon answered 7/5, 2014 at 8:31 Comment(0)
R
5

As far as I'm aware there is no property or event native to Javascript that will tell you the direction. This site details how to track mouse direction, you can tweak it to your needs.

Essentially, as long as you can retrieve the mouse position (with either loc.pageX or Y, or event.clientX or Y), you may be able write your own functions to track the direction based on position and time.

In your case you'd probably only want to capture this when the user has text 'selected', ie on the mousedown event.

Ricciardi answered 7/2, 2012 at 17:3 Comment(2)
Thank you, I was afraid, that i will have to do it :)Whop
@TimDown Sure it's possible, and the link I provided has one approach. There just isn't a native function/property (e.g. window.mouseDirection) that gives it to you; you need to craft custom code, like in your example.Ricciardi
C
2

I was trying to find a solution that works for me for a couple of days. Here is what I came up with, this will work with single range selection:

var selection = window.getSelection();
var range = selection.getRangeAt(0);
var isSelectionDown = selection.focusNode === range.endContainer;
var isSelectionUp = selection.focusNode === range.startContainer;

The focus node of selection is always where the user releases the mouse, but the range end and start containers change depending on direction.

Carruth answered 10/10, 2016 at 10:12 Comment(1)
Only works if selection spans multiple nodes. If not a problem then can be reduced to: var isReverse = selection.anchorNode !== selection.getRangeAt(0).startContainer;Looksee
S
1

track the mousedown X offet and then the mouseup X offset, and the result shows the direction: (using jQuery)

var textSelectionDirection = (function(){
    var direction = '', mouseDownOffset = null;

    function getDirection(e){
        if( e.type == 'mousedown' )
            mouseDownOffset = e.clientX;
        else if( e.type == 'mouseup' ){
            direction = e.clientX < mouseDownOffset ? 'left' : 'right';
            console.log(direction);
        }
    }

    return getDirection
})();

$(document).on('mousedown mouseup', textSelectionDirection);

DEMO: http://jsfiddle.net/ffumv/

Silden answered 20/10, 2012 at 8:15 Comment(1)
this currently only work with mouse selections and not keyboardsSilden
R
1

This should work:

function isBackwards(sel) {
  var rg = document.createRange();
  rg.setStart(sel.anchorNode, sel.anchorOffset);
  rg.setEnd(sel.focusNode, sel.focusOffset);
  return !rg.toString();
}

Note: If you allow selections of nothing but breaks and whitespace you need to modify above function since it would return true in such a case, no matter what.

Resentful answered 28/4, 2013 at 17:46 Comment(1)
Do not work in a single text node. Only work if start and end node are not the same.Platinocyanide
D
0
var selection = window.getSelection();
var range = selection.getRangeAt(0);
var isLeftToRight = selection.anchorNode === range.startNode && selection.anchorOffset === range.startOffset;
Darell answered 6/3 at 20:36 Comment(2)
Please elaborate how your solution fixes the issue.Rarefied
The direction of the Range is always left-to-right. So if selection.anchorNode is not same with range.startContainer, the direction of the selection is right-to-left. However even if selection.anchorNode is same with range.startContainer, if selection.anchorOffset is different to range.startOffset, this means that selection.anchorOffset is same with range.endOffset.Darell

© 2022 - 2024 — McMap. All rights reserved.