Hi I have written this JS script to capture a TAB keypress capture.
It captures and insert a \t in the current pointer location in the "pre" tag.
$m = jQuery.noConflict();
$m(document).keydown(function(event) {
var keyCode = event.which;
if(keyCode == 9) {
// alert(); if this is there the code works, but if i remove this the code doesn't work, i dont want to alert user every time he hits TAB
// get caret position/selection
var start = this.selectionStart;
var end = this.selectionEnd;
var $this = $m(this);
var value = $this.val();
// set textarea value to: text before caret + tab + text after caret
$this.val(value.substring(0, start)
+ "\t"
+ value.substring(end));
// put caret at right position again (add one for the tab)
this.selectionStart = this.selectionEnd = start + 1;
// prevent the focus lose
event.preventDefault();
}
});
<div class="masterContainer" onclick="setFocusDiv();">
<div class="lined"></div>
<pre id="inputId" class="nonlined" contenteditable="true" onkeyup="setLineNu();" onfocus="setLineNu();"></pre>
</div>
but my problem is that when i insert an alert in the script it works perfectrly and insert the \t but when i remove the alert then it does not work. Also there is a focus event there but the focus is lost after the TAB press.
You need to call preventDefault() on your event instead of on this
Related
I have an HTML page that has a textarea. I want to be able to use the tab button inside it instead of it switching focus. I included the code from this answer to another question, but the tab still switches focus. If I run that same code in my JavaScript console, however, it changes the behavior of the tab button to create a tab character.
The relevant code I tried is this:
$("textarea").keydown(function(e) {
if (e.keyCode === 9) { // tab was pressed
// get caret position/selection
var start = this.selectionStart;
var end = this.selectionEnd;
var $this = $(this);
var value = $this.val();
// set textarea value to: text before caret + tab + text after caret
$this.val(value.substring(0, start) + "\t" + value.substring(end));
// put caret at right position again (add one for the tab)
this.selectionStart = this.selectionEnd = start + 1;
// prevent the focus lose
e.preventDefault();
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea rows="20" cols="150"></textarea>
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>
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.
When the user presses enter I want the cursor to move to a new line, but if they are currently indented by two tabs, then the cursor should stay indented two tabs.
I have already implemented the ignore tab event to stop the focus moving within the page, so I'm now just looking for the logic to keep the tab level on new line.
if(e.keyCode === 13){
//Logic here
}
http://jsfiddle.net/DVKbn/
$("textarea").keydown(function(e){
if(e.keyCode == 13){
// assuming 'this' is textarea
var cursorPos = this.selectionStart;
var curentLine = this.value.substr(0, this.selectionStart).split("\n").pop();
var indent = curentLine.match(/^\s*/)[0];
var value = this.value;
var textBefore = value.substring(0, cursorPos );
var textAfter = value.substring( cursorPos, value.length );
e.preventDefault(); // avoid creating a new line since we do it ourself
this.value = textBefore + "\n" + indent + textAfter;
setCaretPosition(this, cursorPos + indent.length + 1); // +1 is for the \n
}
});
function setCaretPosition(ctrl, pos)
{
if(ctrl.setSelectionRange)
{
ctrl.focus();
ctrl.setSelectionRange(pos,pos);
}
else if (ctrl.createTextRange) {
var range = ctrl.createTextRange();
range.collapse(true);
range.moveEnd('character', pos);
range.moveStart('character', pos);
range.select();
}
}
I improved the answer by Endless by using execCommand 'insertText' instead of modifying textarea.value.
Advantages:
Maintains undo-redo history of the <textarea>.
Maintains native behavior where any selected text is deleted.
Does not lag when value is 4000+ characters.
Shorter, simpler code.
Disadvantages:
Currently not supported by Firefox. (Use solution by Endless as fallback.)
$('textarea').on('keydown', function(e) {
if (e.which == 13) { // [ENTER] key
event.preventDefault() // We will add newline ourselves.
var start = this.selectionStart;
var currentLine = this.value.slice(0, start).split('\n').pop();
var newlineIndent = '\n' + currentLine.match(/^\s*/)[0];
if (!document.execCommand('insertText', false, newlineIndent)) {
// Add fallback for Firefox browser:
// Modify this.value and update cursor position as per solution by Endless.
}
}
});
<textarea style="width:99%;height:99px;"> I am indented by 8 spaces.
I am indented by a tab.</textarea>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Must say solutions based on one key press are obscure because people also like pasting text. Use input event instead. You can make it in jQuery like so:
$('textarea').on('input', function(e) {
var el = $(this);
var cur = $(this).prop('selectionStart'); // retrieve current caret position before setting value
var text = $(this).val();
var newText = text.replace(/^(.+)\t+/mg, '$1'); // remove intermediate tabs
newText = newText.replace(/^([^\t]*)$/mg, '\t\t$1'); // add two tabs in the beginning of each line
if (newText != text) { // If text changed...
$(this).val(newText); // finally set value
// and reset caret position shifted right by one symbol
$(this).prop('selectionStart', cur + 1);
$(this).prop('selectionEnd', cur + 1);
}
});
<textarea></textarea>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
By the way I'm too lazy to explain how to watch tab count needed for user, this one just inserts two tabs on every line.
I want to insert some special characters at the caret inside textboxes using javascript on a button. How can this be done?
The script needs to find the active textbox and insert the character at the caret in that textbox. The script also needs to work in IE and Firefox.
EDIT: It is also ok to insert the character "last" in the previously active textbox.
I think Jason Cohen is incorrect. The caret position is preserved when focus is lost.
[Edit: Added code for FireFox that I didn't have originally.]
[Edit: Added code to determine the most recent active text box.]
First, you can use each text box's onBlur event to set a variable to "this" so you always know the most recent active text box.
Then, there's an IE way to get the cursor position that also works in Opera, and an easier way in Firefox.
In IE the basic concept is to use the document.selection object and put some text into the selection. Then, using indexOf, you can get the position of the text you added.
In FireFox, there's a method called selectionStart that will give you the cursor position.
Once you have the cursor position, you overwrite the whole text.value with
text before the cursor position + the text you want to insert + the text after the cursor position
Here is an example with separate links for IE and FireFox. You can use you favorite browser detection method to figure out which code to run.
<html><head></head><body>
<script language="JavaScript">
<!--
var lasttext;
function doinsert_ie() {
var oldtext = lasttext.value;
var marker = "##MARKER##";
lasttext.focus();
var sel = document.selection.createRange();
sel.text = marker;
var tmptext = lasttext.value;
var curpos = tmptext.indexOf(marker);
pretext = oldtext.substring(0,curpos);
posttest = oldtext.substring(curpos,oldtext.length);
lasttext.value = pretext + "|" + posttest;
}
function doinsert_ff() {
var oldtext = lasttext.value;
var curpos = lasttext.selectionStart;
pretext = oldtext.substring(0,curpos);
posttest = oldtext.substring(curpos,oldtext.length);
lasttext.value = pretext + "|" + posttest;
}
-->
</script>
<form name="testform">
<input type="text" name="testtext1" onBlur="lasttext=this;">
<input type="text" name="testtext2" onBlur="lasttext=this;">
<input type="text" name="testtext3" onBlur="lasttext=this;">
</form>
Insert IE
<br>
Insert FF
</body></html>
This will also work with textareas. I don't know how to reposition the cursor so it stays at the insertion point.
In light of your update:
var inputs = document.getElementsByTagName('input');
var lastTextBox = null;
for(var i = 0; i < inputs.length; i++)
{
if(inputs[i].getAttribute('type') == 'text')
{
inputs[i].onfocus = function() {
lastTextBox = this;
}
}
}
var button = document.getElementById("YOURBUTTONID");
button.onclick = function() {
lastTextBox.value += 'PUTYOURTEXTHERE';
}
Note that if the user pushes a button, focus on the textbox will be lost and there will be no caret position!
loop over all you input fields...
finding the one that has focus..
then once you have your text area...
you should be able to do something like...
myTextArea.value = 'text to insert in the text area goes here';
I'm not sure if you can capture the caret position, but if you can, you can avoid Jason Cohen's concern by capturing the location (in relation to the string) using the text box's onblur event.
A butchered version of #bmb code in previous answer works well to reposition the cursor at end of inserted characters too:
var lasttext;
function doinsert_ie() {
var ttInsert = "bla";
lasttext.focus();
var sel = document.selection.createRange();
sel.text = ttInsert;
sel.select();
}
function doinsert_ff() {
var oldtext = lasttext.value;
var curposS = lasttext.selectionStart;
var curposF = lasttext.selectionEnd;
pretext = oldtext.substring(0,curposS);
posttest = oldtext.substring(curposF,oldtext.length);
var ttInsert='bla';
lasttext.value = pretext + ttInsert + posttest;
lasttext.selectionStart=curposS+ttInsert.length;
lasttext.selectionEnd=curposS+ttInsert.length;
}