0

In JavaScript, I don't know how to use window.getSelection() with a single click?

var s = window.getSelection();
s = s.toString().trim();
alert(s);

HTML contains:

<p>This text contains --this; and that-that.</p>

If single click on --this; the expected output should be this. Double click should do this well, but how to do this with just a single click?

Thank you very much to all, I come to this solution:

$('p').bind('click', function () {
    var sel_obj = window.getSelection(); //it will return an object
    sel_obj.modify("move","forward","character");
    sel_obj.modify("extend","backward","word");

    sel_obj.modify("move","backward","character");
    sel_obj.modify("extend","forward","word");

    var text = sel_obj.toString().trim();
    text = text.toLowerCase();
    alert (text);

References: https://developer.mozilla.org/en-US/docs/Web/API/Selection

https://developer.mozilla.org/en-US/docs/Web/API/Selection/modify

Detect which word has been clicked on within a text

behappy
  • 3
  • 3
  • I think you might be misunderstanding how getSelection works. It gets whatever you have highlighted currently. So if you single click something, that doesn't highlight anything. Double-clicking a word highlights it. – levininja May 02 '18 at 16:18

4 Answers4

0

You need for your javascript code to be triggered by an onclick event.

So inside your p element, set onclick to the name of your js function:

<p onClick="myFunction()">Whatever text here</p>

Where that function is defined as

var myFunction = function(){
    var s = window.getSelection();
    s = s.toString().trim();
    alert(s);
}
levininja
  • 3,118
  • 5
  • 26
  • 41
  • Thank you very much. But the matter is not calling myFunction function. And the above code will return empty value also. – behappy May 02 '18 at 14:54
0

Give your this an identifier, then bind a click function:

<p>This text contains <span id="this">--this;</span> and that-that.</p>

$( "#this" ).click(function() {
    var s = window.getSelection();
    s = s.toString().trim();
    alert(s);
});

https://api.jquery.com/click/

For double click, use .dblclick

$( "#this" ).dblclick(function() {
    var s = window.getSelection();
    s = s.toString().trim();
    alert(s);
});

https://api.jquery.com/dblclick/

Rence
  • 2,900
  • 2
  • 23
  • 40
  • Thanks Sirence, but this is not the case. And the text content is long and complicated to add span. For span, can use: $('#this').text(); is enough. – behappy May 02 '18 at 15:08
0

When you single-click you create a zero-length selection range, so the toString() of the selection is naturally going to be an empty string.

If you want to know the whole word that exists where the single click occurred, you're going to have to dig a bit further into whatgetSelection() returns: https://developer.mozilla.org/en-US/docs/Web/API/Selection

The Selection object will tell you the node in the DOM tree where that zero-length selection exists, and the offset into that node where you clicked. You could easily get all of the text that belongs to the node -- but that's more text than you want.

What you'd further have to do is look at the text at the selection offset, and scan backward and forward from that point to look for word boundaries.

Sorry I don't know of a less complicated approach than this -- as far as I know there's nothing that's going to give you the whole word at a single-click selection automatically.

kshetline
  • 12,547
  • 4
  • 37
  • 73
  • thank you very much for your link! This is also important: https://developer.mozilla.org/en-US/docs/Web/API/Selection/modify to – behappy May 02 '18 at 17:13
0

This is my implementation, demo here

document.addEventListener('mouseup', (e) => {
    const selection = window.getSelection();
    if (!selection.isCollapsed) {
        console.info("[skipping] Selection detected");
        return;
    }

    const word = getWordAt(selection.focusNode.textContent, selection.focusOffset);
    if (!word) {
        console.info("[skipping] Nothing selected");
        return;
    }

    const range = selection.getRangeAt(0);

    const elementOfSelectedWord = range.startContainer.splitText(range.startOffset - word.offset),
        elementAfterSelectedWord = elementOfSelectedWord.splitText(word.word.length);

    const decoratedElementOfSelectedWord = document.createElement('span');
    decoratedElementOfSelectedWord.appendChild(document.createTextNode(elementOfSelectedWord.textContent));
    elementOfSelectedWord.parentNode.insertBefore(decoratedElementOfSelectedWord, elementAfterSelectedWord);
    elementOfSelectedWord.parentNode.removeChild(elementOfSelectedWord);

    const clientRect = decoratedElementOfSelectedWord.getBoundingClientRect();

    if (!isMousePosCoveredInClientRect(e, clientRect)) {
        console.info("[skipping] Mouse pos is not covered in client rect");
        return;
    }

    drawRedRect(clientRect);

    console.log(`${word.word}`);
})


function getWordAt(content, offset) {
    const matchLeft = content.substr(0, offset).match(/(\w+)$/);
    const left = matchLeft ? matchLeft[1] : "";

    const matchRight = content.substr(offset).match(/^(\w+)/);
    const right = matchRight ? matchRight[1] : "";

    if (!left && !right) {
        return null;
    }

    return {word: left + right, offset: left.length};
}

function isMousePosCoveredInClientRect(event, clientRect) {
    return (
        event.clientY >= clientRect.y &&
        event.clientY <= clientRect.y + clientRect.height &&
        event.clientX >= clientRect.x &&
        event.clientX <= clientRect.x + clientRect.width
    );
}

function drawRedRect(clientRect) { // this is to simulate a popup
    const div = document.createElement('div');
    Object.assign(div.style, {
        display: "block",
        position: "absolute",
        left: (clientRect.left + window.scrollX) + "px",
        top: (clientRect.top + window.scrollY) + "px",
        width: clientRect.width + "px",
        height: clientRect.height + "px",
        border: "1px solid red"
    });

    document.body.appendChild(div);
    setTimeout(() => {
        document.body.removeChild(div);
    }, 1000)
}
Kevin
  • 2,775
  • 4
  • 16
  • 27