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.
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>