Javascript: Cannot move back in HTML Input - javascript

I have a form where a user can enter a URL but I wanted to have it automatically remove spaces.
To do this I have the following jQuery function:
$('#URL').on('change keyup', function() {
var sanitized = $(this).val().replace(' ', '');
$(this).val(sanitized);
});
But the problem with this code is that you cannot use the arrow keys to move in the input. i.e. if I type in http://oogle.com and I want to use arrow keys to fix my spelling mistake, it will automatically keep the cursor on the very last character. On top of this, I cannot use Ctrl+A to select all the text.
Is there a way to have jQuery/Javascript automatically remove spaces while still being able to move around the input or select it all?
Here is my jsFiddle showing my issue.

Use keypress instead of keyup, so only characters are caught. In this case, discard a space if it is pressed.
Also check for a paste event, and use a regular expression to replace all spaces. Change the value within a timeout in order to capture the pasted value:
$('#URL')
.on('keypress', function(e) {
if(e.which === 32) return false;
})
.on('paste', function() {
$self= $(this);
setTimeout(function() {
$self.val($self.val().replace(/\s/g, ''));
});
});
Fiddle

Fiddle
You can:
Record the cursor position
Execute your original code
Then restore the cursor position
Update:
Make sure to change your .replace to .replace(/\ /g, "")
Update 2 (cursor position):
This fixes the cursor position when inserting spaces.
For example copy and pasting the following will now work with any cursor position:
341 10365
34 1 1 03 65
First you need to get the string to the left of the cursor:
var leftString = $(this).val().substring(0, start);
Then you need to count the spaces in that string:
var leftSpaces = (leftString.match(/ /g) || []).length;
Then subtract leftSpaces from the start and end variables.
Javascript
$('#URL').on('change keyup', function() {
// Store cursor position
var start = this.selectionStart;
var end = this.selectionEnd;
// Check for newly inserted spaces
var leftString = $(this).val().substring(0, start);
var leftSpaces = (leftString.match(/ /g) || []).length;
newStart = start - leftSpaces;
newEnd = end - leftSpaces;
// Original Code
var sanitized = $(this).val().replace(/\ /g, "");
$(this).val(sanitized);
// Place cursor in correct position
this.setSelectionRange(newStart, newEnd);
});

Another option would be to add a delay after the keyup event
$('#URL').on('change keyup', function() {
delay(function(){
var sanitized = $('#URL').val().replace(' ', '');
$('#URL').val(sanitized);
}, 1000 );
});
http://jsfiddle.net/xv2e9bLe/

The usual way to adjust user input in a form is done when user finish their input or edit. It's pretty awkward to adjust user input on the fly. So, the onBlur event usually the best event to catch and sanitize a form input.
Based on the answer from adriancarriger, I use the 'blur' event which catch the user input after the user finish the input and do something else.
$('#URL').on('blur', function() {
var start = this.selectionStart,
end = this.selectionEnd;
var sanitized = $(this).val().replace(/\ /g, "");
$(this).val(sanitized);
this.setSelectionRange(start, end);
});
This should work well. If you have a real form submit, you can also catch the user input at onSubmit event of the form as well. Note that onSubmit happens at the form object, not the input object.

Related

HTML5 JavaScript, How can I clear my input field every time I hit the spacebar so there is only ever max 1 word showing in the input field?

