0

I'm trying to get the selected text inside an <input> when a button is clicked.

I'm successfully window.getSelection() to get selected text, but when I click a button, the input's focus and selected text are lost.

I know there are solutions for this -- I have seen a jQuery library or two -- but I am looking for a (hopefully simple) vanilla JS solution.

<p>Select some text then click the button (doesn't work)</p>
<input type="text" size="20" value="select something">
<button id="btn">alert selection</button>

<script>
    document.getElementById('btn') 
        .addEventListener('click', function() {
            alert(window.getSelection().toString());
        });
</script>

<p>Select some text and see it alerted (works)</p>
<input id="input" type="text" size="20" value="select something">
<script>
    document.getElementById('input')
        .addEventListener('click', function() {
            alert(window.getSelection().toString());
        });
</script>

Edit


In reaction to the solutions posted below, one issue I need to avoid is previous selections effectively being cached. If the user deselects the text purposefully (not by clicking this specific button), I need it to not remember the old selection. The eventual goal is to modify the selected substring when the button is clicked, and if nothing is selected to just append to it.

4 Answers 4

5

Here you go. A clean solution without the need to use a second input field. http://jsfiddle.net/5kq4yecz/1/

document.getElementById('btn').addEventListener('click', function() {
  alert(test.value.substring(test.selectionStart, test.selectionEnd));
});
<p>Select some text then click the button</p>
<input type="text" size="20" id="test" value="select something">
<button id="btn">alert selection</button>

Sign up to request clarification or add additional context in comments.

4 Comments

I dont think this would work in all browsers would it?
Just tested in IE 9 and it works. It works in all other browsers as well.
A good answer, made it a snippet so others don't need to open fiddle to see the result. upvoted.
This one is much closer to what I'm looking for. It's still frustrating that if the user purposefully un-focuses the element de-selecting the text, and then clicks the button, the previous selection is essentially cached and displayed to the user. Unlike @fuyushimoya's answer it does refresh if the user deselects the text but keeps focus in the input.
4

EDITED:

Used what Stanimir post (as it handles the select range better) with a setTimeout when blur, and only cancel the timeout if its directly focus to that button.

Then after the clicked event, clear the select range.

var input = document.getElementById('test');
var btn = document.getElementById('btn');
var blur = null;
var clearSelect = function() {
  input.setSelectionRange(0, 0);
};
input
  .addEventListener('blur', function() {
    blur = setTimeout(clearSelect, 0);
  });
btn
.addEventListener('focus', function() {
  if (blur !== null) {
    clearTimeout(blur);
    blur = null;
  }
});
btn
.addEventListener('click', function() {
  alert(input.value.substring(input.selectionStart, input.selectionEnd));
  clearSelect();
});
<p>Select some text then click the button</p>
<input type="text" size="20" id="test" value="select something">
<button id="btn">alert selection</button>

If the spec of FocusEvent.relatedTarget becomes a standard, and IE<9 is not in concern (or you just love to embrace the newest technology), you can use write the logic as Zach L posted, which can make the code more simple.

var input = document.getElementById('test');
var btn = document.getElementById('btn');
var clearSelect = function() {
  input.setSelectionRange(0, 0);
};
input
  .addEventListener('blur', function(e) {
    // e.relatedTarget would be the elment that will get focus, if click on something that can't be focus
    // the value will be null.
    if (e.relatedTarget !== btn) {
      clearSelect();
    }
  });
btn
.addEventListener('click', function() {
  alert(input.value.substring(input.selectionStart, input.selectionEnd));
  // You can either focus back to the input or just clear the selection range in the input.
  //input.focus();
  clearSelect();
});
<p>Select some text then click the button</p>
<input type="text" size="20" id="test" value="select something">
<button id="btn">alert selection</button>

7 Comments

?? why would you create an event that would trigger at times you don't need it? No, do it correctly.
Maybe I should have been more clear (I'll update shortly), but this has the issue that it will alert the most recently selected text, and will still alert that text even if something else is selected, or the user purposefully de-selected the text. In these cases I do not want something selected.
I've update my answer from @Stanimir's to achieve what you expect, maybe not the best way to do it.
Yep, we know that the key is to find the relation of blur to what, or focus from what, I just see that experimental tag, so decide to use the delay way and thus not test the e.relatedTarget, just learned a lesson of how it would be used. Upvoted your answer.
Sorry, you're getting the check though ;-). Don't quite feel comfortable promoting an approach where the spec is still in flux. Feel free to edit my stuff into your answer if you want to cover all bases.
|
2

I ended up coming up with a workaround, using FocusEvent.relatedTarget to check if the input lost focus when selecting the button.

FocusEvent.relatedTarget and Window.getSelection() are not supported in IE<9 and at the time of posting are not yet officially part of the spec. I feel that their wide adoption indicates that they will probably stay stable.

<p>Select some text then click the button</p>
<input id="input" type="text" size="20" value="select something">
<button id="btn">alert selection</button>

<script>
    var input = document.getElementById('input');
    var btn = document.getElementById('btn');

    btn.addEventListener('click', function() {
        input.focus();
        var selection = window.getSelection().toString();
        alert(selection);
    });

    input.addEventListener('blur', function(e) {
        if (e.relatedTarget !== btn) {
            input.setSelectionRange(0, 0);
        }
    });
</script>

Comments

0

    <p>Select me and click input</p>
    <input id="i1" type="text" onmousedown="document.getElementById('i1').value = document.getSelection().toString()" />

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.