I have text boxes <input type='text'> that only allow numeric characters and wont let the user enter a dot (.) more than once. Problem is, if the text in the text box is selected, the user intends to overwrite the contents with a dot, hence making it allowed! The question is, how can you tell in javascript whether the text in that text box is selected or not.
Thanks
The following will tell you whether or not all of the text is selected within a text input in all major browsers.
Example: http://www.jsfiddle.net/9Q23E/
Code:
function isTextSelected(input) {
if (typeof input.selectionStart == "number") {
return input.selectionStart == 0 && input.selectionEnd == input.value.length;
} else if (typeof document.selection != "undefined") {
input.focus();
return document.selection.createRange().text == input.value;
}
}
2017 Specific Answer - Faced the same issue recently.
We were allowing users to enter only 3 digits at a time. When the user tried to enter the fourth character we returned false.
This became an issue when the user had a selection and was trying to overwrite the values.
Taking a hint from Tim's answer. I understood that I wanted to see if the selection value was same as the input's value.
In modern browsers I achieved it by doing:
document.getSelection().toString() === input.value // edited
Hope this helps someone.
For anyone who needs the code to get at the selected text within a textbox, here's an enhanced version:
http://jsfiddle.net/9Q23E/527/
function getSelection(textbox)
{
var selectedText = null;
var activeElement = document.activeElement;
// all browsers (including IE9 and up), except IE before version 9
if(window.getSelection && activeElement &&
(activeElement.tagName.toLowerCase() == "textarea" || (activeElement.tagName.toLowerCase() == "input" && activeElement.type.toLowerCase() == "text")) &&
activeElement === textbox)
{
var startIndex = textbox.selectionStart;
var endIndex = textbox.selectionEnd;
if(endIndex - startIndex > 0)
{
var text = textbox.value;
selectedText = text.substring(textbox.selectionStart, textbox.selectionEnd);
}
}
else if (document.selection && document.selection.type == "Text" && document.selection.createRange) // All Internet Explorer
{
var range = document.selection.createRange();
selectedText = range.text;
}
return selectedText;
}
Instead of hitting the wall of digits dots and selections you can climb it easily by checking the value in onchange event.
HTML:
<input type="text" onchange="ValidateNumericValue(this);" />
JS:
function ValidateNumericValue(oInput) {
var blnRequired = true; //set to false if allowing empty value
var sValue = oInput.value;
if (blnRequired && sValue.length == 0) {
alert("Please enter a value");
oInput.focus();
return;
}
var numericValue = parseFloat(sValue);
if (isNaN(numericValue)) {
alert("Value is not a valid number");
oInput.focus();
return;
}
//put back to make 2.15A back to 2.15
oInput.value = numericValue + "";
}
This will check the value when changed (and user go to different element) and when not valid will alert and set focus back.
Live test case: http://jsfiddle.net/yahavbr/NFhay/
You can get the id of the selected element in the page with the following code:
elem_offset = document.getSelection().anchorOffset;
elem = document.getSelection().anchorNode.childNodes[elem_offset];
alert(elem.id);
If you're use case is simply to know whether any text is selected.
The difference between selectionStart and selectionEnd is always zero when no text is selected irrespective of cursor position.
So this should do the trick
const element = document.getElementById('inputbox');
const isTextSelected = element.selectionStart - element.selectionEnd;
Related
Using any browser that isn't a mobile device, number input has many features of changing it besides typing a number into it:
-Pressing Up on the arrow keys increases the value, and down arrow keys decreases it. If held down, it will increase or decrease by step, default at 1 (integer) rapidly. Additionally, on most browsers, when selecting it will show two additional buttons to the right to increment and decrement it (and holding down those as well will increase/decrease rapidly):
However, this only works with decimal numbers. There isn't a method of having a field to enter, say hex numbers. There exist a text version (<input type="text">) that allows the user to enter any character in it, and a JavaScript can parse the text into a number (or bigint) using regex prior conversion. But that will not behave like a number since it is a “general-purpose” text input.
So my question is, how do I make an input, that is a text, to behave like a number but accepts a given radix (I don't know the code, but it reacts to up/down, and features increase/decrease, and can be held down for continuous change)? Having the ability to increase/decrease a hex number would be great for making HTML that does things that are programmer-like stuff such as color math or something related to software data.
Solved (but partially). Here is a template, this only works with bigint unless you edit it to support number (double-precision floating point). I don't think the up and down arrow to the right of the input is even possible:
<input type="text" id="tester" class="HexInput"><br>
<input type="text" id="tester2" class="HexInput"><br>
<input type="text" id="tester2" class="SomethingElse"><br>
<script>
window.onload = function(){
var FocusedElement = document.activeElement;
if(FocusedElement.addEventListener ) {
FocusedElement.addEventListener('keydown',this.keyHandler,false);
} else if(FocusedElement.attachEvent ) {
FocusedElement.attachEvent('onkeydown',this.keyHandler);
}
}
function keyHandler(e) {
if (((e.keyCode == 38)||e.keyCode == 40)&&(document.activeElement.className == "HexInput")) {
var target;
var InputNumber = BigInt(CorrectHexBigIntValue(document.activeElement.value))
if (!e) var e = window.event;
if (e.target) target = e.target;
else if (e.srcElement) target = e.srcElement;
if(e.keyCode == 38) {
InputNumber++
} else if(e.keyCode == 40) {
if (InputNumber > 0n) {
InputNumber--
}
}
document.activeElement.value = InputNumber.toString(16).toUpperCase()
}
}
function CorrectHexBigIntValue(String) {
if ((/^([0-9]|[A-F]|[a-f])+$/).test(String) == false) {
String = 0n
}
return CanConvertHexStringToBigInt = BigInt("0x" + String)
}
</script>
But there is one problem: Pressing up always brings the caret (blinking text cursor) to the beginning of the line. On a number input, this always bring the caret to the end, on both pressing up and down.
YES! It is solved. Sorry for adding another answer, stackoverflow is having a bug that wouldn't let me add more text in the previous post. This here is meant to include an improved version, I found a way to prevent the caret from going to the beginning of the line by using preventDefault():
<input type="text" id="tester" class="HexNumberInput" onchange="code()"><br>
<input type="text" id="tester2" class="HexNumberInput" onchange="code()"><br>
<input type="text" id="tester3" class="somethingelse" onchange="code()"><br>
<script>
window.onload = function(){
var FocusedElement = document.activeElement;
if(FocusedElement.addEventListener ) {
FocusedElement.addEventListener('keydown',this.keyHandler,false);
} else if(FocusedElement.attachEvent ) {
FocusedElement.attachEvent('onkeydown',this.keyHandler);
}
}
function keyHandler(e) {
if (((e.keyCode == 38)||e.keyCode == 40)&&(document.activeElement.className == "HexNumberInput")) {
var target;
var InputNumber = BigInt(CorrectHexBigIntValue(document.activeElement.value))
if (!e) var e = window.event;
if (e.target) target = e.target;
else if (e.srcElement) target = e.srcElement;
if(e.keyCode == 38) {
InputNumber++
e.preventDefault() //Prevents the caret (blinking text cursor) from being placed at the beginning of the line.
} else if(e.keyCode == 40) {
if (InputNumber > 0n) {
InputNumber--
}
}
document.activeElement.value = InputNumber.toString(16).toUpperCase()
document.activeElement.setSelectionRange(document.activeElement.value.length, document.activeElement.value.length)
}
}
function code() {
var b = 1 + 1
}
function CorrectHexBigIntValue(String) {
//This converts the user's input hex string (negative numbers not allowed)
//to BigInt.
if ((/^([0-9]|[A-F]|[a-f])+$/).test(String) == false) {
String = 0n
}
return CanConvertHexStringToBigInt = BigInt("0x" + String)
}
</script>
I'm creating a markdown editor and I need to check if neighbor characters are specific characters, then remove them, else append them.
For e.g I want to check selected-text, tow neighbor characters are **, then remove them, else append them around selected text.
I can get selected text using this approach:
function getSelection(elem) {
var selectedText;
if (document.selection != undefined) { // IE
elem.focus();
var sel = document.selection.createRange();
selectedText = sel.text;
} else if (elem.selectionStart != undefined) { // Firefox
var startPos = elem.selectionStart;
var endPos = elem.selectionEnd;
selectedText = elem.value.substring(startPos, endPos)
}
return selectedText;
}
$(document).on('mousedown', 'button', function(e) {
var selection = getSelection( $('#txtarea').get(0) );
alert(selection);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="txtarea">this is a test</textarea>
<button>Bold (toggle)</button>
Now I need when user clicks on that button, it checks if selected text is between ** like this **selectedtext**, then remove them like this selected text else append them like this **selectedtext**. How can I do that?
Before anything I would like to refer to all the markdown editors out there: https://www.google.de/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=javascript%20markdown%20library
So: do not try to reinvent the the wheel, and so on.
But for the sake of learning, my approach would look like this:
function toggleMarker(marker, el) {
var markerLength = marker.length;
var startPos, endPos, selection, range;
if (document.selection != undefined) { // IE
el.focus();
range = document.selection.createRange();
selection = range.text;
} else if (el.selectionStart != undefined) { // Firefox
startPos = el.selectionStart;
endPos = el.selectionEnd;
selection = el.value.substring(startPos, endPos);
}
if (!selection.length){
return;
}
if (el.value.substring(startPos-markerLength,startPos) === marker
&& el.value.substring(endPos,endPos+markerLength) === marker
){
el.value = el.value.substring(0,startPos-markerLength) +
selection +
el.value.substring(endPos+markerLength);
}
else{
el.value = el.value.substring(0,startPos) + marker +
selection + marker + el.value.substring(endPos);
}
}
$(document).on('mousedown', 'button', function(e) {
toggleMarker( $(this).data('marker'), $('#txtarea').get(0) ).text;
});
See it in action: https://jsfiddle.net/t4ro53v8/4/
The solution takes a very generic approach: the marker to toggle is set as a custom data attribute to make it easy to reuse the code.
The functionality is only implemented for the non-IE case. You will have to check, how to determine startPos and endPos for a range in IE.
In all other browsers:
the selection is identified
nothing is done if nothing is selected
sourroundings of the selection are checked against the given marker
if both markers are present, they get deleted
otherwise the markers are inserted
As a proof of concept this example works like a charm.
But there are some shortcomings:
How to distinguish between bold text(**) and italics(*)?
How to handle markers that just appear just on one side of the selection
What to do, if a marker is selected?
But that is for you to solve now ...
You could use regex to find the occurance of a ** ** pattern.This regex will help you find the pattern similar to what you have.
[*][*][a-z]*[*][*] .
Using the exec() method, will help you extract that particular text.
Check the length of this using .length, if it is 4, then there is nothing in between, and you can replace it with the new text surrounded by **,
"**"+ newtext+"**"
For removing the **, you can use the replace() method, where you replace ** with whitespace or so.
I have written a simple javascript code to remove whitespace from a text box. This is working fine in firefox. It is even working in IE and Chrome also, but there is a little problem.
After giving the value in text box if i am trying to move my cursor to the left side of the text box using the left arrow key from my keyboard, it is only crossing the first character from the right side and then stopping.
here is my code:
<script>
function fixme(element)
{
if(element.value != '')
{
var val = element.value;
var pattern = new RegExp('[ ]+', 'g');
val = val.replace(pattern, '');
element.value = val;
}
}
</script>
<input type="text" onkeydown="fixme(this)" onblur="fixme(this)"/>
Any idea?
function fixme(element) {
if(element.value != '') {
var val = element.value;
val = val.replace(/\s/g, '');
if (val != element.value) element.value = val;
}
}
<input type="text" onkeyup="fixme(this)" onblur="fixme(this)" />
Revamped your function to change the text input's value property only when the fixed value is different than the one entered, give it a try.
Fiddle
But if your users are not supposed to type white space in the text input, you may simply prevent them from doing so:
function nospace(e) {
e = e || window.event;
return e.keyCode !== 32;
}
<input type="text" onkeydown="return nospace(event)" onkeyup="fixme(this)" onblur="fixme(this)" />
Keep your previous function in case the user pastes/drags text over to the text input.
Fiddle
I have found this question which provides a solution to compute the exact position of the caret in a text or input box.
For my purposes, this is overkill. I only want to know when the caret is at the end of all the text of an input box. Is there an easy way to do that?
In all modern browsers:
//input refers to the text box
if(input.value.length == input.selectionEnd){
//Caret at end.
}
The selectionEnd property of an input element equals the highest selection index.
<script>
input = document.getElementById('yourinputfieldsid');
if(input.selectionEnd == input.selectionStart && input.value.length == input.selectionEnd){
//your stuff
}
</script>
This checks to see if the caret actually is at the end, and makes sure that it isn't only because of the selection that it shows an end value.
You don't specify what you want to happen when some text is selected, so in that case my code just checks whether the end of the selection is at the end of the input.
Here's a cross-browser function that wil work in IE < 9 (which other answers will not: IE only got selectionStart and selectionEnd in version 9).
Live demo: http://jsfiddle.net/vkCpH/1/
Code:
function isCaretAtTheEnd(el) {
var valueLength = el.value.length;
if (typeof el.selectionEnd == "number") {
// Modern browsers
return el.selectionEnd == valueLength;
} else if (document.selection) {
// IE < 9
var selRange = document.selection.createRange();
if (selRange && selRange.parentElement() == el) {
// Create a working TextRange that lives only in the input
var range = el.createTextRange();
range.moveToBookmark(selRange.getBookmark());
return range.moveEnd("character", valueLength) == 0;
}
}
return false;
}
How can get the selected text from a textbox/textarea if I don't know which one active (focused). I am trying to create a small bookmarklet that will correct the selected text in any type of input on a page.
For the selection, you want selectionStart and selectionEnd.
As for the currently focused element, use document.activeElement.
So as a combination you can use: http://jsfiddle.net/rBPte/1/.
As Tim Down pointed out, you'd need a more complex solution for Internet Explorer version 8 or lower: Caret position in textarea, in characters from the start
function getText(elem) { // only allow input[type=text]/textarea
if(elem.tagName === "TEXTAREA" ||
(elem.tagName === "INPUT" && elem.type === "text")) {
return elem.value.substring(elem.selectionStart,
elem.selectionEnd);
// or return the return value of Tim Down's selection code here
}
return null;
}
setInterval(function() {
var txt = getText(document.activeElement);
document.getElementById('div').innerHTML =
txt === null ? 'no input selected' : txt;
}, 100);