I have 2 input fields where the second is a copy of the first using this code.
window.onload = function() {
var src = document.getElementById("paragraph-text"),
dst = document.getElementById("copy");
src.addEventListener('input', function() {
dst.value = src.value;
});
};
For every key I press when filling the first field, it shows up in the second filed. However, I'd like to have only 1 word show up at a time in the second (copy) field, meaning I want the field to clear every time I hit the spacebar (or keycode 32). Could someone help me out please.
It probably doesn't matter but here are the 2 html fields:
<input type="text" id="paragraph-text" name="paragraph-text" placeholder="type here to begin...">
<input type="text" id="copy" name="copy">
I tried this in the JavaScript:
window.onload = function() {
var src = document.getElementById("paragraph-text"),
dst = document.getElementById("copy");
src.addEventListener('input', function() {
dst.value = src.value;
window.onkeydown = function(event) {
if (event.keyCode == 32) {
src.value += ' '
dst.value = ''
if(event.preventDefault) event.preventDefault();
return false;
}
}
});
};
and it works except for the fact that when I type the next word, the original word is still there, so if i type a long sentence, the copy field will still contain all the words from the paragraph-text field, even though it does clear temporarily with every spacebar press. I would like it to stay cleared so the next word is alone, and so on. There should only ever be 1 word or nothing in the copy field.
I'm not a 100% sure I understand what you actually want, but I think this might be what you're after?
window.onload = function() {
var src = document.getElementById("paragraph-text"),
dst = document.getElementById("copy");
src.addEventListener('input', function() {
dst.value = src.value.split(' ').pop();
});
};
The first input might contain a word, or a sentence containing multiple words separated by whitespaces.
The second input should contain the last word from the first input.
We convert the contents of the first input to an array of words using split(' ') and then pop() to return the last item.

Javascript input change

Is it possible to change the input value of the keyboard?
For example:
You press the a key on your keyboard but b will be typed into the input element, instead of a.
You type abc but in the input element will be def.
I tried to capture the keydown event and then fire a keydown event with CustomEvent / Event, but It doesn't work for me. The event capturing is fine but when I create an other keydown event with the new charCode or keyCode the 'new' character won't be typed into the input.
So, is it possible to write something into an input element to the position of the caret, without using value property or any other methods which handle or modify the whole content of the input. So just insert or paste a letter.
JS
function keydown(e) {
e.preventDefault();
var event = new Event('keydown');
event.charCode = 65;
element.dispatchEvent(event);
}
HTML
<input type="text" onkeydown="keydown(event)">
Probably, this is not possible in this way but I haven't any other idea so far...
I found another way to do this with document.execCommand():
document.querySelector("input")
.addEventListener("keypress", function (event) {
event.preventDefault();
document.execCommand('insertText', false, 'b');
})
<input>
use the following code to get the cursor position when you type something. once you get the cursor position you can replace the character and set the text back to the text box. let me know you want code to put the cursor back to the location where it replaced the character.
<script type="text/javascript">
function getLocation(ctrl)
{
var position = 0;
if (document.selection) {
ctrl.focus ();
var sel = document.selection.createRange ();
sel.moveStart ('character', -ctrl.value.length);
position = Sel.text.length;
}
else if (ctrl.selectionStart || ctrl.selectionStart == '0')
position = ctrl.selectionStart;
alert (position);
}
</script>
<input type="text" onkeyup="getLocation(this);"></input>

simple textarea string replace jquery script

I'm trying to make some simple jquery script that replaces a specific string in the textarea. I've got this know:
$("textarea").bind("keyup", function() {
var text = $(this).val();
text = text.replace(/,,/g, "′");
$(this).val(text);
});
This replaces ,, into the unicode symbol ′. This works, except that the cursors position moves to the last character of the textarea everytime there is a replacement. I want that the cursors goes just after the ′ when there is a replacement. How could I do this ?
Here is my jsfiddle: http://jsfiddle.net/zvhyh/
Edit: thanks for the help guys. I use this now:
http://jsfiddle.net/zvhyh/14/
Here is my take on it:
http://jsfiddle.net/zvhyh/11/
$("textarea").bind("keyup", function() {
var cursorPosition = $('textarea').prop("selectionStart");
var text = $(this).val();
if (text.indexOf(',,') > -1) {
text = text.replace(/,,/g, "′");
$(this).val(text);
$('textarea').prop("selectionStart", cursorPosition - 1);
$('textarea').prop("selectionEnd", cursorPosition - 1);
}
});
Here is your updated fiddle: http://jsfiddle.net/zvhyh/10/
The key is to use selectionStart to get the current position of cursor and setSelectionRange to place the cursor in that position later on.
// get current cursor position
var pos = $(this).val().slice(0, this.selectionStart).length;
// replace the text
$(this).val($(this).val().replace(/,,/g, "′"));
// reset the cursor position
this.setSelectionRange(pos, pos);
Hope that helps.
Update:
Because two characters are being replaced by one character, in the above code the cursor position will skip one character to right. One workaround is to first check if a ",," combo is there, and then use the position as one character before.
Updated fiddle: http://jsfiddle.net/zvhyh/13/
if (text.indexOf(",,") > 0) {
...
pos--;
..

disable textarea by height not characters

So many times we want to limit how much a user can write, but here I have a special sized box that it has to fit in, so I want to disable adding more characters if it would surpass a specific height. here is what I did:
var over;
$('textarea').keypress(function(e){
var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
var t = $(this).val();
jQuery('<div/>', {
style: "visibility:hidden",
text: t,
id: "test"
}).appendTo('body');
var h = $('#test').height();
if(h >= 100){
over = true;
}
else{
over = false;
}
if(over){
//code goes here
}
$('#test').remove();
});
I got the limiting code (what goes where I have the "code goes here" comment) from here and it ALMOST works.
There is only one problem:
if somebody copies and pastes, it can place multiple characters and therefore still go over the limit.
How can I fix this issue?
jsfiddle
Another somewhat hacky solution could be to check scroll on key up. If scroll exists, delete the last character while scroll exists:
function restrictScroll(e){
if(e.target.clientHeight<e.target.scrollHeight){
while(e.target.clientHeight<e.target.scrollHeight){
e.target.value = e.target.value.substring(0, e.target.value.length-1);
}
}
};
document.getElementById("textareaid").addEventListener('keyup', restrictScroll);
This would work as you type and if you paste blocks of text. Large text blocks may take a little longer to loop through though. In which case you may want to split on "\n" and remove lines first, then characters.
jsfiddle
If you want your function to fire whenever the text in your field changes, you can bind it to the input and propertychange events, as per this answer:
https://stackoverflow.com/a/5494697/20578
Like this:
$('#descrip').on('input propertychange', function(e){
This will make sure your code fires when e.g. the user pastes in content using the mouse.
As for stopping them from entering content that would go over the limit, I think you have to keep track of what content they've entered yourself, and then revert their last edit if it infringed your criteria.
Note that e.g. Twitter doesn't stop the user from entering more characters if they've gone over the limit - they just tell the user they're over the limit, and tell them when they're back under. That might be the most usable design.
You may try this:
$('#descrip').bind('paste',function(e) {
var el = $(this);
setTimeout(function() {
//Get text after pasting
var text = $(el).val();
//wath yu want to do
}, 100);
};
Jsfiddle
The solution is taken from here and here. It works by binding to the paste event. Since paste event is fired before the text is pasted, you need to use a setTimeout to catch the text after pasting. There is still some rough edges (i.e. if you select text and press backspace, it does not update).
Still, Spudley comment has some valid points, that you may want to consider.
Edit:
Note on the jsfiddle: It allow you to go over the limit when pasting, but once over the limits, you cannot paste (or type) more text until you go under the limit again.
Must be taken into account that, since you are limiting the text length by the size it ocuppies after rendering (wich have it own issues as pointed by Spudley), and not a defined lenth, you can know if a text fits or not, but not know how much of the text is inside the limits, and how much is out of them.
You may consider reseting textbox value to its previous value if pasted text makes imput go over the limit, like in this one.
However, for cutting down the text after pasting so as non-fitting text is left out, but the rest of the pasted text is allowed, you need an entirely different approach. You may try iterating over the text until you find how much of the new text is enough.
By the way, line feeds and seems to cause your original script to behave weirdly.
I've been able to get the program working:
var over = false;
var num = 0;
var valid_entry = "";
$('#descrip').keyup(function(e){
var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
var t = $(this).val();
getMaxRow(t,key,this);
});
function getMaxRow(t,key,obj) {
jQuery('<div/>', {
"class": "hide",
text: t,
id: "test"
}).appendTo('body');
var h = $('#test').height();
$('#test').remove();
if(h >= 100){
num += 1;
if(num == 1){
var div = '<div id="message">You have run out of room</div>'
$('body').append(div);
}
over = true;
}
else{
over = false;
valid_entry = t;
if(num >= 1){
$('#message').remove();
num = 0;
}
}
if( over ) {
//Do this for copy and paste event:
while ( over ) {
//Try using a substring here
t = t.substr(0,(t.length-1));
over = getMaxRow(t,key,obj);
}
}
$(obj).val(valid_entry);
return over;
}

Insert value into TEXTAREA where cursor was

I have a textarea and a div with values. When I click on a value I insert it into textarea. I need it to be inserted where my cursor was in textarea. Why do I say WAS? Because when I move it out and click on a value to insert, I assume it looses focus in the text area.
So, my question is, is there a way to "remember" the latest cursor position within textarea and then insert my values at that position?
Perhaps it could be a char number in a string?.. Currently I add it like this:
input.val( function( i, val ) { return val + " " + myInsert + " "; } );
Also I use jQuery, perhaps I could use it?
I've written a cross-browser jQuery plug-in for dealing with the caret/selection in textareas and text inputs called Rangy inputs (terrible name, I really should think of a better one). A combination of methods from this and the techniques in Edgar Villegas Alvarado's answer should do the trick, although in IE, the focusout event fires too late and you'll need to use the proprietary beforedeactivate event instead:
var $textBox = $("#foo");
function saveSelection(){
$textBox.data("lastSelection", $textBox.getSelection());
}
$textBox.focusout(saveSelection);
$textBox.bind("beforedeactivate", function() {
saveSelection();
$textBox.unbind("focusout");
});
When inserting text later, the following will insert text at the previous cursor position (or overwrite the previously selected text, if the user had selected any):
var selection = $textBox.data("lastSelection");
$textBox.focus();
$textBox.setSelection(selection.start, selection.end);
$textBox.replaceSelectedText("Some new text");
See jsFiddle example here: http://jsfiddle.net/rQXrJ/1/
Here is a working example of what you are trying to do check it out at:
http://jsfiddle.net/J5Z2n/1/
Hello there my good friend....
how do you do
the jQuery:
function insertAt (myField, myValue, startSel, endSel) {
if (startSel || startSel == '0') {
var startPos = startSel;
var endPos = endSel;
myField.val(myField.val().substring(0, startPos)+ myValue+ myField.val().substring(endPos, myField.val().length));
}
else {
myField.val() += myValue;
}
}
// calling the function
var targetBox = $('textarea#insert'),
startSel,
endSel;
targetBox.bind('focusout', function() {
//insertAtCursor(this, 'how do you do');
startSel = this.selectionStart;
endSel = this.selectionEnd;
});
$("#myvalue").click(function() {
var myValue = $(this).text();
insertAt(targetBox, myValue, startSel, endSel);
});
The original function was borrowed from this post
http://alexking.org/blog/2003/06/02/inserting-at-the-cursor-using-javascript
That should give you a solid head start I hope. Cheers
If the caret (the cursor) is somewhere in the text field, it registers in Javascript as an empty selection. That is, the selectionStart and selectionEnd attributes are the same. You can use those attributes to detect the position of the caret.
Apparently selectionStart and selectionEnd are quite useful here. Check this out:
http://www.scottklarr.com/topic/425/how-to-insert-text-into-a-textarea-where-the-cursor-is/
You can use the jQuery Caret plugin to get/set the cursor position .
Example usage:
var cursorPosition = $("#textbox").caret().start);
You could 'store' this position like this:
$("#textbox").focusout(function(){
var cursorPosition = $(this).caret().start);
$(this).data("lastCursorPos", cursorPosition);
});
To retrieve it (on your div click event), do this:
var lastCursorPosition = $("#textbox").data("lastCursorPos");
Hope this helps. Cheers

Categories

Resources